From 2f6de531e321b7bb24b17b1bd02b43d2854aef3a Mon Sep 17 00:00:00 2001 From: Christopher Swenson Date: Sun, 17 Nov 2024 09:57:21 -0800 Subject: [PATCH 01/51] Update tock-registers (#1771) MCU will be running the Caliptra emulator but also has other Tock libraries. The version of `tock-registers` is currently out of date, and the latest published crate is as well, so we use the git commit dependency as MCU will be using. --- Cargo.lock | 5 ++--- Cargo.toml | 2 +- 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 149e344561..e80f952667 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2429,9 +2429,8 @@ dependencies = [ [[package]] name = "tock-registers" -version = "0.8.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "696941a0aee7e276a165a978b37918fd5d22c55c3d6bda197813070ca9c0f21c" +version = "0.9.0" +source = "git+https://github.com/tock/tock.git?rev=b128ae817b86706c8c4e39d27fae5c54b98659f1#b128ae817b86706c8c4e39d27fae5c54b98659f1" [[package]] name = "toml" diff --git a/Cargo.toml b/Cargo.toml index 0ba656d5f5..ebda096d56 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -171,7 +171,7 @@ sha3 = "0.10.8" smlang = "0.6.0" syn = "1.0.107" tinytemplate = "1.1" -tock-registers = "0.8.1" +tock-registers = { git = "https://github.com/tock/tock.git", rev = "b128ae817b86706c8c4e39d27fae5c54b98659f1" } toml = "0.7.0" ufmt = { git = "https://github.com/korran/ufmt.git", rev = "1d0743c1ffffc68bc05ca8eeb81c166192863f33", features = ["inline"] } uio = { version = "0.2.0" } From 87b2a32be123b058ab503308535587f2458aa73e Mon Sep 17 00:00:00 2001 From: Anthony Rocha <116300062+rusty1968@users.noreply.github.com> Date: Mon, 21 Oct 2024 18:38:59 -0700 Subject: [PATCH 02/51] Enhance PAUSER tests (#1667) * - Modify HwModel trait so it boots with a set of five valid pausers for all supported model types. - Add a negative test to ascertain that , when FpgaRealTime is selected, a SIGBUS is raised if an invalid PAUSER tries to access the mailbox. * Use a Vec to store valid pausers * Add SocManager trait definition to the newly created test (cherry picked from commit f102017b28c27642c50ad04a748d13e05dc35655) --- hw-model/Cargo.toml | 6 + hw-model/src/bin/fpga_realtime_mbox_pauser.rs | 116 ++++++++++++++++++ hw-model/src/lib.rs | 27 ++-- hw-model/tests/model_tests.rs | 48 ++++++++ 4 files changed, 186 insertions(+), 11 deletions(-) create mode 100644 hw-model/src/bin/fpga_realtime_mbox_pauser.rs diff --git a/hw-model/Cargo.toml b/hw-model/Cargo.toml index 793bf060de..d0c716c9e9 100644 --- a/hw-model/Cargo.toml +++ b/hw-model/Cargo.toml @@ -40,3 +40,9 @@ caliptra-image-types.workspace = true caliptra-builder.workspace = true caliptra-registers.workspace = true caliptra-test-harness-types.workspace = true +nix.workspace = true + +[[bin]] +name = "fpga_realtime_mbox_pauser" +path = "src/bin/fpga_realtime_mbox_pauser.rs" +required-features = ["fpga_realtime", "itrng"] diff --git a/hw-model/src/bin/fpga_realtime_mbox_pauser.rs b/hw-model/src/bin/fpga_realtime_mbox_pauser.rs new file mode 100644 index 0000000000..df1a8b1554 --- /dev/null +++ b/hw-model/src/bin/fpga_realtime_mbox_pauser.rs @@ -0,0 +1,116 @@ +// Licensed under the Apache-2.0 license + +use caliptra_hw_model::{mmio::Rv32GenMmio, HwModel, InitParams}; +use nix::sys::signal; +use nix::sys::signal::{SaFlags, SigAction, SigHandler, SigSet}; +use std::process::exit; +use std::sync::atomic::{AtomicBool, Ordering}; +use std::thread; +use std::time::Duration; + +use caliptra_api::soc_mgr::SocManager; +use caliptra_registers::soc_ifc; + +fn gen_image_hi() -> Vec { + let rv32_gen = Rv32GenMmio::new(); + let soc_ifc = + unsafe { soc_ifc::RegisterBlock::new_with_mmio(0x3003_0000 as *mut u32, &rv32_gen) }; + soc_ifc + .cptra_generic_output_wires() + .at(0) + .write(|_| b'h'.into()); + soc_ifc + .cptra_generic_output_wires() + .at(0) + .write(|_| b'i'.into()); + soc_ifc + .cptra_generic_output_wires() + .at(0) + .write(|_| 0x100 | u32::from(b'i')); + soc_ifc.cptra_generic_output_wires().at(0).write(|_| 0xff); + rv32_gen.into_inner().empty_loop().build() +} + +// Atomic flag to indicate if SIGBUS was received +static SIGBUS_RECEIVED: AtomicBool = AtomicBool::new(false); + +// Signal handler function +extern "C" fn handle_sigbus(_: i32) { + SIGBUS_RECEIVED.store(true, Ordering::SeqCst); +} + +fn main() { + println!("Setup signal handler..."); + // Define the signal action + let sig_action = SigAction::new( + SigHandler::Handler(handle_sigbus), + SaFlags::empty(), + SigSet::empty(), + ); + + // Set the signal handler for SIGBUS + unsafe { + signal::sigaction(signal::Signal::SIGBUS, &sig_action) + .expect("Failed to set SIGBUS handler"); + } + + // Spawn a thread that causes a SIGBUS error + thread::spawn(|| { + // Sleep for a short duration to ensure the main thread is ready + thread::sleep(Duration::from_secs(2)); + + let mut model = caliptra_hw_model::new_unbooted(InitParams { + rom: &gen_image_hi(), + ..Default::default() + }) + .unwrap(); + + model.soc_ifc().cptra_fuse_wr_done().write(|w| w.done(true)); + model.soc_ifc().cptra_bootfsm_go().write(|w| w.go(true)); + + // Set up the PAUSER as valid for the mailbox (using index 0) + model + .soc_ifc() + .cptra_mbox_valid_pauser() + .at(0) + .write(|_| 0x1); + model + .soc_ifc() + .cptra_mbox_pauser_lock() + .at(0) + .write(|w| w.lock(true)); + + // Set the PAUSER to something invalid + model.set_apb_pauser(0x2); + + // The accesses below trigger sigbus + assert!(!model.soc_mbox().lock().read().lock()); + // Should continue to read 0 because the reads are being blocked by valid PAUSER + assert!(!model.soc_mbox().lock().read().lock()); + + // Set the PAUSER back to valid + model.set_apb_pauser(0x1); + + // Should read 0 the first time still for lock available + assert!(!model.soc_mbox().lock().read().lock()); + // Should read 1 now for lock taken + assert!(model.soc_mbox().lock().read().lock()); + + model.soc_mbox().cmd().write(|_| 4242); + + assert_eq!(model.soc_mbox().cmd().read(), 4242); + // Continue with the rest of your program + println!("Continuing execution..."); + }); + + // Simulate some work in the main thread + loop { + if SIGBUS_RECEIVED.load(Ordering::SeqCst) { + println!("Received SIGBUS signal!"); + // Handle the SIGBUS signal here + exit(42); + } + println!("Working..."); + thread::sleep(Duration::from_secs(1)); + } +} diff --git a/hw-model/src/lib.rs b/hw-model/src/lib.rs index 137df6f207..184f9402ff 100644 --- a/hw-model/src/lib.rs +++ b/hw-model/src/lib.rs @@ -81,6 +81,8 @@ pub type DefaultHwModel = ModelVerilated; #[cfg(feature = "fpga_realtime")] pub type DefaultHwModel = ModelFpgaRealtime; +pub const DEFAULT_APB_PAUSER: u32 = 0x01; + /// Constructs an HwModel based on the cargo features and environment /// variables. Most test cases that need to construct a HwModel should use this /// function over HwModel::new_unbooted(). @@ -253,7 +255,7 @@ pub struct BootParams<'a> { pub initial_dbg_manuf_service_reg: u32, pub initial_repcnt_thresh_reg: Option, pub initial_adaptp_thresh_reg: Option, - pub valid_axi_id: u32, + pub valid_axi_id: Vec, pub wdt_timeout_cycles: u64, } @@ -266,7 +268,7 @@ impl<'a> Default for BootParams<'a> { initial_dbg_manuf_service_reg: Default::default(), initial_repcnt_thresh_reg: Default::default(), initial_adaptp_thresh_reg: Default::default(), - valid_axi_id: 0x1, + valid_axi_id: vec![0, 1, 2, 3, 4], wdt_timeout_cycles: EXPECTED_CALIPTRA_BOOT_TIME_IN_CYCLES, } } @@ -516,15 +518,18 @@ pub trait HwModel: SocManager { .write(|_| reg); } - // Set up the AXI_ID as valid for the mailbox (using index 0) - self.soc_ifc() - .cptra_mbox_valid_axi_id() - .at(0) - .write(|_| boot_params.valid_axi_id); - self.soc_ifc() - .cptra_mbox_axi_id_lock() - .at(0) - .write(|w| w.lock(true)); + { + for idx in 0..boot_params.valid_axi_id.len() { + self.soc_ifc() + .cptra_mbox_valid_axi_id() + .at(idx) + .write(|_| boot_params.valid_axi_id[idx]); + self.soc_ifc() + .cptra_mbox_axi_id_lock() + .at(idx) + .write(|w| w.lock(true)); + } + } writeln!(self.output().logger(), "writing to cptra_bootfsm_go")?; self.soc_ifc().cptra_bootfsm_go().write(|w| w.go(true)); diff --git a/hw-model/tests/model_tests.rs b/hw-model/tests/model_tests.rs index 6732bffd47..25c8ac5cb9 100644 --- a/hw-model/tests/model_tests.rs +++ b/hw-model/tests/model_tests.rs @@ -6,6 +6,27 @@ use caliptra_hw_model::{BootParams, DefaultHwModel, HwModel, InitParams}; use caliptra_hw_model_types::ErrorInjectionMode; use caliptra_test_harness_types as harness; +#[cfg(feature = "fpga_realtime")] +use std::process::{Child, Command}; +#[cfg(feature = "fpga_realtime")] +use std::thread; +#[cfg(feature = "fpga_realtime")] +use std::time::{Duration, Instant}; + +#[cfg(feature = "fpga_realtime")] +fn wait_with_timeout(child: &mut Child, timeout: Duration) -> Option { + let start = Instant::now(); + while start.elapsed() < timeout { + match child.try_wait() { + Ok(Some(status)) => return status.code(), + Ok(None) => thread::sleep(Duration::from_millis(100)), // Check every 100ms + Err(_) => return None, + } + } + let _ = child.kill(); + None +} + fn run_fw_elf(elf: &[u8]) -> DefaultHwModel { let rom = caliptra_builder::elf2rom(elf).unwrap(); let model = caliptra_hw_model::new( @@ -272,3 +293,30 @@ fn test_pcr_extend() { model.step_until_exit_success().unwrap(); } + +#[test] +#[cfg(feature = "fpga_realtime")] +fn test_mbox_pauser_sigbus() { + fn find_binary_path() -> Option<&'static str> { + // Use this path when running on github. + const TEST_BIN_PATH_SQUASHFS:&str = "/tmp/caliptra-test-binaries/target/aarch64-unknown-linux-gnu/release/fpga_realtime_mbox_pauser"; + + const TEST_BIN_PATH: &str = env!("CARGO_BIN_EXE_fpga_realtime_mbox_pauser"); + if std::path::Path::new(TEST_BIN_PATH_SQUASHFS).exists() { + Some(TEST_BIN_PATH_SQUASHFS) + } else if std::path::Path::new(TEST_BIN_PATH).exists() { + Some(TEST_BIN_PATH) + } else { + None + } + } + + let mut child = Command::new(find_binary_path().unwrap()) + .spawn() + .expect("Failed to start mbox_pauser test utility"); + + let exit_code = wait_with_timeout(&mut child, Duration::from_secs(120)); + + // Check if the exit code is 42 + assert_eq!(exit_code, Some(42)); +} From bfd9bf5b5ce8db5217ecf429c94b09bfbe4aa595 Mon Sep 17 00:00:00 2001 From: Anthony Rocha <116300062+rusty1968@users.noreply.github.com> Date: Wed, 30 Oct 2024 12:27:22 -0700 Subject: [PATCH 03/51] Caliptra API Enhancements : (#1713) - Add documentation showing how to use the SocManager trait. - Address feedback from the last review. - Update SocManager with new trait methods. (cherry picked from commit 613df2bf93db86418ac5e9b367e5c3cf044431d1) --- api/src/lib.rs | 30 +- api/src/mailbox.rs | 25 +- api/src/soc_mgr.rs | 294 ++++++++++++ api/types/src/lib.rs | 2 +- hw-model/src/lib.rs | 441 +++++++++++++----- .../test_idevid_derivation.rs | 2 +- .../caliptra_integration_tests/smoke_test.rs | 2 +- 7 files changed, 676 insertions(+), 120 deletions(-) diff --git a/api/src/lib.rs b/api/src/lib.rs index 0bfed12d96..0075fd998e 100644 --- a/api/src/lib.rs +++ b/api/src/lib.rs @@ -13,6 +13,34 @@ pub use soc_mgr::SocManager; #[derive(Debug, Eq, PartialEq)] pub enum CaliptraApiError { - ReadBuffTooSmall, + UnableToSetPauser, + UnableToLockMailbox, + UnableToReadMailbox, BufferTooLargeForMailbox, + UnknownCommandStatus(u32), + MailboxTimeout, + MailboxCmdFailed(u32), + UnexpectedMailboxFsmStatus { + expected: u32, + actual: u32, + }, + MailboxRespInvalidFipsStatus(u32), + MailboxRespInvalidChecksum { + expected: u32, + actual: u32, + }, + MailboxRespTypeTooSmall, + MailboxReqTypeTooSmall, + MailboxNoResponseData, + MailboxUnexpectedResponseLen { + expected_min: u32, + expected_max: u32, + actual: u32, + }, + UploadFirmwareUnexpectedResponse, + UploadMeasurementResponseError, + ReadBuffTooSmall, + FusesAlreadyIniitalized, + FuseDoneNotSet, + StashMeasurementFailed, } diff --git a/api/src/mailbox.rs b/api/src/mailbox.rs index 46508b0d83..ed666ea4e0 100644 --- a/api/src/mailbox.rs +++ b/api/src/mailbox.rs @@ -1051,9 +1051,26 @@ pub struct AuthorizeAndStashResp { } impl Response for AuthorizeAndStashResp {} +/// Retrieves dlen bytes from the mailbox. +pub fn mbox_read_response( + mbox: mbox::RegisterBlock, + buf: &mut [u8], +) -> Result<&[u8], CaliptraApiError> { + let dlen_bytes = mbox.dlen().read() as usize; + + // Buffer must be big enough to store dlen bytes. + let buf = buf + .get_mut(..dlen_bytes) + .ok_or(CaliptraApiError::ReadBuffTooSmall)?; + + mbox_read_fifo(mbox, buf)?; + + Ok(buf) +} + pub fn mbox_read_fifo( mbox: mbox::RegisterBlock, - mut buf: &mut [u8], + buf: &mut [u8], ) -> core::result::Result<(), CaliptraApiError> { use zerocopy::Unalign; @@ -1065,9 +1082,9 @@ pub fn mbox_read_fifo( let dlen_bytes = mbox.dlen().read() as usize; - if dlen_bytes < buf.len() { - buf = &mut buf[..dlen_bytes]; - } + let buf = buf + .get_mut(..dlen_bytes) + .ok_or(CaliptraApiError::UnableToReadMailbox)?; let len_words = buf.len() / size_of::(); let (mut buf_words, suffix) = LayoutVerified::new_slice_unaligned_from_prefix(buf, len_words) diff --git a/api/src/soc_mgr.rs b/api/src/soc_mgr.rs index b5da6f70e4..b322ae38a7 100644 --- a/api/src/soc_mgr.rs +++ b/api/src/soc_mgr.rs @@ -1,6 +1,63 @@ // Licensed under the Apache-2.0 license + +use crate::{ + calc_checksum, + mailbox::{ + mbox_read_response, mbox_write_fifo, MailboxReqHeader, MailboxRespHeader, Request, + Response, StashMeasurementReq, + }, + CaliptraApiError, +}; +use caliptra_api_types::Fuses; +use core::mem; use ureg::MmioMut; +use zerocopy::{AsBytes, FromBytes}; +/// Implementation of the `SocManager` trait for a `RealSocManager`. +/// +/// # Example +/// +/// ```rust +/// use caliptra_api::SocManager; +/// use ureg::RealMmioMut; +/// struct RealSocManager; +/// const CPTRA_SOC_IFC_ADDR: u32 = 0x3003_0000; +/// const CPTRA_SOC_IFC_TRNG_ADDR: u32 = 0x3003_0000; +/// const CPTRA_SOC_SHA512_ACC_ADDR: u32 = 0x3002_1000; +/// const CPTRA_SOC_MBOX_ADDR: u32 = 0x3002_0000; +/// const fn caliptra_address_remap(addr : u32) -> u32 { +/// addr +/// } +/// impl SocManager for RealSocManager { +/// /// Address of the mailbox, remapped for the SoC. +/// const SOC_MBOX_ADDR: u32 = caliptra_address_remap(CPTRA_SOC_MBOX_ADDR); +/// +/// /// Address of the SoC interface, remapped for the SoC. +/// const SOC_IFC_ADDR: u32 = caliptra_address_remap(CPTRA_SOC_IFC_ADDR); +/// +/// /// Address of the SoC TRNG interface, remapped for the SoC. +/// const SOC_IFC_TRNG_ADDR: u32 = caliptra_address_remap(CPTRA_SOC_IFC_TRNG_ADDR); +/// +/// /// Address of the SHA-512 accelerator, remapped for the SoC. +/// const SOC_SHA512_ACC_ADDR: u32 = caliptra_address_remap(CPTRA_SOC_SHA512_ACC_ADDR); +/// +/// /// Maximum number of wait cycles. +/// const MAX_WAIT_CYCLES: u32 = 400000; +/// +/// /// Type alias for mutable memory-mapped I/O. +/// type TMmio<'a> = RealMmioMut<'a>; +/// +/// /// Returns a mutable reference to the memory-mapped I/O. +/// fn mmio_mut(&mut self) -> Self::TMmio<'_> { +/// ureg::RealMmioMut::default() +/// } +/// +/// /// Provides a delay function to be invoked when polling mailbox status. +/// fn delay(&mut self) { +/// //real_soc_delay_fn(1); +/// } +/// } +/// ``` pub trait SocManager { const SOC_IFC_ADDR: u32; const SOC_MBOX_ADDR: u32; @@ -15,8 +72,94 @@ pub trait SocManager { fn mmio_mut(&mut self) -> Self::TMmio<'_>; + // Provide a time base for mailbox status polling loop. fn delay(&mut self); + /// Set up valid PAUSERs for mailbox access. + fn setup_mailbox_users(&mut self, apb_pausers: &[u32]) -> Result<(), CaliptraApiError> { + for (idx, apb_pauser) in apb_pausers.iter().enumerate() { + if self + .soc_ifc() + .cptra_mbox_axi_id_lock() + .at(idx) + .read() + .lock() + { + return Err(CaliptraApiError::UnableToSetPauser); + } + + self.soc_ifc() + .cptra_mbox_valid_axi_id() + .at(idx) + .write(|_| *apb_pauser); + self.soc_ifc() + .cptra_mbox_axi_id_lock() + .at(idx) + .write(|w| w.lock(true)); + } + Ok(()) + } + + /// Initializes the fuse values and locks them in until the next reset. + /// + /// # Errors + /// + /// If the cptra_fuse_wr_done has already been written, or the + /// hardware prevents cptra_fuse_wr_done from being set. + fn init_fuses(&mut self, fuses: &Fuses) -> Result<(), CaliptraApiError> { + if !self.soc_ifc().cptra_reset_reason().read().warm_reset() + && self.soc_ifc().cptra_fuse_wr_done().read().done() + { + return Err(CaliptraApiError::FusesAlreadyIniitalized); + } + + self.soc_ifc().fuse_uds_seed().write(&fuses.uds_seed); + self.soc_ifc() + .fuse_field_entropy() + .write(&fuses.field_entropy); + self.soc_ifc() + .fuse_key_manifest_pk_hash() + .write(&fuses.key_manifest_pk_hash); + self.soc_ifc() + .fuse_key_manifest_pk_hash_mask() + .write(|w| w.mask(fuses.key_manifest_pk_hash_mask.into())); + self.soc_ifc() + .fuse_owner_pk_hash() + .write(&fuses.owner_pk_hash); + self.soc_ifc() + .fuse_fmc_key_manifest_svn() + .write(|_| fuses.fmc_key_manifest_svn); + self.soc_ifc().fuse_runtime_svn().write(&fuses.runtime_svn); + self.soc_ifc() + .fuse_anti_rollback_disable() + .write(|w| w.dis(fuses.anti_rollback_disable)); + self.soc_ifc() + .fuse_idevid_cert_attr() + .write(&fuses.idevid_cert_attr); + self.soc_ifc() + .fuse_idevid_manuf_hsm_id() + .write(&fuses.idevid_manuf_hsm_id); + self.soc_ifc() + .fuse_life_cycle() + .write(|w| w.life_cycle(fuses.life_cycle.into())); + self.soc_ifc() + .fuse_lms_verify() + .write(|w| w.lms_verify(fuses.lms_verify)); + self.soc_ifc() + .fuse_lms_revocation() + .write(|_| fuses.fuse_lms_revocation); + self.soc_ifc() + .fuse_soc_stepping_id() + .write(|w| w.soc_stepping_id(fuses.soc_stepping_id.into())); + + self.soc_ifc().cptra_fuse_wr_done().write(|w| w.done(true)); + + if !self.soc_ifc().cptra_fuse_wr_done().read().done() { + return Err(CaliptraApiError::FuseDoneNotSet); + } + Ok(()) + } + /// A register block that can be used to manipulate the soc_ifc peripheral /// over the simulated SoC->Caliptra APB bus. fn soc_ifc(&mut self) -> caliptra_registers::soc_ifc::RegisterBlock> { @@ -60,4 +203,155 @@ pub trait SocManager { ) } } + + /// Executes `cmd` with request data `buf`. Returns `Ok(Some(_))` if + /// the uC responded with data, `Ok(None)` if the uC indicated success + /// without data, Err(CaliptraApiError::MailboxCmdFailed) if the microcontroller + /// responded with an error, or other errors if there was a problem + /// communicating with the mailbox. + fn mailbox_exec<'r>( + &mut self, + cmd: u32, + buf: &[u8], + resp_data: &'r mut [u8], + ) -> core::result::Result, CaliptraApiError> { + self.start_mailbox_exec(cmd, buf)?; + self.finish_mailbox_exec(resp_data) + } + + /// Send a command to the mailbox but don't wait for the response + fn start_mailbox_exec( + &mut self, + cmd: u32, + buf: &[u8], + ) -> core::result::Result<(), CaliptraApiError> { + // Read a 0 to get the lock + if self.soc_mbox().lock().read().lock() { + return Err(CaliptraApiError::UnableToLockMailbox); + } + + // Mailbox lock value should read 1 now + // If not, the reads are likely being blocked by the PAUSER check or some other issue + if !(self.soc_mbox().lock().read().lock()) { + return Err(CaliptraApiError::UnableToReadMailbox); + } + + self.soc_mbox().cmd().write(|_| cmd); + mbox_write_fifo(&self.soc_mbox(), buf)?; + + // Ask the microcontroller to execute this command + self.soc_mbox().execute().write(|w| w.execute(true)); + + Ok(()) + } + + fn finish_mailbox_exec<'r>( + &mut self, + resp_data: &'r mut [u8], + ) -> core::result::Result, CaliptraApiError> { + // Wait for the microcontroller to finish executing + let mut timeout_cycles = Self::MAX_WAIT_CYCLES; // 100ms @400MHz + while self.soc_mbox().status().read().status().cmd_busy() { + self.delay(); + timeout_cycles -= 1; + if timeout_cycles == 0 { + return Err(CaliptraApiError::MailboxTimeout); + } + } + let status = self.soc_mbox().status().read().status(); + if status.cmd_failure() { + self.soc_mbox().execute().write(|w| w.execute(false)); + let soc_ifc = self.soc_ifc(); + return Err(CaliptraApiError::MailboxCmdFailed( + if soc_ifc.cptra_fw_error_fatal().read() != 0 { + soc_ifc.cptra_fw_error_fatal().read() + } else { + soc_ifc.cptra_fw_error_non_fatal().read() + }, + )); + } + if status.cmd_complete() { + self.soc_mbox().execute().write(|w| w.execute(false)); + return Ok(None); + } + if !status.data_ready() { + return Err(CaliptraApiError::UnknownCommandStatus(status as u32)); + } + + let res = mbox_read_response(self.soc_mbox(), resp_data); + + self.soc_mbox().execute().write(|w| w.execute(false)); + + let buf = res?; + + Ok(Some(buf)) + } + + /// Executes a typed request and (if success), returns the typed response. + /// The checksum field of the request is calculated, and the checksum of the + /// response is validated. + fn mailbox_exec_req( + &mut self, + mut req: R, + resp_bytes: &mut [u8], + ) -> core::result::Result { + if mem::size_of::() < mem::size_of::() { + return Err(CaliptraApiError::MailboxReqTypeTooSmall); + } + if mem::size_of::() < mem::size_of::() { + return Err(CaliptraApiError::MailboxRespTypeTooSmall); + } + if R::Resp::MIN_SIZE < mem::size_of::() { + return Err(CaliptraApiError::MailboxRespTypeTooSmall); + } + let (header_bytes, payload_bytes) = req + .as_bytes_mut() + .split_at_mut(mem::size_of::()); + + let mut header = MailboxReqHeader::read_from(header_bytes as &[u8]).unwrap(); + header.chksum = calc_checksum(R::ID.into(), payload_bytes); + header_bytes.copy_from_slice(header.as_bytes()); + + let Some(data) = SocManager::mailbox_exec(self, R::ID.into(), req.as_bytes(), resp_bytes)? else { + return Err(CaliptraApiError::MailboxNoResponseData); + }; + + if data.len() < R::Resp::MIN_SIZE || data.len() > mem::size_of::() { + return Err(CaliptraApiError::MailboxUnexpectedResponseLen { + expected_min: R::Resp::MIN_SIZE as u32, + expected_max: mem::size_of::() as u32, + actual: data.len() as u32, + }); + } + + let mut response = R::Resp::new_zeroed(); + response.as_bytes_mut()[..data.len()].copy_from_slice(data); + + let response_header = MailboxRespHeader::read_from_prefix(data).unwrap(); + let actual_checksum = calc_checksum(0, &data[4..]); + if actual_checksum != response_header.chksum { + return Err(CaliptraApiError::MailboxRespInvalidChecksum { + expected: response_header.chksum, + actual: actual_checksum, + }); + } + if response_header.fips_status != MailboxRespHeader::FIPS_STATUS_APPROVED { + return Err(CaliptraApiError::MailboxRespInvalidFipsStatus( + response_header.fips_status, + )); + } + Ok(response) + } + + fn send_stash_measurement_req( + &mut self, + req: StashMeasurementReq, + response_packet: &mut [u8], + ) -> Result<(), CaliptraApiError> { + let resp = self.mailbox_exec_req(req, response_packet)?; + if resp.dpe_result == 0 { + return Ok(()); + } + Err(CaliptraApiError::StashMeasurementFailed) + } } diff --git a/api/types/src/lib.rs b/api/types/src/lib.rs index 10940e7bd9..37f4f05d71 100644 --- a/api/types/src/lib.rs +++ b/api/types/src/lib.rs @@ -152,7 +152,7 @@ impl TryFrom for U4 { } } -#[derive(Clone, Copy, Debug)] +#[derive(Clone, Debug)] pub struct Fuses { pub uds_seed: [u32; 12], pub field_entropy: [u32; 8], diff --git a/hw-model/src/lib.rs b/hw-model/src/lib.rs index 184f9402ff..55b5be6b61 100644 --- a/hw-model/src/lib.rs +++ b/hw-model/src/lib.rs @@ -1,13 +1,11 @@ // Licensed under the Apache-2.0 license -use api::calc_checksum; -use api::mailbox::{MailboxReqHeader, MailboxRespHeader, Response}; use api::CaliptraApiError; use caliptra_api as api; use caliptra_api::SocManager; use caliptra_api_types as api_types; use caliptra_emu_bus::Bus; -use std::mem; +use core::panic; use std::path::PathBuf; use std::str::FromStr; use std::{ @@ -277,6 +275,7 @@ impl<'a> Default for BootParams<'a> { #[derive(Debug, Eq, PartialEq)] pub enum ModelError { MailboxCmdFailed(u32), + UnableToSetPauser, UnableToLockMailbox, BufferTooLargeForMailbox, UploadFirmwareUnexpectedResponse, @@ -309,13 +308,56 @@ pub enum ModelError { MailboxRespInvalidFipsStatus(u32), MailboxTimeout, ReadBufferTooSmall, + FuseDoneNotSet, + FusesAlreadyInitialized, + StashMeasurementFailed, } impl From for ModelError { fn from(error: CaliptraApiError) -> Self { match error { + CaliptraApiError::UnableToLockMailbox => ModelError::UnableToLockMailbox, + CaliptraApiError::UnableToReadMailbox => ModelError::UnableToReadMailbox, CaliptraApiError::BufferTooLargeForMailbox => ModelError::BufferTooLargeForMailbox, + CaliptraApiError::UnknownCommandStatus(code) => ModelError::UnknownCommandStatus(code), + CaliptraApiError::MailboxTimeout => ModelError::MailboxTimeout, + CaliptraApiError::MailboxCmdFailed(code) => ModelError::MailboxCmdFailed(code), + CaliptraApiError::UnexpectedMailboxFsmStatus { expected, actual } => { + ModelError::UnexpectedMailboxFsmStatus { expected, actual } + } + CaliptraApiError::MailboxRespInvalidFipsStatus(status) => { + ModelError::MailboxRespInvalidFipsStatus(status) + } + CaliptraApiError::MailboxRespInvalidChecksum { expected, actual } => { + ModelError::MailboxRespInvalidChecksum { expected, actual } + } + CaliptraApiError::MailboxRespTypeTooSmall => ModelError::MailboxRespTypeTooSmall, + CaliptraApiError::MailboxReqTypeTooSmall => ModelError::MailboxReqTypeTooSmall, + CaliptraApiError::MailboxNoResponseData => ModelError::MailboxNoResponseData, + CaliptraApiError::MailboxUnexpectedResponseLen { + expected_min, + expected_max, + actual, + } => ModelError::MailboxUnexpectedResponseLen { + expected_min, + expected_max, + actual, + }, + CaliptraApiError::UploadFirmwareUnexpectedResponse => { + ModelError::UploadFirmwareUnexpectedResponse + } + CaliptraApiError::UploadMeasurementResponseError => { + ModelError::UploadMeasurementResponseError + } caliptra_api::CaliptraApiError::ReadBuffTooSmall => ModelError::ReadBufferTooSmall, + caliptra_api::CaliptraApiError::FuseDoneNotSet => ModelError::FuseDoneNotSet, + caliptra_api::CaliptraApiError::FusesAlreadyIniitalized => { + ModelError::FusesAlreadyInitialized + } + caliptra_api::CaliptraApiError::StashMeasurementFailed => { + ModelError::StashMeasurementFailed + } + caliptra_api::CaliptraApiError::UnableToSetPauser => ModelError::UnableToSetPauser, } } } @@ -387,6 +429,20 @@ impl Display for ModelError { ModelError::ReadBufferTooSmall => { write!(f, "Cant read mailbox because read buffer too small") } + + ModelError::FuseDoneNotSet => { + write!(f, "Fuse Wr Done bit not set") + } + + ModelError::FusesAlreadyInitialized => { + write!(f, "Fuses already initialized") + } + ModelError::StashMeasurementFailed => { + write!(f, "Stash measurement request failed") + } + ModelError::UnableToSetPauser => { + write!(f, "Valid PAUSER locked") + } } } } @@ -490,7 +546,7 @@ pub trait HwModel: SocManager { where Self: Sized, { - self.init_fuses(&boot_params.fuses); + HwModel::init_fuses(self, &boot_params.fuses); self.soc_ifc() .cptra_dbg_manuf_service_reg() @@ -518,18 +574,9 @@ pub trait HwModel: SocManager { .write(|_| reg); } - { - for idx in 0..boot_params.valid_axi_id.len() { - self.soc_ifc() - .cptra_mbox_valid_axi_id() - .at(idx) - .write(|_| boot_params.valid_axi_id[idx]); - self.soc_ifc() - .cptra_mbox_axi_id_lock() - .at(idx) - .write(|w| w.lock(true)); - } - } + // Set up the PAUSER as valid for the mailbox (using index 0) + self.setup_mailbox_users(boot_params.valid_axi_id.as_slice()) + .map_err(ModelError::from)?; writeln!(self.output().logger(), "writing to cptra_bootfsm_go")?; self.soc_ifc().cptra_bootfsm_go().write(|w| w.go(true)); @@ -568,7 +615,7 @@ pub trait HwModel: SocManager { fn warm_reset_flow(&mut self, fuses: &Fuses) { self.warm_reset(); - self.init_fuses(fuses); + HwModel::init_fuses(self, fuses); self.soc_ifc().cptra_bootfsm_go().write(|w| w.go(true)); } @@ -617,55 +664,13 @@ pub trait HwModel: SocManager { /// If the cptra_fuse_wr_done has already been written, or the /// hardware prevents cptra_fuse_wr_done from being set. fn init_fuses(&mut self, fuses: &Fuses) { - if !self.soc_ifc().cptra_reset_reason().read().warm_reset() { - assert!( - !self.soc_ifc().cptra_fuse_wr_done().read().done(), - "Fuses are already locked in place (according to cptra_fuse_wr_done)" + println!("Initializing fuses"); + if let Err(e) = caliptra_api::SocManager::init_fuses(self, fuses) { + panic!( + "{}", + format!("Fuse initializaton error: {}", ModelError::from(e)) ); } - println!("Initializing fuses: {:#x?}", fuses); - - self.soc_ifc().fuse_uds_seed().write(&fuses.uds_seed); - self.soc_ifc() - .fuse_field_entropy() - .write(&fuses.field_entropy); - self.soc_ifc() - .fuse_key_manifest_pk_hash() - .write(&fuses.key_manifest_pk_hash); - self.soc_ifc() - .fuse_key_manifest_pk_hash_mask() - .write(|w| w.mask(fuses.key_manifest_pk_hash_mask.into())); - self.soc_ifc() - .fuse_owner_pk_hash() - .write(&fuses.owner_pk_hash); - self.soc_ifc() - .fuse_fmc_key_manifest_svn() - .write(|_| fuses.fmc_key_manifest_svn); - self.soc_ifc().fuse_runtime_svn().write(&fuses.runtime_svn); - self.soc_ifc() - .fuse_anti_rollback_disable() - .write(|w| w.dis(fuses.anti_rollback_disable)); - self.soc_ifc() - .fuse_idevid_cert_attr() - .write(&fuses.idevid_cert_attr); - self.soc_ifc() - .fuse_idevid_manuf_hsm_id() - .write(&fuses.idevid_manuf_hsm_id); - self.soc_ifc() - .fuse_life_cycle() - .write(|w| w.life_cycle(fuses.life_cycle.into())); - self.soc_ifc() - .fuse_lms_verify() - .write(|w| w.lms_verify(fuses.lms_verify)); - self.soc_ifc() - .fuse_lms_revocation() - .write(|_| fuses.fuse_lms_revocation); - self.soc_ifc() - .fuse_soc_stepping_id() - .write(|w| w.soc_stepping_id(fuses.soc_stepping_id.into())); - - self.soc_ifc().cptra_fuse_wr_done().write(|w| w.done(true)); - assert!(self.soc_ifc().cptra_fuse_wr_done().read().done()); } fn step_until_exit_success(&mut self) -> std::io::Result<()> { @@ -819,56 +824,12 @@ pub trait HwModel: SocManager { /// response is validated. fn mailbox_execute_req( &mut self, - mut req: R, + req: R, ) -> std::result::Result { - if mem::size_of::() < mem::size_of::() { - return Err(ModelError::MailboxReqTypeTooSmall); - } - if mem::size_of::() < mem::size_of::() { - return Err(ModelError::MailboxRespTypeTooSmall); - } - if R::Resp::MIN_SIZE < mem::size_of::() { - return Err(ModelError::MailboxRespTypeTooSmall); - } - let (header_bytes, payload_bytes) = req - .as_bytes_mut() - .split_at_mut(mem::size_of::()); - - let mut header = MailboxReqHeader::read_from(header_bytes as &[u8]).unwrap(); - header.chksum = api::calc_checksum(R::ID.into(), payload_bytes); - header_bytes.copy_from_slice(header.as_bytes()); - - let Some(response_bytes) = self.mailbox_execute(R::ID.into(), req.as_bytes())? else { - return Err(ModelError::MailboxNoResponseData); - }; - if response_bytes.len() < R::Resp::MIN_SIZE - || response_bytes.len() > mem::size_of::() - { - return Err(ModelError::MailboxUnexpectedResponseLen { - expected_min: R::Resp::MIN_SIZE as u32, - expected_max: mem::size_of::() as u32, - actual: response_bytes.len() as u32, - }); - } - let mut response = R::Resp::new_zeroed(); - response.as_bytes_mut()[..response_bytes.len()].copy_from_slice(&response_bytes); - - let response_header = - MailboxRespHeader::read_from_prefix(response_bytes.as_slice()).unwrap(); - let actual_checksum = calc_checksum(0, &response_bytes[4..]); - if actual_checksum != response_header.chksum { - return Err(ModelError::MailboxRespInvalidChecksum { - expected: response_header.chksum, - actual: actual_checksum, - }); - } - if response_header.fips_status != MailboxRespHeader::FIPS_STATUS_APPROVED { - return Err(ModelError::MailboxRespInvalidFipsStatus( - response_header.fips_status, - )); - } - Ok(response) + + self.mailbox_exec_req(req, response.as_bytes_mut()) + .map_err(ModelError::from) } /// Executes `cmd` with request data `buf`. Returns `Ok(Some(_))` if @@ -1408,6 +1369,98 @@ mod tests { ); } + #[test] + /// Test SocManager maiLbox API. + fn test_negative_soc_mgr_mbox_users() { + let mut model = caliptra_hw_model::new_unbooted(InitParams { + rom: &gen_image_hi(), + ..Default::default() + }) + .unwrap(); + + model.soc_ifc().cptra_fuse_wr_done().write(|w| w.done(true)); + model.soc_ifc().cptra_bootfsm_go().write(|w| w.go(true)); + + // Set up the PAUSER as valid for the mailbox (using index 0) + model + .soc_ifc() + .cptra_mbox_valid_axi_id() + .at(0) + .write(|_| 0x1); + model + .soc_ifc() + .cptra_mbox_axi_id_lock() + .at(0) + .write(|w| w.lock(true)); + + assert_eq!( + model.setup_mailbox_users(&[1]), + Err(caliptra_api::CaliptraApiError::UnableToSetPauser) + ); + } + + #[test] + /// Test SocManager maiLbox API. + fn test_soc_mgr_mbox_api() { + use caliptra_api::CaliptraApiError; + let message: [u8; 10] = [0x90, 0x5e, 0x1f, 0xad, 0x8b, 0x60, 0xb0, 0xbf, 0x1c, 0x7e]; + + let rom = + caliptra_builder::build_firmware_rom(&firmware::hw_model_tests::MAILBOX_RESPONDER) + .unwrap(); + + let mut model = caliptra_hw_model::new( + InitParams { + rom: &rom, + ..Default::default() + }, + BootParams::default(), + ) + .unwrap(); + + // Send command that echoes the command and input message + let mut resp_data = [0u8; 128]; + + assert_eq!( + model.mailbox_exec(0x1000_0000, &message, &mut resp_data), + Ok(Some( + [[0x00, 0x00, 0x00, 0x10].as_slice(), &message] + .concat() + .as_bytes() + )), + ); + + // Send command that echoes the command and input message + let mut resp_data = [0u8; 128]; + assert_eq!( + model.mailbox_exec(0x1000_0000, &message[..8], resp_data.as_bytes_mut()), + Ok(Some( + [0x00, 0x00, 0x00, 0x10, 0x90, 0x5e, 0x1f, 0xad, 0x8b, 0x60, 0xb0, 0xbf].as_slice() + )), + ); + + // Send command that returns 7 bytes of output, and doesn't consume input + // Send command that echoes the command and input message + let mut resp_data = [0u8; 128]; + + assert_eq!( + model.mailbox_exec(0x1000_1000, &[42], resp_data.as_bytes_mut()), + Ok(Some([0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd].as_slice())), + ); + + // Send command that returns success with no output + assert_eq!( + model.mailbox_exec(0x2000_0000, &[], resp_data.as_bytes_mut()), + Ok(None) + ); + + // Send command that returns failure + assert_eq!( + model.mailbox_exec(0x4000_0000, &message, resp_data.as_bytes_mut()), + Err(CaliptraApiError::MailboxCmdFailed(0)) + ); + } + #[test] pub fn test_mailbox_receive() { let rom = caliptra_builder::build_firmware_rom(&firmware::hw_model_tests::MAILBOX_SENDER) @@ -1537,6 +1590,170 @@ mod tests { } } + #[test] + pub fn test_soc_mgr_exec_req() { + const NO_DATA_CMD: u32 = 0x2000_0000; + const SET_RESPONSE_CMD: u32 = 0x3000_0000; + const GET_RESPONSE_CMD: u32 = 0x3000_0001; + + #[repr(C)] + #[derive(AsBytes, FromBytes, Default)] + struct TestReq { + hdr: MailboxReqHeader, + data: [u8; 4], + } + impl mailbox::Request for TestReq { + const ID: CommandId = CommandId(GET_RESPONSE_CMD); + type Resp = TestResp; + } + #[repr(C)] + #[derive(AsBytes, Debug, FromBytes, PartialEq, Eq)] + struct TestResp { + hdr: MailboxRespHeader, + data: [u8; 4], + } + impl mailbox::Response for TestResp {} + + #[repr(C)] + #[derive(AsBytes, FromBytes, Default)] + struct TestReqNoData { + hdr: MailboxReqHeader, + data: [u8; 4], + } + impl mailbox::Request for TestReqNoData { + const ID: CommandId = CommandId(NO_DATA_CMD); + type Resp = TestResp; + } + + fn set_response(model: &mut DefaultHwModel, data: &[u8]) { + model.mailbox_execute(SET_RESPONSE_CMD, data).unwrap(); + } + + let rom = + caliptra_builder::build_firmware_rom(&firmware::hw_model_tests::MAILBOX_RESPONDER) + .unwrap(); + let mut model = caliptra_hw_model::new( + InitParams { + rom: &rom, + ..Default::default() + }, + BootParams::default(), + ) + .unwrap(); + + // Success + set_response( + &mut model, + &[ + 0x2d, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, b'H', b'I', b'!', b'!', + ], + ); + + let mut packet = [0u8; 256]; + let resp = model + .mailbox_exec_req( + TestReq { + data: *b"Hi!!", + ..Default::default() + }, + &mut packet, + ) + .unwrap(); + model + .step_until_output_and_take("|dcfeffff48692121|") + .unwrap(); + assert_eq!( + resp, + TestResp { + hdr: MailboxRespHeader { + chksum: 0xffffff2d, + fips_status: 0 + }, + data: *b"HI!!", + }, + ); + + // Set wrong length in response + set_response( + &mut model, + &[ + 0x2d, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, b'H', b'I', b'!', + ], + ); + let resp = model + .mailbox_exec_req( + TestReq { + data: *b"Hi!!", + ..Default::default() + }, + &mut packet, + ) + .map_err(ModelError::from); + assert_eq!( + resp, + Err(ModelError::MailboxUnexpectedResponseLen { + expected_min: 12, + expected_max: 12, + actual: 11 + }) + ); + + // Set bad checksum in response + set_response( + &mut model, + &[ + 0x2e, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, b'H', b'I', b'!', b'!', + ], + ); + let resp = model + .mailbox_exec_req( + TestReq { + data: *b"Hi!!", + ..Default::default() + }, + packet.as_bytes_mut(), + ) + .map_err(ModelError::from); + assert_eq!( + resp, + Err(ModelError::MailboxRespInvalidChecksum { + expected: 0xffffff2e, + actual: 0xffffff2d + }) + ); + + // Set bad FIPS status in response + set_response( + &mut model, + &[ + 0x0c, 0xff, 0xff, 0xff, 0x01, 0x20, 0x00, 0x00, b'H', b'I', b'!', b'!', + ], + ); + let mut packet = [0u8; 12]; + let resp = model + .mailbox_exec_req( + TestReq { + data: *b"Hi!!", + ..Default::default() + }, + &mut packet, + ) + .map_err(ModelError::from); + assert_eq!(resp, Err(ModelError::MailboxRespInvalidFipsStatus(0x2001))); + + // Set no data in response + let resp = model + .mailbox_exec_req( + TestReqNoData { + data: *b"Hi!!", + ..Default::default() + }, + &mut packet, + ) + .map_err(ModelError::from); + assert_eq!(resp, Err(ModelError::MailboxNoResponseData)); + } + #[test] pub fn test_mailbox_execute_req() { const NO_DATA_CMD: u32 = 0x2000_0000; diff --git a/rom/dev/tests/rom_integration_tests/test_idevid_derivation.rs b/rom/dev/tests/rom_integration_tests/test_idevid_derivation.rs index 016ce8c568..cb77cceca2 100644 --- a/rom/dev/tests/rom_integration_tests/test_idevid_derivation.rs +++ b/rom/dev/tests/rom_integration_tests/test_idevid_derivation.rs @@ -89,7 +89,7 @@ fn test_generate_csr_stress() { for _ in 0..num_tests { let fuses = fuses_with_random_uds(); let (mut hw, image_bundle) = - helpers::build_hw_model_and_image_bundle(fuses, ImageOptions::default()); + helpers::build_hw_model_and_image_bundle(fuses.clone(), ImageOptions::default()); let csr_bytes = generate_csr(&mut hw, &image_bundle); diff --git a/test/tests/caliptra_integration_tests/smoke_test.rs b/test/tests/caliptra_integration_tests/smoke_test.rs index 373c84e1b8..ab6259a5bb 100644 --- a/test/tests/caliptra_integration_tests/smoke_test.rs +++ b/test/tests/caliptra_integration_tests/smoke_test.rs @@ -174,7 +174,7 @@ fn smoke_test() { ..Default::default() }, BootParams { - fuses, + fuses: fuses.clone(), fw_image: Some(&image.to_bytes().unwrap()), ..Default::default() }, From ba8e9e30a290345874fe66c2281c857f2291ac4a Mon Sep 17 00:00:00 2001 From: Vishal Mhatre <38512878+mhatrevi@users.noreply.github.com> Date: Tue, 5 Nov 2024 02:32:59 +0530 Subject: [PATCH 04/51] Adding the stash measurement functionality to AuthorizeAndStashCmd (#1763) (cherry picked from commit 9803094b7240ef1769c8cf7286d5ef67775bad05) --- error/src/lib.rs | 2 ++ runtime/src/authorize_and_stash.rs | 22 +++++++++++++++++----- runtime/src/stash_measurement.rs | 23 +++++++++++++++++------ 3 files changed, 36 insertions(+), 11 deletions(-) diff --git a/error/src/lib.rs b/error/src/lib.rs index 90ba094ccd..bc0fef6cdd 100644 --- a/error/src/lib.rs +++ b/error/src/lib.rs @@ -468,6 +468,8 @@ impl CaliptraError { pub const RUNTIME_AUTH_AND_STASH_UNSUPPORTED_IMAGE_SOURCE: CaliptraError = CaliptraError::new_const(0x000E004E); pub const RUNTIME_CMD_RESERVED_PAUSER: CaliptraError = CaliptraError::new_const(0x000E004F); + pub const RUNTIME_AUTH_AND_STASH_MEASUREMENT_DPE_ERROR: CaliptraError = + CaliptraError::new_const(0x000E0050); /// FMC Errors pub const FMC_GLOBAL_NMI: CaliptraError = CaliptraError::new_const(0x000F0001); diff --git a/runtime/src/authorize_and_stash.rs b/runtime/src/authorize_and_stash.rs index 034d147f92..0ff44365a0 100644 --- a/runtime/src/authorize_and_stash.rs +++ b/runtime/src/authorize_and_stash.rs @@ -15,7 +15,7 @@ Abstract: use core::cmp::min; use core::mem::size_of; -use crate::{dpe_crypto::DpeCrypto, CptraDpeTypes, DpePlatform, Drivers}; +use crate::{dpe_crypto::DpeCrypto, CptraDpeTypes, DpePlatform, Drivers, StashMeasurementCmd}; use caliptra_auth_man_types::{ AuthManifestImageMetadataCollection, AuthManifestImageMetadataCollectionHeader, AuthManifestPreamble, AUTH_MANIFEST_MARKER, @@ -76,10 +76,22 @@ impl AuthorizeAndStashCmd { } } - let flags: AuthAndStashFlags = cmd.flags.into(); - if !flags.contains(AuthAndStashFlags::SKIP_STASH) { - // TODO: Stash the image hash - Err(CaliptraError::RUNTIME_UNIMPLEMENTED_COMMAND)?; + // Stash the measurement if the image is authorized. + if auth_result == AUTHORIZE_IMAGE { + let flags: AuthAndStashFlags = cmd.flags.into(); + if !flags.contains(AuthAndStashFlags::SKIP_STASH) { + let dpe_result = StashMeasurementCmd::stash_measurement( + drivers, + &cmd.metadata, + &cmd.measurement, + )?; + if dpe_result != DpeErrorCode::NoError { + drivers + .soc_ifc + .set_fw_extended_error(dpe_result.get_error_code()); + Err(CaliptraError::RUNTIME_AUTH_AND_STASH_MEASUREMENT_DPE_ERROR)?; + } + } } Ok(MailboxResp::AuthorizeAndStash(AuthorizeAndStashResp { diff --git a/runtime/src/stash_measurement.rs b/runtime/src/stash_measurement.rs index c81c58f0d9..7f13210ec5 100644 --- a/runtime/src/stash_measurement.rs +++ b/runtime/src/stash_measurement.rs @@ -31,9 +31,11 @@ pub struct StashMeasurementCmd; impl StashMeasurementCmd { #[cfg_attr(not(feature = "no-cfi"), cfi_impl_fn)] #[inline(never)] - pub(crate) fn execute(drivers: &mut Drivers, cmd_args: &[u8]) -> CaliptraResult { - let cmd = StashMeasurementReq::read_from(cmd_args) - .ok_or(CaliptraError::RUNTIME_INSUFFICIENT_MEMORY)?; + pub(crate) fn stash_measurement( + drivers: &mut Drivers, + metadata: &[u8; 4], + measurement: &[u8; 48], + ) -> CaliptraResult { let dpe_result = { match drivers.caller_privilege_level() { // Only PL0 can call STASH_MEASUREMENT @@ -78,12 +80,12 @@ impl StashMeasurementCmd { let derive_context_resp = DeriveContextCmd { handle: ContextHandle::default(), - data: cmd.measurement, + data: *measurement, flags: DeriveContextFlags::MAKE_DEFAULT | DeriveContextFlags::CHANGE_LOCALITY | DeriveContextFlags::INPUT_ALLOW_CA | DeriveContextFlags::INPUT_ALLOW_X509, - tci_type: u32::from_ne_bytes(cmd.metadata), + tci_type: u32::from_ne_bytes(*metadata), target_locality: locality, } .execute(&mut pdata.dpe, &mut env, locality); @@ -105,10 +107,19 @@ impl StashMeasurementCmd { drivers.pcr_bank.extend_pcr( PCR_ID_STASH_MEASUREMENT, &mut drivers.sha384, - cmd.measurement.as_bytes(), + measurement.as_bytes(), )?; } + Ok(dpe_result) + } + + pub(crate) fn execute(drivers: &mut Drivers, cmd_args: &[u8]) -> CaliptraResult { + let cmd = StashMeasurementReq::read_from(cmd_args) + .ok_or(CaliptraError::RUNTIME_INSUFFICIENT_MEMORY)?; + + let dpe_result = Self::stash_measurement(drivers, &cmd.metadata, &cmd.measurement)?; + Ok(MailboxResp::StashMeasurement(StashMeasurementResp { hdr: MailboxRespHeader::default(), dpe_result: dpe_result.get_error_code(), From 498b058cf678dfa06e319e73513001192e9d365b Mon Sep 17 00:00:00 2001 From: Nick Quarton <139178705+nquarton@users.noreply.github.com> Date: Wed, 6 Nov 2024 09:12:38 -0800 Subject: [PATCH 05/51] Cert tweaks to names and TCB info (#1725) (cherry picked from commit 1403d297a8ec3308c4f2934294f5f2204148af30) --- FROZEN_IMAGES.sha384sum | 4 +- .../fmc_integration_tests/test_rtalias.rs | 2 +- libcaliptra/examples/generic/idev_csr_array.h | 474 ++++++++++++++++-- rom/dev/build.rs | 11 +- rom/dev/src/flow/cold_reset/fmc_alias.rs | 2 +- .../test_fmcalias_derivation.rs | 2 +- runtime/src/dpe_platform.rs | 2 +- test/src/x509.rs | 5 +- .../caliptra_integration_tests/smoke_test.rs | 18 +- .../fmc_alias_cert_redacted.der | Bin 907 -> 874 bytes .../fmc_alias_cert_redacted.txt | 6 +- .../smoke_testdata/idevid_csr.der | Bin 444 -> 443 bytes .../smoke_testdata/idevid_csr.txt | 14 +- .../smoke_testdata/ldevid_cert.der | Bin 673 -> 674 bytes .../smoke_testdata/ldevid_cert.txt | 16 +- .../smoke_testdata/rt_alias_cert_redacted.der | Bin 784 -> 770 bytes .../smoke_testdata/rt_alias_cert_redacted.txt | 6 +- x509/build/build.rs | 8 +- x509/build/cert.rs | 4 +- x509/build/fmc_alias_cert_tbs.rs | 87 ++-- x509/build/init_dev_id_csr_tbs.rs | 2 +- x509/build/local_dev_id_cert_tbs.rs | 4 +- x509/build/rt_alias_cert_tbs.rs | 25 +- x509/build/x509.rs | 24 +- 24 files changed, 573 insertions(+), 143 deletions(-) diff --git a/FROZEN_IMAGES.sha384sum b/FROZEN_IMAGES.sha384sum index 70980588cd..97f1762a43 100644 --- a/FROZEN_IMAGES.sha384sum +++ b/FROZEN_IMAGES.sha384sum @@ -1,3 +1,3 @@ # WARNING: Do not update this file without the approval of the Caliptra TAC -490c1adcb0f9d2d03335f5eba2c762daf0b7e502aba15d03f12d41b26d74a513d5092200aff516dc009d54579d349217 caliptra-rom-no-log.bin -8ffd1577fa783e15b2a622a11575a5011286f933f2c4a5f267d45a04b93cf5ccd8af01715052b73bdfb5a86a6f2ccf64 caliptra-rom-with-log.bin +9537318fd30c3e3d341cffab5721ba3242810be85e79ed9dc644c47c062555ef7519fb48857745e7ccb9917ac1fe120a caliptra-rom-no-log.bin +e4e74d2d1c4794b950a548072fc8dc4c9ab64aba7a01ae400e9fe66c64b43f715e72dc430e7318496009ebedd0412bc6 caliptra-rom-with-log.bin diff --git a/fmc/tests/fmc_integration_tests/test_rtalias.rs b/fmc/tests/fmc_integration_tests/test_rtalias.rs index f898b5f80d..2c0735b0d5 100644 --- a/fmc/tests/fmc_integration_tests/test_rtalias.rs +++ b/fmc/tests/fmc_integration_tests/test_rtalias.rs @@ -96,7 +96,7 @@ fn test_fht_info() { let data = hw.mailbox_execute(TEST_CMD_READ_FHT, &[]).unwrap().unwrap(); let fht = FirmwareHandoffTable::read_from_prefix(data.as_bytes()).unwrap(); assert_eq!(fht.ldevid_tbs_size, 552); - assert_eq!(fht.fmcalias_tbs_size, 786); + assert_eq!(fht.fmcalias_tbs_size, 753); assert_eq!(fht.ldevid_tbs_addr, LDEVID_TBS_ORG); assert_eq!(fht.fmcalias_tbs_addr, FMCALIAS_TBS_ORG); assert_eq!(fht.pcr_log_addr, PCR_LOG_ORG); diff --git a/libcaliptra/examples/generic/idev_csr_array.h b/libcaliptra/examples/generic/idev_csr_array.h index 2aa5f72740..91439463f9 100644 --- a/libcaliptra/examples/generic/idev_csr_array.h +++ b/libcaliptra/examples/generic/idev_csr_array.h @@ -2,34 +2,450 @@ // Generated from test/tests/caliptra_integration_tests/smoke_testdata/idev_csr.der #include -#define IDEV_CSR_LEN 444 +#define IDEV_CSR_LEN 444 uint8_t idev_csr_bytes[IDEV_CSR_LEN] = { - 0x30, 0x82, 0x01, 0xB8, 0x30, 0x82, 0x01, 0x3E, 0x02, 0x01, 0x00, 0x30, 0x69, 0x31, 0x1C, 0x30, - 0x1A, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0C, 0x13, 0x43, 0x61, 0x6C, 0x69, 0x70, 0x74, 0x72, 0x61, - 0x20, 0x31, 0x2E, 0x30, 0x20, 0x49, 0x44, 0x65, 0x76, 0x49, 0x44, 0x31, 0x49, 0x30, 0x47, 0x06, - 0x03, 0x55, 0x04, 0x05, 0x13, 0x40, 0x45, 0x44, 0x34, 0x45, 0x31, 0x43, 0x44, 0x32, 0x39, 0x43, - 0x41, 0x41, 0x33, 0x44, 0x45, 0x31, 0x35, 0x38, 0x44, 0x46, 0x45, 0x41, 0x37, 0x43, 0x34, 0x30, - 0x39, 0x37, 0x33, 0x38, 0x31, 0x33, 0x39, 0x45, 0x45, 0x30, 0x35, 0x46, 0x34, 0x43, 0x41, 0x31, - 0x41, 0x32, 0x46, 0x38, 0x41, 0x30, 0x33, 0x33, 0x41, 0x41, 0x42, 0x31, 0x37, 0x31, 0x42, 0x36, - 0x38, 0x41, 0x31, 0x33, 0x31, 0x32, 0x30, 0x76, 0x30, 0x10, 0x06, 0x07, 0x2A, 0x86, 0x48, 0xCE, - 0x3D, 0x02, 0x01, 0x06, 0x05, 0x2B, 0x81, 0x04, 0x00, 0x22, 0x03, 0x62, 0x00, 0x04, 0x5B, 0x13, - 0x09, 0x96, 0x1B, 0xC5, 0x66, 0xE3, 0x4D, 0x37, 0x2A, 0x7B, 0x52, 0x2B, 0x9B, 0x4C, 0xD7, 0xB4, - 0x78, 0xE8, 0x45, 0x22, 0xEB, 0x32, 0x33, 0x51, 0x00, 0xBA, 0xE0, 0x90, 0xDE, 0xBF, 0x9F, 0x34, - 0x0A, 0x4A, 0x4C, 0xC6, 0xA8, 0x16, 0xB9, 0x0C, 0x3B, 0xF3, 0x04, 0x62, 0xAD, 0x52, 0x0F, 0x22, - 0x93, 0xA0, 0x9E, 0xB5, 0xAC, 0x38, 0xE4, 0x99, 0x5A, 0x54, 0x6C, 0x0C, 0x7E, 0xDA, 0x2E, 0x58, - 0xCC, 0xBC, 0xD9, 0x23, 0xD0, 0x48, 0x2C, 0x78, 0xCA, 0xF8, 0x71, 0xD1, 0x7B, 0x5A, 0x66, 0x0B, - 0x1C, 0x05, 0x6A, 0xD2, 0xC9, 0x99, 0xAB, 0x48, 0x73, 0x1C, 0xB9, 0xEE, 0x38, 0x26, 0xA0, 0x56, - 0x30, 0x54, 0x06, 0x09, 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x09, 0x0E, 0x31, 0x47, 0x30, - 0x45, 0x30, 0x12, 0x06, 0x03, 0x55, 0x1D, 0x13, 0x01, 0x01, 0xFF, 0x04, 0x08, 0x30, 0x06, 0x01, - 0x01, 0xFF, 0x02, 0x01, 0x05, 0x30, 0x0E, 0x06, 0x03, 0x55, 0x1D, 0x0F, 0x01, 0x01, 0xFF, 0x04, - 0x04, 0x03, 0x02, 0x02, 0x04, 0x30, 0x1F, 0x06, 0x06, 0x67, 0x81, 0x05, 0x05, 0x04, 0x04, 0x04, - 0x15, 0x30, 0x13, 0x04, 0x11, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x0A, 0x06, 0x08, 0x2A, 0x86, 0x48, 0xCE, 0x3D, 0x04, - 0x03, 0x03, 0x03, 0x68, 0x00, 0x30, 0x65, 0x02, 0x31, 0x00, 0xAC, 0x8C, 0x0F, 0xD8, 0xFA, 0xB7, - 0xD3, 0xBC, 0x60, 0x67, 0x68, 0x84, 0xCF, 0x9E, 0xDF, 0xA5, 0xCF, 0x4F, 0xB8, 0x09, 0xF2, 0xB2, - 0x8D, 0xC6, 0x22, 0xF7, 0x4D, 0x3B, 0x7D, 0x03, 0x2F, 0x57, 0x1D, 0x77, 0x59, 0xB1, 0x6A, 0x71, - 0x7F, 0x58, 0x7F, 0xC7, 0x41, 0x04, 0x40, 0x05, 0x2A, 0x89, 0x02, 0x30, 0x4B, 0x67, 0x94, 0x80, - 0xBA, 0x89, 0x47, 0x79, 0x6E, 0xAE, 0x7A, 0x91, 0x8A, 0xD5, 0x56, 0x15, 0x08, 0x73, 0x68, 0x3C, - 0x4B, 0x05, 0xDB, 0xB9, 0xD2, 0x9B, 0xB1, 0x7D, 0x06, 0xDB, 0xAF, 0xEA, 0x4A, 0xD6, 0x65, 0xB2, - 0x13, 0xC7, 0xCA, 0xED, 0x5F, 0x7F, 0x6D, 0xCC, 0x9B, 0x8A, 0x6D, 0x60, + 0x30, + 0x82, + 0x01, + 0xb8, + 0x30, + 0x82, + 0x01, + 0x3e, + 0x02, + 0x01, + 0x00, + 0x30, + 0x69, + 0x31, + 0x1c, + 0x30, + 0x1a, + 0x06, + 0x03, + 0x55, + 0x04, + 0x03, + 0x0c, + 0x13, + 0x43, + 0x61, + 0x6c, + 0x69, + 0x70, + 0x74, + 0x72, + 0x61, + 0x20, + 0x31, + 0x2e, + 0x78, + 0x20, + 0x49, + 0x44, + 0x65, + 0x76, + 0x49, + 0x44, + 0x31, + 0x49, + 0x30, + 0x47, + 0x06, + 0x03, + 0x55, + 0x04, + 0x05, + 0x13, + 0x40, + 0x38, + 0x45, + 0x33, + 0x43, + 0x31, + 0x41, + 0x30, + 0x35, + 0x38, + 0x46, + 0x37, + 0x30, + 0x34, + 0x41, + 0x31, + 0x31, + 0x38, + 0x32, + 0x31, + 0x46, + 0x37, + 0x42, + 0x34, + 0x38, + 0x44, + 0x33, + 0x34, + 0x30, + 0x41, + 0x45, + 0x46, + 0x39, + 0x39, + 0x44, + 0x44, + 0x41, + 0x42, + 0x41, + 0x44, + 0x43, + 0x31, + 0x30, + 0x39, + 0x30, + 0x44, + 0x37, + 0x34, + 0x44, + 0x30, + 0x35, + 0x37, + 0x46, + 0x45, + 0x43, + 0x43, + 0x46, + 0x37, + 0x33, + 0x32, + 0x39, + 0x34, + 0x45, + 0x44, + 0x36, + 0x30, + 0x76, + 0x30, + 0x10, + 0x06, + 0x07, + 0x2a, + 0x86, + 0x48, + 0xce, + 0x3d, + 0x02, + 0x01, + 0x06, + 0x05, + 0x2b, + 0x81, + 0x04, + 0x00, + 0x22, + 0x03, + 0x62, + 0x00, + 0x04, + 0xd7, + 0xb4, + 0x85, + 0xf2, + 0x9f, + 0x11, + 0x5c, + 0x1c, + 0xb3, + 0x04, + 0x6b, + 0x84, + 0x0b, + 0x45, + 0x89, + 0xb5, + 0x78, + 0x62, + 0xf5, + 0xeb, + 0xf9, + 0x9d, + 0x84, + 0x6f, + 0xbe, + 0x3f, + 0xd2, + 0xd1, + 0x43, + 0x96, + 0xf5, + 0xf6, + 0x9a, + 0x37, + 0x9a, + 0x59, + 0xac, + 0xc5, + 0xa2, + 0xae, + 0xc8, + 0x36, + 0x9e, + 0xcb, + 0x65, + 0x90, + 0x44, + 0x37, + 0xb4, + 0xbc, + 0x7c, + 0xd9, + 0xa5, + 0xa8, + 0x40, + 0x3c, + 0x5b, + 0xb1, + 0x91, + 0x52, + 0x23, + 0xaa, + 0x86, + 0xbe, + 0xf2, + 0xc1, + 0xbc, + 0x92, + 0x14, + 0x5f, + 0xfc, + 0x27, + 0xc1, + 0x25, + 0xc6, + 0xdb, + 0xfa, + 0xd4, + 0x9c, + 0x91, + 0xe8, + 0x48, + 0xc5, + 0x44, + 0xac, + 0x7f, + 0x0e, + 0x95, + 0xd6, + 0xcd, + 0x8c, + 0xac, + 0xfb, + 0x92, + 0x3f, + 0xa6, + 0xa0, + 0x56, + 0x30, + 0x54, + 0x06, + 0x09, + 0x2a, + 0x86, + 0x48, + 0x86, + 0xf7, + 0x0d, + 0x01, + 0x09, + 0x0e, + 0x31, + 0x47, + 0x30, + 0x45, + 0x30, + 0x12, + 0x06, + 0x03, + 0x55, + 0x1d, + 0x13, + 0x01, + 0x01, + 0xff, + 0x04, + 0x08, + 0x30, + 0x06, + 0x01, + 0x01, + 0xff, + 0x02, + 0x01, + 0x05, + 0x30, + 0x0e, + 0x06, + 0x03, + 0x55, + 0x1d, + 0x0f, + 0x01, + 0x01, + 0xff, + 0x04, + 0x04, + 0x03, + 0x02, + 0x02, + 0x04, + 0x30, + 0x1f, + 0x06, + 0x06, + 0x67, + 0x81, + 0x05, + 0x05, + 0x04, + 0x04, + 0x04, + 0x15, + 0x30, + 0x13, + 0x04, + 0x11, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x30, + 0x0a, + 0x06, + 0x08, + 0x2a, + 0x86, + 0x48, + 0xce, + 0x3d, + 0x04, + 0x03, + 0x03, + 0x03, + 0x68, + 0x00, + 0x30, + 0x65, + 0x02, + 0x31, + 0x00, + 0xed, + 0x8e, + 0x44, + 0x4e, + 0x3c, + 0x7f, + 0x6f, + 0x96, + 0x4a, + 0x5d, + 0xcb, + 0xe1, + 0xea, + 0x08, + 0xa0, + 0x57, + 0xf5, + 0xd7, + 0xb5, + 0x6d, + 0xce, + 0x72, + 0x9e, + 0xb8, + 0x8c, + 0x88, + 0x38, + 0xf6, + 0x50, + 0x35, + 0x90, + 0xbd, + 0x6b, + 0x59, + 0xdb, + 0x29, + 0x52, + 0x13, + 0x2e, + 0xfc, + 0xa8, + 0xb6, + 0x8d, + 0x8a, + 0x33, + 0xd3, + 0x2a, + 0xcf, + 0x02, + 0x30, + 0x6d, + 0x40, + 0x6a, + 0x1f, + 0x7c, + 0x9e, + 0x74, + 0x8f, + 0x28, + 0xdc, + 0x14, + 0x73, + 0xe0, + 0x96, + 0x92, + 0xd8, + 0x74, + 0xfa, + 0x30, + 0x58, + 0x04, + 0x54, + 0x84, + 0x77, + 0xe9, + 0x52, + 0x3a, + 0x0d, + 0x63, + 0xfa, + 0xf3, + 0x1a, + 0x68, + 0xc3, + 0x88, + 0x07, + 0x50, + 0xa7, + 0x5d, + 0x6f, + 0xf7, + 0xa9, + 0xda, + 0x98, + 0xf7, + 0x8c, + 0x48, + 0x2a, }; diff --git a/rom/dev/build.rs b/rom/dev/build.rs index 3c51a3601e..30bc1d097b 100644 --- a/rom/dev/build.rs +++ b/rom/dev/build.rs @@ -86,10 +86,13 @@ fn main() { use x509_parser::signature_value::EcdsaSigValue; let ws_dir = workspace_dir(); - let ldev_file = std::fs::read( - ws_dir.join("test/tests/caliptra_integration_tests/smoke_testdata/ldevid_cert.der"), - ) - .unwrap(); + let ldev_file_path = + ws_dir.join("test/tests/caliptra_integration_tests/smoke_testdata/ldevid_cert.der"); + println!( + "cargo:rerun-if-changed={}", + ldev_file_path.to_str().unwrap() + ); + let ldev_file = std::fs::read(ldev_file_path).unwrap(); let mut parser = X509CertificateParser::new(); let (_, cert) = parser.parse(&ldev_file).unwrap(); diff --git a/rom/dev/src/flow/cold_reset/fmc_alias.rs b/rom/dev/src/flow/cold_reset/fmc_alias.rs index c880a93c15..1f6f3f0cb2 100644 --- a/rom/dev/src/flow/cold_reset/fmc_alias.rs +++ b/rom/dev/src/flow/cold_reset/fmc_alias.rs @@ -263,6 +263,6 @@ impl FmcAliasLayer { flags |= dice::FLAG_BIT_DEBUG; } - flags.to_be_bytes() + flags.reverse_bits().to_be_bytes() } } diff --git a/rom/dev/tests/rom_integration_tests/test_fmcalias_derivation.rs b/rom/dev/tests/rom_integration_tests/test_fmcalias_derivation.rs index 014a455121..a9e1373c1f 100644 --- a/rom/dev/tests/rom_integration_tests/test_fmcalias_derivation.rs +++ b/rom/dev/tests/rom_integration_tests/test_fmcalias_derivation.rs @@ -744,7 +744,7 @@ fn test_fht_info() { let data = hw.mailbox_execute(0x1000_0003, &[]).unwrap().unwrap(); let fht = FirmwareHandoffTable::read_from_prefix(data.as_bytes()).unwrap(); assert_eq!(fht.ldevid_tbs_size, 552); - assert_eq!(fht.fmcalias_tbs_size, 786); + assert_eq!(fht.fmcalias_tbs_size, 753); assert_eq!(fht.ldevid_tbs_addr, LDEVID_TBS_ORG); assert_eq!(fht.fmcalias_tbs_addr, FMCALIAS_TBS_ORG); assert_eq!(fht.pcr_log_addr, PCR_LOG_ORG); diff --git a/runtime/src/dpe_platform.rs b/runtime/src/dpe_platform.rs index ab53d6122f..daeee3ad2d 100644 --- a/runtime/src/dpe_platform.rs +++ b/runtime/src/dpe_platform.rs @@ -108,7 +108,7 @@ impl Platform for DpePlatform<'_> { &mut self, out: &mut [u8; MAX_ISSUER_NAME_SIZE], ) -> Result { - const CALIPTRA_CN: &[u8] = b"Caliptra 1.0 Rt Alias"; + const CALIPTRA_CN: &[u8] = b"Caliptra 1.x Rt Alias"; let mut issuer_writer = CertWriter::new(out, true); // Caliptra RDN SerialNumber field is always a Sha256 hash diff --git a/test/src/x509.rs b/test/src/x509.rs index 6c5954223c..09ac3374f1 100644 --- a/test/src/x509.rs +++ b/test/src/x509.rs @@ -68,7 +68,10 @@ impl DiceTcbInfo { }) .transpose()? .unwrap_or_default(), - flags: d.read_optional_implicit_element(7)?, + flags: d + .read_optional_implicit_element::(7)? + .and_then(|b| b.as_bytes().try_into().ok()) + .map(u32::from_be_bytes), vendor_info: d .read_optional_implicit_element::<&[u8]>(8)? .map(|s| s.to_vec()), diff --git a/test/tests/caliptra_integration_tests/smoke_test.rs b/test/tests/caliptra_integration_tests/smoke_test.rs index ab6259a5bb..7add7c142f 100644 --- a/test/tests/caliptra_integration_tests/smoke_test.rs +++ b/test/tests/caliptra_integration_tests/smoke_test.rs @@ -278,8 +278,8 @@ fn smoke_test() { dice_tcb_info, [ DiceTcbInfo { - vendor: Some("Caliptra".into()), - model: Some("Device".into()), + vendor: None, + model: None, // This is from the SVN in the fuses (7 bits set) svn: Some(0x107), fwids: vec![DiceFwid { @@ -287,13 +287,13 @@ fn smoke_test() { digest: device_info_hash.to_vec(), },], - flags: Some(0x80000000), + flags: Some(0x00000001), ty: Some(b"DEVICE_INFO".to_vec()), ..Default::default() }, DiceTcbInfo { - vendor: Some("Caliptra".into()), - model: Some("FMC".into()), + vendor: None, + model: None, // This is from the SVN in the image (9) svn: Some(0x109), fwids: vec![DiceFwid { @@ -459,8 +459,8 @@ fn smoke_test() { assert_eq!( rt_dice_tcb_info, Some(DiceTcbInfo { - vendor: Some("Caliptra".into()), - model: Some("RT".into()), + vendor: None, + model: None, svn: Some(0x100), fwids: vec![DiceFwid { // RT @@ -609,8 +609,8 @@ fn smoke_test() { assert_eq!( rt_dice_tcb_info2, Some(DiceTcbInfo { - vendor: Some("Caliptra".into()), - model: Some("RT".into()), + vendor: None, + model: None, svn: Some(0x100), fwids: vec![DiceFwid { // FMC diff --git a/test/tests/caliptra_integration_tests/smoke_testdata/fmc_alias_cert_redacted.der b/test/tests/caliptra_integration_tests/smoke_testdata/fmc_alias_cert_redacted.der index 84e7805d2c139eb500dbefa7e5a5c3988a60cb38..60649c75c60df8f4eff409ccc343618d05c1ff34 100644 GIT binary patch delta 67 zcmeBXf5paU(8Qc((8Tn10W%XL6Vv1eOkxvNlo=}~dh`K_>lavk4VoA|C$C|2=Q+s6 Xmfpz9%EHRhxNR~c)3(Xin6?4{yRa2I delta 70 zcmaFG*3Hgu(8Syh#C!{wnHZUvL?(U|nW(J7XfV;E4@g|Uz?x^!#F#aC4Wm2HBR015 YMpjl9R+h%=lNp(|Okz}?yp?Gy0Lo4kB>(^b diff --git a/test/tests/caliptra_integration_tests/smoke_testdata/fmc_alias_cert_redacted.txt b/test/tests/caliptra_integration_tests/smoke_testdata/fmc_alias_cert_redacted.txt index ef18969566..a63df7f6df 100644 --- a/test/tests/caliptra_integration_tests/smoke_testdata/fmc_alias_cert_redacted.txt +++ b/test/tests/caliptra_integration_tests/smoke_testdata/fmc_alias_cert_redacted.txt @@ -4,11 +4,11 @@ Certificate: Serial Number: 44:44:44:44:44:44:44:44:44:44:44:44:44:44:44:44:44:44:44:44 Signature Algorithm: ecdsa-with-SHA384 - Issuer: CN=Caliptra 1.0 LDevID/serialNumber=21EEEF9A4C61D4B9E3D94BEA46F9A12AC6887CE2188559F40FF95777E8014889 + Issuer: CN=Caliptra 1.x LDevID/serialNumber=21EEEF9A4C61D4B9E3D94BEA46F9A12AC6887CE2188559F40FF95777E8014889 Validity Not Before: Jan 1 00:00:00 2023 GMT Not After : Dec 31 23:59:59 9999 GMT - Subject: CN=Caliptra 1.0 FMC Alias/serialNumber=DDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDD + Subject: CN=Caliptra 1.x FMC Alias/serialNumber=DDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDD Subject Public Key Info: Public Key Algorithm: id-ecPublicKey Public-Key: (384 bit) @@ -30,7 +30,7 @@ Certificate: 2.23.133.5.4.4: 0.................... 2.23.133.5.4.5: - DDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDD + DDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDD X509v3 Subject Key Identifier: 44:44:44:44:44:44:44:44:44:44:44:44:44:44:44:44:44:44:44:44 X509v3 Authority Key Identifier: diff --git a/test/tests/caliptra_integration_tests/smoke_testdata/idevid_csr.der b/test/tests/caliptra_integration_tests/smoke_testdata/idevid_csr.der index 3eb10487e1d55e8b59ecf5590c7b6b4429a33cf3..43da84d54404acd33e9f7950232ba4986d170b89 100644 GIT binary patch delta 150 zcmV;H0BQfc1G@txFoFTMFoFR-0s#OpX)zoy8U_PZ1Op5cLt$)baCCBEATcg@u_P}6 zXlDR0WCAc}E6FoFV}kpx2lc#%ks0eG?3VgYGr05D|&F#zi*=cj$QRbGefVds$E zhWmR{qq`^lY70+(m|xfxC6GmsH48x2{jXDM)nn{j)$e-QmGUl$tjM@klyM delta 128 zcmV-`0Du3Y1)&85FoFV|kpx2lFp)@(0Wh)GVgYDp05D_%Fi+XAYA-(e1o~g^X2QbQ zu2{@Dr3xT>dAD@AwAJhbFkBT>GpBRje@@T{9HW~FsRA%=C6Cf`%jTn?$3>XQz0bM} i)iA=)3%SmHK}%y|ss)mUx8YZ%?QquAKe8(CRd7+C@)GcpBCj%L~l0D)r{hX4Qo delta 79 zcmV-V0I>gp29O31FoFXNFoFV;paTK{0s<6~VHA^%0t}Ha7zHpOMomMJ-BOXBI{`3} l+Rg;>FoExrtN}&~Xa)vnfdvHw0R&!?0Rl{sa1xVE0=0D97e4?1 diff --git a/test/tests/caliptra_integration_tests/smoke_testdata/rt_alias_cert_redacted.txt b/test/tests/caliptra_integration_tests/smoke_testdata/rt_alias_cert_redacted.txt index fabcc6718f..52d55db979 100644 --- a/test/tests/caliptra_integration_tests/smoke_testdata/rt_alias_cert_redacted.txt +++ b/test/tests/caliptra_integration_tests/smoke_testdata/rt_alias_cert_redacted.txt @@ -4,11 +4,11 @@ Certificate: Serial Number: 44:44:44:44:44:44:44:44:44:44:44:44:44:44:44:44:44:44:44:44 Signature Algorithm: ecdsa-with-SHA384 - Issuer: CN=Caliptra 1.0 FMC Alias/serialNumber=DDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDD + Issuer: CN=Caliptra 1.x FMC Alias/serialNumber=DDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDD Validity Not Before: Jan 1 00:00:00 2023 GMT Not After : Dec 31 23:59:59 9999 GMT - Subject: CN=Caliptra 1.0 Rt Alias/serialNumber=DDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDD + Subject: CN=Caliptra 1.x Rt Alias/serialNumber=DDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDD Subject Public Key Info: Public Key Algorithm: id-ecPublicKey Public-Key: (384 bit) @@ -30,7 +30,7 @@ Certificate: 2.23.133.5.4.4: 0.................... 2.23.133.5.4.1: - DDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDD + DDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDD X509v3 Subject Key Identifier: 44:44:44:44:44:44:44:44:44:44:44:44:44:44:44:44:44:44:44:44 X509v3 Authority Key Identifier: diff --git a/x509/build/build.rs b/x509/build/build.rs index aa728c6eaa..dc116c3505 100644 --- a/x509/build/build.rs +++ b/x509/build/build.rs @@ -54,7 +54,7 @@ fn gen_init_devid_csr(out_dir: &str) { .add_basic_constraints_ext(true, 5) .add_key_usage_ext(usage) .add_ueid_ext(&[0xFF; 17]); - let template = bldr.tbs_template("Caliptra 1.0 IDevID"); + let template = bldr.tbs_template("Caliptra 1.x IDevID"); CodeGen::gen_code("InitDevIdCsrTbs", template, out_dir); } @@ -67,7 +67,7 @@ fn gen_local_devid_cert(out_dir: &str) { .add_basic_constraints_ext(true, 4) .add_key_usage_ext(usage) .add_ueid_ext(&[0xFF; 17]); - let template = bldr.tbs_template("Caliptra 1.0 LDevID", "Caliptra 1.0 IDevID"); + let template = bldr.tbs_template("Caliptra 1.x LDevID", "Caliptra 1.x IDevID"); CodeGen::gen_code("LocalDevIdCertTbs", template, out_dir); } @@ -98,7 +98,7 @@ fn gen_fmc_alias_cert(out_dir: &str) { }, }], ); - let template = bldr.tbs_template("Caliptra 1.0 FMC Alias", "Caliptra 1.0 LDevID"); + let template = bldr.tbs_template("Caliptra 1.x FMC Alias", "Caliptra 1.x LDevID"); CodeGen::gen_code("FmcAliasCertTbs", template, out_dir); } @@ -122,6 +122,6 @@ fn gen_rt_alias_cert(out_dir: &str) { digest: &[0xCD; 48], }, }]); - let template = bldr.tbs_template("Caliptra 1.0 Rt Alias", "Caliptra 1.0 FMC Alias"); + let template = bldr.tbs_template("Caliptra 1.x Rt Alias", "Caliptra 1.x FMC Alias"); CodeGen::gen_code("RtAliasCertTbs", template, out_dir); } diff --git a/x509/build/cert.rs b/x509/build/cert.rs index 966a6412bd..3ad2afd090 100644 --- a/x509/build/cert.rs +++ b/x509/build/cert.rs @@ -90,9 +90,11 @@ impl CertTemplateBuilder { device_fwids: &[FwidParam], fmc_fwids: &[FwidParam], ) -> Self { + // This method of finding the offsets is fragile. Especially for the 1 byte values. + // These may need to be updated to stay unique when the cert template is updated. let flags: u32 = 0xC0C1C2C3; let svn: u8 = 0xC4; - let svn_fuses: u8 = 0xC5; + let svn_fuses: u8 = 0xC6; self.exts .push(x509::make_fmc_dice_tcb_info_ext( diff --git a/x509/build/fmc_alias_cert_tbs.rs b/x509/build/fmc_alias_cert_tbs.rs index dfda357ba1..f8724c2441 100644 --- a/x509/build/fmc_alias_cert_tbs.rs +++ b/x509/build/fmc_alias_cert_tbs.rs @@ -46,17 +46,17 @@ impl FmcAliasCertTbs { const PUBLIC_KEY_OFFSET: usize = 319usize; const SUBJECT_SN_OFFSET: usize = 232usize; const ISSUER_SN_OFFSET: usize = 86usize; - const TCB_INFO_DEVICE_INFO_HASH_OFFSET: usize = 551usize; - const TCB_INFO_FMC_TCI_OFFSET: usize = 664usize; + const TCB_INFO_DEVICE_INFO_HASH_OFFSET: usize = 533usize; + const TCB_INFO_FMC_TCI_OFFSET: usize = 631usize; const SERIAL_NUMBER_OFFSET: usize = 11usize; - const SUBJECT_KEY_ID_OFFSET: usize = 733usize; - const AUTHORITY_KEY_ID_OFFSET: usize = 766usize; + const SUBJECT_KEY_ID_OFFSET: usize = 700usize; + const AUTHORITY_KEY_ID_OFFSET: usize = 733usize; const UEID_OFFSET: usize = 476usize; const NOT_BEFORE_OFFSET: usize = 154usize; const NOT_AFTER_OFFSET: usize = 171usize; - const TCB_INFO_FLAGS_OFFSET: usize = 602usize; - const TCB_INFO_FMC_SVN_OFFSET: usize = 646usize; - const TCB_INFO_FMC_SVN_FUSES_OFFSET: usize = 533usize; + const TCB_INFO_FLAGS_OFFSET: usize = 584usize; + const TCB_INFO_FMC_SVN_OFFSET: usize = 613usize; + const TCB_INFO_FMC_SVN_FUSES_OFFSET: usize = 515usize; const PUBLIC_KEY_LEN: usize = 97usize; const SUBJECT_SN_LEN: usize = 64usize; const ISSUER_SN_LEN: usize = 64usize; @@ -71,61 +71,58 @@ impl FmcAliasCertTbs { const TCB_INFO_FLAGS_LEN: usize = 4usize; const TCB_INFO_FMC_SVN_LEN: usize = 1usize; const TCB_INFO_FMC_SVN_FUSES_LEN: usize = 1usize; - pub const TBS_TEMPLATE_LEN: usize = 786usize; + pub const TBS_TEMPLATE_LEN: usize = 753usize; const TBS_TEMPLATE: [u8; Self::TBS_TEMPLATE_LEN] = [ - 48u8, 130u8, 3u8, 14u8, 160u8, 3u8, 2u8, 1u8, 2u8, 2u8, 20u8, 95u8, 95u8, 95u8, 95u8, 95u8, + 48u8, 130u8, 2u8, 237u8, 160u8, 3u8, 2u8, 1u8, 2u8, 2u8, 20u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, - 48u8, 10u8, 6u8, 8u8, 42u8, 134u8, 72u8, 206u8, 61u8, 4u8, 3u8, 3u8, 48u8, 105u8, 49u8, - 28u8, 48u8, 26u8, 6u8, 3u8, 85u8, 4u8, 3u8, 12u8, 19u8, 67u8, 97u8, 108u8, 105u8, 112u8, - 116u8, 114u8, 97u8, 32u8, 49u8, 46u8, 48u8, 32u8, 76u8, 68u8, 101u8, 118u8, 73u8, 68u8, - 49u8, 73u8, 48u8, 71u8, 6u8, 3u8, 85u8, 4u8, 5u8, 19u8, 64u8, 95u8, 95u8, 95u8, 95u8, 95u8, + 95u8, 48u8, 10u8, 6u8, 8u8, 42u8, 134u8, 72u8, 206u8, 61u8, 4u8, 3u8, 3u8, 48u8, 105u8, + 49u8, 28u8, 48u8, 26u8, 6u8, 3u8, 85u8, 4u8, 3u8, 12u8, 19u8, 67u8, 97u8, 108u8, 105u8, + 112u8, 116u8, 114u8, 97u8, 32u8, 49u8, 46u8, 120u8, 32u8, 76u8, 68u8, 101u8, 118u8, 73u8, + 68u8, 49u8, 73u8, 48u8, 71u8, 6u8, 3u8, 85u8, 4u8, 5u8, 19u8, 64u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, - 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 48u8, - 34u8, 24u8, 15u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, - 95u8, 95u8, 95u8, 24u8, 15u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, - 95u8, 95u8, 95u8, 95u8, 95u8, 48u8, 108u8, 49u8, 31u8, 48u8, 29u8, 6u8, 3u8, 85u8, 4u8, - 3u8, 12u8, 22u8, 67u8, 97u8, 108u8, 105u8, 112u8, 116u8, 114u8, 97u8, 32u8, 49u8, 46u8, - 48u8, 32u8, 70u8, 77u8, 67u8, 32u8, 65u8, 108u8, 105u8, 97u8, 115u8, 49u8, 73u8, 48u8, - 71u8, 6u8, 3u8, 85u8, 4u8, 5u8, 19u8, 64u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, + 48u8, 34u8, 24u8, 15u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, + 95u8, 95u8, 95u8, 95u8, 24u8, 15u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, + 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 48u8, 108u8, 49u8, 31u8, 48u8, 29u8, 6u8, 3u8, 85u8, + 4u8, 3u8, 12u8, 22u8, 67u8, 97u8, 108u8, 105u8, 112u8, 116u8, 114u8, 97u8, 32u8, 49u8, + 46u8, 120u8, 32u8, 70u8, 77u8, 67u8, 32u8, 65u8, 108u8, 105u8, 97u8, 115u8, 49u8, 73u8, + 48u8, 71u8, 6u8, 3u8, 85u8, 4u8, 5u8, 19u8, 64u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, - 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 48u8, 118u8, 48u8, 16u8, - 6u8, 7u8, 42u8, 134u8, 72u8, 206u8, 61u8, 2u8, 1u8, 6u8, 5u8, 43u8, 129u8, 4u8, 0u8, 34u8, - 3u8, 98u8, 0u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, + 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 48u8, 118u8, 48u8, + 16u8, 6u8, 7u8, 42u8, 134u8, 72u8, 206u8, 61u8, 2u8, 1u8, 6u8, 5u8, 43u8, 129u8, 4u8, 0u8, + 34u8, 3u8, 98u8, 0u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, - 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 163u8, 130u8, 1u8, 110u8, 48u8, - 130u8, 1u8, 106u8, 48u8, 18u8, 6u8, 3u8, 85u8, 29u8, 19u8, 1u8, 1u8, 255u8, 4u8, 8u8, 48u8, - 6u8, 1u8, 1u8, 255u8, 2u8, 1u8, 3u8, 48u8, 14u8, 6u8, 3u8, 85u8, 29u8, 15u8, 1u8, 1u8, - 255u8, 4u8, 4u8, 3u8, 2u8, 2u8, 4u8, 48u8, 31u8, 6u8, 6u8, 103u8, 129u8, 5u8, 5u8, 4u8, - 4u8, 4u8, 21u8, 48u8, 19u8, 4u8, 17u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, - 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 48u8, 129u8, 226u8, 6u8, 6u8, 103u8, - 129u8, 5u8, 5u8, 4u8, 5u8, 4u8, 129u8, 215u8, 48u8, 129u8, 212u8, 48u8, 114u8, 128u8, 8u8, - 67u8, 97u8, 108u8, 105u8, 112u8, 116u8, 114u8, 97u8, 129u8, 6u8, 68u8, 101u8, 118u8, 105u8, - 99u8, 101u8, 131u8, 2u8, 1u8, 95u8, 166u8, 63u8, 48u8, 61u8, 6u8, 9u8, 96u8, 134u8, 72u8, - 1u8, 101u8, 3u8, 4u8, 2u8, 2u8, 4u8, 48u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, + 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 163u8, 130u8, 1u8, 77u8, + 48u8, 130u8, 1u8, 73u8, 48u8, 18u8, 6u8, 3u8, 85u8, 29u8, 19u8, 1u8, 1u8, 255u8, 4u8, 8u8, + 48u8, 6u8, 1u8, 1u8, 255u8, 2u8, 1u8, 3u8, 48u8, 14u8, 6u8, 3u8, 85u8, 29u8, 15u8, 1u8, + 1u8, 255u8, 4u8, 4u8, 3u8, 2u8, 2u8, 4u8, 48u8, 31u8, 6u8, 6u8, 103u8, 129u8, 5u8, 5u8, + 4u8, 4u8, 4u8, 21u8, 48u8, 19u8, 4u8, 17u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, + 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 48u8, 129u8, 193u8, 6u8, 6u8, 103u8, + 129u8, 5u8, 5u8, 4u8, 5u8, 4u8, 129u8, 182u8, 48u8, 129u8, 179u8, 48u8, 96u8, 131u8, 2u8, + 1u8, 95u8, 166u8, 63u8, 48u8, 61u8, 6u8, 9u8, 96u8, 134u8, 72u8, 1u8, 101u8, 3u8, 4u8, 2u8, + 2u8, 4u8, 48u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, - 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 135u8, 5u8, 0u8, 95u8, 95u8, - 95u8, 95u8, 137u8, 11u8, 68u8, 69u8, 86u8, 73u8, 67u8, 69u8, 95u8, 73u8, 78u8, 70u8, 79u8, - 138u8, 5u8, 0u8, 128u8, 0u8, 0u8, 11u8, 48u8, 94u8, 128u8, 8u8, 67u8, 97u8, 108u8, 105u8, - 112u8, 116u8, 114u8, 97u8, 129u8, 3u8, 70u8, 77u8, 67u8, 131u8, 2u8, 1u8, 95u8, 166u8, - 63u8, 48u8, 61u8, 6u8, 9u8, 96u8, 134u8, 72u8, 1u8, 101u8, 3u8, 4u8, 2u8, 2u8, 4u8, 48u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, + 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 135u8, 5u8, 0u8, 95u8, 95u8, 95u8, 95u8, 137u8, 11u8, + 68u8, 69u8, 86u8, 73u8, 67u8, 69u8, 95u8, 73u8, 78u8, 70u8, 79u8, 138u8, 5u8, 0u8, 208u8, + 0u8, 0u8, 1u8, 48u8, 79u8, 131u8, 2u8, 1u8, 95u8, 166u8, 63u8, 48u8, 61u8, 6u8, 9u8, 96u8, + 134u8, 72u8, 1u8, 101u8, 3u8, 4u8, 2u8, 2u8, 4u8, 48u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, - 95u8, 95u8, 95u8, 137u8, 8u8, 70u8, 77u8, 67u8, 95u8, 73u8, 78u8, 70u8, 79u8, 48u8, 29u8, - 6u8, 3u8, 85u8, 29u8, 14u8, 4u8, 22u8, 4u8, 20u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, - 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 48u8, 31u8, - 6u8, 3u8, 85u8, 29u8, 35u8, 4u8, 24u8, 48u8, 22u8, 128u8, 20u8, 95u8, 95u8, 95u8, 95u8, - 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, - 95u8, + 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 137u8, 8u8, 70u8, + 77u8, 67u8, 95u8, 73u8, 78u8, 70u8, 79u8, 48u8, 29u8, 6u8, 3u8, 85u8, 29u8, 14u8, 4u8, + 22u8, 4u8, 20u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, + 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 48u8, 31u8, 6u8, 3u8, 85u8, 29u8, 35u8, + 4u8, 24u8, 48u8, 22u8, 128u8, 20u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, + 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, ]; pub fn new(params: &FmcAliasCertTbsParams) -> Self { let mut template = Self { @@ -146,7 +143,7 @@ impl FmcAliasCertTbs { fn apply(&mut self, params: &FmcAliasCertTbsParams) { #[inline(always)] fn apply_slice( - buf: &mut [u8; 786usize], + buf: &mut [u8; 753usize], val: &[u8; LEN], ) { buf[OFFSET..OFFSET + LEN].copy_from_slice(val); diff --git a/x509/build/init_dev_id_csr_tbs.rs b/x509/build/init_dev_id_csr_tbs.rs index c989be7267..e4139c01ad 100644 --- a/x509/build/init_dev_id_csr_tbs.rs +++ b/x509/build/init_dev_id_csr_tbs.rs @@ -31,7 +31,7 @@ impl InitDevIdCsrTbs { const TBS_TEMPLATE: [u8; Self::TBS_TEMPLATE_LEN] = [ 48u8, 130u8, 1u8, 62u8, 2u8, 1u8, 0u8, 48u8, 105u8, 49u8, 28u8, 48u8, 26u8, 6u8, 3u8, 85u8, 4u8, 3u8, 12u8, 19u8, 67u8, 97u8, 108u8, 105u8, 112u8, 116u8, 114u8, 97u8, 32u8, 49u8, - 46u8, 48u8, 32u8, 73u8, 68u8, 101u8, 118u8, 73u8, 68u8, 49u8, 73u8, 48u8, 71u8, 6u8, 3u8, + 46u8, 120u8, 32u8, 73u8, 68u8, 101u8, 118u8, 73u8, 68u8, 49u8, 73u8, 48u8, 71u8, 6u8, 3u8, 85u8, 4u8, 5u8, 19u8, 64u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, diff --git a/x509/build/local_dev_id_cert_tbs.rs b/x509/build/local_dev_id_cert_tbs.rs index adb180a84c..b9b0fcdf77 100644 --- a/x509/build/local_dev_id_cert_tbs.rs +++ b/x509/build/local_dev_id_cert_tbs.rs @@ -57,7 +57,7 @@ impl LocalDevIdCertTbs { 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 48u8, 10u8, 6u8, 8u8, 42u8, 134u8, 72u8, 206u8, 61u8, 4u8, 3u8, 3u8, 48u8, 105u8, 49u8, 28u8, 48u8, 26u8, 6u8, 3u8, 85u8, 4u8, 3u8, 12u8, 19u8, 67u8, 97u8, 108u8, 105u8, 112u8, - 116u8, 114u8, 97u8, 32u8, 49u8, 46u8, 48u8, 32u8, 73u8, 68u8, 101u8, 118u8, 73u8, 68u8, + 116u8, 114u8, 97u8, 32u8, 49u8, 46u8, 120u8, 32u8, 73u8, 68u8, 101u8, 118u8, 73u8, 68u8, 49u8, 73u8, 48u8, 71u8, 6u8, 3u8, 85u8, 4u8, 5u8, 19u8, 64u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, @@ -67,7 +67,7 @@ impl LocalDevIdCertTbs { 95u8, 95u8, 95u8, 24u8, 15u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 48u8, 105u8, 49u8, 28u8, 48u8, 26u8, 6u8, 3u8, 85u8, 4u8, 3u8, 12u8, 19u8, 67u8, 97u8, 108u8, 105u8, 112u8, 116u8, 114u8, 97u8, 32u8, 49u8, 46u8, - 48u8, 32u8, 76u8, 68u8, 101u8, 118u8, 73u8, 68u8, 49u8, 73u8, 48u8, 71u8, 6u8, 3u8, 85u8, + 120u8, 32u8, 76u8, 68u8, 101u8, 118u8, 73u8, 68u8, 49u8, 73u8, 48u8, 71u8, 6u8, 3u8, 85u8, 4u8, 5u8, 19u8, 64u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, diff --git a/x509/build/rt_alias_cert_tbs.rs b/x509/build/rt_alias_cert_tbs.rs index 6d07b86bbc..0e2b75eb2d 100644 --- a/x509/build/rt_alias_cert_tbs.rs +++ b/x509/build/rt_alias_cert_tbs.rs @@ -40,14 +40,14 @@ impl RtAliasCertTbs { const PUBLIC_KEY_OFFSET: usize = 321usize; const SUBJECT_SN_OFFSET: usize = 234usize; const ISSUER_SN_OFFSET: usize = 89usize; - const TCB_INFO_RT_TCI_OFFSET: usize = 542usize; + const TCB_INFO_RT_TCI_OFFSET: usize = 528usize; const SERIAL_NUMBER_OFFSET: usize = 11usize; - const SUBJECT_KEY_ID_OFFSET: usize = 610usize; - const AUTHORITY_KEY_ID_OFFSET: usize = 643usize; + const SUBJECT_KEY_ID_OFFSET: usize = 596usize; + const AUTHORITY_KEY_ID_OFFSET: usize = 629usize; const UEID_OFFSET: usize = 476usize; const NOT_BEFORE_OFFSET: usize = 157usize; const NOT_AFTER_OFFSET: usize = 174usize; - const TCB_INFO_RT_SVN_OFFSET: usize = 524usize; + const TCB_INFO_RT_SVN_OFFSET: usize = 510usize; const PUBLIC_KEY_LEN: usize = 97usize; const SUBJECT_SN_LEN: usize = 64usize; const ISSUER_SN_LEN: usize = 64usize; @@ -59,13 +59,13 @@ impl RtAliasCertTbs { const NOT_BEFORE_LEN: usize = 15usize; const NOT_AFTER_LEN: usize = 15usize; const TCB_INFO_RT_SVN_LEN: usize = 1usize; - pub const TBS_TEMPLATE_LEN: usize = 663usize; + pub const TBS_TEMPLATE_LEN: usize = 649usize; const TBS_TEMPLATE: [u8; Self::TBS_TEMPLATE_LEN] = [ - 48u8, 130u8, 2u8, 147u8, 160u8, 3u8, 2u8, 1u8, 2u8, 2u8, 20u8, 95u8, 95u8, 95u8, 95u8, + 48u8, 130u8, 2u8, 133u8, 160u8, 3u8, 2u8, 1u8, 2u8, 2u8, 20u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 48u8, 10u8, 6u8, 8u8, 42u8, 134u8, 72u8, 206u8, 61u8, 4u8, 3u8, 3u8, 48u8, 108u8, 49u8, 31u8, 48u8, 29u8, 6u8, 3u8, 85u8, 4u8, 3u8, 12u8, 22u8, 67u8, 97u8, 108u8, 105u8, - 112u8, 116u8, 114u8, 97u8, 32u8, 49u8, 46u8, 48u8, 32u8, 70u8, 77u8, 67u8, 32u8, 65u8, + 112u8, 116u8, 114u8, 97u8, 32u8, 49u8, 46u8, 120u8, 32u8, 70u8, 77u8, 67u8, 32u8, 65u8, 108u8, 105u8, 97u8, 115u8, 49u8, 73u8, 48u8, 71u8, 6u8, 3u8, 85u8, 4u8, 5u8, 19u8, 64u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, @@ -75,7 +75,7 @@ impl RtAliasCertTbs { 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 24u8, 15u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 48u8, 107u8, 49u8, 30u8, 48u8, 28u8, 6u8, 3u8, 85u8, 4u8, 3u8, 12u8, 21u8, 67u8, 97u8, 108u8, 105u8, 112u8, 116u8, 114u8, - 97u8, 32u8, 49u8, 46u8, 48u8, 32u8, 82u8, 116u8, 32u8, 65u8, 108u8, 105u8, 97u8, 115u8, + 97u8, 32u8, 49u8, 46u8, 120u8, 32u8, 82u8, 116u8, 32u8, 65u8, 108u8, 105u8, 97u8, 115u8, 49u8, 73u8, 48u8, 71u8, 6u8, 3u8, 85u8, 4u8, 5u8, 19u8, 64u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, @@ -89,13 +89,12 @@ impl RtAliasCertTbs { 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 163u8, - 129u8, 242u8, 48u8, 129u8, 239u8, 48u8, 18u8, 6u8, 3u8, 85u8, 29u8, 19u8, 1u8, 1u8, 255u8, + 129u8, 228u8, 48u8, 129u8, 225u8, 48u8, 18u8, 6u8, 3u8, 85u8, 29u8, 19u8, 1u8, 1u8, 255u8, 4u8, 8u8, 48u8, 6u8, 1u8, 1u8, 255u8, 2u8, 1u8, 2u8, 48u8, 14u8, 6u8, 3u8, 85u8, 29u8, 15u8, 1u8, 1u8, 255u8, 4u8, 4u8, 3u8, 2u8, 2u8, 132u8, 48u8, 31u8, 6u8, 6u8, 103u8, 129u8, 5u8, 5u8, 4u8, 4u8, 4u8, 21u8, 48u8, 19u8, 4u8, 17u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, - 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 48u8, 104u8, 6u8, 6u8, - 103u8, 129u8, 5u8, 5u8, 4u8, 1u8, 4u8, 94u8, 48u8, 92u8, 128u8, 8u8, 67u8, 97u8, 108u8, - 105u8, 112u8, 116u8, 114u8, 97u8, 129u8, 2u8, 82u8, 84u8, 131u8, 2u8, 1u8, 95u8, 166u8, + 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 48u8, 90u8, 6u8, 6u8, + 103u8, 129u8, 5u8, 5u8, 4u8, 1u8, 4u8, 80u8, 48u8, 78u8, 131u8, 2u8, 1u8, 95u8, 166u8, 63u8, 48u8, 61u8, 6u8, 9u8, 96u8, 134u8, 72u8, 1u8, 101u8, 3u8, 4u8, 2u8, 2u8, 4u8, 48u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, @@ -126,7 +125,7 @@ impl RtAliasCertTbs { fn apply(&mut self, params: &RtAliasCertTbsParams) { #[inline(always)] fn apply_slice( - buf: &mut [u8; 663usize], + buf: &mut [u8; 649usize], val: &[u8; LEN], ) { buf[OFFSET..OFFSET + LEN].copy_from_slice(val); diff --git a/x509/build/x509.rs b/x509/build/x509.rs index ba71ebdac1..7a90254c79 100644 --- a/x509/build/x509.rs +++ b/x509/build/x509.rs @@ -316,12 +316,12 @@ pub fn make_fmc_dice_tcb_info_ext( let wide_svn_fuses = fixed_width_svn(svn_fuses); let be_flags = flags.to_be_bytes(); - let be_flags_mask = FLAG_MASK.to_be_bytes(); + let be_flags_mask = FLAG_MASK.reverse_bits().to_be_bytes(); let device_asn1_fwids: Vec<&Fwid> = device_fwids.iter().map(|f| &f.fwid).collect(); let device_info = TcbInfo { - vendor: Some(asn1::Utf8String::new("Caliptra")), - model: Some(asn1::Utf8String::new("Device")), + vendor: None, + model: None, version: None, svn: Some(wide_svn_fuses.into()), layer: None, @@ -335,8 +335,8 @@ pub fn make_fmc_dice_tcb_info_ext( let fmc_asn1_fwids: Vec<&Fwid> = fmc_fwids.iter().map(|f| &f.fwid).collect(); let fmc_info = TcbInfo { - vendor: Some(asn1::Utf8String::new("Caliptra")), - model: Some(asn1::Utf8String::new("FMC")), + vendor: None, + model: None, version: None, svn: Some(wide_svn.into()), layer: None, @@ -362,8 +362,8 @@ pub fn make_rt_dice_tcb_info_ext(svn: u8, fwids: &[FwidParam]) -> X509Extension let asn1_fwids: Vec<&Fwid> = fwids.iter().map(|f| &f.fwid).collect(); let rt_info = TcbInfo { - vendor: Some(asn1::Utf8String::new("Caliptra")), - model: Some(asn1::Utf8String::new("RT")), + vendor: None, + model: None, version: None, svn: Some(wide_svn.into()), layer: None, @@ -421,6 +421,16 @@ pub fn get_tbs(der: Vec) -> Vec { pub fn init_param(needle: &[u8], haystack: &[u8], param: TbsParam) -> TbsParam { assert_eq!(needle.len(), param.len); eprintln!("{}", param.name); + // Throw an error if there are multiple instances of our "needle" + // This could lead to incorrect offsets in the cert template + if haystack.windows(param.len).filter(|w| *w == needle).count() > 1 { + panic!( + "Multiple instances of needle '{}' with value\n\n{}\n\nin haystack\n\n{}", + param.name, + needle.encode_hex::(), + haystack.encode_hex::() + ); + } let pos = haystack.windows(param.len).position(|w| w == needle); match pos { From 487fc63d79a47c99184db1968c3ff2ec47b8efe1 Mon Sep 17 00:00:00 2001 From: Christopher Swenson Date: Wed, 6 Nov 2024 09:52:53 -0800 Subject: [PATCH 06/51] cfi: Simpler launder implementation for common types (#1714) * `cfi_launder` is meant to prevent the Rust compiler from optimizing a value away. Our current implementation uses `core::hint::black_box()`, which is the recommended way in Rust. The problem is, this appears to often force the argument to spill into memory and to be reloaded, which can be a lot of extra instructions. The original inspiration for this function is from, I believe, [OpenTitan's launder* functions](https://github.com/lowRISC/opentitan/blob/master/sw/device/lib/base/hardened.h#L193). There, they use an LLVM-specific trick of a blank inline assembly block to force the compiler to keep the argument in a register. After reviewing our code and speaking with @vsonims, it sounds like the intention of the launder in our code is to prevent the compiler from optimizing the value away (as the comments suggest), so the simpler inline assembly trick may be sufficient (since we use the official Rust compiler, which uses LLVM). The biggest problem is that we launder many types of values in our code and not all of them fit into a register. So, this PR represents an incremental change: for `u32`s and similar small types, we implement `cfi_launder` using the inline assembly trick from OpenTitan. For any other types, we have a trait that can be derived that will call `core::hint::black_box` in the same way as today. We can do future follow-up PRs to try to try to clean up some of those other uses of `cfi_launder` to hopefully shrink the code more. I also slipped in avoid a few extra copies in the verifier by using references instead of copies (this saves ~80 bytes of instruction space). This PR appears to shrink the ROM code size by 1232 bytes and the runtime firmware by 700 bytes. (cherry picked from commit 571d253f7dd79dbddcae3403c83f62edd5174e17) --- Cargo.lock | 4 + FROZEN_IMAGES.sha384sum | 4 +- cfi/derive/src/cfi_asm_test.rs | 78 +++++++++++++++ cfi/derive/src/lib.rs | 15 +++ cfi/lib/src/cfi.rs | 122 +++++++++++++++++++++-- drivers/src/array.rs | 3 +- drivers/src/fuse_bank.rs | 7 +- drivers/src/soc_ifc.rs | 3 +- fmc/src/flow/rt_alias.rs | 3 +- image/types/Cargo.toml | 2 + image/verify/src/verifier.rs | 59 +++++++---- lms-types/Cargo.toml | 2 + lms-types/src/lib.rs | 6 +- rom/dev/src/flow/cold_reset/fmc_alias.rs | 2 +- rom/dev/src/flow/cold_reset/idev_id.rs | 2 +- rom/dev/src/flow/cold_reset/ldev_id.rs | 2 +- 16 files changed, 272 insertions(+), 42 deletions(-) create mode 100644 cfi/derive/src/cfi_asm_test.rs diff --git a/Cargo.lock b/Cargo.lock index e80f952667..8711351e01 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -673,6 +673,8 @@ name = "caliptra-image-types" version = "0.1.0" dependencies = [ "arbitrary", + "caliptra-cfi-derive", + "caliptra-cfi-lib", "caliptra-error", "caliptra-lms-types", "memoffset 0.8.0", @@ -709,6 +711,8 @@ name = "caliptra-lms-types" version = "0.1.0" dependencies = [ "arbitrary", + "caliptra-cfi-derive", + "caliptra-cfi-lib", "zerocopy", "zeroize", ] diff --git a/FROZEN_IMAGES.sha384sum b/FROZEN_IMAGES.sha384sum index 97f1762a43..2c902660bc 100644 --- a/FROZEN_IMAGES.sha384sum +++ b/FROZEN_IMAGES.sha384sum @@ -1,3 +1,3 @@ # WARNING: Do not update this file without the approval of the Caliptra TAC -9537318fd30c3e3d341cffab5721ba3242810be85e79ed9dc644c47c062555ef7519fb48857745e7ccb9917ac1fe120a caliptra-rom-no-log.bin -e4e74d2d1c4794b950a548072fc8dc4c9ab64aba7a01ae400e9fe66c64b43f715e72dc430e7318496009ebedd0412bc6 caliptra-rom-with-log.bin +ad1064cba5b190e4f5258c175b7ec7c697ccb188ba0ed18302c6e924f0ea0b10457dc753d6d2963f415fbaf761eace96 caliptra-rom-no-log.bin +4d93a6856a0cba636a5d2a9c116393f56dc3b34113f7149ae62325772c1eacb08b1d78424771cc71197252abe603eb92 caliptra-rom-with-log.bin diff --git a/cfi/derive/src/cfi_asm_test.rs b/cfi/derive/src/cfi_asm_test.rs new file mode 100644 index 0000000000..062455d83e --- /dev/null +++ b/cfi/derive/src/cfi_asm_test.rs @@ -0,0 +1,78 @@ +// Licensed under the Apache-2.0 license + +// These tests are here so that they are excluded in FPGA tests. + +// These tests don't directly import the CFI code. If they fail, +// this likely indicates that the CFI laundering code may not +// be doing what we want, and we need to investigate. + +#[cfg(test)] +mod test { + + const START: &str = " +#![no_std] + +pub fn add(mut a: u32, mut b: u32) -> u32 { + launder(a) + launder(a) + launder(b) + launder(b) +} +"; + + const LAUNDER: &str = " +#[inline(always)] +fn launder(mut val: u32) -> u32 { + // Safety: this is a no-op, since we don't modify the input. + unsafe { + core::arch::asm!( + \"/* {t} */\", + t = inout(reg) val, + ); + } + val +}"; + + const NO_LAUNDER: &str = " +#[inline(always)] +fn launder(mut val: u32) -> u32 { + val +} +"; + + fn compile_to_riscv32_asm(src: String) -> String { + let dir = std::env::temp_dir(); + let src_path = dir.join("asm.rs"); + let dst_path = dir.join("asm.s"); + + std::fs::write(src_path.clone(), src).expect("could not write asm file"); + + let p = std::process::Command::new("rustc") + .args([ + "--crate-type=lib", + "--target", + "riscv32imc-unknown-none-elf", + "-C", + "opt-level=s", + "--emit", + "asm", + src_path.to_str().expect("could not convert path"), + "-o", + dst_path.to_str().expect("could not convert path"), + ]) + .output() + .expect("failed to compile"); + assert!(p.status.success()); + std::fs::read_to_string(dst_path).expect("could not read asm file") + } + + #[test] + fn test_launder() { + // With no laundering, LLVM can simplify the double add to a shift left. + let src = format!("{}{}", START, NO_LAUNDER); + let asm = compile_to_riscv32_asm(src); + assert!(asm.contains("sll")); + + // With laundering, LLVM cannot simplify the double add and has to use the register twice. + let src = format!("{}{}", START, LAUNDER); + let asm = compile_to_riscv32_asm(src); + assert!(!asm.contains("sll")); + } +} diff --git a/cfi/derive/src/lib.rs b/cfi/derive/src/lib.rs index 3ea4644e6e..2b6b61a559 100644 --- a/cfi/derive/src/lib.rs +++ b/cfi/derive/src/lib.rs @@ -16,11 +16,14 @@ References: --*/ +mod cfi_asm_test; + use proc_macro::TokenStream; use quote::{format_ident, quote, ToTokens}; use syn::__private::TokenStream2; use syn::parse_macro_input; use syn::parse_quote; +use syn::DeriveInput; use syn::FnArg; use syn::ItemFn; @@ -94,3 +97,15 @@ fn cfi_fn(mod_fn: bool, input: TokenStream) -> TokenStream { code.into() } + +#[proc_macro_derive(Launder)] +pub fn derive_launder_trait(input: TokenStream) -> TokenStream { + let input = parse_macro_input!(input as DeriveInput); + let name = input.ident; + let (impl_generics, ty_generics, _) = input.generics.split_for_impl(); + let expanded = quote! { + impl #impl_generics caliptra_cfi_lib::LaunderTrait<#name #ty_generics> for caliptra_cfi_lib::Launder<#name #ty_generics> {} + impl #impl_generics caliptra_cfi_lib::LaunderTrait<&#name #ty_generics> for caliptra_cfi_lib::Launder<&#name #ty_generics> {} + }; + TokenStream::from(expanded) +} diff --git a/cfi/lib/src/cfi.rs b/cfi/lib/src/cfi.rs index e45997992f..4204c2e01c 100644 --- a/cfi/lib/src/cfi.rs +++ b/cfi/lib/src/cfi.rs @@ -20,7 +20,7 @@ use caliptra_error::CaliptraError; use crate::CfiCounter; use core::cfg; use core::cmp::{Eq, Ord, PartialEq, PartialOrd}; -use core::marker::Copy; +use core::marker::{Copy, PhantomData}; /// CFI Panic Information #[derive(Debug, Clone, Copy, Eq, PartialEq)] @@ -94,16 +94,107 @@ impl From for CaliptraError { /// # Returns /// /// `T` - Same value -pub fn cfi_launder(val: T) -> T { +pub fn cfi_launder(val: T) -> T +where + Launder: LaunderTrait, +{ if cfg!(feature = "cfi") { - // Note: The black box seems to be disabling more optimization - // than necessary and results in larger binary size - core::hint::black_box(val) + Launder { _val: PhantomData }.launder(val) } else { val } } +pub trait LaunderTrait { + fn launder(&self, val: T) -> T { + core::hint::black_box(val) + } +} + +pub struct Launder { + _val: PhantomData, +} + +// Inline-assembly laundering trick is adapted from OpenTitan: +// https://github.com/lowRISC/opentitan/blob/master/sw/device/lib/base/hardened.h#L193 +// +// NOTE: This implementation is LLVM-specific, and should be considered to be +// a no-op in every other compiler. For example, GCC has in the past peered +// into the insides of assembly blocks. +// +// At the time of writing, it seems preferable to have something we know is +// correct rather than being overly clever; this is recorded here in case +// the current implementation is unsuitable and we need something more +// carefully tuned. +// +// Unlike in C, we don't have volatile assembly blocks, so this doesn't +// necessarily prevent reordering by LLVM. +// +// When we're building for static analysis, reduce false positives by +// short-circuiting the inline assembly block. +impl LaunderTrait for Launder { + #[allow(asm_sub_register)] + fn launder(&self, val: u32) -> u32 { + let mut val = val; + // Safety: this is a no-op, since we don't modify the input. + unsafe { + // We use inout so that LLVM thinks the value might + // be mutated by the assembly and can't eliminate it. + core::arch::asm!( + "/* {t} */", + t = inout(reg) val, + ); + } + val + } +} + +impl LaunderTrait for Launder { + #[allow(asm_sub_register)] + fn launder(&self, val: bool) -> bool { + let mut val = val as u32; + // Safety: this is a no-op, since we don't modify the input. + unsafe { + core::arch::asm!( + "/* {t} */", + t = inout(reg) val, + ); + } + val != 0 + } +} + +impl LaunderTrait for Launder { + #[allow(asm_sub_register)] + fn launder(&self, mut val: usize) -> usize { + // Safety: this is a no-op, since we don't modify the input. + unsafe { + core::arch::asm!( + "/* {t} */", + t = inout(reg) val, + ); + } + val + } +} + +impl LaunderTrait<[T; N]> for Launder<[T; N]> {} +impl<'a, const N: usize, T> LaunderTrait<&'a [T; N]> for Launder<&'a [T; N]> { + fn launder(&self, val: &'a [T; N]) -> &'a [T; N] { + let mut valp = val.as_ptr() as *const [T; N]; + // Safety: this is a no-op, since we don't modify the input. + unsafe { + core::arch::asm!( + "/* {t} */", + t = inout(reg) valp, + ); + &*valp + } + } +} +impl LaunderTrait> for Launder> {} +impl LaunderTrait for Launder {} + /// Control flow integrity panic /// /// This panic is raised when the control flow integrity error is detected @@ -157,6 +248,7 @@ macro_rules! cfi_assert_macro { pub fn $name(lhs: T, rhs: T) where T: $trait1 + $trait2, + Launder: LaunderTrait, { if cfg!(feature = "cfi") { CfiCounter::delay(); @@ -184,10 +276,28 @@ cfi_assert_macro!(cfi_assert_lt, <, Ord, PartialOrd, AssertLtFail); cfi_assert_macro!(cfi_assert_ge, >=, Ord, PartialOrd, AssertGeFail); cfi_assert_macro!(cfi_assert_le, <=, Ord, PartialOrd, AssertLeFail); +// special case for bool assert +#[inline(always)] +#[allow(unused)] +pub fn cfi_assert_bool(cond: bool) { + if cfg!(feature = "cfi") { + CfiCounter::delay(); + if !cond { + cfi_panic(CfiPanicInfo::AssertEqFail); + } + + // Second check for glitch protection + CfiCounter::delay(); + if !cfi_launder(cond) { + cfi_panic(CfiPanicInfo::AssertEqFail); + } + } +} + #[macro_export] macro_rules! cfi_assert { ($cond: expr) => { - cfi_assert_eq($cond, true) + cfi_assert_bool($cond) }; } diff --git a/drivers/src/array.rs b/drivers/src/array.rs index bbaab1f09c..de8372309b 100644 --- a/drivers/src/array.rs +++ b/drivers/src/array.rs @@ -13,6 +13,7 @@ Abstract: --*/ +use caliptra_cfi_derive::Launder; use core::mem::MaybeUninit; use zerocopy::{AsBytes, FromBytes}; use zeroize::Zeroize; @@ -26,7 +27,7 @@ macro_rules! static_assert { /// The `Array4xN` type represents large arrays in the native format of the Caliptra /// cryptographic hardware, and provides From traits for converting to/from byte arrays. #[repr(transparent)] -#[derive(Debug, Clone, Copy, PartialEq, Eq, Zeroize)] +#[derive(Debug, Clone, Copy, PartialEq, Eq, Launder, Zeroize)] pub struct Array4xN(pub [u32; W]); impl Array4xN { pub const fn new(val: [u32; W]) -> Self { diff --git a/drivers/src/fuse_bank.rs b/drivers/src/fuse_bank.rs index 9b060ed41c..f12455319d 100644 --- a/drivers/src/fuse_bank.rs +++ b/drivers/src/fuse_bank.rs @@ -13,6 +13,7 @@ Abstract: --*/ use crate::Array4x12; +use caliptra_cfi_derive::Launder; use caliptra_registers::soc_ifc::SocIfcReg; use zerocopy::AsBytes; @@ -33,7 +34,7 @@ pub enum X509KeyIdAlgo { } bitflags::bitflags! { - #[derive(Default, Copy, Clone, Debug)] + #[derive(Default, Copy, Clone, Debug, Launder)] pub struct VendorPubKeyRevocation : u32 { const KEY0 = 0b0001; const KEY1 = 0b0010; @@ -87,7 +88,7 @@ impl FuseBank<'_> { /// * None /// /// # Returns - /// key id crypto algorithm + /// key id crypto algorithm /// pub fn idev_id_x509_key_id_algo(&self) -> X509KeyIdAlgo { let soc_ifc_regs = self.soc_ifc.regs(); @@ -112,7 +113,7 @@ impl FuseBank<'_> { /// * None /// /// # Returns - /// manufacturer serial number + /// manufacturer serial number /// pub fn ueid(&self) -> [u8; 17] { let soc_ifc_regs = self.soc_ifc.regs(); diff --git a/drivers/src/soc_ifc.rs b/drivers/src/soc_ifc.rs index ff32420e47..872a1722a4 100644 --- a/drivers/src/soc_ifc.rs +++ b/drivers/src/soc_ifc.rs @@ -12,6 +12,7 @@ Abstract: --*/ +use caliptra_cfi_derive::Launder; use caliptra_error::{CaliptraError, CaliptraResult}; use caliptra_registers::soc_ifc::enums::DeviceLifecycleE; use caliptra_registers::soc_ifc::{self, SocIfcReg}; @@ -382,7 +383,7 @@ impl From for MfgFlags { } /// Reset Reason -#[derive(Debug, Eq, PartialEq, Copy, Clone)] +#[derive(Debug, Eq, PartialEq, Copy, Clone, Launder)] pub enum ResetReason { /// Cold Reset ColdReset, diff --git a/fmc/src/flow/rt_alias.rs b/fmc/src/flow/rt_alias.rs index 404925dde4..1e51ce9e72 100644 --- a/fmc/src/flow/rt_alias.rs +++ b/fmc/src/flow/rt_alias.rs @@ -12,8 +12,7 @@ Abstract: --*/ use caliptra_cfi_derive::cfi_impl_fn; -use caliptra_cfi_lib::cfi_assert_eq; -use caliptra_cfi_lib::{cfi_assert, cfi_launder}; +use caliptra_cfi_lib::{cfi_assert, cfi_assert_bool, cfi_assert_eq, cfi_launder}; use crate::flow::crypto::Crypto; use crate::flow::dice::{DiceInput, DiceOutput}; diff --git a/image/types/Cargo.toml b/image/types/Cargo.toml index d1a27d45cc..c245bb219c 100644 --- a/image/types/Cargo.toml +++ b/image/types/Cargo.toml @@ -10,6 +10,8 @@ doctest = false [dependencies] arbitrary = { workspace = true, optional = true } +caliptra-cfi-derive.workspace = true +caliptra-cfi-lib.workspace = true caliptra-lms-types.workspace = true memoffset.workspace = true zerocopy.workspace = true diff --git a/image/verify/src/verifier.rs b/image/verify/src/verifier.rs index 16b90ec4f3..15bd546054 100644 --- a/image/verify/src/verifier.rs +++ b/image/verify/src/verifier.rs @@ -17,12 +17,14 @@ use core::num::NonZeroU32; use crate::*; #[cfg(all(not(test), not(feature = "no-cfi")))] use caliptra_cfi_derive::cfi_impl_fn; -use caliptra_cfi_lib::{cfi_assert, cfi_assert_eq, cfi_assert_ge, cfi_assert_ne, cfi_launder}; +use caliptra_cfi_lib::{ + cfi_assert, cfi_assert_bool, cfi_assert_eq, cfi_assert_ge, cfi_assert_ne, cfi_launder, +}; use caliptra_drivers::*; use caliptra_image_types::*; use memoffset::offset_of; -const ZERO_DIGEST: ImageDigest = [0u32; SHA384_DIGEST_WORD_SIZE]; +const ZERO_DIGEST: &ImageDigest = &[0u32; SHA384_DIGEST_WORD_SIZE]; /// Header Info struct HeaderInfo<'a> { @@ -294,15 +296,21 @@ impl ImageVerifier { pub_key_info: &ImageVendorPubKeyInfo, ) -> Result<(), NonZeroU32> { // We skip vendor public key check in unprovisioned state - if cfi_launder(self.env.dev_lifecycle()) == Lifecycle::Unprovisioned { - cfi_assert_eq(self.env.dev_lifecycle(), Lifecycle::Unprovisioned); + if cfi_launder(self.env.dev_lifecycle() as u32) == Lifecycle::Unprovisioned as u32 { + cfi_assert_eq( + self.env.dev_lifecycle() as u32, + Lifecycle::Unprovisioned as u32, + ); return Ok(()); } else { - cfi_assert_ne(self.env.dev_lifecycle(), Lifecycle::Unprovisioned); + cfi_assert_ne( + self.env.dev_lifecycle() as u32, + Lifecycle::Unprovisioned as u32, + ); } // Read expected value from the fuses - let expected = self.env.vendor_pub_key_info_digest_fuses(); + let expected = &self.env.vendor_pub_key_info_digest_fuses(); // Vendor public key digest from the fuses must never be zero if cfi_launder(expected) == ZERO_DIGEST { @@ -352,7 +360,7 @@ impl ImageVerifier { ) }; - let actual = self + let actual = &self .env .sha384_digest(range.start, range.len() as u32) .map_err(|err| { @@ -363,7 +371,7 @@ impl ImageVerifier { if cfi_launder(expected) != actual { Err(CaliptraError::IMAGE_VERIFIER_ERR_VENDOR_PUB_KEY_DIGEST_MISMATCH)?; } else { - caliptra_cfi_lib::cfi_assert_eq_12_words(&expected, &actual); + caliptra_cfi_lib::cfi_assert_eq_12_words(expected, actual); } // [TODO] Verify active public key's digest from the descriptor hash list. @@ -387,7 +395,7 @@ impl ImageVerifier { ) }; - let actual = self + let actual = &self .env .sha384_digest(range.start, range.len() as u32) .map_err(|err| { @@ -395,28 +403,28 @@ impl ImageVerifier { CaliptraError::IMAGE_VERIFIER_ERR_OWNER_PUB_KEY_DIGEST_FAILURE })?; - let fuses_digest = self.env.owner_pub_key_digest_fuses(); + let fuses_digest = &self.env.owner_pub_key_digest_fuses(); if fuses_digest == ZERO_DIGEST { - caliptra_cfi_lib::cfi_assert_eq_12_words(&fuses_digest, &ZERO_DIGEST); + caliptra_cfi_lib::cfi_assert_eq_12_words(fuses_digest, ZERO_DIGEST); } else if fuses_digest != actual { return Err(CaliptraError::IMAGE_VERIFIER_ERR_OWNER_PUB_KEY_DIGEST_MISMATCH); } else { - caliptra_cfi_lib::cfi_assert_eq_12_words(&fuses_digest, &actual); + caliptra_cfi_lib::cfi_assert_eq_12_words(fuses_digest, actual); } if cfi_launder(reason) == ResetReason::UpdateReset { - let cold_boot_digest = self.env.owner_pub_key_digest_dv(); + let cold_boot_digest = &self.env.owner_pub_key_digest_dv(); if cfi_launder(cold_boot_digest) != actual { return Err(CaliptraError::IMAGE_VERIFIER_ERR_UPDATE_RESET_OWNER_DIGEST_FAILURE); } else { - caliptra_cfi_lib::cfi_assert_eq_12_words(&cold_boot_digest, &actual); + caliptra_cfi_lib::cfi_assert_eq_12_words(cold_boot_digest, actual); } } else { cfi_assert_ne(reason, ResetReason::UpdateReset); } - Ok((actual, fuses_digest != ZERO_DIGEST)) + Ok((*actual, fuses_digest != ZERO_DIGEST)) } /// Verify Header @@ -480,7 +488,11 @@ impl ImageVerifier { // Verify owner LMS signature let (owner_lms_pub_key, owner_lms_sig) = info.owner_lms_info; - self.verify_owner_lms_sig(&digest_owner, owner_lms_pub_key, owner_lms_sig)?; + self.verify_owner_lms_sig( + &digest_owner, + cfi_launder(owner_lms_pub_key), + cfi_launder(owner_lms_sig), + )?; let verif_info = TocInfo { len: header.toc_len, @@ -499,10 +511,10 @@ impl ImageVerifier { pub_key: &ImageEccPubKey, sig: &ImageEccSignature, ) -> CaliptraResult<()> { - if pub_key.x == ZERO_DIGEST || pub_key.y == ZERO_DIGEST { + if &pub_key.x == ZERO_DIGEST || &pub_key.y == ZERO_DIGEST { Err(CaliptraError::IMAGE_VERIFIER_ERR_OWNER_ECC_PUB_KEY_INVALID_ARG)?; } - if sig.r == ZERO_DIGEST || sig.s == ZERO_DIGEST { + if &sig.r == ZERO_DIGEST || &sig.s == ZERO_DIGEST { Err(CaliptraError::IMAGE_VERIFIER_ERR_OWNER_ECC_SIGNATURE_INVALID_ARG)?; } @@ -539,10 +551,10 @@ impl ImageVerifier { lms_info: (&ImageLmsPublicKey, &ImageLmsSignature), ) -> CaliptraResult<()> { let (ecc_pub_key, ecc_sig) = ecc_info; - if ecc_pub_key.x == ZERO_DIGEST || ecc_pub_key.y == ZERO_DIGEST { + if &ecc_pub_key.x == ZERO_DIGEST || &ecc_pub_key.y == ZERO_DIGEST { Err(CaliptraError::IMAGE_VERIFIER_ERR_VENDOR_PUB_KEY_DIGEST_INVALID_ARG)?; } - if ecc_sig.r == ZERO_DIGEST || ecc_sig.s == ZERO_DIGEST { + if &ecc_sig.r == ZERO_DIGEST || &ecc_sig.s == ZERO_DIGEST { Err(CaliptraError::IMAGE_VERIFIER_ERR_VENDOR_ECC_SIGNATURE_INVALID_ARG)?; } @@ -729,8 +741,11 @@ impl ImageVerifier { #[inline(always)] fn svn_check_required(&mut self) -> bool { // If device is unprovisioned or if rollback is enabled (anti_rollback_disable == true), don't check the SVN. - if cfi_launder(self.env.dev_lifecycle()) == Lifecycle::Unprovisioned { - cfi_assert_eq(self.env.dev_lifecycle(), Lifecycle::Unprovisioned); + if cfi_launder(self.env.dev_lifecycle() as u32) == Lifecycle::Unprovisioned as u32 { + cfi_assert_eq( + self.env.dev_lifecycle() as u32, + Lifecycle::Unprovisioned as u32, + ); false // SVN check not required } else if cfi_launder(self.env.anti_rollback_disable()) { cfi_assert!(self.env.anti_rollback_disable()); diff --git a/lms-types/Cargo.toml b/lms-types/Cargo.toml index f9a05dd372..0d60a7b426 100644 --- a/lms-types/Cargo.toml +++ b/lms-types/Cargo.toml @@ -9,5 +9,7 @@ edition = "2021" [dependencies] arbitrary = { workspace = true, optional = true } +caliptra-cfi-derive.workspace = true +caliptra-cfi-lib.workspace = true zerocopy.workspace = true zeroize.workspace = true diff --git a/lms-types/src/lib.rs b/lms-types/src/lib.rs index 11b3cc66dc..d5d1423a3e 100644 --- a/lms-types/src/lib.rs +++ b/lms-types/src/lib.rs @@ -4,6 +4,7 @@ use core::mem::size_of; +use caliptra_cfi_derive::Launder; use zerocopy::{AsBytes, BigEndian, FromBytes, LittleEndian, U32}; use zeroize::Zeroize; @@ -60,7 +61,7 @@ impl LmotsAlgorithmType { pub const LmotsSha256N24W8: Self = Self::new(8); } -#[derive(Copy, Clone, Debug, PartialEq, Eq)] +#[derive(Copy, Clone, Debug, PartialEq, Eq, Launder)] #[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))] #[repr(C)] pub struct LmsPublicKey { @@ -69,6 +70,7 @@ pub struct LmsPublicKey { pub id: [u8; 16], pub digest: [U32; N], } + impl Default for LmsPublicKey { fn default() -> Self { Self { @@ -133,7 +135,7 @@ unsafe impl FromBytes for LmotsSignature { } #[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))] -#[derive(Copy, Clone, Debug, PartialEq, Eq)] +#[derive(Copy, Clone, Debug, PartialEq, Eq, Launder)] #[repr(C)] pub struct LmsSignature { pub q: U32, diff --git a/rom/dev/src/flow/cold_reset/fmc_alias.rs b/rom/dev/src/flow/cold_reset/fmc_alias.rs index 1f6f3f0cb2..0fc9e7c4af 100644 --- a/rom/dev/src/flow/cold_reset/fmc_alias.rs +++ b/rom/dev/src/flow/cold_reset/fmc_alias.rs @@ -24,7 +24,7 @@ use crate::print::HexBytes; use crate::rom_env::RomEnv; #[cfg(not(feature = "no-cfi"))] use caliptra_cfi_derive::cfi_impl_fn; -use caliptra_cfi_lib::{cfi_assert, cfi_assert_eq, cfi_launder}; +use caliptra_cfi_lib::{cfi_assert, cfi_assert_bool, cfi_launder}; use caliptra_common::dice; use caliptra_common::keyids::{ KEY_ID_FMC_ECDSA_PRIV_KEY, KEY_ID_FMC_MLDSA_KEYPAIR_SEED, KEY_ID_ROM_FMC_CDI, diff --git a/rom/dev/src/flow/cold_reset/idev_id.rs b/rom/dev/src/flow/cold_reset/idev_id.rs index 705dadfc13..1cb0723119 100644 --- a/rom/dev/src/flow/cold_reset/idev_id.rs +++ b/rom/dev/src/flow/cold_reset/idev_id.rs @@ -21,7 +21,7 @@ use crate::print::HexBytes; use crate::rom_env::RomEnv; #[cfg(not(feature = "no-cfi"))] use caliptra_cfi_derive::cfi_impl_fn; -use caliptra_cfi_lib::{cfi_assert, cfi_assert_eq, cfi_launder}; +use caliptra_cfi_lib::{cfi_assert, cfi_assert_bool, cfi_launder}; use caliptra_common::keyids::{ KEY_ID_FE, KEY_ID_IDEVID_ECDSA_PRIV_KEY, KEY_ID_IDEVID_MLDSA_KEYPAIR_SEED, KEY_ID_ROM_FMC_CDI, KEY_ID_UDS, diff --git a/rom/dev/src/flow/cold_reset/ldev_id.rs b/rom/dev/src/flow/cold_reset/ldev_id.rs index 7b96fd86c4..36956cf29d 100644 --- a/rom/dev/src/flow/cold_reset/ldev_id.rs +++ b/rom/dev/src/flow/cold_reset/ldev_id.rs @@ -22,7 +22,7 @@ use crate::print::HexBytes; use crate::rom_env::RomEnv; #[cfg(not(feature = "no-cfi"))] use caliptra_cfi_derive::cfi_impl_fn; -use caliptra_cfi_lib::{cfi_assert, cfi_assert_eq, cfi_launder}; +use caliptra_cfi_lib::{cfi_assert, cfi_assert_bool, cfi_launder}; use caliptra_common::keyids::KEY_ID_LDEVID_MLDSA_KEYPAIR_SEED; use caliptra_common::keyids::{KEY_ID_FE, KEY_ID_LDEVID_ECDSA_PRIV_KEY, KEY_ID_ROM_FMC_CDI}; use caliptra_common::RomBootStatus::*; From 113add5328c8e91a33eacc97f032efd6ad05bd94 Mon Sep 17 00:00:00 2001 From: Carl Lundin Date: Thu, 31 Oct 2024 14:57:46 -0700 Subject: [PATCH 07/51] Refactor common runtime tests so new parameters to run_rt_test do not require updating every test using it. (cherry picked from commit d7a616ff0c391c67db1efc875d06fbe666f83e4b) --- .../tests/runtime_integration_tests/common.rs | 28 ++++----- .../test_authorize_and_stash.rs | 4 +- .../runtime_integration_tests/test_boot.rs | 28 ++++++--- .../test_certify_key_extended.rs | 8 +-- .../runtime_integration_tests/test_certs.rs | 20 ++++--- .../runtime_integration_tests/test_disable.rs | 7 ++- .../runtime_integration_tests/test_ecdsa.rs | 10 ++-- .../runtime_integration_tests/test_fips.rs | 14 ++--- .../runtime_integration_tests/test_info.rs | 6 +- .../test_invoke_dpe.rs | 17 +++--- .../runtime_integration_tests/test_lms.rs | 12 ++-- .../runtime_integration_tests/test_mailbox.rs | 8 +-- .../test_pauser_privilege_levels.rs | 59 +++++++++++++++---- .../runtime_integration_tests/test_pcr.rs | 10 ++-- .../test_populate_idev.rs | 6 +- .../test_set_auth_manifest.rs | 8 +-- .../test_stash_measurement.rs | 10 +++- .../runtime_integration_tests/test_tagging.rs | 16 ++--- .../test_update_reset.rs | 38 +++++++++--- 19 files changed, 193 insertions(+), 116 deletions(-) diff --git a/runtime/tests/runtime_integration_tests/common.rs b/runtime/tests/runtime_integration_tests/common.rs index cda2b7cbc2..d4c4022e71 100644 --- a/runtime/tests/runtime_integration_tests/common.rs +++ b/runtime/tests/runtime_integration_tests/common.rs @@ -40,20 +40,22 @@ pub const TEST_DIGEST: [u8; 48] = [ pub const DEFAULT_FMC_VERSION: u16 = 0xaaaa; pub const DEFAULT_APP_VERSION: u32 = 0xbbbbbbbb; -pub fn run_rt_test_lms( - test_fwid: Option<&'static FwId>, - test_image_options: Option, - init_params: Option, - lms_verify: bool, -) -> DefaultHwModel { +#[derive(Default)] +pub struct RuntimeTestArgs<'a> { + pub test_fwid: Option<&'static FwId<'static>>, + pub test_image_options: Option, + pub init_params: Option>, +} + +pub fn run_rt_test_lms(args: RuntimeTestArgs, lms_verify: bool) -> DefaultHwModel { let default_rt_fwid = if cfg!(feature = "fpga_realtime") { &APP_WITH_UART_FPGA } else { &APP_WITH_UART }; - let runtime_fwid = test_fwid.unwrap_or(default_rt_fwid); + let runtime_fwid = args.test_fwid.unwrap_or(default_rt_fwid); - let image_options = test_image_options.unwrap_or_else(|| { + let image_options = args.test_image_options.unwrap_or_else(|| { let mut opts = ImageOptions::default(); opts.vendor_config.pl0_pauser = Some(0x1); opts.fmc_version = DEFAULT_FMC_VERSION; @@ -62,7 +64,7 @@ pub fn run_rt_test_lms( }); let rom = caliptra_builder::rom_for_fw_integration_tests().unwrap(); - let init_params = match init_params { + let init_params = match args.init_params { Some(init_params) => init_params, None => InitParams { rom: &rom, @@ -93,12 +95,8 @@ pub fn run_rt_test_lms( // Run a test which boots ROM -> FMC -> test_bin. If test_bin_name is None, // run the production runtime image. -pub fn run_rt_test( - test_fwid: Option<&'static FwId>, - test_image_options: Option, - init_params: Option, -) -> DefaultHwModel { - run_rt_test_lms(test_fwid, test_image_options, init_params, false) +pub fn run_rt_test(args: RuntimeTestArgs) -> DefaultHwModel { + run_rt_test_lms(args, false) } pub fn generate_test_x509_cert(ec_key: PKey) -> X509 { diff --git a/runtime/tests/runtime_integration_tests/test_authorize_and_stash.rs b/runtime/tests/runtime_integration_tests/test_authorize_and_stash.rs index 09ba0ff59a..91e5b633d7 100644 --- a/runtime/tests/runtime_integration_tests/test_authorize_and_stash.rs +++ b/runtime/tests/runtime_integration_tests/test_authorize_and_stash.rs @@ -1,6 +1,6 @@ // Licensed under the Apache-2.0 license -use crate::common::run_rt_test; +use crate::common::{run_rt_test, RuntimeTestArgs}; use caliptra_api::SocManager; use caliptra_common::mailbox_api::{ AuthorizeAndStashReq, AuthorizeAndStashResp, CommandId, ImageHashSource, MailboxReq, @@ -13,7 +13,7 @@ use zerocopy::FromBytes; #[test] fn test_authorize_and_stash_cmd_deny_authorization() { - let mut model = run_rt_test(None, None, None); + let mut model = run_rt_test(RuntimeTestArgs::default()); model.step_until(|m| { m.soc_ifc().cptra_boot_status().read() == u32::from(RtBootStatus::RtReadyForCommands) diff --git a/runtime/tests/runtime_integration_tests/test_boot.rs b/runtime/tests/runtime_integration_tests/test_boot.rs index 40a50121b6..55baa7d047 100644 --- a/runtime/tests/runtime_integration_tests/test_boot.rs +++ b/runtime/tests/runtime_integration_tests/test_boot.rs @@ -13,7 +13,7 @@ use caliptra_runtime::RtBootStatus; use sha2::{Digest, Sha384}; use zerocopy::AsBytes; -use crate::common::{run_rt_test, DEFAULT_APP_VERSION, DEFAULT_FMC_VERSION}; +use crate::common::{run_rt_test, RuntimeTestArgs, DEFAULT_APP_VERSION, DEFAULT_FMC_VERSION}; const RT_READY_FOR_COMMANDS: u32 = 0x600; @@ -22,14 +22,18 @@ fn test_standard() { // Test that the normal runtime firmware boots. // Ultimately, this will be useful for exercising Caliptra end-to-end // via the mailbox. - let mut model = run_rt_test(None, None, None); + let mut model = run_rt_test(RuntimeTestArgs::default()); model.step_until_boot_status(RT_READY_FOR_COMMANDS, true); } #[test] fn test_boot() { - let mut model = run_rt_test(Some(&firmware::runtime_tests::BOOT), None, None); + let args = RuntimeTestArgs { + test_fwid: Some(&firmware::runtime_tests::BOOT), + ..Default::default() + }; + let mut model = run_rt_test(args); model.step_until_exit_success().unwrap(); } @@ -38,14 +42,18 @@ fn test_boot() { /// This test differs from the drivers' test_persistent() in that it is ran with the "runtime" flag so /// it allows us to test conditionally compiled runtime-only persistent data that ROM/FMC may have corrupted. fn test_persistent_data() { - let mut model = run_rt_test(Some(&firmware::runtime_tests::PERSISTENT_RT), None, None); + let args = RuntimeTestArgs { + test_fwid: Some(&firmware::runtime_tests::PERSISTENT_RT), + ..Default::default() + }; + let mut model = run_rt_test(args); model.step_until_exit_success().unwrap(); } #[test] fn test_fw_version() { - let mut model = run_rt_test(None, None, None); + let mut model = run_rt_test(RuntimeTestArgs::default()); model.step_until(|m| { m.soc_ifc().cptra_boot_status().read() == u32::from(RtBootStatus::RtReadyForCommands) }); @@ -78,7 +86,7 @@ fn test_update() { // Test that the normal runtime firmware boots. // Ultimately, this will be useful for exercising Caliptra end-to-end // via the mailbox. - let mut model = run_rt_test(None, None, None); + let mut model = run_rt_test(RuntimeTestArgs::default()); model.step_until(|m| m.soc_mbox().status().read().mbox_fsm_ps().mbox_idle()); @@ -117,7 +125,7 @@ fn test_stress_update() { .unwrap(), ]; - let mut model = run_rt_test(None, None, None); + let mut model = run_rt_test(RuntimeTestArgs::default()); let stress_num = if cfg!(feature = "slow_tests") { 500 } else { 1 }; let mut image_select = 0; @@ -146,7 +154,11 @@ fn test_stress_update() { #[test] fn test_boot_tci_data() { - let mut model = run_rt_test(Some(&firmware::runtime_tests::MBOX), None, None); + let args = RuntimeTestArgs { + test_fwid: Some(&firmware::runtime_tests::MBOX), + ..Default::default() + }; + let mut model = run_rt_test(args); let rt_journey_pcr_resp = model.mailbox_execute(0x1000_0000, &[]).unwrap().unwrap(); let rt_journey_pcr: [u8; 48] = rt_journey_pcr_resp.as_bytes().try_into().unwrap(); diff --git a/runtime/tests/runtime_integration_tests/test_certify_key_extended.rs b/runtime/tests/runtime_integration_tests/test_certify_key_extended.rs index 9c6b4df275..400b352486 100644 --- a/runtime/tests/runtime_integration_tests/test_certify_key_extended.rs +++ b/runtime/tests/runtime_integration_tests/test_certify_key_extended.rs @@ -17,11 +17,11 @@ use x509_parser::{ }; use zerocopy::{AsBytes, FromBytes}; -use crate::common::{assert_error, run_rt_test, TEST_LABEL}; +use crate::common::{assert_error, run_rt_test, RuntimeTestArgs, TEST_LABEL}; #[test] fn test_dmtf_other_name_validation_fail() { - let mut model = run_rt_test(None, None, None); + let mut model = run_rt_test(RuntimeTestArgs::default()); model.step_until(|m| { m.soc_ifc().cptra_boot_status().read() == u32::from(RtBootStatus::RtReadyForCommands) @@ -54,7 +54,7 @@ fn test_dmtf_other_name_validation_fail() { #[test] fn test_dmtf_other_name_extension_present() { - let mut model = run_rt_test(None, None, None); + let mut model = run_rt_test(RuntimeTestArgs::default()); model.step_until(|m| { m.soc_ifc().cptra_boot_status().read() == u32::from(RtBootStatus::RtReadyForCommands) @@ -123,7 +123,7 @@ fn test_dmtf_other_name_extension_present() { #[test] fn test_dmtf_other_name_extension_not_present() { - let mut model = run_rt_test(None, None, None); + let mut model = run_rt_test(RuntimeTestArgs::default()); model.step_until(|m| { m.soc_ifc().cptra_boot_status().read() == u32::from(RtBootStatus::RtReadyForCommands) diff --git a/runtime/tests/runtime_integration_tests/test_certs.rs b/runtime/tests/runtime_integration_tests/test_certs.rs index 7bae87af04..c94c761a41 100644 --- a/runtime/tests/runtime_integration_tests/test_certs.rs +++ b/runtime/tests/runtime_integration_tests/test_certs.rs @@ -2,7 +2,7 @@ use crate::common::{ execute_dpe_cmd, generate_test_x509_cert, get_fmc_alias_cert, get_rt_alias_cert, run_rt_test, - DpeResult, TEST_LABEL, + DpeResult, RuntimeTestArgs, TEST_LABEL, }; use caliptra_builder::firmware::{APP_WITH_UART, FMC_WITH_UART}; use caliptra_builder::ImageOptions; @@ -58,7 +58,11 @@ fn test_rt_cert_with_custom_dates() { opts.owner_config = Some(own_config); - let mut model = run_rt_test(None, Some(opts), None); + let args = RuntimeTestArgs { + test_image_options: Some(opts), + ..Default::default() + }; + let mut model = run_rt_test(args); let payload = MailboxReqHeader { chksum: caliptra_common::checksum::calc_checksum( @@ -85,7 +89,7 @@ fn test_rt_cert_with_custom_dates() { #[test] fn test_idev_id_cert() { - let mut model = run_rt_test(None, None, None); + let mut model = run_rt_test(RuntimeTestArgs::default()); // generate 48 byte ECDSA key pair let ec_group = EcGroup::from_curve_name(Nid::SECP384R1).unwrap(); @@ -172,7 +176,7 @@ fn get_ldev_cert(model: &mut DefaultHwModel) -> GetLdevCertResp { #[test] fn test_ldev_cert() { - let mut model = run_rt_test(None, None, None); + let mut model = run_rt_test(RuntimeTestArgs::default()); let ldev_resp = get_ldev_cert(&mut model); let ldev_cert: X509 = X509::from_der(&ldev_resp.data[..ldev_resp.data_size as usize]).unwrap(); @@ -200,7 +204,7 @@ fn test_ldev_cert() { #[test] fn test_fmc_alias_cert() { - let mut model = run_rt_test(None, None, None); + let mut model = run_rt_test(RuntimeTestArgs::default()); let ldev_resp = get_ldev_cert(&mut model); let ldev_cert: X509 = X509::from_der(&ldev_resp.data[..ldev_resp.data_size as usize]).unwrap(); @@ -221,7 +225,7 @@ fn test_fmc_alias_cert() { #[test] fn test_rt_alias_cert() { - let mut model = run_rt_test(None, None, None); + let mut model = run_rt_test(RuntimeTestArgs::default()); let fmc_resp = get_fmc_alias_cert(&mut model); let fmc_cert: X509 = X509::from_der(&fmc_resp.data[..fmc_resp.data_size as usize]).unwrap(); @@ -242,7 +246,7 @@ fn test_rt_alias_cert() { #[test] fn test_dpe_leaf_cert() { - let mut model = run_rt_test(None, None, None); + let mut model = run_rt_test(RuntimeTestArgs::default()); let rt_resp = get_rt_alias_cert(&mut model); let rt_cert: X509 = X509::from_der(&rt_resp.data[..rt_resp.data_size as usize]).unwrap(); @@ -279,7 +283,7 @@ fn test_dpe_leaf_cert() { #[test] fn test_full_cert_chain() { - let mut model = run_rt_test(None, None, None); + let mut model = run_rt_test(RuntimeTestArgs::default()); let ldev_resp = get_ldev_cert(&mut model); let ldev_cert: X509 = X509::from_der(&ldev_resp.data[..ldev_resp.data_size as usize]).unwrap(); diff --git a/runtime/tests/runtime_integration_tests/test_disable.rs b/runtime/tests/runtime_integration_tests/test_disable.rs index e05ae80416..a5eaea0c68 100644 --- a/runtime/tests/runtime_integration_tests/test_disable.rs +++ b/runtime/tests/runtime_integration_tests/test_disable.rs @@ -21,12 +21,13 @@ use openssl::{ use zerocopy::{AsBytes, FromBytes}; use crate::common::{ - execute_dpe_cmd, get_rt_alias_cert, run_rt_test, DpeResult, TEST_DIGEST, TEST_LABEL, + execute_dpe_cmd, get_rt_alias_cert, run_rt_test, DpeResult, RuntimeTestArgs, TEST_DIGEST, + TEST_LABEL, }; #[test] fn test_disable_attestation_cmd() { - let mut model = run_rt_test(None, None, None); + let mut model = run_rt_test(RuntimeTestArgs::default()); // sign the digest let sign_cmd = SignCmd { @@ -92,7 +93,7 @@ fn test_disable_attestation_cmd() { #[test] fn test_attestation_disabled_flag_after_update_reset() { - let mut model = run_rt_test(None, None, None); + let mut model = run_rt_test(RuntimeTestArgs::default()); // disable attestation let payload = MailboxReqHeader { diff --git a/runtime/tests/runtime_integration_tests/test_ecdsa.rs b/runtime/tests/runtime_integration_tests/test_ecdsa.rs index 9164672765..634341fbdb 100644 --- a/runtime/tests/runtime_integration_tests/test_ecdsa.rs +++ b/runtime/tests/runtime_integration_tests/test_ecdsa.rs @@ -1,6 +1,6 @@ // Licensed under the Apache-2.0 license. -use crate::common::{assert_error, run_rt_test}; +use crate::common::{assert_error, run_rt_test, RuntimeTestArgs}; use caliptra_api::SocManager; use caliptra_common::mailbox_api::{ CommandId, EcdsaVerifyReq, MailboxReq, MailboxReqHeader, MailboxRespHeader, @@ -19,7 +19,7 @@ fn ecdsa_cmd_run_wycheproof() { // This test is too slow to run as part of the verilator nightly. #![cfg_attr(all(not(feature = "slow_tests"), feature = "verilator"), ignore)] - let mut model = run_rt_test(None, None, None); + let mut model = run_rt_test(RuntimeTestArgs::default()); model.step_until(|m| { m.soc_ifc().cptra_boot_status().read() @@ -149,7 +149,7 @@ fn ecdsa_cmd_run_wycheproof() { #[test] fn test_ecdsa_verify_cmd() { - let mut model = run_rt_test(None, None, None); + let mut model = run_rt_test(RuntimeTestArgs::default()); model.step_until(|m| { m.soc_ifc().cptra_boot_status().read() == u32::from(RtBootStatus::RtReadyForCommands) @@ -227,7 +227,7 @@ fn test_ecdsa_verify_cmd() { #[test] fn test_ecdsa_verify_bad_chksum() { - let mut model = run_rt_test(None, None, None); + let mut model = run_rt_test(RuntimeTestArgs::default()); let cmd = MailboxReq::EcdsaVerify(EcdsaVerifyReq { hdr: MailboxReqHeader { chksum: 0 }, @@ -254,7 +254,7 @@ fn test_ecdsa_verify_bad_chksum() { #[cfg(any(feature = "verilator", feature = "fpga_realtime"))] #[test] fn test_ecdsa_hw_failure() { - let mut model = run_rt_test(None, None, None); + let mut model = run_rt_test(RuntimeTestArgs::default()); let mut cmd = MailboxReq::EcdsaVerify(EcdsaVerifyReq { hdr: MailboxReqHeader { chksum: 0 }, diff --git a/runtime/tests/runtime_integration_tests/test_fips.rs b/runtime/tests/runtime_integration_tests/test_fips.rs index 77568a7dd9..50c0e8b7fa 100644 --- a/runtime/tests/runtime_integration_tests/test_fips.rs +++ b/runtime/tests/runtime_integration_tests/test_fips.rs @@ -1,6 +1,6 @@ // Licensed under the Apache-2.0 license. -use crate::common::{assert_error, run_rt_test}; +use crate::common::{assert_error, run_rt_test, RuntimeTestArgs}; use caliptra_api::SocManager; use caliptra_builder::{version, ImageOptions}; use caliptra_common::mailbox_api::{ @@ -14,15 +14,15 @@ const HW_REV_ID: u32 = 0x11; // TODO 2.0 #[test] fn test_fips_version() { - let mut model = run_rt_test( - None, - Some(ImageOptions { + let args = RuntimeTestArgs { + test_image_options: Some(ImageOptions { fmc_version: version::get_fmc_version(), app_version: version::get_runtime_version(), ..Default::default() }), - None, - ); + ..Default::default() + }; + let mut model = run_rt_test(args); model.step_until(|m| m.soc_mbox().status().read().mbox_fsm_ps().mbox_idle()); @@ -72,7 +72,7 @@ fn test_fips_version() { #[test] fn test_fips_shutdown() { - let mut model = run_rt_test(None, None, None); + let mut model = run_rt_test(RuntimeTestArgs::default()); model.step_until(|m| m.soc_mbox().status().read().mbox_fsm_ps().mbox_idle()); diff --git a/runtime/tests/runtime_integration_tests/test_info.rs b/runtime/tests/runtime_integration_tests/test_info.rs index 4b13cc6097..461fdee7f2 100644 --- a/runtime/tests/runtime_integration_tests/test_info.rs +++ b/runtime/tests/runtime_integration_tests/test_info.rs @@ -1,6 +1,6 @@ // Licensed under the Apache-2.0 license. -use crate::common::run_rt_test; +use crate::common::{run_rt_test, RuntimeTestArgs}; use caliptra_builder::{ firmware::{APP_WITH_UART, FMC_WITH_UART}, ImageOptions, @@ -159,7 +159,7 @@ fn test_fw_info() { #[test] fn test_idev_id_info() { - let mut model = run_rt_test(None, None, None); + let mut model = run_rt_test(RuntimeTestArgs::default()); let payload = MailboxReqHeader { chksum: caliptra_common::checksum::calc_checksum(u32::from(CommandId::GET_IDEV_INFO), &[]), }; @@ -172,7 +172,7 @@ fn test_idev_id_info() { #[test] fn test_capabilities() { - let mut model = run_rt_test(None, None, None); + let mut model = run_rt_test(RuntimeTestArgs::default()); let payload = MailboxReqHeader { chksum: caliptra_common::checksum::calc_checksum(u32::from(CommandId::CAPABILITIES), &[]), }; diff --git a/runtime/tests/runtime_integration_tests/test_invoke_dpe.rs b/runtime/tests/runtime_integration_tests/test_invoke_dpe.rs index b37d12bff2..c900212ae9 100644 --- a/runtime/tests/runtime_integration_tests/test_invoke_dpe.rs +++ b/runtime/tests/runtime_integration_tests/test_invoke_dpe.rs @@ -1,7 +1,8 @@ // Licensed under the Apache-2.0 license. use crate::common::{ - execute_dpe_cmd, get_rt_alias_cert, run_rt_test, DpeResult, TEST_DIGEST, TEST_LABEL, + execute_dpe_cmd, get_rt_alias_cert, run_rt_test, DpeResult, RuntimeTestArgs, TEST_DIGEST, + TEST_LABEL, }; use caliptra_api::SocManager; use caliptra_common::mailbox_api::{InvokeDpeReq, MailboxReq, MailboxReqHeader}; @@ -33,7 +34,7 @@ use sha2::{Digest, Sha384}; #[test] fn test_invoke_dpe_get_profile_cmd() { - let mut model = run_rt_test(None, None, None); + let mut model = run_rt_test(RuntimeTestArgs::default()); model.step_until(|m| { m.soc_ifc().cptra_boot_status().read() == u32::from(RtBootStatus::RtReadyForCommands) @@ -65,7 +66,7 @@ fn test_invoke_dpe_size_too_big() { #[test] fn test_invoke_dpe_get_certificate_chain_cmd() { - let mut model = run_rt_test(None, None, None); + let mut model = run_rt_test(RuntimeTestArgs::default()); model.step_until(|m| { m.soc_ifc().cptra_boot_status().read() == u32::from(RtBootStatus::RtReadyForCommands) @@ -90,7 +91,7 @@ fn test_invoke_dpe_get_certificate_chain_cmd() { #[test] fn test_invoke_dpe_sign_and_certify_key_cmds() { - let mut model = run_rt_test(None, None, None); + let mut model = run_rt_test(RuntimeTestArgs::default()); let sign_cmd = SignCmd { handle: ContextHandle::default(), @@ -135,7 +136,7 @@ fn test_invoke_dpe_sign_and_certify_key_cmds() { #[test] fn test_invoke_dpe_symmetric_sign() { - let mut model = run_rt_test(None, None, None); + let mut model = run_rt_test(RuntimeTestArgs::default()); model.step_until(|m| { m.soc_ifc().cptra_boot_status().read() == u32::from(RtBootStatus::RtReadyForCommands) @@ -160,7 +161,7 @@ fn test_invoke_dpe_symmetric_sign() { #[test] fn test_dpe_header_error_code() { - let mut model = run_rt_test(None, None, None); + let mut model = run_rt_test(RuntimeTestArgs::default()); model.step_until(|m| { m.soc_ifc().cptra_boot_status().read() == u32::from(RtBootStatus::RtReadyForCommands) @@ -184,7 +185,7 @@ fn test_dpe_header_error_code() { #[test] fn test_invoke_dpe_certify_key_csr() { - let mut model = run_rt_test(None, None, None); + let mut model = run_rt_test(RuntimeTestArgs::default()); model.step_until(|m| { m.soc_ifc().cptra_boot_status().read() == u32::from(RtBootStatus::RtReadyForCommands) @@ -252,7 +253,7 @@ fn test_invoke_dpe_certify_key_csr() { #[test] fn test_invoke_dpe_rotate_context() { - let mut model = run_rt_test(None, None, None); + let mut model = run_rt_test(RuntimeTestArgs::default()); model.step_until(|m| { m.soc_ifc().cptra_boot_status().read() == u32::from(RtBootStatus::RtReadyForCommands) diff --git a/runtime/tests/runtime_integration_tests/test_lms.rs b/runtime/tests/runtime_integration_tests/test_lms.rs index 1bebe27678..038e19776b 100644 --- a/runtime/tests/runtime_integration_tests/test_lms.rs +++ b/runtime/tests/runtime_integration_tests/test_lms.rs @@ -1,6 +1,6 @@ // Licensed under the Apache-2.0 license. -use crate::common::{assert_error, run_rt_test}; +use crate::common::{assert_error, run_rt_test, RuntimeTestArgs}; use caliptra_api::SocManager; use caliptra_common::mailbox_api::{ CommandId, LmsVerifyReq, MailboxReq, MailboxReqHeader, MailboxRespHeader, @@ -813,7 +813,7 @@ fn execute_lms_cmd( #[test] fn test_lms_verify_cmd() { - let mut model = run_rt_test(None, None, None); + let mut model = run_rt_test(RuntimeTestArgs::default()); model.step_until(|m| { m.soc_ifc().cptra_boot_status().read() == u32::from(RtBootStatus::RtReadyForCommands) @@ -838,7 +838,7 @@ fn test_lms_verify_cmd() { #[test] fn test_lms_verify_failure() { - let mut model = run_rt_test(None, None, None); + let mut model = run_rt_test(RuntimeTestArgs::default()); model.step_until(|m| { m.soc_ifc().cptra_boot_status().read() == u32::from(RtBootStatus::RtReadyForCommands) @@ -856,7 +856,7 @@ fn test_lms_verify_failure() { #[test] fn test_lms_verify_invalid_sig_lms_type() { - let mut model = run_rt_test(None, None, None); + let mut model = run_rt_test(RuntimeTestArgs::default()); model.step_until(|m| { m.soc_ifc().cptra_boot_status().read() == u32::from(RtBootStatus::RtReadyForCommands) @@ -879,7 +879,7 @@ fn test_lms_verify_invalid_sig_lms_type() { #[test] fn test_lms_verify_invalid_key_lms_type() { - let mut model = run_rt_test(None, None, None); + let mut model = run_rt_test(RuntimeTestArgs::default()); model.step_until(|m| { m.soc_ifc().cptra_boot_status().read() == u32::from(RtBootStatus::RtReadyForCommands) @@ -901,7 +901,7 @@ fn test_lms_verify_invalid_key_lms_type() { #[test] fn test_lms_verify_invalid_lmots_type() { - let mut model = run_rt_test(None, None, None); + let mut model = run_rt_test(RuntimeTestArgs::default()); model.step_until(|m| { m.soc_ifc().cptra_boot_status().read() == u32::from(RtBootStatus::RtReadyForCommands) diff --git a/runtime/tests/runtime_integration_tests/test_mailbox.rs b/runtime/tests/runtime_integration_tests/test_mailbox.rs index b35f64bc2b..7670e97850 100644 --- a/runtime/tests/runtime_integration_tests/test_mailbox.rs +++ b/runtime/tests/runtime_integration_tests/test_mailbox.rs @@ -5,13 +5,13 @@ use caliptra_common::mailbox_api::{CommandId, MailboxReqHeader}; use caliptra_hw_model::HwModel; use zerocopy::AsBytes; -use crate::common::{assert_error, run_rt_test}; +use crate::common::{assert_error, run_rt_test, RuntimeTestArgs}; /// When a successful command runs after a failed command, ensure the error /// register is cleared. #[test] fn test_error_cleared() { - let mut model = run_rt_test(None, None, None); + let mut model = run_rt_test(RuntimeTestArgs::default()); model.step_until(|m| m.soc_mbox().status().read().mbox_fsm_ps().mbox_idle()); @@ -37,7 +37,7 @@ fn test_error_cleared() { #[test] fn test_unimplemented_cmds() { - let mut model = run_rt_test(None, None, None); + let mut model = run_rt_test(RuntimeTestArgs::default()); model.step_until(|m| m.soc_mbox().status().read().mbox_fsm_ps().mbox_idle()); @@ -61,7 +61,7 @@ fn test_unimplemented_cmds() { // Changing PAUSER not supported on sw emulator #[cfg(any(feature = "verilator", feature = "fpga_realtime"))] fn test_reserved_pauser() { - let mut model = run_rt_test(None, None, None); + let mut model = run_rt_test(RuntimeTestArgs::default()); model.step_until(|m| m.soc_mbox().status().read().mbox_fsm_ps().mbox_idle()); diff --git a/runtime/tests/runtime_integration_tests/test_pauser_privilege_levels.rs b/runtime/tests/runtime_integration_tests/test_pauser_privilege_levels.rs index 15865b98a3..b7293d6d9a 100644 --- a/runtime/tests/runtime_integration_tests/test_pauser_privilege_levels.rs +++ b/runtime/tests/runtime_integration_tests/test_pauser_privilege_levels.rs @@ -31,13 +31,15 @@ use dpe::{ }; use zerocopy::AsBytes; -use crate::common::{assert_error, execute_dpe_cmd, run_rt_test, DpeResult, TEST_LABEL}; +use crate::common::{ + assert_error, execute_dpe_cmd, run_rt_test, DpeResult, RuntimeTestArgs, TEST_LABEL, +}; const DATA: [u8; DPE_PROFILE.get_hash_size()] = [0u8; 48]; #[test] fn test_pl0_derive_context_dpe_context_thresholds() { - let mut model = run_rt_test(None, None, None); + let mut model = run_rt_test(RuntimeTestArgs::default()); model.step_until(|m| { m.soc_ifc().cptra_boot_status().read() == u32::from(RtBootStatus::RtReadyForCommands) @@ -103,7 +105,12 @@ fn test_pl1_derive_context_dpe_context_thresholds() { let mut image_opts = ImageOptions::default(); image_opts.vendor_config.pl0_pauser = None; - let mut model = run_rt_test(None, Some(image_opts), None); + let args = RuntimeTestArgs { + test_image_options: Some(image_opts), + ..Default::default() + }; + + let mut model = run_rt_test(args); model.step_until(|m| { m.soc_ifc().cptra_boot_status().read() == u32::from(RtBootStatus::RtReadyForCommands) @@ -165,7 +172,7 @@ fn test_pl1_derive_context_dpe_context_thresholds() { #[test] fn test_pl0_init_ctx_dpe_context_thresholds() { - let mut model = run_rt_test(None, None, None); + let mut model = run_rt_test(RuntimeTestArgs::default()); model.step_until(|m| { m.soc_ifc().cptra_boot_status().read() == u32::from(RtBootStatus::RtReadyForCommands) @@ -204,7 +211,12 @@ fn test_pl1_init_ctx_dpe_context_thresholds() { let mut image_opts = ImageOptions::default(); image_opts.vendor_config.pl0_pauser = None; - let mut model = run_rt_test(None, Some(image_opts), None); + let args = RuntimeTestArgs { + test_image_options: Some(image_opts), + ..Default::default() + }; + + let mut model = run_rt_test(args); model.step_until(|m| { m.soc_ifc().cptra_boot_status().read() == u32::from(RtBootStatus::RtReadyForCommands) @@ -245,7 +257,11 @@ fn test_populate_idev_cannot_be_called_from_pl1() { let mut image_opts = ImageOptions::default(); image_opts.vendor_config.pl0_pauser = None; - let mut model = run_rt_test(None, Some(image_opts), None); + let args = RuntimeTestArgs { + test_image_options: Some(image_opts), + ..Default::default() + }; + let mut model = run_rt_test(args); model.step_until(|m| { m.soc_ifc().cptra_boot_status().read() == u32::from(RtBootStatus::RtReadyForCommands) @@ -272,7 +288,11 @@ fn test_stash_measurement_cannot_be_called_from_pl1() { let mut image_opts = ImageOptions::default(); image_opts.vendor_config.pl0_pauser = None; - let mut model = run_rt_test(None, Some(image_opts), None); + let args = RuntimeTestArgs { + test_image_options: Some(image_opts), + ..Default::default() + }; + let mut model = run_rt_test(args); model.step_until(|m| { m.soc_ifc().cptra_boot_status().read() == u32::from(RtBootStatus::RtReadyForCommands) @@ -299,7 +319,12 @@ fn test_certify_key_x509_cannot_be_called_from_pl1() { let mut image_opts = ImageOptions::default(); image_opts.vendor_config.pl0_pauser = None; - let mut model = run_rt_test(None, Some(image_opts), None); + let args = RuntimeTestArgs { + test_image_options: Some(image_opts), + ..Default::default() + }; + + let mut model = run_rt_test(args); model.step_until(|m| { m.soc_ifc().cptra_boot_status().read() == u32::from(RtBootStatus::RtReadyForCommands) @@ -324,7 +349,12 @@ fn test_certify_key_extended_cannot_be_called_from_pl1() { let mut image_opts = ImageOptions::default(); image_opts.vendor_config.pl0_pauser = None; - let mut model = run_rt_test(None, Some(image_opts), None); + let args = RuntimeTestArgs { + test_image_options: Some(image_opts), + ..Default::default() + }; + + let mut model = run_rt_test(args); model.step_until(|m| { m.soc_ifc().cptra_boot_status().read() == u32::from(RtBootStatus::RtReadyForCommands) @@ -355,7 +385,12 @@ fn test_derive_context_cannot_be_called_from_pl1_if_changes_locality_to_pl0() { let mut image_opts = ImageOptions::default(); image_opts.vendor_config.pl0_pauser = None; - let mut model = run_rt_test(None, Some(image_opts), None); + let args = RuntimeTestArgs { + test_image_options: Some(image_opts), + ..Default::default() + }; + + let mut model = run_rt_test(args); model.step_until(|m| { m.soc_ifc().cptra_boot_status().read() == u32::from(RtBootStatus::RtReadyForCommands) @@ -391,7 +426,7 @@ fn test_derive_context_cannot_be_called_from_pl1_if_changes_locality_to_pl0() { #[test] fn test_stash_measurement_pl_context_thresholds() { - let mut model = run_rt_test(None, None, None); + let mut model = run_rt_test(RuntimeTestArgs::default()); model.step_until(|m| { m.soc_ifc().cptra_boot_status().read() == u32::from(RtBootStatus::RtReadyForCommands) @@ -436,7 +471,7 @@ fn test_stash_measurement_pl_context_thresholds() { #[test] fn test_measurement_log_pl_context_threshold() { - let mut model = run_rt_test(None, None, None); + let mut model = run_rt_test(RuntimeTestArgs::default()); model.step_until(|m| { m.soc_ifc().cptra_boot_status().read() == u32::from(RtBootStatus::RtReadyForCommands) diff --git a/runtime/tests/runtime_integration_tests/test_pcr.rs b/runtime/tests/runtime_integration_tests/test_pcr.rs index 3d692aa2b1..10a5a8bc1b 100644 --- a/runtime/tests/runtime_integration_tests/test_pcr.rs +++ b/runtime/tests/runtime_integration_tests/test_pcr.rs @@ -1,6 +1,6 @@ // Licensed under the Apache-2.0 license -use crate::common::{get_fmc_alias_cert, run_rt_test}; +use crate::common::{get_fmc_alias_cert, run_rt_test, RuntimeTestArgs}; use caliptra_api::SocManager; use caliptra_common::mailbox_api::{ @@ -20,7 +20,7 @@ use zerocopy::{AsBytes, FromBytes}; #[test] fn test_pcr_quote() { - let mut model = run_rt_test(None, None, None); + let mut model = run_rt_test(RuntimeTestArgs::default()); const RESET_PCR: u32 = 7; @@ -114,7 +114,7 @@ fn test_extend_pcr_cmd_multiple_extensions() { } // 0. Get fresh pcr state and verify - let mut model = run_rt_test(None, None, None); + let mut model = run_rt_test(RuntimeTestArgs::default()); assert_eq!(get_model_pcrs(&mut model)[4], [0u8; 48]); // 1.0 Testing for extension_data [0,...,0] @@ -159,7 +159,7 @@ fn test_extend_pcr_cmd_multiple_extensions() { #[test] fn test_extend_pcr_cmd_invalid_pcr_index() { - let mut model = run_rt_test(None, None, None); + let mut model = run_rt_test(RuntimeTestArgs::default()); let extension_data: [u8; 48] = [0u8; 48]; // 3. Invalid PCR index @@ -175,7 +175,7 @@ fn test_extend_pcr_cmd_invalid_pcr_index() { #[test] fn test_extend_pcr_cmd_reserved_range() { - let mut model = run_rt_test(None, None, None); + let mut model = run_rt_test(RuntimeTestArgs::default()); let extension_data: [u8; 48] = [0u8; 48]; // 4. Ensure reserved PCR range diff --git a/runtime/tests/runtime_integration_tests/test_populate_idev.rs b/runtime/tests/runtime_integration_tests/test_populate_idev.rs index eedf829b71..e6c972cc27 100644 --- a/runtime/tests/runtime_integration_tests/test_populate_idev.rs +++ b/runtime/tests/runtime_integration_tests/test_populate_idev.rs @@ -1,6 +1,8 @@ // Licensed under the Apache-2.0 license -use crate::common::{execute_dpe_cmd, generate_test_x509_cert, run_rt_test, DpeResult}; +use crate::common::{ + execute_dpe_cmd, generate_test_x509_cert, run_rt_test, DpeResult, RuntimeTestArgs, +}; use caliptra_api::SocManager; use caliptra_common::mailbox_api::{CommandId, MailboxReq, MailboxReqHeader, PopulateIdevCertReq}; use caliptra_error::CaliptraError; @@ -68,7 +70,7 @@ fn parse_cert_chain(cert_chain: &[u8], cert_chain_size: usize, expected_num_cert #[test] fn test_populate_idev_cert_cmd() { - let mut model = run_rt_test(None, None, None); + let mut model = run_rt_test(RuntimeTestArgs::default()); model.step_until(|m| { m.soc_ifc().cptra_boot_status().read() == u32::from(RtBootStatus::RtReadyForCommands) diff --git a/runtime/tests/runtime_integration_tests/test_set_auth_manifest.rs b/runtime/tests/runtime_integration_tests/test_set_auth_manifest.rs index 22d7392124..dc3dd5ee04 100644 --- a/runtime/tests/runtime_integration_tests/test_set_auth_manifest.rs +++ b/runtime/tests/runtime_integration_tests/test_set_auth_manifest.rs @@ -1,6 +1,6 @@ // Licensed under the Apache-2.0 license -use crate::common::{assert_error, run_rt_test_lms}; +use crate::common::{assert_error, run_rt_test_lms, RuntimeTestArgs}; use caliptra_api::SocManager; use caliptra_auth_man_gen::{ AuthManifestGenerator, AuthManifestGeneratorConfig, AuthManifestGeneratorKeyConfig, @@ -106,7 +106,7 @@ fn test_auth_manifest() -> AuthorizationManifest { #[test] fn test_set_auth_manifest_cmd() { - let mut model = run_rt_test_lms(None, None, None, true); + let mut model = run_rt_test_lms(RuntimeTestArgs::default(), true); model.step_until(|m| { m.soc_ifc().cptra_boot_status().read() == u32::from(RtBootStatus::RtReadyForCommands) @@ -135,7 +135,7 @@ fn test_set_auth_manifest_cmd() { #[test] fn test_set_auth_manifest_cmd_invalid_len() { - let mut model = run_rt_test_lms(None, None, None, true); + let mut model = run_rt_test_lms(RuntimeTestArgs::default(), true); model.step_until(|m| { m.soc_ifc().cptra_boot_status().read() == u32::from(RtBootStatus::RtReadyForCommands) @@ -183,7 +183,7 @@ fn test_set_auth_manifest_cmd_invalid_len() { } fn test_manifest_expect_err(manifest: AuthorizationManifest, expected_err: CaliptraError) { - let mut model = run_rt_test_lms(None, None, None, true); + let mut model = run_rt_test_lms(RuntimeTestArgs::default(), true); model.step_until(|m| { m.soc_ifc().cptra_boot_status().read() == u32::from(RtBootStatus::RtReadyForCommands) diff --git a/runtime/tests/runtime_integration_tests/test_stash_measurement.rs b/runtime/tests/runtime_integration_tests/test_stash_measurement.rs index 36940f4d63..8c3625edcd 100644 --- a/runtime/tests/runtime_integration_tests/test_stash_measurement.rs +++ b/runtime/tests/runtime_integration_tests/test_stash_measurement.rs @@ -13,11 +13,11 @@ use caliptra_runtime::RtBootStatus; use sha2::{Digest, Sha384}; use zerocopy::{AsBytes, LayoutVerified}; -use crate::common::run_rt_test; +use crate::common::{run_rt_test, RuntimeTestArgs}; #[test] fn test_stash_measurement() { - let mut model = run_rt_test(None, None, None); + let mut model = run_rt_test(RuntimeTestArgs::default()); model.step_until(|m| { m.soc_ifc().cptra_boot_status().read() == u32::from(RtBootStatus::RtReadyForCommands) @@ -82,7 +82,11 @@ fn test_stash_measurement() { #[test] fn test_pcr31_extended_upon_stash_measurement() { - let mut model = run_rt_test(Some(&firmware::runtime_tests::MBOX), None, None); + let args = RuntimeTestArgs { + test_fwid: Some(&firmware::runtime_tests::MBOX), + ..Default::default() + }; + let mut model = run_rt_test(args); // Read PCR_ID_STASH_MEASUREMENT let pcr_31_resp = model.mailbox_execute(0x5000_0000, &[]).unwrap().unwrap(); diff --git a/runtime/tests/runtime_integration_tests/test_tagging.rs b/runtime/tests/runtime_integration_tests/test_tagging.rs index 3e0a12fb5f..bde33746cb 100644 --- a/runtime/tests/runtime_integration_tests/test_tagging.rs +++ b/runtime/tests/runtime_integration_tests/test_tagging.rs @@ -1,6 +1,6 @@ // Licensed under the Apache-2.0 license -use crate::common::{assert_error, execute_dpe_cmd, run_rt_test, DpeResult}; +use crate::common::{assert_error, execute_dpe_cmd, run_rt_test, DpeResult, RuntimeTestArgs}; use caliptra_common::mailbox_api::{ CommandId, GetTaggedTciReq, GetTaggedTciResp, MailboxReq, MailboxReqHeader, TagTciReq, }; @@ -20,7 +20,7 @@ const BAD_HANDLE: [u8; 16] = [1u8; 16]; #[test] fn test_tagging_default_context() { - let mut model = run_rt_test(None, None, None); + let mut model = run_rt_test(RuntimeTestArgs::default()); // Tag default context let mut cmd = MailboxReq::TagTci(TagTciReq { @@ -52,7 +52,7 @@ fn test_tagging_default_context() { #[test] fn test_tagging_a_tagged_context() { - let mut model = run_rt_test(None, None, None); + let mut model = run_rt_test(RuntimeTestArgs::default()); // Tag default context let mut cmd = MailboxReq::TagTci(TagTciReq { @@ -85,7 +85,7 @@ fn test_tagging_a_tagged_context() { #[test] fn test_duplicate_tag() { - let mut model = run_rt_test(None, None, None); + let mut model = run_rt_test(RuntimeTestArgs::default()); // Tag default context let mut cmd = MailboxReq::TagTci(TagTciReq { @@ -118,7 +118,7 @@ fn test_duplicate_tag() { #[test] fn test_get_tagged_tci_on_non_existent_tag() { - let mut model = run_rt_test(None, None, None); + let mut model = run_rt_test(RuntimeTestArgs::default()); // Check that DPE_GET_TAGGED_TCI fails if the tag does not exist let mut cmd = MailboxReq::GetTaggedTci(GetTaggedTciReq { @@ -141,7 +141,7 @@ fn test_get_tagged_tci_on_non_existent_tag() { #[test] fn test_tagging_inactive_context() { - let mut model = run_rt_test(None, None, None); + let mut model = run_rt_test(RuntimeTestArgs::default()); // check that we cannot tag an inactive context let mut cmd = MailboxReq::TagTci(TagTciReq { @@ -162,7 +162,7 @@ fn test_tagging_inactive_context() { #[test] fn test_tagging_destroyed_context() { - let mut model = run_rt_test(None, None, None); + let mut model = run_rt_test(RuntimeTestArgs::default()); // Tag default context let mut cmd = MailboxReq::TagTci(TagTciReq { @@ -210,7 +210,7 @@ fn test_tagging_destroyed_context() { #[test] fn test_tagging_retired_context() { - let mut model = run_rt_test(None, None, None); + let mut model = run_rt_test(RuntimeTestArgs::default()); // retire context via DeriveContext let derive_context_cmd = DeriveContextCmd { diff --git a/runtime/tests/runtime_integration_tests/test_update_reset.rs b/runtime/tests/runtime_integration_tests/test_update_reset.rs index 4745481e53..3049a24075 100644 --- a/runtime/tests/runtime_integration_tests/test_update_reset.rs +++ b/runtime/tests/runtime_integration_tests/test_update_reset.rs @@ -23,7 +23,7 @@ use dpe::{ }; use zerocopy::{AsBytes, FromBytes}; -use crate::common::run_rt_test; +use crate::common::{run_rt_test, RuntimeTestArgs}; fn update_fw(model: &mut DefaultHwModel, rt_fw: &FwId<'static>, image_opts: ImageOptions) { let image = caliptra_builder::build_and_sign_image(&FMC_WITH_UART, rt_fw, image_opts) @@ -37,7 +37,7 @@ fn update_fw(model: &mut DefaultHwModel, rt_fw: &FwId<'static>, image_opts: Imag #[test] fn test_rt_journey_pcr_updated_in_dpe() { - let mut model = run_rt_test(None, None, None); + let mut model = run_rt_test(RuntimeTestArgs::default()); model.step_until(|m| { m.soc_ifc().cptra_boot_status().read() == u32::from(RtBootStatus::RtReadyForCommands) @@ -57,7 +57,7 @@ fn test_rt_journey_pcr_updated_in_dpe() { #[test] fn test_tags_persistence() { - let mut model = run_rt_test(None, None, None); + let mut model = run_rt_test(RuntimeTestArgs::default()); model.step_until(|m| { m.soc_ifc().cptra_boot_status().read() == u32::from(RtBootStatus::RtReadyForCommands) @@ -97,7 +97,11 @@ fn test_tags_persistence() { #[test] fn test_context_tags_validation() { - let mut model = run_rt_test(Some(&MBOX), None, None); + let args = RuntimeTestArgs { + test_fwid: Some(&MBOX), + ..Default::default() + }; + let mut model = run_rt_test(args); // make context_tags validation fail by "tagging" an inactive context let mut context_tags = [0u32; MAX_HANDLES]; @@ -119,7 +123,11 @@ fn test_context_tags_validation() { #[test] fn test_context_has_tag_validation() { - let mut model = run_rt_test(Some(&MBOX), None, None); + let args = RuntimeTestArgs { + test_fwid: Some(&MBOX), + ..Default::default() + }; + let mut model = run_rt_test(args); // make context_has_tag validation fail by "tagging" an inactive context let mut context_has_tag = [U8Bool::new(false); MAX_HANDLES]; @@ -141,7 +149,11 @@ fn test_context_has_tag_validation() { #[test] fn test_dpe_validation_deformed_structure() { - let mut model = run_rt_test(Some(&MBOX), None, None); + let args = RuntimeTestArgs { + test_fwid: Some(&MBOX), + ..Default::default() + }; + let mut model = run_rt_test(args); // read DPE after RT initialization let dpe_resp = model.mailbox_execute(0xA000_0000, &[]).unwrap().unwrap(); @@ -187,7 +199,11 @@ fn test_dpe_validation_deformed_structure() { #[test] fn test_dpe_validation_illegal_state() { - let mut model = run_rt_test(Some(&MBOX), None, None); + let args = RuntimeTestArgs { + test_fwid: Some(&MBOX), + ..Default::default() + }; + let mut model = run_rt_test(args); // read DPE after RT initialization let dpe_resp = model.mailbox_execute(0xA000_0000, &[]).unwrap().unwrap(); @@ -231,7 +247,11 @@ fn test_dpe_validation_illegal_state() { #[test] fn test_dpe_validation_used_context_threshold_exceeded() { - let mut model = run_rt_test(Some(&MBOX), None, None); + let args = RuntimeTestArgs { + test_fwid: Some(&MBOX), + ..Default::default() + }; + let mut model = run_rt_test(args); // read DPE after RT initialization let dpe_resp = model.mailbox_execute(0xA000_0000, &[]).unwrap().unwrap(); @@ -281,7 +301,7 @@ fn test_dpe_validation_used_context_threshold_exceeded() { #[test] fn test_pcr_reset_counter_persistence() { - let mut model = run_rt_test(None, None, None); + let mut model = run_rt_test(RuntimeTestArgs::default()); model.step_until(|m| { m.soc_ifc().cptra_boot_status().read() == u32::from(RtBootStatus::RtReadyForCommands) From c156b112e719c52908209d4d4758b9ae2eda2859 Mon Sep 17 00:00:00 2001 From: Carl Lundin Date: Mon, 28 Oct 2024 14:36:06 -0700 Subject: [PATCH 08/51] Tweak UART messages to buy some RO memory in ROM. (cherry picked from commit 4156eda712fc2c85469a2fd08cdc1ac8c7084f49) --- FROZEN_IMAGES.sha384sum | 2 +- rom/dev/src/fht.rs | 5 +---- rom/dev/src/flow/cold_reset/fmc_alias.rs | 4 ++-- rom/dev/src/flow/cold_reset/fw_processor.rs | 18 ++++++++---------- rom/dev/src/flow/cold_reset/idev_id.rs | 4 ++-- rom/dev/src/flow/cold_reset/ldev_id.rs | 2 +- rom/dev/src/flow/cold_reset/x509.rs | 8 ++++---- rom/dev/src/flow/mod.rs | 2 +- rom/dev/src/flow/update_reset.rs | 8 ++++---- rom/dev/src/flow/warm_reset.rs | 4 ++-- rom/dev/src/main.rs | 2 +- rom/dev/src/wdt.rs | 6 ++---- 12 files changed, 29 insertions(+), 36 deletions(-) diff --git a/FROZEN_IMAGES.sha384sum b/FROZEN_IMAGES.sha384sum index 2c902660bc..97e4b9ff3c 100644 --- a/FROZEN_IMAGES.sha384sum +++ b/FROZEN_IMAGES.sha384sum @@ -1,3 +1,3 @@ # WARNING: Do not update this file without the approval of the Caliptra TAC ad1064cba5b190e4f5258c175b7ec7c697ccb188ba0ed18302c6e924f0ea0b10457dc753d6d2963f415fbaf761eace96 caliptra-rom-no-log.bin -4d93a6856a0cba636a5d2a9c116393f56dc3b34113f7149ae62325772c1eacb08b1d78424771cc71197252abe603eb92 caliptra-rom-with-log.bin +2aae08cbe6e13559201fee432a7bbf535d27d94df4e8b4d05adab11c4f27b57c6d8392b71a24ee459af7b9663ce9c31f caliptra-rom-with-log.bin diff --git a/rom/dev/src/fht.rs b/rom/dev/src/fht.rs index aa9cfa5378..6ee377e3d1 100644 --- a/rom/dev/src/fht.rs +++ b/rom/dev/src/fht.rs @@ -152,10 +152,7 @@ impl FhtDataStore { pub fn initialize_fht(env: &mut RomEnv) { let pdata = &env.persistent_data.get(); - cprintln!( - "[fht] Storing FHT @ 0x{:08X}", - &pdata.fht as *const _ as usize - ); + cprintln!("[fht] FHT @ 0x{:08X}", &pdata.fht as *const _ as usize); env.persistent_data.get_mut().fht = FirmwareHandoffTable { fht_marker: FHT_MARKER, diff --git a/rom/dev/src/flow/cold_reset/fmc_alias.rs b/rom/dev/src/flow/cold_reset/fmc_alias.rs index 0fc9e7c4af..94f1ba18ca 100644 --- a/rom/dev/src/flow/cold_reset/fmc_alias.rs +++ b/rom/dev/src/flow/cold_reset/fmc_alias.rs @@ -207,14 +207,14 @@ impl FmcAliasLayer { // Sign the `To Be Signed` portion cprintln!( - "[afmc] Signing Cert with AUTHORITY.KEYID = {}", + "[afmc] Signing Cert w/ AUTHORITY.KEYID = {}", auth_priv_key as u8 ); let mut sig = Crypto::ecdsa384_sign_and_verify(env, auth_priv_key, auth_pub_key, tbs.tbs()); let sig = okmutref(&mut sig)?; // Clear the authority private key - cprintln!("[afmc] Erasing AUTHORITY.KEYID = {}", auth_priv_key as u8); + cprintln!("[afmc] Erase AUTHORITY.KEYID = {}", auth_priv_key as u8); env.key_vault.erase_key(auth_priv_key).map_err(|err| { sig.zeroize(); err diff --git a/rom/dev/src/flow/cold_reset/fw_processor.rs b/rom/dev/src/flow/cold_reset/fw_processor.rs index a69c3859dc..482d350f88 100644 --- a/rom/dev/src/flow/cold_reset/fw_processor.rs +++ b/rom/dev/src/flow/cold_reset/fw_processor.rs @@ -182,7 +182,7 @@ impl FirmwareProcessor { ) -> CaliptraResult>> { let mut self_test_in_progress = false; - cprintln!("[fwproc] Waiting for Commands..."); + cprintln!("[fwproc] Wait for Commands..."); loop { // Random delay for CFI glitch protection. CfiCounter::delay(); @@ -195,7 +195,7 @@ impl FirmwareProcessor { return Err(CaliptraError::FW_PROC_MAILBOX_RESERVED_PAUSER); } - cprintln!("[fwproc] Received command 0x{:08x}", txn.cmd()); + cprintln!("[fwproc] Recv command 0x{:08x}", txn.cmd()); // Handle FW load as a separate case due to the re-borrow explained below if txn.cmd() == CommandId::FIRMWARE_LOAD.into() { @@ -209,11 +209,11 @@ impl FirmwareProcessor { // failure) or by a manual complete call upon success. let txn = ManuallyDrop::new(txn.start_txn()); if txn.dlen() == 0 || txn.dlen() > IMAGE_BYTE_SIZE as u32 { - cprintln!("Invalid Image of size {} bytes" txn.dlen()); + cprintln!("Invalid Img size: {} bytes" txn.dlen()); return Err(CaliptraError::FW_PROC_INVALID_IMAGE_SIZE); } - cprintln!("[fwproc] Received Image of size {} bytes" txn.dlen()); + cprintln!("[fwproc] Recv'd Img size: {} bytes" txn.dlen()); report_boot_status(FwProcessorDownloadImageComplete.into()); return Ok(txn); } @@ -287,9 +287,7 @@ impl FirmwareProcessor { } CommandId::STASH_MEASUREMENT => { if persistent_data.fht.meas_log_index == MEASUREMENT_MAX_COUNT as u32 { - cprintln!( - "[fwproc] Maximum supported number of measurements already received." - ); + cprintln!("[fwproc] Max # of measurements received."); txn.complete(false)?; // Raise a fatal error on hitting the max. limit. @@ -367,7 +365,7 @@ impl FirmwareProcessor { let info = verifier.verify(manifest, img_bundle_sz, ResetReason::ColdReset)?; cprintln!( - "[fwproc] Image verified using Vendor ECC Key Index {}", + "[fwproc] Img verified w/ Vendor ECC Key Idx {}", info.vendor_ecc_pub_key_idx, ); report_boot_status(FwProcessorImageVerificationComplete.into()); @@ -474,7 +472,7 @@ impl FirmwareProcessor { #[cfg_attr(not(feature = "no-cfi"), cfi_impl_fn)] fn load_image(manifest: &ImageManifest, txn: &mut MailboxRecvTxn) -> CaliptraResult<()> { cprintln!( - "[fwproc] Loading FMC at address 0x{:08x} len {}", + "[fwproc] Load FMC at address 0x{:08x} len {}", manifest.fmc.load_addr, manifest.fmc.size ); @@ -487,7 +485,7 @@ impl FirmwareProcessor { txn.copy_request(fmc_dest.as_bytes_mut())?; cprintln!( - "[fwproc] Loading Runtime at address 0x{:08x} len {}", + "[fwproc] Load Runtime at address 0x{:08x} len {}", manifest.runtime.load_addr, manifest.runtime.size ); diff --git a/rom/dev/src/flow/cold_reset/idev_id.rs b/rom/dev/src/flow/cold_reset/idev_id.rs index 1cb0723119..e22cbb661b 100644 --- a/rom/dev/src/flow/cold_reset/idev_id.rs +++ b/rom/dev/src/flow/cold_reset/idev_id.rs @@ -243,7 +243,7 @@ impl InitDevIdLayer { return Ok(()); } - cprintln!("[idev] CSR upload requested"); + cprintln!("[idev] CSR upload begun"); // Generate the CSR Self::make_csr(env, output) @@ -274,7 +274,7 @@ impl InitDevIdLayer { let tbs = InitDevIdCsrTbs::new(¶ms); cprintln!( - "[idev] Signing CSR with SUBJECT.KEYID = {}", + "[idev] Sign CSR w/ SUBJECT.KEYID = {}", key_pair.priv_key as u8 ); diff --git a/rom/dev/src/flow/cold_reset/ldev_id.rs b/rom/dev/src/flow/cold_reset/ldev_id.rs index 36956cf29d..f294185be1 100644 --- a/rom/dev/src/flow/cold_reset/ldev_id.rs +++ b/rom/dev/src/flow/cold_reset/ldev_id.rs @@ -183,7 +183,7 @@ impl LocalDevIdLayer { // Sign the `To Be Signed` portion cprintln!( - "[ldev] Signing Cert with AUTHORITY.KEYID = {}", + "[ldev] Signing Cert w/ AUTHORITY.KEYID = {}", auth_priv_key as u8 ); let mut sig = Crypto::ecdsa384_sign_and_verify(env, auth_priv_key, auth_pub_key, tbs.tbs()); diff --git a/rom/dev/src/flow/cold_reset/x509.rs b/rom/dev/src/flow/cold_reset/x509.rs index 261c1829b8..aa5b4ecac6 100644 --- a/rom/dev/src/flow/cold_reset/x509.rs +++ b/rom/dev/src/flow/cold_reset/x509.rs @@ -89,24 +89,24 @@ impl X509 { let digest: [u8; 20] = match env.soc_ifc.fuse_bank().idev_id_x509_key_id_algo() { X509KeyIdAlgo::Sha1 => { - cprintln!("[idev] Using Sha1 for KeyId Algorithm"); + cprintln!("[idev] Sha1 KeyId Algorithm"); let digest = Crypto::sha1_digest(env, &data); okref(&digest)?.into() } X509KeyIdAlgo::Sha256 => { - cprintln!("[idev] Using Sha256 for KeyId Algorithm"); + cprintln!("[idev] Sha256 KeyId Algorithm"); let digest = Crypto::sha256_digest(env, &data); let digest: [u8; 32] = okref(&digest)?.into(); digest[..20].try_into().unwrap() } X509KeyIdAlgo::Sha384 => { - cprintln!("[idev] Using Sha384 for KeyId Algorithm"); + cprintln!("[idev] Sha384 KeyId Algorithm"); let digest = Crypto::sha384_digest(env, &data); let digest: [u8; 48] = okref(&digest)?.into(); digest[..20].try_into().unwrap() } X509KeyIdAlgo::Fuse => { - cprintln!("[idev] Using Fuse for KeyId"); + cprintln!("[idev] Fuse KeyId"); env.soc_ifc.fuse_bank().subject_key_id() } }; diff --git a/rom/dev/src/flow/mod.rs b/rom/dev/src/flow/mod.rs index f0e2772551..cdce5a522c 100644 --- a/rom/dev/src/flow/mod.rs +++ b/rom/dev/src/flow/mod.rs @@ -67,7 +67,7 @@ pub fn run(env: &mut RomEnv) -> CaliptraResult<()> { if (env.soc_ifc.lifecycle() == caliptra_drivers::Lifecycle::Production) && !(env.soc_ifc.prod_en_in_fake_mode()) { - cprintln!("Fake ROM in Production lifecycle not enabled"); + cprintln!("Fake ROM in Prod disabled"); handle_fatal_error(CaliptraError::ROM_GLOBAL_FAKE_ROM_IN_PRODUCTION.into()); } diff --git a/rom/dev/src/flow/update_reset.rs b/rom/dev/src/flow/update_reset.rs index a952f177f2..5ae975878e 100644 --- a/rom/dev/src/flow/update_reset.rs +++ b/rom/dev/src/flow/update_reset.rs @@ -52,13 +52,13 @@ impl UpdateResetFlow { ); let Some(mut recv_txn) = env.mbox.try_start_recv_txn() else { - cprintln!("Failed To Get Mailbox Transaction"); + cprintln!("Failed To Get Mailbox Txn"); return Err(CaliptraError::ROM_UPDATE_RESET_FLOW_MAILBOX_ACCESS_FAILURE); }; let mut process_txn = || -> CaliptraResult<()> { if recv_txn.cmd() != CommandId::FIRMWARE_LOAD.into() { - cprintln!("Invalid command 0x{:08x} received", recv_txn.cmd()); + cprintln!("Invalid command 0x{:08x} recv", recv_txn.cmd()); return Err(CaliptraError::ROM_UPDATE_RESET_FLOW_INVALID_FIRMWARE_COMMAND); } @@ -87,7 +87,7 @@ impl UpdateResetFlow { report_boot_status(UpdateResetExtendPcrComplete.into()); cprintln!( - "[update-reset] Image verified using Vendor ECC Key Index {}", + "[update-reset] Img verified w/ Vendor ECC Key Index {}", info.vendor_ecc_pub_key_idx ); @@ -167,7 +167,7 @@ impl UpdateResetFlow { #[cfg_attr(not(feature = "no-cfi"), cfi_impl_fn)] fn load_image(manifest: &ImageManifest, txn: &mut MailboxRecvTxn) -> CaliptraResult<()> { cprintln!( - "[update-reset] Loading Runtime at address 0x{:08x} len {}", + "[update-reset] Loading Runtime at addr 0x{:08x} len {}", manifest.runtime.load_addr, manifest.runtime.size ); diff --git a/rom/dev/src/flow/warm_reset.rs b/rom/dev/src/flow/warm_reset.rs index 67683eda40..07e5ae799a 100644 --- a/rom/dev/src/flow/warm_reset.rs +++ b/rom/dev/src/flow/warm_reset.rs @@ -34,7 +34,7 @@ impl WarmResetFlow { // Check if previous Cold-Reset was successful. if cfi_launder(env.data_vault.rom_cold_boot_status()) != ColdResetComplete.into() { - cprintln!("[warm-reset] Previous Cold-Reset was not successful."); + cprintln!("[warm-reset] Prev Cold-Reset failed"); return Err(CaliptraError::ROM_WARM_RESET_UNSUCCESSFUL_PREVIOUS_COLD_RESET); } else { cfi_assert_eq( @@ -45,7 +45,7 @@ impl WarmResetFlow { // Check if previous Update-Reset, if any, was successful. if cfi_launder(env.data_vault.rom_update_reset_status()) == UpdateResetStarted.into() { - cprintln!("[warm-reset] Previous Update Reset was not successful."); + cprintln!("[warm-reset] Prev Update Reset failed"); return Err(CaliptraError::ROM_WARM_RESET_UNSUCCESSFUL_PREVIOUS_UPDATE_RESET); } else { cfi_assert_ne( diff --git a/rom/dev/src/main.rs b/rom/dev/src/main.rs index ffb8c193d5..4a96563644 100644 --- a/rom/dev/src/main.rs +++ b/rom/dev/src/main.rs @@ -99,7 +99,7 @@ pub extern "C" fn rom_entry() -> ! { && (env.soc_ifc.lifecycle() == caliptra_drivers::Lifecycle::Production) && !(env.soc_ifc.prod_en_in_fake_mode()) { - cprintln!("Fake ROM in Production lifecycle not enabled"); + cprintln!("Fake ROM in Prod lifecycle disabled"); handle_fatal_error(CaliptraError::ROM_GLOBAL_FAKE_ROM_IN_PRODUCTION.into()); } diff --git a/rom/dev/src/wdt.rs b/rom/dev/src/wdt.rs index 61c5e0820f..50e765872a 100644 --- a/rom/dev/src/wdt.rs +++ b/rom/dev/src/wdt.rs @@ -37,7 +37,7 @@ pub fn start_wdt(soc_ifc: &mut SocIfc) { wdt_timeout_cycles = 1; } cprintln!( - "[state] Starting the Watchdog Timer {} cycles", + "[state] Starting the WD Timer {} cycles", wdt_timeout_cycles ); caliptra_common::wdt::start_wdt( @@ -45,8 +45,6 @@ pub fn start_wdt(soc_ifc: &mut SocIfc) { WdtTimeout::from(core::num::NonZeroU64::new(wdt_timeout_cycles).unwrap()), ); } else { - cprintln!( - "[state] Watchdog Timer is not started because the device is not locked for debugging" - ); + cprintln!("[state] WD Timer not started. Device not locked for debugging"); } } From 0ef4b220223e4a58c88451b53f2b8216268f4f57 Mon Sep 17 00:00:00 2001 From: Carl Lundin Date: Wed, 6 Nov 2024 14:37:01 -0800 Subject: [PATCH 09/51] Remove WD print statement. (cherry picked from commit 20162e302327c08dfd371e557e4c1255c38ec374) --- FROZEN_IMAGES.sha384sum | 4 ++-- rom/dev/src/wdt.rs | 8 -------- 2 files changed, 2 insertions(+), 10 deletions(-) diff --git a/FROZEN_IMAGES.sha384sum b/FROZEN_IMAGES.sha384sum index 97e4b9ff3c..cf802c0b9c 100644 --- a/FROZEN_IMAGES.sha384sum +++ b/FROZEN_IMAGES.sha384sum @@ -1,3 +1,3 @@ # WARNING: Do not update this file without the approval of the Caliptra TAC -ad1064cba5b190e4f5258c175b7ec7c697ccb188ba0ed18302c6e924f0ea0b10457dc753d6d2963f415fbaf761eace96 caliptra-rom-no-log.bin -2aae08cbe6e13559201fee432a7bbf535d27d94df4e8b4d05adab11c4f27b57c6d8392b71a24ee459af7b9663ce9c31f caliptra-rom-with-log.bin +89a3a6cfd9103f902e677a5004e5f600857f33f5931c6a18724447f61808bf39d9604ab7034802e1b2f0e78fdee0e8ef caliptra-rom-no-log.bin +418e2f952d29f7a07a8acdff46a8e4f06826c27feacf1409c395262698ceb324aa5aeaea9895a2d0ad9a62ae9c2e4c89 caliptra-rom-with-log.bin diff --git a/rom/dev/src/wdt.rs b/rom/dev/src/wdt.rs index 50e765872a..3535a45981 100644 --- a/rom/dev/src/wdt.rs +++ b/rom/dev/src/wdt.rs @@ -21,8 +21,6 @@ use caliptra_cfi_derive::cfi_mod_fn; use caliptra_common::WdtTimeout; use caliptra_drivers::SocIfc; -use crate::cprintln; - /// Start the Watchdog Timer /// Note: WDT is configured only if the device is in non-debug mode (i.e debug_locked = 1) /// @@ -36,15 +34,9 @@ pub fn start_wdt(soc_ifc: &mut SocIfc) { if wdt_timeout_cycles == 0 { wdt_timeout_cycles = 1; } - cprintln!( - "[state] Starting the WD Timer {} cycles", - wdt_timeout_cycles - ); caliptra_common::wdt::start_wdt( soc_ifc, WdtTimeout::from(core::num::NonZeroU64::new(wdt_timeout_cycles).unwrap()), ); - } else { - cprintln!("[state] WD Timer not started. Device not locked for debugging"); } } From 312de56e05d72be87b38eb0507a2ea9cd3b80a52 Mon Sep 17 00:00:00 2001 From: Carl Lundin Date: Wed, 6 Nov 2024 17:09:35 -0800 Subject: [PATCH 10/51] Revert "Remove WD print statement." This reverts commit 188c02dc57a54ff12e6586a11229da17c31818ab. (cherry picked from commit b9149760d72dbd51c7553e88a3e7c89b0f8722e2) --- FROZEN_IMAGES.sha384sum | 4 ++-- rom/dev/src/wdt.rs | 8 ++++++++ 2 files changed, 10 insertions(+), 2 deletions(-) diff --git a/FROZEN_IMAGES.sha384sum b/FROZEN_IMAGES.sha384sum index cf802c0b9c..97e4b9ff3c 100644 --- a/FROZEN_IMAGES.sha384sum +++ b/FROZEN_IMAGES.sha384sum @@ -1,3 +1,3 @@ # WARNING: Do not update this file without the approval of the Caliptra TAC -89a3a6cfd9103f902e677a5004e5f600857f33f5931c6a18724447f61808bf39d9604ab7034802e1b2f0e78fdee0e8ef caliptra-rom-no-log.bin -418e2f952d29f7a07a8acdff46a8e4f06826c27feacf1409c395262698ceb324aa5aeaea9895a2d0ad9a62ae9c2e4c89 caliptra-rom-with-log.bin +ad1064cba5b190e4f5258c175b7ec7c697ccb188ba0ed18302c6e924f0ea0b10457dc753d6d2963f415fbaf761eace96 caliptra-rom-no-log.bin +2aae08cbe6e13559201fee432a7bbf535d27d94df4e8b4d05adab11c4f27b57c6d8392b71a24ee459af7b9663ce9c31f caliptra-rom-with-log.bin diff --git a/rom/dev/src/wdt.rs b/rom/dev/src/wdt.rs index 3535a45981..50e765872a 100644 --- a/rom/dev/src/wdt.rs +++ b/rom/dev/src/wdt.rs @@ -21,6 +21,8 @@ use caliptra_cfi_derive::cfi_mod_fn; use caliptra_common::WdtTimeout; use caliptra_drivers::SocIfc; +use crate::cprintln; + /// Start the Watchdog Timer /// Note: WDT is configured only if the device is in non-debug mode (i.e debug_locked = 1) /// @@ -34,9 +36,15 @@ pub fn start_wdt(soc_ifc: &mut SocIfc) { if wdt_timeout_cycles == 0 { wdt_timeout_cycles = 1; } + cprintln!( + "[state] Starting the WD Timer {} cycles", + wdt_timeout_cycles + ); caliptra_common::wdt::start_wdt( soc_ifc, WdtTimeout::from(core::num::NonZeroU64::new(wdt_timeout_cycles).unwrap()), ); + } else { + cprintln!("[state] WD Timer not started. Device not locked for debugging"); } } From 9666b6b718188ac933b36792a802de332a9bc167 Mon Sep 17 00:00:00 2001 From: Nick Quarton <139178705+nquarton@users.noreply.github.com> Date: Thu, 7 Nov 2024 10:42:13 -0800 Subject: [PATCH 11/51] Replace error README's outdated error code table with link to source code (cherry picked from commit c94ce2b2e90f24741dbe5944ce4f72dd729acfa6) --- error/README.md | 152 +----------------------------------------------- 1 file changed, 1 insertion(+), 151 deletions(-) diff --git a/error/README.md b/error/README.md index 2d91e4a1fa..fffc73527b 100644 --- a/error/README.md +++ b/error/README.md @@ -1,153 +1,3 @@ ## Error Codes -| Component | Module | Description | Error Code | -| --- | ----------- | ----- | ----- | -| Driver | SHA256 | Internal Error |0x00020001 | -| Driver | SHA256 | Max Data Limit Reached |0x00020002 | -| Driver | SHA256 | Invalid Slice |0x00020003 | -| Driver | SHA256 | Array Index Out of Bounds |0x00020004 | -| Driver | SHA384 | Read Data Key Vault Read Error |0x00030001 | -| Driver | SHA384 | Read Data Key Vault Write Error |0x00030002 | -| Driver | SHA384 | Read Data Key Vault Unknown Error |0x00030003 | -| Driver | SHA384 | Invalid State Error |0x00030007 | -| Driver | SHA384 | Max Data Error |0x00030008 | -| Driver | HMAC384 | ReadKeyKvRead Error |0x00040001 | -| Driver | HMAC384 | ReadKeyKvWrite Error |0x00040002 | -| Driver | HMAC384 | ReadKeyKvUnknown Error |0x00040003 | -| Driver | HMAC384 | ReadData Kv Read Error |0x00040004 | -| Driver | HMAC384 | ReadData Kv Write Error |0x00040005 | -| Driver | HMAC384 | ReadData Kv Unknown Error |0x00040006 | -| Driver | HMAC384 | Write Tag Kv Read Error |0x00040007 | -| Driver | HMAC384 | Write Tag Kv Write Error |0x00040008 | -| Driver | HMAC384 | Write Tag Kv Unknown Error |0x00040009 | -| Driver | HMAC384 | Invalid Key Size Error |0x0004000A | -| Driver | HMAC384 | Invalid State Error |0x0004000B | -| Driver | HMAC384 | Max Data Error |0x0004000C | -| Driver | HMAC384 | Invalid Slice Error |0x0004000D | -| Driver | HMAC384 | Index Out of Bounds Error |0x0004000E | -| Driver | ECC384 | ReadSeedKvRead |0x00050001 | -| Driver | ECC384 | ReadSeedKvWrite |0x00050002 | -| Driver | ECC384 | ReadSeedKvUnknown |0x00050003 | -| Driver | ECC384 | WritePrivKeyKvRead |0x00050004 | -| Driver | ECC384 | WritePrivKeyKvWrite |0x00050005 | -| Driver | ECC384 | WritePrivKeyKvUnknown |0x00050006 | -| Driver | ECC384 | ReadPrivKeyKvRead |0x00050007 | -| Driver | ECC384 | ReadPrivKeyKvWrite |0x00050008 | -| Driver | ECC384 | ReadPrivKeyKvUnknown |0x00050009 | -| Driver | ECC384 | ReadDataKvRead |0x0005000A | -| Driver | ECC384 | ReadDataKvWrite |0x0005000B | -| Driver | ECC384 | ReadDataKvUnknown |0x0005000C | -| Driver | Key Vault | Erase failed due to use lock was set|0x00060001 | -| Driver | Key Vault | Erase failed due to write lock was set|0x00060002 | -| Driver | Pcr Bank | Erase failed due to write lock st |0x00070001 | -| Driver | Mailbox | Invalid State Error |0x00080001 | -| Driver | Mailbox | Invalid Data Length Error |0x00080002 | -| Driver | Mailbox | No Data Available Error |0x00080003 | -| Driver | Mailbox | Enqueue Error |0x00080004 | -| Driver | Mailbox | Dequeue Error |0x00080005 | -| Driver | SHA2_512_384Acc | Invalid Op |0x00090001 | -| Driver | SHA2_512_384Acc | Max Data Err |0x00090002 | -| Driver | SHA2_512_384Acc | Index Out of Bounds |0x00090003 | -| Driver | SHA1 | Invalid State Error |0x000A0001 | -| Driver | SHA1 | Max Data Error |0x000A0002 | -| Driver | SHA1 | Invalid Slice Error |0x000A0003 | -| Driver | SHA1 | Index Out of Bounds Error |0x000A0004 | -| Image Verifier | Verifier | ManifestMarkerMismatch |0x000B0001 | -| Image Verifier | Verifier | ManifestSizeMismatch |0x000B0002 | -| Image Verifier | Verifier | VendorPubKeyDigestInvalid |0x000B0003 | -| Image Verifier | Verifier | VendorPubKeyDigestFailure |0x000B0004 | -| Image Verifier | Verifier | VendorPubKeyDigestMismatch |0x000B0005 | -| Image Verifier | Verifier | OwnerPubKeyDigestFailure |0x000B0006 | -| Image Verifier | Verifier | OwnerPubKeyDigestMismatch |0x000B0007 | -| Image Verifier | Verifier | VendorEccPubKeyIndexOutOfBounds |0x000B0008 | -| Image Verifier | Verifier | VendorEccPubKeyRevoked |0x000B0009 | -| Image Verifier | Verifier | HeaderDigestFailure |0x000B000A | -| Image Verifier | Verifier | VendorEccVerifyFailure |0x000B000B | -| Image Verifier | Verifier | VendorEccSignatureInvalid |0x000B000C | -| Image Verifier | Verifier | VendorEccPubKeyIndexMismatch |0x000B000D | -| Image Verifier | Verifier | OwnerEccVerifyFailure |0x000B000E | -| Image Verifier | Verifier | OwnerEccSignatureInvalid |0x000B000F | -| Image Verifier | Verifier | TocEntryCountInvalid |0x000B0010 | -| Image Verifier | Verifier | TocDigestFailures |0x000B0011 | -| Image Verifier | Verifier | TocDigestMismatch |0x000B0012 | -| Image Verifier | Verifier | FmcDigestFailure |0x000B0013 | -| Image Verifier | Verifier | FmcDigestMismatch |0x000B0014 | -| Image Verifier | Verifier | RuntimeDigestFailure |0x000B0015 | -| Image Verifier | Verifier | RuntimeDigestMismatch |0x000B0016 | -| Image Verifier | Verifier | FmcRuntimeOverlap |0x000B0017 | -| Image Verifier | Verifier | FmcRuntimeIncorrectOrder |0x000B0018 | -| Image Verifier | Verifier | OwnerPubKeyDigestInvalidArg |0x000B0019 | -| Image Verifier | Verifier | OwnerEccSignatureInvalidArg |0x000B001A | -| Image Verifier | Verifier | VendorPubKeyDigestInvalidArg |0x000B001B | -| Image Verifier | Verifier | VendorEccSignatureInvalidArg |0x000B001C | -| Image Verifier | Verifier | UpdateResetOwnerDigestFailure |0x000B001D | -| Image Verifier | Verifier | UpdateResetVenPubKeyIdxMismatch |0x000B001E | -| Image Verifier | Verifier | UpdateResetFmcDigestMismatch |0x000B001F | -| Image Verifier | Verifier | UpdateResetVenPubKeyIdxOutOfBounds |0x000B0020 | -| Image Verifier | Verifier | FmcLoadAddrInvalid |0x000B0021 | -| Image Verifier | Verifier | FmcLoadAddrUnaligned |0x000B0022 | -| Image Verifier | Verifier | FmcEntryPointInvalid |0x000B0023 | -| Image Verifier | Verifier | FmcEntryPointUnaligned |0x000B0024 | -| Image Verifier | Verifier | FmcSvnGreaterThanMaxSupported |0x000B0025 | -| Image Verifier | Verifier | FmcSvnLessThanMinSupported |0x000B0026 | -| Image Verifier | Verifier | FmcSvnLessThanFuse |0x000B0027 | -| Image Verifier | Verifier | RuntimeLoadAddrInvalid |0x000B0028 | -| Image Verifier | Verifier | RuntimeLoadAddrUnaligned |0x000B0029 | -| Image Verifier | Verifier | RuntimeEntryPointInvalid |0x000B002A | -| Image Verifier | Verifier | RuntimeEntryPointUnaligned |0x000B002B | -| Image Verifier | Verifier | RuntimeSvnGreaterThanMaxSupported |0x000B002C | -| Image Verifier | Verifier | RuntimeSvnLessThanMinSupported |0x000B002D | -| Image Verifier | Verifier | RuntimeSvnLessThanFuse |0x000B002E | -| Driver | LMS | InvalidLmsAlgorithmType |0x000C0001 | -| Driver | LMS | InvalidLmotsAlgorithmType |0x000C0002 | -| Driver | LMS | InvalidWinternitzParameter |0x000C0003 | -| Driver | LMS | InvalidPValue |0x000C0004 | -| Driver | LMS | InvalidHashWidth |0x000C0005 | -| Driver | LMS | InvalidTreeHeight |0x000C0006 | -| Driver | LMS | InvalidQValue |0x000C0007 | -| Driver | LMS | InvalidIndex |0x000C0008 | -| Driver | LMS | PathOutOfBounds |0x000C0009 | -| Driver | CSRNG | Instantiate Error |0x000d0001 | -| Driver | CSRNG | Uninstantiate Error |0x000d0002 | -| Driver | CSRNG | Reseed Error |0x000d0003 | -| Driver | CSRNG | Generate Error |0x000d0004 | -| Driver | CSRNG | Update Error |0x000d0005 | -| Driver | CSRNG | Other Health Check Failed |0x000d0006 | -| Driver | CSRNG | Repetition Count Health Check Failed |0x000d0007 | -| Driver | CSRNG | Adaptive Proportion Health Check Failed |0x000d0008 | -| Runtime | Command Handler | Internal Error |0x000e0001 | -| Runtime | Command Handler | Unimplemented Command |0x000e0002 | -| Runtime | Command Handler | Insufficient Memory |0x000e0003 | -| ROM | IDEVID | CSR Builder Init Failure |0x01000001 | -| ROM | IDEVID | CSR Builder Build Failure |0x01000002 | -| ROM | IDEVID | Invalid CSR |0x01000003 | -| ROM | IDEVID | CSR Verification Failure |0x01000004 | -| ROM | IDEVID | CSR Overflow |0x01000005 | -| ROM | LDEVID | Certificate Verification Failure |0x01010001 | -| ROM | FMC Alias Layer | Certificate Verification Failure |0x01020001 | -| ROM | FMC Alias Layer | Caliptra Image Bundle Manifest Read Failure |0x01020002 | -| ROM | FMC Alias Layer | Caliptra Image Bundle Invalid Image Size |0x01020003 | -| ROM | FMC Alias Layer | Mailbox state inconsistent |0x01020004 | -| ROM | Update Reset Flow | Caliptra Image Bundle Manifest Read Failure |0x01030002 | -| ROM | Update Reset Flow | Invalid Firmware Command |0x01030003 | -| ROM | Update Reset Flow | Mailbox Access Failure |0x01030004 | -| ROM | Global Scope | Non Maskable Interrupt |0x01040001 | -| ROM | Global Scope | Exception |0x01040002 | -| ROM | Global Scope | Panic |0x01040003 | -| KAT | SHA256 | Digest Failure |0x90010001 | -| KAT | SHA256 | Digest Mismatch |0x90010002 | -| KAT | SHA384 | Digest Failure |0x90020001 | -| KAT | SHA384 | Digest Mismatch |0x90020002 | -| KAT | HMAC384 | HMAC Failure |0x90030001 | -| KAT | HMAC384 | HMAC Tag Mismatch |0x90030002 | -| KAT | ECC384 | Signature Generation Failure |0x90040001 | -| KAT | ECC384 | Signature Verification Failure |0x90040002 | -| KAT | ECC384 | Signature Mismatch |0x90040003 | -| KAT | SHA384 Accel | Digest Start Operation Failure |0x90050001 | -| KAT | SHA384 Accel | Digest Failure |0x90050002 | -| KAT | SHA384 Accel | Digest Mismatch |0x90050003 | -| KAT | SHA1 | Digest Failure |0x90060001 | -| KAT | SHA1 | Digest Mismatch |0x90060002 | -| KAT | LMS | Digest Failure |0x90070001 | -| KAT | LMS | Digest Mismatch |0x90070002 | - +See https://github.com/chipsalliance/caliptra-sw/blob/main/error/src/lib.rs for error code definitions \ No newline at end of file From 28c9c4362c7e73806763291266e2bf39e7e40f06 Mon Sep 17 00:00:00 2001 From: Vishal Mhatre <38512878+mhatrevi@users.noreply.github.com> Date: Sun, 10 Nov 2024 08:13:06 -0800 Subject: [PATCH 12/51] [update] Update auth manifest metadata limit to 128 (#1773) (cherry picked from commit 926ad4ae45b3baf1e935b80f7b4dfca178014a76) --- api/src/mailbox.rs | 2 +- auth-manifest/app/src/config.rs | 6 ++-- auth-manifest/gen/src/generator.rs | 6 ++-- auth-manifest/types/src/lib.rs | 30 +++++++++---------- drivers/src/lib.rs | 2 +- drivers/src/memory_layout.rs | 6 ++-- drivers/src/persistent.rs | 17 +++++------ runtime/src/authorize_and_stash.rs | 4 +-- runtime/src/packet.rs | 2 +- runtime/src/set_auth_manifest.rs | 14 ++++----- .../test_set_auth_manifest.rs | 4 +-- 11 files changed, 42 insertions(+), 51 deletions(-) diff --git a/api/src/mailbox.rs b/api/src/mailbox.rs index ed666ea4e0..c0d941132e 100644 --- a/api/src/mailbox.rs +++ b/api/src/mailbox.rs @@ -948,7 +948,7 @@ pub struct SetAuthManifestReq { pub manifest: [u8; SetAuthManifestReq::MAX_MAN_SIZE], } impl SetAuthManifestReq { - pub const MAX_MAN_SIZE: usize = 8192; + pub const MAX_MAN_SIZE: usize = 14 * 1024; pub fn as_bytes_partial(&self) -> CaliptraResult<&[u8]> { if self.manifest_size as usize > Self::MAX_MAN_SIZE { diff --git a/auth-manifest/app/src/config.rs b/auth-manifest/app/src/config.rs index 1ee33df7c6..a94f966b00 100644 --- a/auth-manifest/app/src/config.rs +++ b/auth-manifest/app/src/config.rs @@ -38,7 +38,7 @@ pub(crate) struct AuthManifestKeyConfigFromFile { } #[derive(Serialize, Deserialize)] -pub struct ImageMetadata { +pub struct ImageMetadataConfigFromFile { digest: String, source: u32, } @@ -54,7 +54,7 @@ pub(crate) struct AuthManifestConfigFromFile { pub owner_man_key_config: Option, - pub image_metadata_list: Vec, + pub image_metadata_list: Vec, } /// Load Authorization Manifest Key Configuration from file @@ -116,7 +116,7 @@ pub(crate) fn owner_config_from_file( } pub(crate) fn image_metadata_config_from_file( - config: &Vec, + config: &Vec, ) -> anyhow::Result> { let mut image_metadata_list = Vec::new(); diff --git a/auth-manifest/gen/src/generator.rs b/auth-manifest/gen/src/generator.rs index 09f0e7a04c..d9d487f8af 100644 --- a/auth-manifest/gen/src/generator.rs +++ b/auth-manifest/gen/src/generator.rs @@ -47,9 +47,7 @@ impl AuthManifestGenerator { let slice = config.image_metadata_list.as_slice(); auth_manifest.image_metadata_col.image_metadata_list[..slice.len()].copy_from_slice(slice); - auth_manifest.image_metadata_col.header.entry_count = - config.image_metadata_list.len() as u32; - auth_manifest.image_metadata_col.header.revision = 0; // [TODO] Need to update this. + auth_manifest.image_metadata_col.entry_count = config.image_metadata_list.len() as u32; // Generate the preamble. auth_manifest.preamble.marker = AUTH_MANIFEST_MARKER; @@ -118,7 +116,7 @@ impl AuthManifestGenerator { // Sign the IMC with the vendor manifest public keys if indicated in the flags. if config .flags - .contains(AuthManifestFlags::VENDOR_SIGNATURE_REQURIED) + .contains(AuthManifestFlags::VENDOR_SIGNATURE_REQUIRED) { if let Some(vendor_man_priv_keys) = config.vendor_man_key_info.priv_keys { let sig = self.crypto.ecdsa384_sign( diff --git a/auth-manifest/types/src/lib.rs b/auth-manifest/types/src/lib.rs index 004e9c0b50..a6aa13e67b 100644 --- a/auth-manifest/types/src/lib.rs +++ b/auth-manifest/types/src/lib.rs @@ -23,12 +23,12 @@ use zerocopy::{AsBytes, FromBytes}; use zeroize::Zeroize; pub const AUTH_MANIFEST_MARKER: u32 = 0x4154_4D4E; -pub const AUTH_MANIFEST_IMAGE_METADATA_MAX_COUNT: usize = 16; +pub const AUTH_MANIFEST_IMAGE_METADATA_MAX_COUNT: usize = 128; bitflags::bitflags! { #[derive(Default, Copy, Clone, Debug)] pub struct AuthManifestFlags : u32 { - const VENDOR_SIGNATURE_REQURIED = 0b1; + const VENDOR_SIGNATURE_REQUIRED = 0b1; } } @@ -139,18 +139,6 @@ pub struct AuthManifestImageMetadata { pub image_source: u32, } -/// Caliptra Authorization Manifest Image Metadata Collection Header -#[repr(C)] -#[derive(AsBytes, FromBytes, Clone, Copy, Debug, Zeroize, Default)] -#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))] -pub struct AuthManifestImageMetadataCollectionHeader { - pub revision: u32, - - pub reserved: [u8; 12], - - pub entry_count: u32, -} - impl Default for AuthManifestImageMetadata { fn default() -> Self { AuthManifestImageMetadata { @@ -162,14 +150,24 @@ impl Default for AuthManifestImageMetadata { /// Caliptra Authorization Manifest Image Metadata Collection #[repr(C)] -#[derive(AsBytes, FromBytes, Clone, Copy, Debug, Zeroize, Default)] +#[derive(AsBytes, FromBytes, Clone, Copy, Debug, Zeroize)] #[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))] pub struct AuthManifestImageMetadataCollection { - pub header: AuthManifestImageMetadataCollectionHeader, + pub entry_count: u32, pub image_metadata_list: [AuthManifestImageMetadata; AUTH_MANIFEST_IMAGE_METADATA_MAX_COUNT], } +impl Default for AuthManifestImageMetadataCollection { + fn default() -> Self { + AuthManifestImageMetadataCollection { + entry_count: 0, + image_metadata_list: [AuthManifestImageMetadata::default(); + AUTH_MANIFEST_IMAGE_METADATA_MAX_COUNT], + } + } +} + /// Caliptra Image Authorization Manifest #[repr(C)] #[derive(AsBytes, FromBytes, Clone, Copy, Debug, Zeroize, Default)] diff --git a/drivers/src/lib.rs b/drivers/src/lib.rs index 910b6c8521..d89ace877d 100644 --- a/drivers/src/lib.rs +++ b/drivers/src/lib.rs @@ -91,7 +91,7 @@ pub use okref::okref; pub use pcr_bank::{PcrBank, PcrId}; pub use pcr_reset::PcrResetCounter; #[cfg(feature = "runtime")] -pub use persistent::{AuthManifestImageMetadataList, AUTH_MANIFEST_IMAGE_METADATA_LIST_MAX_COUNT}; +pub use persistent::AuthManifestImageMetadataList; pub use persistent::{ FuseLogArray, PcrLogArray, PersistentData, PersistentDataAccessor, StashMeasurementArray, FUSE_LOG_MAX_COUNT, MEASUREMENT_MAX_COUNT, PCR_LOG_MAX_COUNT, diff --git a/drivers/src/memory_layout.rs b/drivers/src/memory_layout.rs index 1705f6c774..b371d3e719 100644 --- a/drivers/src/memory_layout.rs +++ b/drivers/src/memory_layout.rs @@ -44,7 +44,7 @@ pub const FUSE_LOG_ORG: u32 = MEASUREMENT_LOG_ORG + MEASUREMENT_LOG_SIZE; pub const DPE_ORG: u32 = FUSE_LOG_ORG + FUSE_LOG_SIZE; pub const PCR_RESET_COUNTER_ORG: u32 = DPE_ORG + DPE_SIZE; pub const AUTH_MAN_IMAGE_METADATA_LIST_ORG: u32 = PCR_RESET_COUNTER_ORG + PCR_RESET_COUNTER_SIZE; -pub const DATA_ORG: u32 = AUTH_MAN_IMAGE_METADATA_LIST_ORG + AUTH_MAN_IMAGE_METADATA_LIST_MAX_SIZE; +pub const DATA_ORG: u32 = AUTH_MAN_IMAGE_METADATA_LIST_ORG + AUTH_MAN_IMAGE_METADATA_MAX_SIZE; pub const STACK_ORG: u32 = DATA_ORG + DATA_SIZE; pub const ROM_STACK_ORG: u32 = STACK_ORG + (STACK_SIZE - ROM_STACK_SIZE); @@ -76,8 +76,8 @@ pub const MEASUREMENT_LOG_SIZE: u32 = 1024; pub const FUSE_LOG_SIZE: u32 = 1024; pub const DPE_SIZE: u32 = 5 * 1024; pub const PCR_RESET_COUNTER_SIZE: u32 = 1024; -pub const AUTH_MAN_IMAGE_METADATA_LIST_MAX_SIZE: u32 = 1024; -pub const DATA_SIZE: u32 = 69 * 1024; +pub const AUTH_MAN_IMAGE_METADATA_MAX_SIZE: u32 = 7 * 1024; +pub const DATA_SIZE: u32 = 63 * 1024; pub const STACK_SIZE: u32 = 22 * 1024; pub const ROM_STACK_SIZE: u32 = 14 * 1024; pub const ESTACK_SIZE: u32 = 1024; diff --git a/drivers/src/persistent.rs b/drivers/src/persistent.rs index d1a2b01643..4afbf7535a 100644 --- a/drivers/src/persistent.rs +++ b/drivers/src/persistent.rs @@ -3,9 +3,10 @@ use core::{marker::PhantomData, mem::size_of, ptr::addr_of}; #[cfg(feature = "runtime")] -use caliptra_auth_man_types::AuthManifestImageMetadata; -#[cfg(feature = "runtime")] -use caliptra_auth_man_types::AuthManifestImageMetadataCollection; +use caliptra_auth_man_types::{ + AuthManifestImageMetadata, AuthManifestImageMetadataCollection, + AUTH_MANIFEST_IMAGE_METADATA_MAX_COUNT, +}; use caliptra_image_types::ImageManifest; #[cfg(feature = "runtime")] use dpe::{DpeInstance, U8Bool, MAX_HANDLES}; @@ -25,8 +26,6 @@ use crate::pcr_reset::PcrResetCounter; pub const PCR_LOG_MAX_COUNT: usize = 17; pub const FUSE_LOG_MAX_COUNT: usize = 62; pub const MEASUREMENT_MAX_COUNT: usize = 8; -#[cfg(feature = "runtime")] -pub const AUTH_MANIFEST_IMAGE_METADATA_LIST_MAX_COUNT: usize = 8; #[cfg(feature = "runtime")] const DPE_DCCM_STORAGE: usize = size_of::() @@ -42,7 +41,7 @@ pub type FuseLogArray = [FuseLogEntry; FUSE_LOG_MAX_COUNT]; pub type StashMeasurementArray = [MeasurementLogEntry; MEASUREMENT_MAX_COUNT]; #[cfg(feature = "runtime")] pub type AuthManifestImageMetadataList = - [AuthManifestImageMetadata; AUTH_MANIFEST_IMAGE_METADATA_LIST_MAX_COUNT]; + [AuthManifestImageMetadata; AUTH_MANIFEST_IMAGE_METADATA_MAX_COUNT]; #[derive(FromBytes, AsBytes, Zeroize)] #[repr(C)] @@ -99,12 +98,12 @@ pub struct PersistentData { #[cfg(feature = "runtime")] pub auth_manifest_image_metadata_col: AuthManifestImageMetadataCollection, #[cfg(feature = "runtime")] - reserved9: [u8; memory_layout::AUTH_MAN_IMAGE_METADATA_LIST_MAX_SIZE as usize + reserved9: [u8; memory_layout::AUTH_MAN_IMAGE_METADATA_MAX_SIZE as usize - size_of::()], #[cfg(not(feature = "runtime"))] pub auth_manifest_image_metadata_col: - [u8; memory_layout::AUTH_MAN_IMAGE_METADATA_LIST_MAX_SIZE as usize], + [u8; memory_layout::AUTH_MAN_IMAGE_METADATA_MAX_SIZE as usize], } impl PersistentData { pub fn assert_matches_layout() { @@ -139,7 +138,7 @@ impl PersistentData { assert_eq!( P.add(1) as u32, memory_layout::AUTH_MAN_IMAGE_METADATA_LIST_ORG - + memory_layout::AUTH_MAN_IMAGE_METADATA_LIST_MAX_SIZE + + memory_layout::AUTH_MAN_IMAGE_METADATA_MAX_SIZE ); } } diff --git a/runtime/src/authorize_and_stash.rs b/runtime/src/authorize_and_stash.rs index 0ff44365a0..9a1de26c0f 100644 --- a/runtime/src/authorize_and_stash.rs +++ b/runtime/src/authorize_and_stash.rs @@ -17,8 +17,7 @@ use core::mem::size_of; use crate::{dpe_crypto::DpeCrypto, CptraDpeTypes, DpePlatform, Drivers, StashMeasurementCmd}; use caliptra_auth_man_types::{ - AuthManifestImageMetadataCollection, AuthManifestImageMetadataCollectionHeader, - AuthManifestPreamble, AUTH_MANIFEST_MARKER, + AuthManifestImageMetadataCollection, AuthManifestPreamble, AUTH_MANIFEST_MARKER, }; use caliptra_cfi_derive_git::cfi_impl_fn; use caliptra_cfi_lib_git::cfi_launder; @@ -30,7 +29,6 @@ use caliptra_drivers::{ pcr_log::PCR_ID_STASH_MEASUREMENT, Array4x12, Array4xN, AuthManifestImageMetadataList, CaliptraError, CaliptraResult, Ecc384, Ecc384PubKey, Ecc384Signature, HashValue, Lms, PersistentData, RomPqcVerifyConfig, Sha256, Sha384, SocIfc, - AUTH_MANIFEST_IMAGE_METADATA_LIST_MAX_COUNT, }; use caliptra_image_types::{ ImageDigest, ImageEccPubKey, ImageEccSignature, ImageLmsPublicKey, ImageLmsSignature, diff --git a/runtime/src/packet.rs b/runtime/src/packet.rs index 3072e2e673..1a925fb32b 100644 --- a/runtime/src/packet.rs +++ b/runtime/src/packet.rs @@ -25,7 +25,7 @@ pub struct Packet { pub len: usize, // Length in bytes } -const MAX_PAYLOAD_SIZE: usize = 2050; // in dwords +const MAX_PAYLOAD_SIZE: usize = 3586; // in dwords impl Default for Packet { fn default() -> Self { diff --git a/runtime/src/set_auth_manifest.rs b/runtime/src/set_auth_manifest.rs index b582a8b098..666f2c8f12 100644 --- a/runtime/src/set_auth_manifest.rs +++ b/runtime/src/set_auth_manifest.rs @@ -18,8 +18,8 @@ use core::mem::size_of; use crate::verify; use crate::{dpe_crypto::DpeCrypto, CptraDpeTypes, DpePlatform, Drivers}; use caliptra_auth_man_types::{ - AuthManifestFlags, AuthManifestImageMetadataCollection, - AuthManifestImageMetadataCollectionHeader, AuthManifestPreamble, AUTH_MANIFEST_MARKER, + AuthManifestFlags, AuthManifestImageMetadataCollection, AuthManifestPreamble, + AUTH_MANIFEST_IMAGE_METADATA_MAX_COUNT, AUTH_MANIFEST_MARKER, }; use caliptra_cfi_derive_git::cfi_impl_fn; use caliptra_cfi_lib_git::cfi_launder; @@ -30,7 +30,6 @@ use caliptra_drivers::{ pcr_log::PCR_ID_STASH_MEASUREMENT, Array4x12, Array4xN, AuthManifestImageMetadataList, CaliptraError, CaliptraResult, Ecc384, Ecc384PubKey, Ecc384Signature, HashValue, Lms, PersistentData, RomPqcVerifyConfig, Sha256, Sha384, SocIfc, - AUTH_MANIFEST_IMAGE_METADATA_LIST_MAX_COUNT, }; use caliptra_image_types::{ ImageDigest, ImageEccPubKey, ImageEccSignature, ImageLmsPublicKey, ImageLmsSignature, @@ -221,7 +220,7 @@ impl SetAuthManifestCmd { soc_ifc: &SocIfc, ) -> CaliptraResult<()> { let flags = AuthManifestFlags::from(auth_manifest_preamble.flags); - if !flags.contains(AuthManifestFlags::VENDOR_SIGNATURE_REQURIED) { + if !flags.contains(AuthManifestFlags::VENDOR_SIGNATURE_REQUIRED) { return Ok(()); } // Verify the vendor ECC signature over the image metadata collection. @@ -340,7 +339,7 @@ impl SetAuthManifestCmd { sha256: &mut Sha256, soc_ifc: &SocIfc, ) -> CaliptraResult<()> { - if cmd_buf.len() < size_of::() { + if cmd_buf.len() < size_of::() { Err(CaliptraError::RUNTIME_AUTH_MANIFEST_IMAGE_METADATA_LIST_INVALID_SIZE)?; } @@ -354,9 +353,8 @@ impl SetAuthManifestCmd { image_metadata_col.as_bytes_mut()[..col_size].copy_from_slice(buf); - if image_metadata_col.header.entry_count == 0 - || image_metadata_col.header.entry_count - > AUTH_MANIFEST_IMAGE_METADATA_LIST_MAX_COUNT as u32 + if image_metadata_col.entry_count == 0 + || image_metadata_col.entry_count > AUTH_MANIFEST_IMAGE_METADATA_MAX_COUNT as u32 { Err(CaliptraError::RUNTIME_AUTH_MANIFEST_IMAGE_METADATA_LIST_INVALID_ENTRY_COUNT)?; } diff --git a/runtime/tests/runtime_integration_tests/test_set_auth_manifest.rs b/runtime/tests/runtime_integration_tests/test_set_auth_manifest.rs index dc3dd5ee04..d15ba3314a 100644 --- a/runtime/tests/runtime_integration_tests/test_set_auth_manifest.rs +++ b/runtime/tests/runtime_integration_tests/test_set_auth_manifest.rs @@ -97,7 +97,7 @@ fn test_auth_manifest() -> AuthorizationManifest { owner_man_key_info, image_metadata_list, version: 1, - flags: AuthManifestFlags::VENDOR_SIGNATURE_REQURIED, + flags: AuthManifestFlags::VENDOR_SIGNATURE_REQUIRED, }; let gen = AuthManifestGenerator::new(Crypto::default()); @@ -273,7 +273,7 @@ fn test_set_auth_manifest_invalid_owner_lms_sig() { #[test] fn test_set_auth_manifest_invalid_metadata_list_count() { let mut auth_manifest = test_auth_manifest(); - auth_manifest.image_metadata_col.header.entry_count = 0; + auth_manifest.image_metadata_col.entry_count = 0; test_manifest_expect_err( auth_manifest, CaliptraError::RUNTIME_AUTH_MANIFEST_IMAGE_METADATA_LIST_INVALID_ENTRY_COUNT, From e0513fe6c4457b5f811d6c2fa771340356eca891 Mon Sep 17 00:00:00 2001 From: Carl Lundin Date: Wed, 16 Oct 2024 14:46:15 -0700 Subject: [PATCH 13/51] Add command to retrieve IDevID CSR from persistent storage. * This resolves https://github.com/chipsalliance/caliptra-sw/issues/1687, for ROM. (cherry picked from commit 6cd0ebe294b720aff9db35fb51cb3f0680e21d1c) --- FROZEN_IMAGES.sha384sum | 4 +- api/src/mailbox.rs | 41 +++++++++++ drivers/src/lib.rs | 5 +- drivers/src/memory_layout.rs | 12 +++- drivers/src/persistent.rs | 72 ++++++++++++++++++- error/src/lib.rs | 6 ++ hw-model/src/lib.rs | 9 +++ rom/dev/README.md | 1 + rom/dev/src/flow/cold_reset/fw_processor.rs | 27 ++++++- rom/dev/src/flow/cold_reset/idev_id.rs | 45 ++++++++---- rom/dev/src/flow/cold_reset/x509.rs | 23 ------ rom/dev/tests/rom_integration_tests/main.rs | 1 + .../tests_get_idev_csr.rs | 70 ++++++++++++++++++ runtime/README.md | 27 +++++++ runtime/src/get_idev_csr.rs | 56 +++++++++++++++ runtime/src/lib.rs | 3 + .../tests/runtime_integration_tests/common.rs | 9 +++ .../tests/runtime_integration_tests/main.rs | 1 + .../test_get_idev_csr.rs | 63 ++++++++++++++++ 19 files changed, 431 insertions(+), 44 deletions(-) create mode 100644 rom/dev/tests/rom_integration_tests/tests_get_idev_csr.rs create mode 100644 runtime/src/get_idev_csr.rs create mode 100644 runtime/tests/runtime_integration_tests/test_get_idev_csr.rs diff --git a/FROZEN_IMAGES.sha384sum b/FROZEN_IMAGES.sha384sum index 97e4b9ff3c..d5bb5388ab 100644 --- a/FROZEN_IMAGES.sha384sum +++ b/FROZEN_IMAGES.sha384sum @@ -1,3 +1,3 @@ # WARNING: Do not update this file without the approval of the Caliptra TAC -ad1064cba5b190e4f5258c175b7ec7c697ccb188ba0ed18302c6e924f0ea0b10457dc753d6d2963f415fbaf761eace96 caliptra-rom-no-log.bin -2aae08cbe6e13559201fee432a7bbf535d27d94df4e8b4d05adab11c4f27b57c6d8392b71a24ee459af7b9663ce9c31f caliptra-rom-with-log.bin +fc4ceed3891771c263c42eb56bdfff3026e1baf75e48b09bad58aaf562aea1a31f5df6636ac90f3aab73d533f03f0e5d caliptra-rom-no-log.bin +e6254e3492969108c1340b2f662d82ab72572f38fab970990c72bdb03f0bfbfd18f6a16a5f273df8fd0faf5aefe9c138 caliptra-rom-with-log.bin diff --git a/api/src/mailbox.rs b/api/src/mailbox.rs index c0d941132e..f8b1225753 100644 --- a/api/src/mailbox.rs +++ b/api/src/mailbox.rs @@ -51,6 +51,9 @@ impl CommandId { // The authorize and stash command. pub const AUTHORIZE_AND_STASH: Self = Self(0x4154_5348); // "ATSH" + + // The get IDevID CSR command. + pub const GET_IDEV_CSR: Self = Self(0x4944_4352); // "IDCR" } impl From for CommandId { @@ -151,6 +154,7 @@ pub enum MailboxResp { QuotePcrs(QuotePcrsResp), CertifyKeyExtended(CertifyKeyExtendedResp), AuthorizeAndStash(AuthorizeAndStashResp), + GetIdevIdCsr(GetIdevIdCsrResp), } impl MailboxResp { @@ -171,6 +175,7 @@ impl MailboxResp { MailboxResp::QuotePcrs(resp) => Ok(resp.as_bytes()), MailboxResp::CertifyKeyExtended(resp) => Ok(resp.as_bytes()), MailboxResp::AuthorizeAndStash(resp) => Ok(resp.as_bytes()), + MailboxResp::GetIdevIdCsr(resp) => Ok(resp.as_bytes()), } } @@ -191,6 +196,7 @@ impl MailboxResp { MailboxResp::QuotePcrs(resp) => Ok(resp.as_bytes_mut()), MailboxResp::CertifyKeyExtended(resp) => Ok(resp.as_bytes_mut()), MailboxResp::AuthorizeAndStash(resp) => Ok(resp.as_bytes_mut()), + MailboxResp::GetIdevIdCsr(resp) => Ok(resp.as_bytes_mut()), } } @@ -458,6 +464,7 @@ pub struct GetIdevInfoResp { pub struct GetLdevCertReq { header: MailboxReqHeader, } + impl Request for GetLdevCertReq { const ID: CommandId = CommandId::GET_LDEV_CERT; type Resp = GetLdevCertResp; @@ -976,6 +983,40 @@ impl Default for SetAuthManifestReq { } } +// GET_IDEVID_CSR +#[repr(C)] +#[derive(Default, Debug, AsBytes, FromBytes, PartialEq, Eq)] +pub struct GetIdevIdCsrReq { + pub hdr: MailboxReqHeader, +} + +impl Request for GetIdevIdCsrReq { + const ID: CommandId = CommandId::GET_IDEV_CSR; + type Resp = GetIdevIdCsrResp; +} + +#[repr(C)] +#[derive(Debug, AsBytes, FromBytes, PartialEq, Eq)] +pub struct GetIdevIdCsrResp { + pub hdr: MailboxRespHeader, + pub data_size: u32, + pub data: [u8; Self::DATA_MAX_SIZE], +} +impl GetIdevIdCsrResp { + pub const DATA_MAX_SIZE: usize = 512; +} +impl ResponseVarSize for GetIdevIdCsrResp {} + +impl Default for GetIdevIdCsrResp { + fn default() -> Self { + Self { + hdr: MailboxRespHeader::default(), + data_size: 0, + data: [0u8; Self::DATA_MAX_SIZE], + } + } +} + #[repr(u32)] #[derive(Debug, PartialEq, Eq)] pub enum ImageHashSource { diff --git a/drivers/src/lib.rs b/drivers/src/lib.rs index d89ace877d..830e9f5174 100644 --- a/drivers/src/lib.rs +++ b/drivers/src/lib.rs @@ -93,8 +93,9 @@ pub use pcr_reset::PcrResetCounter; #[cfg(feature = "runtime")] pub use persistent::AuthManifestImageMetadataList; pub use persistent::{ - FuseLogArray, PcrLogArray, PersistentData, PersistentDataAccessor, StashMeasurementArray, - FUSE_LOG_MAX_COUNT, MEASUREMENT_MAX_COUNT, PCR_LOG_MAX_COUNT, + FuseLogArray, IdevIdCsr, PcrLogArray, PersistentData, PersistentDataAccessor, + StashMeasurementArray, FUSE_LOG_MAX_COUNT, MAX_CSR_SIZE, MEASUREMENT_MAX_COUNT, + PCR_LOG_MAX_COUNT, }; pub use pic::{IntSource, Pic}; pub use sha1::{Sha1, Sha1Digest, Sha1DigestOp}; diff --git a/drivers/src/memory_layout.rs b/drivers/src/memory_layout.rs index b371d3e719..d0992485e1 100644 --- a/drivers/src/memory_layout.rs +++ b/drivers/src/memory_layout.rs @@ -44,7 +44,8 @@ pub const FUSE_LOG_ORG: u32 = MEASUREMENT_LOG_ORG + MEASUREMENT_LOG_SIZE; pub const DPE_ORG: u32 = FUSE_LOG_ORG + FUSE_LOG_SIZE; pub const PCR_RESET_COUNTER_ORG: u32 = DPE_ORG + DPE_SIZE; pub const AUTH_MAN_IMAGE_METADATA_LIST_ORG: u32 = PCR_RESET_COUNTER_ORG + PCR_RESET_COUNTER_SIZE; -pub const DATA_ORG: u32 = AUTH_MAN_IMAGE_METADATA_LIST_ORG + AUTH_MAN_IMAGE_METADATA_MAX_SIZE; +pub const IDEVID_CSR_ORG: u32 = AUTH_MAN_IMAGE_METADATA_LIST_ORG + AUTH_MAN_IMAGE_METADATA_MAX_SIZE; +pub const DATA_ORG: u32 = IDEVID_CSR_ORG + IDEVID_CSR_SIZE; pub const STACK_ORG: u32 = DATA_ORG + DATA_SIZE; pub const ROM_STACK_ORG: u32 = STACK_ORG + (STACK_SIZE - ROM_STACK_SIZE); @@ -77,7 +78,8 @@ pub const FUSE_LOG_SIZE: u32 = 1024; pub const DPE_SIZE: u32 = 5 * 1024; pub const PCR_RESET_COUNTER_SIZE: u32 = 1024; pub const AUTH_MAN_IMAGE_METADATA_MAX_SIZE: u32 = 7 * 1024; -pub const DATA_SIZE: u32 = 63 * 1024; +pub const IDEVID_CSR_SIZE: u32 = 1024; +pub const DATA_SIZE: u32 = 62 * 1024; pub const STACK_SIZE: u32 = 22 * 1024; pub const ROM_STACK_SIZE: u32 = 14 * 1024; pub const ESTACK_SIZE: u32 = 1024; @@ -168,6 +170,12 @@ fn mem_layout_test_pcr_reset_counter() { ); } +#[test] +#[allow(clippy::assertions_on_constants)] +fn mem_layout_test_idevid_csr() { + assert_eq!((DATA_ORG - IDEVID_CSR_ORG), IDEVID_CSR_SIZE); +} + #[test] #[allow(clippy::assertions_on_constants)] fn mem_layout_test_data() { diff --git a/drivers/src/persistent.rs b/drivers/src/persistent.rs index 4afbf7535a..a3b43fc290 100644 --- a/drivers/src/persistent.rs +++ b/drivers/src/persistent.rs @@ -7,6 +7,7 @@ use caliptra_auth_man_types::{ AuthManifestImageMetadata, AuthManifestImageMetadataCollection, AUTH_MANIFEST_IMAGE_METADATA_MAX_COUNT, }; +use caliptra_error::{CaliptraError, CaliptraResult}; use caliptra_image_types::ImageManifest; #[cfg(feature = "runtime")] use dpe::{DpeInstance, U8Bool, MAX_HANDLES}; @@ -23,6 +24,7 @@ use crate::{ #[cfg(feature = "runtime")] use crate::pcr_reset::PcrResetCounter; +pub const MAX_CSR_SIZE: usize = 512; pub const PCR_LOG_MAX_COUNT: usize = 17; pub const FUSE_LOG_MAX_COUNT: usize = 62; pub const MEASUREMENT_MAX_COUNT: usize = 8; @@ -43,6 +45,65 @@ pub type StashMeasurementArray = [MeasurementLogEntry; MEASUREMENT_MAX_COUNT]; pub type AuthManifestImageMetadataList = [AuthManifestImageMetadata; AUTH_MANIFEST_IMAGE_METADATA_MAX_COUNT]; +#[derive(Clone, FromBytes, AsBytes, Zeroize)] +#[repr(C)] +pub struct IdevIdCsr { + csr_len: u32, + csr: [u8; MAX_CSR_SIZE], +} + +impl Default for IdevIdCsr { + fn default() -> Self { + Self { + csr_len: Self::UNPROVISIONED_CSR, + csr: [0; MAX_CSR_SIZE], + } + } +} + +impl IdevIdCsr { + /// The `csr_len` field is set to this constant when a ROM image supports CSR generation but + /// the CSR generation flag was not enabled. + /// + /// This is used by the runtime to distinguish ROM images that support CSR generation from + /// ones that do not. + /// + /// u32::MAX is too large to be a valid CSR, so we use it to encode this state. + pub const UNPROVISIONED_CSR: u32 = u32::MAX; + + /// Get the CSR buffer + pub fn get(&self) -> Option<&[u8]> { + self.csr.get(..self.csr_len as usize) + } + + /// Create `Self` from a csr slice. `csr_len` MUST be the actual length of the csr. + pub fn new(csr_buf: &[u8], csr_len: usize) -> CaliptraResult { + if csr_len >= MAX_CSR_SIZE { + return Err(CaliptraError::ROM_IDEVID_INVALID_CSR); + } + + let mut _self = Self { + csr_len: csr_len as u32, + csr: [0; MAX_CSR_SIZE], + }; + _self.csr[..csr_len].copy_from_slice(&csr_buf[..csr_len]); + + Ok(_self) + } + + /// Get the length of the CSR in bytes. + pub fn get_csr_len(&self) -> u32 { + self.csr_len + } + + /// Check if the CSR was unprovisioned + pub fn is_unprovisioned(&self) -> bool { + self.csr_len == Self::UNPROVISIONED_CSR + } +} + +const _: () = assert!(size_of::() < memory_layout::IDEVID_CSR_SIZE as usize); + #[derive(FromBytes, AsBytes, Zeroize)] #[repr(C)] pub struct PersistentData { @@ -104,7 +165,11 @@ pub struct PersistentData { #[cfg(not(feature = "runtime"))] pub auth_manifest_image_metadata_col: [u8; memory_layout::AUTH_MAN_IMAGE_METADATA_MAX_SIZE as usize], + + pub idevid_csr: IdevIdCsr, + reserved10: [u8; memory_layout::IDEVID_CSR_SIZE as usize - size_of::()], } + impl PersistentData { pub fn assert_matches_layout() { const P: *const PersistentData = memory_layout::MAN1_ORG as *const PersistentData; @@ -135,10 +200,13 @@ impl PersistentData { addr_of!((*P).auth_manifest_image_metadata_col) as u32, memory_layout::AUTH_MAN_IMAGE_METADATA_LIST_ORG ); + assert_eq!( + addr_of!((*P).idevid_csr) as u32, + memory_layout::IDEVID_CSR_ORG + ); assert_eq!( P.add(1) as u32, - memory_layout::AUTH_MAN_IMAGE_METADATA_LIST_ORG - + memory_layout::AUTH_MAN_IMAGE_METADATA_MAX_SIZE + memory_layout::IDEVID_CSR_ORG + memory_layout::IDEVID_CSR_SIZE ); } } diff --git a/error/src/lib.rs b/error/src/lib.rs index bc0fef6cdd..a8ab62d60e 100644 --- a/error/src/lib.rs +++ b/error/src/lib.rs @@ -470,6 +470,10 @@ impl CaliptraError { pub const RUNTIME_CMD_RESERVED_PAUSER: CaliptraError = CaliptraError::new_const(0x000E004F); pub const RUNTIME_AUTH_AND_STASH_MEASUREMENT_DPE_ERROR: CaliptraError = CaliptraError::new_const(0x000E0050); + pub const RUNTIME_GET_IDEV_ID_UNPROVISIONED: CaliptraError = + CaliptraError::new_const(0x000E0051); + pub const RUNTIME_GET_IDEV_ID_UNSUPPORTED_ROM: CaliptraError = + CaliptraError::new_const(0x000E0052); /// FMC Errors pub const FMC_GLOBAL_NMI: CaliptraError = CaliptraError::new_const(0x000F0001); @@ -526,6 +530,8 @@ impl CaliptraError { pub const FW_PROC_MAILBOX_STASH_MEASUREMENT_MAX_LIMIT: CaliptraError = CaliptraError::new_const(0x01020008); pub const FW_PROC_MAILBOX_RESERVED_PAUSER: CaliptraError = CaliptraError::new_const(0x01020009); + pub const FW_PROC_MAILBOX_GET_IDEV_CSR_UNPROVISIONED_CSR: CaliptraError = + CaliptraError::new_const(0x0102000A); /// FMC Alias Layer : Certificate Verification Failure. pub const FMC_ALIAS_CERT_VERIFY: CaliptraError = CaliptraError::new_const(0x01030001); diff --git a/hw-model/src/lib.rs b/hw-model/src/lib.rs index 55b5be6b61..8552a83301 100644 --- a/hw-model/src/lib.rs +++ b/hw-model/src/lib.rs @@ -587,6 +587,15 @@ pub trait HwModel: SocManager { const MAX_WAIT_CYCLES: u32 = 20_000_000; let mut cycles = 0; while !self.ready_for_fw() { + // If GENERATE_IDEVID_CSR was set then we need to clear cptra_dbg_manuf_service_reg + // once the CSR is ready to continue making progress. + // + // Generally the CSR should be read from the mailbox at this point, but to + // accommodate test cases that ignore the CSR mailbox, we will ignore it here. + if self.soc_ifc().cptra_flow_status().read().idevid_csr_ready() { + self.soc_ifc().cptra_dbg_manuf_service_reg().write(|_| 0); + } + self.step(); cycles += 1; if cycles > MAX_WAIT_CYCLES { diff --git a/rom/dev/README.md b/rom/dev/README.md index 224e534127..792b576164 100644 --- a/rom/dev/README.md +++ b/rom/dev/README.md @@ -625,6 +625,7 @@ ROM supports the following set of commands before handling the FW_DOWNLOAD comma 4. **SELF_TEST_GET_RESULTS**: This command is used to check if a SELF_TEST command is in progress. [Self Test Get Results command](https://github.com/chipsalliance/caliptra-sw/blob/main/runtime/README.md#self_test_get_results). 5. **SHUTDOWN**: This command is used clear the hardware crypto blocks including the keyvault. [Shutdown command](https://github.com/chipsalliance/caliptra-sw/blob/main/runtime/README.md#shutdown). 6. **CAPABILITIES**: This command is used to query the ROM capabilities. Capabilities is a 128-bit value with individual bits indicating a specific capability. Currently, the only capability supported is ROM_BASE (bit 0). [Capabilities command](https://github.com/chipsalliance/caliptra-sw/blob/main/runtime/README.md#capabilities). +7. **GET_IDEVID_CSR**: This command is used to fetch the IDevID CSR from ROM. [Fetch IDevIDCSR command](https://github.com/chipsalliance/caliptra-sw/blob/main/runtime/README.md#get_idevid_csr). #### Downloading firmware image from mailbox diff --git a/rom/dev/src/flow/cold_reset/fw_processor.rs b/rom/dev/src/flow/cold_reset/fw_processor.rs index 482d350f88..e5988aa33d 100644 --- a/rom/dev/src/flow/cold_reset/fw_processor.rs +++ b/rom/dev/src/flow/cold_reset/fw_processor.rs @@ -23,7 +23,7 @@ use caliptra_cfi_lib::CfiCounter; use caliptra_common::capabilities::Capabilities; use caliptra_common::fips::FipsVersionCmd; use caliptra_common::mailbox_api::{ - CapabilitiesResp, CommandId, MailboxReqHeader, MailboxRespHeader, Response, + CapabilitiesResp, CommandId, GetIdevIdCsrResp, MailboxReqHeader, MailboxRespHeader, Response, StashMeasurementReq, StashMeasurementResp, }; use caliptra_common::{ @@ -306,6 +306,31 @@ impl FirmwareProcessor { resp.populate_chksum(); txn.send_response(resp.as_bytes())?; } + CommandId::GET_IDEV_CSR => { + let mut request = MailboxReqHeader::default(); + Self::copy_req_verify_chksum(&mut txn, request.as_bytes_mut())?; + + let csr_persistent_mem = &persistent_data.idevid_csr; + let mut resp = GetIdevIdCsrResp::default(); + + if csr_persistent_mem.is_unprovisioned() { + // CSR was never written to DCCM. This means the gen_idev_id_csr + // manufacturing flag was not set before booting into ROM. + return Err( + CaliptraError::FW_PROC_MAILBOX_GET_IDEV_CSR_UNPROVISIONED_CSR, + ); + } + + let csr = csr_persistent_mem + .get() + .ok_or(CaliptraError::ROM_IDEVID_INVALID_CSR)?; + + resp.data_size = csr_persistent_mem.get_csr_len(); + resp.data[..resp.data_size as usize].copy_from_slice(csr); + + resp.populate_chksum(); + txn.send_response(resp.as_bytes())?; + } _ => { cprintln!("[fwproc] Invalid command received"); // Don't complete the transaction here; let the fatal diff --git a/rom/dev/src/flow/cold_reset/idev_id.rs b/rom/dev/src/flow/cold_reset/idev_id.rs index e22cbb661b..6397edb54a 100644 --- a/rom/dev/src/flow/cold_reset/idev_id.rs +++ b/rom/dev/src/flow/cold_reset/idev_id.rs @@ -27,18 +27,14 @@ use caliptra_common::keyids::{ KEY_ID_UDS, }; use caliptra_common::RomBootStatus::*; +use caliptra_drivers::MAX_CSR_SIZE; use caliptra_drivers::*; use caliptra_x509::*; use zeroize::Zeroize; -type InitDevIdCsr<'a> = Certificate<'a, { MAX_CSR_SIZE }>; - /// Initialization Vector used by Deobfuscation Engine during UDS / field entropy decryption. const DOE_IV: Array4x4 = Array4xN::<4, 16>([0xfb10365b, 0xa1179741, 0xfba193a1, 0x0f406d7e]); -/// Maximum Certificate Signing Request Size -const MAX_CSR_SIZE: usize = 512; - /// Dice Initial Device Identity (IDEVID) Layer pub enum InitDevIdLayer {} @@ -240,6 +236,8 @@ impl InitDevIdLayer { // // A flag is asserted via JTAG interface to enable the generation of CSR if !env.soc_ifc.mfg_flag_gen_idev_id_csr() { + let dev_id_csr = IdevIdCsr::default(); + Self::write_csr_to_peristent_storage(env, &dev_id_csr)?; return Ok(()); } @@ -294,7 +292,7 @@ impl InitDevIdLayer { cprintln!("[idev] SIG.S = {}", HexBytes(&_sig_s)); // Build the CSR with `To Be Signed` & `Signature` - let mut csr = [0u8; MAX_CSR_SIZE]; + let mut csr_buf = [0; MAX_CSR_SIZE]; let ecdsa384_sig = sig.to_ecdsa(); let result = Ecdsa384CsrBuilder::new(tbs.tbs(), &ecdsa384_sig) .ok_or(CaliptraError::ROM_IDEVID_CSR_BUILDER_INIT_FAILURE); @@ -302,32 +300,44 @@ impl InitDevIdLayer { let csr_bldr = result?; let csr_len = csr_bldr - .build(&mut csr) + .build(&mut csr_buf) .ok_or(CaliptraError::ROM_IDEVID_CSR_BUILDER_BUILD_FAILURE)?; - if csr_len > csr.len() { + if csr_len > csr_buf.len() { return Err(CaliptraError::ROM_IDEVID_CSR_OVERFLOW); } // [TODO] Generate MLDSA CSR. - cprintln!("[idev] CSR = {}", HexBytes(&csr[..csr_len])); + cprintln!("[idev] CSR = {}", HexBytes(&csr_buf[..csr_len])); report_boot_status(IDevIdMakeCsrComplete.into()); + let dev_id_csr = IdevIdCsr::new(&csr_buf, csr_len)?; + // Execute Send CSR Flow - let result = Self::send_csr(env, InitDevIdCsr::new(&csr, csr_len)); - csr.zeroize(); + let mut result = Self::send_csr(env, &dev_id_csr); + if result.is_ok() { + result = Self::write_csr_to_peristent_storage(env, &dev_id_csr); + } + csr_buf.zeroize(); result } + fn write_csr_to_peristent_storage(env: &mut RomEnv, csr: &IdevIdCsr) -> CaliptraResult<()> { + let csr_persistent_mem = &mut env.persistent_data.get_mut().idevid_csr; + *csr_persistent_mem = csr.clone(); + + Ok(()) + } + /// Send Initial Device ID CSR to SOC /// /// # Argument /// /// * `env` - ROM Environment /// * `csr` - Certificate Signing Request to send to SOC - fn send_csr(env: &mut RomEnv, csr: InitDevIdCsr) -> CaliptraResult<()> { + fn send_csr(env: &mut RomEnv, csr: &IdevIdCsr) -> CaliptraResult<()> { loop { // Create Mailbox send transaction to send the CSR if let Some(mut txn) = env.mbox.try_start_send_txn() { @@ -352,3 +362,14 @@ impl InitDevIdLayer { } } } + +#[cfg(test)] +mod tests { + use super::*; + use caliptra_drivers::memory_layout::IDEVID_CSR_SIZE; + + #[test] + fn verify_csr_fits_in_dccm() { + assert!(MAX_CSR_SIZE <= IDEVID_CSR_SIZE as usize); + } +} diff --git a/rom/dev/src/flow/cold_reset/x509.rs b/rom/dev/src/flow/cold_reset/x509.rs index aa5b4ecac6..e62dadfdda 100644 --- a/rom/dev/src/flow/cold_reset/x509.rs +++ b/rom/dev/src/flow/cold_reset/x509.rs @@ -16,29 +16,6 @@ use crate::cprintln; use crate::rom_env::RomEnv; use caliptra_drivers::*; -/// Wrapper to hold certificate buffer and length -pub struct Certificate<'a, const LEN: usize> { - buf: &'a [u8; LEN], - len: usize, -} - -impl<'a, const LEN: usize> Certificate<'a, LEN> { - /// Create an instance of `Certificate` - /// - /// # Arguments - /// - /// * `buf` - Buffer - /// * `len` - Buffer length - pub fn new(buf: &'a [u8; LEN], len: usize) -> Self { - Self { buf, len } - } - - /// Get the buffer - pub fn get(&self) -> Option<&[u8]> { - self.buf.get(..self.len) - } -} - /// X509 API pub enum X509 {} diff --git a/rom/dev/tests/rom_integration_tests/main.rs b/rom/dev/tests/rom_integration_tests/main.rs index 2cb2d0f87c..73e7b76021 100644 --- a/rom/dev/tests/rom_integration_tests/main.rs +++ b/rom/dev/tests/rom_integration_tests/main.rs @@ -21,3 +21,4 @@ mod test_update_reset; mod test_version; mod test_warm_reset; mod test_wdt_activation_and_stoppage; +mod tests_get_idev_csr; diff --git a/rom/dev/tests/rom_integration_tests/tests_get_idev_csr.rs b/rom/dev/tests/rom_integration_tests/tests_get_idev_csr.rs new file mode 100644 index 0000000000..3cb44d1d84 --- /dev/null +++ b/rom/dev/tests/rom_integration_tests/tests_get_idev_csr.rs @@ -0,0 +1,70 @@ +// Licensed under the Apache-2.0 license + +use caliptra_api::SocManager; +use caliptra_builder::ImageOptions; +use caliptra_common::mailbox_api::{CommandId, GetIdevIdCsrResp, MailboxReqHeader}; +use caliptra_drivers::MfgFlags; +use caliptra_error::CaliptraError; +use caliptra_hw_model::{Fuses, HwModel, ModelError}; +use zerocopy::{AsBytes, FromBytes}; + +use crate::helpers; + +#[test] +fn test_get_csr() { + let (mut hw, _) = + helpers::build_hw_model_and_image_bundle(Fuses::default(), ImageOptions::default()); + + let csr_bytes = { + let flags = MfgFlags::GENERATE_IDEVID_CSR; + hw.soc_ifc() + .cptra_dbg_manuf_service_reg() + .write(|_| flags.bits()); + + let downloaded = helpers::get_csr(&mut hw).unwrap(); + + hw.step_until(|m| m.soc_ifc().cptra_flow_status().read().ready_for_fw()); + downloaded + }; + + let payload = MailboxReqHeader { + chksum: caliptra_common::checksum::calc_checksum(u32::from(CommandId::GET_IDEV_CSR), &[]), + }; + + let response = hw + .mailbox_execute(CommandId::GET_IDEV_CSR.into(), payload.as_bytes()) + .unwrap() + .unwrap(); + + let get_idv_csr_resp = GetIdevIdCsrResp::read_from(response.as_bytes()).unwrap(); + + assert!(caliptra_common::checksum::verify_checksum( + get_idv_csr_resp.hdr.chksum, + 0x0, + &get_idv_csr_resp.as_bytes()[core::mem::size_of_val(&get_idv_csr_resp.hdr.chksum)..], + )); + + assert_eq!(csr_bytes.len() as u32, get_idv_csr_resp.data_size); + assert_eq!( + csr_bytes, + get_idv_csr_resp.data[..get_idv_csr_resp.data_size as usize] + ); +} + +#[test] +fn test_get_csr_generate_csr_flag_not_set() { + let (mut hw, _) = + helpers::build_hw_model_and_image_bundle(Fuses::default(), ImageOptions::default()); + hw.step_until(|m| m.soc_ifc().cptra_flow_status().read().ready_for_fw()); + + let payload = MailboxReqHeader { + chksum: caliptra_common::checksum::calc_checksum(u32::from(CommandId::GET_IDEV_CSR), &[]), + }; + + let response = hw.mailbox_execute(CommandId::GET_IDEV_CSR.into(), payload.as_bytes()); + + let expected_error = ModelError::MailboxCmdFailed( + CaliptraError::FW_PROC_MAILBOX_GET_IDEV_CSR_UNPROVISIONED_CSR.into(), + ); + assert_eq!(expected_error, response.unwrap_err()); +} diff --git a/runtime/README.md b/runtime/README.md index 51a65a4a98..d1b970062d 100644 --- a/runtime/README.md +++ b/runtime/README.md @@ -1532,6 +1532,33 @@ Command Code: `0x434D_5354` ("CMST") | total blocks | u32 | Total 16-byte blocks | +### GET\_IDEVID\_CSR + +Command Code: `0x4944_4352` ("IDCR") + +*Table: `GET_IDEVID_CSR` input arguments* + +| **Name** | **Type** | **Description** +| -------- | -------- | --------------- +| chksum | u32 | Checksum over other input arguments, computed by the caller. Little endian. | + +*Table: `GET_IDEVID_CSR` output arguments* +| **Name** | **Type** | **Description** +| -------- | -------- | --------------- +| chksum | u32 | Checksum over other output arguments, computed by Caliptra. Little endian. | +| data\_size | u32 | Length in bytes of the valid data in the data field. | +| data | u8[...] | DER-encoded IDevID certificate signing request. | + +The `mfg_flag_gen_idev_id_csr` manufacturing flag **MUST** have been set to generate a CSR. + +When called from ROM, if the CSR was not previously provisioned this command will return `FW_PROC_MAILBOX_UNPROVISIONED_CSR(0x0102000A)`. + +When called from runtime, if the CSR was not previously provisioned this command will return `RUNTIME_GET_IDEV_ID_UNPROVISIONED(0x000E0051)`. If the ROM did not support CSR generation, this command will return `RUNTIME_GET_IDEV_ID_UNSUPPORTED_ROM(0x000E0052)`. + + + +When the `mfg_flag_gen_idev_id_csr` flag has been set, the SoC **MUST** wait for the `flow_status_set_idevid_csr_ready` bit to be set by Caliptra. Once set, the SoC **MUST** clear the `mfg_flag_gen_idev_id_csr` flag for Caliptra to progress. + ## Checksum For every command except for FW_LOAD, the request and response feature a checksum. This diff --git a/runtime/src/get_idev_csr.rs b/runtime/src/get_idev_csr.rs new file mode 100644 index 0000000000..1ccd6374c2 --- /dev/null +++ b/runtime/src/get_idev_csr.rs @@ -0,0 +1,56 @@ +// Licensed under the Apache-2.0 license + +use crate::Drivers; + +use caliptra_cfi_derive_git::cfi_impl_fn; +use caliptra_cfi_lib_git::cfi_launder; + +use caliptra_common::{ + cprintln, + mailbox_api::{GetIdevIdCsrReq, GetIdevIdCsrResp, MailboxResp, MailboxRespHeader}, +}; +use caliptra_error::{CaliptraError, CaliptraResult}; + +use caliptra_drivers::IdevIdCsr; + +use zerocopy::{AsBytes, FromBytes}; + +pub struct GetIdevIdCsrCmd; +impl GetIdevIdCsrCmd { + #[cfg_attr(not(feature = "no-cfi"), cfi_impl_fn)] + #[inline(never)] + pub(crate) fn execute(drivers: &mut Drivers, cmd_args: &[u8]) -> CaliptraResult { + if let Some(cmd) = GetIdevIdCsrReq::read_from(cmd_args) { + let csr_persistent_mem = &drivers.persistent_data.get().idevid_csr; + + match csr_persistent_mem.get_csr_len() { + IdevIdCsr::UNPROVISIONED_CSR => { + Err(CaliptraError::RUNTIME_GET_IDEV_ID_UNPROVISIONED) + } + 0 => Err(CaliptraError::RUNTIME_GET_IDEV_ID_UNSUPPORTED_ROM), + len => { + let csr = csr_persistent_mem + .get() + .ok_or(CaliptraError::RUNTIME_GET_IDEV_ID_UNPROVISIONED)?; + + let mut resp = GetIdevIdCsrResp { + data_size: len, + ..Default::default() + }; + // NOTE: This code will not panic. + // + // csr is guranteed to be the same size as `len`, and therefore + // `resp.data_size` by the `IDevIDCsr::get` API. + // + // A valid `IDevIDCsr` cannot be larger than `MAX_CSR_SIZE`, which is the max + // size of the buffer in `GetIdevIdCsrResp` + resp.data[..resp.data_size as usize].copy_from_slice(csr); + + Ok(MailboxResp::GetIdevIdCsr(resp)) + } + } + } else { + Err(CaliptraError::RUNTIME_INSUFFICIENT_MEMORY) + } + } +} diff --git a/runtime/src/lib.rs b/runtime/src/lib.rs index dc15a6ef0d..995cf52b25 100644 --- a/runtime/src/lib.rs +++ b/runtime/src/lib.rs @@ -22,6 +22,7 @@ mod dpe_crypto; mod dpe_platform; mod drivers; pub mod fips; +mod get_idev_csr; pub mod handoff; mod hmac; pub mod info; @@ -57,6 +58,7 @@ pub use fips::FipsShutdownCmd; pub use fips::{fips_self_test_cmd, fips_self_test_cmd::SelfTestStatus}; pub use populate_idev::PopulateIDevIdCertCmd; +pub use get_idev_csr::GetIdevIdCsrCmd; pub use info::{FwInfoCmd, IDevIdInfoCmd}; pub use invoke_dpe::InvokeDpeCmd; pub use pcr::IncrementPcrResetCounterCmd; @@ -226,6 +228,7 @@ fn handle_command(drivers: &mut Drivers) -> CaliptraResult { CommandId::SHUTDOWN => FipsShutdownCmd::execute(drivers), CommandId::SET_AUTH_MANIFEST => SetAuthManifestCmd::execute(drivers, cmd_bytes), CommandId::AUTHORIZE_AND_STASH => AuthorizeAndStashCmd::execute(drivers, cmd_bytes), + CommandId::GET_IDEV_CSR => GetIdevIdCsrCmd::execute(drivers, cmd_bytes), _ => Err(CaliptraError::RUNTIME_UNIMPLEMENTED_COMMAND), }?; diff --git a/runtime/tests/runtime_integration_tests/common.rs b/runtime/tests/runtime_integration_tests/common.rs index d4c4022e71..eb7fce430a 100644 --- a/runtime/tests/runtime_integration_tests/common.rs +++ b/runtime/tests/runtime_integration_tests/common.rs @@ -9,6 +9,7 @@ use caliptra_common::mailbox_api::{ CommandId, GetFmcAliasCertResp, GetRtAliasCertResp, InvokeDpeReq, InvokeDpeResp, MailboxReq, MailboxReqHeader, }; +use caliptra_drivers::MfgFlags; use caliptra_error::CaliptraError; use caliptra_hw_model::{BootParams, DefaultHwModel, Fuses, HwModel, InitParams, ModelError}; use dpe::{ @@ -45,6 +46,7 @@ pub struct RuntimeTestArgs<'a> { pub test_fwid: Option<&'static FwId<'static>>, pub test_image_options: Option, pub init_params: Option>, + pub test_mfg_flags: Option, } pub fn run_rt_test_lms(args: RuntimeTestArgs, lms_verify: bool) -> DefaultHwModel { @@ -75,6 +77,12 @@ pub fn run_rt_test_lms(args: RuntimeTestArgs, lms_verify: bool) -> DefaultHwMode let image = caliptra_builder::build_and_sign_image(&FMC_WITH_UART, runtime_fwid, image_options) .unwrap(); + let boot_flags = if let Some(flags) = args.test_mfg_flags { + flags.bits() + } else { + 0 + }; + let mut model = caliptra_hw_model::new( init_params, BootParams { @@ -83,6 +91,7 @@ pub fn run_rt_test_lms(args: RuntimeTestArgs, lms_verify: bool) -> DefaultHwMode lms_verify, ..Default::default() }, + initial_dbg_manuf_service_reg: boot_flags, ..Default::default() }, ) diff --git a/runtime/tests/runtime_integration_tests/main.rs b/runtime/tests/runtime_integration_tests/main.rs index fb62673997..417946cda3 100644 --- a/runtime/tests/runtime_integration_tests/main.rs +++ b/runtime/tests/runtime_integration_tests/main.rs @@ -8,6 +8,7 @@ mod test_certs; mod test_disable; mod test_ecdsa; mod test_fips; +mod test_get_idev_csr; mod test_info; mod test_invoke_dpe; mod test_lms; diff --git a/runtime/tests/runtime_integration_tests/test_get_idev_csr.rs b/runtime/tests/runtime_integration_tests/test_get_idev_csr.rs new file mode 100644 index 0000000000..6e072f097f --- /dev/null +++ b/runtime/tests/runtime_integration_tests/test_get_idev_csr.rs @@ -0,0 +1,63 @@ +// Licensed under the Apache-2.0 license + +use caliptra_api::SocManager; +use caliptra_common::mailbox_api::{CommandId, GetIdevIdCsrResp, MailboxReqHeader}; +use caliptra_drivers::{IdevIdCsr, MfgFlags}; +use caliptra_error::CaliptraError; +use caliptra_hw_model::{HwModel, ModelError}; +use caliptra_runtime::RtBootStatus; +use openssl::x509::X509Req; +use zerocopy::{AsBytes, FromBytes}; + +use crate::common::{run_rt_test, RuntimeTestArgs}; + +#[test] +fn test_get_csr() { + // `run_rt_test` is responsibly for clearing the CSR bit. + // Caliptra will wait until the CSR bit is cleared during startup. + let args = RuntimeTestArgs { + test_mfg_flags: Some(MfgFlags::GENERATE_IDEVID_CSR), + ..Default::default() + }; + let mut model = run_rt_test(args); + + let payload = MailboxReqHeader { + chksum: caliptra_common::checksum::calc_checksum(u32::from(CommandId::GET_IDEV_CSR), &[]), + }; + + let response = model + .mailbox_execute(CommandId::GET_IDEV_CSR.into(), payload.as_bytes()) + .unwrap() + .unwrap(); + + let get_idv_csr_resp = GetIdevIdCsrResp::read_from(response.as_bytes()).unwrap(); + + assert_ne!(IdevIdCsr::UNPROVISIONED_CSR, get_idv_csr_resp.data_size); + assert_ne!(0, get_idv_csr_resp.data_size); + + let csr_bytes = &get_idv_csr_resp.data[..get_idv_csr_resp.data_size as usize]; + assert_ne!([0; 512], csr_bytes); + + assert!(X509Req::from_der(csr_bytes).is_ok()); +} + +#[test] +fn test_missing_csr() { + let mut model = run_rt_test(RuntimeTestArgs::default()); + + model.step_until(|m| { + m.soc_ifc().cptra_boot_status().read() == u32::from(RtBootStatus::RtReadyForCommands) + }); + + let payload = MailboxReqHeader { + chksum: caliptra_common::checksum::calc_checksum(u32::from(CommandId::GET_IDEV_CSR), &[]), + }; + + let response = model + .mailbox_execute(CommandId::GET_IDEV_CSR.into(), payload.as_bytes()) + .unwrap_err(); + assert_eq!( + response, + ModelError::MailboxCmdFailed(CaliptraError::RUNTIME_GET_IDEV_ID_UNPROVISIONED.into()) + ); +} From 5b205d39c2030a3b136bfcda7985773f9f3be58e Mon Sep 17 00:00:00 2001 From: Carl Lundin Date: Wed, 6 Nov 2024 17:41:16 -0800 Subject: [PATCH 14/51] Inline execute methods. (cherry picked from commit 7ba955c8d5d711f732daa65e227304ca7c32c52b) --- common/src/fips.rs | 1 + runtime/src/capabilities.rs | 1 + runtime/src/certify_key_extended.rs | 1 + runtime/src/dice.rs | 4 ++++ runtime/src/fips.rs | 1 + runtime/src/info.rs | 2 ++ runtime/src/invoke_dpe.rs | 1 + runtime/src/pcr.rs | 3 +++ runtime/src/populate_idev.rs | 1 + runtime/src/subject_alt_name.rs | 1 + runtime/src/tagging.rs | 1 + runtime/src/verify.rs | 2 ++ 12 files changed, 19 insertions(+) diff --git a/common/src/fips.rs b/common/src/fips.rs index 6b07e52726..d295a7ab0b 100644 --- a/common/src/fips.rs +++ b/common/src/fips.rs @@ -10,6 +10,7 @@ impl FipsVersionCmd { pub const NAME: [u8; 12] = *b"Caliptra RTM"; pub const MODE: u32 = 0x46495053; + #[cfg_attr(feature = "runtime", inline(never))] pub fn execute(soc_ifc: &SocIfc) -> CaliptraResult { cprintln!("[rt] FIPS Version"); diff --git a/runtime/src/capabilities.rs b/runtime/src/capabilities.rs index 9ff9cf1b85..0759fd21a4 100644 --- a/runtime/src/capabilities.rs +++ b/runtime/src/capabilities.rs @@ -20,6 +20,7 @@ use caliptra_error::CaliptraResult; pub struct CapabilitiesCmd; impl CapabilitiesCmd { + #[inline(never)] pub(crate) fn execute() -> CaliptraResult { let mut capabilities = Capabilities::default(); capabilities |= Capabilities::RT_BASE; diff --git a/runtime/src/certify_key_extended.rs b/runtime/src/certify_key_extended.rs index 77968ca7a4..0e806131e8 100644 --- a/runtime/src/certify_key_extended.rs +++ b/runtime/src/certify_key_extended.rs @@ -34,6 +34,7 @@ use crate::{ pub struct CertifyKeyExtendedCmd; impl CertifyKeyExtendedCmd { + #[inline(never)] pub(crate) fn execute(drivers: &mut Drivers, cmd_args: &[u8]) -> CaliptraResult { let cmd = CertifyKeyExtendedReq::read_from(cmd_args) .ok_or(CaliptraError::RUNTIME_INSUFFICIENT_MEMORY)?; diff --git a/runtime/src/dice.rs b/runtime/src/dice.rs index a8eb178b48..cca1659125 100644 --- a/runtime/src/dice.rs +++ b/runtime/src/dice.rs @@ -28,6 +28,7 @@ use zerocopy::AsBytes; pub struct IDevIdCertCmd; impl IDevIdCertCmd { + #[inline(never)] pub(crate) fn execute(cmd_args: &[u8]) -> CaliptraResult { if cmd_args.len() <= core::mem::size_of::() { let mut cmd = GetIdevCertReq::default(); @@ -65,6 +66,7 @@ impl IDevIdCertCmd { pub struct GetLdevCertCmd; impl GetLdevCertCmd { + #[inline(never)] pub(crate) fn execute(drivers: &mut Drivers) -> CaliptraResult { let mut resp = GetLdevCertResp::default(); @@ -80,6 +82,7 @@ impl GetLdevCertCmd { pub struct GetFmcAliasCertCmd; impl GetFmcAliasCertCmd { + #[inline(never)] pub(crate) fn execute(drivers: &mut Drivers) -> CaliptraResult { let mut resp = GetFmcAliasCertResp::default(); @@ -95,6 +98,7 @@ impl GetFmcAliasCertCmd { pub struct GetRtAliasCertCmd; impl GetRtAliasCertCmd { + #[inline(never)] pub(crate) fn execute(drivers: &mut Drivers) -> CaliptraResult { let mut resp = GetRtAliasCertResp::default(); diff --git a/runtime/src/fips.rs b/runtime/src/fips.rs index 3dace80355..6a5a068dcb 100644 --- a/runtime/src/fips.rs +++ b/runtime/src/fips.rs @@ -212,6 +212,7 @@ pub mod fips_self_test_cmd { pub struct FipsShutdownCmd; impl FipsShutdownCmd { #[cfg_attr(not(feature = "no-cfi"), cfi_impl_fn)] + #[inline(never)] pub(crate) fn execute(env: &mut Drivers) -> CaliptraResult { FipsModule::zeroize(env); env.is_shutdown = true; diff --git a/runtime/src/info.rs b/runtime/src/info.rs index e5d5c51f93..4bcf205bb2 100644 --- a/runtime/src/info.rs +++ b/runtime/src/info.rs @@ -19,6 +19,7 @@ use caliptra_image_types::RomInfo; pub struct FwInfoCmd; impl FwInfoCmd { + #[inline(never)] pub(crate) fn execute(drivers: &Drivers) -> CaliptraResult { let pdata = drivers.persistent_data.get(); @@ -51,6 +52,7 @@ impl FwInfoCmd { pub struct IDevIdInfoCmd; impl IDevIdInfoCmd { + #[inline(never)] pub(crate) fn execute(drivers: &Drivers) -> CaliptraResult { let pdata = drivers.persistent_data.get(); let pub_key = pdata.fht.idev_dice_ecdsa_pub_key; diff --git a/runtime/src/invoke_dpe.rs b/runtime/src/invoke_dpe.rs index d46a33d0cf..4a731e16ca 100644 --- a/runtime/src/invoke_dpe.rs +++ b/runtime/src/invoke_dpe.rs @@ -32,6 +32,7 @@ use zerocopy::{AsBytes, FromBytes}; pub struct InvokeDpeCmd; impl InvokeDpeCmd { #[cfg_attr(not(feature = "no-cfi"), cfi_impl_fn)] + #[inline(never)] pub(crate) fn execute(drivers: &mut Drivers, cmd_args: &[u8]) -> CaliptraResult { if cmd_args.len() <= core::mem::size_of::() { let mut cmd = InvokeDpeReq::default(); diff --git a/runtime/src/pcr.rs b/runtime/src/pcr.rs index e6cfdda124..1cbd1a1875 100644 --- a/runtime/src/pcr.rs +++ b/runtime/src/pcr.rs @@ -24,6 +24,7 @@ use zerocopy::FromBytes; pub struct IncrementPcrResetCounterCmd; impl IncrementPcrResetCounterCmd { #[cfg_attr(not(feature = "no-cfi"), cfi_impl_fn)] + #[inline(never)] pub(crate) fn execute(drivers: &mut Drivers, cmd_args: &[u8]) -> CaliptraResult { let cmd = IncrementPcrResetCounterReq::read_from(cmd_args) .ok_or(CaliptraError::RUNTIME_INSUFFICIENT_MEMORY)?; @@ -45,6 +46,7 @@ impl IncrementPcrResetCounterCmd { pub struct GetPcrQuoteCmd; impl GetPcrQuoteCmd { #[cfg_attr(not(feature = "no-cfi"), cfi_impl_fn)] + #[inline(never)] pub(crate) fn execute(drivers: &mut Drivers, cmd_bytes: &[u8]) -> CaliptraResult { let args: QuotePcrsReq = QuotePcrsReq::read_from(cmd_bytes) .ok_or(CaliptraError::RUNTIME_MAILBOX_INVALID_PARAMS)?; @@ -73,6 +75,7 @@ impl GetPcrQuoteCmd { pub struct ExtendPcrCmd; impl ExtendPcrCmd { #[cfg_attr(not(feature = "no-cfi"), cfi_impl_fn)] + #[inline(never)] pub(crate) fn execute(drivers: &mut Drivers, cmd_args: &[u8]) -> CaliptraResult { let cmd = ExtendPcrReq::read_from(cmd_args).ok_or(CaliptraError::RUNTIME_INSUFFICIENT_MEMORY)?; diff --git a/runtime/src/populate_idev.rs b/runtime/src/populate_idev.rs index 509fb19389..7c397ce3aa 100644 --- a/runtime/src/populate_idev.rs +++ b/runtime/src/populate_idev.rs @@ -21,6 +21,7 @@ use crate::{Drivers, MAX_CERT_CHAIN_SIZE, PL0_PAUSER_FLAG}; pub struct PopulateIDevIdCertCmd; impl PopulateIDevIdCertCmd { + #[inline(never)] pub(crate) fn execute(drivers: &mut Drivers, cmd_args: &[u8]) -> CaliptraResult { if cmd_args.len() <= core::mem::size_of::() { let mut cmd = PopulateIdevCertReq::default(); diff --git a/runtime/src/subject_alt_name.rs b/runtime/src/subject_alt_name.rs index cc9b7cc8ad..68166d09f8 100644 --- a/runtime/src/subject_alt_name.rs +++ b/runtime/src/subject_alt_name.rs @@ -27,6 +27,7 @@ impl AddSubjectAltNameCmd { pub const DMTF_OID: &'static [u8] = &[0x2B, 0x06, 0x01, 0x04, 0x01, 0x83, 0x1C, 0x82, 0x12, 0x01]; + #[inline(never)] pub(crate) fn execute(drivers: &mut Drivers, cmd_args: &[u8]) -> CaliptraResult { if cmd_args.len() <= core::mem::size_of::() { let mut cmd = AddSubjectAltNameReq::default(); diff --git a/runtime/src/tagging.rs b/runtime/src/tagging.rs index f00ef0ef5c..63539a0b8c 100644 --- a/runtime/src/tagging.rs +++ b/runtime/src/tagging.rs @@ -31,6 +31,7 @@ use crate::{dpe_crypto::DpeCrypto, CptraDpeTypes, DpePlatform, Drivers}; pub struct TagTciCmd; impl TagTciCmd { #[cfg_attr(not(feature = "no-cfi"), cfi_impl_fn)] + #[inline(never)] pub(crate) fn execute(drivers: &mut Drivers, cmd_args: &[u8]) -> CaliptraResult { let cmd = TagTciReq::read_from(cmd_args).ok_or(CaliptraError::RUNTIME_INSUFFICIENT_MEMORY)?; diff --git a/runtime/src/verify.rs b/runtime/src/verify.rs index bb434d9e78..3ac5350f26 100644 --- a/runtime/src/verify.rs +++ b/runtime/src/verify.rs @@ -28,6 +28,7 @@ use zerocopy::{BigEndian, FromBytes, LittleEndian, U32}; pub struct EcdsaVerifyCmd; impl EcdsaVerifyCmd { #[cfg_attr(not(feature = "no-cfi"), cfi_impl_fn)] + #[inline(never)] pub(crate) fn execute(drivers: &mut Drivers, cmd_args: &[u8]) -> CaliptraResult { let cmd = EcdsaVerifyReq::read_from(cmd_args) .ok_or(CaliptraError::RUNTIME_INSUFFICIENT_MEMORY)?; @@ -60,6 +61,7 @@ impl EcdsaVerifyCmd { pub struct LmsVerifyCmd; impl LmsVerifyCmd { #[cfg_attr(not(feature = "no-cfi"), cfi_impl_fn)] + #[inline(never)] pub(crate) fn execute(drivers: &mut Drivers, cmd_args: &[u8]) -> CaliptraResult { // Re-run LMS KAT once (since LMS is more SW-based than other crypto) if let Err(e) = From 437640dcfc8b6d262afd80dbac3048609e795fb6 Mon Sep 17 00:00:00 2001 From: leongross Date: Fri, 8 Nov 2024 14:41:10 +0100 Subject: [PATCH 15/51] add dummy workflow for building ROM release from versioned git ref (#1604,#1691) Signed-off-by: leongross (cherry picked from commit a52cdb14637d2b9a446b419e5e6c58b6fcc1991e) --- .../workflows/versioned-full-build-test.yml | 59 +++++++++++++++++++ 1 file changed, 59 insertions(+) create mode 100644 .github/workflows/versioned-full-build-test.yml diff --git a/.github/workflows/versioned-full-build-test.yml b/.github/workflows/versioned-full-build-test.yml new file mode 100644 index 0000000000..31557aa382 --- /dev/null +++ b/.github/workflows/versioned-full-build-test.yml @@ -0,0 +1,59 @@ +name: Versioned Build Test + +on: + workflow_dispatch: + inputs: + hw-version: + default: "latest" + type: string + rom-ref: + default: "main" + type: string + firmware-version: + default: "main" + type: string + + pull_request: + inputs: + todo-remove-before-merging: + default: "" + type: string + hw-version: + default: "latest" + type: string + rom-ref: + default: "main" + type: string + firmware-version: + default: "main" + type: string + +jobs: + fpga-full-suite-etrng-log: + name: FPGA Suite (etrng, log) + + fpga-full-suite-etrng-nolog: + name: FPGA Suite (etrng, nolog) + + fpga-full-suite-itrng-log: + name: FPGA Suite (itrng, log) + + fpga-full-suite-itrng-nolog: + name: FPGA Suite (itrng, nolog) + + sw-emulator-full-suite-etrng-log: + name: sw-emulator Suite (etrng, log) + + sw-emulator-full-suite-etrng-nolog: + name: sw-emulator Suite (etrng, nolog) + + sw-emulator-full-suite-itrng-log: + name: sw-emulator Suite (itrng, log) + + sw-emulator-full-suite-itrng-nolog: + name: sw-emulator Suite (itrng, nolog) + + build-release: + runs-on: ubuntu-22.04 + permissions: + contents: write From 09250f823dd09f1d3835072f5ec8567ce885f8d8 Mon Sep 17 00:00:00 2001 From: Carl Lundin Date: Fri, 8 Nov 2024 15:28:02 -0800 Subject: [PATCH 16/51] Don't copy manifest2 onto the stack (cherry picked from commit adeff0c917721b875ecf7f8b36aebe21e199de20) --- FROZEN_IMAGES.sha384sum | 4 ++-- rom/dev/src/flow/update_reset.rs | 14 +++++++++----- 2 files changed, 11 insertions(+), 7 deletions(-) diff --git a/FROZEN_IMAGES.sha384sum b/FROZEN_IMAGES.sha384sum index d5bb5388ab..778b1b47ce 100644 --- a/FROZEN_IMAGES.sha384sum +++ b/FROZEN_IMAGES.sha384sum @@ -1,3 +1,3 @@ # WARNING: Do not update this file without the approval of the Caliptra TAC -fc4ceed3891771c263c42eb56bdfff3026e1baf75e48b09bad58aaf562aea1a31f5df6636ac90f3aab73d533f03f0e5d caliptra-rom-no-log.bin -e6254e3492969108c1340b2f662d82ab72572f38fab970990c72bdb03f0bfbfd18f6a16a5f273df8fd0faf5aefe9c138 caliptra-rom-with-log.bin +133bf3969893178e041b61001d75bfb504be3b3676cac608a40877f1e4b46b4855f86c1859cfc3e22745327102fba4b0 caliptra-rom-no-log.bin +44f5bbbc4b71d7f0926f85b7d81ef7e17f721557b38379b650497eb8dd19d0a74ab5a1e2177c7e99653a878d2daed3b3 caliptra-rom-with-log.bin diff --git a/rom/dev/src/flow/update_reset.rs b/rom/dev/src/flow/update_reset.rs index 5ae975878e..06269bbf36 100644 --- a/rom/dev/src/flow/update_reset.rs +++ b/rom/dev/src/flow/update_reset.rs @@ -62,7 +62,7 @@ impl UpdateResetFlow { return Err(CaliptraError::ROM_UPDATE_RESET_FLOW_INVALID_FIRMWARE_COMMAND); } - let manifest = Self::load_manifest(env.persistent_data.get_mut(), &mut recv_txn)?; + Self::load_manifest(env.persistent_data.get_mut(), &mut recv_txn)?; report_boot_status(UpdateResetLoadManifestComplete.into()); let mut venv = FirmwareImageVerificationEnv { @@ -75,7 +75,10 @@ impl UpdateResetFlow { image: recv_txn.raw_mailbox_contents(), }; - let info = Self::verify_image(&mut venv, &manifest, recv_txn.dlen()); + let info = { + let manifest = &env.persistent_data.get().manifest2; + Self::verify_image(&mut venv, manifest, recv_txn.dlen()) + }; let info = okref(&info)?; report_boot_status(UpdateResetImageVerificationComplete.into()); @@ -91,7 +94,8 @@ impl UpdateResetFlow { info.vendor_ecc_pub_key_idx ); - Self::load_image(&manifest, &mut recv_txn)?; + let manifest = &env.persistent_data.get().manifest2; + Self::load_image(manifest, &mut recv_txn)?; Ok(()) }; if let Err(e) = process_txn() { @@ -197,9 +201,9 @@ impl UpdateResetFlow { fn load_manifest( persistent_data: &mut PersistentData, txn: &mut MailboxRecvTxn, - ) -> CaliptraResult { + ) -> CaliptraResult<()> { txn.copy_request(persistent_data.manifest2.as_bytes_mut())?; - Ok(persistent_data.manifest2) + Ok(()) } /// Populate data vault From e7a2b41665d57c51d56b6c6f0985b575b3dcb8c1 Mon Sep 17 00:00:00 2001 From: Arthur Heymans Date: Wed, 13 Nov 2024 23:40:52 +0100 Subject: [PATCH 17/51] Test 'authorize_and_stash' more extensively (#1772) This adds: - A check on stash on both failing and succeeding paths - A succeeding path test Signed-off-by: Arthur Heymans (cherry picked from commit b5514212025468ecc3eaf5ddc89280bb6f1bd551) --- .../test_authorize_and_stash.rs | 137 ++++++++++++++++-- .../test_set_auth_manifest.rs | 16 +- 2 files changed, 133 insertions(+), 20 deletions(-) diff --git a/runtime/tests/runtime_integration_tests/test_authorize_and_stash.rs b/runtime/tests/runtime_integration_tests/test_authorize_and_stash.rs index 91e5b633d7..588c440656 100644 --- a/runtime/tests/runtime_integration_tests/test_authorize_and_stash.rs +++ b/runtime/tests/runtime_integration_tests/test_authorize_and_stash.rs @@ -1,16 +1,29 @@ // Licensed under the Apache-2.0 license use crate::common::{run_rt_test, RuntimeTestArgs}; +use crate::test_set_auth_manifest::test_auth_manifest; use caliptra_api::SocManager; +use caliptra_builder::{ + firmware::{self, FMC_WITH_UART}, + ImageOptions, +}; use caliptra_common::mailbox_api::{ AuthorizeAndStashReq, AuthorizeAndStashResp, CommandId, ImageHashSource, MailboxReq, - MailboxReqHeader, + MailboxReqHeader, SetAuthManifestReq, }; use caliptra_hw_model::HwModel; use caliptra_runtime::RtBootStatus; -use caliptra_runtime::DENY_IMAGE_AUTHORIZATION; +use caliptra_runtime::{AUTHORIZE_IMAGE, DENY_IMAGE_AUTHORIZATION}; +use sha2::{Digest, Sha384}; +use zerocopy::AsBytes; use zerocopy::FromBytes; +pub const IMAGE_DIGEST1: [u8; 48] = [ + 0x38, 0xB0, 0x60, 0xA7, 0x51, 0xAC, 0x96, 0x38, 0x4C, 0xD9, 0x32, 0x7E, 0xB1, 0xB1, 0xE3, 0x6A, + 0x21, 0xFD, 0xB7, 0x11, 0x14, 0xBE, 0x07, 0x43, 0x4C, 0x0C, 0xC7, 0xBF, 0x63, 0xF6, 0xE1, 0xDA, + 0x27, 0x4E, 0xDE, 0xBF, 0xE7, 0x6F, 0x65, 0xFB, 0xD5, 0x1A, 0xD2, 0xF1, 0x48, 0x98, 0xB9, 0x5B, +]; + #[test] fn test_authorize_and_stash_cmd_deny_authorization() { let mut model = run_rt_test(RuntimeTestArgs::default()); @@ -19,17 +32,11 @@ fn test_authorize_and_stash_cmd_deny_authorization() { m.soc_ifc().cptra_boot_status().read() == u32::from(RtBootStatus::RtReadyForCommands) }); - let image_digest1: [u8; 48] = [ - 0x38, 0xB0, 0x60, 0xA7, 0x51, 0xAC, 0x96, 0x38, 0x4C, 0xD9, 0x32, 0x7E, 0xB1, 0xB1, 0xE3, - 0x6A, 0x21, 0xFD, 0xB7, 0x11, 0x14, 0xBE, 0x07, 0x43, 0x4C, 0x0C, 0xC7, 0xBF, 0x63, 0xF6, - 0xE1, 0xDA, 0x27, 0x4E, 0xDE, 0xBF, 0xE7, 0x6F, 0x65, 0xFB, 0xD5, 0x1A, 0xD2, 0xF1, 0x48, - 0x98, 0xB9, 0x5B, - ]; - let mut authorize_and_stash_cmd = MailboxReq::AuthorizeAndStash(AuthorizeAndStashReq { hdr: MailboxReqHeader { chksum: 0 }, - measurement: image_digest1, + measurement: IMAGE_DIGEST1, source: ImageHashSource::InRequest as u32, + flags: 0, // Don't skip stash ..Default::default() }); authorize_and_stash_cmd.populate_chksum().unwrap(); @@ -47,4 +54,114 @@ fn test_authorize_and_stash_cmd_deny_authorization() { authorize_and_stash_resp.auth_req_result, DENY_IMAGE_AUTHORIZATION ); + + // create a new fw image with the runtime replaced by the mbox responder + let updated_fw_image = caliptra_builder::build_and_sign_image( + &FMC_WITH_UART, + &firmware::runtime_tests::MBOX, + ImageOptions::default(), + ) + .unwrap() + .to_bytes() + .unwrap(); + + // trigger an update reset so we can use commands in mbox responder + model + .mailbox_execute(u32::from(CommandId::FIRMWARE_LOAD), &updated_fw_image) + .unwrap(); + + let rt_journey_pcr_resp = model.mailbox_execute(0x1000_0000, &[]).unwrap().unwrap(); + let rt_journey_pcr: [u8; 48] = rt_journey_pcr_resp.as_bytes().try_into().unwrap(); + + let valid_pauser_hash_resp = model.mailbox_execute(0x2000_0000, &[]).unwrap().unwrap(); + let valid_pauser_hash: [u8; 48] = valid_pauser_hash_resp.as_bytes().try_into().unwrap(); + + // We don't expect the image_digest to be part of the stash + let mut hasher = Sha384::new(); + hasher.update(rt_journey_pcr); + hasher.update(valid_pauser_hash); + let expected_measurement_hash = hasher.finalize(); + + let dpe_measurement_hash = model.mailbox_execute(0x3000_0000, &[]).unwrap().unwrap(); + assert_eq!(expected_measurement_hash.as_bytes(), dpe_measurement_hash); +} + +#[test] +fn test_authorize_and_stash_cmd_succes() { + let mut model = run_rt_test(RuntimeTestArgs::default()); + + model.step_until(|m| { + m.soc_ifc().cptra_boot_status().read() == u32::from(RtBootStatus::RtReadyForCommands) + }); + + let auth_manifest = test_auth_manifest(); + let buf = auth_manifest.as_bytes(); + let mut auth_manifest_slice = [0u8; SetAuthManifestReq::MAX_MAN_SIZE]; + auth_manifest_slice[..buf.len()].copy_from_slice(buf); + + let mut set_auth_manifest_cmd = MailboxReq::SetAuthManifest(SetAuthManifestReq { + hdr: MailboxReqHeader { chksum: 0 }, + manifest_size: buf.len() as u32, + manifest: auth_manifest_slice, + }); + set_auth_manifest_cmd.populate_chksum().unwrap(); + + model + .mailbox_execute( + u32::from(CommandId::SET_AUTH_MANIFEST), + set_auth_manifest_cmd.as_bytes().unwrap(), + ) + .unwrap() + .expect("We should have received a response"); + + let mut authorize_and_stash_cmd = MailboxReq::AuthorizeAndStash(AuthorizeAndStashReq { + hdr: MailboxReqHeader { chksum: 0 }, + measurement: IMAGE_DIGEST1, + source: ImageHashSource::InRequest as u32, + flags: 0, // Don't skip stash + ..Default::default() + }); + authorize_and_stash_cmd.populate_chksum().unwrap(); + + let resp = model + .mailbox_execute( + u32::from(CommandId::AUTHORIZE_AND_STASH), + authorize_and_stash_cmd.as_bytes().unwrap(), + ) + .unwrap() + .expect("We should have received a response"); + + let authorize_and_stash_resp = AuthorizeAndStashResp::read_from(resp.as_slice()).unwrap(); + assert_eq!(authorize_and_stash_resp.auth_req_result, AUTHORIZE_IMAGE); + + // create a new fw image with the runtime replaced by the mbox responder + let updated_fw_image = caliptra_builder::build_and_sign_image( + &FMC_WITH_UART, + &firmware::runtime_tests::MBOX, + ImageOptions::default(), + ) + .unwrap() + .to_bytes() + .unwrap(); + + // trigger an update reset so we can use commands in mbox responder + model + .mailbox_execute(u32::from(CommandId::FIRMWARE_LOAD), &updated_fw_image) + .unwrap(); + + let rt_journey_pcr_resp = model.mailbox_execute(0x1000_0000, &[]).unwrap().unwrap(); + let rt_journey_pcr: [u8; 48] = rt_journey_pcr_resp.as_bytes().try_into().unwrap(); + + let valid_pauser_hash_resp = model.mailbox_execute(0x2000_0000, &[]).unwrap().unwrap(); + let valid_pauser_hash: [u8; 48] = valid_pauser_hash_resp.as_bytes().try_into().unwrap(); + + // hash expected DPE measurements in order to check that stashed measurement was added to DPE + let mut hasher = Sha384::new(); + hasher.update(rt_journey_pcr); + hasher.update(valid_pauser_hash); + hasher.update(IMAGE_DIGEST1); + let expected_measurement_hash = hasher.finalize(); + + let dpe_measurement_hash = model.mailbox_execute(0x3000_0000, &[]).unwrap().unwrap(); + assert_eq!(expected_measurement_hash.as_bytes(), dpe_measurement_hash); } diff --git a/runtime/tests/runtime_integration_tests/test_set_auth_manifest.rs b/runtime/tests/runtime_integration_tests/test_set_auth_manifest.rs index d15ba3314a..e4db31a51b 100644 --- a/runtime/tests/runtime_integration_tests/test_set_auth_manifest.rs +++ b/runtime/tests/runtime_integration_tests/test_set_auth_manifest.rs @@ -1,6 +1,9 @@ // Licensed under the Apache-2.0 license -use crate::common::{assert_error, run_rt_test_lms, RuntimeTestArgs}; +use crate::{ + common::{assert_error, run_rt_test_lms, RuntimeTestArgs}, + test_authorize_and_stash::IMAGE_DIGEST1, +}; use caliptra_api::SocManager; use caliptra_auth_man_gen::{ AuthManifestGenerator, AuthManifestGeneratorConfig, AuthManifestGeneratorKeyConfig, @@ -17,7 +20,7 @@ use caliptra_image_fake_keys::*; use caliptra_runtime::RtBootStatus; use zerocopy::AsBytes; -fn test_auth_manifest() -> AuthorizationManifest { +pub fn test_auth_manifest() -> AuthorizationManifest { let vendor_fw_key_info: AuthManifestGeneratorKeyConfig = AuthManifestGeneratorKeyConfig { pub_keys: AuthManifestPubKeys { ecc_pub_key: VENDOR_ECC_KEY_0_PUBLIC, @@ -64,13 +67,6 @@ fn test_auth_manifest() -> AuthorizationManifest { }), }); - let image_digest1: [u8; 48] = [ - 0x38, 0xB0, 0x60, 0xA7, 0x51, 0xAC, 0x96, 0x38, 0x4C, 0xD9, 0x32, 0x7E, 0xB1, 0xB1, 0xE3, - 0x6A, 0x21, 0xFD, 0xB7, 0x11, 0x14, 0xBE, 0x07, 0x43, 0x4C, 0x0C, 0xC7, 0xBF, 0x63, 0xF6, - 0xE1, 0xDA, 0x27, 0x4E, 0xDE, 0xBF, 0xE7, 0x6F, 0x65, 0xFB, 0xD5, 0x1A, 0xD2, 0xF1, 0x48, - 0x98, 0xB9, 0x5B, - ]; - let image_digest2: [u8; 48] = [ 0xCB, 0x00, 0x75, 0x3F, 0x45, 0xA3, 0x5E, 0x8B, 0xB5, 0xA0, 0x3D, 0x69, 0x9A, 0xC6, 0x50, 0x07, 0x27, 0x2C, 0x32, 0xAB, 0x0E, 0xDE, 0xD1, 0x63, 0x1A, 0x8B, 0x60, 0x5A, 0x43, 0xFF, @@ -82,7 +78,7 @@ fn test_auth_manifest() -> AuthorizationManifest { let image_metadata_list: Vec = vec![ AuthManifestImageMetadata { image_source: 0, - digest: image_digest1, + digest: IMAGE_DIGEST1, }, AuthManifestImageMetadata { image_source: 1, From da5e5d9311523538ef9e1602edc36ec8022dfe98 Mon Sep 17 00:00:00 2001 From: Carl Lundin Date: Wed, 13 Nov 2024 10:21:29 -0800 Subject: [PATCH 18/51] Add GetIdevCsr to libcaliptra. (cherry picked from commit 73bdc9672c79d078785c8d2df41d97e7bec30936) --- libcaliptra/examples/generic/test.c | 22 ++++++++++++++++++++++ libcaliptra/inc/caliptra_api.h | 3 +++ libcaliptra/inc/caliptra_types.h | 6 ++++++ libcaliptra/src/caliptra_api.c | 15 +++++++++++++++ libcaliptra/src/caliptra_mbox.h | 1 + 5 files changed, 47 insertions(+) diff --git a/libcaliptra/examples/generic/test.c b/libcaliptra/examples/generic/test.c index eff16cc277..c41053a419 100644 --- a/libcaliptra/examples/generic/test.c +++ b/libcaliptra/examples/generic/test.c @@ -664,6 +664,28 @@ int rom_test_devid_csr(const test_info* info) printf("IDEV CSR matches\n"); } + caliptra_req_idev_csr_complete(); + caliptra_ready_for_firmware(); + + // Test Get Idev CSR now that a CSR is provisioned. + // GET IDEV CSR + struct caliptra_get_idev_csr_resp csr_resp = {0}; + + status = caliptra_get_idev_csr(&csr_resp, false); + + if (status) { + printf("Get IDev CSR failed: 0x%x\n", status); + dump_caliptra_error_codes(); + failure = 1; + } else { + if (memcmp(csr_resp.data, idev_csr_bytes, csr_resp.data_size) != 0) { + printf("IDEV CSR does not match\n"); + failure = 1; + } else { + printf("Get IDev CSR: OK\n"); + } + } + free((void*)caliptra_idevid_csr_buf.data); return failure; } diff --git a/libcaliptra/inc/caliptra_api.h b/libcaliptra/inc/caliptra_api.h index a5fbeefd68..8992dad882 100644 --- a/libcaliptra/inc/caliptra_api.h +++ b/libcaliptra/inc/caliptra_api.h @@ -180,6 +180,9 @@ int caliptra_certify_key_extended(struct caliptra_certify_key_extended_req *req, // FIPS version int caliptra_fips_version(struct caliptra_fips_version_resp *resp, bool async); +// Get IDev CSR +int caliptra_get_idev_csr(struct caliptra_get_idev_csr_resp *resp, bool async); + // Self test start int caliptra_self_test_start(bool async); diff --git a/libcaliptra/inc/caliptra_types.h b/libcaliptra/inc/caliptra_types.h index 165b27348a..9058f50bd7 100644 --- a/libcaliptra/inc/caliptra_types.h +++ b/libcaliptra/inc/caliptra_types.h @@ -218,6 +218,12 @@ struct caliptra_capabilities_resp { uint8_t capabilities[16]; }; +struct caliptra_get_idev_csr_resp { + struct caliptra_resp_header hdr; + uint32_t data_size; + uint8_t data[512]; +}; + // DPE commands #define DPE_MAGIC 0x44504543 // "DPEC" diff --git a/libcaliptra/src/caliptra_api.c b/libcaliptra/src/caliptra_api.c index de470484b2..2417891888 100644 --- a/libcaliptra/src/caliptra_api.c +++ b/libcaliptra/src/caliptra_api.c @@ -1172,6 +1172,21 @@ int caliptra_fips_version(struct caliptra_fips_version_resp *resp, bool async) return pack_and_execute_command(&p, async); } +// Get IDev CSR +int caliptra_get_idev_csr(struct caliptra_get_idev_csr_resp *resp, bool async) +{ + if (!resp) + { + return INVALID_PARAMS; + } + + caliptra_checksum checksum = 0; + + CREATE_PARCEL(p, OP_GET_IDEV_CSR, &checksum, resp); + + return pack_and_execute_command(&p, async); +} + // Self test start int caliptra_self_test_start(bool async) { diff --git a/libcaliptra/src/caliptra_mbox.h b/libcaliptra/src/caliptra_mbox.h index f62ce0b765..2b5d77b5df 100644 --- a/libcaliptra/src/caliptra_mbox.h +++ b/libcaliptra/src/caliptra_mbox.h @@ -51,6 +51,7 @@ enum mailbox_command { OP_SELF_TEST_GET_RESULTS = 0x46504C67, // "FPGR" OP_SHUTDOWN = 0x46505344, // "FPSD" OP_CAPABILITIES = 0x43415053, // "CAPS" + OP_GET_IDEV_CSR = 0x49444352, // "IDCR" }; struct parcel { From e3425829929237644029d7d8c5b86582898763d8 Mon Sep 17 00:00:00 2001 From: Carl Lundin Date: Tue, 12 Nov 2024 14:25:44 -0800 Subject: [PATCH 19/51] Increase stack size to 64KiB (cherry picked from commit 0cc6ca8bcefae780c2547854985d831e0ec847e6) --- drivers/src/memory_layout.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/src/memory_layout.rs b/drivers/src/memory_layout.rs index d0992485e1..7146a595fc 100644 --- a/drivers/src/memory_layout.rs +++ b/drivers/src/memory_layout.rs @@ -79,8 +79,8 @@ pub const DPE_SIZE: u32 = 5 * 1024; pub const PCR_RESET_COUNTER_SIZE: u32 = 1024; pub const AUTH_MAN_IMAGE_METADATA_MAX_SIZE: u32 = 7 * 1024; pub const IDEVID_CSR_SIZE: u32 = 1024; -pub const DATA_SIZE: u32 = 62 * 1024; -pub const STACK_SIZE: u32 = 22 * 1024; +pub const DATA_SIZE: u32 = 20 * 1024; +pub const STACK_SIZE: u32 = 64 * 1024; pub const ROM_STACK_SIZE: u32 = 14 * 1024; pub const ESTACK_SIZE: u32 = 1024; pub const ROM_ESTACK_SIZE: u32 = 1024; From e53f89019bd05229aa8f8c2e98cb56c327cd0d94 Mon Sep 17 00:00:00 2001 From: Carl Lundin Date: Tue, 12 Nov 2024 17:17:55 -0800 Subject: [PATCH 20/51] Make `GetIdevCsr` enums / naming consistent with `GetIdevCert` naming. `%s/GetIdevIdCsr/GetIdevCsr/g` (cherry picked from commit 665bfd19b6ae31f84df84febb2d742459fa491a6) --- api/src/mailbox.rs | 20 +++++++++---------- rom/dev/src/flow/cold_reset/fw_processor.rs | 4 ++-- .../tests_get_idev_csr.rs | 4 ++-- runtime/src/get_idev_csr.rs | 14 ++++++------- runtime/src/lib.rs | 4 ++-- .../test_get_idev_csr.rs | 4 ++-- 6 files changed, 25 insertions(+), 25 deletions(-) diff --git a/api/src/mailbox.rs b/api/src/mailbox.rs index f8b1225753..9db5ff59f0 100644 --- a/api/src/mailbox.rs +++ b/api/src/mailbox.rs @@ -154,7 +154,7 @@ pub enum MailboxResp { QuotePcrs(QuotePcrsResp), CertifyKeyExtended(CertifyKeyExtendedResp), AuthorizeAndStash(AuthorizeAndStashResp), - GetIdevIdCsr(GetIdevIdCsrResp), + GetIdevCsr(GetIdevCsrResp), } impl MailboxResp { @@ -175,7 +175,7 @@ impl MailboxResp { MailboxResp::QuotePcrs(resp) => Ok(resp.as_bytes()), MailboxResp::CertifyKeyExtended(resp) => Ok(resp.as_bytes()), MailboxResp::AuthorizeAndStash(resp) => Ok(resp.as_bytes()), - MailboxResp::GetIdevIdCsr(resp) => Ok(resp.as_bytes()), + MailboxResp::GetIdevCsr(resp) => Ok(resp.as_bytes()), } } @@ -196,7 +196,7 @@ impl MailboxResp { MailboxResp::QuotePcrs(resp) => Ok(resp.as_bytes_mut()), MailboxResp::CertifyKeyExtended(resp) => Ok(resp.as_bytes_mut()), MailboxResp::AuthorizeAndStash(resp) => Ok(resp.as_bytes_mut()), - MailboxResp::GetIdevIdCsr(resp) => Ok(resp.as_bytes_mut()), + MailboxResp::GetIdevCsr(resp) => Ok(resp.as_bytes_mut()), } } @@ -986,28 +986,28 @@ impl Default for SetAuthManifestReq { // GET_IDEVID_CSR #[repr(C)] #[derive(Default, Debug, AsBytes, FromBytes, PartialEq, Eq)] -pub struct GetIdevIdCsrReq { +pub struct GetIdevCsrReq { pub hdr: MailboxReqHeader, } -impl Request for GetIdevIdCsrReq { +impl Request for GetIdevCsrReq { const ID: CommandId = CommandId::GET_IDEV_CSR; - type Resp = GetIdevIdCsrResp; + type Resp = GetIdevCsrResp; } #[repr(C)] #[derive(Debug, AsBytes, FromBytes, PartialEq, Eq)] -pub struct GetIdevIdCsrResp { +pub struct GetIdevCsrResp { pub hdr: MailboxRespHeader, pub data_size: u32, pub data: [u8; Self::DATA_MAX_SIZE], } -impl GetIdevIdCsrResp { +impl GetIdevCsrResp { pub const DATA_MAX_SIZE: usize = 512; } -impl ResponseVarSize for GetIdevIdCsrResp {} +impl ResponseVarSize for GetIdevCsrResp {} -impl Default for GetIdevIdCsrResp { +impl Default for GetIdevCsrResp { fn default() -> Self { Self { hdr: MailboxRespHeader::default(), diff --git a/rom/dev/src/flow/cold_reset/fw_processor.rs b/rom/dev/src/flow/cold_reset/fw_processor.rs index e5988aa33d..0b6870d141 100644 --- a/rom/dev/src/flow/cold_reset/fw_processor.rs +++ b/rom/dev/src/flow/cold_reset/fw_processor.rs @@ -23,7 +23,7 @@ use caliptra_cfi_lib::CfiCounter; use caliptra_common::capabilities::Capabilities; use caliptra_common::fips::FipsVersionCmd; use caliptra_common::mailbox_api::{ - CapabilitiesResp, CommandId, GetIdevIdCsrResp, MailboxReqHeader, MailboxRespHeader, Response, + CapabilitiesResp, CommandId, GetIdevCsrResp, MailboxReqHeader, MailboxRespHeader, Response, StashMeasurementReq, StashMeasurementResp, }; use caliptra_common::{ @@ -311,7 +311,7 @@ impl FirmwareProcessor { Self::copy_req_verify_chksum(&mut txn, request.as_bytes_mut())?; let csr_persistent_mem = &persistent_data.idevid_csr; - let mut resp = GetIdevIdCsrResp::default(); + let mut resp = GetIdevCsrResp::default(); if csr_persistent_mem.is_unprovisioned() { // CSR was never written to DCCM. This means the gen_idev_id_csr diff --git a/rom/dev/tests/rom_integration_tests/tests_get_idev_csr.rs b/rom/dev/tests/rom_integration_tests/tests_get_idev_csr.rs index 3cb44d1d84..2327d013ad 100644 --- a/rom/dev/tests/rom_integration_tests/tests_get_idev_csr.rs +++ b/rom/dev/tests/rom_integration_tests/tests_get_idev_csr.rs @@ -2,7 +2,7 @@ use caliptra_api::SocManager; use caliptra_builder::ImageOptions; -use caliptra_common::mailbox_api::{CommandId, GetIdevIdCsrResp, MailboxReqHeader}; +use caliptra_common::mailbox_api::{CommandId, GetIdevCsrResp, MailboxReqHeader}; use caliptra_drivers::MfgFlags; use caliptra_error::CaliptraError; use caliptra_hw_model::{Fuses, HwModel, ModelError}; @@ -36,7 +36,7 @@ fn test_get_csr() { .unwrap() .unwrap(); - let get_idv_csr_resp = GetIdevIdCsrResp::read_from(response.as_bytes()).unwrap(); + let get_idv_csr_resp = GetIdevCsrResp::read_from(response.as_bytes()).unwrap(); assert!(caliptra_common::checksum::verify_checksum( get_idv_csr_resp.hdr.chksum, diff --git a/runtime/src/get_idev_csr.rs b/runtime/src/get_idev_csr.rs index 1ccd6374c2..5ec4b2ef60 100644 --- a/runtime/src/get_idev_csr.rs +++ b/runtime/src/get_idev_csr.rs @@ -7,7 +7,7 @@ use caliptra_cfi_lib_git::cfi_launder; use caliptra_common::{ cprintln, - mailbox_api::{GetIdevIdCsrReq, GetIdevIdCsrResp, MailboxResp, MailboxRespHeader}, + mailbox_api::{GetIdevCsrReq, GetIdevCsrResp, MailboxResp, MailboxRespHeader}, }; use caliptra_error::{CaliptraError, CaliptraResult}; @@ -15,12 +15,12 @@ use caliptra_drivers::IdevIdCsr; use zerocopy::{AsBytes, FromBytes}; -pub struct GetIdevIdCsrCmd; -impl GetIdevIdCsrCmd { +pub struct GetIdevCsrCmd; +impl GetIdevCsrCmd { #[cfg_attr(not(feature = "no-cfi"), cfi_impl_fn)] #[inline(never)] pub(crate) fn execute(drivers: &mut Drivers, cmd_args: &[u8]) -> CaliptraResult { - if let Some(cmd) = GetIdevIdCsrReq::read_from(cmd_args) { + if let Some(cmd) = GetIdevCsrReq::read_from(cmd_args) { let csr_persistent_mem = &drivers.persistent_data.get().idevid_csr; match csr_persistent_mem.get_csr_len() { @@ -33,7 +33,7 @@ impl GetIdevIdCsrCmd { .get() .ok_or(CaliptraError::RUNTIME_GET_IDEV_ID_UNPROVISIONED)?; - let mut resp = GetIdevIdCsrResp { + let mut resp = GetIdevCsrResp { data_size: len, ..Default::default() }; @@ -43,10 +43,10 @@ impl GetIdevIdCsrCmd { // `resp.data_size` by the `IDevIDCsr::get` API. // // A valid `IDevIDCsr` cannot be larger than `MAX_CSR_SIZE`, which is the max - // size of the buffer in `GetIdevIdCsrResp` + // size of the buffer in `GetIdevCsrResp` resp.data[..resp.data_size as usize].copy_from_slice(csr); - Ok(MailboxResp::GetIdevIdCsr(resp)) + Ok(MailboxResp::GetIdevCsr(resp)) } } } else { diff --git a/runtime/src/lib.rs b/runtime/src/lib.rs index 995cf52b25..fd8480f23c 100644 --- a/runtime/src/lib.rs +++ b/runtime/src/lib.rs @@ -58,7 +58,7 @@ pub use fips::FipsShutdownCmd; pub use fips::{fips_self_test_cmd, fips_self_test_cmd::SelfTestStatus}; pub use populate_idev::PopulateIDevIdCertCmd; -pub use get_idev_csr::GetIdevIdCsrCmd; +pub use get_idev_csr::GetIdevCsrCmd; pub use info::{FwInfoCmd, IDevIdInfoCmd}; pub use invoke_dpe::InvokeDpeCmd; pub use pcr::IncrementPcrResetCounterCmd; @@ -228,7 +228,7 @@ fn handle_command(drivers: &mut Drivers) -> CaliptraResult { CommandId::SHUTDOWN => FipsShutdownCmd::execute(drivers), CommandId::SET_AUTH_MANIFEST => SetAuthManifestCmd::execute(drivers, cmd_bytes), CommandId::AUTHORIZE_AND_STASH => AuthorizeAndStashCmd::execute(drivers, cmd_bytes), - CommandId::GET_IDEV_CSR => GetIdevIdCsrCmd::execute(drivers, cmd_bytes), + CommandId::GET_IDEV_CSR => GetIdevCsrCmd::execute(drivers, cmd_bytes), _ => Err(CaliptraError::RUNTIME_UNIMPLEMENTED_COMMAND), }?; diff --git a/runtime/tests/runtime_integration_tests/test_get_idev_csr.rs b/runtime/tests/runtime_integration_tests/test_get_idev_csr.rs index 6e072f097f..13078f7e60 100644 --- a/runtime/tests/runtime_integration_tests/test_get_idev_csr.rs +++ b/runtime/tests/runtime_integration_tests/test_get_idev_csr.rs @@ -1,7 +1,7 @@ // Licensed under the Apache-2.0 license use caliptra_api::SocManager; -use caliptra_common::mailbox_api::{CommandId, GetIdevIdCsrResp, MailboxReqHeader}; +use caliptra_common::mailbox_api::{CommandId, GetIdevCsrResp, MailboxReqHeader}; use caliptra_drivers::{IdevIdCsr, MfgFlags}; use caliptra_error::CaliptraError; use caliptra_hw_model::{HwModel, ModelError}; @@ -30,7 +30,7 @@ fn test_get_csr() { .unwrap() .unwrap(); - let get_idv_csr_resp = GetIdevIdCsrResp::read_from(response.as_bytes()).unwrap(); + let get_idv_csr_resp = GetIdevCsrResp::read_from(response.as_bytes()).unwrap(); assert_ne!(IdevIdCsr::UNPROVISIONED_CSR, get_idv_csr_resp.data_size); assert_ne!(0, get_idv_csr_resp.data_size); From f18da60ed54c6305af46f5afb20177bc6177b44a Mon Sep 17 00:00:00 2001 From: Nick Quarton <139178705+nquarton@users.noreply.github.com> Date: Fri, 15 Nov 2024 10:20:52 -0800 Subject: [PATCH 21/51] Adding KAT for ECC deterministic key pair generation (#1655) (cherry picked from commit 86a37b03b955d42a5ed0f3b09e3793d22f815847) --- FROZEN_IMAGES.sha384sum | 4 +- drivers/src/ecc384.rs | 74 ++++++++++++++++++++++-- drivers/src/fips_test_hooks.rs | 3 + error/src/lib.rs | 10 ++-- kat/src/ecc384_kat.rs | 61 +++++++++++-------- test/tests/fips_test_suite/self_tests.rs | 46 ++++++++++++--- 6 files changed, 155 insertions(+), 43 deletions(-) diff --git a/FROZEN_IMAGES.sha384sum b/FROZEN_IMAGES.sha384sum index 778b1b47ce..8bda8fe0b6 100644 --- a/FROZEN_IMAGES.sha384sum +++ b/FROZEN_IMAGES.sha384sum @@ -1,3 +1,3 @@ # WARNING: Do not update this file without the approval of the Caliptra TAC -133bf3969893178e041b61001d75bfb504be3b3676cac608a40877f1e4b46b4855f86c1859cfc3e22745327102fba4b0 caliptra-rom-no-log.bin -44f5bbbc4b71d7f0926f85b7d81ef7e17f721557b38379b650497eb8dd19d0a74ab5a1e2177c7e99653a878d2daed3b3 caliptra-rom-with-log.bin +9fe3c2a8031c31e7a9ce56e5b8b430414d74db9d04161512b90fb60d5df120cc3998c8881eea10b7c4e1c1bea4326b27 caliptra-rom-no-log.bin +f1a8736ab386897c62a173032910ed03566043b01305ceaab7d25614b86e86ef97dd90bf9cdf7aaa7eb470f9e155133b caliptra-rom-with-log.bin diff --git a/drivers/src/ecc384.rs b/drivers/src/ecc384.rs index 48bc925ee1..d41f61e54b 100644 --- a/drivers/src/ecc384.rs +++ b/drivers/src/ecc384.rs @@ -228,6 +228,58 @@ impl Ecc384 { trng: &mut Trng, priv_key: Ecc384PrivKeyOut, ) -> CaliptraResult { + self.key_pair_base(seed, nonce, trng, priv_key, None) + } + + /// Generate ECC-384 Key Pair for FIPS KAT testing + /// ONLY to be used for KAT testing + /// + /// # Arguments + /// + /// * `trng` - TRNG driver instance + /// * `priv_key` - Generate ECC-384 Private key + /// * `pct_sig` - Ecc 384 signature to return signature generated during the pairwise consistency test + /// + /// # Returns + /// + /// * `Ecc384PubKey` - Generated ECC-384 Public Key + #[cfg_attr(not(feature = "no-cfi"), cfi_impl_fn)] + pub fn key_pair_for_fips_kat( + &mut self, + trng: &mut Trng, + priv_key: Ecc384PrivKeyOut, + pct_sig: &mut Ecc384Signature, + ) -> CaliptraResult { + let seed = Array4x12::new([0u32; 12]); + let nonce = Array4x12::new([0u32; 12]); + self.key_pair_base( + &Ecc384Seed::from(&seed), + &nonce, + trng, + priv_key, + Some(pct_sig), + ) + } + + /// Private base function to generate ECC-384 Key Pair + /// pct_sig should only be provided in the KAT use case + #[cfg_attr(not(feature = "no-cfi"), cfi_impl_fn)] + #[inline(never)] + fn key_pair_base( + &mut self, + seed: &Ecc384Seed, + nonce: &Array4x12, + trng: &mut Trng, + priv_key: Ecc384PrivKeyOut, + pct_sig: Option<&mut Ecc384Signature>, + ) -> CaliptraResult { + #[cfg(feature = "fips-test-hooks")] + unsafe { + crate::FipsTestHook::error_if_hook_set( + crate::FipsTestHook::ECC384_KEY_PAIR_GENERATE_FAILURE, + )? + } + let ecc = self.ecc.regs_mut(); let mut priv_key = priv_key; @@ -299,7 +351,13 @@ impl Ecc384 { }; match self.sign(&priv_key.into(), &pub_key, &digest, trng) { - Ok(mut sig) => sig.zeroize(), + Ok(mut sig) => { + // Return the signature from this test if requested (only used for KAT) + if let Some(output_sig) = pct_sig { + *output_sig = sig; + } + sig.zeroize(); + } Err(_) => { // Remap error to a pairwise consistency check failure return Err(CaliptraError::DRIVER_ECC384_KEYGEN_PAIRWISE_CONSISTENCY_FAILURE); @@ -308,6 +366,14 @@ impl Ecc384 { self.zeroize_internal(); + #[cfg(feature = "fips-test-hooks")] + let pub_key = unsafe { + crate::FipsTestHook::corrupt_data_if_hook_set( + crate::FipsTestHook::ECC384_CORRUPT_KEY_PAIR, + &pub_key, + ) + }; + Ok(pub_key) } @@ -431,12 +497,12 @@ impl Ecc384 { caliptra_cfi_lib::cfi_assert_eq_12_words(&r.0, &sig.r.0); #[cfg(feature = "fips-test-hooks")] - let sig_result = unsafe { + let sig_result = Ok(unsafe { crate::FipsTestHook::corrupt_data_if_hook_set( crate::FipsTestHook::ECC384_CORRUPT_SIGNATURE, - &sig_result, + sig, ) - }; + }); sig_result } diff --git a/drivers/src/fips_test_hooks.rs b/drivers/src/fips_test_hooks.rs index 0a02241027..5a2e0718dc 100755 --- a/drivers/src/fips_test_hooks.rs +++ b/drivers/src/fips_test_hooks.rs @@ -11,6 +11,7 @@ impl FipsTestHook { pub const COMPLETE: u8 = 0x1; // Set by external test pub const CONTINUE: u8 = 0x10; + pub const HALT_SELF_TESTS: u8 = 0x21; pub const SHA1_CORRUPT_DIGEST: u8 = 0x22; pub const SHA256_CORRUPT_DIGEST: u8 = 0x23; @@ -22,6 +23,7 @@ impl FipsTestHook { pub const ECC384_PAIRWISE_CONSISTENCY_ERROR: u8 = 0x29; pub const HALT_FW_LOAD: u8 = 0x2A; pub const HALT_SHUTDOWN_RT: u8 = 0x2B; + pub const ECC384_CORRUPT_KEY_PAIR: u8 = 0x2C; pub const SHA1_DIGEST_FAILURE: u8 = 0x40; pub const SHA256_DIGEST_FAILURE: u8 = 0x41; @@ -32,6 +34,7 @@ impl FipsTestHook { pub const ECC384_VERIFY_FAILURE: u8 = 0x46; pub const HMAC384_FAILURE: u8 = 0x47; pub const LMS_VERIFY_FAILURE: u8 = 0x48; + pub const ECC384_KEY_PAIR_GENERATE_FAILURE: u8 = 0x49; // FW Load Errors pub const FW_LOAD_VENDOR_PUB_KEY_DIGEST_FAILURE: u8 = 0x50; diff --git a/error/src/lib.rs b/error/src/lib.rs index a8ab62d60e..3097d8be94 100644 --- a/error/src/lib.rs +++ b/error/src/lib.rs @@ -614,11 +614,13 @@ impl CaliptraError { pub const KAT_HMAC384_FAILURE: CaliptraError = CaliptraError::new_const(0x90030001); pub const KAT_HMAC384_TAG_MISMATCH: CaliptraError = CaliptraError::new_const(0x90030002); - pub const KAT_ECC384_SIGNATURE_GENERATE_FAILURE: CaliptraError = - CaliptraError::new_const(0x90040001); - pub const KAT_ECC384_SIGNATURE_VERIFY_FAILURE: CaliptraError = - CaliptraError::new_const(0x90040002); + // 0x90040001 was KAT_ECC384_SIGNATURE_GENERATE_FAILURE + // 0x90040002 was KAT_ECC384_SIGNATURE_VERIFY_FAILURE pub const KAT_ECC384_SIGNATURE_MISMATCH: CaliptraError = CaliptraError::new_const(0x90040003); + pub const KAT_ECC384_KEY_PAIR_GENERATE_FAILURE: CaliptraError = + CaliptraError::new_const(0x90040004); + pub const KAT_ECC384_KEY_PAIR_VERIFY_FAILURE: CaliptraError = + CaliptraError::new_const(0x90040005); pub const KAT_SHA2_512_384_ACC_DIGEST_START_OP_FAILURE: CaliptraError = CaliptraError::new_const(0x90050001); diff --git a/kat/src/ecc384_kat.rs b/kat/src/ecc384_kat.rs index c8513ee7df..4a82acff9d 100644 --- a/kat/src/ecc384_kat.rs +++ b/kat/src/ecc384_kat.rs @@ -13,34 +13,34 @@ Abstract: --*/ use caliptra_drivers::{ - Array4x12, Array4xN, CaliptraError, CaliptraResult, Ecc384, Ecc384PrivKeyIn, Ecc384PubKey, + Array4x12, Array4xN, CaliptraError, CaliptraResult, Ecc384, Ecc384PrivKeyOut, Ecc384PubKey, Ecc384Signature, Trng, }; -const PRIV_KEY: Array4x12 = Array4x12::new([ - 0xc908585a, 0x486c3b3d, 0x8bbe50eb, 0x7d2eb8a0, 0x3aa04e3d, 0x8bde2c31, 0xa8a2a1e3, 0x349dc21c, - 0xbbe6c90a, 0xe2f74912, 0x8884b622, 0xbb72b4c5, +const KEY_GEN_PRIV_KEY: Array4x12 = Array4x12::new([ + 0xfeeef554, 0x4a765649, 0x90128ad1, 0x89e873f2, 0x1f0dfd5a, 0xd7e2fa86, 0x1127ee6e, 0x394ca784, + 0x871c1aec, 0x032c7a8b, 0x10b93e0e, 0xab8946d6, ]); -const PUB_KEY: Ecc384PubKey = Ecc384PubKey { +const KEY_GEN_PUB_KEY: Ecc384PubKey = Ecc384PubKey { x: Array4xN([ - 0x98233ca, 0x567a3f14, 0xbe784904, 0xc6921d43, 0x3b4f853a, 0x523742e4, 0xbc98767e, - 0x23ca3da6, 0x656bec46, 0xa7b1119e, 0x63d266ca, 0x6254977f, + 0xd7dd94e0, 0xbffc4cad, 0xe9902b7f, 0xdb154260, 0xd5ec5dfd, 0x57950e83, 0x59015a30, + 0x2c8bf7bb, 0xa7e5f6df, 0xfc168516, 0x2bdd35f9, 0xf5c1b0ff, ]), y: Array4xN([ - 0x75d0b401, 0xc8bac39a, 0xc5fb0f2b, 0x3b95372c, 0x41d9de40, 0x55fddb06, 0xf7484974, - 0x8d0aed85, 0x9b6550ca, 0x750c3cd1, 0x1851e050, 0xbb7d20b2, + 0xbb9c3a2f, 0x061e8d70, 0x14278dd5, 0x1e66a918, 0xa6b6f9f1, 0xc1937312, 0xd4e7a921, + 0xb18ef0f4, 0x1fdd401d, 0x9e771850, 0x9f8731e9, 0xeec9c31d, ]), }; const SIGNATURE: Ecc384Signature = Ecc384Signature { r: Array4xN([ - 0x36f85014, 0x6f400443, 0x848cae03, 0x57591032, 0xe6a395de, 0x66e7261a, 0x38049fb, - 0xee15db19, 0x5dbd9786, 0x9439292a, 0x4f5792e4, 0x3a1231b7, + 0x93799D55, 0x12263628, 0x34F60F7B, 0x945290B7, 0xCCE6E996, 0x01FB7EBD, 0x026C2E3C, + 0x445D3CD9, 0xB65068DA, 0xC0A848BE, 0x9F0560AA, 0x758FDA27, ]), s: Array4xN([ - 0xeeea4294, 0x82fd8fa9, 0xd4d5f960, 0xa09edfa6, 0xc765efe5, 0xff4c17a5, 0x12e694fa, - 0xcc45d3f6, 0xfc3d3b5c, 0x62739c1f, 0xb9fcae3, 0x26f54b43, + 0xE548E535, 0xA1CC600E, 0x133B5591, 0xAEBAAD78, 0x054006D7, 0x52D0E1DF, 0x94FBFA95, + 0xD78F0B3F, 0x8E81B911, 0x9C2BE008, 0xBF6D6F4E, 0x4185F87D, ]), }; @@ -51,7 +51,7 @@ impl Ecc384Kat { /// This function executes the Known Answer Tests (aka KAT) for ECC384. /// /// Test vector source: - /// Generated using MbedTLS library. + /// Zeroed inputs, outputs verified against python cryptography lib built on OpenSSL /// /// # Arguments /// @@ -61,24 +61,35 @@ impl Ecc384Kat { /// /// * `CaliptraResult` - Result denoting the KAT outcome. pub fn execute(&self, ecc: &mut Ecc384, trng: &mut Trng) -> CaliptraResult<()> { - self.kat_signature_generate_and_verify(ecc, trng) + self.kat_key_pair_gen_sign_and_verify(ecc, trng) } - fn kat_signature_generate_and_verify( + fn kat_key_pair_gen_sign_and_verify( &self, ecc: &mut Ecc384, trng: &mut Trng, ) -> CaliptraResult<()> { - let digest = Array4x12::new([0u32; 12]); - // The driver validates every signature that it generates, so don't need - // to explicitly verify here. - let signature = ecc - .sign(&Ecc384PrivKeyIn::from(&PRIV_KEY), &PUB_KEY, &digest, trng) - .map_err(|_| CaliptraError::KAT_ECC384_SIGNATURE_GENERATE_FAILURE)?; - - if signature != SIGNATURE { - Err(CaliptraError::KAT_ECC384_SIGNATURE_VERIFY_FAILURE)?; + let mut priv_key = Array4x12::new([0u32; 12]); + let mut pct_sig = Ecc384Signature { + r: Array4x12::new([0u32; 12]), + s: Array4x12::new([0u32; 12]), + }; + + let pub_key = ecc + .key_pair_for_fips_kat(trng, Ecc384PrivKeyOut::from(&mut priv_key), &mut pct_sig) + .map_err(|_| CaliptraError::KAT_ECC384_KEY_PAIR_GENERATE_FAILURE)?; + + // NOTE: Signature verify step is performed in ECC driver sign function + if priv_key != KEY_GEN_PRIV_KEY { + Err(CaliptraError::KAT_ECC384_KEY_PAIR_VERIFY_FAILURE)?; + } + if pub_key != KEY_GEN_PUB_KEY { + Err(CaliptraError::KAT_ECC384_KEY_PAIR_VERIFY_FAILURE)?; } + if pct_sig != SIGNATURE { + Err(CaliptraError::KAT_ECC384_SIGNATURE_MISMATCH)?; + } + Ok(()) } } diff --git a/test/tests/fips_test_suite/self_tests.rs b/test/tests/fips_test_suite/self_tests.rs index af065aed42..1168527ec2 100755 --- a/test/tests/fips_test_suite/self_tests.rs +++ b/test/tests/fips_test_suite/self_tests.rs @@ -394,38 +394,68 @@ pub fn kat_sha2_512_384acc_digest_mismatch_rt() { #[test] #[cfg(not(feature = "test_env_immutable_rom"))] pub fn kat_ecc384_signature_generate_failure_rom() { - // Should be KAT_ECC384_SIGNATURE_VERIFY_FAILURE but ROM is using the wrong code self_test_failure_flow_rom( FipsTestHook::ECC384_SIGNATURE_GENERATE_FAILURE, - u32::from(CaliptraError::KAT_ECC384_SIGNATURE_GENERATE_FAILURE), + u32::from(CaliptraError::KAT_ECC384_KEY_PAIR_GENERATE_FAILURE), ); } #[test] pub fn kat_ecc384_signature_generate_failure_rt() { - // Should be KAT_ECC384_SIGNATURE_VERIFY_FAILURE but ROM is using the wrong code self_test_failure_flow_rt( FipsTestHook::ECC384_SIGNATURE_GENERATE_FAILURE, - u32::from(CaliptraError::KAT_ECC384_SIGNATURE_GENERATE_FAILURE), + u32::from(CaliptraError::KAT_ECC384_KEY_PAIR_GENERATE_FAILURE), ); } #[test] #[cfg(not(feature = "test_env_immutable_rom"))] pub fn kat_ecc384_signature_verify_failure_rom() { - // Should be KAT_ECC384_SIGNATURE_VERIFY_FAILURE but ROM is using the wrong code self_test_failure_flow_rom( FipsTestHook::ECC384_CORRUPT_SIGNATURE, - u32::from(CaliptraError::KAT_ECC384_SIGNATURE_GENERATE_FAILURE), + u32::from(CaliptraError::KAT_ECC384_SIGNATURE_MISMATCH), ); } #[test] pub fn kat_ecc384_signature_verify_failure_rt() { - // Should be KAT_ECC384_SIGNATURE_VERIFY_FAILURE but ROM is using the wrong code self_test_failure_flow_rt( FipsTestHook::ECC384_CORRUPT_SIGNATURE, - u32::from(CaliptraError::KAT_ECC384_SIGNATURE_GENERATE_FAILURE), + u32::from(CaliptraError::KAT_ECC384_SIGNATURE_MISMATCH), + ); +} + +#[test] +#[cfg(not(feature = "test_env_immutable_rom"))] +pub fn kat_ecc384_deterministic_key_gen_generate_failure_rom() { + self_test_failure_flow_rom( + FipsTestHook::ECC384_KEY_PAIR_GENERATE_FAILURE, + u32::from(CaliptraError::KAT_ECC384_KEY_PAIR_GENERATE_FAILURE), + ); +} + +#[test] +pub fn kat_ecc384_deterministic_key_gen_generate_failure_rt() { + self_test_failure_flow_rt( + FipsTestHook::ECC384_KEY_PAIR_GENERATE_FAILURE, + u32::from(CaliptraError::KAT_ECC384_KEY_PAIR_GENERATE_FAILURE), + ); +} + +#[test] +#[cfg(not(feature = "test_env_immutable_rom"))] +pub fn kat_ecc384_deterministic_key_gen_verify_failure_rom() { + self_test_failure_flow_rom( + FipsTestHook::ECC384_CORRUPT_KEY_PAIR, + u32::from(CaliptraError::KAT_ECC384_KEY_PAIR_VERIFY_FAILURE), + ); +} + +#[test] +pub fn kat_ecc384_deterministic_key_gen_verify_failure_rt() { + self_test_failure_flow_rt( + FipsTestHook::ECC384_CORRUPT_KEY_PAIR, + u32::from(CaliptraError::KAT_ECC384_KEY_PAIR_VERIFY_FAILURE), ); } From 8724274f6795800a58f8b961ac566fa33e39df2f Mon Sep 17 00:00:00 2001 From: Nick Quarton <139178705+nquarton@users.noreply.github.com> Date: Thu, 14 Nov 2024 14:13:02 -0800 Subject: [PATCH 22/51] Reverting subject name in all certs to Caliptra 1.0 from Caliptra 1.x (cherry picked from commit 9a1a9daeaa6f0d53e83191a917707af6a3886ccf) --- FROZEN_IMAGES.sha384sum | 4 +- libcaliptra/examples/generic/idev_csr_array.h | 191 +- libcaliptra/examples/generic/test.c | 1643 +++++++++-------- runtime/src/dpe_platform.rs | 2 +- .../fmc_alias_cert_redacted.der | Bin 874 -> 874 bytes .../fmc_alias_cert_redacted.txt | 4 +- .../smoke_testdata/idevid_csr.der | Bin 443 -> 444 bytes .../smoke_testdata/idevid_csr.txt | 14 +- .../smoke_testdata/ldevid_cert.der | Bin 674 -> 673 bytes .../smoke_testdata/ldevid_cert.txt | 16 +- .../smoke_testdata/rt_alias_cert_redacted.der | Bin 770 -> 770 bytes .../smoke_testdata/rt_alias_cert_redacted.txt | 4 +- x509/build/build.rs | 8 +- x509/build/fmc_alias_cert_tbs.rs | 4 +- x509/build/init_dev_id_csr_tbs.rs | 2 +- x509/build/local_dev_id_cert_tbs.rs | 4 +- x509/build/rt_alias_cert_tbs.rs | 4 +- 17 files changed, 1018 insertions(+), 882 deletions(-) diff --git a/FROZEN_IMAGES.sha384sum b/FROZEN_IMAGES.sha384sum index 8bda8fe0b6..8138d5d756 100644 --- a/FROZEN_IMAGES.sha384sum +++ b/FROZEN_IMAGES.sha384sum @@ -1,3 +1,3 @@ # WARNING: Do not update this file without the approval of the Caliptra TAC -9fe3c2a8031c31e7a9ce56e5b8b430414d74db9d04161512b90fb60d5df120cc3998c8881eea10b7c4e1c1bea4326b27 caliptra-rom-no-log.bin -f1a8736ab386897c62a173032910ed03566043b01305ceaab7d25614b86e86ef97dd90bf9cdf7aaa7eb470f9e155133b caliptra-rom-with-log.bin +129ee84ecdc1f80a9aab51883589b4eb80191bc726277fb31fab2bb2e99f54b3ad7dc80459914c9cd9749e5994614ccd caliptra-rom-no-log.bin +162eb324937462a1534406d43b9ba74b229d9347541f148eebc435f901e839e4c95af308f91b873f0bc67124cf35ecc1 caliptra-rom-with-log.bin diff --git a/libcaliptra/examples/generic/idev_csr_array.h b/libcaliptra/examples/generic/idev_csr_array.h index 91439463f9..b105dca434 100644 --- a/libcaliptra/examples/generic/idev_csr_array.h +++ b/libcaliptra/examples/generic/idev_csr_array.h @@ -2,12 +2,12 @@ // Generated from test/tests/caliptra_integration_tests/smoke_testdata/idev_csr.der #include -#define IDEV_CSR_LEN 444 +#define IDEV_CSR_LEN 443 uint8_t idev_csr_bytes[IDEV_CSR_LEN] = { 0x30, 0x82, 0x01, - 0xb8, + 0xb7, 0x30, 0x82, 0x01, @@ -39,7 +39,7 @@ uint8_t idev_csr_bytes[IDEV_CSR_LEN] = { 0x20, 0x31, 0x2e, - 0x78, + 0x30, 0x20, 0x49, 0x44, @@ -343,109 +343,108 @@ uint8_t idev_csr_bytes[IDEV_CSR_LEN] = { 0x03, 0x03, 0x03, - 0x68, + 0x67, 0x00, 0x30, - 0x65, - 0x02, - 0x31, - 0x00, - 0xed, - 0x8e, - 0x44, - 0x4e, - 0x3c, - 0x7f, - 0x6f, - 0x96, - 0x4a, - 0x5d, - 0xcb, - 0xe1, - 0xea, - 0x08, - 0xa0, - 0x57, - 0xf5, - 0xd7, - 0xb5, - 0x6d, - 0xce, - 0x72, - 0x9e, - 0xb8, - 0x8c, - 0x88, - 0x38, - 0xf6, - 0x50, - 0x35, - 0x90, - 0xbd, - 0x6b, - 0x59, - 0xdb, - 0x29, - 0x52, - 0x13, - 0x2e, - 0xfc, - 0xa8, - 0xb6, - 0x8d, - 0x8a, - 0x33, - 0xd3, - 0x2a, - 0xcf, + 0x64, 0x02, 0x30, - 0x6d, - 0x40, - 0x6a, - 0x1f, 0x7c, - 0x9e, 0x74, - 0x8f, + 0xfd, 0x28, + 0xce, + 0x0f, + 0xf9, + 0xe9, + 0xda, + 0xef, + 0x90, + 0x84, + 0xa5, + 0xaf, + 0xc0, + 0x42, + 0xd1, + 0xe2, + 0x08, + 0x84, + 0x67, + 0xd6, + 0x6a, + 0xe8, 0xdc, - 0x14, - 0x73, - 0xe0, - 0x96, - 0x92, - 0xd8, - 0x74, - 0xfa, + 0x46, + 0xcc, + 0x02, + 0x1d, + 0x80, + 0xda, + 0x37, + 0x50, + 0x91, + 0xee, + 0x75, + 0x09, + 0xed, + 0x15, + 0x55, + 0x0f, + 0x31, + 0x15, + 0x23, + 0xc9, + 0xbb, + 0xe6, + 0xe1, + 0x02, 0x30, - 0x58, + 0x24, + 0xfd, + 0x1b, + 0x5b, + 0x47, + 0xcc, + 0x14, + 0x4a, + 0x66, + 0xa5, + 0xbb, + 0xe7, 0x04, - 0x54, - 0x84, - 0x77, - 0xe9, - 0x52, + 0x74, + 0xf0, + 0x21, + 0x36, + 0x37, + 0xf4, + 0x9e, + 0x5d, + 0xcd, + 0xa1, + 0x42, + 0xbf, + 0xf6, + 0x82, + 0x5c, + 0xa1, + 0xf4, + 0x51, + 0x43, + 0xe2, + 0x97, + 0xfc, + 0x95, + 0xce, + 0x56, + 0xb1, + 0x67, + 0xe1, + 0xbf, + 0xe1, + 0x26, 0x3a, - 0x0d, - 0x63, - 0xfa, + 0xce, + 0xa1, 0xf3, - 0x1a, - 0x68, - 0xc3, - 0x88, - 0x07, - 0x50, - 0xa7, - 0x5d, - 0x6f, - 0xf7, - 0xa9, - 0xda, - 0x98, - 0xf7, - 0x8c, - 0x48, - 0x2a, }; diff --git a/libcaliptra/examples/generic/test.c b/libcaliptra/examples/generic/test.c index c41053a419..dbe5647302 100644 --- a/libcaliptra/examples/generic/test.c +++ b/libcaliptra/examples/generic/test.c @@ -13,7 +13,7 @@ #include "idev_csr_array.h" // Arbitrary example only - values must be customized/tuned for the SoC -static const uint64_t wdt_timeout = 0xA0000000; // approximately 5s for 500MHz clock +static const uint64_t wdt_timeout = 0xA0000000; // approximately 5s for 500MHz clock // Arbitrary example only - values must be customized/tuned for the SoC static const uint16_t itrng_entropy_low_threshold = 0x1; // Arbitrary example only - values must be customized/tuned for the SoC @@ -29,803 +29,940 @@ void hwmod_init(struct caliptra_buffer rom); #ifdef ENABLE_DEBUG // Exists for testbench only - not part of interface for actual implementation -static int dump_array_to_file(struct caliptra_buffer* buffer, const char *filename); +static int dump_array_to_file(struct caliptra_buffer *buffer, const char *filename); #endif /* -* caliptra_csr_is_ready -* -* Waits forever for the CSR to be ready -* -* @return bool True if ready, false otherwise -*/ + * caliptra_csr_is_ready + * + * Waits forever for the CSR to be ready + * + * @return bool True if ready, false otherwise + */ static void caliptra_wait_for_csr_ready(void) { - while (true) - { - if (caliptra_is_idevid_csr_ready()) { - break; - } - caliptra_wait(); - } + while (true) + { + if (caliptra_is_idevid_csr_ready()) + { + break; + } + caliptra_wait(); + } } void dump_caliptra_error_codes() { - printf("Caliptra FW error non-fatal code is 0x%x\n", caliptra_read_fw_non_fatal_error()); - printf("Caliptra FW error fatal code is 0x%x\n", caliptra_read_fw_fatal_error()); + printf("Caliptra FW error non-fatal code is 0x%x\n", caliptra_read_fw_non_fatal_error()); + printf("Caliptra FW error fatal code is 0x%x\n", caliptra_read_fw_fatal_error()); } -int boot_to_ready_for_fw(const test_info* info, bool req_idev_csr) +int boot_to_ready_for_fw(const test_info *info, bool req_idev_csr) { - int status; - - // Initialize FSM GO - caliptra_bootfsm_go(); - - // Request CSR if needed - if (req_idev_csr) - { - caliptra_req_idev_csr_start(); - } - - caliptra_set_wdt_timeout(wdt_timeout); - - caliptra_configure_itrng_entropy(itrng_entropy_low_threshold, - itrng_entropy_high_threshold, - itrng_entropy_repetition_count); - - // Set up our PAUSER value for the mailbox regs - status = caliptra_mbox_pauser_set_and_lock(axi_pauser); - if (status) { - printf("Set MBOX pauser Failed: 0x%x\n", status); - return status; - } - - // Set up our PAUSER value for the fuse regs - status = caliptra_fuse_pauser_set_and_lock(axi_pauser); - if (status) { - printf("Set FUSE pauser Failed: 0x%x\n", status); - return status; - } - - if ((status = caliptra_init_fuses(&info->fuses)) != 0) { - printf("Failed to init fuses: %d\n", status); - return status; - } - - if (req_idev_csr == false) - { - // Wait until ready for FW - caliptra_ready_for_firmware(); - } - - return status; + int status; + + // Initialize FSM GO + caliptra_bootfsm_go(); + + // Request CSR if needed + if (req_idev_csr) + { + caliptra_req_idev_csr_start(); + } + + caliptra_set_wdt_timeout(wdt_timeout); + + caliptra_configure_itrng_entropy(itrng_entropy_low_threshold, + itrng_entropy_high_threshold, + itrng_entropy_repetition_count); + + // Set up our PAUSER value for the mailbox regs + status = caliptra_mbox_pauser_set_and_lock(axi_pauser); + if (status) + { + printf("Set MBOX pauser Failed: 0x%x\n", status); + return status; + } + + // Set up our PAUSER value for the fuse regs + status = caliptra_fuse_pauser_set_and_lock(axi_pauser); + if (status) + { + printf("Set FUSE pauser Failed: 0x%x\n", status); + return status; + } + + if ((status = caliptra_init_fuses(&info->fuses)) != 0) + { + printf("Failed to init fuses: %d\n", status); + return status; + } + + if (req_idev_csr == false) + { + // Wait until ready for FW + caliptra_ready_for_firmware(); + } + + return status; } -int legacy_boot_test(const test_info* info) +int legacy_boot_test(const test_info *info) { - int failure = 0; - int status = boot_to_ready_for_fw(info, false); - - if (status){ - failure = 1; - } - - // Load Image Bundle - // FW_PATH is defined on the compiler command line - status = caliptra_upload_fw(&info->image_bundle, false); - - if (status) - { - printf("FW Load Failed: 0x%x\n", status); - failure = 1; - } else { - printf("FW Load: OK\n"); - } - - // Send a FIPS version command in async mode - struct caliptra_fips_version_resp version; - // Send async - status = caliptra_fips_version(&version, true); - - if (status) { - printf("Get FIPS Version send failed: 0x%x\n", status); - failure = 1; - } else { - // Wait indefinitely for completion - while (!caliptra_test_for_completion()){ - caliptra_wait(); - } - - status = caliptra_complete(); - } - - if (status) - { - printf("Get FIPS Version failed: 0x%x\n", status); - failure = 1; - } - else - { - int last_char = sizeof(version.name) - 1; - version.name[last_char] = 0; - printf("FIPS_VERSION = mode: 0x%x, fips_rev (0x%x, 0x%x, 0x%x), name %s \n", version.mode, - version.fips_rev[0], version.fips_rev[1], version.fips_rev[2], version.name); - } - - // Send a stash measurement command with async off - // Need some representative values for these, see below. - struct caliptra_stash_measurement_req r = {0}; - struct caliptra_stash_measurement_resp c = {0}; - - status = caliptra_stash_measurement(&r, &c, false); - - if (status) { - printf("Stash measurement failed: 0x%x\n", status); - failure = 1; - } else { - printf("Stash measurement: OK\n"); - } - - return failure; + int failure = 0; + int status = boot_to_ready_for_fw(info, false); + + if (status) + { + failure = 1; + } + + // Load Image Bundle + // FW_PATH is defined on the compiler command line + status = caliptra_upload_fw(&info->image_bundle, false); + + if (status) + { + printf("FW Load Failed: 0x%x\n", status); + failure = 1; + } + else + { + printf("FW Load: OK\n"); + } + + // Send a FIPS version command in async mode + struct caliptra_fips_version_resp version; + // Send async + status = caliptra_fips_version(&version, true); + + if (status) + { + printf("Get FIPS Version send failed: 0x%x\n", status); + failure = 1; + } + else + { + // Wait indefinitely for completion + while (!caliptra_test_for_completion()) + { + caliptra_wait(); + } + + status = caliptra_complete(); + } + + if (status) + { + printf("Get FIPS Version failed: 0x%x\n", status); + failure = 1; + } + else + { + int last_char = sizeof(version.name) - 1; + version.name[last_char] = 0; + printf("FIPS_VERSION = mode: 0x%x, fips_rev (0x%x, 0x%x, 0x%x), name %s \n", version.mode, + version.fips_rev[0], version.fips_rev[1], version.fips_rev[2], version.name); + } + + // Send a stash measurement command with async off + // Need some representative values for these, see below. + struct caliptra_stash_measurement_req r = {0}; + struct caliptra_stash_measurement_resp c = {0}; + + status = caliptra_stash_measurement(&r, &c, false); + + if (status) + { + printf("Stash measurement failed: 0x%x\n", status); + failure = 1; + } + else + { + printf("Stash measurement: OK\n"); + } + + return failure; } // Issue every ROM command // Intent is just to make sure ROM accepts the command ID and the payload // Not attempting to actually test command functionality -int rom_test_all_commands(const test_info* info) +int rom_test_all_commands(const test_info *info) { - int failure = 0; - int status = boot_to_ready_for_fw(info, false); - - if (status){ - dump_caliptra_error_codes(); - failure = 1; - } - - // NOTE: Response structs are uninitialized to confirm libcaliptra handles this properly - // STASH_MEASUREMENT - struct caliptra_stash_measurement_req stash_req = {}; - struct caliptra_stash_measurement_resp stash_resp; - - status = caliptra_stash_measurement(&stash_req, &stash_resp, false); - - if (status) { - printf("Stash Measurement failed: 0x%x\n", status); - dump_caliptra_error_codes(); - failure = 1; - } else { - printf("Stash Measurement: OK\n"); - } - - // CAPABILITIES - struct caliptra_capabilities_resp cap_resp; - - status = caliptra_capabilities(&cap_resp, false); - - if (status) { - printf("Capabilities failed: 0x%x\n", status); - dump_caliptra_error_codes(); - failure = 1; - } else { - printf("Capabilities: OK\n"); - } - - // FIPS_VERSION - struct caliptra_fips_version_resp version_resp; - - status = caliptra_fips_version(&version_resp, false); - - if (status) { - printf("FIPS Version failed: 0x%x\n", status); - dump_caliptra_error_codes(); - failure = 1; - } else { - printf("FIPS Version: OK\n"); - } - - // SELF_TEST_START - status = caliptra_self_test_start(false); - - if (status) { - printf("FIPS Self Test Start failed: 0x%x\n", status); - dump_caliptra_error_codes(); - failure = 1; - } else { - printf("FIPS Self Test Start: OK\n"); - } - - // SELF_TEST_GET_RESULTS - status = caliptra_self_test_get_results(false); - - if (status) { - printf("FIPS Self Test Get Results failed: 0x%x\n", status); - dump_caliptra_error_codes(); - failure = 1; - } else { - printf("FIPS Self Test Get Results: OK\n"); - } - - // SHUTDOWN - status = caliptra_shutdown(false); - - if (status) { - printf("FIPS Shutdown failed: 0x%x\n", status); - dump_caliptra_error_codes(); - failure = 1; - } else { - printf("FIPS Shutdown: OK\n"); - } - - return failure; + int failure = 0; + int status = boot_to_ready_for_fw(info, false); + + if (status) + { + dump_caliptra_error_codes(); + failure = 1; + } + + // NOTE: Response structs are uninitialized to confirm libcaliptra handles this properly + // STASH_MEASUREMENT + struct caliptra_stash_measurement_req stash_req = {}; + struct caliptra_stash_measurement_resp stash_resp; + + status = caliptra_stash_measurement(&stash_req, &stash_resp, false); + + if (status) + { + printf("Stash Measurement failed: 0x%x\n", status); + dump_caliptra_error_codes(); + failure = 1; + } + else + { + printf("Stash Measurement: OK\n"); + } + + // CAPABILITIES + struct caliptra_capabilities_resp cap_resp; + + status = caliptra_capabilities(&cap_resp, false); + + if (status) + { + printf("Capabilities failed: 0x%x\n", status); + dump_caliptra_error_codes(); + failure = 1; + } + else + { + printf("Capabilities: OK\n"); + } + + // FIPS_VERSION + struct caliptra_fips_version_resp version_resp; + + status = caliptra_fips_version(&version_resp, false); + + if (status) + { + printf("FIPS Version failed: 0x%x\n", status); + dump_caliptra_error_codes(); + failure = 1; + } + else + { + printf("FIPS Version: OK\n"); + } + + // SELF_TEST_START + status = caliptra_self_test_start(false); + + if (status) + { + printf("FIPS Self Test Start failed: 0x%x\n", status); + dump_caliptra_error_codes(); + failure = 1; + } + else + { + printf("FIPS Self Test Start: OK\n"); + } + + // SELF_TEST_GET_RESULTS + status = caliptra_self_test_get_results(false); + + if (status) + { + printf("FIPS Self Test Get Results failed: 0x%x\n", status); + dump_caliptra_error_codes(); + failure = 1; + } + else + { + printf("FIPS Self Test Get Results: OK\n"); + } + + // SHUTDOWN + status = caliptra_shutdown(false); + + if (status) + { + printf("FIPS Shutdown failed: 0x%x\n", status); + dump_caliptra_error_codes(); + failure = 1; + } + else + { + printf("FIPS Shutdown: OK\n"); + } + + return failure; } // Issue every runtime command // Intent is just to make sure FW accepts the command ID and the payload // Not attempting to actually test command functionality -int rt_test_all_commands(const test_info* info) +int rt_test_all_commands(const test_info *info) { - int failure = 0; - uint32_t non_fatal_error; - int status = boot_to_ready_for_fw(info, false); - - if (status){ - failure = 1; - } - - // NOTE: Response structs are uninitialized to confirm libcaliptra handles this properly - // Load Image Bundle - // FW_PATH is defined on the compiler command line - status = caliptra_upload_fw(&info->image_bundle, false); - - if (status) - { - printf("FW Load Failed: 0x%x\n", status); - dump_caliptra_error_codes(); - failure = 1; - } else { - printf("FW Load: OK\n"); - } - - // GET_IDEV_CERT - struct caliptra_get_idev_cert_req idev_cert_req = {}; - struct caliptra_get_idev_cert_resp idev_cert_resp; - - status = caliptra_get_idev_cert(&idev_cert_req, &idev_cert_resp, false); - - if (status) { - printf("Get IDEV Cert failed: 0x%x\n", status); - dump_caliptra_error_codes(); - failure = 1; - } else { - printf("Get IDEV Cert: OK\n"); - } - - // GET_IDEV_INFO - struct caliptra_get_idev_info_resp idev_info_resp; - - status = caliptra_get_idev_info(&idev_info_resp, false); - - if (status) { - printf("Get IDEV Info: 0x%x\n", status); - dump_caliptra_error_codes(); - failure = 1; - } else { - printf("Get IDEV Info: OK\n"); - } - - // POPULATE_IDEV_CERT - struct caliptra_populate_idev_cert_req populate_idev_req = {}; - - status = caliptra_populate_idev_cert(&populate_idev_req, false); - - if (status) { - printf("Populate IDEV Cert failed: 0x%x\n", status); - dump_caliptra_error_codes(); - failure = 1; - } else { - printf("Populate IDEV Cert: OK\n"); - } - - // GET_LDEV_CERT - struct caliptra_get_ldev_cert_resp ldev_cert_resp; - - status = caliptra_get_ldev_cert(&ldev_cert_resp, false); - - if (status) { - printf("Get LDEV Cert failed: 0x%x\n", status); - dump_caliptra_error_codes(); - failure = 1; - } else { - printf("Get LDEV Cert: OK\n"); - } - - // GET_FMC_ALIAS_CERT - struct caliptra_get_fmc_alias_cert_resp fmc_alias_cert_resp; - - status = caliptra_get_fmc_alias_cert(&fmc_alias_cert_resp, false); - - if (status) { - printf("Get FMC Alias Cert failed: 0x%x\n", status); - dump_caliptra_error_codes(); - failure = 1; - } else { - printf("Get FMC Alias Cert: OK\n"); - } - - // GET_RT_ALIAS_CERT - struct caliptra_get_rt_alias_cert_resp rt_alias_cert_resp; - - status = caliptra_get_rt_alias_cert(&rt_alias_cert_resp, false); - - if (status) { - printf("Get Runtime Alias Cert failed: 0x%x\n", status); - dump_caliptra_error_codes(); - failure = 1; - } else { - printf("Get Runtime Alias Cert: OK\n"); - } - - // ECDSA384_VERIFY - struct caliptra_ecdsa_verify_req ecdsa_req = {}; - - status = caliptra_ecdsa384_verify(&ecdsa_req, false); - - // Not testing for full success - // Instead, just want to see it give the right ECC-specific error - // This still proves the FW recognizes the message and request data and got to the right ECC code - uint32_t DRIVER_ECC384_KEYGEN_BAD_USAGE = 0x5000f; - non_fatal_error = caliptra_read_fw_non_fatal_error(); - if (status != MBX_STATUS_FAILED || non_fatal_error != DRIVER_ECC384_KEYGEN_BAD_USAGE) { - printf("ECDSA384 Verify unexpected result/failure: 0x%x\n", status); - dump_caliptra_error_codes(); - failure = 1; - } else { - printf("ECDSA384 Verify: OK\n"); - } - - // LMS_VERIFY - struct caliptra_lms_verify_req lms_req = {}; - - status = caliptra_lms_verify(&lms_req, false); - - // Not testing for full success - // Instead, just want to see it give the right LMS-specific error - // This still proves the FW recognizes the message and request data and got to the right LMS code - uint32_t RUNTIME_LMS_VERIFY_INVALID_LMS_ALGORITHM = 0xE0043; - non_fatal_error = caliptra_read_fw_non_fatal_error(); - if (status != MBX_STATUS_FAILED || non_fatal_error != RUNTIME_LMS_VERIFY_INVALID_LMS_ALGORITHM) { - printf("LMS Verify unexpected result/failure: 0x%x\n", status); - dump_caliptra_error_codes(); - failure = 1; - } else { - printf("LMS Verify: OK\n"); - } - - // STASH_MEASUREMENT - struct caliptra_stash_measurement_req stash_req = {}; - struct caliptra_stash_measurement_resp stash_resp; - - status = caliptra_stash_measurement(&stash_req, &stash_resp, false); - - if (status) { - printf("Stash Measurement failed: 0x%x\n", status); - dump_caliptra_error_codes(); - failure = 1; - } else { - printf("Stash Measurement: OK\n"); - } - - // INVOKE_DPE_COMMAND - // Using GET_PROFILE as an example command - // TODO: Coverage of other DPE commands should be added - struct caliptra_invoke_dpe_req dpe_req = {}; - struct caliptra_invoke_dpe_resp dpe_resp; - - dpe_req.data_size = sizeof(struct dpe_get_profile_cmd); - dpe_req.get_profile_cmd.cmd_hdr.magic = DPE_MAGIC; - dpe_req.get_profile_cmd.cmd_hdr.cmd_id = DPE_GET_PROFILE; - dpe_req.get_profile_cmd.cmd_hdr.profile = 0x2; - - status = caliptra_invoke_dpe_command(&dpe_req, &dpe_resp, false); - - if (status) { - printf("DPE Command failed: 0x%x\n", status); - dump_caliptra_error_codes(); - failure = 1; - } else { - printf("DPE Command: OK\n"); - } - - - // FW_INFO - struct caliptra_fw_info_resp fw_info_resp; - - status = caliptra_fw_info(&fw_info_resp, false); - - if (status) { - printf("FW Info failed: 0x%x\n", status); - dump_caliptra_error_codes(); - failure = 1; - } else { - printf("FW Info: OK\n"); - } - - // DPE_TAG_TCI - struct caliptra_dpe_tag_tci_req tag_tci_req = {}; - - status = caliptra_dpe_tag_tci(&tag_tci_req, false); - - if (status) { - printf("DPE Tag TCI failed: 0x%x\n", status); - dump_caliptra_error_codes(); - failure = 1; - } else { - printf("DPE Tag TCI: OK\n"); - } - - // DPE_GET_TAGGED_TCI - struct caliptra_get_tagged_tci_req get_tagged_tci_req = {}; - struct caliptra_get_tagged_tci_resp get_tagged_tci_resp; - - status = caliptra_dpe_get_tagged_tci(&get_tagged_tci_req, &get_tagged_tci_resp, false); - - if (status) { - printf("DPE Get Tagged TCI failed: 0x%x\n", status); - dump_caliptra_error_codes(); - failure = 1; - } else { - printf("DPE Get Tagged TCI: OK\n"); - } - - // Increment PCR Reset Counter - struct caliptra_increment_pcr_reset_counter_req inc_pcr_rst_cntr_req = {}; - - status = caliptra_increment_pcr_reset_counter(&inc_pcr_rst_cntr_req, false); - - if (status) { - printf("Increment PCR Reset Counter failed: 0x%x\n", status); - dump_caliptra_error_codes(); - failure = 1; - } else { - printf("Increment PCR Reset Counter: OK\n"); - } - - // Quote PCRs - struct caliptra_quote_pcrs_req quote_pcrs_req = {}; - struct caliptra_quote_pcrs_resp quote_pcrs_resp; - - status = caliptra_quote_pcrs("e_pcrs_req, "e_pcrs_resp, false); - - if (status) { - printf("Quote PCRs failed: 0x%x\n", status); - dump_caliptra_error_codes(); - failure = 1; - } else { - printf("Quote PCRs: OK\n"); - } - - // Extend PCR - struct caliptra_extend_pcr_req extend_pcr_req = {}; - extend_pcr_req.pcr_idx = 0x4; // First non-reserved index - - status = caliptra_extend_pcr(&extend_pcr_req, false); - - if (status) { - printf("Extend PCR failed: 0x%x\n", status); - dump_caliptra_error_codes(); - failure = 1; - } else { - printf("Extend PCR: OK\n"); - } - - // Add subject alt name - struct caliptra_add_subject_alt_name_req add_subject_alt_name_req = {}; - strcpy((char *)add_subject_alt_name_req.dmtf_device_info, "ChipsAlliance:Caliptra:0123456789"); - add_subject_alt_name_req.dmtf_device_info_size = strlen((char *)add_subject_alt_name_req.dmtf_device_info); - - status = caliptra_add_subject_alt_name(&add_subject_alt_name_req, false); - - if (status) { - printf("Add Subject Alt Name failed: 0x%x\n", status); - dump_caliptra_error_codes(); - failure = 1; - } else { - printf("Add Subject Alt Name: OK\n"); - } - - // Certify key extended - int caliptra_certify_key_extended(struct caliptra_certify_key_extended_req *req, struct caliptra_certify_key_extended_resp *resp, bool async); - struct caliptra_certify_key_extended_req certify_key_extended_req = {}; - struct caliptra_certify_key_extended_resp certify_key_extended_resp; - - status = caliptra_certify_key_extended(&certify_key_extended_req, &certify_key_extended_resp, false); - - if (status) { - printf("Certify Key Extended failed: 0x%x\n", status); - dump_caliptra_error_codes(); - failure = 1; - } else { - printf("Certify Key Extended: OK\n"); - } - - - // FIPS_VERSION - struct caliptra_fips_version_resp version_resp; - - status = caliptra_fips_version(&version_resp, false); - - if (status) { - printf("FIPS Version failed: 0x%x\n", status); - dump_caliptra_error_codes(); - failure = 1; - } else { - printf("FIPS Version: OK\n"); - } - - // SELF_TEST_START - status = caliptra_self_test_start(false); - - if (status) { - printf("FIPS Self Test Start failed: 0x%x\n", status); - dump_caliptra_error_codes(); - failure = 1; - } else { - printf("FIPS Self Test Start: OK\n"); - } - - // Give self test time to run - for (int i = 0; i < 4000000; i++){ - caliptra_wait(); - } - - // SELF_TEST_GET_RESULTS - status = caliptra_self_test_get_results(false); - - if (status) { - printf("FIPS Self Test Get Results failed: 0x%x\n", status); - dump_caliptra_error_codes(); - failure = 1; - } else { - printf("FIPS Self Test Get Results: OK\n"); - } - - // These commands are last since they cause lasting affects on the runtime - // DISABLE_ATTESTATION - status = caliptra_disable_attestation(false); - - if (status) { - printf("Disable Attestation failed: 0x%x\n", status); - dump_caliptra_error_codes(); - failure = 1; - } else { - printf("Disable Attestation: OK\n"); - } - - // SHUTDOWN - status = caliptra_shutdown(false); - - if (status) { - printf("FIPS Shutdown failed: 0x%x\n", status); - dump_caliptra_error_codes(); - failure = 1; - } else { - printf("FIPS Shutdown: OK\n"); - } - - return failure; + int failure = 0; + uint32_t non_fatal_error; + int status = boot_to_ready_for_fw(info, false); + + if (status) + { + failure = 1; + } + + // NOTE: Response structs are uninitialized to confirm libcaliptra handles this properly + // Load Image Bundle + // FW_PATH is defined on the compiler command line + status = caliptra_upload_fw(&info->image_bundle, false); + + if (status) + { + printf("FW Load Failed: 0x%x\n", status); + dump_caliptra_error_codes(); + failure = 1; + } + else + { + printf("FW Load: OK\n"); + } + + // GET_IDEV_CERT + struct caliptra_get_idev_cert_req idev_cert_req = {}; + struct caliptra_get_idev_cert_resp idev_cert_resp; + + status = caliptra_get_idev_cert(&idev_cert_req, &idev_cert_resp, false); + + if (status) + { + printf("Get IDEV Cert failed: 0x%x\n", status); + dump_caliptra_error_codes(); + failure = 1; + } + else + { + printf("Get IDEV Cert: OK\n"); + } + + // GET_IDEV_INFO + struct caliptra_get_idev_info_resp idev_info_resp; + + status = caliptra_get_idev_info(&idev_info_resp, false); + + if (status) + { + printf("Get IDEV Info: 0x%x\n", status); + dump_caliptra_error_codes(); + failure = 1; + } + else + { + printf("Get IDEV Info: OK\n"); + } + + // POPULATE_IDEV_CERT + struct caliptra_populate_idev_cert_req populate_idev_req = {}; + + status = caliptra_populate_idev_cert(&populate_idev_req, false); + + if (status) + { + printf("Populate IDEV Cert failed: 0x%x\n", status); + dump_caliptra_error_codes(); + failure = 1; + } + else + { + printf("Populate IDEV Cert: OK\n"); + } + + // GET_LDEV_CERT + struct caliptra_get_ldev_cert_resp ldev_cert_resp; + + status = caliptra_get_ldev_cert(&ldev_cert_resp, false); + + if (status) + { + printf("Get LDEV Cert failed: 0x%x\n", status); + dump_caliptra_error_codes(); + failure = 1; + } + else + { + printf("Get LDEV Cert: OK\n"); + } + + // GET_FMC_ALIAS_CERT + struct caliptra_get_fmc_alias_cert_resp fmc_alias_cert_resp; + + status = caliptra_get_fmc_alias_cert(&fmc_alias_cert_resp, false); + + if (status) + { + printf("Get FMC Alias Cert failed: 0x%x\n", status); + dump_caliptra_error_codes(); + failure = 1; + } + else + { + printf("Get FMC Alias Cert: OK\n"); + } + + // GET_RT_ALIAS_CERT + struct caliptra_get_rt_alias_cert_resp rt_alias_cert_resp; + + status = caliptra_get_rt_alias_cert(&rt_alias_cert_resp, false); + + if (status) + { + printf("Get Runtime Alias Cert failed: 0x%x\n", status); + dump_caliptra_error_codes(); + failure = 1; + } + else + { + printf("Get Runtime Alias Cert: OK\n"); + } + + // ECDSA384_VERIFY + struct caliptra_ecdsa_verify_req ecdsa_req = {}; + + status = caliptra_ecdsa384_verify(&ecdsa_req, false); + + // Not testing for full success + // Instead, just want to see it give the right ECC-specific error + // This still proves the FW recognizes the message and request data and got to the right ECC code + uint32_t DRIVER_ECC384_KEYGEN_BAD_USAGE = 0x5000f; + non_fatal_error = caliptra_read_fw_non_fatal_error(); + if (status != MBX_STATUS_FAILED || non_fatal_error != DRIVER_ECC384_KEYGEN_BAD_USAGE) + { + printf("ECDSA384 Verify unexpected result/failure: 0x%x\n", status); + dump_caliptra_error_codes(); + failure = 1; + } + else + { + printf("ECDSA384 Verify: OK\n"); + } + + // LMS_VERIFY + struct caliptra_lms_verify_req lms_req = {}; + + status = caliptra_lms_verify(&lms_req, false); + + // Not testing for full success + // Instead, just want to see it give the right LMS-specific error + // This still proves the FW recognizes the message and request data and got to the right LMS code + uint32_t RUNTIME_LMS_VERIFY_INVALID_LMS_ALGORITHM = 0xE0043; + non_fatal_error = caliptra_read_fw_non_fatal_error(); + if (status != MBX_STATUS_FAILED || non_fatal_error != RUNTIME_LMS_VERIFY_INVALID_LMS_ALGORITHM) + { + printf("LMS Verify unexpected result/failure: 0x%x\n", status); + dump_caliptra_error_codes(); + failure = 1; + } + else + { + printf("LMS Verify: OK\n"); + } + + // STASH_MEASUREMENT + struct caliptra_stash_measurement_req stash_req = {}; + struct caliptra_stash_measurement_resp stash_resp; + + status = caliptra_stash_measurement(&stash_req, &stash_resp, false); + + if (status) + { + printf("Stash Measurement failed: 0x%x\n", status); + dump_caliptra_error_codes(); + failure = 1; + } + else + { + printf("Stash Measurement: OK\n"); + } + + // INVOKE_DPE_COMMAND + // Using GET_PROFILE as an example command + // TODO: Coverage of other DPE commands should be added + struct caliptra_invoke_dpe_req dpe_req = {}; + struct caliptra_invoke_dpe_resp dpe_resp; + + dpe_req.data_size = sizeof(struct dpe_get_profile_cmd); + dpe_req.get_profile_cmd.cmd_hdr.magic = DPE_MAGIC; + dpe_req.get_profile_cmd.cmd_hdr.cmd_id = DPE_GET_PROFILE; + dpe_req.get_profile_cmd.cmd_hdr.profile = 0x2; + + status = caliptra_invoke_dpe_command(&dpe_req, &dpe_resp, false); + + if (status) + { + printf("DPE Command failed: 0x%x\n", status); + dump_caliptra_error_codes(); + failure = 1; + } + else + { + printf("DPE Command: OK\n"); + } + + // FW_INFO + struct caliptra_fw_info_resp fw_info_resp; + + status = caliptra_fw_info(&fw_info_resp, false); + + if (status) + { + printf("FW Info failed: 0x%x\n", status); + dump_caliptra_error_codes(); + failure = 1; + } + else + { + printf("FW Info: OK\n"); + } + + // DPE_TAG_TCI + struct caliptra_dpe_tag_tci_req tag_tci_req = {}; + + status = caliptra_dpe_tag_tci(&tag_tci_req, false); + + if (status) + { + printf("DPE Tag TCI failed: 0x%x\n", status); + dump_caliptra_error_codes(); + failure = 1; + } + else + { + printf("DPE Tag TCI: OK\n"); + } + + // DPE_GET_TAGGED_TCI + struct caliptra_get_tagged_tci_req get_tagged_tci_req = {}; + struct caliptra_get_tagged_tci_resp get_tagged_tci_resp; + + status = caliptra_dpe_get_tagged_tci(&get_tagged_tci_req, &get_tagged_tci_resp, false); + + if (status) + { + printf("DPE Get Tagged TCI failed: 0x%x\n", status); + dump_caliptra_error_codes(); + failure = 1; + } + else + { + printf("DPE Get Tagged TCI: OK\n"); + } + + // Increment PCR Reset Counter + struct caliptra_increment_pcr_reset_counter_req inc_pcr_rst_cntr_req = {}; + + status = caliptra_increment_pcr_reset_counter(&inc_pcr_rst_cntr_req, false); + + if (status) + { + printf("Increment PCR Reset Counter failed: 0x%x\n", status); + dump_caliptra_error_codes(); + failure = 1; + } + else + { + printf("Increment PCR Reset Counter: OK\n"); + } + + // Quote PCRs + struct caliptra_quote_pcrs_req quote_pcrs_req = {}; + struct caliptra_quote_pcrs_resp quote_pcrs_resp; + + status = caliptra_quote_pcrs("e_pcrs_req, "e_pcrs_resp, false); + + if (status) + { + printf("Quote PCRs failed: 0x%x\n", status); + dump_caliptra_error_codes(); + failure = 1; + } + else + { + printf("Quote PCRs: OK\n"); + } + + // Extend PCR + struct caliptra_extend_pcr_req extend_pcr_req = {}; + extend_pcr_req.pcr_idx = 0x4; // First non-reserved index + + status = caliptra_extend_pcr(&extend_pcr_req, false); + + if (status) + { + printf("Extend PCR failed: 0x%x\n", status); + dump_caliptra_error_codes(); + failure = 1; + } + else + { + printf("Extend PCR: OK\n"); + } + + // Add subject alt name + struct caliptra_add_subject_alt_name_req add_subject_alt_name_req = {}; + strcpy((char *)add_subject_alt_name_req.dmtf_device_info, "ChipsAlliance:Caliptra:0123456789"); + add_subject_alt_name_req.dmtf_device_info_size = strlen((char *)add_subject_alt_name_req.dmtf_device_info); + + status = caliptra_add_subject_alt_name(&add_subject_alt_name_req, false); + + if (status) + { + printf("Add Subject Alt Name failed: 0x%x\n", status); + dump_caliptra_error_codes(); + failure = 1; + } + else + { + printf("Add Subject Alt Name: OK\n"); + } + + // Certify key extended + int caliptra_certify_key_extended(struct caliptra_certify_key_extended_req * req, struct caliptra_certify_key_extended_resp * resp, bool async); + struct caliptra_certify_key_extended_req certify_key_extended_req = {}; + struct caliptra_certify_key_extended_resp certify_key_extended_resp; + + status = caliptra_certify_key_extended(&certify_key_extended_req, &certify_key_extended_resp, false); + + if (status) + { + printf("Certify Key Extended failed: 0x%x\n", status); + dump_caliptra_error_codes(); + failure = 1; + } + else + { + printf("Certify Key Extended: OK\n"); + } + + // FIPS_VERSION + struct caliptra_fips_version_resp version_resp; + + status = caliptra_fips_version(&version_resp, false); + + if (status) + { + printf("FIPS Version failed: 0x%x\n", status); + dump_caliptra_error_codes(); + failure = 1; + } + else + { + printf("FIPS Version: OK\n"); + } + + // SELF_TEST_START + status = caliptra_self_test_start(false); + + if (status) + { + printf("FIPS Self Test Start failed: 0x%x\n", status); + dump_caliptra_error_codes(); + failure = 1; + } + else + { + printf("FIPS Self Test Start: OK\n"); + } + + // Give self test time to run + for (int i = 0; i < 4000000; i++) + { + caliptra_wait(); + } + + // SELF_TEST_GET_RESULTS + status = caliptra_self_test_get_results(false); + + if (status) + { + printf("FIPS Self Test Get Results failed: 0x%x\n", status); + dump_caliptra_error_codes(); + failure = 1; + } + else + { + printf("FIPS Self Test Get Results: OK\n"); + } + + // These commands are last since they cause lasting affects on the runtime + // DISABLE_ATTESTATION + status = caliptra_disable_attestation(false); + + if (status) + { + printf("Disable Attestation failed: 0x%x\n", status); + dump_caliptra_error_codes(); + failure = 1; + } + else + { + printf("Disable Attestation: OK\n"); + } + + // SHUTDOWN + status = caliptra_shutdown(false); + + if (status) + { + printf("FIPS Shutdown failed: 0x%x\n", status); + dump_caliptra_error_codes(); + failure = 1; + } + else + { + printf("FIPS Shutdown: OK\n"); + } + + return failure; } -int rom_test_devid_csr(const test_info* info) +int rom_test_devid_csr(const test_info *info) { - int failure = 0; - - struct caliptra_buffer caliptra_idevid_csr_buf = {0}; - caliptra_idevid_csr_buf.len = IDEV_CSR_LEN; - // Allocte a buffer to hold the IDEV CSR using malloc - caliptra_idevid_csr_buf.data = malloc(caliptra_idevid_csr_buf.len); - - // Check if the buffer was allocated successfully - if (caliptra_idevid_csr_buf.data == NULL) { - printf("Failed to allocate memory for IDEV CSR\n"); - return 1; - } - - bool request_csr = true; - int status = boot_to_ready_for_fw(info, request_csr); - - if (status){ - dump_caliptra_error_codes(); - failure = 1; - } - - caliptra_wait_for_csr_ready(); - - - int ret; - // Retrieve the IDEV CSR - if ((ret = caliptra_retrieve_idevid_csr(&caliptra_idevid_csr_buf)) != NO_ERROR) { - printf("Failed to retrieve IDEV CSR\n"); - printf("Error is 0x%x\n", ret); - failure = 1; - } else { - printf("IDEV CSR retrieved\n"); - } - - // Compare the retrieved IDEV CSR with the expected IDEV CSR - if (memcmp(caliptra_idevid_csr_buf.data, idev_csr_bytes, caliptra_idevid_csr_buf.len) != 0) { - printf("IDEV CSR does not match\n"); + int failure = 0; + + struct caliptra_buffer caliptra_idevid_csr_buf = {0}; + caliptra_idevid_csr_buf.len = IDEV_CSR_LEN; + // Allocte a buffer to hold the IDEV CSR using malloc + caliptra_idevid_csr_buf.data = malloc(caliptra_idevid_csr_buf.len); + + // Check if the buffer was allocated successfully + if (caliptra_idevid_csr_buf.data == NULL) + { + printf("Failed to allocate memory for IDEV CSR\n"); + return 1; + } + + bool request_csr = true; + int status = boot_to_ready_for_fw(info, request_csr); + + if (status) + { + dump_caliptra_error_codes(); + failure = 1; + } + + caliptra_wait_for_csr_ready(); + + int ret; + // Retrieve the IDEV CSR + if ((ret = caliptra_retrieve_idevid_csr(&caliptra_idevid_csr_buf)) != NO_ERROR) + { + printf("Failed to retrieve IDEV CSR\n"); + printf("Error is 0x%x\n", ret); + failure = 1; + } + else + { + printf("IDEV CSR retrieved\n"); + } + + // Compare the retrieved IDEV CSR with the expected IDEV CSR + if (memcmp(caliptra_idevid_csr_buf.data, idev_csr_bytes, caliptra_idevid_csr_buf.len) != 0) + { + printf("IDEV CSR does not match\n"); #ifdef ENABLE_DEBUG - dump_array_to_file(&caliptra_idevid_csr_buf, "retrieved.bin"); + dump_array_to_file(&caliptra_idevid_csr_buf, "retrieved.bin"); #endif - failure = 1; - } else { - printf("IDEV CSR matches\n"); - } - - caliptra_req_idev_csr_complete(); - caliptra_ready_for_firmware(); - - // Test Get Idev CSR now that a CSR is provisioned. - // GET IDEV CSR - struct caliptra_get_idev_csr_resp csr_resp = {0}; - - status = caliptra_get_idev_csr(&csr_resp, false); - - if (status) { - printf("Get IDev CSR failed: 0x%x\n", status); - dump_caliptra_error_codes(); - failure = 1; - } else { - if (memcmp(csr_resp.data, idev_csr_bytes, csr_resp.data_size) != 0) { - printf("IDEV CSR does not match\n"); - failure = 1; - } else { - printf("Get IDev CSR: OK\n"); - } - } - - free((void*)caliptra_idevid_csr_buf.data); - return failure; + failure = 1; + } + else + { + printf("IDEV CSR matches\n"); + } + + caliptra_req_idev_csr_complete(); + caliptra_ready_for_firmware(); + + // Test Get Idev CSR now that a CSR is provisioned. + // GET IDEV CSR + struct caliptra_get_idev_csr_resp csr_resp = {0}; + + status = caliptra_get_idev_csr(&csr_resp, false); + + if (status) + { + printf("Get IDev CSR failed: 0x%x\n", status); + dump_caliptra_error_codes(); + failure = 1; + } + else + { + if (memcmp(csr_resp.data, idev_csr_bytes, csr_resp.data_size) != 0) + { + printf("IDEV CSR does not match\n"); + failure = 1; + } + else + { + printf("Get IDev CSR: OK\n"); + } + } + + free((void *)caliptra_idevid_csr_buf.data); + return failure; } // Issue FW load commands repeatedly // Coverage for piecewise FW load and runtime FW updates -int upload_fw_piecewise(const test_info* info) +int upload_fw_piecewise(const test_info *info) { - int failure = 0; - int status = boot_to_ready_for_fw(info, false); - - if (status){ - printf("Failed to boot to ready for FW: 0x%x\n", status); - failure = 1; - } - - // Some "random" size to split up the FW load into chunks - // These represent the first two chunks, the third chunk is the remainder of the image - // Sizes of 0 are ignored (meaning one fewer chunk is sent) - uint32_t chunk_sizes[][2] = { - {0x4, 0}, - {0x1000, 0}, - {0x1234, 0}, - {0xe924, 0}, - {0x8, 0x2000}, - {0x2340, 0x4}, - {0x388, 0x1844}, - }; - - // Load FW in a loop, using the offsets above as points to split chunks - for (int i = 0; i < CALIPTRA_ARRAY_SIZE(chunk_sizes); i++) { - // Start the FW load - uint32_t total_fw_size = info->image_bundle.len; - status = caliptra_upload_fw_start_req(total_fw_size); - - if (status) - { - printf("FW Load %d Start Failed: 0x%x\n", i, status); - dump_caliptra_error_codes(); - failure = 1; - } else { - printf("FW Load %d Start: OK\n", i); - } - - // Ensure other commands report busy during this process - struct caliptra_fips_version_resp version_resp; - status = caliptra_fips_version(&version_resp, false); - if (status != MBX_BUSY) { - printf("Command during piecewise FW load should report MBX_BUSY. Result was: 0x%x\n", status); - failure = 1; - } - - uint32_t sent_bytes = 0; - uint8_t chunk_count = 0; - // Upload each of up to 3 chunks - // The size of the first two chunks comes from the table above - // The final chunk is the remainder - // Some chunks may be skipped if their size is 0 in the table - for (int j = 0; j < 3; j++){ - uint32_t chunk_size; - if (j == 2) { - // Final chunk - chunk_size = total_fw_size - sent_bytes; - } else { - chunk_size = chunk_sizes[i][j]; - } - - if (chunk_size != 0){ - // Set up the caliptra_buffer for the chunk and send it - struct caliptra_buffer fw_chunk = {.data = info->image_bundle.data + sent_bytes, .len = chunk_size}; - status = caliptra_upload_fw_send_data(&fw_chunk); - - if (status) - { - printf("FW Load %d Send Data chunk %d (%d bytes) Failed: 0x%x\n", i, chunk_count, status, chunk_size); - dump_caliptra_error_codes(); - failure = 1; - } else { - printf("FW Load %d Send Data chunk %d (%d bytes): OK\n", i, chunk_count, chunk_size); - } - - // Track what has been sent - sent_bytes += chunk_size; - chunk_count++; - } - } - - // Finish the FW load - status = caliptra_upload_fw_end_req(false); - - if (status) - { - printf("FW Load %d End Failed: 0x%x\n", i, status); - dump_caliptra_error_codes(); - failure = 1; - } else { - printf("FW Load %d End: OK\n", i); - } - } - - return failure; + int failure = 0; + int status = boot_to_ready_for_fw(info, false); + + if (status) + { + printf("Failed to boot to ready for FW: 0x%x\n", status); + failure = 1; + } + + // Some "random" size to split up the FW load into chunks + // These represent the first two chunks, the third chunk is the remainder of the image + // Sizes of 0 are ignored (meaning one fewer chunk is sent) + uint32_t chunk_sizes[][2] = { + {0x4, 0}, + {0x1000, 0}, + {0x1234, 0}, + {0xe924, 0}, + {0x8, 0x2000}, + {0x2340, 0x4}, + {0x388, 0x1844}, + }; + + // Load FW in a loop, using the offsets above as points to split chunks + for (int i = 0; i < CALIPTRA_ARRAY_SIZE(chunk_sizes); i++) + { + // Start the FW load + uint32_t total_fw_size = info->image_bundle.len; + status = caliptra_upload_fw_start_req(total_fw_size); + + if (status) + { + printf("FW Load %d Start Failed: 0x%x\n", i, status); + dump_caliptra_error_codes(); + failure = 1; + } + else + { + printf("FW Load %d Start: OK\n", i); + } + + // Ensure other commands report busy during this process + struct caliptra_fips_version_resp version_resp; + status = caliptra_fips_version(&version_resp, false); + if (status != MBX_BUSY) + { + printf("Command during piecewise FW load should report MBX_BUSY. Result was: 0x%x\n", status); + failure = 1; + } + + uint32_t sent_bytes = 0; + uint8_t chunk_count = 0; + // Upload each of up to 3 chunks + // The size of the first two chunks comes from the table above + // The final chunk is the remainder + // Some chunks may be skipped if their size is 0 in the table + for (int j = 0; j < 3; j++) + { + uint32_t chunk_size; + if (j == 2) + { + // Final chunk + chunk_size = total_fw_size - sent_bytes; + } + else + { + chunk_size = chunk_sizes[i][j]; + } + + if (chunk_size != 0) + { + // Set up the caliptra_buffer for the chunk and send it + struct caliptra_buffer fw_chunk = {.data = info->image_bundle.data + sent_bytes, .len = chunk_size}; + status = caliptra_upload_fw_send_data(&fw_chunk); + + if (status) + { + printf("FW Load %d Send Data chunk %d (%d bytes) Failed: 0x%x\n", i, chunk_count, status, chunk_size); + dump_caliptra_error_codes(); + failure = 1; + } + else + { + printf("FW Load %d Send Data chunk %d (%d bytes): OK\n", i, chunk_count, chunk_size); + } + + // Track what has been sent + sent_bytes += chunk_size; + chunk_count++; + } + } + + // Finish the FW load + status = caliptra_upload_fw_end_req(false); + + if (status) + { + printf("FW Load %d End Failed: 0x%x\n", i, status); + dump_caliptra_error_codes(); + failure = 1; + } + else + { + printf("FW Load %d End: OK\n", i); + } + } + + return failure; } // Test infrastructure int global_test_result = 0; -void run_test(int func(const test_info *), const test_info* info, char* test_name) +void run_test(int func(const test_info *), const test_info *info, char *test_name) { - testbench_reinit(); - int result = func(info); - - if (result) { - printf("\n\n\t%s FAILED\n", test_name); - dump_caliptra_error_codes(); - printf("\n\n"); - } else { - printf("\n\n\t%s PASSED\n\n\n", test_name); - } - - global_test_result |= result; + testbench_reinit(); + int result = func(info); + + if (result) + { + printf("\n\n\t%s FAILED\n", test_name); + dump_caliptra_error_codes(); + printf("\n\n"); + } + else + { + printf("\n\n\t%s PASSED\n\n\n", test_name); + } + + global_test_result |= result; } -int run_tests(const test_info* info) +int run_tests(const test_info *info) { - global_test_result = 0; - - hwmod_init(info->rom); - - // [TODO][FIX] run_test(legacy_boot_test, info, "Legacy boot test"); - run_test(rom_test_all_commands, info, "Test all ROM commands"); - // [TODO][FIX] run_test(rt_test_all_commands, info, "Test all Runtime commmands"); - run_test(rom_test_devid_csr, info, "Test IDEV CSR GEN"); - // [TODO][FIX] run_test(upload_fw_piecewise, info, "Test Piecewise FW Load"); - - if (global_test_result) { - printf("\t\tlibcaliptra test failures reported\n"); - } else { - printf("\t\tAll libcaliptra tests passed\n"); - } - - return global_test_result; + global_test_result = 0; + + hwmod_init(info->rom); + + // [CAP2][TODO][FIX] run_test(legacy_boot_test, info, "Legacy boot test"); + run_test(rom_test_all_commands, info, "Test all ROM commands"); + // [CAP2][TODO][FIX] run_test(rt_test_all_commands, info, "Test all Runtime commmands"); + // [CAP2][TODO][FIX] run_test(rom_test_devid_csr, info, "Test IDEV CSR GEN"); + // [CAP2][TODO][FIX] run_test(upload_fw_piecewise, info, "Test Piecewise FW Load"); + + if (global_test_result) + { + printf("\t\tlibcaliptra test failures reported\n"); + } + else + { + printf("\t\tAll libcaliptra tests passed\n"); + } + + return global_test_result; } diff --git a/runtime/src/dpe_platform.rs b/runtime/src/dpe_platform.rs index daeee3ad2d..ab53d6122f 100644 --- a/runtime/src/dpe_platform.rs +++ b/runtime/src/dpe_platform.rs @@ -108,7 +108,7 @@ impl Platform for DpePlatform<'_> { &mut self, out: &mut [u8; MAX_ISSUER_NAME_SIZE], ) -> Result { - const CALIPTRA_CN: &[u8] = b"Caliptra 1.x Rt Alias"; + const CALIPTRA_CN: &[u8] = b"Caliptra 1.0 Rt Alias"; let mut issuer_writer = CertWriter::new(out, true); // Caliptra RDN SerialNumber field is always a Sha256 hash diff --git a/test/tests/caliptra_integration_tests/smoke_testdata/fmc_alias_cert_redacted.der b/test/tests/caliptra_integration_tests/smoke_testdata/fmc_alias_cert_redacted.der index 60649c75c60df8f4eff409ccc343618d05c1ff34..42eec06ea6733956bd1ca03be62f6337154e9ee8 100644 GIT binary patch delta 17 ZcmaFG_KIzSJEOrwk3L3&jn^kL0RTNV2A%)_ delta 17 ZcmaFG_KIzSJ7dK}k3PnVjn^kL0RTa62QB~r diff --git a/test/tests/caliptra_integration_tests/smoke_testdata/fmc_alias_cert_redacted.txt b/test/tests/caliptra_integration_tests/smoke_testdata/fmc_alias_cert_redacted.txt index a63df7f6df..4aede310cc 100644 --- a/test/tests/caliptra_integration_tests/smoke_testdata/fmc_alias_cert_redacted.txt +++ b/test/tests/caliptra_integration_tests/smoke_testdata/fmc_alias_cert_redacted.txt @@ -4,11 +4,11 @@ Certificate: Serial Number: 44:44:44:44:44:44:44:44:44:44:44:44:44:44:44:44:44:44:44:44 Signature Algorithm: ecdsa-with-SHA384 - Issuer: CN=Caliptra 1.x LDevID/serialNumber=21EEEF9A4C61D4B9E3D94BEA46F9A12AC6887CE2188559F40FF95777E8014889 + Issuer: CN=Caliptra 1.0 LDevID/serialNumber=21EEEF9A4C61D4B9E3D94BEA46F9A12AC6887CE2188559F40FF95777E8014889 Validity Not Before: Jan 1 00:00:00 2023 GMT Not After : Dec 31 23:59:59 9999 GMT - Subject: CN=Caliptra 1.x FMC Alias/serialNumber=DDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDD + Subject: CN=Caliptra 1.0 FMC Alias/serialNumber=DDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDD Subject Public Key Info: Public Key Algorithm: id-ecPublicKey Public-Key: (384 bit) diff --git a/test/tests/caliptra_integration_tests/smoke_testdata/idevid_csr.der b/test/tests/caliptra_integration_tests/smoke_testdata/idevid_csr.der index 43da84d54404acd33e9f7950232ba4986d170b89..3eb10487e1d55e8b59ecf5590c7b6b4429a33cf3 100644 GIT binary patch delta 151 zcmV;I0BHZa1H1zyFoFTNFoFR-0s#OpX)zoy8U_PZ1Op5cLt$)baCCBEATcg5u_P}6 zX=ng2Wdbn(tc(xX`nS`(U}tEA&z|3<&ri4s^0JM_BKJ)@eFHC79d}u=YH@#9f5$-t zKm{s^0x(Nwlz_U4M|p0pdXb9NRuu?yXgo^=+qu%4v3&;Huj)$HWwH~;%I#l&ZOogB FZD3=KJX!z% delta 150 zcmV;H0BQfc1G@txFoFTMFoFR-0s#OpX)zoy8U_PZ1Op5cLt$)baCCBEATcg@u_P}6 zXlDR0WCAc}dAD@AwAJhbFkBT>GpBRje@@T{9HW~FsRA%=C6Cf`%jTn?$3>XQz0bM} i)iA=)3%SmHK}%y|ss)mUxE6FoFV}kpx2lc#%ks0eG?3VgYGr05D|&F#zi*=cj$QRbGefVds$E zhWmR{qq`^lY70+(m|xfxC6GmsH48x2{jXDM)nn{j)$e-QmGUl$tjM@klyM diff --git a/test/tests/caliptra_integration_tests/smoke_testdata/ldevid_cert.txt b/test/tests/caliptra_integration_tests/smoke_testdata/ldevid_cert.txt index 80dd063a10..08e2a35418 100644 --- a/test/tests/caliptra_integration_tests/smoke_testdata/ldevid_cert.txt +++ b/test/tests/caliptra_integration_tests/smoke_testdata/ldevid_cert.txt @@ -4,11 +4,11 @@ Certificate: Serial Number: 25:ee:ef:9a:4c:61:d4:b9:e3:d9:4b:ea:46:f9:a1:2a:c6:88:7c:e2 Signature Algorithm: ecdsa-with-SHA384 - Issuer: CN=Caliptra 1.x IDevID/serialNumber=ED4E1CD29CAA3DE158DFEA7C409738139EE05F4CA1A2F8A033AAB171B68A1312 + Issuer: CN=Caliptra 1.0 IDevID/serialNumber=ED4E1CD29CAA3DE158DFEA7C409738139EE05F4CA1A2F8A033AAB171B68A1312 Validity Not Before: Jan 1 00:00:00 2023 GMT Not After : Dec 31 23:59:59 9999 GMT - Subject: CN=Caliptra 1.x LDevID/serialNumber=21EEEF9A4C61D4B9E3D94BEA46F9A12AC6887CE2188559F40FF95777E8014889 + Subject: CN=Caliptra 1.0 LDevID/serialNumber=21EEEF9A4C61D4B9E3D94BEA46F9A12AC6887CE2188559F40FF95777E8014889 Subject Public Key Info: Public Key Algorithm: id-ecPublicKey Public-Key: (384 bit) @@ -35,9 +35,9 @@ Certificate: E0:BF:2D:84:D1:65:71:98:4C:B5:2E:74:6A:63:C4:D9:73:47:57:5B Signature Algorithm: ecdsa-with-SHA384 Signature Value: - 30:65:02:31:00:eb:28:e7:a7:7d:b7:55:5e:87:ed:61:e7:90: - de:86:fb:7b:53:a3:bb:27:fd:6a:0b:4f:7e:98:5f:d8:15:e4: - 8e:30:e7:08:6d:67:cd:01:c2:6f:83:43:fa:fe:43:4a:1c:02: - 30:32:7c:1e:28:09:93:ad:de:a1:ba:71:67:52:c3:94:76:47: - 40:cd:7e:a4:8b:18:1d:97:54:c8:53:b7:ae:4f:c0:29:48:74: - f5:fd:b3:40:36:dd:e1:c1:47:94:9a:37:05 + 30:64:02:30:4f:d9:b0:6a:2f:3e:fa:04:fa:5f:ef:66:c2:c2: + d8:ae:58:cc:39:a5:0a:20:7b:79:b7:74:b9:b4:d5:ec:03:30: + 5c:15:54:33:a7:73:de:7f:4e:d0:08:1c:a3:9b:09:a9:02:30: + 6e:25:8f:d2:73:cb:e6:a3:a0:c7:45:98:c9:bd:cf:ba:0b:d5: + 30:c2:d0:0b:b9:ce:7d:41:4b:63:62:aa:05:92:86:ba:45:6f: + f1:80:00:30:6a:f3:8a:28:0c:e5:09:1e diff --git a/test/tests/caliptra_integration_tests/smoke_testdata/rt_alias_cert_redacted.der b/test/tests/caliptra_integration_tests/smoke_testdata/rt_alias_cert_redacted.der index 9e6aeef81d8fda0bc4db3b15ce135f6437c3c472..58e1b6e1a3e5cafad3dd482fac42d521ab18c0d0 100644 GIT binary patch delta 24 gcmZo-Yhs(=&T63G=IcE1ZqUSe){F)lZ)q?A0AK+KBLDyZ delta 24 gcmZo-Yhs(=&RU`1=IcE1ZqUSe){GS!Z)q?A0A?`=vj6}9 diff --git a/test/tests/caliptra_integration_tests/smoke_testdata/rt_alias_cert_redacted.txt b/test/tests/caliptra_integration_tests/smoke_testdata/rt_alias_cert_redacted.txt index 52d55db979..72a5ca0c82 100644 --- a/test/tests/caliptra_integration_tests/smoke_testdata/rt_alias_cert_redacted.txt +++ b/test/tests/caliptra_integration_tests/smoke_testdata/rt_alias_cert_redacted.txt @@ -4,11 +4,11 @@ Certificate: Serial Number: 44:44:44:44:44:44:44:44:44:44:44:44:44:44:44:44:44:44:44:44 Signature Algorithm: ecdsa-with-SHA384 - Issuer: CN=Caliptra 1.x FMC Alias/serialNumber=DDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDD + Issuer: CN=Caliptra 1.0 FMC Alias/serialNumber=DDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDD Validity Not Before: Jan 1 00:00:00 2023 GMT Not After : Dec 31 23:59:59 9999 GMT - Subject: CN=Caliptra 1.x Rt Alias/serialNumber=DDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDD + Subject: CN=Caliptra 1.0 Rt Alias/serialNumber=DDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDD Subject Public Key Info: Public Key Algorithm: id-ecPublicKey Public-Key: (384 bit) diff --git a/x509/build/build.rs b/x509/build/build.rs index dc116c3505..aa728c6eaa 100644 --- a/x509/build/build.rs +++ b/x509/build/build.rs @@ -54,7 +54,7 @@ fn gen_init_devid_csr(out_dir: &str) { .add_basic_constraints_ext(true, 5) .add_key_usage_ext(usage) .add_ueid_ext(&[0xFF; 17]); - let template = bldr.tbs_template("Caliptra 1.x IDevID"); + let template = bldr.tbs_template("Caliptra 1.0 IDevID"); CodeGen::gen_code("InitDevIdCsrTbs", template, out_dir); } @@ -67,7 +67,7 @@ fn gen_local_devid_cert(out_dir: &str) { .add_basic_constraints_ext(true, 4) .add_key_usage_ext(usage) .add_ueid_ext(&[0xFF; 17]); - let template = bldr.tbs_template("Caliptra 1.x LDevID", "Caliptra 1.x IDevID"); + let template = bldr.tbs_template("Caliptra 1.0 LDevID", "Caliptra 1.0 IDevID"); CodeGen::gen_code("LocalDevIdCertTbs", template, out_dir); } @@ -98,7 +98,7 @@ fn gen_fmc_alias_cert(out_dir: &str) { }, }], ); - let template = bldr.tbs_template("Caliptra 1.x FMC Alias", "Caliptra 1.x LDevID"); + let template = bldr.tbs_template("Caliptra 1.0 FMC Alias", "Caliptra 1.0 LDevID"); CodeGen::gen_code("FmcAliasCertTbs", template, out_dir); } @@ -122,6 +122,6 @@ fn gen_rt_alias_cert(out_dir: &str) { digest: &[0xCD; 48], }, }]); - let template = bldr.tbs_template("Caliptra 1.x Rt Alias", "Caliptra 1.x FMC Alias"); + let template = bldr.tbs_template("Caliptra 1.0 Rt Alias", "Caliptra 1.0 FMC Alias"); CodeGen::gen_code("RtAliasCertTbs", template, out_dir); } diff --git a/x509/build/fmc_alias_cert_tbs.rs b/x509/build/fmc_alias_cert_tbs.rs index f8724c2441..f8c623efe6 100644 --- a/x509/build/fmc_alias_cert_tbs.rs +++ b/x509/build/fmc_alias_cert_tbs.rs @@ -77,7 +77,7 @@ impl FmcAliasCertTbs { 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 48u8, 10u8, 6u8, 8u8, 42u8, 134u8, 72u8, 206u8, 61u8, 4u8, 3u8, 3u8, 48u8, 105u8, 49u8, 28u8, 48u8, 26u8, 6u8, 3u8, 85u8, 4u8, 3u8, 12u8, 19u8, 67u8, 97u8, 108u8, 105u8, - 112u8, 116u8, 114u8, 97u8, 32u8, 49u8, 46u8, 120u8, 32u8, 76u8, 68u8, 101u8, 118u8, 73u8, + 112u8, 116u8, 114u8, 97u8, 32u8, 49u8, 46u8, 48u8, 32u8, 76u8, 68u8, 101u8, 118u8, 73u8, 68u8, 49u8, 73u8, 48u8, 71u8, 6u8, 3u8, 85u8, 4u8, 5u8, 19u8, 64u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, @@ -87,7 +87,7 @@ impl FmcAliasCertTbs { 95u8, 95u8, 95u8, 95u8, 24u8, 15u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 48u8, 108u8, 49u8, 31u8, 48u8, 29u8, 6u8, 3u8, 85u8, 4u8, 3u8, 12u8, 22u8, 67u8, 97u8, 108u8, 105u8, 112u8, 116u8, 114u8, 97u8, 32u8, 49u8, - 46u8, 120u8, 32u8, 70u8, 77u8, 67u8, 32u8, 65u8, 108u8, 105u8, 97u8, 115u8, 49u8, 73u8, + 46u8, 48u8, 32u8, 70u8, 77u8, 67u8, 32u8, 65u8, 108u8, 105u8, 97u8, 115u8, 49u8, 73u8, 48u8, 71u8, 6u8, 3u8, 85u8, 4u8, 5u8, 19u8, 64u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, diff --git a/x509/build/init_dev_id_csr_tbs.rs b/x509/build/init_dev_id_csr_tbs.rs index e4139c01ad..c989be7267 100644 --- a/x509/build/init_dev_id_csr_tbs.rs +++ b/x509/build/init_dev_id_csr_tbs.rs @@ -31,7 +31,7 @@ impl InitDevIdCsrTbs { const TBS_TEMPLATE: [u8; Self::TBS_TEMPLATE_LEN] = [ 48u8, 130u8, 1u8, 62u8, 2u8, 1u8, 0u8, 48u8, 105u8, 49u8, 28u8, 48u8, 26u8, 6u8, 3u8, 85u8, 4u8, 3u8, 12u8, 19u8, 67u8, 97u8, 108u8, 105u8, 112u8, 116u8, 114u8, 97u8, 32u8, 49u8, - 46u8, 120u8, 32u8, 73u8, 68u8, 101u8, 118u8, 73u8, 68u8, 49u8, 73u8, 48u8, 71u8, 6u8, 3u8, + 46u8, 48u8, 32u8, 73u8, 68u8, 101u8, 118u8, 73u8, 68u8, 49u8, 73u8, 48u8, 71u8, 6u8, 3u8, 85u8, 4u8, 5u8, 19u8, 64u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, diff --git a/x509/build/local_dev_id_cert_tbs.rs b/x509/build/local_dev_id_cert_tbs.rs index b9b0fcdf77..adb180a84c 100644 --- a/x509/build/local_dev_id_cert_tbs.rs +++ b/x509/build/local_dev_id_cert_tbs.rs @@ -57,7 +57,7 @@ impl LocalDevIdCertTbs { 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 48u8, 10u8, 6u8, 8u8, 42u8, 134u8, 72u8, 206u8, 61u8, 4u8, 3u8, 3u8, 48u8, 105u8, 49u8, 28u8, 48u8, 26u8, 6u8, 3u8, 85u8, 4u8, 3u8, 12u8, 19u8, 67u8, 97u8, 108u8, 105u8, 112u8, - 116u8, 114u8, 97u8, 32u8, 49u8, 46u8, 120u8, 32u8, 73u8, 68u8, 101u8, 118u8, 73u8, 68u8, + 116u8, 114u8, 97u8, 32u8, 49u8, 46u8, 48u8, 32u8, 73u8, 68u8, 101u8, 118u8, 73u8, 68u8, 49u8, 73u8, 48u8, 71u8, 6u8, 3u8, 85u8, 4u8, 5u8, 19u8, 64u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, @@ -67,7 +67,7 @@ impl LocalDevIdCertTbs { 95u8, 95u8, 95u8, 24u8, 15u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 48u8, 105u8, 49u8, 28u8, 48u8, 26u8, 6u8, 3u8, 85u8, 4u8, 3u8, 12u8, 19u8, 67u8, 97u8, 108u8, 105u8, 112u8, 116u8, 114u8, 97u8, 32u8, 49u8, 46u8, - 120u8, 32u8, 76u8, 68u8, 101u8, 118u8, 73u8, 68u8, 49u8, 73u8, 48u8, 71u8, 6u8, 3u8, 85u8, + 48u8, 32u8, 76u8, 68u8, 101u8, 118u8, 73u8, 68u8, 49u8, 73u8, 48u8, 71u8, 6u8, 3u8, 85u8, 4u8, 5u8, 19u8, 64u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, diff --git a/x509/build/rt_alias_cert_tbs.rs b/x509/build/rt_alias_cert_tbs.rs index 0e2b75eb2d..fb13855784 100644 --- a/x509/build/rt_alias_cert_tbs.rs +++ b/x509/build/rt_alias_cert_tbs.rs @@ -65,7 +65,7 @@ impl RtAliasCertTbs { 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 48u8, 10u8, 6u8, 8u8, 42u8, 134u8, 72u8, 206u8, 61u8, 4u8, 3u8, 3u8, 48u8, 108u8, 49u8, 31u8, 48u8, 29u8, 6u8, 3u8, 85u8, 4u8, 3u8, 12u8, 22u8, 67u8, 97u8, 108u8, 105u8, - 112u8, 116u8, 114u8, 97u8, 32u8, 49u8, 46u8, 120u8, 32u8, 70u8, 77u8, 67u8, 32u8, 65u8, + 112u8, 116u8, 114u8, 97u8, 32u8, 49u8, 46u8, 48u8, 32u8, 70u8, 77u8, 67u8, 32u8, 65u8, 108u8, 105u8, 97u8, 115u8, 49u8, 73u8, 48u8, 71u8, 6u8, 3u8, 85u8, 4u8, 5u8, 19u8, 64u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, @@ -75,7 +75,7 @@ impl RtAliasCertTbs { 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 24u8, 15u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 48u8, 107u8, 49u8, 30u8, 48u8, 28u8, 6u8, 3u8, 85u8, 4u8, 3u8, 12u8, 21u8, 67u8, 97u8, 108u8, 105u8, 112u8, 116u8, 114u8, - 97u8, 32u8, 49u8, 46u8, 120u8, 32u8, 82u8, 116u8, 32u8, 65u8, 108u8, 105u8, 97u8, 115u8, + 97u8, 32u8, 49u8, 46u8, 48u8, 32u8, 82u8, 116u8, 32u8, 65u8, 108u8, 105u8, 97u8, 115u8, 49u8, 73u8, 48u8, 71u8, 6u8, 3u8, 85u8, 4u8, 5u8, 19u8, 64u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, 95u8, From bb450961843ea71cf0b517b1e219b7dfc961491f Mon Sep 17 00:00:00 2001 From: Arthur Heymans Date: Tue, 19 Nov 2024 21:33:17 +0100 Subject: [PATCH 23/51] [feat] ML-DSA87 driver (#1778) This change adds a driver for interacting with the MLDSA peripheral. --- builder/src/firmware.rs | 6 + drivers/src/lib.rs | 4 +- drivers/src/memory_layout.rs | 4 +- drivers/src/mldsa87.rs | 282 ++++++++-- drivers/src/persistent.rs | 6 +- drivers/test-fw/Cargo.toml | 5 + drivers/test-fw/src/bin/mldsa87_tests.rs | 498 ++++++++++++++++++ .../tests/drivers_integration_tests/main.rs | 5 + error/src/lib.rs | 10 + hw/latest/registers/src/i3ccsr.rs | 2 +- hw/latest/registers/src/mldsa.rs | 80 ++- registers/bin/extra-rdl/el2_pic_ctrl.rdl | 2 +- registers/bin/generator/src/main.rs | 35 ++ rom/dev/README.md | 6 +- rom/dev/src/flow/cold_reset/crypto.rs | 4 +- rom/dev/src/rom_env.rs | 14 +- sw-emulator/lib/periph/src/ml_dsa87.rs | 253 ++++----- sw-emulator/lib/periph/src/root_bus.rs | 12 +- x509/src/cert_bldr.rs | 8 +- x509/src/lib.rs | 2 +- 20 files changed, 1010 insertions(+), 228 deletions(-) create mode 100644 drivers/test-fw/src/bin/mldsa87_tests.rs diff --git a/builder/src/firmware.rs b/builder/src/firmware.rs index aeee14287b..1b665c0e9e 100644 --- a/builder/src/firmware.rs +++ b/builder/src/firmware.rs @@ -220,6 +220,11 @@ pub mod driver_tests { ..BASE_FWID }; + pub const ML_DSA87: FwId = FwId { + bin_name: "ml_dsa87", + ..BASE_FWID + }; + pub const PCRBANK: FwId = FwId { bin_name: "pcrbank", ..BASE_FWID @@ -421,6 +426,7 @@ pub const REGISTERED_FW: &[&FwId] = &[ &driver_tests::MAILBOX_DRIVER_SENDER, &driver_tests::MAILBOX_DRIVER_NEGATIVE_TESTS, &driver_tests::MBOX_SEND_TXN_DROP, + &driver_tests::ML_DSA87, &driver_tests::PCRBANK, &driver_tests::SHA1, &driver_tests::SHA256, diff --git a/drivers/src/lib.rs b/drivers/src/lib.rs index 830e9f5174..0a62a9f846 100644 --- a/drivers/src/lib.rs +++ b/drivers/src/lib.rs @@ -85,7 +85,9 @@ pub use lms::{ Sha256Digest, D_INTR, D_LEAF, D_MESG, D_PBLC, }; pub use mailbox::{Mailbox, MailboxRecvTxn, MailboxSendTxn}; -pub use mldsa87::{MlDsa87, MlDsa87PubKey, MlDsa87Reg, MlDsa87Signature}; +pub use mldsa87::{ + Mldsa87, Mldsa87Msg, Mldsa87PubKey, Mldsa87Result, Mldsa87SignRnd, Mldsa87Signature, +}; pub use okref::okmutref; pub use okref::okref; pub use pcr_bank::{PcrBank, PcrId}; diff --git a/drivers/src/memory_layout.rs b/drivers/src/memory_layout.rs index 7146a595fc..70dc9edbd8 100644 --- a/drivers/src/memory_layout.rs +++ b/drivers/src/memory_layout.rs @@ -19,7 +19,7 @@ use crate::FirmwareHandoffTable; use caliptra_image_types::ImageManifest; #[cfg(test)] -use crate::MlDsa87PubKey; +use crate::Mldsa87PubKey; // // Memory Addresses @@ -112,7 +112,7 @@ fn mem_layout_test_fht() { #[test] #[allow(clippy::assertions_on_constants)] fn mem_layout_test_idevid_mldsa_pub_key() { - assert!(IDEVID_MLDSA_PUB_KEY_MAX_SIZE as usize >= core::mem::size_of::()); + assert!(IDEVID_MLDSA_PUB_KEY_MAX_SIZE as usize >= core::mem::size_of::()); assert_eq!( (LDEVID_TBS_ORG - IDEVID_MLDSA_PUB_KEY_ORG), IDEVID_MLDSA_PUB_KEY_MAX_SIZE diff --git a/drivers/src/mldsa87.rs b/drivers/src/mldsa87.rs index 837a5e11e4..8f3a684c5c 100644 --- a/drivers/src/mldsa87.rs +++ b/drivers/src/mldsa87.rs @@ -4,7 +4,7 @@ Licensed under the Apache-2.0 license. File Name: - mldsa87.rs + Mldsa87.rs Abstract: @@ -14,56 +14,85 @@ Abstract: #![allow(dead_code)] use crate::{ - array::{Array4x1157, Array4x648}, - Array4x16, + array::{Array4x1157, Array4x16, Array4x648, Array4x8}, + kv_access::{KvAccess, KvAccessErr}, + wait, CaliptraError, CaliptraResult, KeyReadArgs, Trng, }; -use crate::{CaliptraResult, KeyReadArgs, Trng}; +#[cfg(not(feature = "no-cfi"))] +use caliptra_cfi_derive::cfi_impl_fn; +use caliptra_registers::mldsa::{MldsaReg, RegisterBlock}; #[must_use] #[repr(u32)] #[derive(Debug, Clone, Copy, PartialEq, Eq)] -pub enum MlDsa87Result { +pub enum Mldsa87Result { Success = 0xAAAAAAAA, SigVerifyFailed = 0x55555555, } /// MLDSA-87 Public Key -pub type MlDsa87PubKey = Array4x648; +pub type Mldsa87PubKey = Array4x648; /// MLDSA-87 Signature -pub type MlDsa87Signature = Array4x1157; +pub type Mldsa87Signature = Array4x1157; /// MLDSA-87 Message (64 Bytes) -pub type MlDsa87MsgScalar = Array4x16; +pub type Mldsa87Msg = Array4x16; -/// TEMP: Placeholder for MlDsa87Reg -pub struct MlDsa87Reg { - _priv: (), -} -impl MlDsa87Reg { - /// # Safety - /// - /// Caller must ensure that all concurrent use of this - /// peripheral in the firmware is done so in a compatible - /// way. The simplest way to enforce this is to only call - /// this function once. - #[inline(always)] - pub unsafe fn new() -> Self { - Self { _priv: () } - } -} -/// END - TEMP: Placeholder for MlDsa87Reg +/// MLDSA-87 Signature RND +pub type Mldsa87SignRnd = Array4x8; + +type Mldsa87VerifyRes = Array4x16; /// MLDSA-87 API -pub struct MlDsa87 { - mldsa87: MlDsa87Reg, +pub struct Mldsa87 { + mldsa87: MldsaReg, } -impl MlDsa87 { - pub fn new(mldsa87: MlDsa87Reg) -> Self { +impl Mldsa87 { + pub fn new(mldsa87: MldsaReg) -> Self { Self { mldsa87 } } + // The trng only generates 12 dwords + fn generate_iv(trng: &mut Trng) -> CaliptraResult { + let iv = { + let mut iv = [0; 16]; + let iv1 = trng.generate()?; + let iv2 = trng.generate()?; + iv[..12].copy_from_slice(&iv1.0); + iv[12..16].copy_from_slice(&iv2.0[0..4]); + Array4x16::from(iv) + }; + Ok(iv) + } + + // Wait on the provided condition OR the error condition defined in this function + // In the event of the error condition being set, clear the error bits and return an error + fn wait(regs: RegisterBlock, condition: F) -> CaliptraResult<()> + where + F: Fn() -> bool, + { + let err_condition = || { + (u32::from(regs.intr_block_rf().error_global_intr_r().read()) != 0) + || (u32::from(regs.intr_block_rf().error_internal_intr_r().read()) != 0) + }; + + // Wait for either the given condition or the error condition + wait::until(|| (condition() || err_condition())); + + if err_condition() { + // Clear the errors + // error_global_intr_r is RO + regs.intr_block_rf() + .error_internal_intr_r() + .write(|_| u32::from(regs.intr_block_rf().error_internal_intr_r().read()).into()); + return Err(CaliptraError::DRIVER_MLDSA87_HW_ERROR); + } + + Ok(()) + } + /// Generate MLDSA-87 Key Pair /// /// # Arguments @@ -73,13 +102,42 @@ impl MlDsa87 { /// /// # Returns /// - /// * `MlDsa87PubKey` - Generated MLDSA-87 Public Key + /// * `Mldsa87PubKey` - Generated MLDSA-87 Public Key pub fn key_pair( &mut self, - _seed: &KeyReadArgs, - _trng: &mut Trng, - ) -> CaliptraResult { - Ok(MlDsa87PubKey::default()) + seed: &KeyReadArgs, + trng: &mut Trng, + ) -> CaliptraResult { + let mldsa = self.mldsa87.regs_mut(); + + // Wait for hardware ready + Mldsa87::wait(mldsa, || mldsa.status().read().ready())?; + + // Clear the hardware before start + mldsa.ctrl().write(|w| w.zeroize(true)); + + // Copy seed from keyvault + KvAccess::copy_from_kv(*seed, mldsa.kv_rd_seed_status(), mldsa.kv_rd_seed_ctrl()) + .map_err(|err| err.into_read_seed_err())?; + + // Generate an IV. + let iv = Self::generate_iv(trng)?; + KvAccess::copy_from_arr(&iv, mldsa.entropy())?; + + // Program the command register for key generation + mldsa.ctrl().write(|w| w.ctrl(|w| w.keygen())); + + // Wait for hardware ready + Mldsa87::wait(mldsa, || mldsa.status().read().valid())?; + + // Copy pubkey + let pubkey = Mldsa87PubKey::read_from_reg(mldsa.pubkey()); + + // Clear the hardware when done + mldsa.ctrl().write(|w| w.zeroize(true)); + + Ok(pubkey) + // TODO check that pubkey is valid? } /// Sign the digest with specified private key. To defend against glitching @@ -88,22 +146,75 @@ impl MlDsa87 { /// /// # Arguments /// - /// * `priv_key_in` - Key Vault slot containing the seed for the private key generation. + /// * `seed` - Key Vault slot containing the seed for deterministic MLDSA Key Pair generation. /// * `pub_key` - Public key to verify the signature with. /// * `msg` - Message to sign. + /// * `sign_rnd` - Signature RND input /// * `trng` - TRNG driver instance. /// /// # Returns /// - /// * `MlDsa87Signature` - Generated signature + /// * `Mldsa87Signature` - Generated signature pub fn sign( &mut self, - _priv_key_in: &KeyReadArgs, - _pub_key: &MlDsa87PubKey, - _msg: &MlDsa87MsgScalar, - _trng: &mut Trng, - ) -> CaliptraResult { - Ok(MlDsa87Signature::default()) + seed: &KeyReadArgs, + pub_key: &Mldsa87PubKey, + msg: &Mldsa87Msg, + sign_rnd: &Mldsa87SignRnd, + trng: &mut Trng, + ) -> CaliptraResult { + let mldsa = self.mldsa87.regs_mut(); + + // Wait for hardware ready + Mldsa87::wait(mldsa, || mldsa.status().read().ready())?; + + // Clear the hardware before start + mldsa.ctrl().write(|w| w.zeroize(true)); + + // Copy seed from keyvault + KvAccess::copy_from_kv(*seed, mldsa.kv_rd_seed_status(), mldsa.kv_rd_seed_ctrl()) + .map_err(|err| err.into_read_seed_err())?; + + // Copy digest + KvAccess::copy_from_arr(msg, mldsa.msg())?; + + // Sign RND, TODO do we want deterministic? + KvAccess::copy_from_arr(sign_rnd, mldsa.sign_rnd())?; + + // Generate an IV. + let iv = Self::generate_iv(trng)?; + KvAccess::copy_from_arr(&iv, mldsa.entropy())?; + + // Program the command register for key generation + mldsa.ctrl().write(|w| w.ctrl(|w| w.keygen_sign())); + + // Wait for hardware ready + Mldsa87::wait(mldsa, || mldsa.status().read().valid())?; + + // Copy signature + let signature = Mldsa87Signature::read_from_reg(mldsa.signature()); + + // Clear the hardware when done + mldsa.ctrl().write(|w| w.zeroize(true)); + + let verify_res = self.verify_res(pub_key, msg, &signature)?; + + let truncated_signature = &signature.0[..16]; + + if verify_res.0 == truncated_signature { + // We only have a 6, 8 and 12 dword cfi assert + caliptra_cfi_lib::cfi_assert_eq_12_words( + &verify_res.0[..12].try_into().unwrap(), + &truncated_signature[..12].try_into().unwrap(), + ); + caliptra_cfi_lib::cfi_assert_eq_8_words( + &verify_res.0[8..].try_into().unwrap(), + &truncated_signature[8..].try_into().unwrap(), + ); + Ok(signature) + } else { + Err(CaliptraError::DRIVER_MLDSA87_SIGN_VALIDATION_FAILED) + } } /// Verify the signature with specified public key and message. @@ -116,13 +227,88 @@ impl MlDsa87 { /// /// # Result /// - /// * `MlDsa87Result` - MlDsa87Result::Success if the signature verification passed else an error code. + /// * `Mldsa87Result` - Mldsa87Result::Success if the signature verification passed else an error code. + fn verify_res( + &mut self, + pub_key: &Mldsa87PubKey, + msg: &Mldsa87Msg, + signature: &Mldsa87Signature, + ) -> CaliptraResult { + let mldsa = self.mldsa87.regs_mut(); + + // Wait for hardware ready + Mldsa87::wait(mldsa, || mldsa.status().read().ready())?; + + // Clear the hardware before start + mldsa.ctrl().write(|w| w.zeroize(true)); + + // Copy digest + msg.write_to_reg(mldsa.msg()); + + // Copy pubkey + pub_key.write_to_reg(mldsa.pubkey()); + + // Copy signature + signature.write_to_reg(mldsa.signature()); + + // Program the command register for signature verification + mldsa.ctrl().write(|w| w.ctrl(|w| w.verifying())); + + // Wait for hardware ready + Mldsa87::wait(mldsa, || mldsa.status().read().valid())?; + + // Copy the random value + let verify_res = Array4x16::read_from_reg(mldsa.verify_res()); + + // Clear the hardware when done + mldsa.ctrl().write(|w| w.zeroize(true)); + + Ok(verify_res) + } + + #[cfg_attr(not(feature = "no-cfi"), cfi_impl_fn)] pub fn verify( &mut self, - _pub_key: &MlDsa87PubKey, - _msg: &MlDsa87MsgScalar, - _signature: &MlDsa87Signature, - ) -> CaliptraResult { - Ok(MlDsa87Result::Success) + pub_key: &Mldsa87PubKey, + msg: &Mldsa87Msg, + signature: &Mldsa87Signature, + ) -> CaliptraResult { + let verify_res = self.verify_res(pub_key, msg, signature)?; + + let truncated_signature = &signature.0[..16]; + + let result = if verify_res.0 == truncated_signature { + // We only have a 6, 8 and 12 dword cfi assert + caliptra_cfi_lib::cfi_assert_eq_12_words( + &verify_res.0[..12].try_into().unwrap(), + &truncated_signature[..12].try_into().unwrap(), + ); + caliptra_cfi_lib::cfi_assert_eq_8_words( + &verify_res.0[8..].try_into().unwrap(), + &truncated_signature[8..].try_into().unwrap(), + ); + Mldsa87Result::Success + } else { + Mldsa87Result::SigVerifyFailed + }; + + Ok(result) + } +} + +/// Mldsa87 key access error trait +trait MlDsaKeyAccessErr { + /// Convert to read seed operation error + fn into_read_seed_err(self) -> CaliptraError; +} + +impl MlDsaKeyAccessErr for KvAccessErr { + /// Convert to read seed operation error + fn into_read_seed_err(self) -> CaliptraError { + match self { + KvAccessErr::KeyRead => CaliptraError::DRIVER_MLDSA87_READ_SEED_KV_READ, + KvAccessErr::KeyWrite => CaliptraError::DRIVER_MLDSA87_READ_SEED_KV_WRITE, + KvAccessErr::Generic => CaliptraError::DRIVER_MLDSA87_READ_SEED_KV_UNKNOWN, + } } } diff --git a/drivers/src/persistent.rs b/drivers/src/persistent.rs index a3b43fc290..5824b56154 100644 --- a/drivers/src/persistent.rs +++ b/drivers/src/persistent.rs @@ -18,7 +18,7 @@ use crate::{ fuse_log::FuseLogEntry, memory_layout, pcr_log::{MeasurementLogEntry, PcrLogEntry}, - FirmwareHandoffTable, MlDsa87PubKey, + FirmwareHandoffTable, Mldsa87PubKey, }; #[cfg(feature = "runtime")] @@ -116,9 +116,9 @@ pub struct PersistentData { pub fht: FirmwareHandoffTable, reserved2: [u8; memory_layout::FHT_SIZE as usize - size_of::()], - pub idevid_mldsa_pub_key: MlDsa87PubKey, + pub idevid_mldsa_pub_key: Mldsa87PubKey, reserved2_1: - [u8; memory_layout::IDEVID_MLDSA_PUB_KEY_MAX_SIZE as usize - size_of::()], + [u8; memory_layout::IDEVID_MLDSA_PUB_KEY_MAX_SIZE as usize - size_of::()], // TODO: Do we want to hide these fields from the FMC/runtime and force them // to go through the FHT addresses? diff --git a/drivers/test-fw/Cargo.toml b/drivers/test-fw/Cargo.toml index b4313b5046..6110444368 100644 --- a/drivers/test-fw/Cargo.toml +++ b/drivers/test-fw/Cargo.toml @@ -178,3 +178,8 @@ required-features = ["riscv"] name = "axi_dma_tests" path = "src/bin/dma_tests.rs" required-features = ["riscv"] + +[[bin]] +name = "ml_dsa87" +path = "src/bin/mldsa87_tests.rs" +required-features = ["riscv"] diff --git a/drivers/test-fw/src/bin/mldsa87_tests.rs b/drivers/test-fw/src/bin/mldsa87_tests.rs new file mode 100644 index 0000000000..ec3c47a0cd --- /dev/null +++ b/drivers/test-fw/src/bin/mldsa87_tests.rs @@ -0,0 +1,498 @@ +/*++ + +Licensed under the Apache-2.0 license. + +File Name: + + ml_dsa87_tests.rs + +Abstract: + + File contains test cases for ML_DSA87 API tests + +--*/ + +#![no_std] +#![no_main] + +use caliptra_cfi_lib::CfiCounter; +use caliptra_drivers::{ + Array4x12, Hmac, HmacData, HmacKey, HmacMode, HmacTag, KeyId, KeyReadArgs, KeyUsage, + KeyWriteArgs, Mldsa87, Mldsa87Msg, Mldsa87PubKey, Mldsa87Result, Mldsa87SignRnd, + Mldsa87Signature, Trng, +}; +use caliptra_registers::csrng::CsrngReg; +use caliptra_registers::entropy_src::EntropySrcReg; +use caliptra_registers::hmac::HmacReg; +use caliptra_registers::mldsa::MldsaReg; +use caliptra_registers::soc_ifc::SocIfcReg; +use caliptra_registers::soc_ifc_trng::SocIfcTrngReg; +use caliptra_test_harness::test_suite; + +const PUBKEY: [u8; 2592] = [ + 251, 202, 217, 224, 179, 133, 165, 63, 79, 52, 212, 239, 6, 145, 130, 220, 45, 173, 142, 113, + 182, 61, 254, 182, 63, 92, 58, 184, 26, 206, 128, 249, 150, 238, 171, 190, 52, 113, 142, 191, + 39, 216, 4, 52, 168, 202, 179, 10, 194, 99, 157, 193, 210, 194, 71, 144, 18, 54, 54, 188, 120, + 162, 209, 234, 103, 155, 208, 98, 79, 123, 21, 75, 247, 74, 17, 226, 112, 140, 96, 21, 117, 33, + 195, 133, 31, 156, 29, 46, 81, 106, 124, 66, 236, 49, 108, 49, 221, 166, 49, 219, 149, 101, + 186, 165, 103, 72, 121, 232, 128, 208, 59, 226, 199, 172, 189, 255, 116, 43, 140, 73, 249, 134, + 77, 240, 38, 23, 178, 38, 41, 56, 237, 254, 135, 47, 19, 236, 232, 86, 49, 221, 126, 135, 102, + 151, 195, 178, 79, 24, 36, 117, 33, 168, 161, 111, 8, 12, 48, 50, 178, 59, 76, 101, 219, 46, + 220, 43, 248, 112, 224, 251, 87, 244, 202, 145, 160, 40, 223, 147, 84, 134, 108, 156, 99, 106, + 190, 172, 217, 252, 82, 175, 176, 209, 86, 119, 78, 187, 102, 149, 217, 62, 7, 146, 82, 246, + 49, 170, 132, 222, 154, 181, 140, 101, 238, 242, 209, 124, 112, 132, 6, 232, 243, 54, 41, 199, + 194, 233, 200, 182, 236, 161, 174, 4, 236, 91, 229, 27, 246, 218, 245, 246, 163, 86, 88, 82, + 43, 214, 54, 162, 81, 119, 164, 252, 236, 237, 169, 1, 76, 108, 89, 187, 70, 191, 79, 40, 187, + 122, 70, 230, 249, 31, 225, 192, 121, 213, 208, 42, 165, 200, 231, 210, 98, 109, 198, 67, 62, + 122, 211, 197, 211, 232, 23, 42, 25, 199, 221, 18, 173, 164, 119, 86, 216, 166, 209, 184, 86, + 38, 51, 70, 101, 175, 226, 133, 153, 45, 66, 167, 215, 227, 252, 147, 207, 121, 191, 192, 126, + 237, 122, 66, 84, 245, 48, 25, 40, 221, 154, 15, 11, 185, 170, 155, 52, 134, 34, 3, 249, 54, + 46, 6, 215, 89, 72, 83, 40, 253, 55, 189, 41, 138, 189, 164, 200, 52, 224, 60, 55, 125, 16, + 191, 74, 59, 102, 14, 208, 83, 169, 237, 121, 149, 222, 177, 56, 157, 254, 226, 220, 140, 251, + 63, 242, 238, 32, 233, 106, 23, 126, 131, 167, 153, 169, 80, 171, 202, 72, 67, 130, 86, 19, 11, + 1, 34, 112, 19, 58, 2, 58, 35, 34, 178, 141, 86, 57, 236, 39, 223, 229, 194, 69, 227, 63, 14, + 7, 209, 32, 147, 235, 244, 102, 229, 99, 51, 104, 218, 89, 95, 245, 19, 152, 93, 123, 134, 214, + 60, 255, 69, 134, 4, 171, 49, 12, 31, 130, 171, 249, 97, 155, 157, 227, 69, 1, 200, 182, 45, + 44, 84, 187, 101, 106, 95, 150, 127, 20, 102, 234, 15, 192, 24, 48, 218, 67, 112, 67, 246, 202, + 145, 243, 55, 102, 0, 238, 30, 16, 192, 218, 30, 70, 183, 155, 74, 36, 100, 46, 116, 30, 232, + 226, 159, 162, 101, 99, 12, 144, 223, 145, 113, 164, 20, 219, 200, 84, 85, 175, 119, 7, 180, + 30, 89, 106, 227, 214, 113, 7, 51, 194, 77, 70, 95, 235, 161, 32, 248, 57, 106, 6, 74, 154, 18, + 183, 71, 217, 64, 178, 201, 235, 205, 231, 187, 47, 20, 123, 15, 20, 69, 45, 199, 254, 56, 67, + 33, 135, 207, 152, 169, 237, 2, 153, 44, 252, 67, 232, 70, 199, 177, 218, 111, 10, 89, 42, 155, + 171, 225, 45, 53, 71, 132, 34, 247, 202, 198, 223, 42, 22, 206, 158, 152, 46, 111, 174, 98, 67, + 159, 131, 12, 207, 71, 233, 45, 221, 78, 154, 245, 139, 116, 98, 0, 208, 118, 68, 3, 122, 111, + 55, 104, 163, 36, 200, 77, 230, 149, 55, 121, 235, 52, 245, 102, 115, 172, 83, 20, 206, 142, + 97, 154, 57, 242, 250, 155, 68, 99, 71, 170, 91, 180, 192, 115, 143, 177, 91, 133, 91, 238, + 173, 72, 164, 80, 121, 139, 68, 121, 165, 111, 32, 219, 134, 48, 92, 121, 190, 243, 71, 183, + 44, 195, 24, 239, 52, 88, 255, 231, 104, 55, 37, 52, 168, 216, 74, 103, 66, 89, 90, 248, 65, + 134, 29, 54, 34, 46, 220, 228, 236, 83, 85, 168, 173, 126, 231, 239, 116, 98, 222, 232, 243, + 98, 207, 158, 189, 168, 197, 211, 158, 73, 245, 204, 184, 88, 227, 193, 72, 56, 191, 184, 185, + 193, 252, 156, 189, 211, 79, 99, 35, 237, 17, 208, 73, 226, 215, 93, 137, 67, 28, 8, 52, 19, + 72, 35, 82, 27, 48, 206, 218, 75, 152, 205, 139, 135, 74, 100, 146, 167, 181, 158, 61, 159, 92, + 122, 95, 253, 250, 218, 147, 235, 143, 206, 137, 16, 205, 86, 109, 189, 163, 8, 62, 153, 100, + 66, 15, 244, 112, 135, 71, 91, 251, 35, 102, 100, 185, 203, 222, 234, 97, 135, 80, 0, 221, 248, + 253, 109, 64, 25, 97, 205, 92, 33, 227, 247, 193, 55, 128, 203, 177, 63, 126, 75, 9, 134, 167, + 123, 107, 250, 87, 16, 172, 146, 58, 179, 145, 47, 149, 114, 225, 11, 2, 232, 121, 249, 219, + 59, 18, 14, 73, 165, 248, 116, 58, 210, 28, 163, 147, 167, 232, 250, 201, 224, 244, 78, 218, + 70, 73, 76, 94, 233, 205, 204, 13, 103, 173, 123, 195, 169, 130, 42, 185, 180, 59, 156, 149, + 150, 246, 66, 255, 133, 23, 91, 123, 145, 18, 217, 25, 106, 100, 195, 207, 242, 64, 1, 23, 209, + 140, 109, 140, 211, 17, 31, 178, 212, 140, 169, 12, 121, 116, 224, 53, 225, 4, 221, 177, 53, + 127, 28, 193, 213, 46, 35, 113, 34, 50, 197, 16, 73, 65, 212, 114, 89, 137, 7, 216, 82, 0, 49, + 13, 79, 164, 147, 205, 102, 242, 144, 217, 233, 231, 46, 213, 78, 134, 120, 13, 148, 244, 194, + 109, 202, 242, 13, 94, 61, 231, 171, 210, 70, 107, 100, 186, 172, 35, 143, 187, 190, 190, 120, + 12, 181, 242, 171, 125, 183, 39, 22, 110, 186, 142, 218, 141, 19, 163, 138, 214, 162, 143, 16, + 33, 29, 209, 238, 235, 152, 29, 91, 139, 132, 118, 212, 19, 148, 26, 230, 231, 227, 202, 101, + 3, 164, 189, 59, 223, 125, 140, 86, 217, 153, 134, 70, 84, 161, 48, 50, 189, 180, 46, 148, 181, + 83, 213, 53, 247, 106, 208, 249, 91, 114, 9, 189, 15, 134, 219, 74, 89, 228, 125, 57, 159, 70, + 139, 97, 63, 89, 182, 145, 247, 251, 196, 70, 20, 60, 166, 244, 218, 78, 133, 253, 8, 241, 66, + 125, 200, 146, 222, 49, 90, 214, 217, 201, 151, 42, 209, 206, 165, 191, 68, 31, 112, 173, 183, + 113, 243, 193, 115, 3, 77, 152, 132, 85, 58, 243, 138, 211, 35, 49, 51, 131, 194, 105, 171, + 109, 97, 154, 6, 134, 53, 145, 98, 155, 79, 11, 175, 244, 192, 50, 108, 207, 208, 12, 48, 205, + 243, 47, 78, 77, 50, 196, 177, 188, 249, 207, 188, 223, 180, 42, 44, 153, 252, 147, 66, 159, + 140, 127, 56, 148, 124, 168, 32, 67, 56, 106, 19, 194, 202, 51, 51, 46, 214, 208, 34, 191, 165, + 93, 23, 169, 89, 199, 232, 26, 185, 72, 48, 111, 49, 215, 82, 251, 170, 151, 159, 204, 248, + 120, 183, 64, 199, 223, 110, 46, 90, 215, 236, 135, 90, 81, 185, 82, 153, 104, 143, 17, 178, + 107, 27, 123, 184, 19, 126, 47, 135, 138, 172, 199, 109, 240, 225, 3, 215, 141, 185, 78, 105, + 191, 85, 141, 113, 161, 86, 228, 111, 76, 38, 138, 72, 60, 148, 178, 52, 83, 191, 185, 19, 145, + 212, 142, 115, 27, 124, 64, 25, 2, 30, 167, 184, 64, 148, 109, 117, 145, 123, 158, 165, 95, 81, + 68, 39, 6, 27, 248, 161, 154, 139, 133, 93, 18, 50, 7, 29, 231, 239, 135, 251, 93, 117, 54, 38, + 27, 90, 173, 210, 243, 98, 238, 110, 41, 30, 187, 191, 219, 154, 10, 24, 231, 253, 128, 99, + 101, 248, 44, 107, 60, 225, 45, 145, 146, 231, 8, 146, 82, 120, 163, 56, 89, 165, 120, 21, 233, + 15, 24, 147, 145, 238, 236, 209, 28, 187, 168, 103, 92, 99, 111, 197, 157, 12, 236, 53, 126, + 174, 31, 243, 115, 190, 67, 186, 64, 253, 40, 172, 145, 222, 8, 27, 37, 35, 196, 131, 214, 139, + 26, 206, 229, 225, 159, 22, 184, 151, 170, 205, 128, 134, 98, 108, 40, 184, 80, 23, 145, 76, + 164, 182, 221, 61, 180, 207, 9, 187, 115, 242, 169, 46, 143, 223, 176, 36, 128, 109, 87, 15, + 237, 27, 96, 69, 52, 144, 109, 190, 217, 92, 196, 167, 101, 57, 70, 117, 122, 129, 239, 101, + 78, 137, 113, 238, 102, 221, 100, 172, 190, 230, 245, 68, 91, 6, 98, 97, 246, 46, 152, 152, + 224, 45, 36, 38, 154, 222, 77, 1, 215, 62, 197, 55, 83, 83, 202, 172, 52, 5, 37, 181, 209, 137, + 65, 109, 176, 168, 237, 20, 183, 46, 140, 19, 209, 239, 19, 183, 224, 221, 191, 163, 237, 151, + 208, 98, 130, 201, 75, 59, 159, 171, 198, 182, 42, 167, 1, 63, 28, 62, 104, 212, 8, 220, 216, + 199, 120, 127, 25, 160, 198, 186, 119, 84, 73, 29, 11, 195, 31, 239, 232, 116, 110, 212, 76, + 243, 148, 138, 1, 105, 166, 130, 98, 189, 28, 82, 20, 171, 118, 51, 132, 246, 238, 249, 220, + 210, 147, 164, 205, 72, 7, 175, 85, 217, 179, 230, 210, 85, 222, 69, 39, 151, 89, 225, 243, + 124, 210, 247, 204, 56, 171, 59, 149, 112, 29, 14, 11, 178, 214, 192, 43, 132, 151, 57, 62, + 152, 48, 74, 117, 104, 209, 63, 67, 126, 6, 64, 160, 94, 147, 216, 31, 4, 20, 190, 197, 180, + 129, 116, 146, 46, 25, 226, 124, 120, 56, 197, 23, 82, 144, 106, 119, 132, 101, 196, 201, 191, + 164, 15, 141, 212, 167, 169, 43, 151, 22, 190, 202, 152, 101, 82, 173, 171, 141, 253, 1, 113, + 215, 49, 30, 15, 8, 122, 42, 60, 46, 108, 11, 230, 175, 201, 64, 160, 6, 211, 214, 247, 72, 32, + 182, 29, 170, 133, 80, 63, 247, 9, 249, 118, 130, 44, 243, 185, 137, 8, 16, 121, 191, 92, 54, + 231, 184, 0, 223, 41, 178, 253, 12, 232, 48, 235, 39, 104, 191, 77, 189, 7, 122, 76, 189, 207, + 50, 15, 138, 172, 13, 163, 37, 121, 83, 211, 155, 42, 110, 190, 24, 238, 41, 35, 42, 197, 240, + 185, 56, 218, 65, 213, 86, 174, 114, 55, 182, 250, 117, 42, 109, 85, 44, 174, 101, 59, 124, + 170, 81, 166, 210, 142, 236, 105, 179, 13, 243, 8, 166, 64, 162, 209, 57, 237, 144, 142, 188, + 245, 219, 157, 171, 112, 228, 93, 2, 211, 143, 202, 226, 244, 194, 107, 14, 78, 122, 49, 150, + 234, 18, 78, 111, 178, 60, 106, 225, 19, 85, 72, 42, 211, 201, 54, 157, 93, 77, 61, 54, 124, + 218, 158, 31, 112, 30, 141, 199, 176, 135, 245, 84, 240, 215, 26, 219, 1, 21, 196, 97, 153, 19, + 141, 55, 103, 195, 147, 80, 132, 91, 21, 211, 73, 157, 11, 8, 177, 67, 45, 209, 119, 233, 219, + 124, 141, 52, 196, 84, 39, 249, 225, 155, 89, 206, 235, 70, 142, 136, 171, 238, 127, 63, 155, + 106, 121, 33, 1, 240, 8, 100, 222, 147, 77, 115, 82, 140, 244, 222, 5, 143, 55, 167, 71, 79, + 155, 27, 12, 194, 231, 90, 102, 15, 10, 136, 199, 77, 118, 166, 133, 87, 132, 161, 239, 211, + 196, 120, 57, 149, 139, 243, 131, 121, 235, 41, 213, 78, 225, 179, 16, 175, 238, 7, 73, 225, + 74, 250, 184, 105, 188, 21, 228, 190, 20, 163, 120, 14, 194, 195, 9, 34, 35, 98, 149, 233, 79, + 164, 116, 179, 133, 219, 251, 212, 194, 94, 83, 125, 78, 113, 9, 144, 80, 36, 184, 193, 86, + 168, 242, 115, 62, 119, 225, 212, 247, 42, 237, 173, 140, 90, 125, 42, 209, 168, 87, 5, 183, + 92, 1, 221, 167, 56, 73, 209, 44, 45, 18, 177, 121, 59, 204, 85, 25, 230, 206, 101, 161, 199, + 95, 186, 156, 152, 235, 141, 223, 26, 99, 47, 198, 92, 168, 2, 26, 255, 132, 126, 75, 30, 168, + 88, 12, 84, 157, 59, 106, 166, 127, 77, 82, 149, 49, 226, 171, 188, 95, 13, 255, 58, 191, 244, + 143, 128, 251, 165, 141, 149, 18, 190, 195, 70, 186, 129, 45, 19, 123, 0, 246, 162, 108, 42, + 163, 82, 112, 90, 101, 59, 173, 163, 182, 243, 241, 201, 78, 168, 6, 135, 191, 15, 66, 168, 19, + 150, 10, 37, 173, 88, 188, 72, 219, 182, 164, 163, 173, 238, 120, 154, 199, 176, 242, 19, 149, + 48, 4, 16, 234, 77, 95, 124, 144, 106, 115, 75, 119, 68, 184, 34, 91, 10, 122, 151, 236, 34, + 51, 69, 5, 209, 221, 157, 80, 74, 137, 94, 48, 14, 54, 35, 99, 16, 231, 202, 51, 155, 214, 227, + 128, 10, 173, 129, 98, 59, 62, 235, 203, 22, 198, 84, 95, 123, 109, 126, 7, 169, 173, 13, 240, + 240, 2, 150, 153, 212, 39, 183, 28, 17, 175, 149, 224, 53, 199, 160, 144, 179, 205, 0, 183, + 226, 243, 16, 209, 75, 155, 176, 80, 12, 161, 180, 188, 222, 101, 42, 105, 117, 207, 108, 166, + 240, 96, 10, 27, 101, 160, 89, 156, 5, 43, 137, 58, 32, 168, 160, 11, 82, 81, 89, 34, 254, 75, + 62, 83, 113, 79, 174, 59, 103, 172, 30, 231, 61, 145, 197, 211, 188, 184, 49, 168, 194, 13, + 185, 36, 113, 92, 99, 128, 155, 100, 143, 240, 81, 85, 13, 49, 232, 156, 183, 113, 141, 157, + 164, 34, 170, 148, 102, 48, 245, 128, 252, 234, 95, 218, 245, 174, 124, 71, 253, 127, 135, 191, + 233, 134, 86, 133, 72, 214, 126, 102, 118, 167, 149, 20, 70, 0, 97, 236, 187, 103, 160, 63, 95, + 191, 100, 61, 123, 173, 187, 217, 203, 56, 251, 72, 243, 180, 136, 88, 252, 106, 181, 155, 59, + 159, 101, 114, 1, 201, 74, 30, 229, 188, 6, 202, 195, 105, 242, 133, 101, 215, 135, 119, 98, + 157, 31, 160, 61, 64, 90, 229, 130, 90, 246, 202, 4, 127, 31, 191, 143, 250, 203, 49, 77, 95, + 68, 123, 207, 184, 47, 107, 200, 227, 228, 178, 21, 184, 163, 6, 26, 23, 11, 106, 159, 206, 99, + 201, 83, 58, 188, 54, 57, 181, 146, 137, 36, 139, 104, 79, 21, 147, 77, 105, 82, 20, 144, 12, + 82, 235, 59, 93, 192, 126, 111, 235, 68, 181, 59, 222, 188, 66, 204, 62, 30, 74, 105, 95, 139, + 91, 211, 25, 217, 140, 75, 158, 207, 77, 67, 206, 141, 191, 45, 113, 20, 53, 184, 255, 155, + 202, 94, 68, 205, 24, 1, 53, 108, 0, 7, 194, 245, 124, 15, 49, 24, 211, 156, 12, 96, 143, 196, + 68, 72, 47, 171, 95, 242, 43, 45, 94, 82, 212, 91, 238, 50, 242, 205, 249, 161, 208, 50, 109, + 147, +]; + +const SIGNATURE: [u8; 4628] = [ + 211, 210, 148, 168, 141, 152, 17, 222, 104, 63, 8, 6, 151, 147, 134, 100, 203, 10, 28, 42, 253, + 62, 96, 2, 224, 203, 230, 222, 125, 28, 214, 182, 153, 150, 13, 62, 242, 165, 47, 183, 164, 70, + 226, 64, 139, 61, 219, 229, 163, 172, 163, 231, 93, 220, 209, 156, 11, 251, 185, 238, 14, 187, + 158, 130, 63, 219, 81, 173, 58, 130, 119, 166, 1, 102, 187, 101, 126, 99, 182, 184, 197, 202, + 226, 73, 91, 109, 151, 104, 167, 139, 120, 69, 149, 32, 32, 127, 232, 111, 17, 176, 34, 6, 232, + 133, 88, 166, 96, 95, 233, 204, 16, 174, 61, 115, 51, 65, 131, 46, 238, 36, 243, 183, 92, 29, + 113, 46, 203, 58, 163, 160, 204, 98, 166, 192, 240, 178, 122, 207, 30, 106, 96, 151, 251, 106, + 66, 99, 97, 5, 85, 172, 235, 32, 10, 50, 102, 138, 242, 22, 19, 227, 44, 169, 145, 32, 228, + 107, 15, 70, 83, 245, 162, 233, 121, 49, 17, 168, 160, 52, 171, 250, 83, 23, 195, 158, 210, + 146, 12, 227, 5, 12, 141, 219, 53, 97, 120, 189, 78, 196, 94, 149, 77, 33, 212, 246, 171, 102, + 212, 103, 219, 112, 31, 221, 54, 212, 95, 35, 106, 242, 251, 129, 201, 98, 165, 69, 162, 80, + 23, 212, 208, 234, 213, 215, 30, 105, 186, 241, 69, 35, 82, 222, 250, 121, 94, 212, 205, 28, + 211, 71, 44, 42, 120, 53, 4, 137, 141, 219, 250, 215, 203, 147, 193, 209, 191, 99, 136, 105, + 161, 188, 116, 146, 164, 17, 51, 20, 105, 235, 7, 112, 105, 182, 94, 244, 88, 228, 249, 11, + 174, 87, 73, 73, 105, 156, 133, 35, 72, 143, 45, 95, 120, 98, 79, 45, 37, 194, 52, 108, 252, + 181, 50, 166, 132, 110, 228, 6, 197, 68, 190, 69, 125, 169, 57, 57, 196, 181, 95, 22, 197, 106, + 146, 218, 67, 53, 148, 115, 198, 234, 188, 72, 207, 112, 240, 50, 34, 181, 94, 44, 228, 63, + 189, 80, 205, 124, 148, 96, 243, 100, 55, 171, 132, 241, 186, 95, 99, 62, 227, 79, 113, 254, + 42, 82, 73, 236, 55, 154, 55, 97, 157, 235, 70, 8, 234, 161, 12, 27, 49, 78, 168, 6, 52, 154, + 162, 214, 226, 78, 198, 194, 151, 73, 128, 77, 109, 54, 29, 191, 19, 81, 116, 76, 125, 62, 188, + 225, 21, 48, 65, 43, 76, 93, 47, 19, 169, 63, 79, 29, 229, 158, 182, 194, 138, 239, 75, 234, 8, + 86, 150, 203, 223, 169, 113, 241, 160, 214, 119, 51, 241, 200, 30, 154, 50, 226, 2, 133, 136, + 97, 126, 118, 51, 185, 170, 1, 128, 6, 254, 77, 31, 57, 64, 214, 126, 57, 84, 217, 111, 46, + 181, 145, 205, 56, 243, 208, 58, 177, 14, 128, 92, 209, 110, 37, 140, 182, 244, 230, 103, 146, + 240, 167, 203, 106, 151, 87, 220, 17, 162, 121, 135, 85, 163, 111, 220, 154, 94, 66, 71, 209, + 86, 2, 228, 15, 160, 88, 195, 219, 157, 165, 197, 210, 14, 94, 37, 227, 157, 141, 179, 54, 245, + 200, 147, 243, 184, 39, 248, 73, 191, 74, 188, 18, 164, 94, 99, 132, 108, 221, 151, 76, 233, + 212, 237, 150, 32, 98, 219, 3, 24, 102, 221, 183, 195, 136, 31, 200, 121, 160, 137, 79, 129, + 21, 84, 248, 1, 229, 169, 251, 235, 30, 139, 232, 144, 77, 114, 226, 236, 30, 163, 242, 158, + 226, 47, 220, 178, 70, 136, 192, 251, 115, 24, 210, 73, 25, 233, 122, 253, 172, 126, 21, 4, + 107, 96, 80, 201, 22, 49, 189, 188, 105, 130, 114, 92, 215, 119, 116, 139, 53, 222, 50, 48, + 108, 232, 105, 13, 92, 38, 93, 199, 241, 32, 91, 97, 20, 99, 6, 107, 105, 38, 28, 180, 193, + 108, 72, 14, 114, 180, 61, 0, 49, 8, 143, 173, 95, 46, 25, 97, 241, 115, 63, 231, 145, 128, + 133, 47, 48, 111, 57, 189, 39, 172, 88, 194, 111, 252, 49, 217, 38, 162, 238, 169, 192, 89, + 120, 191, 148, 246, 40, 213, 141, 52, 194, 58, 111, 238, 252, 96, 83, 150, 252, 43, 237, 118, + 118, 185, 37, 105, 144, 134, 191, 248, 44, 237, 225, 38, 72, 37, 76, 209, 73, 58, 89, 132, 214, + 92, 226, 193, 202, 7, 147, 172, 95, 239, 90, 104, 125, 92, 254, 60, 49, 22, 163, 246, 161, 77, + 74, 29, 46, 126, 188, 67, 245, 138, 141, 59, 245, 16, 182, 84, 45, 120, 84, 244, 181, 80, 29, + 23, 17, 203, 133, 248, 249, 106, 130, 72, 254, 33, 154, 167, 227, 99, 214, 30, 202, 253, 234, + 1, 215, 95, 227, 154, 23, 42, 238, 19, 26, 119, 153, 227, 247, 18, 28, 237, 101, 56, 66, 159, + 30, 31, 119, 238, 50, 93, 24, 3, 87, 128, 184, 251, 10, 110, 92, 20, 93, 123, 31, 71, 84, 250, + 230, 55, 139, 203, 29, 217, 218, 57, 240, 254, 199, 146, 32, 230, 14, 71, 215, 84, 126, 162, + 203, 208, 185, 245, 238, 220, 197, 137, 232, 138, 55, 240, 152, 201, 208, 93, 231, 209, 144, + 104, 241, 167, 19, 182, 216, 193, 144, 218, 5, 132, 167, 86, 22, 152, 44, 230, 65, 122, 159, + 18, 175, 163, 205, 217, 248, 121, 179, 80, 118, 26, 43, 157, 122, 167, 211, 157, 230, 28, 154, + 169, 96, 249, 222, 15, 229, 150, 214, 58, 240, 153, 249, 207, 5, 103, 110, 191, 237, 3, 220, + 100, 212, 53, 27, 236, 157, 31, 224, 79, 39, 193, 110, 249, 135, 58, 60, 47, 239, 212, 125, + 215, 196, 62, 250, 196, 23, 110, 3, 249, 91, 220, 5, 223, 26, 175, 158, 158, 1, 48, 68, 146, + 114, 2, 59, 15, 64, 89, 21, 37, 17, 251, 81, 139, 178, 38, 154, 164, 67, 121, 205, 46, 217, + 177, 104, 209, 127, 76, 240, 149, 35, 127, 30, 1, 43, 134, 20, 227, 36, 6, 23, 188, 52, 189, + 66, 202, 239, 201, 248, 5, 51, 246, 11, 24, 38, 31, 18, 70, 196, 217, 75, 229, 189, 38, 121, + 34, 212, 139, 166, 156, 239, 231, 121, 37, 142, 159, 45, 20, 75, 39, 199, 66, 26, 175, 211, + 176, 155, 227, 193, 136, 38, 185, 132, 248, 201, 173, 210, 244, 130, 203, 248, 66, 217, 17, 2, + 152, 65, 97, 96, 69, 16, 237, 37, 134, 21, 114, 232, 101, 41, 143, 142, 158, 17, 120, 54, 117, + 162, 116, 28, 112, 74, 131, 251, 188, 108, 232, 52, 30, 50, 147, 136, 33, 226, 120, 145, 217, + 177, 187, 119, 139, 174, 47, 248, 3, 99, 163, 12, 65, 148, 69, 167, 68, 163, 46, 253, 220, 150, + 40, 124, 96, 179, 108, 155, 44, 52, 222, 233, 113, 128, 172, 2, 223, 208, 230, 245, 110, 65, + 158, 93, 187, 124, 241, 51, 94, 130, 180, 140, 195, 3, 217, 171, 30, 166, 254, 124, 38, 43, + 188, 60, 253, 155, 40, 145, 193, 114, 201, 84, 152, 93, 155, 191, 170, 151, 193, 196, 53, 61, + 5, 217, 68, 144, 246, 92, 235, 198, 116, 126, 59, 26, 146, 165, 0, 39, 63, 151, 219, 43, 90, + 98, 168, 246, 235, 218, 7, 154, 113, 190, 156, 105, 1, 50, 51, 56, 175, 151, 145, 72, 176, 37, + 9, 39, 59, 115, 218, 220, 66, 196, 10, 78, 68, 234, 109, 38, 137, 60, 176, 19, 221, 15, 125, + 227, 198, 210, 45, 165, 1, 127, 37, 177, 53, 111, 181, 211, 102, 207, 221, 115, 155, 206, 83, + 171, 152, 109, 142, 8, 240, 75, 254, 158, 53, 85, 62, 151, 181, 179, 237, 248, 71, 150, 160, + 148, 160, 244, 165, 118, 84, 37, 11, 163, 199, 183, 116, 28, 165, 68, 49, 112, 113, 116, 105, + 23, 95, 173, 144, 230, 162, 54, 71, 114, 138, 71, 148, 80, 93, 113, 85, 93, 202, 25, 111, 92, + 41, 148, 156, 91, 125, 35, 215, 49, 64, 92, 76, 13, 27, 149, 218, 143, 144, 91, 164, 194, 122, + 84, 236, 95, 150, 240, 32, 5, 241, 204, 209, 214, 69, 184, 255, 150, 119, 173, 190, 244, 193, + 235, 42, 214, 18, 40, 86, 185, 140, 48, 248, 73, 67, 178, 102, 31, 97, 88, 156, 108, 67, 244, + 42, 230, 40, 126, 127, 49, 204, 99, 214, 124, 241, 229, 252, 50, 204, 232, 96, 115, 157, 101, + 253, 129, 228, 194, 166, 81, 35, 52, 165, 81, 208, 7, 96, 192, 30, 246, 69, 29, 131, 224, 23, + 129, 235, 123, 200, 229, 54, 172, 239, 57, 111, 12, 19, 253, 125, 134, 149, 94, 123, 88, 98, + 17, 237, 101, 230, 240, 241, 34, 216, 28, 189, 18, 66, 142, 103, 98, 10, 18, 6, 78, 165, 119, + 7, 28, 133, 193, 182, 205, 74, 216, 242, 55, 129, 35, 78, 66, 225, 28, 117, 199, 85, 16, 149, + 198, 117, 36, 128, 244, 95, 233, 16, 158, 213, 79, 110, 90, 34, 217, 53, 242, 215, 222, 129, + 131, 158, 94, 29, 48, 206, 200, 197, 33, 21, 221, 97, 65, 58, 205, 30, 53, 205, 24, 172, 249, + 233, 185, 60, 59, 197, 121, 100, 97, 89, 136, 221, 184, 128, 70, 180, 240, 90, 108, 39, 33, 61, + 112, 63, 78, 221, 227, 155, 106, 250, 120, 210, 162, 211, 178, 9, 219, 0, 56, 136, 102, 246, + 201, 187, 171, 151, 182, 143, 248, 136, 226, 53, 190, 128, 128, 211, 96, 149, 223, 190, 212, + 102, 108, 101, 170, 37, 108, 232, 213, 203, 108, 17, 14, 251, 155, 109, 39, 116, 217, 144, 118, + 193, 42, 183, 26, 159, 15, 82, 7, 165, 64, 156, 61, 126, 154, 179, 167, 53, 144, 255, 241, 173, + 84, 106, 49, 164, 2, 185, 153, 240, 254, 174, 245, 187, 246, 180, 240, 242, 228, 58, 238, 202, + 236, 36, 124, 37, 47, 56, 184, 118, 215, 71, 22, 198, 250, 217, 214, 233, 128, 131, 188, 59, 9, + 71, 0, 188, 120, 150, 106, 246, 196, 28, 64, 28, 155, 108, 138, 234, 210, 116, 198, 190, 70, + 125, 85, 44, 203, 194, 57, 162, 2, 23, 62, 225, 177, 111, 250, 201, 48, 55, 214, 2, 53, 138, + 249, 119, 36, 225, 49, 79, 172, 165, 69, 167, 232, 253, 240, 69, 93, 77, 122, 27, 72, 0, 14, + 150, 133, 74, 108, 122, 38, 119, 112, 241, 190, 87, 234, 136, 33, 215, 104, 68, 238, 131, 248, + 99, 19, 53, 57, 52, 210, 60, 43, 224, 186, 215, 172, 234, 182, 49, 229, 184, 41, 243, 50, 203, + 255, 135, 123, 179, 182, 178, 191, 42, 93, 223, 25, 107, 113, 120, 150, 239, 71, 7, 63, 225, + 127, 85, 114, 235, 9, 36, 44, 159, 101, 212, 130, 81, 211, 198, 161, 34, 221, 138, 52, 236, + 209, 28, 232, 187, 64, 159, 224, 219, 61, 202, 174, 161, 93, 188, 119, 39, 76, 168, 104, 209, + 147, 224, 133, 137, 10, 9, 38, 10, 18, 15, 29, 64, 26, 104, 156, 79, 70, 54, 234, 105, 239, + 107, 208, 69, 23, 58, 130, 178, 173, 106, 215, 49, 209, 172, 122, 131, 103, 31, 62, 139, 247, + 238, 174, 245, 200, 98, 94, 53, 54, 4, 162, 156, 229, 159, 178, 102, 101, 227, 230, 148, 195, + 93, 254, 89, 102, 35, 206, 90, 247, 174, 41, 108, 253, 103, 58, 101, 102, 55, 64, 70, 210, 223, + 229, 4, 204, 254, 81, 255, 44, 169, 78, 207, 163, 62, 11, 12, 3, 159, 122, 95, 248, 155, 13, + 107, 187, 173, 80, 189, 236, 132, 104, 200, 72, 117, 31, 153, 191, 59, 61, 198, 197, 50, 193, + 102, 178, 24, 135, 136, 198, 176, 54, 57, 64, 151, 109, 21, 6, 129, 33, 240, 14, 2, 217, 112, + 112, 146, 201, 90, 200, 69, 178, 51, 235, 192, 25, 221, 233, 72, 184, 128, 37, 228, 32, 233, + 51, 162, 31, 42, 112, 12, 186, 197, 211, 195, 175, 177, 87, 50, 191, 35, 135, 120, 58, 92, 110, + 129, 137, 49, 219, 218, 45, 252, 209, 75, 215, 149, 109, 183, 142, 179, 0, 224, 85, 229, 135, + 216, 164, 225, 144, 215, 9, 209, 37, 84, 29, 235, 106, 155, 190, 71, 119, 98, 200, 103, 17, + 174, 250, 249, 53, 5, 8, 239, 215, 223, 185, 147, 44, 22, 202, 34, 166, 43, 95, 155, 153, 234, + 244, 250, 96, 95, 161, 23, 196, 174, 222, 191, 80, 166, 145, 27, 104, 85, 95, 212, 230, 36, + 238, 233, 90, 5, 197, 134, 170, 113, 121, 208, 242, 65, 72, 227, 93, 61, 127, 224, 231, 70, 33, + 246, 71, 0, 162, 185, 67, 241, 208, 242, 3, 102, 185, 31, 87, 1, 98, 164, 215, 211, 230, 82, + 196, 199, 83, 239, 255, 95, 172, 188, 185, 180, 117, 39, 150, 54, 133, 43, 29, 17, 97, 9, 21, + 171, 122, 88, 3, 129, 121, 190, 147, 110, 217, 47, 232, 136, 92, 111, 199, 61, 202, 244, 232, + 214, 72, 75, 134, 167, 208, 163, 162, 225, 221, 211, 58, 251, 223, 149, 49, 100, 96, 51, 53, + 121, 161, 136, 12, 238, 199, 158, 162, 82, 166, 146, 223, 202, 202, 130, 211, 189, 202, 215, + 31, 166, 168, 196, 135, 96, 223, 102, 98, 121, 243, 95, 237, 103, 225, 117, 60, 100, 210, 229, + 148, 249, 189, 105, 78, 69, 116, 12, 33, 87, 72, 84, 239, 99, 188, 105, 255, 18, 96, 78, 131, + 9, 212, 44, 188, 16, 85, 30, 33, 238, 244, 194, 217, 240, 61, 235, 167, 120, 199, 169, 161, 78, + 13, 151, 178, 251, 50, 160, 155, 207, 62, 60, 204, 41, 254, 102, 233, 65, 85, 89, 195, 202, 78, + 0, 88, 113, 135, 224, 237, 252, 154, 102, 190, 92, 187, 70, 168, 14, 221, 100, 132, 69, 175, + 243, 165, 74, 18, 165, 196, 232, 202, 211, 13, 238, 89, 8, 222, 53, 30, 95, 253, 48, 157, 69, + 229, 34, 117, 165, 232, 133, 46, 182, 140, 207, 27, 183, 133, 28, 244, 38, 181, 212, 75, 179, + 22, 162, 21, 199, 101, 80, 125, 185, 49, 166, 17, 247, 25, 51, 250, 253, 26, 111, 27, 237, 51, + 196, 80, 111, 79, 143, 79, 205, 132, 244, 166, 155, 171, 185, 159, 144, 207, 128, 114, 136, + 128, 28, 115, 70, 186, 110, 194, 228, 54, 177, 51, 0, 212, 145, 216, 165, 86, 242, 35, 31, 255, + 239, 149, 19, 193, 107, 84, 136, 61, 60, 95, 113, 160, 45, 116, 164, 101, 252, 166, 189, 110, + 1, 193, 132, 79, 213, 17, 102, 94, 191, 81, 173, 239, 169, 47, 255, 108, 74, 208, 144, 79, 212, + 205, 106, 193, 139, 69, 62, 152, 112, 3, 11, 23, 239, 187, 160, 193, 1, 110, 80, 224, 159, 39, + 11, 112, 1, 135, 250, 98, 251, 13, 143, 3, 165, 201, 68, 234, 194, 93, 3, 158, 165, 138, 194, + 187, 143, 230, 37, 195, 166, 48, 77, 104, 161, 6, 231, 44, 104, 66, 87, 214, 14, 85, 61, 27, + 86, 184, 156, 127, 19, 203, 217, 249, 222, 122, 29, 43, 3, 17, 169, 133, 209, 175, 244, 188, + 89, 15, 249, 37, 107, 149, 50, 132, 70, 60, 73, 26, 141, 86, 244, 30, 23, 10, 163, 125, 166, + 226, 230, 107, 149, 76, 227, 82, 209, 59, 152, 18, 101, 227, 25, 32, 243, 230, 74, 166, 16, 74, + 148, 151, 81, 201, 237, 81, 158, 181, 153, 242, 13, 162, 126, 248, 152, 18, 42, 91, 193, 214, + 189, 122, 226, 159, 68, 216, 163, 239, 177, 238, 5, 5, 4, 122, 181, 236, 98, 82, 63, 107, 124, + 30, 191, 211, 172, 89, 236, 51, 1, 53, 222, 192, 10, 230, 36, 232, 208, 87, 120, 184, 1, 7, 12, + 228, 122, 236, 93, 94, 164, 250, 166, 132, 31, 1, 56, 188, 168, 229, 11, 131, 172, 54, 147, + 243, 143, 255, 1, 36, 87, 94, 232, 90, 39, 158, 116, 15, 6, 15, 197, 34, 190, 68, 77, 177, 194, + 88, 242, 172, 37, 73, 222, 44, 194, 124, 193, 155, 154, 57, 219, 237, 202, 84, 151, 34, 35, + 188, 195, 10, 106, 188, 191, 102, 193, 213, 145, 0, 147, 174, 194, 89, 142, 206, 58, 110, 119, + 86, 149, 183, 167, 121, 167, 192, 80, 218, 163, 46, 191, 95, 39, 20, 213, 190, 103, 127, 74, + 255, 68, 88, 136, 163, 66, 169, 50, 232, 25, 215, 31, 51, 83, 132, 118, 28, 218, 91, 93, 176, + 205, 123, 188, 123, 242, 251, 115, 228, 125, 191, 84, 65, 22, 199, 218, 199, 146, 168, 112, 60, + 58, 170, 218, 4, 125, 91, 3, 72, 214, 77, 133, 243, 251, 43, 255, 176, 210, 151, 54, 197, 253, + 28, 238, 218, 170, 132, 136, 186, 241, 111, 11, 250, 118, 189, 236, 178, 150, 218, 159, 3, 171, + 162, 172, 185, 43, 55, 225, 200, 244, 119, 44, 173, 222, 87, 210, 77, 233, 105, 65, 63, 241, + 220, 130, 235, 123, 68, 199, 89, 234, 130, 139, 84, 16, 46, 30, 51, 197, 246, 172, 102, 14, 31, + 121, 214, 192, 54, 251, 252, 127, 196, 43, 157, 51, 245, 8, 39, 116, 217, 69, 253, 184, 246, + 240, 58, 223, 153, 155, 139, 179, 74, 124, 158, 225, 234, 166, 112, 203, 174, 128, 88, 160, 6, + 56, 1, 165, 38, 168, 64, 225, 137, 228, 223, 137, 228, 227, 160, 218, 243, 79, 69, 188, 64, + 122, 139, 191, 98, 107, 10, 232, 19, 36, 221, 94, 17, 27, 200, 137, 137, 252, 213, 7, 200, 97, + 46, 188, 4, 169, 193, 131, 129, 239, 179, 144, 118, 57, 113, 220, 70, 177, 106, 214, 225, 182, + 115, 175, 181, 84, 83, 129, 114, 107, 151, 62, 135, 103, 75, 176, 231, 65, 208, 112, 100, 2, + 193, 75, 99, 14, 122, 57, 122, 122, 136, 150, 170, 105, 208, 252, 246, 142, 161, 15, 29, 10, + 71, 3, 9, 99, 41, 23, 68, 58, 118, 190, 208, 151, 59, 149, 84, 26, 40, 211, 176, 63, 0, 159, + 235, 115, 84, 54, 11, 218, 183, 216, 147, 207, 96, 33, 99, 4, 48, 90, 92, 172, 36, 213, 233, + 247, 194, 124, 247, 225, 130, 159, 27, 111, 75, 52, 84, 38, 248, 18, 148, 32, 161, 117, 18, 86, + 131, 129, 161, 202, 51, 211, 103, 147, 215, 229, 230, 34, 187, 185, 93, 37, 53, 179, 202, 106, + 201, 105, 207, 212, 167, 152, 191, 200, 70, 141, 200, 230, 249, 244, 110, 199, 125, 36, 18, + 103, 217, 2, 167, 125, 170, 75, 20, 224, 92, 251, 26, 234, 35, 18, 81, 212, 186, 233, 98, 9, + 181, 64, 67, 28, 176, 15, 79, 242, 202, 244, 111, 248, 36, 122, 231, 2, 98, 216, 4, 226, 149, + 161, 9, 211, 139, 134, 249, 207, 79, 92, 247, 176, 52, 10, 6, 189, 39, 84, 99, 46, 179, 83, + 248, 75, 6, 122, 103, 129, 244, 143, 13, 154, 240, 8, 137, 52, 123, 8, 85, 51, 121, 201, 5, 60, + 6, 63, 113, 40, 31, 218, 47, 222, 201, 140, 58, 149, 243, 186, 131, 128, 27, 183, 173, 93, 190, + 200, 130, 254, 237, 51, 1, 124, 214, 240, 237, 61, 193, 63, 232, 243, 239, 191, 212, 101, 17, + 11, 103, 88, 134, 233, 64, 37, 213, 108, 143, 218, 121, 222, 82, 243, 207, 198, 193, 179, 230, + 164, 250, 40, 105, 206, 38, 45, 132, 45, 59, 226, 74, 112, 49, 36, 171, 82, 62, 2, 186, 195, + 145, 121, 205, 208, 179, 154, 229, 33, 2, 238, 95, 127, 57, 18, 173, 27, 13, 201, 63, 162, 199, + 142, 25, 155, 8, 100, 5, 134, 61, 12, 193, 135, 41, 192, 219, 121, 240, 176, 150, 91, 11, 145, + 142, 113, 75, 160, 220, 177, 141, 68, 39, 66, 72, 139, 99, 79, 7, 50, 51, 82, 31, 91, 72, 2, + 66, 106, 109, 161, 254, 134, 232, 96, 175, 140, 139, 53, 101, 221, 195, 36, 211, 16, 176, 156, + 218, 7, 170, 181, 82, 157, 200, 79, 190, 234, 162, 73, 180, 189, 200, 166, 49, 128, 228, 137, + 222, 19, 81, 45, 160, 102, 128, 139, 51, 56, 82, 105, 57, 159, 6, 166, 94, 222, 35, 188, 57, + 128, 158, 168, 117, 221, 154, 100, 226, 200, 203, 122, 75, 11, 141, 194, 152, 120, 142, 11, + 199, 111, 20, 203, 216, 76, 200, 125, 164, 117, 59, 208, 4, 150, 151, 103, 56, 85, 232, 180, + 61, 162, 23, 137, 143, 176, 79, 251, 184, 240, 175, 185, 78, 221, 175, 171, 5, 60, 128, 66, + 184, 204, 79, 38, 118, 121, 95, 196, 190, 181, 219, 200, 230, 61, 65, 232, 81, 196, 119, 85, + 221, 194, 91, 151, 45, 121, 159, 44, 13, 5, 123, 105, 112, 56, 161, 228, 44, 194, 110, 67, 209, + 231, 255, 69, 172, 165, 199, 105, 87, 100, 27, 177, 54, 255, 9, 223, 224, 31, 211, 231, 191, + 182, 123, 2, 81, 191, 246, 42, 45, 238, 165, 162, 137, 206, 103, 84, 51, 251, 210, 133, 98, + 127, 113, 125, 82, 151, 155, 212, 20, 97, 245, 122, 26, 119, 114, 198, 168, 208, 100, 58, 218, + 60, 148, 70, 69, 184, 81, 76, 242, 193, 17, 210, 107, 193, 166, 243, 46, 132, 21, 76, 66, 223, + 254, 226, 167, 155, 9, 247, 141, 185, 6, 18, 227, 95, 57, 77, 64, 34, 31, 218, 24, 0, 119, 138, + 140, 206, 185, 85, 219, 35, 47, 97, 180, 55, 251, 205, 153, 24, 216, 50, 241, 240, 143, 113, + 94, 237, 40, 17, 23, 148, 88, 178, 251, 127, 213, 99, 232, 195, 149, 104, 127, 145, 149, 39, + 54, 109, 168, 98, 167, 118, 4, 24, 27, 184, 146, 82, 182, 184, 28, 31, 55, 0, 248, 239, 243, + 24, 37, 102, 240, 140, 146, 162, 95, 130, 174, 146, 78, 23, 139, 143, 11, 208, 162, 152, 209, + 209, 34, 73, 106, 176, 210, 167, 62, 15, 7, 153, 182, 146, 79, 207, 222, 125, 115, 189, 104, + 132, 165, 217, 73, 128, 133, 48, 135, 128, 27, 184, 209, 86, 78, 140, 32, 21, 119, 66, 55, 240, + 255, 152, 89, 87, 200, 83, 20, 237, 126, 10, 111, 252, 169, 111, 232, 236, 170, 70, 246, 246, + 237, 226, 93, 194, 184, 150, 49, 132, 217, 40, 169, 38, 54, 5, 190, 131, 53, 10, 176, 235, 51, + 173, 172, 150, 131, 80, 153, 245, 213, 69, 215, 95, 38, 55, 152, 212, 204, 251, 105, 96, 48, + 108, 71, 41, 185, 57, 2, 177, 105, 90, 101, 226, 242, 232, 120, 11, 172, 225, 141, 16, 159, 49, + 135, 231, 41, 223, 102, 131, 101, 50, 39, 42, 245, 225, 244, 117, 188, 108, 55, 99, 182, 92, + 126, 254, 235, 223, 154, 228, 86, 224, 194, 25, 138, 83, 162, 169, 137, 207, 203, 220, 72, 164, + 83, 168, 179, 173, 138, 87, 191, 21, 66, 200, 90, 32, 246, 115, 81, 190, 231, 152, 187, 198, + 21, 62, 33, 215, 134, 5, 1, 157, 66, 244, 50, 118, 98, 194, 177, 254, 238, 65, 103, 110, 242, + 66, 133, 138, 149, 35, 21, 90, 161, 109, 253, 52, 78, 50, 248, 83, 238, 109, 113, 241, 177, + 177, 50, 141, 8, 7, 157, 62, 241, 177, 182, 213, 128, 152, 213, 100, 99, 173, 236, 22, 72, 218, + 37, 243, 140, 115, 39, 27, 74, 48, 14, 9, 75, 59, 62, 77, 227, 23, 139, 45, 44, 122, 96, 186, + 162, 108, 72, 95, 228, 41, 25, 26, 248, 195, 49, 209, 60, 218, 47, 90, 101, 34, 195, 90, 10, + 157, 21, 255, 76, 64, 223, 37, 29, 26, 46, 56, 120, 132, 21, 42, 245, 240, 85, 199, 19, 201, + 85, 193, 219, 221, 215, 223, 84, 246, 95, 245, 5, 75, 224, 171, 164, 25, 224, 150, 9, 216, 217, + 213, 15, 151, 241, 76, 233, 18, 40, 254, 100, 93, 154, 53, 251, 217, 138, 131, 51, 74, 10, 121, + 247, 180, 44, 8, 228, 61, 221, 148, 195, 96, 13, 218, 83, 72, 171, 45, 19, 4, 216, 206, 167, + 199, 5, 151, 63, 26, 213, 246, 170, 247, 140, 152, 237, 72, 148, 250, 153, 140, 67, 46, 66, + 232, 169, 48, 246, 190, 89, 66, 108, 236, 145, 63, 249, 218, 181, 10, 146, 35, 99, 161, 186, + 180, 125, 90, 167, 213, 198, 75, 29, 95, 57, 176, 116, 214, 117, 70, 0, 191, 237, 127, 153, + 134, 185, 97, 90, 225, 93, 237, 204, 247, 238, 213, 66, 28, 219, 91, 198, 120, 173, 144, 14, + 80, 139, 9, 213, 79, 27, 220, 47, 81, 240, 145, 90, 59, 170, 188, 247, 98, 84, 181, 173, 181, + 53, 155, 115, 80, 38, 180, 119, 243, 243, 137, 133, 227, 149, 157, 166, 189, 60, 49, 182, 74, + 147, 205, 106, 173, 150, 227, 134, 140, 130, 79, 2, 162, 192, 213, 192, 70, 137, 99, 137, 213, + 55, 198, 252, 229, 48, 48, 66, 222, 16, 7, 225, 202, 50, 122, 120, 90, 132, 169, 153, 166, 15, + 109, 48, 40, 71, 199, 36, 255, 202, 167, 23, 42, 247, 127, 185, 165, 157, 65, 160, 58, 144, 24, + 166, 128, 85, 244, 93, 79, 20, 14, 91, 83, 178, 79, 245, 120, 148, 23, 242, 208, 76, 160, 141, + 211, 104, 95, 185, 223, 122, 62, 120, 177, 74, 144, 93, 71, 251, 160, 208, 44, 192, 91, 222, + 171, 184, 125, 41, 186, 170, 254, 183, 129, 157, 10, 197, 117, 164, 203, 38, 57, 13, 175, 225, + 135, 210, 76, 231, 139, 53, 198, 74, 107, 109, 61, 235, 58, 158, 163, 118, 35, 20, 97, 222, + 127, 219, 228, 34, 216, 0, 55, 125, 197, 182, 153, 134, 169, 13, 195, 157, 128, 195, 229, 192, + 25, 177, 100, 249, 160, 58, 239, 77, 144, 166, 239, 105, 126, 136, 82, 25, 180, 244, 9, 185, + 133, 210, 67, 20, 165, 35, 179, 188, 130, 100, 132, 77, 12, 105, 73, 76, 246, 40, 152, 80, 83, + 253, 166, 73, 19, 224, 72, 83, 90, 227, 236, 57, 203, 16, 222, 91, 20, 99, 80, 183, 230, 4, 4, + 202, 65, 66, 43, 98, 21, 99, 247, 97, 50, 50, 223, 235, 238, 12, 198, 119, 152, 208, 139, 103, + 43, 98, 56, 233, 60, 161, 164, 1, 92, 129, 89, 124, 44, 177, 62, 130, 96, 38, 113, 17, 83, 160, + 216, 177, 146, 127, 111, 250, 201, 73, 112, 102, 102, 67, 112, 62, 116, 32, 31, 210, 124, 252, + 83, 215, 137, 44, 31, 2, 87, 3, 147, 134, 204, 245, 94, 215, 180, 17, 220, 47, 182, 25, 79, + 104, 255, 76, 81, 213, 23, 130, 99, 32, 232, 81, 190, 157, 93, 65, 225, 203, 197, 196, 98, 89, + 82, 44, 209, 164, 117, 110, 64, 54, 12, 232, 142, 136, 135, 113, 225, 206, 188, 180, 201, 41, + 39, 37, 49, 27, 21, 214, 194, 166, 113, 77, 89, 55, 2, 231, 221, 206, 129, 128, 27, 26, 17, + 249, 95, 85, 65, 55, 225, 214, 188, 164, 39, 35, 249, 236, 0, 0, 0, 115, 0, 0, 0, 0, 8, 0, 0, + 0, 41, 33, 28, 17, 0, 65, 62, 49, +]; + +fn test_gen_key_pair() { + let mut trng = unsafe { + Trng::new( + CsrngReg::new(), + EntropySrcReg::new(), + SocIfcTrngReg::new(), + &SocIfcReg::new(), + ) + .unwrap() + }; + let mut entropy_gen = || trng.generate().map(|a| a.0); + + // This needs to happen in the first test + CfiCounter::reset(&mut entropy_gen); + + let mut ml_dsa87 = unsafe { Mldsa87::new(MldsaReg::new()) }; + + let mut hmac = unsafe { Hmac::new(HmacReg::new()) }; + let key_out_1 = KeyWriteArgs { + id: KeyId::KeyId0, + usage: KeyUsage::default().set_ecc_key_gen_seed_en(), + }; + + hmac.hmac( + &HmacKey::from(&Array4x12::default()), + &HmacData::from(&[0]), + &mut trng, + HmacTag::Key(key_out_1), + HmacMode::Hmac384, + ) + .unwrap(); + + let seed = KeyReadArgs::new(KeyId::KeyId0); + let public_key = ml_dsa87.key_pair(&seed, &mut trng).unwrap(); + + assert_eq!(public_key, Mldsa87PubKey::from(PUBKEY)); +} + +fn test_sign() { + let mut ml_dsa87 = unsafe { Mldsa87::new(MldsaReg::new()) }; + + let mut trng = unsafe { + Trng::new( + CsrngReg::new(), + EntropySrcReg::new(), + SocIfcTrngReg::new(), + &SocIfcReg::new(), + ) + .unwrap() + }; + + let msg = Mldsa87Msg::default(); + let sign_rnd = Mldsa87SignRnd::default(); // Deterministic signing + let seed = KeyReadArgs::new(KeyId::KeyId0); // Reuse SEED + + let signature = ml_dsa87 + .sign( + &seed, + &Mldsa87PubKey::from(PUBKEY), + &msg, + &sign_rnd, + &mut trng, + ) + .unwrap(); + + assert_eq!(signature, Mldsa87Signature::from(SIGNATURE)); +} + +fn test_verify() { + let mut ml_dsa87 = unsafe { Mldsa87::new(MldsaReg::new()) }; + + let msg = Mldsa87Msg::default(); + + assert_eq!( + ml_dsa87 + .verify( + &Mldsa87PubKey::from(PUBKEY), + &msg, + &Mldsa87Signature::from(SIGNATURE) + ) + .unwrap(), + Mldsa87Result::Success + ); +} + +fn test_verify_failure() { + let mut ml_dsa87 = unsafe { Mldsa87::new(MldsaReg::new()) }; + + let msg = Mldsa87Msg::from([0xff; 64]); + + assert_eq!( + ml_dsa87 + .verify( + &Mldsa87PubKey::from(PUBKEY), + &msg, + &Mldsa87Signature::from(SIGNATURE) + ) + .unwrap(), + Mldsa87Result::SigVerifyFailed + ); +} + +test_suite! { + test_gen_key_pair, + test_sign, + test_verify, + test_verify_failure, +} diff --git a/drivers/tests/drivers_integration_tests/main.rs b/drivers/tests/drivers_integration_tests/main.rs index b548ac2fb2..4ce11e5d20 100644 --- a/drivers/tests/drivers_integration_tests/main.rs +++ b/drivers/tests/drivers_integration_tests/main.rs @@ -335,6 +335,11 @@ fn test_ecc384_sign_validation_failure() { .unwrap(); } +#[test] +fn test_ml_dsa87() { + run_driver_test(&firmware::driver_tests::ML_DSA87); +} + #[test] fn test_error_reporter() { run_driver_test(&firmware::driver_tests::ERROR_REPORTER); diff --git a/error/src/lib.rs b/error/src/lib.rs index 3097d8be94..6103bd3c21 100644 --- a/error/src/lib.rs +++ b/error/src/lib.rs @@ -108,6 +108,16 @@ impl CaliptraError { pub const DRIVER_ECC384_KEYGEN_BAD_USAGE: CaliptraError = CaliptraError::new_const(0x00050010); pub const DRIVER_ECC384_HW_ERROR: CaliptraError = CaliptraError::new_const(0x00050011); + pub const DRIVER_MLDSA87_READ_SEED_KV_READ: CaliptraError = + CaliptraError::new_const(0x00058000); + pub const DRIVER_MLDSA87_READ_SEED_KV_WRITE: CaliptraError = + CaliptraError::new_const(0x00058001); + pub const DRIVER_MLDSA87_READ_SEED_KV_UNKNOWN: CaliptraError = + CaliptraError::new_const(0x00058002); + pub const DRIVER_MLDSA87_HW_ERROR: CaliptraError = CaliptraError::new_const(0x00058003); + pub const DRIVER_MLDSA87_SIGN_VALIDATION_FAILED: CaliptraError = + CaliptraError::new_const(0x00058004); + pub const DRIVER_KV_ERASE_USE_LOCK_SET_FAILURE: CaliptraError = CaliptraError::new_const(0x00060001); pub const DRIVER_KV_ERASE_WRITE_LOCK_SET_FAILURE: CaliptraError = diff --git a/hw/latest/registers/src/i3ccsr.rs b/hw/latest/registers/src/i3ccsr.rs index 354759dac0..9c643394e6 100644 --- a/hw/latest/registers/src/i3ccsr.rs +++ b/hw/latest/registers/src/i3ccsr.rs @@ -13,7 +13,7 @@ pub struct I3ccsr { _priv: (), } impl I3ccsr { - pub const PTR: *mut u32 = 0x10038000 as *mut u32; + pub const PTR: *mut u32 = 0x10040000 as *mut u32; /// # Safety /// /// Caller must ensure that all concurrent use of this diff --git a/hw/latest/registers/src/mldsa.rs b/hw/latest/registers/src/mldsa.rs index 1473d7d545..32d0f3ae71 100644 --- a/hw/latest/registers/src/mldsa.rs +++ b/hw/latest/registers/src/mldsa.rs @@ -576,8 +576,11 @@ pub mod regs { impl CtrlWriteVal { /// Control command field #[inline(always)] - pub fn ctrl(self, val: u32) -> Self { - Self((self.0 & !(7 << 0)) | ((val & 7) << 0)) + pub fn ctrl( + self, + f: impl FnOnce(super::enums::selector::CtrlSelector) -> super::enums::Ctrl, + ) -> Self { + Self((self.0 & !(7 << 0)) | (u32::from(f(super::enums::selector::CtrlSelector())) << 0)) } /// Zeroize all internal registers #[inline(always)] @@ -910,6 +913,56 @@ pub mod enums { //! Enumerations used by some register fields. #[derive(Clone, Copy, Eq, PartialEq)] #[repr(u32)] + pub enum Ctrl { + None = 0, + Keygen = 1, + Signing = 2, + Verifying = 3, + KeygenSign = 4, + Reserved5 = 5, + Reserved6 = 6, + Reserved7 = 7, + } + impl Ctrl { + #[inline(always)] + pub fn none(&self) -> bool { + *self == Self::None + } + #[inline(always)] + pub fn keygen(&self) -> bool { + *self == Self::Keygen + } + #[inline(always)] + pub fn signing(&self) -> bool { + *self == Self::Signing + } + #[inline(always)] + pub fn verifying(&self) -> bool { + *self == Self::Verifying + } + #[inline(always)] + pub fn keygen_sign(&self) -> bool { + *self == Self::KeygenSign + } + } + impl TryFrom for Ctrl { + type Error = (); + #[inline(always)] + fn try_from(val: u32) -> Result { + if val < 8 { + Ok(unsafe { core::mem::transmute(val) }) + } else { + Err(()) + } + } + } + impl From for u32 { + fn from(val: Ctrl) -> Self { + val as u32 + } + } + #[derive(Clone, Copy, Eq, PartialEq)] + #[repr(u32)] pub enum KvErrorE { Success = 0, KvReadFail = 1, @@ -1199,6 +1252,29 @@ pub mod enums { } } pub mod selector { + pub struct CtrlSelector(); + impl CtrlSelector { + #[inline(always)] + pub fn none(&self) -> super::Ctrl { + super::Ctrl::None + } + #[inline(always)] + pub fn keygen(&self) -> super::Ctrl { + super::Ctrl::Keygen + } + #[inline(always)] + pub fn signing(&self) -> super::Ctrl { + super::Ctrl::Signing + } + #[inline(always)] + pub fn verifying(&self) -> super::Ctrl { + super::Ctrl::Verifying + } + #[inline(always)] + pub fn keygen_sign(&self) -> super::Ctrl { + super::Ctrl::KeygenSign + } + } pub struct KvErrorESelector(); impl KvErrorESelector { #[inline(always)] diff --git a/registers/bin/extra-rdl/el2_pic_ctrl.rdl b/registers/bin/extra-rdl/el2_pic_ctrl.rdl index a9fa533f59..513665f358 100644 --- a/registers/bin/extra-rdl/el2_pic_ctrl.rdl +++ b/registers/bin/extra-rdl/el2_pic_ctrl.rdl @@ -89,5 +89,5 @@ addrmap el2_pic_ctrl { addrmap clp2 { el2_pic_ctrl el2_pic_ctrl @ 0x6000_0000; - I3CCSR I3CCSR @ 0x1003_8000; + I3CCSR I3CCSR @ 0x1004_0000; }; diff --git a/registers/bin/generator/src/main.rs b/registers/bin/generator/src/main.rs index 90a9533e0f..0c020e81d9 100644 --- a/registers/bin/generator/src/main.rs +++ b/registers/bin/generator/src/main.rs @@ -321,6 +321,41 @@ fn real_main() -> Result<(), Box> { ); }); } + if block.block().name == "mldsa" { + block.transform(|t| { + // [TODO]: Put this enumeration into the RDL and remove this hack + t.set_register_enum( + "CTRL", + "CTRL", + Rc::new(Enum { + name: Some("Ctrl".into()), + variants: vec![ + EnumVariant { + name: "NONE".into(), + value: 0, + }, + EnumVariant { + name: "KEYGEN".into(), + value: 1, + }, + EnumVariant { + name: "SIGNING".into(), + value: 2, + }, + EnumVariant { + name: "VERIFYING".into(), + value: 3, + }, + EnumVariant { + name: "KEYGEN_SIGN".into(), + value: 4, + }, + ], + bit_width: 3, + }), + ); + }); + } let module_ident = format_ident!("{}", block.block().name); ureg_codegen::build_extern_types( diff --git a/rom/dev/README.md b/rom/dev/README.md index 792b576164..3570812db5 100644 --- a/rom/dev/README.md +++ b/rom/dev/README.md @@ -188,9 +188,9 @@ The following sections define the various cryptographic primitives used by Calip | Elliptic Curve Cryptography | `ecc384_keygen(seed_kv_slot, priv_kv_slot) -> pub_key` | Generate ECC384 Key Pair.
**Input**:
***seed_key_slot*** - key vault slot to use as seed for key generation
***priv_kv_slot*** - key vault slot to store the private key to
**Output**:
***pub-key*** - public key associated with the private key | | | `ecc384_sign(priv_kv_slot, data) -> sig` | ECC384 signing operation
**Input**:
***priv_kv_slot*** - key vault slot to use a private key from
***data*** - data to sign
**Output**:
***sig*** - signature | | | `ecc384_verify(pub_key, data, sig) -> CaliptraResult>` | ECC384 verify operation
**Input**:
***pub-key*** -public key
data - data to verify
sig - signature
**Output**:
***Ecc384Result*** - verify.r value on success, else an error | -| Module-Lattice-Based Digital Signature Algorithm | `mldsa87_keygen(seed_kv_slot) -> pub_key` | Generate MLDSA87 Key Pair.
**Input**:
***seed_key_slot*** - key vault slot to use as seed for key generation
**Output**:
***pub-key*** - public key associated with the private key | -| | `mldsa87_sign(seed_kv_slot, data) -> sig` | MLDSA87 signing operation
**Input**:
***seed_kv_slot*** - key vault slot to use as seed for key generation for signing
***data*** - data to sign
**Output**:
***sig*** - signature | -| | `mldsa87_verify(pub_key, data, sig) -> MlDsa87Result` | MLDSA87 verify operation
**Input**:
***pub-key*** -public key
data - data to verify
sig - signature
**Output**:
***MlDsa87Result*** - '0xAAAAAAAA' value on success, '0x55555555' on error | +| Module-Lattice-Based Digital Signature Algorithm | `mldsa87_keygen(seed_kv_slot) -> pub_key` | Generate Mldsa87 Key Pair.
**Input**:
***seed_key_slot*** - key vault slot to use as seed for key generation
**Output**:
***pub-key*** - public key associated with the private key | +| | `mldsa87_sign(seed_kv_slot, data) -> sig` | Mldsa87 signing operation
**Input**:
***seed_kv_slot*** - key vault slot to use as seed for key generation for signing
***data*** - data to sign
**Output**:
***sig*** - signature | +| | `mldsa87_verify(pub_key, data, sig) -> Mldsa87Result` | Mldsa87 verify operation
**Input**:
***pub-key*** -public key
data - data to verify
sig - signature
**Output**:
***Mldsa87Result*** - '0xAAAAAAAA' value on success, '0x55555555' on error | | Secure Hash Algorithm | `sha384_digest(data) -> digest` | Calculate the digest of the data
**Input**:
***data*** - data to verify
**Output**:
***digest*** - digest of the data | | Key Vault | `kv_clear(kv_slot)` | Key Vault slot to clear
**Input**:
***kv_slot*** - key vault slot to clear | | Data Vault | `dv48_store(data, dv_slot)` | Store the 48-byte data in the specified data vault slot
**Input**:
***data*** - data to store
***dv_slot*** - data vault slot | diff --git a/rom/dev/src/flow/cold_reset/crypto.rs b/rom/dev/src/flow/cold_reset/crypto.rs index e9cc8a3a12..9a816fd3e2 100644 --- a/rom/dev/src/flow/cold_reset/crypto.rs +++ b/rom/dev/src/flow/cold_reset/crypto.rs @@ -56,7 +56,7 @@ pub struct MlDsaKeyPair { pub key_pair_seed: KeyId, /// Public Key - pub pub_key: MlDsa87PubKey, + pub pub_key: Mldsa87PubKey, } pub enum Crypto {} @@ -251,7 +251,7 @@ impl Crypto { /// /// # Returns /// - /// * `MlDsa87PubKey` - Public key + /// * `Mldsa87PubKey` - Public key #[inline(always)] pub fn mldsa_key_gen( env: &mut RomEnv, diff --git a/rom/dev/src/rom_env.rs b/rom/dev/src/rom_env.rs index cbe867e9b9..7294716be9 100644 --- a/rom/dev/src/rom_env.rs +++ b/rom/dev/src/rom_env.rs @@ -17,14 +17,14 @@ Abstract: use crate::fht::FhtDataStore; use caliptra_drivers::{ - DataVault, DeobfuscationEngine, Ecc384, Hmac, KeyVault, Lms, Mailbox, MlDsa87, MlDsa87Reg, - PcrBank, PersistentDataAccessor, Sha1, Sha256, Sha2_512_384Acc, Sha384, SocIfc, Trng, + DataVault, DeobfuscationEngine, Ecc384, Hmac, KeyVault, Lms, Mailbox, Mldsa87, PcrBank, + PersistentDataAccessor, Sha1, Sha256, Sha2_512_384Acc, Sha384, SocIfc, Trng, }; use caliptra_error::CaliptraResult; use caliptra_registers::{ csrng::CsrngReg, doe::DoeReg, dv::DvReg, ecc::EccReg, entropy_src::EntropySrcReg, - hmac::HmacReg, kv::KvReg, mbox::MboxCsr, pv::PvReg, sha256::Sha256Reg, sha512::Sha512Reg, - sha512_acc::Sha512AccCsr, soc_ifc::SocIfcReg, soc_ifc_trng::SocIfcTrngReg, + hmac::HmacReg, kv::KvReg, mbox::MboxCsr, mldsa::MldsaReg, pv::PvReg, sha256::Sha256Reg, + sha512::Sha512Reg, sha512_acc::Sha512AccCsr, soc_ifc::SocIfcReg, soc_ifc_trng::SocIfcTrngReg, }; /// Rom Context @@ -77,8 +77,8 @@ pub struct RomEnv { /// Mechanism to access the persistent data safely pub persistent_data: PersistentDataAccessor, - /// MlDsa87 Engine - pub mldsa: MlDsa87, + /// Mldsa87 Engine + pub mldsa: Mldsa87, } impl RomEnv { @@ -107,7 +107,7 @@ impl RomEnv { fht_data_store: FhtDataStore::default(), trng, persistent_data: PersistentDataAccessor::new(), - mldsa: MlDsa87::new(MlDsa87Reg::new()), + mldsa: Mldsa87::new(MldsaReg::new()), }) } } diff --git a/sw-emulator/lib/periph/src/ml_dsa87.rs b/sw-emulator/lib/periph/src/ml_dsa87.rs index ca1782f1e2..172424f52c 100644 --- a/sw-emulator/lib/periph/src/ml_dsa87.rs +++ b/sw-emulator/lib/periph/src/ml_dsa87.rs @@ -98,7 +98,7 @@ register_bitfields! [ #[poll_fn(poll)] #[warm_reset_fn(warm_reset)] #[update_reset_fn(update_reset)] -pub struct MlDsa87 { +pub struct Mldsa87 { /// Name registers #[register_array(offset = 0x0000_0000)] name: [u32; 2], @@ -136,22 +136,30 @@ pub struct MlDsa87 { verify_res: [u32; ML_DSA87_VERIFICATION_SIZE / 4], /// Public key - #[register_array(offset = 0x0000_0118)] + #[register_array(offset = 0x0000_1000)] pubkey: [u32; ML_DSA87_PUBKEY_SIZE / 4], /// Signature - #[register_array(offset = 0x0000_0b38)] + #[register_array(offset = 0x0000_2000)] signature: [u32; ML_DSA87_SIGNATURE_SIZE / 4], // Private Key In & Out (We don't want to use this) /// Key Vault Read Control - #[register(offset = 0x6000, write_fn = on_write_kv_rd_seed_ctrl)] + #[register(offset = 0x0000_8000, write_fn = on_write_kv_rd_seed_ctrl)] kv_rd_seed_ctrl: ReadWriteRegister, /// Key Vault Read Status - #[register(offset = 0x6004)] + #[register(offset = 0x0000_8004)] kv_rd_seed_status: ReadOnlyRegister, + /// Error Global Intr register + #[register(offset = 0x0000_810c)] + error_global_intr: ReadOnlyRegister, + + /// Error Internal Intr register + #[register(offset = 0x0000_8114)] + error_internal_intr: ReadOnlyRegister, + private_key: [u8; ML_DSA87_PRIVKEY_SIZE], /// Timer @@ -167,7 +175,7 @@ pub struct MlDsa87 { op_seed_read_complete_action: Option, } -impl MlDsa87 { +impl Mldsa87 { /// NAME0 Register Value TODO update when known const NAME0_VAL: RvData = 0x73656370; //0x63737065; // secp @@ -195,6 +203,8 @@ impl MlDsa87 { signature: [0; ML_DSA87_SIGNATURE_SIZE / 4], kv_rd_seed_ctrl: ReadWriteRegister::new(0), kv_rd_seed_status: ReadOnlyRegister::new(0), + error_global_intr: ReadOnlyRegister::new(0), + error_internal_intr: ReadOnlyRegister::new(0), private_key: [0; ML_DSA87_PRIVKEY_SIZE], timer: Timer::new(clock), key_vault, @@ -214,7 +224,6 @@ impl MlDsa87 { fn zeroize(&mut self) { self.control.reg.set(0); - self.status.reg.set(0); self.seed = Default::default(); self.sign_rnd = Default::default(); self.msg = Default::default(); @@ -311,8 +320,8 @@ impl MlDsa87 { } fn sign(&mut self) { - let seed_bytes = &bytes_from_words_le(&self.seed); - let mut rng = StdRng::from_seed(*seed_bytes); + let sign_seed = &bytes_from_words_le(&self.sign_rnd); + let mut rng = StdRng::from_seed(*sign_seed); let secret_key = PrivateKey::try_from_bytes(self.private_key).unwrap(); @@ -327,8 +336,7 @@ impl MlDsa87 { sig[..SIG_LEN].copy_from_slice(&signature); sig }; - self.signature - .copy_from_slice(&words_from_bytes_le(&signature_extended)); + self.signature = words_from_bytes_le(&signature_extended); } fn verify(&mut self) { @@ -341,11 +349,14 @@ impl MlDsa87 { let signature = &bytes_from_words_le(&self.signature); - let result = public_key.verify(message, &signature[..SIG_LEN].try_into().unwrap(), &[]); + let success = public_key.verify(message, &signature[..SIG_LEN].try_into().unwrap(), &[]); - self.verify_res - .iter_mut() - .for_each(|e| *e = if result { 1 } else { 0 }); + if success { + self.verify_res + .copy_from_slice(&self.signature[..ML_DSA87_VERIFICATION_SIZE / 4]); + } else { + self.verify_res.fill(0); + } } fn op_complete(&mut self) { @@ -439,20 +450,13 @@ mod tests { const OFFSET_SEED: RvAddr = 0x58; const OFFSET_SIGN_RND: RvAddr = 0x78; const OFFSET_MSG: RvAddr = 0x98; - // const OFFSET_SK_IN: RvAddr = 0x1620; - const OFFSET_PK: RvAddr = 0x118; - const OFFSET_SIGNATURE: RvAddr = 0xb38; - const OFFSET_KV_RD_SEED_CONTROL: RvAddr = 0x6000; - const OFFSET_KV_RD_SEED_STATUS: RvAddr = 0x6004; + const OFFSET_PK: RvAddr = 0x1000; + const OFFSET_SIGNATURE: RvAddr = 0x2000; + const OFFSET_KV_RD_SEED_CONTROL: RvAddr = 0x8000; + const OFFSET_KV_RD_SEED_STATUS: RvAddr = 0x8004; include!("./test_data/ml_dsa87_test_data.rs"); - const VERIFICATION_SUCCES: [u8; 64] = [ - 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, - 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, - 0, 0, 0, 1, - ]; - fn make_word(idx: usize, arr: &[u8]) -> RvData { let mut res: RvData = 0; for i in 0..4 { @@ -466,7 +470,7 @@ mod tests { let clock = Clock::new(); let key_vault = KeyVault::new(); - let mut ml_dsa87 = MlDsa87::new(&clock, key_vault); + let mut ml_dsa87 = Mldsa87::new(&clock, key_vault); let name0 = ml_dsa87.read(RvSize::Word, OFFSET_NAME0).unwrap(); let name0 = String::from_utf8_lossy(&name0.to_be_bytes()).to_string(); @@ -482,7 +486,7 @@ mod tests { let clock = Clock::new(); let key_vault = KeyVault::new(); - let mut ml_dsa87 = MlDsa87::new(&clock, key_vault); + let mut ml_dsa87 = Mldsa87::new(&clock, key_vault); let version0 = ml_dsa87.read(RvSize::Word, OFFSET_VERSION0).unwrap(); let version0 = String::from_utf8_lossy(&version0.to_le_bytes()).to_string(); @@ -498,7 +502,7 @@ mod tests { let clock = Clock::new(); let key_vault = KeyVault::new(); - let mut ml_dsa87 = MlDsa87::new(&clock, key_vault); + let mut ml_dsa87 = Mldsa87::new(&clock, key_vault); assert_eq!(ml_dsa87.read(RvSize::Word, OFFSET_CONTROL).unwrap(), 0); } @@ -507,7 +511,7 @@ mod tests { let clock = Clock::new(); let key_vault = KeyVault::new(); - let mut ml_dsa87 = MlDsa87::new(&clock, key_vault); + let mut ml_dsa87 = Mldsa87::new(&clock, key_vault); assert_eq!(ml_dsa87.read(RvSize::Word, OFFSET_STATUS).unwrap(), 1); } @@ -516,25 +520,19 @@ mod tests { let clock = Clock::new(); let key_vault = KeyVault::new(); - let mut ml_dsa87 = MlDsa87::new(&clock, key_vault); + let mut ml_dsa87 = Mldsa87::new(&clock, key_vault); let mut seed = [0u8; 32]; seed.to_big_endian(); // Change DWORDs to big-endian. TODO is this needed? for i in (0..seed.len()).step_by(4) { - assert_eq!( - ml_dsa87 - .write(RvSize::Word, OFFSET_SEED + i as RvAddr, make_word(i, &seed)) - .ok(), - Some(()) - ); + ml_dsa87 + .write(RvSize::Word, OFFSET_SEED + i as RvAddr, make_word(i, &seed)) + .unwrap(); } - assert_eq!( - ml_dsa87 - .write(RvSize::Word, OFFSET_CONTROL, Control::CTRL::KEYGEN.into()) - .ok(), - Some(()) - ); + ml_dsa87 + .write(RvSize::Word, OFFSET_CONTROL, Control::CTRL::KEYGEN.into()) + .unwrap(); loop { let status = InMemoryRegister::::new( @@ -559,57 +557,45 @@ mod tests { let clock = Clock::new(); let key_vault = KeyVault::new(); - let mut ml_dsa87 = MlDsa87::new(&clock, key_vault); + let mut ml_dsa87 = Mldsa87::new(&clock, key_vault); let mut seed = [0u8; 32]; seed.to_big_endian(); // Change DWORDs to big-endian. TODO is this needed? for i in (0..seed.len()).step_by(4) { - assert_eq!( - ml_dsa87 - .write(RvSize::Word, OFFSET_SEED + i as RvAddr, make_word(i, &seed)) - .ok(), - Some(()) - ); + ml_dsa87 + .write(RvSize::Word, OFFSET_SEED + i as RvAddr, make_word(i, &seed)) + .unwrap(); } let mut msg = [0u8; 64]; msg.to_big_endian(); // Change DWORDs to big-endian. TODO is this necessary for i in (0..msg.len()).step_by(4) { - assert_eq!( - ml_dsa87 - .write(RvSize::Word, OFFSET_MSG + i as RvAddr, make_word(i, &msg)) - .ok(), - Some(()) - ); + ml_dsa87 + .write(RvSize::Word, OFFSET_MSG + i as RvAddr, make_word(i, &msg)) + .unwrap(); } let mut sign_rnd = SIGN_RND; sign_rnd.to_big_endian(); // Change DWORDs to big-endian. for i in (0..SIGN_RND.len()).step_by(4) { - assert_eq!( - ml_dsa87 - .write( - RvSize::Word, - OFFSET_SIGN_RND + i as RvAddr, - make_word(i, &sign_rnd) - ) - .ok(), - Some(()) - ); - } - - assert_eq!( ml_dsa87 .write( RvSize::Word, - OFFSET_CONTROL, - Control::CTRL::KEYGEN_AND_SIGN.into() + OFFSET_SIGN_RND + i as RvAddr, + make_word(i, &sign_rnd), ) - .ok(), - Some(()) - ); + .unwrap(); + } + + ml_dsa87 + .write( + RvSize::Word, + OFFSET_CONTROL, + Control::CTRL::KEYGEN_AND_SIGN.into(), + ) + .unwrap(); loop { let status = InMemoryRegister::::new( @@ -634,32 +620,26 @@ mod tests { let clock = Clock::new(); let key_vault = KeyVault::new(); - let mut ml_dsa87 = MlDsa87::new(&clock, key_vault); + let mut ml_dsa87 = Mldsa87::new(&clock, key_vault); let msg = [0u8; 64]; for i in (0..msg.len()).step_by(4) { - assert_eq!( - ml_dsa87 - .write(RvSize::Word, OFFSET_MSG + i as RvAddr, make_word(i, &msg)) - .ok(), - Some(()) - ); + ml_dsa87 + .write(RvSize::Word, OFFSET_MSG + i as RvAddr, make_word(i, &msg)) + .unwrap(); } let mut pub_key = PUB_KEY; pub_key.to_big_endian(); for i in (0..pub_key.len()).step_by(4) { - assert_eq!( - ml_dsa87 - .write( - RvSize::Word, - OFFSET_PK + i as RvAddr, - make_word(i, &pub_key) - ) - .ok(), - Some(()) - ); + ml_dsa87 + .write( + RvSize::Word, + OFFSET_PK + i as RvAddr, + make_word(i, &pub_key), + ) + .unwrap(); } // Good signature @@ -667,28 +647,22 @@ mod tests { signature.to_big_endian(); for i in (0..signature.len()).step_by(4) { - assert_eq!( - ml_dsa87 - .write( - RvSize::Word, - OFFSET_SIGNATURE + i as RvAddr, - make_word(i, &signature) - ) - .ok(), - Some(()) - ); - } - - assert_eq!( ml_dsa87 .write( RvSize::Word, - OFFSET_CONTROL, - Control::CTRL::VERIFYING.into() + OFFSET_SIGNATURE + i as RvAddr, + make_word(i, &signature), ) - .ok(), - Some(()) - ); + .unwrap(); + } + + ml_dsa87 + .write( + RvSize::Word, + OFFSET_CONTROL, + Control::CTRL::VERIFYING.into(), + ) + .unwrap(); loop { let status = InMemoryRegister::::new( @@ -705,35 +679,29 @@ mod tests { let mut result = bytes_from_words_le(&ml_dsa87.verify_res); result.to_little_endian(); - assert_eq!(&result, &VERIFICATION_SUCCES); + assert_eq!(result, &SIGNATURE[..ML_DSA87_VERIFICATION_SIZE]); // Bad signature let mut signature = [0; SIG_LEN + 1]; signature.to_big_endian(); for i in (0..signature.len()).step_by(4) { - assert_eq!( - ml_dsa87 - .write( - RvSize::Word, - OFFSET_SIGNATURE + i as RvAddr, - make_word(i, &signature) - ) - .ok(), - Some(()) - ); - } - - assert_eq!( ml_dsa87 .write( RvSize::Word, - OFFSET_CONTROL, - Control::CTRL::VERIFYING.into() + OFFSET_SIGNATURE + i as RvAddr, + make_word(i, &signature), ) - .ok(), - Some(()) - ); + .unwrap(); + } + + ml_dsa87 + .write( + RvSize::Word, + OFFSET_CONTROL, + Control::CTRL::VERIFYING.into(), + ) + .unwrap(); loop { let status = InMemoryRegister::::new( @@ -769,30 +737,24 @@ mod tests { .write_key(key_id, &seed, u32::from(key_usage)) .unwrap(); - let mut ml_dsa87 = MlDsa87::new(&clock, key_vault); + let mut ml_dsa87 = Mldsa87::new(&clock, key_vault); // We expect the output to match seed 0. Write a different seed first to make sure the Kv seed is used let mut seed = [0xABu8; 32]; seed.to_big_endian(); // Change DWORDs to big-endian. TODO is this needed? for i in (0..seed.len()).step_by(4) { - assert_eq!( - ml_dsa87 - .write(RvSize::Word, OFFSET_SEED + i as RvAddr, make_word(i, &seed)) - .ok(), - Some(()) - ); + ml_dsa87 + .write(RvSize::Word, OFFSET_SEED + i as RvAddr, make_word(i, &seed)) + .unwrap(); } // Instruct seed to be read from key-vault. let seed_ctrl = InMemoryRegister::::new(0); seed_ctrl.modify(KvRdSeedCtrl::READ_ENTRY.val(key_id) + KvRdSeedCtrl::READ_EN.val(1)); - assert_eq!( - ml_dsa87 - .write(RvSize::Word, OFFSET_KV_RD_SEED_CONTROL, seed_ctrl.get()) - .ok(), - Some(()) - ); + ml_dsa87 + .write(RvSize::Word, OFFSET_KV_RD_SEED_CONTROL, seed_ctrl.get()) + .unwrap(); // Wait for ml_dsa87 periph to retrieve the seed from key-vault. loop { @@ -812,12 +774,9 @@ mod tests { clock.increment_and_process_timer_actions(1, &mut ml_dsa87); } - assert_eq!( - ml_dsa87 - .write(RvSize::Word, OFFSET_CONTROL, Control::CTRL::KEYGEN.into()) - .ok(), - Some(()) - ); + ml_dsa87 + .write(RvSize::Word, OFFSET_CONTROL, Control::CTRL::KEYGEN.into()) + .unwrap(); loop { let status = InMemoryRegister::::new( diff --git a/sw-emulator/lib/periph/src/root_bus.rs b/sw-emulator/lib/periph/src/root_bus.rs index f410149d23..313ecf90a5 100644 --- a/sw-emulator/lib/periph/src/root_bus.rs +++ b/sw-emulator/lib/periph/src/root_bus.rs @@ -16,7 +16,7 @@ use crate::{ dma::Dma, helpers::words_from_bytes_be, iccm::Iccm, - ml_dsa87::MlDsa87, + ml_dsa87::Mldsa87, recovery::RecoveryRegisterInterface, soc_reg::{DebugManufService, SocRegistersExternal}, AsymEcc384, Csrng, Doe, EmuCtrl, HashSha256, HashSha512, HmacSha, KeyVault, MailboxExternal, @@ -270,11 +270,11 @@ pub struct CaliptraRootBus { #[peripheral(offset = 0x1002_8000, mask = 0x0000_7fff)] pub sha256: HashSha256, - #[peripheral(offset = 0x1003_0000, mask = 0x0000_7fff)] // TODO update when known - pub ml_dsa87: MlDsa87, + #[peripheral(offset = 0x1003_0000, mask = 0x0000_ffff)] + pub ml_dsa87: Mldsa87, - // We set I3C at 0x1003_8000 and EC is at 0x100 offset - #[peripheral(offset = 0x1003_8100, mask = 0x0000_7fff)] // TODO + // We set I3C at 0x1004_0000 and EC is at 0x100 offset + #[peripheral(offset = 0x1004_0100, mask = 0x0000_7fff)] // TODO pub recovery: RecoveryRegisterInterface, #[peripheral(offset = 0x4000_0000, mask = 0x0fff_ffff)] @@ -341,7 +341,7 @@ impl CaliptraRootBus { key_vault: key_vault.clone(), sha512, sha256: HashSha256::new(clock), - ml_dsa87: MlDsa87::new(clock, key_vault.clone()), + ml_dsa87: Mldsa87::new(clock, key_vault.clone()), recovery: RecoveryRegisterInterface::new(), iccm, dccm: Ram::new(vec![0; Self::DCCM_SIZE]), diff --git a/x509/src/cert_bldr.rs b/x509/src/cert_bldr.rs index a08e2d217c..f8388d0a5e 100644 --- a/x509/src/cert_bldr.rs +++ b/x509/src/cert_bldr.rs @@ -102,18 +102,18 @@ impl Signature<108> for Ecdsa384Signature { } /// Ml-Dsa87 Signature -pub struct MlDsa87Signature { +pub struct Mldsa87Signature { pub sig: [u8; 4627], } -impl Default for MlDsa87Signature { +impl Default for Mldsa87Signature { /// Returns the "default value" for a type. fn default() -> Self { Self { sig: [0; 4627] } } } -impl Signature<4635> for MlDsa87Signature { +impl Signature<4635> for Mldsa87Signature { fn to_der(&self, buf: &mut [u8; 4635]) -> Option { let ml_dsa_signature_len = der_uint_len(&self.sig)?; @@ -258,5 +258,5 @@ pub type Ecdsa384CertBuilder<'a> = CertBuilder<'a, Ecdsa384Signature, 108>; pub type Ecdsa384CsrBuilder<'a> = Ecdsa384CertBuilder<'a>; // Type alias for Ml-Dsa87 Certificate Builder -pub type MlDsa87CertBuilder<'a> = CertBuilder<'a, MlDsa87Signature, 4627>; +pub type MlDsa87CertBuilder<'a> = CertBuilder<'a, Mldsa87Signature, 4627>; pub type MlDsa87CsrBuilder<'a> = MlDsa87CertBuilder<'a>; diff --git a/x509/src/lib.rs b/x509/src/lib.rs index cf998c97bd..53a8f27a58 100644 --- a/x509/src/lib.rs +++ b/x509/src/lib.rs @@ -24,7 +24,7 @@ mod test_util; pub use cert_bldr::{ Ecdsa384CertBuilder, Ecdsa384CsrBuilder, Ecdsa384Signature, MlDsa87CertBuilder, - MlDsa87CsrBuilder, MlDsa87Signature, + MlDsa87CsrBuilder, Mldsa87Signature, }; pub use der_helper::{der_encode_len, der_encode_uint, der_uint_len}; pub use fmc_alias_cert::{FmcAliasCertTbs, FmcAliasCertTbsParams}; From 98df8cbd3b3cf7d2c5c0bc419301bf73e1abc564 Mon Sep 17 00:00:00 2001 From: Vishal Mhatre <38512878+mhatrevi@users.noreply.github.com> Date: Wed, 20 Nov 2024 09:59:02 -0800 Subject: [PATCH 24/51] [feat] ROM LDEVID DICE changes for MLDSA support (#1798) --- rom/dev/src/flow/cold_reset/crypto.rs | 10 +- rom/dev/src/flow/cold_reset/dice.rs | 21 +++- rom/dev/src/flow/cold_reset/fmc_alias.rs | 20 ++-- rom/dev/src/flow/cold_reset/idev_id.rs | 30 +++-- rom/dev/src/flow/cold_reset/ldev_id.rs | 111 +++++++++++------- rom/dev/src/flow/cold_reset/mod.rs | 9 +- rom/dev/src/flow/cold_reset/x509.rs | 74 +++++++++--- test/src/derive.rs | 8 +- .../fmc_alias_cert_redacted.der | Bin 874 -> 874 bytes .../fmc_alias_cert_redacted.txt | 4 +- .../smoke_testdata/ldevid_cert.der | Bin 673 -> 674 bytes .../smoke_testdata/ldevid_cert.txt | 32 ++--- 12 files changed, 203 insertions(+), 116 deletions(-) diff --git a/rom/dev/src/flow/cold_reset/crypto.rs b/rom/dev/src/flow/cold_reset/crypto.rs index 9a816fd3e2..04b4079e78 100644 --- a/rom/dev/src/flow/cold_reset/crypto.rs +++ b/rom/dev/src/flow/cold_reset/crypto.rs @@ -37,7 +37,7 @@ impl Ecdsa384SignatureAdapter for Ecc384Signature { } } -/// DICE Layer Key Pair +/// DICE Layer ECC Key Pair #[derive(Debug, Zeroize)] pub struct Ecc384KeyPair { /// Private Key KV Slot Id @@ -48,7 +48,7 @@ pub struct Ecc384KeyPair { pub pub_key: Ecc384PubKey, } -/// DICE Layer Key Pair +/// DICE Layer MLDSA Key Pair #[derive(Debug, Zeroize)] pub struct MlDsaKeyPair { /// Key Pair Generation KV Slot Id @@ -59,6 +59,12 @@ pub struct MlDsaKeyPair { pub pub_key: Mldsa87PubKey, } +#[derive(Debug)] +pub enum PubKey<'a> { + Ecc(&'a Ecc384PubKey), + Mldsa(&'a Mldsa87PubKey), +} + pub enum Crypto {} impl Crypto { diff --git a/rom/dev/src/flow/cold_reset/dice.rs b/rom/dev/src/flow/cold_reset/dice.rs index f0a234b740..92b5a19c56 100644 --- a/rom/dev/src/flow/cold_reset/dice.rs +++ b/rom/dev/src/flow/cold_reset/dice.rs @@ -19,14 +19,23 @@ use zeroize::Zeroize; /// DICE Layer Input #[derive(Debug)] pub struct DiceInput<'a> { - /// Authority Key Pair - pub auth_key_pair: &'a Ecc384KeyPair, + /// ECC Authority Key Pair + pub ecc_auth_key_pair: &'a Ecc384KeyPair, - /// Authority Serial Number - pub auth_sn: &'a [u8; 64], + /// ECC Authority Serial Number + pub ecc_auth_sn: &'a [u8; 64], - /// Authority Key Identifier - pub auth_key_id: &'a [u8; 20], + /// ECC Authority Key Identifier + pub ecc_auth_key_id: &'a [u8; 20], + + /// MLDSA Authority Key Pair + pub mldsa_auth_key_pair: &'a MlDsaKeyPair, + + /// MLDSA Authority Serial Number + pub mldsa_auth_sn: &'a [u8; 64], + + /// MLDSA Authority Key Identifier + pub mldsa_auth_key_id: &'a [u8; 20], } /// DICE Layer Output diff --git a/rom/dev/src/flow/cold_reset/fmc_alias.rs b/rom/dev/src/flow/cold_reset/fmc_alias.rs index 94f1ba18ca..e6a02bdeb7 100644 --- a/rom/dev/src/flow/cold_reset/fmc_alias.rs +++ b/rom/dev/src/flow/cold_reset/fmc_alias.rs @@ -18,7 +18,7 @@ use super::dice::{DiceInput, DiceOutput}; use super::fw_processor::FwProcInfo; use super::x509::X509; use crate::cprintln; -use crate::flow::cold_reset::crypto::MlDsaKeyPair; +use crate::flow::cold_reset::crypto::{MlDsaKeyPair, PubKey}; use crate::flow::cold_reset::{copy_tbs, TbsType}; use crate::print::HexBytes; use crate::rom_env::RomEnv; @@ -50,8 +50,8 @@ impl FmcAliasLayer { cprintln!("[afmc] CDI.KEYID = {}", KEY_ID_ROM_FMC_CDI as u8); cprintln!("[afmc] SUBJECT.KEYID = {}", KEY_ID_FMC_ECDSA_PRIV_KEY as u8); cprintln!( - "[afmc] AUTHORITY.KEYID = {}", - input.auth_key_pair.priv_key as u8 + "[afmc] ECC AUTHORITY.KEYID = {}", + input.ecc_auth_key_pair.priv_key as u8 ); // We use the value of PCR0 as the measurement for deriving the CDI. @@ -70,10 +70,10 @@ impl FmcAliasLayer { // // This information will be used by next DICE Layer while generating // certificates - let ecc_subj_sn = X509::subj_sn(env, &ecc_key_pair.pub_key)?; + let ecc_subj_sn = X509::subj_sn(env, &PubKey::Ecc(&ecc_key_pair.pub_key))?; report_boot_status(FmcAliasSubjIdSnGenerationComplete.into()); - let ecc_subj_key_id = X509::subj_key_id(env, &ecc_key_pair.pub_key)?; + let ecc_subj_key_id = X509::subj_key_id(env, &PubKey::Ecc(&ecc_key_pair.pub_key))?; report_boot_status(FmcAliasSubjKeyIdGenerationComplete.into()); // Generate the output for next layer @@ -158,8 +158,8 @@ impl FmcAliasLayer { output: &DiceOutput, fw_proc_info: &FwProcInfo, ) -> CaliptraResult<()> { - let auth_priv_key = input.auth_key_pair.priv_key; - let auth_pub_key = &input.auth_key_pair.pub_key; + let auth_priv_key = input.ecc_auth_key_pair.priv_key; + let auth_pub_key = &input.ecc_auth_key_pair.pub_key; let pub_key = &output.ecc_subj_key_pair.pub_key; let flags = Self::make_flags(env.soc_ifc.lifecycle(), env.soc_ifc.debug_locked()); @@ -189,9 +189,9 @@ impl FmcAliasLayer { ueid: &X509::ueid(env)?, subject_sn: &output.ecc_subj_sn, subject_key_id: &output.ecc_subj_key_id, - issuer_sn: input.auth_sn, - authority_key_id: input.auth_key_id, - serial_number: &X509::cert_sn(env, pub_key)?, + issuer_sn: input.ecc_auth_sn, + authority_key_id: input.ecc_auth_key_id, + serial_number: &X509::ecc_cert_sn(env, pub_key)?, public_key: &pub_key.to_der(), tcb_info_fmc_tci: &(&env.data_vault.fmc_tci()).into(), tcb_info_device_info_hash: &fuse_info_digest.into(), diff --git a/rom/dev/src/flow/cold_reset/idev_id.rs b/rom/dev/src/flow/cold_reset/idev_id.rs index 6397edb54a..2168d19d57 100644 --- a/rom/dev/src/flow/cold_reset/idev_id.rs +++ b/rom/dev/src/flow/cold_reset/idev_id.rs @@ -88,22 +88,23 @@ impl InitDevIdLayer { // Generate the Subject Serial Number and Subject Key Identifier for ECC. // This information will be used by next DICE Layer while generating // certificates - let ecc_subj_sn = X509::subj_sn(env, &ecc_key_pair.pub_key)?; + let ecc_subj_sn = X509::subj_sn(env, &PubKey::Ecc(&ecc_key_pair.pub_key))?; + let mldsa_subj_sn = X509::subj_sn(env, &PubKey::Mldsa(&mldsa_key_pair.pub_key))?; report_boot_status(IDevIdSubjIdSnGenerationComplete.into()); - let ecc_subj_key_id = X509::idev_subj_key_id(env, &ecc_key_pair.pub_key)?; + let ecc_subj_key_id = X509::idev_subj_key_id(env, &PubKey::Ecc(&ecc_key_pair.pub_key))?; + let mldsa_subj_key_id = + X509::idev_subj_key_id(env, &PubKey::Mldsa(&mldsa_key_pair.pub_key))?; report_boot_status(IDevIdSubjKeyIdGenerationComplete.into()); - // [TODO] Generate the Subject Serial Number and Subject Key Identifier for MLDSA. - // Generate the output for next layer let output = DiceOutput { ecc_subj_key_pair: ecc_key_pair, ecc_subj_sn, ecc_subj_key_id, - mldsa_subj_key_id: [0; 20], + mldsa_subj_key_id, mldsa_subj_key_pair: mldsa_key_pair, - mldsa_subj_sn: [0; 64], + mldsa_subj_sn, }; // Generate the Initial DevID Certificate Signing Request (CSR) @@ -193,7 +194,7 @@ impl InitDevIdLayer { /// /// * `env` - ROM Environment /// * `cdi` - Composite Device Identity - /// * `ecdsa_priv_key` - Key slot to store the ECC private key into + /// * `ecc_priv_key` - Key slot to store the ECC private key into /// * `mldsa_keypair_seed` - Key slot to store the MLDSA key pair seed /// /// # Returns @@ -203,10 +204,10 @@ impl InitDevIdLayer { fn derive_key_pair( env: &mut RomEnv, cdi: KeyId, - ecdsa_priv_key: KeyId, + ecc_priv_key: KeyId, mldsa_keypair_seed: KeyId, ) -> CaliptraResult<(Ecc384KeyPair, MlDsaKeyPair)> { - let result = Crypto::ecc384_key_gen(env, cdi, b"idevid_ecc_key", ecdsa_priv_key); + let result = Crypto::ecc384_key_gen(env, cdi, b"idevid_ecc_key", ecc_priv_key); if cfi_launder(result.is_ok()) { cfi_assert!(result.is_ok()); } else { @@ -215,11 +216,16 @@ impl InitDevIdLayer { let ecc_keypair = result?; // Derive the MLDSA Key Pair. - let mldsa_key_pair = - Crypto::mldsa_key_gen(env, cdi, b"idevid_mldsa_key", mldsa_keypair_seed)?; + let result = Crypto::mldsa_key_gen(env, cdi, b"idevid_mldsa_key", mldsa_keypair_seed); + if cfi_launder(result.is_ok()) { + cfi_assert!(result.is_ok()); + } else { + cfi_assert!(result.is_err()); + } + let mldsa_keypair = result?; report_boot_status(IDevIdKeyPairDerivationComplete.into()); - Ok((ecc_keypair, mldsa_key_pair)) + Ok((ecc_keypair, mldsa_keypair)) } /// Generate Local Device ID CSR diff --git a/rom/dev/src/flow/cold_reset/ldev_id.rs b/rom/dev/src/flow/cold_reset/ldev_id.rs index f294185be1..8f2c1f35db 100644 --- a/rom/dev/src/flow/cold_reset/ldev_id.rs +++ b/rom/dev/src/flow/cold_reset/ldev_id.rs @@ -50,12 +50,14 @@ impl LocalDevIdLayer { cprintln!("[ldev] ++"); cprintln!("[ldev] CDI.KEYID = {}", KEY_ID_ROM_FMC_CDI as u8); cprintln!( - "[ldev] SUBJECT.KEYID = {}", - KEY_ID_LDEVID_ECDSA_PRIV_KEY as u8 + "[ldev] ECC SUBJECT.KEYID = {}, MLDSA SUBJECT.KEYID = {}", + KEY_ID_LDEVID_ECDSA_PRIV_KEY as u8, + KEY_ID_LDEVID_MLDSA_KEYPAIR_SEED as u8, ); cprintln!( - "[ldev] AUTHORITY.KEYID = {}", - input.auth_key_pair.priv_key as u8 + "[ldev] ECC AUTHORITY.KEYID = {}, MLDSA AUTHORITY.KEYID = {}", + input.ecc_auth_key_pair.priv_key as u8, + input.mldsa_auth_key_pair.key_pair_seed as u8, ); cprintln!("[ldev] FE.KEYID = {}", KEY_ID_FE as u8); @@ -65,31 +67,34 @@ impl LocalDevIdLayer { // This is the decrypted Field Entropy Self::derive_cdi(env, KEY_ID_FE, KEY_ID_ROM_FMC_CDI)?; - // Derive DICE Key Pair from CDI - let key_pair = - Self::derive_key_pair(env, KEY_ID_ROM_FMC_CDI, KEY_ID_LDEVID_ECDSA_PRIV_KEY)?; + // Derive DICE ECC and MLDSA Key Pairs from CDI + let (ecc_key_pair, mldsa_key_pair) = Self::derive_key_pair( + env, + KEY_ID_ROM_FMC_CDI, + KEY_ID_LDEVID_ECDSA_PRIV_KEY, + KEY_ID_LDEVID_MLDSA_KEYPAIR_SEED, + )?; // Generate the Subject Serial Number and Subject Key Identifier. // // This information will be used by the next DICE Layer while generating // certificates - let ecc_subj_sn = X509::subj_sn(env, &key_pair.pub_key)?; + let ecc_subj_sn = X509::subj_sn(env, &PubKey::Ecc(&ecc_key_pair.pub_key))?; + let mldsa_subj_sn = X509::subj_sn(env, &PubKey::Mldsa(&mldsa_key_pair.pub_key))?; report_boot_status(LDevIdSubjIdSnGenerationComplete.into()); - let ecc_subj_key_id = X509::subj_key_id(env, &key_pair.pub_key)?; + let ecc_subj_key_id = X509::subj_key_id(env, &PubKey::Ecc(&ecc_key_pair.pub_key))?; + let mldsa_subj_key_id = X509::subj_key_id(env, &PubKey::Mldsa(&mldsa_key_pair.pub_key))?; report_boot_status(LDevIdSubjKeyIdGenerationComplete.into()); // Generate the output for next layer let output = DiceOutput { - ecc_subj_key_pair: key_pair, + ecc_subj_key_pair: ecc_key_pair, ecc_subj_sn, ecc_subj_key_id, - mldsa_subj_key_id: [0; 20], - mldsa_subj_key_pair: MlDsaKeyPair { - key_pair_seed: KEY_ID_LDEVID_MLDSA_KEYPAIR_SEED, - pub_key: Default::default(), - }, - mldsa_subj_sn: [0; 64], + mldsa_subj_key_pair: mldsa_key_pair, + mldsa_subj_sn, + mldsa_subj_key_id, }; // Generate Local Device ID Certificate @@ -125,25 +130,38 @@ impl LocalDevIdLayer { /// /// * `env` - ROM Environment /// * `cdi` - Composite Device Identity - /// * `priv_key` - Key slot to store the private key into + /// * `ecc_priv_key` - Key slot to store the ECC private key into + /// * `mldsa_keypair_seed` - Key slot to store the MLDSA key pair seed /// /// # Returns /// - /// * `Ecc384KeyPair` - Derive DICE Layer Key Pair + /// * `(Ecc384KeyPair, MlDsaKeyPair)` - DICE Layer ECC and MLDSA Key Pairs #[cfg_attr(not(feature = "no-cfi"), cfi_impl_fn)] fn derive_key_pair( env: &mut RomEnv, cdi: KeyId, - priv_key: KeyId, - ) -> CaliptraResult { - let result = Crypto::ecc384_key_gen(env, cdi, b"ldevid_keygen", priv_key); + ecc_priv_key: KeyId, + mldsa_keypair_seed: KeyId, + ) -> CaliptraResult<(Ecc384KeyPair, MlDsaKeyPair)> { + let result = Crypto::ecc384_key_gen(env, cdi, b"ldevid_ecc_key", ecc_priv_key); if cfi_launder(result.is_ok()) { cfi_assert!(result.is_ok()); - report_boot_status(LDevIdKeyPairDerivationComplete.into()); } else { cfi_assert!(result.is_err()); } - result + let ecc_keypair = result?; + + // Derive the MLDSA Key Pair. + let result = Crypto::mldsa_key_gen(env, cdi, b"ldevid_mldsa_key", mldsa_keypair_seed); + if cfi_launder(result.is_ok()) { + cfi_assert!(result.is_ok()); + } else { + cfi_assert!(result.is_err()); + } + let mldsa_keypair = result?; + + report_boot_status(LDevIdKeyPairDerivationComplete.into()); + Ok((ecc_keypair, mldsa_keypair)) } /// Generate Local Device ID Certificate Signature @@ -158,45 +176,50 @@ impl LocalDevIdLayer { input: &DiceInput, output: &DiceOutput, ) -> CaliptraResult<()> { - let auth_priv_key = input.auth_key_pair.priv_key; - let auth_pub_key = &input.auth_key_pair.pub_key; - let pub_key = &output.ecc_subj_key_pair.pub_key; + let ecc_auth_priv_key = input.ecc_auth_key_pair.priv_key; + let ecc_auth_pub_key = &input.ecc_auth_key_pair.pub_key; + let ecc_pub_key = &output.ecc_subj_key_pair.pub_key; - let serial_number = X509::cert_sn(env, pub_key); - let serial_number = okref(&serial_number)?; + let ecc_serial_number = X509::ecc_cert_sn(env, ecc_pub_key); + let ecc_serial_number = okref(&ecc_serial_number)?; // CSR `To Be Signed` Parameters - let params = LocalDevIdCertTbsParams { + let ecc_tbs_params = LocalDevIdCertTbsParams { ueid: &X509::ueid(env)?, subject_sn: &output.ecc_subj_sn, subject_key_id: &output.ecc_subj_key_id, - issuer_sn: input.auth_sn, - authority_key_id: input.auth_key_id, - serial_number, - public_key: &pub_key.to_der(), + issuer_sn: input.ecc_auth_sn, + authority_key_id: input.ecc_auth_key_id, + serial_number: ecc_serial_number, + public_key: &ecc_pub_key.to_der(), not_before: &NotBefore::default().value, not_after: &NotAfter::default().value, }; - // Generate the `To Be Signed` portion of the CSR - let tbs = LocalDevIdCertTbs::new(¶ms); + // Generate the ECC `To Be Signed` portion of the CSR + let ecc_tbs = LocalDevIdCertTbs::new(&ecc_tbs_params); // Sign the `To Be Signed` portion cprintln!( - "[ldev] Signing Cert w/ AUTHORITY.KEYID = {}", - auth_priv_key as u8 + "[ldev] Signing Cert with ECC AUTHORITY.KEYID = {}", + ecc_auth_priv_key as u8 + ); + let mut sig = Crypto::ecdsa384_sign_and_verify( + env, + ecc_auth_priv_key, + ecc_auth_pub_key, + ecc_tbs.tbs(), ); - let mut sig = Crypto::ecdsa384_sign_and_verify(env, auth_priv_key, auth_pub_key, tbs.tbs()); let sig = okmutref(&mut sig)?; // Clear the authority private key - env.key_vault.erase_key(auth_priv_key).map_err(|err| { + env.key_vault.erase_key(ecc_auth_priv_key).map_err(|err| { sig.zeroize(); err })?; - let _pub_x: [u8; 48] = (&pub_key.x).into(); - let _pub_y: [u8; 48] = (&pub_key.y).into(); + let _pub_x: [u8; 48] = (&ecc_pub_key.x).into(); + let _pub_y: [u8; 48] = (&ecc_pub_key.y).into(); cprintln!("[ldev] PUB.X = {}", HexBytes(&_pub_x)); cprintln!("[ldev] PUB.Y = {}", HexBytes(&_pub_y)); @@ -212,10 +235,12 @@ impl LocalDevIdLayer { // Lock the Local Device ID public key in data vault until // cold reset - env.data_vault.set_ldev_dice_pub_key(pub_key); + env.data_vault.set_ldev_dice_pub_key(ecc_pub_key); // Copy TBS to DCCM. - copy_tbs(tbs.tbs(), TbsType::LdevidTbs, env)?; + copy_tbs(ecc_tbs.tbs(), TbsType::LdevidTbs, env)?; + + // [CAP2][TODO] Generate the MLDSA TBS report_boot_status(LDevIdCertSigGenerationComplete.into()); Ok(()) diff --git a/rom/dev/src/flow/cold_reset/mod.rs b/rom/dev/src/flow/cold_reset/mod.rs index 9beee585da..0b07a8d003 100644 --- a/rom/dev/src/flow/cold_reset/mod.rs +++ b/rom/dev/src/flow/cold_reset/mod.rs @@ -130,8 +130,11 @@ pub fn copy_tbs(tbs: &[u8], tbs_type: TbsType, env: &mut RomEnv) -> CaliptraResu fn dice_input_from_output(dice_output: &DiceOutput) -> DiceInput { DiceInput { - auth_key_pair: &dice_output.ecc_subj_key_pair, - auth_sn: &dice_output.ecc_subj_sn, - auth_key_id: &dice_output.ecc_subj_key_id, + ecc_auth_key_pair: &dice_output.ecc_subj_key_pair, + ecc_auth_sn: &dice_output.ecc_subj_sn, + ecc_auth_key_id: &dice_output.ecc_subj_key_id, + mldsa_auth_key_pair: &dice_output.mldsa_subj_key_pair, + mldsa_auth_sn: &dice_output.mldsa_subj_sn, + mldsa_auth_key_id: &dice_output.mldsa_subj_key_id, } } diff --git a/rom/dev/src/flow/cold_reset/x509.rs b/rom/dev/src/flow/cold_reset/x509.rs index e62dadfdda..c48a63429b 100644 --- a/rom/dev/src/flow/cold_reset/x509.rs +++ b/rom/dev/src/flow/cold_reset/x509.rs @@ -11,10 +11,13 @@ Abstract: File contains X509 Certificate & CSR related utility functions --*/ -use super::crypto::Crypto; +use super::crypto::{Crypto, PubKey}; use crate::cprintln; use crate::rom_env::RomEnv; use caliptra_drivers::*; +use core::mem::size_of; +use core::usize; +use zerocopy::AsBytes; /// X509 API pub enum X509 {} @@ -34,19 +37,51 @@ impl X509 { Ok(ueid) } - /// Get X509 Subject Serial Number + fn get_pubkey_bytes(pub_key: &PubKey, pub_key_bytes: &mut [u8]) -> usize { + fn copy_and_swap_endianess(src: &[u8], dst: &mut [u8]) { + for i in (0..src.len()).step_by(4) { + if i + 3 < src.len() && i + 3 < dst.len() { + dst[i] = src[i + 3]; + dst[i + 1] = src[i + 2]; + dst[i + 2] = src[i + 1]; + dst[i + 3] = src[i]; + } + } + } + + match pub_key { + PubKey::Ecc(pub_key) => { + let ecc_pubkey_der = pub_key.to_der(); + pub_key_bytes[..ecc_pubkey_der.len()].copy_from_slice(&ecc_pubkey_der); + ecc_pubkey_der.len() + } + PubKey::Mldsa(pub_key) => { + // pub_key is in Caliptra Hw format (big-endian DWORDs). Convert it to little-endian DWORDs. + copy_and_swap_endianess(pub_key.0.as_bytes(), pub_key_bytes); + pub_key_bytes.len() + } + } + } + + fn pub_key_digest(env: &mut RomEnv, pub_key: &PubKey) -> CaliptraResult { + // Define an array large enough to hold the largest public key. + let mut pub_key_bytes: [u8; size_of::()] = [0; size_of::()]; + let pub_key_size = Self::get_pubkey_bytes(pub_key, &mut pub_key_bytes); + Crypto::sha256_digest(env, &pub_key_bytes[..pub_key_size]) + } + + /// Get X509 Subject Serial Number from public key /// /// # Arguments /// /// * `env` - ROM Environment - /// * `pub_key` - Public Key + /// * `pub_key` - ECC or MLDSA Public Key /// /// # Returns /// /// `[u8; 64]` - X509 Subject Identifier serial number - pub fn subj_sn(env: &mut RomEnv, pub_key: &Ecc384PubKey) -> CaliptraResult<[u8; 64]> { - let data = pub_key.to_der(); - let digest = Crypto::sha256_digest(env, &data); + pub fn subj_sn(env: &mut RomEnv, pub_key: &PubKey) -> CaliptraResult<[u8; 64]> { + let digest = Self::pub_key_digest(env, pub_key); let digest = okref(&digest)?; Ok(Self::hex(&digest.into())) } @@ -56,29 +91,33 @@ impl X509 { /// # Arguments /// /// * `env` - ROM Environment - /// * `pub_key` - Public Key + /// * `pub_key` - ECC or MLDSA Public Key /// /// # Returns /// /// `[u8; 20]` - X509 Subject Key Identifier - pub fn idev_subj_key_id(env: &mut RomEnv, pub_key: &Ecc384PubKey) -> CaliptraResult<[u8; 20]> { - let data = pub_key.to_der(); + pub fn idev_subj_key_id(env: &mut RomEnv, pub_key: &PubKey) -> CaliptraResult<[u8; 20]> { + let mut pub_key_bytes: [u8; size_of::()] = [0; size_of::()]; + let pub_key_size = Self::get_pubkey_bytes(pub_key, &mut pub_key_bytes); + let data: &[u8] = &pub_key_bytes[..pub_key_size]; + + // [CAP2][TODO] Get the hash algorithm if the key is MLDSA. let digest: [u8; 20] = match env.soc_ifc.fuse_bank().idev_id_x509_key_id_algo() { X509KeyIdAlgo::Sha1 => { cprintln!("[idev] Sha1 KeyId Algorithm"); - let digest = Crypto::sha1_digest(env, &data); + let digest = Crypto::sha1_digest(env, data); okref(&digest)?.into() } X509KeyIdAlgo::Sha256 => { cprintln!("[idev] Sha256 KeyId Algorithm"); - let digest = Crypto::sha256_digest(env, &data); + let digest = Crypto::sha256_digest(env, data); let digest: [u8; 32] = okref(&digest)?.into(); digest[..20].try_into().unwrap() } X509KeyIdAlgo::Sha384 => { cprintln!("[idev] Sha384 KeyId Algorithm"); - let digest = Crypto::sha384_digest(env, &data); + let digest = Crypto::sha384_digest(env, data); let digest: [u8; 48] = okref(&digest)?.into(); digest[..20].try_into().unwrap() } @@ -101,24 +140,23 @@ impl X509 { /// # Returns /// /// `[u8; 20]` - X509 Subject Key Identifier - pub fn subj_key_id(env: &mut RomEnv, pub_key: &Ecc384PubKey) -> CaliptraResult<[u8; 20]> { - let data = pub_key.to_der(); - let digest = Crypto::sha256_digest(env, &data); + pub fn subj_key_id(env: &mut RomEnv, pub_key: &PubKey) -> CaliptraResult<[u8; 20]> { + let digest = Self::pub_key_digest(env, pub_key); let digest: [u8; 32] = okref(&digest)?.into(); Ok(digest[..20].try_into().unwrap()) } - /// Get Cert Serial Number + /// Get Serial Number for ECC certificate. /// /// # Arguments /// /// * `env` - ROM Environment - /// * `pub_key` - Public Key + /// * `pub_key` - ECC Public Key /// /// # Returns /// /// `[u8; 20]` - X509 Serial Number - pub fn cert_sn(env: &mut RomEnv, pub_key: &Ecc384PubKey) -> CaliptraResult<[u8; 20]> { + pub fn ecc_cert_sn(env: &mut RomEnv, pub_key: &Ecc384PubKey) -> CaliptraResult<[u8; 20]> { let data = pub_key.to_der(); let digest = Crypto::sha256_digest(env, &data); let mut digest: [u8; 32] = okref(&digest)?.into(); diff --git a/test/src/derive.rs b/test/src/derive.rs index b7b28bccc0..946007db33 100644 --- a/test/src/derive.rs +++ b/test/src/derive.rs @@ -242,7 +242,7 @@ impl LDevId { let mut priv_key_seed: [u32; 12] = transmute!(hmac384_kdf( swap_word_bytes(&cdi).as_bytes(), - b"ldevid_keygen", + b"ldevid_ecc_key", None )); swap_word_bytes_inplace(&mut priv_key_seed); @@ -285,9 +285,9 @@ fn test_ldevid() { 0x6f1271bc, 0xf35c0619, 0x0856f1e3, 0x7d560cf2, 0xaa227256, ], priv_key: [ - 0xd6cb583, 0x3a6de03c, 0x2cbf7476, 0x5cfd3cf0, 0x36871eae, 0xd4144aea, 0xce3cec09, - 0x8168274, 0xb97d7cfe, 0x5b106642, 0x6c8d2cc2, 0xf2edcb8b, - ], + 0xce7579e1, 0x37fe98bd, 0x54dd77e6, 0xc20331d, 0xe0ae1006, 0x64577cf9, 0xd04306f5, + 0x434d4dde, 0x43974611, 0x1ceb42a1, 0x2b6d1959, 0xbebeb390, + ] } ); } diff --git a/test/tests/caliptra_integration_tests/smoke_testdata/fmc_alias_cert_redacted.der b/test/tests/caliptra_integration_tests/smoke_testdata/fmc_alias_cert_redacted.der index 42eec06ea6733956bd1ca03be62f6337154e9ee8..ce0d4844c5e0260128b759ba3cd5baa1e55be5b5 100644 GIT binary patch delta 99 zcmV-p0G$8o2I>ZoT0ccWHZeFvLPSDEMMW?-I6*TvIX6Q!MKeN0LpC@yHA6HpHZVd% zGcZFmK{PcpGc`CdMmaP?HA6T;G(s~sFtM3P0u<_DjlI6^2Z}eB#pAxlgAW8rL delta 99 zcmaFG_KIynl)aImtE;P$x!ra-_$k4*V z)YQ_=#K6tX($w7C+||Os(8R)G<4g}G5yf}!XZa*v+4=aU_ba!b3$>1Q)I6H}m8lc} Dg$W^* diff --git a/test/tests/caliptra_integration_tests/smoke_testdata/fmc_alias_cert_redacted.txt b/test/tests/caliptra_integration_tests/smoke_testdata/fmc_alias_cert_redacted.txt index 4aede310cc..50bdec9b40 100644 --- a/test/tests/caliptra_integration_tests/smoke_testdata/fmc_alias_cert_redacted.txt +++ b/test/tests/caliptra_integration_tests/smoke_testdata/fmc_alias_cert_redacted.txt @@ -4,7 +4,7 @@ Certificate: Serial Number: 44:44:44:44:44:44:44:44:44:44:44:44:44:44:44:44:44:44:44:44 Signature Algorithm: ecdsa-with-SHA384 - Issuer: CN=Caliptra 1.0 LDevID/serialNumber=21EEEF9A4C61D4B9E3D94BEA46F9A12AC6887CE2188559F40FF95777E8014889 + Issuer: CN=Caliptra 1.0 LDevID/serialNumber=EA618DBDBEEE078A3797C5E3BEC6855C4160BC30C4A4533581F94C5C8B4B3709 Validity Not Before: Jan 1 00:00:00 2023 GMT Not After : Dec 31 23:59:59 9999 GMT @@ -34,7 +34,7 @@ Certificate: X509v3 Subject Key Identifier: 44:44:44:44:44:44:44:44:44:44:44:44:44:44:44:44:44:44:44:44 X509v3 Authority Key Identifier: - 21:EE:EF:9A:4C:61:D4:B9:E3:D9:4B:EA:46:F9:A1:2A:C6:88:7C:E2 + EA:61:8D:BD:BE:EE:07:8A:37:97:C5:E3:BE:C6:85:5C:41:60:BC:30 Signature Algorithm: ecdsa-with-SHA384 Signature Value: 30:64:02:30:44:44:44:44:44:44:44:44:44:44:44:44:44:44: diff --git a/test/tests/caliptra_integration_tests/smoke_testdata/ldevid_cert.der b/test/tests/caliptra_integration_tests/smoke_testdata/ldevid_cert.der index 1d64c96b20617730d1313adb2ec41961c419bfc2..dce4f7d88d22834c7a8d0172c1df5c1b92f8c27e 100644 GIT binary patch delta 364 zcmZ3;x`22^efbj)5l;jr^QO9zgsu7`6bq(v4zUe?$ZIAi{yIllJRru!!=-@jXx z^J#kgDHm1qzXeV#N0+zkZeMg*aa*DVw~J#_`{ad;VIr@v_-ZmYlU`;9gFz~jLBRR< zTKc#D8YlDm-E+Q$%qaM=dDavkCPRjs zuIJN#Se*|sxMIt{bnC77vWFgb8kewI(-m7R}odcSh}xlrp^N6n*&%E#)B3|(Da z-7FnVoXrefOq?uTja@8FoLn7E%z%Q1Mvl&A78d5tu11Cy7N(|_ZYBn9ZkDFz=H{*z z28JdU7M2EO1_EsCT5TTZY?&C@ShX8j7?hZk7+6|#7}m3{IrCa1&`;NV!{JqnBt8a& zf4s9pWs%4X?h?0-1sz>X(|^@k9)0-g#wnqRx0U8-yl$)5^MavChh3@PG3&`(#lF}@ zpDwOgRC{pN{j{!y_T+_(VIqoHd^MSyNiQRv!61dn!2jlk zEPcCQEWhI4ryV+UV_n1<%cWcj)s@>zc5b=)hS?xSG{ks$@x6M#3mh_wXLGJ(GRRZy zzf^qs+2RGqU1yx!dwv)9Rf9tpxObkbb@Wb7TE#l4ZI^5Q#|8$2tj}E Date: Wed, 20 Nov 2024 13:59:23 -0800 Subject: [PATCH 25/51] [feat] ROM ALIAS FMC DICE changes for MLDSA support (#1799) --- rom/dev/src/flow/cold_reset/fmc_alias.rs | 61 ++++++++++++++++-------- test/src/derive.rs | 16 +++---- 2 files changed, 50 insertions(+), 27 deletions(-) diff --git a/rom/dev/src/flow/cold_reset/fmc_alias.rs b/rom/dev/src/flow/cold_reset/fmc_alias.rs index e6a02bdeb7..b466270ec9 100644 --- a/rom/dev/src/flow/cold_reset/fmc_alias.rs +++ b/rom/dev/src/flow/cold_reset/fmc_alias.rs @@ -48,10 +48,15 @@ impl FmcAliasLayer { ) -> CaliptraResult<()> { cprintln!("[afmc] ++"); cprintln!("[afmc] CDI.KEYID = {}", KEY_ID_ROM_FMC_CDI as u8); - cprintln!("[afmc] SUBJECT.KEYID = {}", KEY_ID_FMC_ECDSA_PRIV_KEY as u8); cprintln!( - "[afmc] ECC AUTHORITY.KEYID = {}", - input.ecc_auth_key_pair.priv_key as u8 + "[afmc] ECC SUBJECT.KEYID = {}, MLDSA SUBJECT.KEYID = {}", + KEY_ID_FMC_ECDSA_PRIV_KEY as u8, + KEY_ID_FMC_MLDSA_KEYPAIR_SEED as u8 + ); + cprintln!( + "[afmc] ECC AUTHORITY.KEYID = {}, MLDSA AUTHORITY.KEYID = {}", + input.ecc_auth_key_pair.priv_key as u8, + input.mldsa_auth_key_pair.key_pair_seed as u8 ); // We use the value of PCR0 as the measurement for deriving the CDI. @@ -62,18 +67,24 @@ impl FmcAliasLayer { measurement.0.zeroize(); result?; - // Derive DICE Key Pair from CDI - let ecc_key_pair = - Self::derive_key_pair(env, KEY_ID_ROM_FMC_CDI, KEY_ID_FMC_ECDSA_PRIV_KEY)?; + // Derive DICE ECC and MLDSA Key Pairs from CDI + let (ecc_key_pair, mldsa_key_pair) = Self::derive_key_pair( + env, + KEY_ID_ROM_FMC_CDI, + KEY_ID_FMC_ECDSA_PRIV_KEY, + KEY_ID_FMC_MLDSA_KEYPAIR_SEED, + )?; // Generate the Subject Serial Number and Subject Key Identifier. // // This information will be used by next DICE Layer while generating // certificates let ecc_subj_sn = X509::subj_sn(env, &PubKey::Ecc(&ecc_key_pair.pub_key))?; + let mldsa_subj_sn = X509::subj_sn(env, &PubKey::Mldsa(&mldsa_key_pair.pub_key))?; report_boot_status(FmcAliasSubjIdSnGenerationComplete.into()); let ecc_subj_key_id = X509::subj_key_id(env, &PubKey::Ecc(&ecc_key_pair.pub_key))?; + let mldsa_subj_key_id = X509::subj_key_id(env, &PubKey::Mldsa(&mldsa_key_pair.pub_key))?; report_boot_status(FmcAliasSubjKeyIdGenerationComplete.into()); // Generate the output for next layer @@ -81,12 +92,9 @@ impl FmcAliasLayer { ecc_subj_key_pair: ecc_key_pair, ecc_subj_sn, ecc_subj_key_id, - mldsa_subj_key_id: [0; 20], - mldsa_subj_key_pair: MlDsaKeyPair { - key_pair_seed: KEY_ID_FMC_MLDSA_KEYPAIR_SEED, - pub_key: Default::default(), - }, - mldsa_subj_sn: [0; 64], + mldsa_subj_key_pair: mldsa_key_pair, + mldsa_subj_sn, + mldsa_subj_key_id, }; // Generate FMC Alias Certificate @@ -111,7 +119,7 @@ impl FmcAliasLayer { fn derive_cdi(env: &mut RomEnv, measurements: &Array4x12, cdi: KeyId) -> CaliptraResult<()> { let mut measurements: [u8; 48] = measurements.into(); - let result = Crypto::hmac384_kdf(env, cdi, b"fmc_alias_cdi", Some(&measurements), cdi); + let result = Crypto::hmac384_kdf(env, cdi, b"alias_fmc_cdi", Some(&measurements), cdi); measurements.zeroize(); result?; report_boot_status(FmcAliasDeriveCdiComplete.into()); @@ -124,7 +132,8 @@ impl FmcAliasLayer { /// /// * `env` - ROM Environment /// * `cdi` - Composite Device Identity - /// * `priv_key` - Key slot to store the private key into + /// * `ecc_priv_key` - Key slot to store the ECC private key into + /// * `mldsa_keypair_seed` - Key slot to store the MLDSA key pair seed /// /// # Returns /// @@ -133,16 +142,28 @@ impl FmcAliasLayer { fn derive_key_pair( env: &mut RomEnv, cdi: KeyId, - priv_key: KeyId, - ) -> CaliptraResult { - let result = Crypto::ecc384_key_gen(env, cdi, b"fmc_alias_keygen", priv_key); + ecc_priv_key: KeyId, + mldsa_keypair_seed: KeyId, + ) -> CaliptraResult<(Ecc384KeyPair, MlDsaKeyPair)> { + let result = Crypto::ecc384_key_gen(env, cdi, b"alias_fmc_ecc_key", ecc_priv_key); + if cfi_launder(result.is_ok()) { + cfi_assert!(result.is_ok()); + } else { + cfi_assert!(result.is_err()); + } + let ecc_keypair = result?; + + // Derive the MLDSA Key Pair. + let result = Crypto::mldsa_key_gen(env, cdi, b"alias_fmc_mldsa_key", mldsa_keypair_seed); if cfi_launder(result.is_ok()) { cfi_assert!(result.is_ok()); - report_boot_status(FmcAliasKeyPairDerivationComplete.into()); } else { cfi_assert!(result.is_err()); } - result + let mldsa_keypair = result?; + + report_boot_status(FmcAliasKeyPairDerivationComplete.into()); + Ok((ecc_keypair, mldsa_keypair)) } /// Generate Local Device ID Certificate Signature @@ -240,6 +261,8 @@ impl FmcAliasLayer { // Copy TBS to DCCM. copy_tbs(tbs.tbs(), TbsType::FmcaliasTbs, env)?; + // [CAP2][TODO] Generate MLDSA certificate signature, TBS. + report_boot_status(FmcAliasCertSigGenerationComplete.into()); Ok(()) } diff --git a/test/src/derive.rs b/test/src/derive.rs index 946007db33..964375b3b3 100644 --- a/test/src/derive.rs +++ b/test/src/derive.rs @@ -420,14 +420,14 @@ impl FmcAliasKey { pub fn derive(pcr0: &Pcr0, ldevid: &LDevId) -> Self { let mut cdi: [u32; 12] = transmute!(hmac384_kdf( swap_word_bytes(&ldevid.cdi).as_bytes(), - b"fmc_alias_cdi", + b"alias_fmc_cdi", Some(swap_word_bytes(&pcr0.0).as_bytes()), )); swap_word_bytes_inplace(&mut cdi); let mut priv_key_seed: [u32; 12] = transmute!(hmac384_kdf( swap_word_bytes(&cdi).as_bytes(), - b"fmc_alias_keygen", + b"alias_fmc_ecc_key", None )); swap_word_bytes_inplace(&mut priv_key_seed); @@ -519,13 +519,13 @@ fn test_derive_fmc_alias_key() { assert_eq!( fmc_alias_key, FmcAliasKey { - cdi: [ - 0xf4fb8b09, 0xc9233adb, 0x3dfade39, 0xb656f0ef, 0x151404dc, 0xf4fe787a, 0x0664baea, - 0xe9d2de59, 0x22401c7c, 0x59087111, 0xd3aeb5b1, 0x368742da - ], priv_key: [ - 0x81a4f53c, 0xeb0749ca, 0x77b0fe32, 0x33fd9798, 0x7412f652, 0xded8f8a5, 0x39a9ebbd, - 0x75ce2870, 0xb5f62bb3, 0x25376504, 0xa34f286c, 0x849ea86c, + 0xB0490161, 0xA1D2393A, 0x752E2F60, 0x4BB9A01E, 0x293B9E47, 0x61698007, 0x2CED9BAF, + 0x1F828679, 0xCB5054CD, 0xFD0EB072, 0x8D6BE59F, 0x75C55332 + ], + cdi: [ + 0xCEAA7956, 0x4E5A8809, 0x7F1BF1B8, 0xA3A9C903, 0x37B4335F, 0xEA8A93D2, 0x5D02F1BF, + 0x16B1A537, 0xFE5DB006, 0xD8427583, 0x72C836F1, 0x9BE74AF5, ], } ); From e0beffe228d2a62c1c9387e5af31b0c021fe1577 Mon Sep 17 00:00:00 2001 From: Arthur Heymans Date: Thu, 21 Nov 2024 22:03:50 +0100 Subject: [PATCH 26/51] Add keyvault with 64b keys (#1805) --- sw-emulator/lib/periph/src/asym_ecc384.rs | 6 ++--- sw-emulator/lib/periph/src/doe.rs | 20 +++++++++++--- sw-emulator/lib/periph/src/hash_sha512.rs | 28 ++++++++++--------- sw-emulator/lib/periph/src/key_vault.rs | 33 ++++++++++++----------- sw-emulator/lib/periph/src/root_bus.rs | 6 +++-- 5 files changed, 55 insertions(+), 38 deletions(-) diff --git a/sw-emulator/lib/periph/src/asym_ecc384.rs b/sw-emulator/lib/periph/src/asym_ecc384.rs index 859890a200..200e3faaae 100644 --- a/sw-emulator/lib/periph/src/asym_ecc384.rs +++ b/sw-emulator/lib/periph/src/asym_ecc384.rs @@ -638,7 +638,7 @@ impl AsymEcc384 { let pcr_digest = self.hash_sha512.pcr_hash_digest(); - let signature = Ecc384::sign(&pcr_key, &pcr_digest); + let signature = Ecc384::sign(&pcr_key[..48].try_into().unwrap(), &pcr_digest); self.sig_r = words_from_bytes_le(&signature.r); self.sig_s = words_from_bytes_le(&signature.s); } @@ -1037,7 +1037,7 @@ mod tests { let mut ecc = AsymEcc384::new(&clock, key_vault, sha512); - let mut hash = [0u8; KeyVault::KEY_SIZE]; + let mut hash = [0u8; 48]; hash.to_big_endian(); // Change DWORDs to big-endian. for i in (0..hash.len()).step_by(4) { @@ -1238,7 +1238,7 @@ mod tests { let mut ecc = AsymEcc384::new(&clock, key_vault, sha512); - let hash = [0u8; KeyVault::KEY_SIZE]; + let hash = [0u8; 48]; for i in (0..hash.len()).step_by(4) { assert_eq!( ecc.write(RvSize::Word, OFFSET_HASH + i as RvAddr, make_word(i, &hash)) diff --git a/sw-emulator/lib/periph/src/doe.rs b/sw-emulator/lib/periph/src/doe.rs index a4536ac671..47a48dfd13 100644 --- a/sw-emulator/lib/periph/src/doe.rs +++ b/sw-emulator/lib/periph/src/doe.rs @@ -298,8 +298,14 @@ mod tests { let mut ku_hmac_key = KeyUsage::default(); ku_hmac_key.set_hmac_key(true); - assert_eq!(key_vault.read_key(2, ku_hmac_data).unwrap(), PLAIN_TEXT_UDS); - assert_eq!(key_vault.read_key(2, ku_hmac_key).unwrap(), PLAIN_TEXT_UDS); + assert_eq!( + key_vault.read_key(2, ku_hmac_data).unwrap()[..48], + PLAIN_TEXT_UDS + ); + assert_eq!( + key_vault.read_key(2, ku_hmac_key).unwrap()[..48], + PLAIN_TEXT_UDS + ); } #[test] @@ -364,8 +370,14 @@ mod tests { let mut ku_hmac_key = KeyUsage::default(); ku_hmac_key.set_hmac_key(true); - assert_eq!(key_vault.read_key(3, ku_hmac_data).unwrap(), PLAIN_TEXT_FE); - assert_eq!(key_vault.read_key(3, ku_hmac_key).unwrap(), PLAIN_TEXT_FE); + assert_eq!( + key_vault.read_key(3, ku_hmac_data).unwrap()[..48], + PLAIN_TEXT_FE + ); + assert_eq!( + key_vault.read_key(3, ku_hmac_key).unwrap()[..48], + PLAIN_TEXT_FE + ); } #[test] diff --git a/sw-emulator/lib/periph/src/hash_sha512.rs b/sw-emulator/lib/periph/src/hash_sha512.rs index a781edb1fb..59718f88d6 100644 --- a/sw-emulator/lib/periph/src/hash_sha512.rs +++ b/sw-emulator/lib/periph/src/hash_sha512.rs @@ -536,7 +536,7 @@ impl HashSha512Regs { // Copy the hash to the PCR if this is the last block and PCR_HASH_EXTEND is set. let pcr_id = self.block_read_ctrl.reg.read(BlockReadControl::KEY_ID); self.key_vault - .write_pcr(pcr_id, array_ref![self.hash.data(), 0, KeyVault::KEY_SIZE]) + .write_pcr(pcr_id, array_ref![self.hash.data(), 0, KeyVault::PCR_SIZE]) .unwrap(); self.block_read_ctrl @@ -560,10 +560,13 @@ impl HashSha512Regs { // Clear the block self.block.fill(0); - let result: Result<[u8; KeyVault::KEY_SIZE], BusError> = if pcr_hash_extend == 0 { + let result: Result<[u8; KeyVault::PCR_SIZE], BusError> = if pcr_hash_extend == 0 { let mut key_usage = KeyUsage::default(); key_usage.set_sha_data(true); - self.key_vault.read_key(key_id, key_usage) + match self.key_vault.read_key(key_id, key_usage) { + Err(x) => Err(x), + Ok(x) => Ok(x[..KeyVault::PCR_SIZE].try_into().unwrap()), + } } else { Ok(self.key_vault.read_pcr(key_id)) }; @@ -582,8 +585,8 @@ impl HashSha512Regs { if let Some(data) = data { if pcr_hash_extend != 0 { // Copy the PCR (48 bytes) to the block registers. - self.block[..KeyVault::KEY_SIZE / 4].copy_from_slice(&words_from_bytes_le( - &<[u8; KeyVault::KEY_SIZE]>::try_from(&data[..KeyVault::KEY_SIZE]).unwrap(), + self.block[..KeyVault::PCR_SIZE / 4].copy_from_slice(&words_from_bytes_le( + &<[u8; KeyVault::PCR_SIZE]>::try_from(&data[..KeyVault::PCR_SIZE]).unwrap(), )); self.pcr_present = true; } else { @@ -603,13 +606,12 @@ impl HashSha512Regs { /// /// # Arguments /// - /// * `data_len` - Size of the data /// * `data` - Data to hash. This is in big-endian format. /// /// # Error /// /// * `None` - fn format_block(&mut self, data: &[u8; KeyVault::KEY_SIZE]) { + fn format_block(&mut self, data: &[u8]) { let mut block_arr = [0u8; SHA512_BLOCK_SIZE]; block_arr[..data.len()].copy_from_slice(&data[..data.len()]); @@ -1170,7 +1172,7 @@ mod tests { #[test] fn test_sha384_kv_block_read() { - let test_block: [u8; KeyVault::KEY_SIZE] = [ + let test_block: [u8; SHA384_HASH_SIZE] = [ 0x9c, 0x2f, 0x48, 0x76, 0x0d, 0x13, 0xac, 0x42, 0xea, 0xd1, 0x96, 0xe5, 0x4d, 0xcb, 0xaa, 0x5e, 0x58, 0x72, 0x06, 0x62, 0xa9, 0x6b, 0x91, 0x94, 0xe9, 0x81, 0x33, 0x29, 0xbd, 0xb6, 0x27, 0xc7, 0xc1, 0xca, 0x77, 0x15, 0x31, 0x16, 0x32, 0xc1, 0x39, 0xe7, @@ -1196,7 +1198,7 @@ mod tests { #[test] fn test_sha384_kv_block_read_fail() { - let test_block: [u8; KeyVault::KEY_SIZE] = [ + let test_block: [u8; SHA384_HASH_SIZE] = [ 0x9c, 0x2f, 0x48, 0x76, 0x0d, 0x13, 0xac, 0x42, 0xea, 0xd1, 0x96, 0xe5, 0x4d, 0xcb, 0xaa, 0x5e, 0x58, 0x72, 0x06, 0x62, 0xa9, 0x6b, 0x91, 0x94, 0xe9, 0x81, 0x33, 0x29, 0xbd, 0xb6, 0x27, 0xc7, 0xc1, 0xca, 0x77, 0x15, 0x31, 0x16, 0x32, 0xc1, 0x39, 0xe7, @@ -1239,7 +1241,7 @@ mod tests { #[test] fn test_sha384_kv_hash_write() { - let test_block: [u8; KeyVault::KEY_SIZE] = [ + let test_block: [u8; SHA384_HASH_SIZE] = [ 0x9c, 0x2f, 0x48, 0x76, 0x0d, 0x13, 0xac, 0x42, 0xea, 0xd1, 0x96, 0xe5, 0x4d, 0xcb, 0xaa, 0x5e, 0x58, 0x72, 0x06, 0x62, 0xa9, 0x6b, 0x91, 0x94, 0xe9, 0x81, 0x33, 0x29, 0xbd, 0xb6, 0x27, 0xc7, 0xc1, 0xca, 0x77, 0x15, 0x31, 0x16, 0x32, 0xc1, 0x39, 0xe7, @@ -1265,7 +1267,7 @@ mod tests { #[test] fn test_sha384_kv_hash_write_fail() { - let test_block: [u8; KeyVault::KEY_SIZE] = [ + let test_block: [u8; SHA384_HASH_SIZE] = [ 0x9c, 0x2f, 0x48, 0x76, 0x0d, 0x13, 0xac, 0x42, 0xea, 0xd1, 0x96, 0xe5, 0x4d, 0xcb, 0xaa, 0x5e, 0x58, 0x72, 0x06, 0x62, 0xa9, 0x6b, 0x91, 0x94, 0xe9, 0x81, 0x33, 0x29, 0xbd, 0xb6, 0x27, 0xc7, 0xc1, 0xca, 0x77, 0x15, 0x31, 0x16, 0x32, 0xc1, 0x39, 0xe7, @@ -1294,7 +1296,7 @@ mod tests { #[test] fn test_sha384_kv_block_read_hash_write() { - let test_block: [u8; KeyVault::KEY_SIZE] = [ + let test_block: [u8; SHA384_HASH_SIZE] = [ 0x9c, 0x2f, 0x48, 0x76, 0x0d, 0x13, 0xac, 0x42, 0xea, 0xd1, 0x96, 0xe5, 0x4d, 0xcb, 0xaa, 0x5e, 0x58, 0x72, 0x06, 0x62, 0xa9, 0x6b, 0x91, 0x94, 0xe9, 0x81, 0x33, 0x29, 0xbd, 0xb6, 0x27, 0xc7, 0xc1, 0xca, 0x77, 0x15, 0x31, 0x16, 0x32, 0xc1, 0x39, 0xe7, @@ -1321,7 +1323,7 @@ mod tests { } } - fn test_pcr_hash_extend(data: &[u8], pcr_data: &mut [u8; KeyVault::KEY_SIZE], expected: &[u8]) { + fn test_pcr_hash_extend(data: &[u8], pcr_data: &mut [u8; SHA384_HASH_SIZE], expected: &[u8]) { // Prime the PCR vault. let clock = Clock::new(); let pcr_id = 0; diff --git a/sw-emulator/lib/periph/src/key_vault.rs b/sw-emulator/lib/periph/src/key_vault.rs index 7e86033583..57532129ff 100644 --- a/sw-emulator/lib/periph/src/key_vault.rs +++ b/sw-emulator/lib/periph/src/key_vault.rs @@ -20,7 +20,7 @@ use std::cell::RefCell; use std::rc::Rc; use tock_registers::{register_bitfields, LocalRegisterCopy}; -mod constants { +pub mod constants { #![allow(unused)] // Key Vault @@ -109,7 +109,7 @@ mod constants { pub const PCR_CONTROL_REG_RESET_VAL: u32 = 0; /// Key Memory Size - pub const KEY_REG_SIZE: usize = 0x600; + pub const KEY_REG_SIZE: usize = 0x800; /// Key control register reset value pub const KEY_CONTROL_REG_RESET_VAL: u32 = 0; @@ -145,8 +145,9 @@ pub struct KeyVault { } impl KeyVault { + pub const PCR_SIZE: usize = 48; pub const KEY_COUNT: u32 = 32; - pub const KEY_SIZE: usize = 48; + pub const KEY_SIZE: usize = 64; pub const KEY_CONTROL_REG_OFFSET: u32 = 0; pub const KEY_CONTROL_REG_WIDTH: u32 = 0x4; @@ -725,7 +726,7 @@ mod tests { #[test] fn test_key_private_read_write() { - let expected: [u8; KeyVault::KEY_SIZE] = [ + let expected: &[u8] = &[ 0x11, 0x65, 0xb3, 0x40, 0x6f, 0xf0, 0xb5, 0x2a, 0x3d, 0x24, 0x72, 0x1f, 0x78, 0x54, 0x62, 0xca, 0x22, 0x76, 0xc9, 0xf4, 0x54, 0xa1, 0x16, 0xc2, 0xb2, 0xba, 0x20, 0x17, 0x1a, 0x79, 0x05, 0xea, 0x5a, 0x02, 0x66, 0x82, 0xeb, 0x65, 0x9c, 0x4d, 0x5f, 0x11, @@ -738,10 +739,10 @@ mod tests { for idx in 0..KeyVault::KEY_COUNT { vault - .write_key(idx, &expected, u32::from(key_usage)) + .write_key(idx, expected, u32::from(key_usage)) .unwrap(); let returned = vault.read_key(idx, key_usage).unwrap(); - assert_eq!(&returned, &expected); + assert_eq!(&returned[..expected.len()], expected); } } @@ -773,7 +774,8 @@ mod tests { 0x11, 0x65, 0xb3, 0x40, 0x6f, 0xf0, 0xb5, 0x2a, 0x3d, 0x24, 0x72, 0x1f, 0x78, 0x54, 0x62, 0xca, 0x22, 0x76, 0xc9, 0xf4, 0x54, 0xa1, 0x16, 0xc2, 0xb2, 0xba, 0x20, 0x17, 0x1a, 0x79, 0x05, 0xea, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 ] ); } @@ -903,7 +905,7 @@ mod tests { #[test] fn test_key_private_read_blocked() { - let expected: [u8; KeyVault::KEY_SIZE] = [ + let expected: &[u8] = &[ 0x11, 0x65, 0xb3, 0x40, 0x6f, 0xf0, 0xb5, 0x2a, 0x3d, 0x24, 0x72, 0x1f, 0x78, 0x54, 0x62, 0xca, 0x22, 0x76, 0xc9, 0xf4, 0x54, 0xa1, 0x16, 0xc2, 0xb2, 0xba, 0x20, 0x17, 0x1a, 0x79, 0x05, 0xea, 0x5a, 0x02, 0x66, 0x82, 0xeb, 0x65, 0x9c, 0x4d, 0x5f, 0x11, @@ -926,7 +928,7 @@ mod tests { ); assert!(vault - .write_key(key_id, &expected, u32::from(key_usage)) + .write_key(key_id, expected, u32::from(key_usage)) .is_ok()); // Block read access to the key. @@ -947,7 +949,7 @@ mod tests { #[test] fn test_key_private_write_blocked() { - let expected: [u8; KeyVault::KEY_SIZE] = [ + let expected: &[u8] = &[ 0x11, 0x65, 0xb3, 0x40, 0x6f, 0xf0, 0xb5, 0x2a, 0x3d, 0x24, 0x72, 0x1f, 0x78, 0x54, 0x62, 0xca, 0x22, 0x76, 0xc9, 0xf4, 0x54, 0xa1, 0x16, 0xc2, 0xb2, 0xba, 0x20, 0x17, 0x1a, 0x79, 0x05, 0xea, 0x5a, 0x02, 0x66, 0x82, 0xeb, 0x65, 0x9c, 0x4d, 0x5f, 0x11, @@ -975,7 +977,7 @@ mod tests { assert_eq!( vault - .write_key(key_id, &expected, u32::from(key_usage)) + .write_key(key_id, expected, u32::from(key_usage)) .err(), Some(BusError::StoreAccessFault) ); @@ -984,7 +986,7 @@ mod tests { #[test] fn test_key_clear() { - let expected: [u8; KeyVault::KEY_SIZE] = [ + let expected: &[u8] = &[ 0x11, 0x65, 0xb3, 0x40, 0x6f, 0xf0, 0xb5, 0x2a, 0x3d, 0x24, 0x72, 0x1f, 0x78, 0x54, 0x62, 0xca, 0x22, 0x76, 0xc9, 0xf4, 0x54, 0xa1, 0x16, 0xc2, 0xb2, 0xba, 0x20, 0x17, 0x1a, 0x79, 0x05, 0xea, 0x5a, 0x02, 0x66, 0x82, 0xeb, 0x65, 0x9c, 0x4d, 0x5f, 0x11, @@ -1001,12 +1003,11 @@ mod tests { for key_id in 0..KeyVault::KEY_COUNT { assert_eq!( - vault - .write_key(key_id, &expected, u32::from(key_usage)) - .ok(), + vault.write_key(key_id, expected, u32::from(key_usage)).ok(), Some(()) ); - assert_eq!(&vault.read_key(key_id, key_usage).unwrap(), &expected); + let key = vault.read_key(key_id, key_usage).unwrap(); + assert_eq!(&key[..expected.len()], expected); // Clear the key. assert_eq!( diff --git a/sw-emulator/lib/periph/src/root_bus.rs b/sw-emulator/lib/periph/src/root_bus.rs index 313ecf90a5..7b9a5568ba 100644 --- a/sw-emulator/lib/periph/src/root_bus.rs +++ b/sw-emulator/lib/periph/src/root_bus.rs @@ -415,7 +415,8 @@ mod tests { 0x00_u8, 0x11, 0x22, 0x33, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, - 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa + 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, + 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa ] ); } @@ -446,7 +447,8 @@ mod tests { 0x00_u8, 0x11, 0x22, 0x33, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 ] ); } From ce4af679b3f52bac9cb7fe77a4a476c5fd7f11f9 Mon Sep 17 00:00:00 2001 From: Jeff Andersen Date: Mon, 18 Nov 2024 20:27:17 -0800 Subject: [PATCH 27/51] [ROM] Only inspect RT FW's SVN during image validation. This is done as part of Stable Identity, which requires Caliptra to have a single SVN. As part of this work, FMC's SVN is being deprecated. Instead, the runtime SVN now describes the security state of the entire firmware image. This is safe because the FMC and runtime images are always signed, validated, and updated in tandem. Future changes will update build tooling to prevent callers from setting FMC's SVN. --- common/src/verifier.rs | 5 - drivers/src/fuse_log.rs | 22 +-- error/src/lib.rs | 12 +- image/types/src/lib.rs | 1 + image/verify/fuzz/src/fuzz_target_common.rs | 8 -- image/verify/src/lib.rs | 24 ++-- image/verify/src/verifier.rs | 132 +++++++----------- rom/dev/README.md | 17 +-- rom/dev/doc/error-attribution.md | 8 -- rom/dev/doc/test-coverage/test-coverage.md | 2 - rom/dev/src/flow/cold_reset/fmc_alias.rs | 2 +- rom/dev/src/flow/cold_reset/fw_processor.rs | 29 ++-- rom/dev/src/flow/fake.rs | 7 +- rom/dev/src/flow/update_reset.rs | 2 +- rom/dev/src/pcr.rs | 2 +- .../test_fmcalias_derivation.rs | 13 +- .../test_image_validation.rs | 71 ---------- .../rom_integration_tests/test_warm_reset.rs | 3 + .../runtime_integration_tests/test_info.rs | 5 +- .../fake_collateral_boot_test.rs | 2 + .../caliptra_integration_tests/jtag_test.rs | 1 + .../caliptra_integration_tests/smoke_test.rs | 9 +- .../caliptra_integration_tests/warm_reset.rs | 6 + test/tests/fips_test_suite/README.md | 2 +- test/tests/fips_test_suite/fw_load.rs | 59 -------- 25 files changed, 142 insertions(+), 302 deletions(-) diff --git a/common/src/verifier.rs b/common/src/verifier.rs index 35b7b2ef7a..ae558cff94 100644 --- a/common/src/verifier.rs +++ b/common/src/verifier.rs @@ -128,11 +128,6 @@ impl<'a, 'b> ImageVerificationEnv for &mut FirmwareImageVerificationEnv<'a, 'b> self.data_vault.fmc_tci().into() } - // Get Fuse FMC Key Manifest SVN - fn fmc_fuse_svn(&self) -> u32 { - self.soc_ifc.fuse_bank().fmc_fuse_svn() - } - // Get Runtime fuse SVN fn runtime_fuse_svn(&self) -> u32 { self.soc_ifc.fuse_bank().runtime_fuse_svn() diff --git a/drivers/src/fuse_log.rs b/drivers/src/fuse_log.rs index 1e09f6f321..3f73a1de2c 100644 --- a/drivers/src/fuse_log.rs +++ b/drivers/src/fuse_log.rs @@ -19,26 +19,28 @@ use zeroize::Zeroize; pub enum FuseLogEntryId { Invalid = 0, - VendorEccPubKeyIndex = 1, // 4 bytes (From Manifest) - VendorEccPubKeyRevocation = 2, // 4 bytes (From Fuse) - ManifestFmcSvn = 3, // 4 bytes - ManifestReserved0 = 4, // 4 bytes - FuseFmcSvn = 5, // 4 bytes - ManifestRtSvn = 6, // 4 bytes - ManifestReserved1 = 7, // 4 bytes - FuseRtSvn = 8, // 4 bytes - VendorLmsPubKeyIndex = 9, // 4 bytes (From Manifest) + VendorEccPubKeyIndex = 1, // 4 bytes (From Manifest) + VendorEccPubKeyRevocation = 2, // 4 bytes (From Fuse) + ManifestFmcSvn = 3, // 4 bytes + ManifestReserved0 = 4, // 4 bytes + #[deprecated] + _DeprecatedFuseFmcSvn = 5, // 4 bytes + ManifestRtSvn = 6, // 4 bytes + ManifestReserved1 = 7, // 4 bytes + FuseRtSvn = 8, // 4 bytes + VendorLmsPubKeyIndex = 9, // 4 bytes (From Manifest) VendorLmsPubKeyRevocation = 10, // 4 bytes (From Fuse) } impl From for FuseLogEntryId { + #[allow(deprecated)] fn from(id: u32) -> FuseLogEntryId { match id { 1 => FuseLogEntryId::VendorEccPubKeyIndex, 2 => FuseLogEntryId::VendorEccPubKeyRevocation, 3 => FuseLogEntryId::ManifestFmcSvn, 4 => FuseLogEntryId::ManifestReserved0, - 5 => FuseLogEntryId::FuseFmcSvn, + 5 => FuseLogEntryId::_DeprecatedFuseFmcSvn, 6 => FuseLogEntryId::ManifestRtSvn, 7 => FuseLogEntryId::ManifestReserved1, 8 => FuseLogEntryId::FuseRtSvn, diff --git a/error/src/lib.rs b/error/src/lib.rs index 6103bd3c21..1bd65a3840 100644 --- a/error/src/lib.rs +++ b/error/src/lib.rs @@ -218,12 +218,9 @@ impl CaliptraError { CaliptraError::new_const(0x000b0023); pub const IMAGE_VERIFIER_ERR_FMC_ENTRY_POINT_UNALIGNED: CaliptraError = CaliptraError::new_const(0x000b0024); - pub const IMAGE_VERIFIER_ERR_FMC_SVN_GREATER_THAN_MAX_SUPPORTED: CaliptraError = - CaliptraError::new_const(0x000b0025); - pub const IMAGE_VERIFIER_ERR_FMC_SVN_LESS_THAN_MIN_SUPPORTED: CaliptraError = - CaliptraError::new_const(0x000b0026); - pub const IMAGE_VERIFIER_ERR_FMC_SVN_LESS_THAN_FUSE: CaliptraError = - CaliptraError::new_const(0x000b0027); + // 0x000b0025 was IMAGE_VERIFIER_ERR_FMC_SVN_GREATER_THAN_MAX_SUPPORTED + // 0x000b0026 was IMAGE_VERIFIER_ERR_FMC_SVN_LESS_THAN_MIN_SUPPORTED + // 0x000b0027 was IMAGE_VERIFIER_ERR_FMC_SVN_LESS_THAN_FUSE pub const IMAGE_VERIFIER_ERR_RUNTIME_LOAD_ADDR_INVALID: CaliptraError = CaliptraError::new_const(0x000b0028); pub const IMAGE_VERIFIER_ERR_RUNTIME_LOAD_ADDR_UNALIGNED: CaliptraError = @@ -234,8 +231,7 @@ impl CaliptraError { CaliptraError::new_const(0x000b002b); pub const IMAGE_VERIFIER_ERR_RUNTIME_SVN_GREATER_THAN_MAX_SUPPORTED: CaliptraError = CaliptraError::new_const(0x000b002c); - pub const IMAGE_VERIFIER_ERR_RUNTIME_SVN_LESS_THAN_MIN_SUPPORTED: CaliptraError = - CaliptraError::new_const(0x000b002d); + // 0x000b002d was IMAGE_VERIFIER_ERR_RUNTIME_SVN_LESS_THAN_MIN_SUPPORTED pub const IMAGE_VERIFIER_ERR_RUNTIME_SVN_LESS_THAN_FUSE: CaliptraError = CaliptraError::new_const(0x000b002e); pub const IMAGE_VERIFIER_ERR_IMAGE_LEN_MORE_THAN_BUNDLE_SIZE: CaliptraError = diff --git a/image/types/src/lib.rs b/image/types/src/lib.rs index 3b778e925c..c645707836 100644 --- a/image/types/src/lib.rs +++ b/image/types/src/lib.rs @@ -479,6 +479,7 @@ pub struct ImageTocEntry { pub version: u32, /// Security Version Number + /// Only read for Runtime entries. Not read for FMC. pub svn: u32, /// Reserved field diff --git a/image/verify/fuzz/src/fuzz_target_common.rs b/image/verify/fuzz/src/fuzz_target_common.rs index 900fdbb3a6..5a39d1b07c 100644 --- a/image/verify/fuzz/src/fuzz_target_common.rs +++ b/image/verify/fuzz/src/fuzz_target_common.rs @@ -121,14 +121,6 @@ impl ImageVerificationEnv for TestEnv { self.fmc_digest } - fn fmc_fuse_svn(&self) -> u32 { - 0 - } - - fn runtime_fuse_svn(&self) -> u32 { - 0 - } - fn iccm_range(&self) -> Range { Range { start: ICCM_ORG, diff --git a/image/verify/src/lib.rs b/image/verify/src/lib.rs index f132b81f49..a013cc9cc1 100644 --- a/image/verify/src/lib.rs +++ b/image/verify/src/lib.rs @@ -25,7 +25,7 @@ pub const MAX_RUNTIME_SVN: u32 = 128; /// Image Verifification Executable Info #[derive(Default, Debug)] -pub struct ImageSvnLogInfo { +pub struct FirmwareSvnLogInfo { pub manifest_svn: u32, pub reserved: u32, pub fuse_svn: u32, @@ -43,12 +43,6 @@ pub struct ImageVerificationExeInfo { /// Entry Point pub entry_point: u32, - /// Security version number - pub svn: u32, - - /// The effective fuse SVN for this image - pub effective_fuse_svn: u32, - /// Digest of the image pub digest: ImageDigest, } @@ -68,11 +62,8 @@ pub struct ImageVerificationLogInfo { /// Vendor LMS Public Key Revocation Fuse pub fuse_vendor_lms_pub_key_revocation: u32, - /// First Mutable code's logging information - pub fmc_log_info: ImageSvnLogInfo, - - /// Runtime Mutable code's logging information - pub rt_log_info: ImageSvnLogInfo, + /// Firmware's SVN logging information + pub fw_log_info: FirmwareSvnLogInfo, } /// Verified image information @@ -93,6 +84,12 @@ pub struct ImageVerificationInfo { /// Whether `owner_pub_keys_digest` was in fuses pub owner_pub_keys_digest_in_fuses: bool, + /// The SVN for this firmware bundle + pub fw_svn: u32, + + /// The effective fuse SVN for this firmware bundle + pub effective_fuse_svn: u32, + /// First mutable code pub fmc: ImageVerificationExeInfo, @@ -154,9 +151,6 @@ pub trait ImageVerificationEnv { // Save the fmc digest in the data vault on cold boot fn get_fmc_digest_dv(&self) -> ImageDigest; - // Get Fuse FMC Key Manifest SVN - fn fmc_fuse_svn(&self) -> u32; - // Get Runtime fuse SVN fn runtime_fuse_svn(&self) -> u32; diff --git a/image/verify/src/verifier.rs b/image/verify/src/verifier.rs index 15bd546054..e0228a326a 100644 --- a/image/verify/src/verifier.rs +++ b/image/verify/src/verifier.rs @@ -112,10 +112,18 @@ impl ImageVerifier { let image_info = okref(&image_info)?; // Verify FMC - let (fmc_info, fmc_log_info) = self.verify_fmc(image_info.fmc, reason)?; + let fmc_info = self.verify_fmc(image_info.fmc, reason)?; // Verify Runtime - let (runtime_info, rt_log_info) = self.verify_runtime(image_info.runtime)?; + let runtime_info = self.verify_runtime(image_info.runtime)?; + + // The FMC and RT FW images within the bundle each include an SVN, for + // backwards compatibility with 1.x. ROM only inspects the RT FW SVN. + let fw_svn = image_info.runtime.svn; + + self.verify_svn(fw_svn)?; + + let effective_fuse_svn = self.effective_fuse_svn(); let info = ImageVerificationInfo { vendor_ecc_pub_key_idx: header_info.vendor_ecc_pub_key_idx, @@ -124,13 +132,18 @@ impl ImageVerifier { owner_pub_keys_digest_in_fuses: header_info.owner_pub_keys_digest_in_fuses, fmc: fmc_info, runtime: runtime_info, + fw_svn, + effective_fuse_svn, log_info: ImageVerificationLogInfo { vendor_ecc_pub_key_idx: header_info.vendor_ecc_pub_key_idx, fuse_vendor_ecc_pub_key_revocation: header_info.vendor_ecc_pub_key_revocation, - fmc_log_info, - rt_log_info, fuse_vendor_lms_pub_key_revocation: header_info.vendor_lms_pub_key_revocation, vendor_lms_pub_key_idx: header_info.vendor_lms_pub_key_idx, + fw_log_info: FirmwareSvnLogInfo { + manifest_svn: fw_svn, + reserved: 0, + fuse_svn: self.env.runtime_fuse_svn(), + }, }, pqc_verify_config: manifest.fw_image_type.into(), }; @@ -138,6 +151,37 @@ impl ImageVerifier { Ok(info) } + /// If an SVN check is required, verifies that the given SVN is greater than + /// or equal to the fuse SVN. + fn verify_svn(&mut self, fw_svn: u32) -> CaliptraResult<()> { + if self.svn_check_required() { + if fw_svn > MAX_RUNTIME_SVN { + Err(CaliptraError::IMAGE_VERIFIER_ERR_RUNTIME_SVN_GREATER_THAN_MAX_SUPPORTED)?; + } + + if cfi_launder(fw_svn) < self.env.runtime_fuse_svn() { + Err(CaliptraError::IMAGE_VERIFIER_ERR_RUNTIME_SVN_LESS_THAN_FUSE)?; + } else { + cfi_assert_ge(fw_svn, self.env.runtime_fuse_svn()); + } + } + Ok(()) + } + + /// Calculates the effective fuse SVN. + /// + /// If anti-rollback is disabled, the effective fuse-SVN is zero. + /// Otherwise, it is the value in fuses. + fn effective_fuse_svn(&mut self) -> u32 { + if cfi_launder(self.env.anti_rollback_disable()) { + cfi_assert!(self.env.anti_rollback_disable()); + 0_u32 + } else { + cfi_assert!(!self.env.anti_rollback_disable()); + self.env.runtime_fuse_svn() + } + } + /// Verify Preamble #[cfg_attr(all(not(test), not(feature = "no-cfi")), cfi_impl_fn)] fn verify_preamble<'a>( @@ -761,7 +805,7 @@ impl ImageVerifier { &mut self, verify_info: &ImageTocEntry, reason: ResetReason, - ) -> CaliptraResult<(ImageVerificationExeInfo, ImageSvnLogInfo)> { + ) -> CaliptraResult { let range = verify_info.image_range()?; #[cfg(feature = "fips-test-hooks")] @@ -806,21 +850,6 @@ impl ImageVerifier { Err(CaliptraError::IMAGE_VERIFIER_ERR_FMC_ENTRY_POINT_UNALIGNED)?; } - if self.svn_check_required() { - if verify_info.svn > 32 { - Err(CaliptraError::IMAGE_VERIFIER_ERR_FMC_SVN_GREATER_THAN_MAX_SUPPORTED)?; - } - - if cfi_launder(verify_info.svn) < self.env.fmc_fuse_svn() { - Err(CaliptraError::IMAGE_VERIFIER_ERR_FMC_SVN_LESS_THAN_FUSE)?; - } else { - cfi_assert_ge(verify_info.svn, self.env.fmc_fuse_svn()); - } - } - - let effective_fuse_svn = - Self::effective_fuse_svn(self.env.fmc_fuse_svn(), self.env.anti_rollback_disable()); - if cfi_launder(reason) == ResetReason::UpdateReset { if cfi_launder(actual) != self.env.get_fmc_digest_dv() { Err(CaliptraError::IMAGE_VERIFIER_ERR_UPDATE_RESET_FMC_DIGEST_MISMATCH)?; @@ -834,19 +863,11 @@ impl ImageVerifier { let info = ImageVerificationExeInfo { load_addr: verify_info.load_addr, entry_point: verify_info.entry_point, - svn: verify_info.svn, - effective_fuse_svn, digest: verify_info.digest, size: verify_info.size, }; - let log_info: ImageSvnLogInfo = ImageSvnLogInfo { - manifest_svn: verify_info.svn, - reserved: verify_info.reserved, - fuse_svn: self.env.fmc_fuse_svn(), - }; - - Ok((info, log_info)) + Ok(info) } /// Verify Runtime @@ -854,7 +875,7 @@ impl ImageVerifier { fn verify_runtime( &mut self, verify_info: &ImageTocEntry, - ) -> CaliptraResult<(ImageVerificationExeInfo, ImageSvnLogInfo)> { + ) -> CaliptraResult { let range = verify_info.image_range()?; #[cfg(feature = "fips-test-hooks")] @@ -898,53 +919,14 @@ impl ImageVerifier { Err(CaliptraError::IMAGE_VERIFIER_ERR_RUNTIME_ENTRY_POINT_UNALIGNED)?; } - if self.svn_check_required() { - if verify_info.svn > MAX_RUNTIME_SVN { - Err(CaliptraError::IMAGE_VERIFIER_ERR_RUNTIME_SVN_GREATER_THAN_MAX_SUPPORTED)?; - } - - if cfi_launder(verify_info.svn) < self.env.runtime_fuse_svn() { - Err(CaliptraError::IMAGE_VERIFIER_ERR_RUNTIME_SVN_LESS_THAN_FUSE)?; - } else { - cfi_assert_ge(verify_info.svn, self.env.runtime_fuse_svn()); - } - } - - let effective_fuse_svn = Self::effective_fuse_svn( - self.env.runtime_fuse_svn(), - self.env.anti_rollback_disable(), - ); - let info = ImageVerificationExeInfo { load_addr: verify_info.load_addr, entry_point: verify_info.entry_point, - svn: verify_info.svn, - effective_fuse_svn, digest: verify_info.digest, size: verify_info.size, }; - let log_info: ImageSvnLogInfo = ImageSvnLogInfo { - manifest_svn: verify_info.svn, - reserved: verify_info.reserved, - fuse_svn: self.env.runtime_fuse_svn(), - }; - - Ok((info, log_info)) - } - - /// Calculates the effective fuse SVN. - /// - /// If anti-rollback is disabled, the effective fuse-SVN is zero. - /// Otherwise, it is SVN-fuses. - fn effective_fuse_svn(fuse_svn: u32, anti_rollback_disable: bool) -> u32 { - if cfi_launder(anti_rollback_disable) { - cfi_assert!(anti_rollback_disable); - 0_u32 - } else { - cfi_assert!(!anti_rollback_disable); - fuse_svn - } + Ok(info) } } @@ -1953,10 +1935,9 @@ mod tests { let result = verifier.verify_fmc(&verify_info, ResetReason::ColdReset); assert!(result.is_ok()); - let (info, _log_info) = result.unwrap(); + let info = result.unwrap(); assert_eq!(info.load_addr, ICCM_ORG); assert_eq!(info.entry_point, ICCM_ORG); - assert_eq!(info.svn, 1); assert_eq!(info.size, 100); } @@ -2016,10 +1997,9 @@ mod tests { }; let result = verifier.verify_runtime(&verify_info); assert!(result.is_ok()); - let (info, _log_info) = result.unwrap(); + let info = result.unwrap(); assert_eq!(info.load_addr, ICCM_ORG); assert_eq!(info.entry_point, ICCM_ORG); - assert_eq!(info.svn, 1); assert_eq!(info.size, 100); } @@ -2122,10 +2102,6 @@ mod tests { self.fmc_digest } - fn fmc_fuse_svn(&self) -> u32 { - 0 - } - fn runtime_fuse_svn(&self) -> u32 { 0 } diff --git a/rom/dev/README.md b/rom/dev/README.md index 3570812db5..4fa7917269 100644 --- a/rom/dev/README.md +++ b/rom/dev/README.md @@ -62,7 +62,6 @@ Following are the main FUSE & Architectural Registers used by the Caliptra ROM f | FUSE_LMS_REVOCATION | 32 | Manufacturer LMS Public Key Revocation Mask | | FUSE_MLDSA_REVOCATION | 32 | Manufacturer MLDSA Public Key Revocation Mask | | FUSE_OWNER_PK_HASH | 384 | Owner ECC and LMS or MLDSA Public Key Hash | -| FUSE_FMC_KEY_MANIFEST_SVN | 32 | FMC Security Version Number | | FUSE_RUNTIME_SVN | 128 | Runtime Security Version Number | | FUSE_ANTI_ROLLBACK_DISABLE | 1 | Disable SVN checking for FMC & Runtime when bit is set | | FUSE_IDEVID_CERT_ATTR | 768 | FUSE containing information for generating IDEVID CSR
**Word 0:bits[0-2]**: ECDSA X509 Key Id Algorithm (3 bits) 0: SHA1, 1: SHA256, 2: SHA384, 3: SHA512, 4: Fuse
**Word 0:bits[3-5]**: MLDSA X509 Key Id Algorithm (3 bits) 0: SHA1, 1: SHA256, 2: SHA384, 3: SHA512, 4: Fuse
**Word 1,2,3,4,5**: ECDSA Subject Key Id
**Word 6,7,8,9,10**: MLDSA Subject Key Id
**Words 11,12**: Unique Endpoint ID
**Words 13,14,15,16**: Manufacturer Serial Number | @@ -159,7 +158,7 @@ It contains the image information and SHA-384 hash of individual firmware images | Image Type | 4 | Image Type that defines format of the image section
**0x0000_0001:** Executable | | Image Revision | 20 | Git Commit hash of the build | | Image Version | 4 | Firmware release number | -| Image SVN | 4 | Security Version Number for the Image. This field is compared against the fuses (FMC SVN or RUNTIME SVN) | +| Image SVN | 4 | Security Version Number for the image. It is compared to FW SVN fuses. FMC TOC entry's SVN field is ignored. | | Reserved | 4 | Reserved field | | Image Load Address | 4 | Load address | | Image Entry Point | 4 | Entry point to start the execution from | @@ -683,7 +682,7 @@ Alias FMC Layer includes the measurement of the FMC and other security states. T - Firmware Image Bundle is successfully loaded and verified from the Mailbox - ROM has following information from Firmware Image Bundle - FMC_DIGEST - Digest of the FMC -- FMC_SVN - SVN for FMC +- FW_SVN - SVN for the firmware - MANUFACTURER_PK - Manufacturer Public Key(s) used to verify the firmware image bundle - MANUFACTURER_PK_INDEX - Index of the MANUFACTURER_PK in the firmware image bundle @@ -698,8 +697,8 @@ Alias FMC Layer includes the measurement of the FMC and other security states. T CPTRA_SECURITY_STATE.DEBUG_ENABLED, FUSE_ANTI_ROLLBACK_DISABLE, ECC_VENDOR_PK_INDEX, - FMC_SVN, - FMC_FUSE_SVN (or 0 if `FUSE_ANTI_ROLLBACK_DISABLE`), + FW_SVN, + FW_FUSE_SVN (or 0 if `FUSE_ANTI_ROLLBACK_DISABLE`), PQC_VENDOR_PK_INDEX, ROM_VERIFY_CONFIG, OWNER_PK_HASH_FROM_FUSES (0 or 1), @@ -774,7 +773,7 @@ Alias FMC Layer includes the measurement of the FMC and other security states. T `dccm_dv_store(FMC_DIGEST, lock_for_wr)` - `dccm_dv_store(FMC_SVN, lock_for_wr)` + `dccm_dv_store(FW_SVN, lock_for_wr)` `dccm_dv_store(FUSE_OWNER_PK_HASH, lock_for_wr)` @@ -811,7 +810,7 @@ Alias FMC Layer includes the measurement of the FMC and other security states. T | 🔒Alias FMC Cert ECDSA Signature R | | 🔒Alias FMC Cert ECDSA Signature S | | 🔒Alias FMC Cert MLDSA Signature | - | 🔒FMC SVN | + | 🔒FW SVN | | 🔒ROM Cold Boot Status | | 🔒FMC Entry Point | | 🔒Manufacturer ECDSA Public Key Index | @@ -828,7 +827,6 @@ Alias FMC Layer includes the measurement of the FMC and other security states. T - **Cold Reset Unlockable values:** These values are unlocked on a Cold Reset: - FMC TCI - - FMC SVN - FMC Entry Point - Owner Pub Key Hash - Ecc Vendor Pub Key Index @@ -943,7 +941,6 @@ The following are the pre-conditions that should be satisfied: - fuse_lms_revocation : This is the bitmask of the LMS keys which are revoked. - fuse_mldsa_revocation : This is the bitmask of the MLDSA keys which are revoked. - fuse_owner_pk_hash : The hash of the owner public keys in preamble. - - fuse_key_manifest_svn : Used in FMC validation to make sure that the version number is good. - fuse_runtime_svn : Used in RT validation to make sure that the runtime image's version number is good. - The SOC has written the data to the mailbox. - The SOC has written the data length in the DLEN mailbox register. @@ -1053,7 +1050,7 @@ Compare the computed hash with the hash specified in the RT TOC. - Alias FMC Public MLDSA Key. - Digest of the FMC part of the image. - Digest of the ECC and LMS or MLDSA owner public keys portion of preamble. - - FMC SVN. + - FW SVN. - ROM Cold Boot Status. - FMC Entry Point. - ECC Vendor public key index. diff --git a/rom/dev/doc/error-attribution.md b/rom/dev/doc/error-attribution.md index 2ab9b22050..c871f3509b 100644 --- a/rom/dev/doc/error-attribution.md +++ b/rom/dev/doc/error-attribution.md @@ -91,15 +91,11 @@ Verifier Library | IMAGE_VERIFIER_ERR_FMC_LOAD_ADDR_INVALID Verifier Library | IMAGE_VERIFIER_ERR_FMC_LOAD_ADDR_UNALIGNED | 0x000b0022 Verifier Library | IMAGE_VERIFIER_ERR_FMC_ENTRY_POINT_INVALID | 0x000b0023 Verifier Library | IMAGE_VERIFIER_ERR_FMC_ENTRY_POINT_UNALIGNED | 0x000b0024 -Verifier Library | IMAGE_VERIFIER_ERR_FMC_SVN_GREATER_THAN_MAX_SUPPORTED | 0x000b0025 -Verifier Library | IMAGE_VERIFIER_ERR_FMC_SVN_LESS_THAN_MIN_SUPPORTED | 0x000b0026 -Verifier Library | IMAGE_VERIFIER_ERR_FMC_SVN_LESS_THAN_FUSE | 0x000b0027 Verifier Library | IMAGE_VERIFIER_ERR_RUNTIME_LOAD_ADDR_INVALID | 0x000b0028 Verifier Library | IMAGE_VERIFIER_ERR_RUNTIME_LOAD_ADDR_UNALIGNED | 0x000b0029 Verifier Library | IMAGE_VERIFIER_ERR_RUNTIME_ENTRY_POINT_INVALID | 0x000b002a Verifier Library | IMAGE_VERIFIER_ERR_RUNTIME_ENTRY_POINT_UNALIGNED | 0x000b002b Verifier Library | IMAGE_VERIFIER_ERR_RUNTIME_SVN_GREATER_THAN_MAX_SUPPORTED | 0x000b002c -Verifier Library | IMAGE_VERIFIER_ERR_RUNTIME_SVN_LESS_THAN_MIN_SUPPORTED | 0x000b002d Verifier Library | IMAGE_VERIFIER_ERR_RUNTIME_SVN_LESS_THAN_FUSE | 0x000b002e Verifier Library | IMAGE_VERIFIER_ERR_IMAGE_LEN_MORE_THAN_BUNDLE_SIZE | 0x000b002f Verifier Library | IMAGE_VERIFIER_ERR_VENDOR_LMS_PUB_KEY_INDEX_MISMATCH | 0x000b0030 @@ -211,15 +207,11 @@ Verifier Library | IMAGE_VERIFIER_ERR_FMC_LOAD_ADDR_INVALID Verifier Library | IMAGE_VERIFIER_ERR_FMC_LOAD_ADDR_UNALIGNED | 0x000b0022 Verifier Library | IMAGE_VERIFIER_ERR_FMC_ENTRY_POINT_INVALID | 0x000b0023 Verifier Library | IMAGE_VERIFIER_ERR_FMC_ENTRY_POINT_UNALIGNED | 0x000b0024 -Verifier Library | IMAGE_VERIFIER_ERR_FMC_SVN_GREATER_THAN_MAX_SUPPORTED | 0x000b0025 -Verifier Library | IMAGE_VERIFIER_ERR_FMC_SVN_LESS_THAN_MIN_SUPPORTED | 0x000b0026 -Verifier Library | IMAGE_VERIFIER_ERR_FMC_SVN_LESS_THAN_FUSE | 0x000b0027 Verifier Library | IMAGE_VERIFIER_ERR_RUNTIME_LOAD_ADDR_INVALID | 0x000b0028 Verifier Library | IMAGE_VERIFIER_ERR_RUNTIME_LOAD_ADDR_UNALIGNED | 0x000b0029 Verifier Library | IMAGE_VERIFIER_ERR_RUNTIME_ENTRY_POINT_INVALID | 0x000b002a Verifier Library | IMAGE_VERIFIER_ERR_RUNTIME_ENTRY_POINT_UNALIGNED | 0x000b002b Verifier Library | IMAGE_VERIFIER_ERR_RUNTIME_SVN_GREATER_THAN_MAX_SUPPORTED | 0x000b002c -Verifier Library | IMAGE_VERIFIER_ERR_RUNTIME_SVN_LESS_THAN_MIN_SUPPORTED | 0x000b002d Verifier Library | IMAGE_VERIFIER_ERR_RUNTIME_SVN_LESS_THAN_FUSE | 0x000b002e Verifier Library | IMAGE_VERIFIER_ERR_IMAGE_LEN_MORE_THAN_BUNDLE_SIZE | 0x000b002f Verifier Library | IMAGE_VERIFIER_ERR_VENDOR_LMS_PUB_KEY_INDEX_MISMATCH | 0x000b0030 diff --git a/rom/dev/doc/test-coverage/test-coverage.md b/rom/dev/doc/test-coverage/test-coverage.md index 85b1801763..9477b13a3f 100644 --- a/rom/dev/doc/test-coverage/test-coverage.md +++ b/rom/dev/doc/test-coverage/test-coverage.md @@ -37,8 +37,6 @@ Test Scenario| Test Name | ROM Error Code Check if FMC entry point is within ICCM range | **test_fmc_invalid_entry_point_before_iccm** | IMAGE_VERIFIER_ERR_FMC_ENTRY_POINT_INVALID Check if FMC entry point is within ICCM range | **test_fmc_invalid_entry_point_after_iccm** | IMAGE_VERIFIER_ERR_FMC_ENTRY_POINT_INVALID Check if FMC entry point is DWORD aligned | **test_fmc_entry_point_unaligned** | IMAGE_VERIFIER_ERR_FMC_ENTRY_POINT_UNALIGNED - Check if FMC SVN is greater than max (32) | **test_fmc_svn_greater_than_32** | IMAGE_VERIFIER_ERR_FMC_SVN_GREATER_THAN_MAX_SUPPORTED - Check if FMC SVN is less than fuse svn | **test_fmc_svn_less_than_fuse_svn** | IMAGE_VERIFIER_ERR_FMC_SVN_LESS_THAN_FUSE Check if RT size if 0 | **test_toc_rt_size_zero** | IMAGE_VERIFIER_ERR_RUNTIME_SIZE_ZERO Check if manifest.rt_toc.digest matches Runtime image digest | **test_runtime_digest_mismatch** | IMAGE_VERIFIER_ERR_RUNTIME_DIGEST_MISMATCH Check if RT load address is within ICCM range | **test_runtime_invalid_load_addr_before_iccm** | IMAGE_VERIFIER_ERR_RUNTIME_LOAD_ADDR_INVALID diff --git a/rom/dev/src/flow/cold_reset/fmc_alias.rs b/rom/dev/src/flow/cold_reset/fmc_alias.rs index b466270ec9..19f754b3d0 100644 --- a/rom/dev/src/flow/cold_reset/fmc_alias.rs +++ b/rom/dev/src/flow/cold_reset/fmc_alias.rs @@ -186,7 +186,7 @@ impl FmcAliasLayer { let flags = Self::make_flags(env.soc_ifc.lifecycle(), env.soc_ifc.debug_locked()); let svn = env.data_vault.fmc_svn() as u8; - let fuse_svn = fw_proc_info.fmc_effective_fuse_svn as u8; + let fuse_svn = fw_proc_info.effective_fuse_svn as u8; let mut fuse_info_digest = Array4x12::default(); let mut hasher = env.sha384.digest_init()?; diff --git a/rom/dev/src/flow/cold_reset/fw_processor.rs b/rom/dev/src/flow/cold_reset/fw_processor.rs index 0b6870d141..112163193c 100644 --- a/rom/dev/src/flow/cold_reset/fw_processor.rs +++ b/rom/dev/src/flow/cold_reset/fw_processor.rs @@ -47,7 +47,7 @@ pub struct FwProcInfo { pub fmc_cert_valid_not_after: NotAfter, - pub fmc_effective_fuse_svn: u32, + pub effective_fuse_svn: u32, pub owner_pub_keys_digest_in_fuses: bool, @@ -148,7 +148,7 @@ impl FirmwareProcessor { Ok(FwProcInfo { fmc_cert_valid_not_before: nb, fmc_cert_valid_not_after: nf, - fmc_effective_fuse_svn: info.fmc.effective_fuse_svn, + effective_fuse_svn: info.effective_fuse_svn, owner_pub_keys_digest_in_fuses: info.owner_pub_keys_digest_in_fuses, pqc_verify_config: info.pqc_verify_config as u8, }) @@ -390,8 +390,10 @@ impl FirmwareProcessor { let info = verifier.verify(manifest, img_bundle_sz, ResetReason::ColdReset)?; cprintln!( - "[fwproc] Img verified w/ Vendor ECC Key Idx {}", + "[fwproc] Img verified w/ Vendor ECC Key Idx {}, with SVN {} and effective fuse SVN {}", info.vendor_ecc_pub_key_idx, + info.fw_svn, + info.effective_fuse_svn, ); report_boot_status(FwProcessorImageVerificationComplete.into()); Ok(info) @@ -430,42 +432,43 @@ impl FirmwareProcessor { log_fuse_data( log, FuseLogEntryId::ManifestFmcSvn, - log_info.fmc_log_info.manifest_svn.as_bytes(), + log_info.fw_log_info.manifest_svn.as_bytes(), )?; // Log ManifestReserved0 log_fuse_data( log, FuseLogEntryId::ManifestReserved0, - log_info.fmc_log_info.reserved.as_bytes(), + log_info.fw_log_info.reserved.as_bytes(), )?; - // Log FuseFmcSvn + // Log DeprecatedFuseFmcSvn (which is now the same as FuseRtSvn) + #[allow(deprecated)] log_fuse_data( log, - FuseLogEntryId::FuseFmcSvn, - log_info.fmc_log_info.fuse_svn.as_bytes(), + FuseLogEntryId::_DeprecatedFuseFmcSvn, + log_info.fw_log_info.fuse_svn.as_bytes(), )?; // Log ManifestRtSvn log_fuse_data( log, FuseLogEntryId::ManifestRtSvn, - log_info.rt_log_info.manifest_svn.as_bytes(), + log_info.fw_log_info.manifest_svn.as_bytes(), )?; // Log ManifestReserved1 log_fuse_data( log, FuseLogEntryId::ManifestReserved1, - log_info.rt_log_info.reserved.as_bytes(), + log_info.fw_log_info.reserved.as_bytes(), )?; // Log FuseRtSvn log_fuse_data( log, FuseLogEntryId::FuseRtSvn, - log_info.rt_log_info.fuse_svn.as_bytes(), + log_info.fw_log_info.fuse_svn.as_bytes(), )?; // Log VendorLmsPubKeyIndex @@ -540,7 +543,7 @@ impl FirmwareProcessor { ) { data_vault.write_cold_reset_entry48(ColdResetEntry48::FmcTci, &info.fmc.digest.into()); - data_vault.write_cold_reset_entry4(ColdResetEntry4::FmcSvn, info.fmc.svn); + data_vault.write_cold_reset_entry4(ColdResetEntry4::FmcSvn, info.fw_svn); data_vault.write_cold_reset_entry4(ColdResetEntry4::FmcEntryPoint, info.fmc.entry_point); @@ -563,7 +566,7 @@ impl FirmwareProcessor { data_vault.write_warm_reset_entry48(WarmResetEntry48::RtTci, &info.runtime.digest.into()); - data_vault.write_warm_reset_entry4(WarmResetEntry4::RtSvn, info.runtime.svn); + data_vault.write_warm_reset_entry4(WarmResetEntry4::RtSvn, info.fw_svn); data_vault.write_warm_reset_entry4(WarmResetEntry4::RtEntryPoint, info.runtime.entry_point); diff --git a/rom/dev/src/flow/fake.rs b/rom/dev/src/flow/fake.rs index e79fe95d93..b8a8f7dc7d 100644 --- a/rom/dev/src/flow/fake.rs +++ b/rom/dev/src/flow/fake.rs @@ -340,12 +340,7 @@ impl<'a, 'b> ImageVerificationEnv for &mut FakeRomImageVerificationEnv<'a, 'b> { self.data_vault.fmc_tci().into() } - // Get Fuse FMC Key Manifest SVN - fn fmc_fuse_svn(&self) -> u32 { - self.soc_ifc.fuse_bank().fmc_fuse_svn() - } - - // Get Runtime fuse SVN + // Get Fuse FW Manifest SVN fn runtime_fuse_svn(&self) -> u32 { self.soc_ifc.fuse_bank().runtime_fuse_svn() } diff --git a/rom/dev/src/flow/update_reset.rs b/rom/dev/src/flow/update_reset.rs index 06269bbf36..2f453feb8d 100644 --- a/rom/dev/src/flow/update_reset.rs +++ b/rom/dev/src/flow/update_reset.rs @@ -215,7 +215,7 @@ impl UpdateResetFlow { fn populate_data_vault(data_vault: &mut DataVault, info: &ImageVerificationInfo) { data_vault.write_warm_reset_entry48(WarmResetEntry48::RtTci, &info.runtime.digest.into()); - data_vault.write_warm_reset_entry4(WarmResetEntry4::RtSvn, info.runtime.svn); + data_vault.write_warm_reset_entry4(WarmResetEntry4::RtSvn, info.fw_svn); data_vault.write_warm_reset_entry4(WarmResetEntry4::RtEntryPoint, info.runtime.entry_point); diff --git a/rom/dev/src/pcr.rs b/rom/dev/src/pcr.rs index 41cbb2b77e..54d3d02b05 100644 --- a/rom/dev/src/pcr.rs +++ b/rom/dev/src/pcr.rs @@ -84,7 +84,7 @@ pub(crate) fn extend_pcrs( env.soc_ifc.fuse_bank().anti_rollback_disable() as u8, env.data_vault.ecc_vendor_pk_index() as u8, env.data_vault.fmc_svn() as u8, - info.fmc.effective_fuse_svn as u8, + info.effective_fuse_svn as u8, env.data_vault.lms_vendor_pk_index() as u8, info.pqc_verify_config as u8, info.owner_pub_keys_digest_in_fuses as u8, diff --git a/rom/dev/tests/rom_integration_tests/test_fmcalias_derivation.rs b/rom/dev/tests/rom_integration_tests/test_fmcalias_derivation.rs index a9e1373c1f..72a3079fca 100644 --- a/rom/dev/tests/rom_integration_tests/test_fmcalias_derivation.rs +++ b/rom/dev/tests/rom_integration_tests/test_fmcalias_derivation.rs @@ -163,6 +163,7 @@ fn test_pcr_log() { let image_options = ImageOptions { vendor_config: VENDOR_CONFIG_KEY_1, fmc_svn: FMC_SVN, + app_svn: FMC_SVN, ..Default::default() }; let image_bundle = caliptra_builder::build_and_sign_image( @@ -339,6 +340,7 @@ fn test_pcr_log_fmc_fuse_svn() { key_manifest_pk_hash: vendor_pubkey_digest, owner_pk_hash: owner_pubkey_digest, fmc_key_manifest_svn: FMC_FUSE_SVN, + runtime_svn: [0x3, 0, 0, 0], // TODO: add tooling to make this more ergonomic. ..Default::default() }; let rom = caliptra_builder::build_firmware_rom(firmware::rom_from_env()).unwrap(); @@ -358,6 +360,7 @@ fn test_pcr_log_fmc_fuse_svn() { let image_options = ImageOptions { vendor_config: VENDOR_CONFIG_KEY_1, fmc_svn: FMC_SVN, + app_svn: FMC_SVN, ..Default::default() }; let image_bundle = caliptra_builder::build_and_sign_image( @@ -478,6 +481,7 @@ fn test_pcr_log_across_update_reset() { let fuses = Fuses { anti_rollback_disable: false, fmc_key_manifest_svn: FMC_FUSE_SVN, + runtime_svn: [1, 0, 0, 0], key_manifest_pk_hash: vendor_pubkey_digest, owner_pk_hash: owner_pubkey_digest, ..Default::default() @@ -499,6 +503,7 @@ fn test_pcr_log_across_update_reset() { let image_options = ImageOptions { vendor_config: VENDOR_CONFIG_KEY_1, fmc_svn: FMC_SVN, + app_svn: FMC_SVN, ..Default::default() }; let image_bundle = caliptra_builder::build_and_sign_image( @@ -572,6 +577,7 @@ fn test_pcr_log_across_update_reset() { } #[test] +#[allow(deprecated)] fn test_fuse_log() { const FMC_SVN: u32 = 4; @@ -660,11 +666,14 @@ fn test_fuse_log() { ); assert_eq!(fuse_log_entry.log_data[0], 0); - // Validate the FuseFmcSvn + // Validate the _DeprecatedFuseFmcSvn fuse_log_entry_offset += core::mem::size_of::(); let fuse_log_entry = FuseLogEntry::read_from_prefix(fuse_entry_arr[fuse_log_entry_offset..].as_bytes()).unwrap(); - assert_eq!(fuse_log_entry.entry_id, FuseLogEntryId::FuseFmcSvn as u32); + assert_eq!( + fuse_log_entry.entry_id, + FuseLogEntryId::_DeprecatedFuseFmcSvn as u32 + ); assert_eq!(fuse_log_entry.log_data[0], FMC_SVN); // Validate the ManifestRtSvn diff --git a/rom/dev/tests/rom_integration_tests/test_image_validation.rs b/rom/dev/tests/rom_integration_tests/test_image_validation.rs index db0f915aaf..89618df6e8 100644 --- a/rom/dev/tests/rom_integration_tests/test_image_validation.rs +++ b/rom/dev/tests/rom_integration_tests/test_image_validation.rs @@ -1348,77 +1348,6 @@ fn test_fmc_entry_point_unaligned() { ); } -#[test] -fn test_fmc_svn_greater_than_32() { - let gen = ImageGenerator::new(Crypto::default()); - let image_bundle = helpers::build_image_bundle(ImageOptions::default()); - let vendor_pubkey_digest = gen - .vendor_pubkey_digest(&image_bundle.manifest.preamble) - .unwrap(); - - let fuses = caliptra_hw_model::Fuses { - life_cycle: DeviceLifecycle::Manufacturing, - anti_rollback_disable: false, - key_manifest_pk_hash: vendor_pubkey_digest, - ..Default::default() - }; - - let image_options = ImageOptions { - fmc_svn: 33, - ..Default::default() - }; - - let (mut hw, image_bundle) = helpers::build_hw_model_and_image_bundle(fuses, image_options); - assert_eq!( - ModelError::MailboxCmdFailed( - CaliptraError::IMAGE_VERIFIER_ERR_FMC_SVN_GREATER_THAN_MAX_SUPPORTED.into() - ), - hw.upload_firmware(&image_bundle.to_bytes().unwrap()) - .unwrap_err() - ); - - assert_eq!( - hw.soc_ifc().cptra_boot_status().read(), - u32::from(FwProcessorManifestLoadComplete) - ); -} - -#[test] -fn test_fmc_svn_less_than_fuse_svn() { - let gen = ImageGenerator::new(Crypto::default()); - let image_bundle = helpers::build_image_bundle(ImageOptions::default()); - let vendor_pubkey_digest = gen - .vendor_pubkey_digest(&image_bundle.manifest.preamble) - .unwrap(); - - let fuses = caliptra_hw_model::Fuses { - life_cycle: DeviceLifecycle::Manufacturing, - anti_rollback_disable: false, - key_manifest_pk_hash: vendor_pubkey_digest, - fmc_key_manifest_svn: 0b11, // fuse svn = 2 - ..Default::default() - }; - - let image_options = ImageOptions { - fmc_svn: 1, - ..Default::default() - }; - - let (mut hw, image_bundle) = helpers::build_hw_model_and_image_bundle(fuses, image_options); - assert_eq!( - ModelError::MailboxCmdFailed(u32::from( - CaliptraError::IMAGE_VERIFIER_ERR_FMC_SVN_LESS_THAN_FUSE - )), - hw.upload_firmware(&image_bundle.to_bytes().unwrap()) - .unwrap_err() - ); - - assert_eq!( - hw.soc_ifc().cptra_boot_status().read(), - u32::from(FwProcessorManifestLoadComplete) - ); -} - #[test] fn test_toc_rt_size_zero() { let (mut hw, mut image_bundle) = diff --git a/rom/dev/tests/rom_integration_tests/test_warm_reset.rs b/rom/dev/tests/rom_integration_tests/test_warm_reset.rs index 19d45dfb03..2ddaeb1806 100644 --- a/rom/dev/tests/rom_integration_tests/test_warm_reset.rs +++ b/rom/dev/tests/rom_integration_tests/test_warm_reset.rs @@ -33,6 +33,7 @@ fn test_warm_reset_success() { &APP_WITH_UART, ImageOptions { fmc_svn: 9, + app_svn: 9, ..Default::default() }, ) @@ -56,6 +57,7 @@ fn test_warm_reset_success() { key_manifest_pk_hash: vendor_pk_desc_hash, owner_pk_hash: owner_pk_desc_hash, fmc_key_manifest_svn: 0b1111111, + runtime_svn: [0x7F, 0, 0, 0], // Equals 7 ..Default::default() }, fw_image: Some(&image.to_bytes().unwrap()), @@ -74,6 +76,7 @@ fn test_warm_reset_success() { key_manifest_pk_hash: vendor_pk_desc_hash, owner_pk_hash: owner_pk_desc_hash, fmc_key_manifest_svn: 0b1111111, + runtime_svn: [0x7F, 0, 0, 0], // Equals 7 ..Default::default() }); diff --git a/runtime/tests/runtime_integration_tests/test_info.rs b/runtime/tests/runtime_integration_tests/test_info.rs index 461fdee7f2..07745a793c 100644 --- a/runtime/tests/runtime_integration_tests/test_info.rs +++ b/runtime/tests/runtime_integration_tests/test_info.rs @@ -107,7 +107,7 @@ fn test_fw_info() { let info = get_fwinfo(&mut model); // Verify FW info assert_eq!(info.pl0_pauser, 0x1); - assert_eq!(info.fmc_manifest_svn, 5); + assert_eq!(info.fmc_manifest_svn, 10); assert_eq!(info.runtime_svn, 10); assert_eq!(info.min_runtime_svn, 10); // Verify revision (Commit ID) and digest of each component @@ -134,6 +134,7 @@ fn test_fw_info() { let info = get_fwinfo(&mut model); assert_eq!(info.runtime_svn, 20); assert_eq!(info.min_runtime_svn, 10); + assert_eq!(info.fmc_manifest_svn, 10); // Make image with older SVN. let mut image_opts5 = image_opts; @@ -149,12 +150,14 @@ fn test_fw_info() { let info = get_fwinfo(&mut model); assert_eq!(info.runtime_svn, 5); assert_eq!(info.min_runtime_svn, 5); + assert_eq!(info.fmc_manifest_svn, 10); // Go back to SVN 20 update_to(&mut model, &image20); let info = get_fwinfo(&mut model); assert_eq!(info.runtime_svn, 20); assert_eq!(info.min_runtime_svn, 5); + assert_eq!(info.fmc_manifest_svn, 10); } #[test] diff --git a/test/tests/caliptra_integration_tests/fake_collateral_boot_test.rs b/test/tests/caliptra_integration_tests/fake_collateral_boot_test.rs index b837701cef..811583c884 100755 --- a/test/tests/caliptra_integration_tests/fake_collateral_boot_test.rs +++ b/test/tests/caliptra_integration_tests/fake_collateral_boot_test.rs @@ -59,6 +59,7 @@ fn fake_boot_test() { &APP_WITH_UART, ImageOptions { fmc_svn: 9, + app_svn: 9, ..Default::default() }, ) @@ -81,6 +82,7 @@ fn fake_boot_test() { key_manifest_pk_hash: vendor_pk_desc_hash, owner_pk_hash: owner_pk_desc_hash, fmc_key_manifest_svn: 0b1111111, + runtime_svn: [0x7F, 0, 0, 0], // Equals 7 ..Default::default() }, fw_image: Some(&image.to_bytes().unwrap()), diff --git a/test/tests/caliptra_integration_tests/jtag_test.rs b/test/tests/caliptra_integration_tests/jtag_test.rs index 00535c1819..e3615b85d6 100644 --- a/test/tests/caliptra_integration_tests/jtag_test.rs +++ b/test/tests/caliptra_integration_tests/jtag_test.rs @@ -90,6 +90,7 @@ fn gdb_test() { &firmware::APP_WITH_UART, ImageOptions { fmc_svn: 9, + app_svn: 9, ..Default::default() }, ) diff --git a/test/tests/caliptra_integration_tests/smoke_test.rs b/test/tests/caliptra_integration_tests/smoke_test.rs index 7add7c142f..d915d24059 100644 --- a/test/tests/caliptra_integration_tests/smoke_test.rs +++ b/test/tests/caliptra_integration_tests/smoke_test.rs @@ -151,6 +151,7 @@ fn smoke_test() { &firmware::APP_WITH_UART, ImageOptions { fmc_svn: 9, + app_svn: 9, ..Default::default() }, ) @@ -164,6 +165,7 @@ fn smoke_test() { key_manifest_pk_hash: vendor_pk_desc_hash_words, owner_pk_hash: owner_pk_desc_hash_words, fmc_key_manifest_svn: 0b1111111, + runtime_svn: [0x7F, 0, 0, 0], // Equals 7 lms_verify: true, ..Default::default() }; @@ -461,7 +463,8 @@ fn smoke_test() { Some(DiceTcbInfo { vendor: None, model: None, - svn: Some(0x100), + // This is from the SVN in the image (9) + svn: Some(0x109), fwids: vec![DiceFwid { // RT hash_alg: asn1::oid!(2, 16, 840, 1, 101, 3, 4, 2, 2), @@ -559,6 +562,7 @@ fn smoke_test() { ImageOptions { fmc_version: 1, fmc_svn: 10, + app_svn: 10, app_version: 2, ..Default::default() }, @@ -611,7 +615,8 @@ fn smoke_test() { Some(DiceTcbInfo { vendor: None, model: None, - svn: Some(0x100), + // This is from the SVN in the image (10) + svn: Some(0x10A), fwids: vec![DiceFwid { // FMC hash_alg: asn1::oid!(2, 16, 840, 1, 101, 3, 4, 2, 2), diff --git a/test/tests/caliptra_integration_tests/warm_reset.rs b/test/tests/caliptra_integration_tests/warm_reset.rs index c793369829..eb6d6a8110 100644 --- a/test/tests/caliptra_integration_tests/warm_reset.rs +++ b/test/tests/caliptra_integration_tests/warm_reset.rs @@ -30,6 +30,7 @@ fn warm_reset_basic() { &APP_WITH_UART, ImageOptions { fmc_svn: 9, + app_svn: 9, ..Default::default() }, ) @@ -52,6 +53,7 @@ fn warm_reset_basic() { key_manifest_pk_hash: vendor_pk_desc_hash, owner_pk_hash: owner_pk_desc_hash, fmc_key_manifest_svn: 0b1111111, + runtime_svn: [0x7F, 0, 0, 0], // Equals 7 ..Default::default() }, fw_image: Some(&image.to_bytes().unwrap()), @@ -70,6 +72,7 @@ fn warm_reset_basic() { key_manifest_pk_hash: vendor_pk_desc_hash, owner_pk_hash: owner_pk_desc_hash, fmc_key_manifest_svn: 0b1111111, + runtime_svn: [0x7F, 0, 0, 0], // Equals 7 ..Default::default() }); @@ -91,6 +94,7 @@ fn warm_reset_during_fw_load() { &APP_WITH_UART, ImageOptions { fmc_svn: 9, + app_svn: 9, ..Default::default() }, ) @@ -113,6 +117,7 @@ fn warm_reset_during_fw_load() { key_manifest_pk_hash: vendor_pk_desc_hash, owner_pk_hash: owner_pk_desc_hash, fmc_key_manifest_svn: 0b1111111, + runtime_svn: [0x7F, 0, 0, 0], // Equals 7 ..Default::default() }, fw_image: None, @@ -142,6 +147,7 @@ fn warm_reset_during_fw_load() { key_manifest_pk_hash: vendor_pk_desc_hash, owner_pk_hash: owner_pk_desc_hash, fmc_key_manifest_svn: 0b1111111, + runtime_svn: [0x7F, 0, 0, 0], // Equals 7 ..Default::default() }); diff --git a/test/tests/fips_test_suite/README.md b/test/tests/fips_test_suite/README.md index 38085b0624..414ee0ffa8 100755 --- a/test/tests/fips_test_suite/README.md +++ b/test/tests/fips_test_suite/README.md @@ -72,7 +72,7 @@ Test hooks are needed to meet the following FIPS 140-3 test requirements: | kat_sha1_digest_failure_rom
kat_sha1_digest_mismatch_rom
kat_sha256_digest_failure_rom
kat_sha256_digest_mismatch_rom
kat_sha384_digest_failure_rom
kat_sha384_digest_mismatch_rom
kat_sha2_512_384acc_digest_start_op_failure_rom
kat_sha2_512_384acc_digest_failure_rom
kat_sha2_512_384acc_digest_mismatch_rom
kat_ecc384_signature_generate_failure_rom
kat_ecc384_signature_verify_failure_rom
kat_hmac384_failure_rom
kat_hmac384_tag_mismatch_rom
kat_lms_digest_mismatch_rom | TE10.07.03
TE10.08.03
TE10.09.03
TE10.10.01
TE10.10.02 | Enable the hook for triggering an error with the SHA1 KAT
Verify the correct error is returned
Verify we cannot utilize the associated functionality by proving we can't issues commands
Verify an undocumented attempt to clear the error fails
Clear the error with an approved method - restart Caliptra
Verify crypto operations using the engine can be performed | | kat_sha1_digest_failure_rt
kat_sha1_digest_mismatch_rt
kat_sha256_digest_failure_rt
kat_sha256_digest_mismatch_rt
kat_sha384_digest_failure_rt
kat_sha384_digest_mismatch_rt
kat_sha2_512_384acc_digest_start_op_failure_rt
kat_sha2_512_384acc_digest_failure_rt
kat_sha2_512_384acc_digest_mismatch_rt
kat_ecc384_signature_generate_failure_rt
kat_ecc384_signature_verify_failure_rt
kat_hmac384_failure_rt
kat_hmac384_tag_mismatch_rt
kat_lms_digest_mismatch_rt | TE10.07.03
TE10.08.03
TE10.09.03
TE10.10.01
TE10.10.02 | Boot to runtime
Enable the hook for triggering an error with the KAT
Issue self test command
Verify the correct error is returned
Verify we cannot utilize the associated functionality by proving we can't issues commands
Verify an undocumented attempt to clear the error fails
Clear the error with an approved method - restart Caliptra
Verify crypto operations using the engine can be performed | | integrity_check_failure_rom | TE10.07.03
TE10.08.03
TE10.09.03
TE10.10.01
TE10.10.02 | Corrupt ROM integrity check hash
Verify the correct error is returned
Verify we cannot issue commands
Verify an undocumented attempt to clear the error fails
(Cannot clear this error without changing ROM which would invlove recreating the whole platform with a new ROM and therefore isn't really a continuation of this test) | -| fw_load_error_manifest_marker_mismatch
fw_load_error_manifest_size_mismatch
fw_load_error_vendor_pub_key_digest_invalid
fw_load_error_vendor_pub_key_digest_failure
fw_load_error_vendor_pub_key_digest_mismatch
fw_load_error_owner_pub_key_digest_failure
fw_load_error_owner_pub_key_digest_mismatch
fw_load_error_vendor_ecc_pub_key_index_out_of_bounds
fw_load_error_vendor_ecc_pub_key_revoked
fw_load_error_header_digest_failure
fw_load_error_vendor_ecc_verify_failure
fw_load_error_vendor_ecc_signature_invalid
fw_load_error_vendor_ecc_pub_key_index_mismatch
fw_load_error_owner_ecc_verify_failure
fw_load_error_owner_ecc_signature_invalid
fw_load_error_toc_entry_count_invalid
fw_load_error_toc_digest_failure
fw_load_error_toc_digest_mismatch
fw_load_error_fmc_digest_failure
fw_load_error_fmc_digest_mismatch
fw_load_error_runtime_digest_failure
fw_load_error_runtime_digest_mismatch
fw_load_error_fmc_runtime_overlap
fw_load_error_fmc_runtime_incorrect_order
fw_load_error_owner_ecc_pub_key_invalid_arg
fw_load_error_owner_ecc_signature_invalid_arg
fw_load_error_vendor_pub_key_digest_invalid_arg
fw_load_error_vendor_ecc_signature_invalid_arg
fw_load_error_update_reset_owner_digest_failure
fw_load_error_update_reset_vendor_ecc_pub_key_idx_mismatch
fw_load_error_update_reset_fmc_digest_mismatch
fw_load_error_fmc_load_addr_invalid
fw_load_error_fmc_load_addr_unaligned
fw_load_error_fmc_entry_point_invalid
fw_load_error_fmc_entry_point_unaligned
fw_load_error_fmc_svn_greater_than_max_supported
fw_load_error_fmc_svn_less_than_fuse
fw_load_error_runtime_load_addr_invalid
fw_load_error_runtime_load_addr_unaligned
fw_load_error_runtime_entry_point_invalid
fw_load_error_runtime_entry_point_unaligned
fw_load_error_runtime_svn_greater_than_max_supported
fw_load_error_runtime_svn_less_than_fuse
fw_load_error_image_len_more_than_bundle_size
fw_load_error_vendor_lms_pub_key_index_mismatch
fw_load_error_vendor_lms_verify_failure
fw_load_error_vendor_lms_pub_key_index_out_of_bounds
fw_load_error_vendor_lms_signature_invalid
fw_load_error_fmc_runtime_load_addr_overlap
fw_load_error_owner_lms_verify_failure
fw_load_error_owner_lms_signature_invalid
fw_load_error_vendor_lms_pub_key_revoked
fw_load_error_fmc_size_zero
fw_load_error_runtime_size_zero
fw_load_error_update_reset_vendor_lms_pub_key_idx_mismatch
fw_load_error_fmc_load_address_image_size_arithmetic_overflow
fw_load_error_runtime_load_address_image_size_arithmetic_overflow
fw_load_error_toc_entry_range_arithmetic_overflow | TE10.07.03
TE10.08.03
TE10.09.03
TE10.10.01
TE10.10.02 | Make change related to error in fw bundle or fuses
Attempt to load the FW
Verify the correct error is returned
Verify we cannot utilize RT FW by sending a message
Verify an undocumented attempt to clear the error fails
Clear the error with an approved method - restart Caliptra
Verify we can utilize RT FW by sending a message
NOTE: This isn't a specific crypto engine but this still counts as a self test, some of the requirements are tailored toward crypto engines. | +| fw_load_error_manifest_marker_mismatch
fw_load_error_manifest_size_mismatch
fw_load_error_vendor_pub_key_digest_invalid
fw_load_error_vendor_pub_key_digest_failure
fw_load_error_vendor_pub_key_digest_mismatch
fw_load_error_owner_pub_key_digest_failure
fw_load_error_owner_pub_key_digest_mismatch
fw_load_error_vendor_ecc_pub_key_index_out_of_bounds
fw_load_error_vendor_ecc_pub_key_revoked
fw_load_error_header_digest_failure
fw_load_error_vendor_ecc_verify_failure
fw_load_error_vendor_ecc_signature_invalid
fw_load_error_vendor_ecc_pub_key_index_mismatch
fw_load_error_owner_ecc_verify_failure
fw_load_error_owner_ecc_signature_invalid
fw_load_error_toc_entry_count_invalid
fw_load_error_toc_digest_failure
fw_load_error_toc_digest_mismatch
fw_load_error_fmc_digest_failure
fw_load_error_fmc_digest_mismatch
fw_load_error_runtime_digest_failure
fw_load_error_runtime_digest_mismatch
fw_load_error_fmc_runtime_overlap
fw_load_error_fmc_runtime_incorrect_order
fw_load_error_owner_ecc_pub_key_invalid_arg
fw_load_error_owner_ecc_signature_invalid_arg
fw_load_error_vendor_pub_key_digest_invalid_arg
fw_load_error_vendor_ecc_signature_invalid_arg
fw_load_error_update_reset_owner_digest_failure
fw_load_error_update_reset_vendor_ecc_pub_key_idx_mismatch
fw_load_error_update_reset_fmc_digest_mismatch
fw_load_error_fmc_load_addr_invalid
fw_load_error_fmc_load_addr_unaligned
fw_load_error_fmc_entry_point_invalid
fw_load_error_fmc_entry_point_unaligned
fw_load_error_runtime_load_addr_invalid
fw_load_error_runtime_load_addr_unaligned
fw_load_error_runtime_entry_point_invalid
fw_load_error_runtime_entry_point_unaligned
fw_load_error_runtime_svn_greater_than_max_supported
fw_load_error_runtime_svn_less_than_fuse
fw_load_error_image_len_more_than_bundle_size
fw_load_error_vendor_lms_pub_key_index_mismatch
fw_load_error_vendor_lms_verify_failure
fw_load_error_vendor_lms_pub_key_index_out_of_bounds
fw_load_error_vendor_lms_signature_invalid
fw_load_error_fmc_runtime_load_addr_overlap
fw_load_error_owner_lms_verify_failure
fw_load_error_owner_lms_signature_invalid
fw_load_error_vendor_lms_pub_key_revoked
fw_load_error_fmc_size_zero
fw_load_error_runtime_size_zero
fw_load_error_update_reset_vendor_lms_pub_key_idx_mismatch
fw_load_error_fmc_load_address_image_size_arithmetic_overflow
fw_load_error_runtime_load_address_image_size_arithmetic_overflow
fw_load_error_toc_entry_range_arithmetic_overflow | TE10.07.03
TE10.08.03
TE10.09.03
TE10.10.01
TE10.10.02 | Make change related to error in fw bundle or fuses
Attempt to load the FW
Verify the correct error is returned
Verify we cannot utilize RT FW by sending a message
Verify an undocumented attempt to clear the error fails
Clear the error with an approved method - restart Caliptra
Verify we can utilize RT FW by sending a message
NOTE: This isn't a specific crypto engine but this still counts as a self test, some of the requirements are tailored toward crypto engines. | | key_pair_consistency_error | TE10.35.04 | Enable hook to corrupt key pair during generation
Trigger the keypair generation (Just boot and allow DICE flow to start?)
Verify the correct error for key pair inconsistency is generated | | fw_load_blank_pub_keys
fw_load_blank_pub_key_hashes | TE10.37.09 | Clear the public keys/hashes from the FW image
Start the FW load
Verify the correct error is returned | | fips_self_test_rom
fips_self_test_rt | TE10.53.02 | Execute FIPS self test command
Verify the output is correct and the self tests pass | diff --git a/test/tests/fips_test_suite/fw_load.rs b/test/tests/fips_test_suite/fw_load.rs index 0d7192bb5b..3821bb7c24 100755 --- a/test/tests/fips_test_suite/fw_load.rs +++ b/test/tests/fips_test_suite/fw_load.rs @@ -792,65 +792,6 @@ fn fw_load_error_fmc_entry_point_unaligned() { ); } -#[test] -fn fw_load_error_fmc_svn_greater_than_max_supported() { - // Generate image - let image_options = ImageOptions { - fmc_svn: 33, - ..Default::default() - }; - let fw_image = build_fw_image(image_options); - - // Set fuses - let gen = ImageGenerator::new(Crypto::default()); - let vendor_pubkey_digest = gen - .vendor_pubkey_digest(&fw_image.manifest.preamble) - .unwrap(); - let fuses = caliptra_hw_model::Fuses { - life_cycle: DeviceLifecycle::Manufacturing, - anti_rollback_disable: false, - key_manifest_pk_hash: vendor_pubkey_digest, - ..Default::default() - }; - - fw_load_error_flow( - Some(fw_image), - Some(fuses), - CaliptraError::IMAGE_VERIFIER_ERR_FMC_SVN_GREATER_THAN_MAX_SUPPORTED.into(), - ); -} - -// IMAGE_VERIFIER_ERR_FMC_SVN_LESS_THAN_MIN_SUPPORTED is defined but never used in the code (svn is a u32) - -#[test] -fn fw_load_error_fmc_svn_less_than_fuse() { - // Generate image - let image_options = ImageOptions { - fmc_svn: 1, - ..Default::default() - }; - let fw_image = build_fw_image(image_options); - - // Set fuses - let gen = ImageGenerator::new(Crypto::default()); - let vendor_pubkey_digest = gen - .vendor_pubkey_digest(&fw_image.manifest.preamble) - .unwrap(); - let fuses = caliptra_hw_model::Fuses { - life_cycle: DeviceLifecycle::Manufacturing, - anti_rollback_disable: false, - key_manifest_pk_hash: vendor_pubkey_digest, - fmc_key_manifest_svn: 0b11, // fuse svn = 2 - ..Default::default() - }; - - fw_load_error_flow( - Some(fw_image), - Some(fuses), - CaliptraError::IMAGE_VERIFIER_ERR_FMC_SVN_LESS_THAN_FUSE.into(), - ); -} - #[test] fn fw_load_error_runtime_load_addr_invalid() { // Generate image From dc558d2656f14d8cc4c9db5f8a61918dcbd47981 Mon Sep 17 00:00:00 2001 From: Anthony Rocha <116300062+rusty1968@users.noreply.github.com> Date: Wed, 20 Nov 2024 08:51:50 -0800 Subject: [PATCH 28/51] Miscellaneous fixes to the Soc Manager API (#1804) - Add hw-1.0 feature switch for support of hw-1.0 RTL. - Validate length of slice passed as an argument. (cherry picked from commit 51bfb5cc0928232bdc555be15f1e4fef3f191d21) --- api/src/soc_mgr.rs | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/api/src/soc_mgr.rs b/api/src/soc_mgr.rs index b322ae38a7..2693aab6ac 100644 --- a/api/src/soc_mgr.rs +++ b/api/src/soc_mgr.rs @@ -13,6 +13,8 @@ use core::mem; use ureg::MmioMut; use zerocopy::{AsBytes, FromBytes}; +pub const NUM_PAUSERS: usize = 5; + /// Implementation of the `SocManager` trait for a `RealSocManager`. /// /// # Example @@ -77,6 +79,10 @@ pub trait SocManager { /// Set up valid PAUSERs for mailbox access. fn setup_mailbox_users(&mut self, apb_pausers: &[u32]) -> Result<(), CaliptraApiError> { + if apb_pausers.len() > NUM_PAUSERS { + return Err(CaliptraApiError::UnableToSetPauser); + } + for (idx, apb_pauser) in apb_pausers.iter().enumerate() { if self .soc_ifc() From 0076a1b9cc15cd77b981d79db6c91e142bc7d12f Mon Sep 17 00:00:00 2001 From: Nick Quarton <139178705+nquarton@users.noreply.github.com> Date: Thu, 21 Nov 2024 10:48:11 -0800 Subject: [PATCH 29/51] Fix to FPGA pauser_sigbus test (#1810) (cherry picked from commit 873c3c2abe2703ffec02e1ced3a2d1b9a70a23c2) --- hw-model/Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/hw-model/Cargo.toml b/hw-model/Cargo.toml index d0c716c9e9..8d3e0d6335 100644 --- a/hw-model/Cargo.toml +++ b/hw-model/Cargo.toml @@ -45,4 +45,4 @@ nix.workspace = true [[bin]] name = "fpga_realtime_mbox_pauser" path = "src/bin/fpga_realtime_mbox_pauser.rs" -required-features = ["fpga_realtime", "itrng"] +required-features = ["fpga_realtime"] From f22cbcab3cac990ab288e676fa4a5781ec1d821c Mon Sep 17 00:00:00 2001 From: Jeff Andersen Date: Mon, 25 Nov 2024 15:08:38 -0800 Subject: [PATCH 30/51] Move min-SVN calculation from FMC to ROM. (#1812) This change moves the min-SVN check from FMC to ROM. --- drivers/src/hand_off.rs | 13 ----- fmc/src/flow/rt_alias.rs | 24 --------- fmc/src/hand_off.rs | 56 --------------------- rom/dev/src/flow/cold_reset/fw_processor.rs | 1 + rom/dev/src/flow/update_reset.rs | 4 ++ rom/dev/src/lock.rs | 4 +- 6 files changed, 8 insertions(+), 94 deletions(-) diff --git a/drivers/src/hand_off.rs b/drivers/src/hand_off.rs index 96e813fc47..eb59f6a39c 100644 --- a/drivers/src/hand_off.rs +++ b/drivers/src/hand_off.rs @@ -293,19 +293,13 @@ pub struct FirmwareHandoffTable { pub rtalias_tbs_size: u16, /// Maximum value RT FW SVN can take. - #[cfg(any(feature = "fmc", feature = "runtime"))] pub rt_hash_chain_max_svn: u16, /// Index of RT hash chain value in the Key Vault. - #[cfg(any(feature = "fmc", feature = "runtime"))] pub rt_hash_chain_kv_hdl: HandOffDataHandle, /// Reserved for future use. - #[cfg(any(feature = "fmc", feature = "runtime"))] pub reserved: [u8; 1632], - - #[cfg(not(any(feature = "fmc", feature = "runtime")))] - pub reserved: [u8; 1638], } impl Default for FirmwareHandoffTable { @@ -347,16 +341,9 @@ impl Default for FirmwareHandoffTable { idev_dice_mldsa_pub_key_load_addr: 0, rom_info_addr: RomAddr::new(FHT_INVALID_ADDRESS), rtalias_tbs_size: 0, - - #[cfg(any(feature = "fmc", feature = "runtime"))] rt_hash_chain_max_svn: 0, - #[cfg(any(feature = "fmc", feature = "runtime"))] rt_hash_chain_kv_hdl: HandOffDataHandle(0), - #[cfg(any(feature = "fmc", feature = "runtime"))] reserved: [0u8; 1632], - - #[cfg(not(any(feature = "fmc", feature = "runtime")))] - reserved: [0u8; 1638], } } } diff --git a/fmc/src/flow/rt_alias.rs b/fmc/src/flow/rt_alias.rs index 1e51ce9e72..816316b2b7 100644 --- a/fmc/src/flow/rt_alias.rs +++ b/fmc/src/flow/rt_alias.rs @@ -111,9 +111,6 @@ impl RtAliasLayer { .set_pcr_lock(caliptra_common::RT_FW_JOURNEY_PCR); cprintln!("[alias rt] Lock RT PCRs Done"); - cprintln!("[alias rt] Populate DV"); - Self::populate_dv(env)?; - cprintln!("[alias rt] Populate DV Done"); report_boot_status(crate::FmcBootStatus::RtMeasurementComplete as u32); // Retrieve Dice Input Layer from Hand Off and Derive Key @@ -183,27 +180,6 @@ impl RtAliasLayer { } } - /// Populate Data Vault - /// - /// # Arguments - /// - /// * `env` - FMC Environment - /// * `hand_off` - HandOff - #[cfg_attr(not(feature = "no-cfi"), cfi_impl_fn)] - pub fn populate_dv(env: &mut FmcEnv) -> CaliptraResult<()> { - let rt_svn = HandOff::rt_svn(env); - let reset_reason = env.soc_ifc.reset_reason(); - - let rt_min_svn = if reset_reason == ResetReason::ColdReset { - cfi_assert_eq(reset_reason, ResetReason::ColdReset); - rt_svn - } else { - core::cmp::min(rt_svn, HandOff::rt_min_svn(env)) - }; - - HandOff::set_and_lock_rt_min_svn(env, rt_min_svn) - } - fn get_cert_validity_info( manifest: &caliptra_image_types::ImageManifest, ) -> (NotBefore, NotAfter) { diff --git a/fmc/src/hand_off.rs b/fmc/src/hand_off.rs index 6033fcdc1a..5e1e77e6ca 100644 --- a/fmc/src/hand_off.rs +++ b/fmc/src/hand_off.rs @@ -196,50 +196,6 @@ impl HandOff { } } - /// Retrieve runtime minimum SVN. - pub fn rt_min_svn(env: &FmcEnv) -> u32 { - let ds: DataStore = - Self::fht(env) - .rt_min_svn_dv_hdl - .try_into() - .unwrap_or_else(|e: CaliptraError| { - cprintln!("[fht] Invalid RT Min SVN handle"); - handle_fatal_error(e.into()) - }); - - // The data store must be a warm reset entry. - match ds { - DataVaultNonSticky4(dv_entry) => env.data_vault.read_warm_reset_entry4(dv_entry), - _ => { - handle_fatal_error(CaliptraError::FMC_HANDOFF_INVALID_PARAM.into()); - } - } - } - - #[cfg_attr(not(feature = "no-cfi"), cfi_impl_fn)] - pub fn set_and_lock_rt_min_svn(env: &mut FmcEnv, min_svn: u32) -> CaliptraResult<()> { - let ds: DataStore = - Self::fht(env) - .rt_min_svn_dv_hdl - .try_into() - .unwrap_or_else(|e: CaliptraError| { - cprintln!("[fht] Invalid RT Min SVN handle"); - handle_fatal_error(e.into()) - }); - - // The data store must be a warm reset entry. - match ds { - DataVaultNonSticky4(dv_entry) => { - env.data_vault.write_warm_reset_entry4(dv_entry, min_svn); - env.data_vault.lock_warm_reset_entry4(dv_entry); - Ok(()) - } - _ => { - handle_fatal_error(CaliptraError::FMC_HANDOFF_INVALID_PARAM.into()); - } - } - } - /// Store runtime Dice Signature #[cfg_attr(not(feature = "no-cfi"), cfi_impl_fn)] pub fn set_rt_dice_signature(env: &mut FmcEnv, sig: &Ecc384Signature) { @@ -270,18 +226,6 @@ impl HandOff { } } - #[allow(dead_code)] - #[cfg_attr(not(feature = "no-cfi"), cfi_impl_fn)] - pub fn set_rt_hash_chain_max_svn(env: &mut FmcEnv, max_svn: u16) { - Self::fht_mut(env).rt_hash_chain_max_svn = max_svn; - } - - #[allow(dead_code)] - #[cfg_attr(not(feature = "no-cfi"), cfi_impl_fn)] - pub fn set_rt_hash_chain_kv_hdl(env: &mut FmcEnv, kv_slot: KeyId) { - Self::fht_mut(env).rt_hash_chain_kv_hdl = Self::key_id_to_handle(kv_slot) - } - /// The FMC CDI is stored in a 32-bit DataVault sticky register. fn key_id_to_handle(key_id: KeyId) -> HandOffDataHandle { HandOffDataHandle(((Vault::KeyVault as u32) << 12) | key_id as u32) diff --git a/rom/dev/src/flow/cold_reset/fw_processor.rs b/rom/dev/src/flow/cold_reset/fw_processor.rs index 112163193c..b11ab9a732 100644 --- a/rom/dev/src/flow/cold_reset/fw_processor.rs +++ b/rom/dev/src/flow/cold_reset/fw_processor.rs @@ -567,6 +567,7 @@ impl FirmwareProcessor { data_vault.write_warm_reset_entry48(WarmResetEntry48::RtTci, &info.runtime.digest.into()); data_vault.write_warm_reset_entry4(WarmResetEntry4::RtSvn, info.fw_svn); + data_vault.write_warm_reset_entry4(WarmResetEntry4::RtMinSvn, info.fw_svn); // At cold-boot, min_svn == curr_svn data_vault.write_warm_reset_entry4(WarmResetEntry4::RtEntryPoint, info.runtime.entry_point); diff --git a/rom/dev/src/flow/update_reset.rs b/rom/dev/src/flow/update_reset.rs index 2f453feb8d..947e7dde2a 100644 --- a/rom/dev/src/flow/update_reset.rs +++ b/rom/dev/src/flow/update_reset.rs @@ -215,7 +215,11 @@ impl UpdateResetFlow { fn populate_data_vault(data_vault: &mut DataVault, info: &ImageVerificationInfo) { data_vault.write_warm_reset_entry48(WarmResetEntry48::RtTci, &info.runtime.digest.into()); + let cur_min_svn = data_vault.read_warm_reset_entry4(WarmResetEntry4::RtMinSvn); + let new_min_svn = core::cmp::min(cur_min_svn, info.fw_svn); + data_vault.write_warm_reset_entry4(WarmResetEntry4::RtSvn, info.fw_svn); + data_vault.write_warm_reset_entry4(WarmResetEntry4::RtMinSvn, new_min_svn); data_vault.write_warm_reset_entry4(WarmResetEntry4::RtEntryPoint, info.runtime.entry_point); diff --git a/rom/dev/src/lock.rs b/rom/dev/src/lock.rs index c39f039b71..58f4cd7214 100644 --- a/rom/dev/src/lock.rs +++ b/rom/dev/src/lock.rs @@ -99,7 +99,9 @@ fn lock_common_reg_set(env: &mut RomEnv) { env.data_vault .lock_warm_reset_entry4(WarmResetEntry4::RtSvn); - // Do not lock Runtime minimum SVN; FMC will manage this. + // Lock the Firmware Min-SVN in data vault until next reset + env.data_vault + .lock_warm_reset_entry4(WarmResetEntry4::RtMinSvn); // Lock the Runtime entry point in data vault until next reset env.data_vault From 742b6571a96bd38bff60f73c13d11ac4258c7b48 Mon Sep 17 00:00:00 2001 From: Vishal Mhatre <38512878+mhatrevi@users.noreply.github.com> Date: Mon, 2 Dec 2024 15:14:17 -0800 Subject: [PATCH 31/51] [feat] Updating HMAC KDF from 384 to 512 for ROM (#1819) --- drivers/src/hmac.rs | 2 +- drivers/src/{hmac384_kdf.rs => hmac_kdf.rs} | 16 +-- drivers/src/lib.rs | 4 +- drivers/test-fw/src/bin/hmac_tests.rs | 26 +++-- fmc/src/flow/crypto.rs | 9 +- kat/src/hmac384kdf_kat.rs | 14 ++- kat/src/kats_env.rs | 4 +- kat/src/lib.rs | 2 +- rom/dev/README.md | 8 +- rom/dev/src/flow/cold_reset/crypto.rs | 30 ++--- rom/dev/src/flow/cold_reset/fmc_alias.rs | 18 ++- rom/dev/src/flow/cold_reset/fw_processor.rs | 4 +- rom/dev/src/flow/cold_reset/idev_id.rs | 2 +- rom/dev/src/flow/cold_reset/ldev_id.rs | 10 +- rom/dev/src/main.rs | 4 +- rom/dev/src/rom_env.rs | 6 +- runtime/src/certify_key_extended.rs | 2 +- runtime/src/disable.rs | 7 +- runtime/src/dpe_crypto.rs | 27 +++-- runtime/src/drivers.rs | 8 +- runtime/src/fips.rs | 4 +- runtime/src/hmac.rs | 11 +- runtime/src/invoke_dpe.rs | 2 +- runtime/src/stash_measurement.rs | 2 +- sw-emulator/lib/periph/src/hmac.rs | 22 ++-- test/src/crypto.rs | 27 +++++ test/src/derive.rs | 104 +++++++++--------- .../caliptra_integration_tests/smoke_test.rs | 12 +- .../fmc_alias_cert_redacted.der | Bin 874 -> 874 bytes .../fmc_alias_cert_redacted.txt | 4 +- .../smoke_testdata/idevid_csr.der | Bin 444 -> 443 bytes .../smoke_testdata/idevid_csr.txt | 28 ++--- .../smoke_testdata/ldevid_cert.der | Bin 674 -> 673 bytes .../smoke_testdata/ldevid_cert.txt | 36 +++--- 34 files changed, 268 insertions(+), 187 deletions(-) rename drivers/src/{hmac384_kdf.rs => hmac_kdf.rs} (83%) diff --git a/drivers/src/hmac.rs b/drivers/src/hmac.rs index 520ce4e4b3..ee6630c8e8 100644 --- a/drivers/src/hmac.rs +++ b/drivers/src/hmac.rs @@ -166,7 +166,7 @@ impl Hmac { // Configure the hardware so that the output tag is stored at a location specified by the // caller. - if matches!(&mut tag, HmacTag::Array4x12(_)) { + if matches!(&mut tag, HmacTag::Array4x12(_) | HmacTag::Array4x16(_)) { KvAccess::begin_copy_to_arr(hmac.hmac512_kv_wr_status(), hmac.hmac512_kv_wr_ctrl())?; } diff --git a/drivers/src/hmac384_kdf.rs b/drivers/src/hmac_kdf.rs similarity index 83% rename from drivers/src/hmac384_kdf.rs rename to drivers/src/hmac_kdf.rs index 2da0b22279..a145d53a6f 100644 --- a/drivers/src/hmac384_kdf.rs +++ b/drivers/src/hmac_kdf.rs @@ -4,7 +4,7 @@ Licensed under the Apache-2.0 license. File Name: - hmac384_kdf.rs + hmac_kdf.rs Abstract: @@ -17,36 +17,38 @@ use crate::{Hmac, HmacKey, HmacMode, HmacTag, Trng}; use caliptra_cfi_derive::cfi_mod_fn; use caliptra_error::CaliptraResult; -/// Calculate HMAC-384-KDF +/// Calculate HMAC-KDF /// /// If the output is a KV slot, the slot is marked as a valid HMAC key / -/// ECC keygen seed. +/// ECC or MLDSA keygen seed. /// /// # Arguments /// -/// * `hmac` - HMAC384 context -/// * `key` - HMAC384 key +/// * `hmac` - HMAC context +/// * `key` - HMAC key /// * `label` - Label for the KDF. If `context` is omitted, this is considered /// the fixed input data. /// * `context` - Context for KDF. If present, a NULL byte is included between /// the label and context. /// * `trng` - TRNG driver instance /// * `output` - Location to store the output +/// * `mode` - HMAC Mode #[cfg_attr(not(feature = "no-cfi"), cfi_mod_fn)] -pub fn hmac384_kdf( +pub fn hmac_kdf( hmac: &mut Hmac, key: HmacKey, label: &[u8], context: Option<&[u8]>, trng: &mut Trng, output: HmacTag, + mode: HmacMode, ) -> CaliptraResult<()> { #[cfg(feature = "fips-test-hooks")] unsafe { crate::FipsTestHook::error_if_hook_set(crate::FipsTestHook::HMAC384_FAILURE)? } - let mut hmac_op = hmac.hmac_init(&key, trng, output, HmacMode::Hmac384)?; + let mut hmac_op = hmac.hmac_init(&key, trng, output, mode)?; hmac_op.update(&1_u32.to_be_bytes())?; hmac_op.update(label)?; diff --git a/drivers/src/lib.rs b/drivers/src/lib.rs index 0a62a9f846..31a54c33e1 100644 --- a/drivers/src/lib.rs +++ b/drivers/src/lib.rs @@ -32,7 +32,7 @@ mod fuse_bank; pub mod fuse_log; pub mod hand_off; mod hmac; -mod hmac384_kdf; +mod hmac_kdf; mod key_vault; mod kv_access; mod lms; @@ -77,7 +77,7 @@ pub use fuse_bank::{ }; pub use hand_off::FirmwareHandoffTable; pub use hmac::{Hmac, HmacData, HmacKey, HmacMode, HmacOp, HmacTag}; -pub use hmac384_kdf::hmac384_kdf; +pub use hmac_kdf::hmac_kdf; pub use key_vault::{KeyId, KeyUsage, KeyVault}; pub use kv_access::{KeyReadArgs, KeyWriteArgs}; pub use lms::{ diff --git a/drivers/test-fw/src/bin/hmac_tests.rs b/drivers/test-fw/src/bin/hmac_tests.rs index 5f7b73af58..7722b5545b 100755 --- a/drivers/test-fw/src/bin/hmac_tests.rs +++ b/drivers/test-fw/src/bin/hmac_tests.rs @@ -17,7 +17,7 @@ Abstract: use caliptra_cfi_lib::CfiCounter; use caliptra_drivers::{ - hmac384_kdf, Array4x12, Array4x16, Ecc384, Ecc384PrivKeyOut, Ecc384Scalar, Ecc384Seed, Hmac, + hmac_kdf, Array4x12, Array4x16, Ecc384, Ecc384PrivKeyOut, Ecc384Scalar, Ecc384Seed, Hmac, HmacMode, KeyId, KeyReadArgs, KeyUsage, KeyWriteArgs, Trng, }; use caliptra_kat::Hmac384KdfKat; @@ -406,7 +406,7 @@ fn test_hmac5() { assert_eq!(hmac_step_1, hmac_step_2); } -fn test_kdf( +fn test_kdf_hmac384( key_0: &[u8; 48], msg_0: &[u8], label: &[u8], @@ -445,13 +445,14 @@ fn test_kdf( let kdf_out = KeyWriteArgs::new(KeyId::KeyId1, KeyUsage::default().set_ecc_key_gen_seed_en()); - hmac384_kdf( + hmac_kdf( &mut hmac384, kdf_key_in.into(), label, context, &mut trng, kdf_out.into(), + HmacMode::Hmac384, ) .unwrap(); @@ -471,7 +472,7 @@ fn test_kdf( } // context_len = 48 -fn test_kdf0() { +fn test_kdf0_hmac384() { let key_0 = [ 0x9e, 0x2c, 0xce, 0xc7, 0x00, 0x16, 0x1e, 0x42, 0xff, 0x0e, 0x13, 0x8c, 0x48, 0x89, 0xe4, 0xd6, 0xa0, 0x88, 0x8d, 0x13, 0x1d, 0x58, 0xcb, 0x44, 0xf5, 0xe2, 0x92, 0x47, 0x59, 0x64, @@ -504,7 +505,7 @@ fn test_kdf0() { 0xcb, 0x13, 0x18, ]; - test_kdf( + test_kdf_hmac384( &key_0, &msg_0, &label, @@ -515,7 +516,7 @@ fn test_kdf0() { } // context_len = 0 -fn test_kdf1() { +fn test_kdf1_hmac384() { let key_0 = [ 0xd3, 0x45, 0xe5, 0x14, 0x19, 0xda, 0xc6, 0x9c, 0x70, 0xc8, 0x22, 0x71, 0xe9, 0x12, 0x28, 0x58, 0x65, 0x64, 0x16, 0xc9, 0x92, 0xf3, 0xda, 0x58, 0x5a, 0xca, 0x96, 0xe5, 0x99, 0x29, @@ -542,11 +543,11 @@ fn test_kdf1() { 0x9a, 0xa4, 0x19, ]; - test_kdf(&key_0, &msg_0, &label, None, &out_pub_x, &out_pub_y); + test_kdf_hmac384(&key_0, &msg_0, &label, None, &out_pub_x, &out_pub_y); } // Test using a NIST vector. -fn test_kdf2() { +fn test_kdf2_hmac384() { let mut hmac384 = unsafe { Hmac::new(HmacReg::new()) }; let mut trng = unsafe { Trng::new( @@ -578,13 +579,14 @@ fn test_kdf2() { let mut out_buf = Array4x12::default(); - hmac384_kdf( + hmac_kdf( &mut hmac384, (&Array4x12::from(&key)).into(), &label, None, &mut trng, (&mut out_buf).into(), + HmacMode::Hmac384, ) .unwrap(); @@ -1015,9 +1017,9 @@ test_suite! { test_hmac4, test_hmac_kv_multiblock, test_hmac5, - test_kdf0, - test_kdf1, - test_kdf2, + test_kdf0_hmac384, + test_kdf1_hmac384, + test_kdf2_hmac384, test_hmac_multi_block, test_hmac_exact_single_block, test_hmac_multi_block_two_step, diff --git a/fmc/src/flow/crypto.rs b/fmc/src/flow/crypto.rs index 23e83edae9..0abc8a9ecc 100644 --- a/fmc/src/flow/crypto.rs +++ b/fmc/src/flow/crypto.rs @@ -9,9 +9,9 @@ use crate::fmc_env::FmcEnv; use caliptra_cfi_derive::cfi_impl_fn; use caliptra_common::{crypto::Ecc384KeyPair, keyids::KEY_ID_TMP}; use caliptra_drivers::{ - hmac384_kdf, okref, Array4x12, Array4x5, Array4x8, CaliptraResult, Ecc384PrivKeyIn, - Ecc384PrivKeyOut, Ecc384PubKey, Ecc384Result, Ecc384Signature, KeyId, KeyReadArgs, KeyUsage, - KeyWriteArgs, Sha256Alg, + hmac_kdf, okref, Array4x12, Array4x5, Array4x8, CaliptraResult, Ecc384PrivKeyIn, + Ecc384PrivKeyOut, Ecc384PubKey, Ecc384Result, Ecc384Signature, HmacMode, KeyId, KeyReadArgs, + KeyUsage, KeyWriteArgs, Sha256Alg, }; pub enum Crypto {} @@ -79,7 +79,7 @@ impl Crypto { context: Option<&[u8]>, output: KeyId, ) -> CaliptraResult<()> { - hmac384_kdf( + hmac_kdf( &mut env.hmac384, KeyReadArgs::new(key).into(), label, @@ -92,6 +92,7 @@ impl Crypto { .set_ecc_key_gen_seed_en(), ) .into(), + HmacMode::Hmac384, ) } diff --git a/kat/src/hmac384kdf_kat.rs b/kat/src/hmac384kdf_kat.rs index 30015dab22..31038bce58 100644 --- a/kat/src/hmac384kdf_kat.rs +++ b/kat/src/hmac384kdf_kat.rs @@ -12,7 +12,7 @@ Abstract: --*/ -use caliptra_drivers::{hmac384_kdf, Array4x12, CaliptraError, CaliptraResult, Hmac, Trng}; +use caliptra_drivers::{hmac_kdf, Array4x12, CaliptraError, CaliptraResult, Hmac, HmacMode, Trng}; const KEY: Array4x12 = Array4x12::new([ 0xb57dc523, 0x54afee11, 0xedb4c905, 0x2a528344, 0x348b2c6b, 0x6c39f321, 0x33ed3bb7, 0x2035a4ab, @@ -67,8 +67,16 @@ impl Hmac384KdfKat { fn kat_nist_vector(&self, hmac: &mut Hmac, trng: &mut Trng) -> CaliptraResult<()> { let mut out = Array4x12::default(); - hmac384_kdf(hmac, (&KEY).into(), &LABEL, None, trng, (&mut out).into()) - .map_err(|_| CaliptraError::KAT_HMAC384_FAILURE)?; + hmac_kdf( + hmac, + (&KEY).into(), + &LABEL, + None, + trng, + (&mut out).into(), + HmacMode::Hmac384, + ) + .map_err(|_| CaliptraError::KAT_HMAC384_FAILURE)?; if EXPECTED_OUT != <[u8; 48]>::from(out)[..EXPECTED_OUT.len()] { Err(CaliptraError::KAT_HMAC384_TAG_MISMATCH)?; diff --git a/kat/src/kats_env.rs b/kat/src/kats_env.rs index b2de48da31..fc5827b141 100644 --- a/kat/src/kats_env.rs +++ b/kat/src/kats_env.rs @@ -17,8 +17,8 @@ pub struct KatsEnv<'a> { // SHA2-512/384 Accelerator pub sha2_512_384_acc: &'a mut Sha2_512_384Acc, - /// Hmac384 Engine - pub hmac384: &'a mut Hmac, + /// Hmac-512/384 Engine + pub hmac: &'a mut Hmac, /// Cryptographically Secure Random Number Generator pub trng: &'a mut Trng, diff --git a/kat/src/lib.rs b/kat/src/lib.rs index f71bc6bce6..660661bd63 100644 --- a/kat/src/lib.rs +++ b/kat/src/lib.rs @@ -59,7 +59,7 @@ pub fn execute_kat(env: &mut KatsEnv) -> CaliptraResult<()> { Ecc384Kat::default().execute(env.ecc384, env.trng)?; cprintln!("[kat] HMAC-384Kdf"); - Hmac384KdfKat::default().execute(env.hmac384, env.trng)?; + Hmac384KdfKat::default().execute(env.hmac, env.trng)?; cprintln!("[kat] LMS"); LmsKat::default().execute(env.sha256, env.lms)?; diff --git a/rom/dev/README.md b/rom/dev/README.md index 4fa7917269..cac3579868 100644 --- a/rom/dev/README.md +++ b/rom/dev/README.md @@ -180,8 +180,8 @@ The following sections define the various cryptographic primitives used by Calip | Deobfuscation Engine | `doe_decrypt_uds(kv_slot, iv)` | Decrypt UDS to the specified key vault slot with specified initialization vector
**Input**:
***kv_slot*** - key vault slot to decrypt the uds to
***iv*** - initialization vector | | | `doe_decrypt_fe(kv_slot, iv)` | Decrypt Field Entropy to the specified key vault slot with specified initialization vector
**Input**:
***kv_slot*** - key vault slot to decrypt the field entropy to
***iv*** - initialization vector | | | `doe_clear_secrets()` | Clear UDS Fuse Register, Field Entropy Fuse Register and Obfuscation key | -| Hashed Message Authentication Code | `hmac384_mac(key,data,mac_kv_slot)` | Calculate the MAC using a caller provided key and data. The resultant MAC is stored in key vault slot
**Input**:
***key*** - caller specified key
data - data
***mac_kv_slot*** - key vault slot to store the MAC to | -| | `hmac384_mac(kv_slot,data,mac_kv_slot)` | Calculate the MAC using a caller provided key and data. The resultant MAC is stored in key vault slot
**Input**:
***kv_slot*** - key vault slot to use the key from
***data*** - data
***mac_kv_slot*** - key vault slot to store the MAC to | +| Hashed Message Authentication Code | `hmac_mac(key,data,mac_kv_slot,mode)` | Calculate the MAC using a caller provided key and data. The resultant MAC is stored in key vault slot
**Input**:
***key*** - caller specified key
data - data
***mac_kv_slot*** - key vault slot to store the MAC to
***mode*** - HMAC384 or HMAC512 | +| | `hmac_mac(kv_slot,data,mac_kv_slot)` | Calculate the MAC using a caller provided key and data. The resultant MAC is stored in key vault slot
**Input**:
***kv_slot*** - key vault slot to use the key from
***data*** - data
***mac_kv_slot*** - key vault slot to store the MAC to
***mode*** - HMAC384 or HMAC512 | | | `hmac512_mac(key,data,mac_kv_slot)` | Calculate the MAC using a caller provided key and data. The resultant MAC is stored in key vault slot
**Input**:
***key*** - caller specified key
data - data
***mac_kv_slot*** - key vault slot to store the MAC to | | | `hmac512_mac(kv_slot,data,mac_kv_slot)` | Calculate the MAC using a caller provided key and data. The resultant MAC is stored in key vault slot
**Input**:
***kv_slot*** - key vault slot to use the key from
***data*** - data
***mac_kv_slot*** - key vault slot to store the MAC to | | Elliptic Curve Cryptography | `ecc384_keygen(seed_kv_slot, priv_kv_slot) -> pub_key` | Generate ECC384 Key Pair.
**Input**:
***seed_key_slot*** - key vault slot to use as seed for key generation
***priv_kv_slot*** - key vault slot to store the private key to
**Output**:
***pub-key*** - public key associated with the private key | @@ -471,9 +471,9 @@ Initial Device ID Layer is used to generate Manufacturer CDI & Private Keys. Thi 11. Generate the MACs over the tbs digests as follows: - `IDevIdTbsEcdsaMac = hmac384_mac(VendorSecretKvSlot, b"idevid_ecc_csr", IDevIdTbsDigestEcdsa)` + `IDevIdTbsEcdsaMac = hmac_mac(VendorSecretKvSlot, b"idevid_ecc_csr", IDevIdTbsDigestEcdsa, HmacMode::Hmac384)` - `IDevIdTbsMldsaMac = hmac512_mac(VendorSecretKvSlot, b"idevid_mldsa_csr",IDevIdTbsDigestMldsa)` + `IDevIdTbsMldsaMac = hmac512_mac(VendorSecretKvSlot, b"idevid_mldsa_csr",IDevIdTbsDigestMldsa, HmacMode::Hmac512)` 12. Upload the CSR(s) to mailbox and wait for JTAG to read the CSR out of the mailbox. Format of the CSR payload is documented below: diff --git a/rom/dev/src/flow/cold_reset/crypto.rs b/rom/dev/src/flow/cold_reset/crypto.rs index 04b4079e78..7432bdbe8b 100644 --- a/rom/dev/src/flow/cold_reset/crypto.rs +++ b/rom/dev/src/flow/cold_reset/crypto.rs @@ -113,22 +113,24 @@ impl Crypto { env.sha384.digest(data) } - /// Calculate HMAC-348 + /// Calculate HMAC /// /// # Arguments /// /// * `env` - ROM Environment - /// * `key` - HMAC384 key slot + /// * `key` - HMAC key slot /// * `data` - Input data to hash /// * `tag` - Key slot to store the tag + /// * `mode` - HMAC Mode #[inline(always)] - pub fn hmac384_mac( + pub fn hmac_mac( env: &mut RomEnv, key: KeyId, data: &HmacData, tag: KeyId, + mode: HmacMode, ) -> CaliptraResult<()> { - env.hmac384.hmac( + env.hmac.hmac( &KeyReadArgs::new(key).into(), data, &mut env.trng, @@ -139,29 +141,31 @@ impl Crypto { .set_ecc_key_gen_seed_en(), ) .into(), - HmacMode::Hmac384, + mode, ) } - /// Calculate HMAC-348 KDF + /// Calculate HMAC KDF /// /// # Arguments /// /// * `env` - ROM Environment - /// * `key` - HMAC384 key slot + /// * `key` - HMAC key slot /// * `label` - Input label /// * `context` - Input context /// * `output` - Key slot to store the output + /// * `mode` - HMAC Mode #[inline(always)] - pub fn hmac384_kdf( + pub fn hmac_kdf( env: &mut RomEnv, key: KeyId, label: &[u8], context: Option<&[u8]>, output: KeyId, + mode: HmacMode, ) -> CaliptraResult<()> { - hmac384_kdf( - &mut env.hmac384, + hmac_kdf( + &mut env.hmac, KeyReadArgs::new(key).into(), label, context, @@ -173,6 +177,7 @@ impl Crypto { .set_ecc_key_gen_seed_en(), ) .into(), + mode, ) } @@ -194,7 +199,7 @@ impl Crypto { label: &[u8], priv_key: KeyId, ) -> CaliptraResult { - Crypto::hmac384_kdf(env, cdi, label, None, KEY_ID_TMP)?; + Crypto::hmac_kdf(env, cdi, label, None, KEY_ID_TMP, HmacMode::Hmac512)?; let key_out = Ecc384PrivKeyOut::Key(KeyWriteArgs::new( priv_key, @@ -266,8 +271,7 @@ impl Crypto { key_pair_seed: KeyId, ) -> CaliptraResult { // Generate the seed for key pair generation. - // [CAP2][TODO] Change this to hmac512_kdfwhen available. - Crypto::hmac384_kdf(env, cdi, label, None, key_pair_seed)?; + Crypto::hmac_kdf(env, cdi, label, None, key_pair_seed, HmacMode::Hmac512)?; // Generate the public key. let pub_key = env diff --git a/rom/dev/src/flow/cold_reset/fmc_alias.rs b/rom/dev/src/flow/cold_reset/fmc_alias.rs index 19f754b3d0..3ce68c231f 100644 --- a/rom/dev/src/flow/cold_reset/fmc_alias.rs +++ b/rom/dev/src/flow/cold_reset/fmc_alias.rs @@ -31,7 +31,9 @@ use caliptra_common::keyids::{ }; use caliptra_common::pcr::PCR_ID_FMC_CURRENT; use caliptra_common::RomBootStatus::*; -use caliptra_drivers::{okmutref, report_boot_status, Array4x12, CaliptraResult, KeyId, Lifecycle}; +use caliptra_drivers::{ + okmutref, report_boot_status, Array4x12, CaliptraResult, HmacMode, KeyId, Lifecycle, +}; use caliptra_x509::{FmcAliasCertTbs, FmcAliasCertTbsParams}; use zeroize::Zeroize; @@ -53,6 +55,11 @@ impl FmcAliasLayer { KEY_ID_FMC_ECDSA_PRIV_KEY as u8, KEY_ID_FMC_MLDSA_KEYPAIR_SEED as u8 ); + cprintln!( + "[afmc] ECC SUBJECT.KEYID = {}, MLDSA SUBJECT.KEYID = {}", + KEY_ID_FMC_ECDSA_PRIV_KEY as u8, + KEY_ID_FMC_MLDSA_KEYPAIR_SEED as u8 + ); cprintln!( "[afmc] ECC AUTHORITY.KEYID = {}, MLDSA AUTHORITY.KEYID = {}", input.ecc_auth_key_pair.priv_key as u8, @@ -119,7 +126,14 @@ impl FmcAliasLayer { fn derive_cdi(env: &mut RomEnv, measurements: &Array4x12, cdi: KeyId) -> CaliptraResult<()> { let mut measurements: [u8; 48] = measurements.into(); - let result = Crypto::hmac384_kdf(env, cdi, b"alias_fmc_cdi", Some(&measurements), cdi); + let result = Crypto::hmac_kdf( + env, + cdi, + b"alias_fmc_cdi", + Some(&measurements), + KEY_ID_ROM_FMC_CDI, + HmacMode::Hmac512, + ); measurements.zeroize(); result?; report_boot_status(FmcAliasDeriveCdiComplete.into()); diff --git a/rom/dev/src/flow/cold_reset/fw_processor.rs b/rom/dev/src/flow/cold_reset/fw_processor.rs index b11ab9a732..a5fd27070a 100644 --- a/rom/dev/src/flow/cold_reset/fw_processor.rs +++ b/rom/dev/src/flow/cold_reset/fw_processor.rs @@ -71,8 +71,8 @@ impl FirmwareProcessor { // SHA2-512/384 Accelerator sha2_512_384_acc: &mut env.sha2_512_384_acc, - // Hmac384 Engine - hmac384: &mut env.hmac384, + // Hmac-512/384 Engine + hmac: &mut env.hmac, /// Cryptographically Secure Random Number Generator trng: &mut env.trng, diff --git a/rom/dev/src/flow/cold_reset/idev_id.rs b/rom/dev/src/flow/cold_reset/idev_id.rs index 2168d19d57..e761df95bc 100644 --- a/rom/dev/src/flow/cold_reset/idev_id.rs +++ b/rom/dev/src/flow/cold_reset/idev_id.rs @@ -180,7 +180,7 @@ impl InitDevIdLayer { /// * `cdi` - Key Slot to store the generated CDI #[cfg_attr(not(feature = "no-cfi"), cfi_impl_fn)] fn derive_cdi(env: &mut RomEnv, uds: KeyId, cdi: KeyId) -> CaliptraResult<()> { - Crypto::hmac384_kdf(env, uds, b"idevid_cdi", None, cdi)?; + Crypto::hmac_kdf(env, uds, b"idevid_cdi", None, cdi, HmacMode::Hmac512)?; cprintln!("[idev] Erasing UDS.KEYID = {}", uds as u8); env.key_vault.erase_key(uds)?; diff --git a/rom/dev/src/flow/cold_reset/ldev_id.rs b/rom/dev/src/flow/cold_reset/ldev_id.rs index 8f2c1f35db..5b7386dd1b 100644 --- a/rom/dev/src/flow/cold_reset/ldev_id.rs +++ b/rom/dev/src/flow/cold_reset/ldev_id.rs @@ -115,8 +115,14 @@ impl LocalDevIdLayer { /// * `cdi` - Key Slot to store the generated CDI #[cfg_attr(not(feature = "no-cfi"), cfi_impl_fn)] fn derive_cdi(env: &mut RomEnv, fe: KeyId, cdi: KeyId) -> CaliptraResult<()> { - Crypto::hmac384_mac(env, cdi, &b"ldevid_cdi".into(), cdi)?; - Crypto::hmac384_mac(env, cdi, &KeyReadArgs::new(fe).into(), cdi)?; + Crypto::hmac_mac(env, cdi, &b"ldevid_cdi".into(), cdi, HmacMode::Hmac512)?; + Crypto::hmac_mac( + env, + cdi, + &KeyReadArgs::new(fe).into(), + cdi, + HmacMode::Hmac512, + )?; cprintln!("[ldev] Erasing FE.KEYID = {}", fe as u8); env.key_vault.erase_key(fe)?; diff --git a/rom/dev/src/main.rs b/rom/dev/src/main.rs index 4a96563644..e8464de91d 100644 --- a/rom/dev/src/main.rs +++ b/rom/dev/src/main.rs @@ -139,8 +139,8 @@ pub extern "C" fn rom_entry() -> ! { // SHA2-512/384 Accelerator sha2_512_384_acc: &mut env.sha2_512_384_acc, - // Hmac384 Engine - hmac384: &mut env.hmac384, + // Hmac-512/384 Engine + hmac: &mut env.hmac, /// Cryptographically Secure Random Number Generator trng: &mut env.trng, diff --git a/rom/dev/src/rom_env.rs b/rom/dev/src/rom_env.rs index 7294716be9..78a0a29abd 100644 --- a/rom/dev/src/rom_env.rs +++ b/rom/dev/src/rom_env.rs @@ -44,8 +44,8 @@ pub struct RomEnv { // SHA2-512/384 Accelerator pub sha2_512_384_acc: Sha2_512_384Acc, - /// Hmac384 Engine - pub hmac384: Hmac, + /// Hmac Engine + pub hmac: Hmac, /// Ecc384 Engine pub ecc384: Ecc384, @@ -96,7 +96,7 @@ impl RomEnv { sha256: Sha256::new(Sha256Reg::new()), sha384: Sha384::new(Sha512Reg::new()), sha2_512_384_acc: Sha2_512_384Acc::new(Sha512AccCsr::new()), - hmac384: Hmac::new(HmacReg::new()), + hmac: Hmac::new(HmacReg::new()), ecc384: Ecc384::new(EccReg::new()), lms: Lms::default(), key_vault: KeyVault::new(KvReg::new()), diff --git a/runtime/src/certify_key_extended.rs b/runtime/src/certify_key_extended.rs index 0e806131e8..8c33768ad3 100644 --- a/runtime/src/certify_key_extended.rs +++ b/runtime/src/certify_key_extended.rs @@ -55,7 +55,7 @@ impl CertifyKeyExtendedCmd { &mut drivers.sha384, &mut drivers.trng, &mut drivers.ecc384, - &mut drivers.hmac384, + &mut drivers.hmac, &mut drivers.key_vault, &mut pdata.fht.rt_dice_pub_key, key_id_rt_cdi, diff --git a/runtime/src/disable.rs b/runtime/src/disable.rs index 9c0d567f5a..9d889049aa 100644 --- a/runtime/src/disable.rs +++ b/runtime/src/disable.rs @@ -16,7 +16,7 @@ use crate::Drivers; use caliptra_cfi_derive_git::cfi_impl_fn; use caliptra_common::mailbox_api::MailboxResp; use caliptra_drivers::{ - hmac384_kdf, Array4x12, CaliptraError, CaliptraResult, Ecc384Seed, HmacKey, KeyReadArgs, + hmac_kdf, Array4x12, CaliptraError, CaliptraResult, Ecc384Seed, HmacKey, HmacMode, KeyReadArgs, KeyUsage, KeyWriteArgs, }; use dpe::U8Bool; @@ -54,8 +54,8 @@ impl DisableAttestationCmd { #[cfg_attr(not(feature = "no-cfi"), cfi_impl_fn)] fn zero_rt_cdi(drivers: &mut Drivers) -> CaliptraResult<()> { let key_id_rt_cdi = Drivers::get_key_id_rt_cdi(drivers)?; - hmac384_kdf( - &mut drivers.hmac384, + hmac_kdf( + &mut drivers.hmac, HmacKey::Array4x12(&Array4x12::default()), b"zero_rt_cdi", None, @@ -67,6 +67,7 @@ impl DisableAttestationCmd { .set_ecc_key_gen_seed_en(), ) .into(), + HmacMode::Hmac384, )?; Ok(()) diff --git a/runtime/src/dpe_crypto.rs b/runtime/src/dpe_crypto.rs index b8fd4798d3..46f29b4996 100644 --- a/runtime/src/dpe_crypto.rs +++ b/runtime/src/dpe_crypto.rs @@ -18,8 +18,8 @@ use caliptra_cfi_derive_git::cfi_impl_fn; use caliptra_cfi_lib_git::{cfi_assert, cfi_assert_eq, cfi_launder}; use caliptra_common::keyids::{KEY_ID_DPE_CDI, KEY_ID_DPE_PRIV_KEY, KEY_ID_TMP}; use caliptra_drivers::{ - cprintln, hmac384_kdf, Array4x12, Ecc384, Ecc384PrivKeyIn, Ecc384PubKey, Ecc384Scalar, - Ecc384Seed, Hmac, HmacData, HmacKey, HmacMode, HmacTag, KeyId, KeyReadArgs, KeyUsage, KeyVault, + cprintln, hmac_kdf, Array4x12, Ecc384, Ecc384PrivKeyIn, Ecc384PubKey, Ecc384Scalar, Ecc384Seed, + Hmac, HmacData, HmacKey, HmacMode, HmacTag, KeyId, KeyReadArgs, KeyUsage, KeyVault, KeyWriteArgs, Sha384, Sha384DigestOp, Trng, }; use crypto::{AlgLen, Crypto, CryptoBuf, CryptoError, Digest, EcdsaPub, EcdsaSig, Hasher, HmacSig}; @@ -30,7 +30,7 @@ pub struct DpeCrypto<'a> { sha384: &'a mut Sha384, trng: &'a mut Trng, ecc384: &'a mut Ecc384, - hmac384: &'a mut Hmac, + hmac: &'a mut Hmac, key_vault: &'a mut KeyVault, rt_pub_key: &'a mut Ecc384PubKey, key_id_rt_cdi: KeyId, @@ -43,7 +43,7 @@ impl<'a> DpeCrypto<'a> { sha384: &'a mut Sha384, trng: &'a mut Trng, ecc384: &'a mut Ecc384, - hmac384: &'a mut Hmac, + hmac: &'a mut Hmac, key_vault: &'a mut KeyVault, rt_pub_key: &'a mut Ecc384PubKey, key_id_rt_cdi: KeyId, @@ -53,7 +53,7 @@ impl<'a> DpeCrypto<'a> { sha384, trng, ecc384, - hmac384, + hmac, key_vault, rt_pub_key, key_id_rt_cdi, @@ -144,8 +144,8 @@ impl<'a> Crypto for DpeCrypto<'a> { hasher.update(info)?; let context = hasher.finish()?; - hmac384_kdf( - self.hmac384, + hmac_kdf( + self.hmac, KeyReadArgs::new(self.key_id_rt_cdi).into(), b"derive_cdi", Some(context.bytes()), @@ -157,6 +157,7 @@ impl<'a> Crypto for DpeCrypto<'a> { .set_ecc_key_gen_seed_en(), ) .into(), + HmacMode::Hmac384, ) .map_err(|e| CryptoError::CryptoLibError(u32::from(e)))?; Ok(KEY_ID_DPE_CDI) @@ -175,14 +176,15 @@ impl<'a> Crypto for DpeCrypto<'a> { match algs { AlgLen::Bit256 => Err(CryptoError::Size), AlgLen::Bit384 => { - hmac384_kdf( - self.hmac384, + hmac_kdf( + self.hmac, KeyReadArgs::new(*cdi).into(), label, Some(info), self.trng, KeyWriteArgs::new(KEY_ID_TMP, KeyUsage::default().set_ecc_key_gen_seed_en()) .into(), + HmacMode::Hmac384, ) .map_err(|e| CryptoError::CryptoLibError(u32::from(e)))?; @@ -329,20 +331,21 @@ impl<'a> Crypto for DpeCrypto<'a> { // derive an hmac key let mut hmac_key = Array4x12::default(); - hmac384_kdf( - self.hmac384, + hmac_kdf( + self.hmac, HmacKey::Array4x12(&Array4x12::from(hmac_ikm)), &[], None, self.trng, HmacTag::Array4x12(&mut hmac_key), + HmacMode::Hmac384, ) .map_err(|e| CryptoError::CryptoLibError(u32::from(e)))?; hmac_ikm.zeroize(); // sign digest with HMAC key let mut tag = Array4x12::default(); - self.hmac384 + self.hmac .hmac( &HmacKey::Array4x12(&hmac_key), &HmacData::Slice(digest.bytes()), diff --git a/runtime/src/drivers.rs b/runtime/src/drivers.rs index e00b0f90e4..659be4b62b 100644 --- a/runtime/src/drivers.rs +++ b/runtime/src/drivers.rs @@ -81,8 +81,8 @@ pub struct Drivers { // SHA2-512/384 Accelerator pub sha2_512_384_acc: Sha2_512_384Acc, - /// Hmac384 Engine - pub hmac384: Hmac, + /// Hmac-512/384 Engine + pub hmac: Hmac, /// Cryptographically Secure Random Number Generator pub trng: Trng, @@ -133,7 +133,7 @@ impl Drivers { sha256: Sha256::new(Sha256Reg::new()), sha384: Sha384::new(Sha512Reg::new()), sha2_512_384_acc: Sha2_512_384Acc::new(Sha512AccCsr::new()), - hmac384: Hmac::new(HmacReg::new()), + hmac: Hmac::new(HmacReg::new()), ecc384: Ecc384::new(EccReg::new()), sha1: Sha1::default(), lms: Lms::default(), @@ -384,7 +384,7 @@ impl Drivers { &mut drivers.sha384, &mut drivers.trng, &mut drivers.ecc384, - &mut drivers.hmac384, + &mut drivers.hmac, &mut drivers.key_vault, &mut pdata.fht.rt_dice_pub_key, key_id_rt_cdi, diff --git a/runtime/src/fips.rs b/runtime/src/fips.rs index 6a5a068dcb..0d963101c9 100644 --- a/runtime/src/fips.rs +++ b/runtime/src/fips.rs @@ -159,8 +159,8 @@ pub mod fips_self_test_cmd { // SHA2-512/384 Accelerator sha2_512_384_acc: &mut env.sha2_512_384_acc, - // Hmac384 Engine - hmac384: &mut env.hmac384, + // Hmac-512/384 Engine + hmac: &mut env.hmac, /// Cryptographically Secure Random Number Generator trng: &mut env.trng, diff --git a/runtime/src/hmac.rs b/runtime/src/hmac.rs index 19c3b13945..a0a56aa9a7 100644 --- a/runtime/src/hmac.rs +++ b/runtime/src/hmac.rs @@ -16,7 +16,7 @@ use caliptra_cfi_derive_git::{cfi_impl_fn, cfi_mod_fn}; use caliptra_cfi_lib_git::{cfi_assert, cfi_assert_eq, cfi_launder}; use caliptra_common::{crypto::Ecc384KeyPair, keyids::KEY_ID_TMP}; use caliptra_drivers::{ - hmac384_kdf, Array4x12, Ecc384PrivKeyOut, Ecc384PubKey, HmacData, HmacKey, HmacMode, HmacTag, + hmac_kdf, Array4x12, Ecc384PrivKeyOut, Ecc384PubKey, HmacData, HmacKey, HmacMode, HmacTag, KeyId, KeyReadArgs, KeyUsage, KeyWriteArgs, }; use caliptra_error::CaliptraResult; @@ -44,8 +44,8 @@ fn ecc384_key_gen( label: &[u8], priv_key: KeyId, ) -> CaliptraResult { - hmac384_kdf( - &mut drivers.hmac384, + hmac_kdf( + &mut drivers.hmac, KeyReadArgs::new(input).into(), label, None, @@ -57,6 +57,7 @@ fn ecc384_key_gen( .set_ecc_key_gen_seed_en(), ) .into(), + HmacMode::Hmac384, )?; let pub_key = drivers.ecc384.key_pair( @@ -92,7 +93,7 @@ impl Hmac { /// * `output` - KeyId which the output hash should be written to #[cfg_attr(not(feature = "no-cfi"), cfi_impl_fn)] pub fn hmac384_hash(drivers: &mut Drivers, input: KeyId, output: KeyId) -> CaliptraResult<()> { - drivers.hmac384.hmac( + drivers.hmac.hmac( &KeyReadArgs::new(input).into(), &HmacData::Slice(&[]), &mut drivers.trng, @@ -149,7 +150,7 @@ impl Hmac { hasher.finalize(&mut pubkey_digest)?; let mut hmac_output = Array4x12::default(); - drivers.hmac384.hmac( + drivers.hmac.hmac( &HmacKey::Array4x12(&pubkey_digest), &HmacData::Slice(data), &mut drivers.trng, diff --git a/runtime/src/invoke_dpe.rs b/runtime/src/invoke_dpe.rs index 4a731e16ca..0ee8773768 100644 --- a/runtime/src/invoke_dpe.rs +++ b/runtime/src/invoke_dpe.rs @@ -55,7 +55,7 @@ impl InvokeDpeCmd { &mut drivers.sha384, &mut drivers.trng, &mut drivers.ecc384, - &mut drivers.hmac384, + &mut drivers.hmac, &mut drivers.key_vault, &mut pdata.fht.rt_dice_pub_key, key_id_rt_cdi, diff --git a/runtime/src/stash_measurement.rs b/runtime/src/stash_measurement.rs index 7f13210ec5..12856259da 100644 --- a/runtime/src/stash_measurement.rs +++ b/runtime/src/stash_measurement.rs @@ -57,7 +57,7 @@ impl StashMeasurementCmd { &mut drivers.sha384, &mut drivers.trng, &mut drivers.ecc384, - &mut drivers.hmac384, + &mut drivers.hmac, &mut drivers.key_vault, &mut pdata.fht.rt_dice_pub_key, key_id_rt_cdi, diff --git a/sw-emulator/lib/periph/src/hmac.rs b/sw-emulator/lib/periph/src/hmac.rs index fb67da889f..f7b54d5a95 100644 --- a/sw-emulator/lib/periph/src/hmac.rs +++ b/sw-emulator/lib/periph/src/hmac.rs @@ -91,8 +91,11 @@ register_bitfields! [ /// HMAC384 Key Size. const HMAC_KEY_SIZE_384: usize = 48; -/// HMAC512 Key Size. -const HMAC_KEY_SIZE_512: usize = 64; +/// HMAC512 Key Size in Bytes. +const HMAC_KEY_SIZE_BYTES_512: usize = 64; + +/// HMAC512 Key Size in DWORDs. +const HMAC_KEY_SIZE_DWORD_512: usize = 16; /// HMAC Block Size const HMAC_BLOCK_SIZE: usize = 128; // SHA-384/512 block size is 128 bytes @@ -144,7 +147,7 @@ pub struct HmacSha { /// HMAC Key Register #[register_array(offset = 0x0000_0040, item_size = 4, len = 16, read_fn = read_access_fault, write_fn = on_write_key)] - key: [u32; HMAC_KEY_SIZE_512 / 4], + key: [u32; HMAC_KEY_SIZE_DWORD_512], /// HMAC Block Register #[register_array(offset = 0x0000_0080, item_size = 4, len = 32, read_fn = read_access_fault, write_fn = on_write_block)] @@ -238,7 +241,7 @@ impl HmacSha { /// * `Self` - Instance of HMAC-SHA-384 Engine pub fn new(clock: &Clock, key_vault: KeyVault) -> Self { Self { - hmac: Box::new(Hmac512::::new(Hmac512Mode::Sha512)), + hmac: Box::new(Hmac512::::new(Hmac512Mode::Sha512)), name0: ReadOnlyRegister::new(Self::NAME0_VAL), name1: ReadOnlyRegister::new(Self::NAME1_VAL), version0: ReadOnlyRegister::new(Self::VERSION0_VAL), @@ -341,7 +344,8 @@ impl HmacSha { if self.control.reg.is_set(Control::INIT) { if mode512 { - self.hmac = Box::new(Hmac512::::new(Hmac512Mode::Sha512)) + self.hmac = + Box::new(Hmac512::::new(Hmac512Mode::Sha512)) } else { self.hmac = Box::new(Hmac512::::new(Hmac512Mode::Sha384)) } @@ -562,10 +566,12 @@ impl HmacSha { if let Some(key) = &key { self.key_from_kv = true; - let key_len = self.key_len(); - self.key[..key_len] + // HMAC mode is not known at this point. Thus, copying the entire + // key from the KV slot even though the actual key might be shorter. + // Peripherals using the key material will size it appropriately. + self.key[..HMAC_KEY_SIZE_DWORD_512] .as_bytes_mut() - .copy_from_slice(&key[..key_len * 4]); + .copy_from_slice(key.as_bytes()); } self.key_read_status.reg.modify( diff --git a/test/src/crypto.rs b/test/src/crypto.rs index 3fac843568..c7a953a3f1 100644 --- a/test/src/crypto.rs +++ b/test/src/crypto.rs @@ -134,6 +134,18 @@ pub(crate) fn hmac384(key: &[u8], data: &[u8]) -> [u8; 48] { result } +pub(crate) fn hmac512(key: &[u8], data: &[u8]) -> [u8; 64] { + use openssl::hash::MessageDigest; + use openssl::sign::Signer; + + let pkey = PKey::hmac(key).unwrap(); + let mut signer = Signer::new(MessageDigest::sha512(), &pkey).unwrap(); + signer.update(data).unwrap(); + let mut result = [0u8; 64]; + signer.sign(&mut result).unwrap(); + result +} + #[test] fn test_hmac384() { // test vector from https://csrc.nist.gov/projects/cryptographic-algorithm-validation-program/message-authentication @@ -183,6 +195,21 @@ pub(crate) fn hmac384_kdf(key: &[u8], label: &[u8], context: Option<&[u8]>) -> [ hmac384(key, &msg) } +pub(crate) fn hmac512_kdf(key: &[u8], label: &[u8], context: Option<&[u8]>) -> [u8; 64] { + let ctr_be = 1_u32.to_be_bytes(); + + let mut msg = Vec::::default(); + msg.extend_from_slice(&ctr_be); + msg.extend_from_slice(label); + + if let Some(context) = context { + msg.push(0x00); + msg.extend_from_slice(context); + } + + hmac512(key, &msg) +} + #[test] fn test_hmac384_kdf() { // test vector from https://csrc.nist.gov/Projects/cryptographic-algorithm-validation-program/key-derivation diff --git a/test/src/derive.rs b/test/src/derive.rs index 964375b3b3..8f85415351 100644 --- a/test/src/derive.rs +++ b/test/src/derive.rs @@ -16,7 +16,7 @@ use zerocopy::{transmute, AsBytes}; use caliptra_api_types::DeviceLifecycle; use crate::{ - crypto::{self, derive_ecdsa_key, hmac384, hmac384_drbg_keygen, hmac384_kdf}, + crypto::{self, derive_ecdsa_key, hmac384_drbg_keygen, hmac384_kdf, hmac512, hmac512_kdf}, swap_word_bytes, swap_word_bytes_inplace, }; @@ -154,37 +154,37 @@ fn test_doe_output() { #[derive(Clone, Copy, Debug, Eq, PartialEq)] pub struct IDevId { - pub cdi: [u32; 12], + pub cdi: [u32; 16], - pub priv_key: [u32; 12], + pub ecc_priv_key: [u32; 12], } impl IDevId { pub fn derive(doe_output: &DoeOutput) -> Self { - let mut cdi: [u32; 12] = transmute!(hmac384_kdf( + let mut cdi: [u32; 16] = transmute!(hmac512_kdf( swap_word_bytes(&doe_output.uds).as_bytes(), b"idevid_cdi", None )); swap_word_bytes_inplace(&mut cdi); - let mut priv_key_seed: [u32; 12] = transmute!(hmac384_kdf( + let mut priv_key_seed: [u32; 16] = transmute!(hmac512_kdf( swap_word_bytes(&cdi).as_bytes(), b"idevid_ecc_key", None )); swap_word_bytes_inplace(&mut priv_key_seed); - let mut priv_key: [u32; 12] = transmute!(hmac384_drbg_keygen( - swap_word_bytes(&priv_key_seed).as_bytes(), + let mut ecc_priv_key: [u32; 12] = transmute!(hmac384_drbg_keygen( + &swap_word_bytes(&priv_key_seed).as_bytes()[..48], swap_word_bytes(&ECDSA_KEYGEN_NONCE).as_bytes() )); - swap_word_bytes_inplace(&mut priv_key); - Self { cdi, priv_key } + swap_word_bytes_inplace(&mut ecc_priv_key); + Self { cdi, ecc_priv_key } } pub fn derive_public_key(&self) -> PKey { derive_ecdsa_key( - swap_word_bytes(&self.priv_key) + swap_word_bytes(&self.ecc_priv_key) .as_bytes() .try_into() .unwrap(), @@ -208,12 +208,13 @@ fn test_idevid() { idevid, IDevId { cdi: [ - 0x4C4F422C, 0x8EDA4E83, 0x1F669172, 0xA4315915, 0x9BE4B317, 0x449FF543, 0x81FFEF29, - 0xF7BE0784, 0x0586992C, 0x170E7C92, 0x8D4F72B2, 0xAA4051AD, + 0x0ae8ec4b, 0x25da6d36, 0x6469502c, 0x94c7b654, 0xf78a5b9e, 0x1cef338f, 0xee5b5ecb, + 0x9b533c4e, 0xc11af69e, 0xe23d2612, 0x6b37a1fb, 0xd36e0914, 0x1f5d9fdc, 0x2927753a, + 0x4523e552, 0x5216eaf3, ], - priv_key: [ - 0x9437E80E, 0x5C402F62, 0xA9CF3A1C, 0x5EA40A12, 0xE6E3FAC3, 0x96F31B72, 0xA4C3AB28, - 0x3455C2C7, 0x824571EE, 0x27609F5C, 0x46907450, 0x12F7AA8D, + ecc_priv_key: [ + 0xaf16a87e, 0x14729bb6, 0xa9912ded, 0xe8331772, 0x288451ff, 0x4a304f24, 0xe02438c3, + 0xf3413e68, 0x4862cca1, 0xfe65126b, 0x1f3d8677, 0x36424b27, ], } ); @@ -221,43 +222,43 @@ fn test_idevid() { #[derive(Clone, Copy, Debug, Eq, PartialEq)] pub struct LDevId { - pub cdi: [u32; 12], + pub cdi: [u32; 16], - pub priv_key: [u32; 12], + pub ecc_priv_key: [u32; 12], } impl LDevId { pub fn derive(doe_output: &DoeOutput) -> Self { let idevid = IDevId::derive(doe_output); - let mut cdi_seed: [u32; 12] = transmute!(hmac384( + let mut cdi_seed: [u32; 16] = transmute!(hmac512( swap_word_bytes(&idevid.cdi).as_bytes(), b"ldevid_cdi", )); swap_word_bytes_inplace(&mut cdi_seed); - let mut cdi: [u32; 12] = transmute!(hmac384( + let mut cdi: [u32; 16] = transmute!(hmac512( swap_word_bytes(&cdi_seed).as_bytes(), swap_word_bytes(&doe_output.field_entropy[0..8]).as_bytes(), )); swap_word_bytes_inplace(&mut cdi); - let mut priv_key_seed: [u32; 12] = transmute!(hmac384_kdf( + let mut priv_key_seed: [u32; 16] = transmute!(hmac512_kdf( swap_word_bytes(&cdi).as_bytes(), b"ldevid_ecc_key", None )); swap_word_bytes_inplace(&mut priv_key_seed); - let mut priv_key: [u32; 12] = transmute!(hmac384_drbg_keygen( - swap_word_bytes(&priv_key_seed).as_bytes(), + let mut ecc_priv_key: [u32; 12] = transmute!(hmac384_drbg_keygen( + &swap_word_bytes(&priv_key_seed).as_bytes()[..48], swap_word_bytes(&ECDSA_KEYGEN_NONCE).as_bytes() )); - swap_word_bytes_inplace(&mut priv_key); - Self { cdi, priv_key } + swap_word_bytes_inplace(&mut ecc_priv_key); + Self { cdi, ecc_priv_key } } pub fn derive_public_key(&self) -> PKey { derive_ecdsa_key( - swap_word_bytes(&self.priv_key) + swap_word_bytes(&self.ecc_priv_key) .as_bytes() .try_into() .unwrap(), @@ -281,13 +282,14 @@ fn test_ldevid() { ldevid, LDevId { cdi: [ - 0x2f711e48, 0xef2be87e, 0xfa3394af, 0x04a0df89, 0xb236860c, 0x745f6d6c, 0xa464de75, - 0x6f1271bc, 0xf35c0619, 0x0856f1e3, 0x7d560cf2, 0xaa227256, + 0x179d3c40, 0xddca767f, 0x47cd8c43, 0x4dfe5832, 0x9e8f8119, 0xec29ffeb, 0x21fb3af5, + 0xd50a5ab4, 0x2d7b7d1d, 0x61e96220, 0xbc161735, 0xc66dce6f, 0x6dd8e4ec, 0xa28b66d7, + 0x28788a5f, 0x6f845a7c, + ], + ecc_priv_key: [ + 0xec4cfba4, 0x28d8344c, 0xbb443f0d, 0xcca57231, 0x1b28d1df, 0x202aaff3, 0xc2f37cd3, + 0x7e1de81d, 0xfc624db2, 0x835f1a4, 0x37b02dbc, 0xd39e5a09, ], - priv_key: [ - 0xce7579e1, 0x37fe98bd, 0x54dd77e6, 0xc20331d, 0xe0ae1006, 0x64577cf9, 0xd04306f5, - 0x434d4dde, 0x43974611, 0x1ceb42a1, 0x2b6d1959, 0xbebeb390, - ] } ); } @@ -412,36 +414,36 @@ impl PcrRtCurrent { #[derive(Clone, Copy, Debug, Eq, PartialEq)] pub struct FmcAliasKey { // The FMC alias private key as stored in the key-vault - pub priv_key: [u32; 12], + pub ecc_priv_key: [u32; 12], - pub cdi: [u32; 12], + pub cdi: [u32; 16], } impl FmcAliasKey { pub fn derive(pcr0: &Pcr0, ldevid: &LDevId) -> Self { - let mut cdi: [u32; 12] = transmute!(hmac384_kdf( + let mut cdi: [u32; 16] = transmute!(hmac512_kdf( swap_word_bytes(&ldevid.cdi).as_bytes(), b"alias_fmc_cdi", Some(swap_word_bytes(&pcr0.0).as_bytes()), )); swap_word_bytes_inplace(&mut cdi); - let mut priv_key_seed: [u32; 12] = transmute!(hmac384_kdf( + let mut priv_key_seed: [u32; 16] = transmute!(hmac512_kdf( swap_word_bytes(&cdi).as_bytes(), b"alias_fmc_ecc_key", None )); swap_word_bytes_inplace(&mut priv_key_seed); - let mut priv_key: [u32; 12] = transmute!(hmac384_drbg_keygen( - swap_word_bytes(&priv_key_seed).as_bytes(), + let mut ecc_priv_key: [u32; 12] = transmute!(hmac384_drbg_keygen( + &swap_word_bytes(&priv_key_seed).as_bytes()[..48], swap_word_bytes(&ECDSA_KEYGEN_NONCE).as_bytes() )); - swap_word_bytes_inplace(&mut priv_key); - Self { priv_key, cdi } + swap_word_bytes_inplace(&mut ecc_priv_key); + Self { ecc_priv_key, cdi } } pub fn derive_public_key(&self) -> PKey { derive_ecdsa_key( - swap_word_bytes(&self.priv_key) + swap_word_bytes(&self.ecc_priv_key) .as_bytes() .try_into() .unwrap(), @@ -468,21 +470,21 @@ impl RtAliasKey { .copy_from_slice(&sha384(tci_input.manifest.as_bytes())); let mut cdi: [u32; 12] = transmute!(hmac384_kdf( - swap_word_bytes(&fmc_key.cdi).as_bytes(), + &swap_word_bytes(&fmc_key.cdi).as_bytes()[..48], b"rt_alias_cdi", Some(&tci), )); swap_word_bytes_inplace(&mut cdi); let mut priv_key_seed: [u32; 12] = transmute!(hmac384_kdf( - swap_word_bytes(&cdi).as_bytes(), + &swap_word_bytes(&cdi).as_bytes()[..48], b"rt_alias_keygen", None )); swap_word_bytes_inplace(&mut priv_key_seed); let mut priv_key: [u32; 12] = transmute!(hmac384_drbg_keygen( - swap_word_bytes(&priv_key_seed).as_bytes(), + &swap_word_bytes(&priv_key_seed).as_bytes()[..48], swap_word_bytes(&ECDSA_KEYGEN_NONCE).as_bytes() )); swap_word_bytes_inplace(&mut priv_key); @@ -508,9 +510,10 @@ fn test_derive_fmc_alias_key() { &LDevId { cdi: [ 0x0e7b8a15, 0x0cc1476b, 0x28d395d9, 0x233f9f05, 0x670bd435, 0x96758224, 0xd3dd5081, - 0x3da916e5, 0x94f2b09e, 0x257f151d, 0x261ade90, 0x73a9b3fb, + 0x3da916e5, 0x94f2b09e, 0x257f151d, 0x261ade90, 0x73a9b3fb, 0xf35c0619, 0x0856f1e3, + 0x7d560cf2, 0xaa227256, ], - priv_key: [ + ecc_priv_key: [ 0xd3ef1bff, 0x0b52919d, 0xe084ee81, 0x47544a50, 0xf7ff4c2d, 0x18038a26, 0x0695a0b1, 0x8103e7f4, 0x30651311, 0xc5658261, 0xe30ae241, 0xa8d9ad51, ], @@ -519,13 +522,14 @@ fn test_derive_fmc_alias_key() { assert_eq!( fmc_alias_key, FmcAliasKey { - priv_key: [ - 0xB0490161, 0xA1D2393A, 0x752E2F60, 0x4BB9A01E, 0x293B9E47, 0x61698007, 0x2CED9BAF, - 0x1F828679, 0xCB5054CD, 0xFD0EB072, 0x8D6BE59F, 0x75C55332 + ecc_priv_key: [ + 0xfcd8c50e, 0x45ddf47b, 0xe272c12c, 0x2a49576f, 0xb57f994d, 0x723de453, 0x14229ac9, + 0x714b2a8a, 0x6f1ce75f, 0x788cf75c, 0xdbe9da02, 0x51a22e82, ], cdi: [ - 0xCEAA7956, 0x4E5A8809, 0x7F1BF1B8, 0xA3A9C903, 0x37B4335F, 0xEA8A93D2, 0x5D02F1BF, - 0x16B1A537, 0xFE5DB006, 0xD8427583, 0x72C836F1, 0x9BE74AF5, + 0x41529a09, 0xe976d227, 0x456a211c, 0x86187b33, 0x15c88587, 0x60c51cb8, 0xfbcbb695, + 0xf67988dc, 0x14f6ae96, 0xc3dbdaa2, 0xad287006, 0x33a7f284, 0x81d964ce, 0x45af6c6b, + 0xdd8b95fd, 0x5cbcbc4b, ], } ); diff --git a/test/tests/caliptra_integration_tests/smoke_test.rs b/test/tests/caliptra_integration_tests/smoke_test.rs index d915d24059..c7b710b2f5 100644 --- a/test/tests/caliptra_integration_tests/smoke_test.rs +++ b/test/tests/caliptra_integration_tests/smoke_test.rs @@ -105,8 +105,9 @@ fn test_golden_idevid_pubkey_matches_generated() { assert_eq!( generated_idevid.cdi, [ - 0x4443b819, 0x8ca0984a, 0x2d566eed, 0x40f94074, 0x0c7cc63b, 0x85f939ac, 0xa2df92bf, - 0xb00f2f3e, 0x1e70ec47, 0x6736c596, 0x58a8a450, 0xeeac2f20, + 3736836117, 951734631, 1062246775, 1343680552, 3737486010, 473346827, 2246415195, + 914173071, 357859522, 506223632, 1064260590, 4040292325, 1807964448, 3683558581, + 3839832324, 1615123947, ] ); assert!(generated_idevid @@ -123,8 +124,9 @@ fn test_golden_ldevid_pubkey_matches_generated() { assert_eq!( generated_ldevid.cdi, [ - 0xf226cb0f, 0x1b527a8d, 0x9abeb5eb, 0xf407069a, 0xeda6909b, 0xad434d1d, 0x5f3586ff, - 0xa4729b8c, 0xd9e34ef9, 0xcb4317aa, 0x596674e5, 0x7f3c0f5b, + 0x34caaef4, 0x5b1cf2cc, 0x80034cc7, 0xda97ab04, 0xfcf1df75, 0x48896447, 0x81e51dd4, + 0x80638cbe, 0xe349cfad, 0x4d70b120, 0xcbf5cc76, 0x8c00bb5c, 0x10179e15, 0xfdd9244b, + 0x6226db25, 0xd4f08f3d, ] ); assert!(generated_ldevid @@ -429,7 +431,7 @@ fn smoke_test() { let rt_alias_cert_txt = String::from_utf8(rt_alias_cert.to_text().unwrap()).unwrap(); println!( - "Manifest digest is {:02x?}", + "Manifest Runtime digest is {:02x?}", image.manifest.runtime.digest.as_bytes() ); let expected_rt_alias_key = RtAliasKey::derive( diff --git a/test/tests/caliptra_integration_tests/smoke_testdata/fmc_alias_cert_redacted.der b/test/tests/caliptra_integration_tests/smoke_testdata/fmc_alias_cert_redacted.der index ce0d4844c5e0260128b759ba3cd5baa1e55be5b5..2cbe7ddd85bbe584457f1a882e2dfcea28552997 100644 GIT binary patch delta 100 zcmaFG_KIynl!J?#v$30no4KKzvyq93v!$b%k(;TZsiCWrfwP&DtBH}hxrvdJv#Ya- zfwPG*P{PsD$->ma($vz_)XdDxapNp^CXxGxe|(oeZoT0liXHZeFvLPSDEMMW?-I6*TvIX6Q!MKeN0LpC@yHA6HpHZVd% zGcZFmK{PcpGc`CdMmaP?HA6T;G(s~sFgdZBM*(FgQdsLpC%wL^3i)F)~6lIYUD< zH#tHwF+?yqGBZRlMKwe?F)=qXLODS}F)%YkL_iGrUw&l>`@uLscXG9X8UNwh}1UXaWJRT!i4oPX@@~MRIJ&Kkkt5c z^DB=d5)|7^hwN;ir4tX;$7S%Ww(%U4)I*KD2r$re3)SiFpV8FOE465fss5933z6<+ zXlDR0WCAcEltGo4hl#WMb!T$tas19$nv5WvU z1=^MZFjRj-T$@4gJKcRivKghw7KOLSg&m$I8@g}RYe*oC>ajuB_|&D>R%cO#NRSG# E${-Vd7XSbN delta 307 zcmV-30nGlp1H1zSFoFTNkpwb-MMN}3F+)T$IYU7~Geku(H8?~@ML{=1G%z_gGdM9b zIYmV+GpEL?eOvb1=7P$;N^8{k8 zQV$}Npq{m?IOLgHRBQ}>+AdhkyxAkrNGy2D_;JyDT4oCz1!~gCnX5>19J%f|CXw!C zX=ng2Wdbn(tc(xX`nS`(U}tEA&z|3<&ri4s^0JM_BKJ)@eFHC79d}u=YH@#9f5$-t zKm{s^0x(Nwlz_U4M|p0pdXb9NRuu?yXgo^=+qu%4v3&;Huj)$HWwH~;%I#l&ZOogB FZD3wkcC7#a diff --git a/test/tests/caliptra_integration_tests/smoke_testdata/idevid_csr.txt b/test/tests/caliptra_integration_tests/smoke_testdata/idevid_csr.txt index 4db9c32ca1..61b0b36de3 100644 --- a/test/tests/caliptra_integration_tests/smoke_testdata/idevid_csr.txt +++ b/test/tests/caliptra_integration_tests/smoke_testdata/idevid_csr.txt @@ -1,18 +1,18 @@ Certificate Request: Data: Version: 1 (0x0) - Subject: CN=Caliptra 1.0 IDevID/serialNumber=ED4E1CD29CAA3DE158DFEA7C409738139EE05F4CA1A2F8A033AAB171B68A1312 + Subject: CN=Caliptra 1.0 IDevID/serialNumber=A4E4087E3C1F08D4C647D22F12B49CC479B21D0923D0E5D81172B9AA103DDCCA Subject Public Key Info: Public Key Algorithm: id-ecPublicKey Public-Key: (384 bit) pub: - 04:5b:13:09:96:1b:c5:66:e3:4d:37:2a:7b:52:2b: - 9b:4c:d7:b4:78:e8:45:22:eb:32:33:51:00:ba:e0: - 90:de:bf:9f:34:0a:4a:4c:c6:a8:16:b9:0c:3b:f3: - 04:62:ad:52:0f:22:93:a0:9e:b5:ac:38:e4:99:5a: - 54:6c:0c:7e:da:2e:58:cc:bc:d9:23:d0:48:2c:78: - ca:f8:71:d1:7b:5a:66:0b:1c:05:6a:d2:c9:99:ab: - 48:73:1c:b9:ee:38:26 + 04:06:3d:ee:99:b8:27:78:0d:a6:07:13:6e:ec:51: + 19:bd:a9:6b:bd:36:66:fb:68:c4:88:d4:36:e2:71: + 30:a7:d3:c2:84:f5:31:69:87:41:54:ac:d9:8e:90: + d4:f8:72:f3:2b:8f:23:12:14:db:4c:87:ec:6c:a0: + a5:13:0f:d5:c7:65:f0:ac:b6:f1:1c:94:d4:43:8d: + bc:08:30:d0:74:0b:d5:e9:ee:9f:d1:d4:d1:2b:b5: + 68:8a:a9:fe:93:71:0b ASN1 OID: secp384r1 NIST CURVE: P-384 Attributes: @@ -25,9 +25,9 @@ Certificate Request: 0.................... Signature Algorithm: ecdsa-with-SHA384 Signature Value: - 30:65:02:31:00:ac:8c:0f:d8:fa:b7:d3:bc:60:67:68:84:cf: - 9e:df:a5:cf:4f:b8:09:f2:b2:8d:c6:22:f7:4d:3b:7d:03:2f: - 57:1d:77:59:b1:6a:71:7f:58:7f:c7:41:04:40:05:2a:89:02: - 30:4b:67:94:80:ba:89:47:79:6e:ae:7a:91:8a:d5:56:15:08: - 73:68:3c:4b:05:db:b9:d2:9b:b1:7d:06:db:af:ea:4a:d6:65: - b2:13:c7:ca:ed:5f:7f:6d:cc:9b:8a:6d:60 + 30:64:02:30:22:94:41:95:98:87:89:b3:fb:75:67:72:e7:e3: + f2:b0:3f:12:5d:4d:92:e5:8b:d8:c2:a0:44:4a:0c:bc:94:77: + c2:3d:62:0d:cc:a8:0e:6f:b5:b1:8c:00:35:05:da:96:02:30: + 54:7f:43:5c:9b:41:f0:3b:dd:7d:40:b2:19:a5:c8:16:85:b7: + c8:85:1d:9e:26:1b:ba:6f:d5:6b:48:20:8d:ea:b1:41:d7:f8: + d4:a5:d7:56:67:51:85:48:90:0a:b1:ca diff --git a/test/tests/caliptra_integration_tests/smoke_testdata/ldevid_cert.der b/test/tests/caliptra_integration_tests/smoke_testdata/ldevid_cert.der index dce4f7d88d22834c7a8d0172c1df5c1b92f8c27e..4114083c4e5d38b4fa721baba12ca4fb4dd90245 100644 GIT binary patch delta 473 zcmZ3)x{y`bpowWN5UVU;W@2Pw5{Wz$($Ue- zz}Usb+1YX8EdP2JH)mrv3paB^H)kUg6K6|DGb1-sLsLUnCj)0QCsz|Ab8{0TCudh@ z69Z=xW1xhirIUrJg{7&bsi~QnnWI6OfdCu3R-4B;TP8*}R_#U>1|{Ys1{Tia&yz2* z|FkIPds)r*LHP6fh12G(7QKTCRTkrv5CZe*If( znB=y%eHQ)gcq`%il0BBTE$420@jtMH)BI4+*PZ*8S8cd+#4+Pw!Smj5#>opA!|Ly2 z2^j-fWu!C8cnVHiW3{sd3 za$5>wwYuB>_+6TFNbqs*?$?K$KXy(rUCv~fz0%C`S9kxGy3NUP?<}n2ydSTVR$^f? zFuBHb=Z1F2ljQY$30k$UqW?^}#1zf^F1_#EgH_8#7QAS1(ukVB9hU7bh1dSD<2Z3rAyfOLJ#aS7RqvXEO^^Q)d%HGXp1QV*_Us zM-x+HV^a%5H%k*|Q)de&6DMPH151N40|7R6tu~KywoHs{tlEt%3`)#N3@lG7{#)=C zByc_a)*S!z)l;K0>+;3rEt91l-%m*lsN5Fln7wquVds684jffo59drsi!6G)tg$O_ z#{5HbeC@4G_fJ;7f43^<)AaaLE~@5#3!GSvE^pc0zUZ*xwnPhV7ssad$qO07>R(|A z83TDX=1^H>76}8f29XE*bz3f`7S8b5s#lVgeB@@adw8?~7aIrI!7R+o%oz*@sZ0g| z=ih7T-~N|t@k(>9-rqjW$4lcivKwx6SMC0C Date: Mon, 2 Dec 2024 16:50:50 -0800 Subject: [PATCH 32/51] [feat] Increase ROM size from 48 KB to 96 KB (#1827) --- builder/src/lib.rs | 2 +- builder/src/testdata/example.rom.golden | Bin 49152 -> 98304 bytes drivers/src/memory_layout.rs | 2 +- fmc/Makefile | 4 ++-- hw/fpga/rom_backdoor/rom_backdoor.c | 2 +- rom/dev/src/rom.ld | 2 +- sw-emulator/lib/cpu/src/cpu.rs | 2 +- sw-emulator/lib/periph/src/root_bus.rs | 2 +- 8 files changed, 8 insertions(+), 8 deletions(-) diff --git a/builder/src/lib.rs b/builder/src/lib.rs index e9edb0a0b7..7ffb0c5ff1 100644 --- a/builder/src/lib.rs +++ b/builder/src/lib.rs @@ -368,7 +368,7 @@ pub fn build_firmware_rom(id: &FwId<'static>) -> io::Result> { } pub fn elf2rom(elf_bytes: &[u8]) -> io::Result> { - let mut result = vec![0u8; 0xC000]; + let mut result = vec![0u8; 0x18000]; let elf = elf::ElfBytes::::minimal_parse(elf_bytes).map_err(other_err)?; let Some(segments) = elf.segments() else { diff --git a/builder/src/testdata/example.rom.golden b/builder/src/testdata/example.rom.golden index 110bf85ae7df63f48f85f25e53a8e521066e3202..e7fd32ab89cd9064561e73f59b23b1795747b073 100644 GIT binary patch delta 16 XcmZo@U~Xt&TX0~bz=!;e0s;X5I->@w delta 8 PcmZo@U~6b#UT^>a4mAU6 diff --git a/drivers/src/memory_layout.rs b/drivers/src/memory_layout.rs index 70dc9edbd8..28c2cb0e6c 100644 --- a/drivers/src/memory_layout.rs +++ b/drivers/src/memory_layout.rs @@ -60,7 +60,7 @@ pub const ROM_NSTACK_ORG: u32 = NSTACK_ORG; // Memory Sizes In Bytes // pub const ROM_RELAXATION_PADDING: u32 = 4 * 1024; -pub const ROM_SIZE: u32 = 48 * 1024; +pub const ROM_SIZE: u32 = 96 * 1024; pub const MBOX_SIZE: u32 = 128 * 1024; pub const ICCM_SIZE: u32 = 128 * 1024; pub const DCCM_SIZE: u32 = 128 * 1024; diff --git a/fmc/Makefile b/fmc/Makefile index 4672911301..04f2e7a761 100644 --- a/fmc/Makefile +++ b/fmc/Makefile @@ -44,7 +44,7 @@ build-rom: objcopy-rom: riscv64-unknown-elf-objcopy \ --gap-fill 0x00 \ - --pad-to 0xC000 \ + --pad-to 0x18000 \ -j .text \ -j .rodata \ -O binary \ @@ -101,7 +101,7 @@ objdump: objcopy: riscv32imc-unknown-elf-objcopy \ --gap-fill 0x00 \ - --pad-to 0xC000 \ + --pad-to 0x18000 \ -j .text \ -j .rodata \ -O binary \ diff --git a/hw/fpga/rom_backdoor/rom_backdoor.c b/hw/fpga/rom_backdoor/rom_backdoor.c index 5f888afc97..f6660fd94e 100644 --- a/hw/fpga/rom_backdoor/rom_backdoor.c +++ b/hw/fpga/rom_backdoor/rom_backdoor.c @@ -12,7 +12,7 @@ #define ROM_BACKDOOR_MAJOR_ID 47 #define ROM_ADDRESS 0x82000000 -#define ROM_SIZE 0xC000 +#define ROM_SIZE 0x18000 struct rom_backdoor_backend_data { diff --git a/rom/dev/src/rom.ld b/rom/dev/src/rom.ld index 8ba6fb2c6d..bc3e6908f6 100644 --- a/rom/dev/src/rom.ld +++ b/rom/dev/src/rom.ld @@ -32,7 +32,7 @@ CFI_STATE_ORG = 0x500003E4; * ensure that the sections fit within the true 48k ROM size. */ ROM_RELAXATION_PADDING = 8k; -ROM_SIZE = 48K; +ROM_SIZE = 96K; ICCM_SIZE = 128K; DCCM_SIZE = 128K; DATA_SIZE = 996; diff --git a/sw-emulator/lib/cpu/src/cpu.rs b/sw-emulator/lib/cpu/src/cpu.rs index 07cf7d765d..942ca383ea 100644 --- a/sw-emulator/lib/cpu/src/cpu.rs +++ b/sw-emulator/lib/cpu/src/cpu.rs @@ -37,7 +37,7 @@ const ICCM_SIZE: usize = 128 * 1024; const ICCM_ORG: usize = 0x40000000; const ICCM_UPPER: usize = ICCM_ORG + ICCM_SIZE - 1; -const ROM_SIZE: usize = 48 * 1024; +const ROM_SIZE: usize = 96 * 1024; const ROM_ORG: usize = 0x00000000; const ROM_UPPER: usize = ROM_ORG + ROM_SIZE - 1; diff --git a/sw-emulator/lib/periph/src/root_bus.rs b/sw-emulator/lib/periph/src/root_bus.rs index 7b9a5568ba..879ee666d2 100644 --- a/sw-emulator/lib/periph/src/root_bus.rs +++ b/sw-emulator/lib/periph/src/root_bus.rs @@ -312,7 +312,7 @@ pub struct CaliptraRootBus { } impl CaliptraRootBus { - pub const ROM_SIZE: usize = 48 * 1024; + pub const ROM_SIZE: usize = 96 * 1024; pub const ICCM_SIZE: usize = 128 * 1024; pub const DCCM_SIZE: usize = 128 * 1024; From 3230230b46e9aac09fd720d4cffa116425248577 Mon Sep 17 00:00:00 2001 From: Arthur Heymans Date: Tue, 3 Dec 2024 21:42:55 +0100 Subject: [PATCH 33/51] sw-emulator: MlDsa87 Fix endianness (#1831) The format of the hardware to represent MLDSA87 is big endian. This mistake entered by copying the ecc384 peripheral which switches endianness inside the lib/crypto and not inside the emulator peripheral. --- drivers/test-fw/src/bin/mldsa87_tests.rs | 706 +++++++++--------- sw-emulator/lib/periph/src/ml_dsa87.rs | 42 +- .../src/test_data/ml_dsa87_test_data.rs | 700 ++++++++--------- 3 files changed, 718 insertions(+), 730 deletions(-) diff --git a/drivers/test-fw/src/bin/mldsa87_tests.rs b/drivers/test-fw/src/bin/mldsa87_tests.rs index ec3c47a0cd..1ec433e1aa 100644 --- a/drivers/test-fw/src/bin/mldsa87_tests.rs +++ b/drivers/test-fw/src/bin/mldsa87_tests.rs @@ -30,362 +30,361 @@ use caliptra_registers::soc_ifc_trng::SocIfcTrngReg; use caliptra_test_harness::test_suite; const PUBKEY: [u8; 2592] = [ - 251, 202, 217, 224, 179, 133, 165, 63, 79, 52, 212, 239, 6, 145, 130, 220, 45, 173, 142, 113, - 182, 61, 254, 182, 63, 92, 58, 184, 26, 206, 128, 249, 150, 238, 171, 190, 52, 113, 142, 191, - 39, 216, 4, 52, 168, 202, 179, 10, 194, 99, 157, 193, 210, 194, 71, 144, 18, 54, 54, 188, 120, - 162, 209, 234, 103, 155, 208, 98, 79, 123, 21, 75, 247, 74, 17, 226, 112, 140, 96, 21, 117, 33, - 195, 133, 31, 156, 29, 46, 81, 106, 124, 66, 236, 49, 108, 49, 221, 166, 49, 219, 149, 101, - 186, 165, 103, 72, 121, 232, 128, 208, 59, 226, 199, 172, 189, 255, 116, 43, 140, 73, 249, 134, - 77, 240, 38, 23, 178, 38, 41, 56, 237, 254, 135, 47, 19, 236, 232, 86, 49, 221, 126, 135, 102, - 151, 195, 178, 79, 24, 36, 117, 33, 168, 161, 111, 8, 12, 48, 50, 178, 59, 76, 101, 219, 46, - 220, 43, 248, 112, 224, 251, 87, 244, 202, 145, 160, 40, 223, 147, 84, 134, 108, 156, 99, 106, - 190, 172, 217, 252, 82, 175, 176, 209, 86, 119, 78, 187, 102, 149, 217, 62, 7, 146, 82, 246, - 49, 170, 132, 222, 154, 181, 140, 101, 238, 242, 209, 124, 112, 132, 6, 232, 243, 54, 41, 199, - 194, 233, 200, 182, 236, 161, 174, 4, 236, 91, 229, 27, 246, 218, 245, 246, 163, 86, 88, 82, - 43, 214, 54, 162, 81, 119, 164, 252, 236, 237, 169, 1, 76, 108, 89, 187, 70, 191, 79, 40, 187, - 122, 70, 230, 249, 31, 225, 192, 121, 213, 208, 42, 165, 200, 231, 210, 98, 109, 198, 67, 62, - 122, 211, 197, 211, 232, 23, 42, 25, 199, 221, 18, 173, 164, 119, 86, 216, 166, 209, 184, 86, - 38, 51, 70, 101, 175, 226, 133, 153, 45, 66, 167, 215, 227, 252, 147, 207, 121, 191, 192, 126, - 237, 122, 66, 84, 245, 48, 25, 40, 221, 154, 15, 11, 185, 170, 155, 52, 134, 34, 3, 249, 54, - 46, 6, 215, 89, 72, 83, 40, 253, 55, 189, 41, 138, 189, 164, 200, 52, 224, 60, 55, 125, 16, - 191, 74, 59, 102, 14, 208, 83, 169, 237, 121, 149, 222, 177, 56, 157, 254, 226, 220, 140, 251, - 63, 242, 238, 32, 233, 106, 23, 126, 131, 167, 153, 169, 80, 171, 202, 72, 67, 130, 86, 19, 11, - 1, 34, 112, 19, 58, 2, 58, 35, 34, 178, 141, 86, 57, 236, 39, 223, 229, 194, 69, 227, 63, 14, - 7, 209, 32, 147, 235, 244, 102, 229, 99, 51, 104, 218, 89, 95, 245, 19, 152, 93, 123, 134, 214, - 60, 255, 69, 134, 4, 171, 49, 12, 31, 130, 171, 249, 97, 155, 157, 227, 69, 1, 200, 182, 45, - 44, 84, 187, 101, 106, 95, 150, 127, 20, 102, 234, 15, 192, 24, 48, 218, 67, 112, 67, 246, 202, - 145, 243, 55, 102, 0, 238, 30, 16, 192, 218, 30, 70, 183, 155, 74, 36, 100, 46, 116, 30, 232, - 226, 159, 162, 101, 99, 12, 144, 223, 145, 113, 164, 20, 219, 200, 84, 85, 175, 119, 7, 180, - 30, 89, 106, 227, 214, 113, 7, 51, 194, 77, 70, 95, 235, 161, 32, 248, 57, 106, 6, 74, 154, 18, - 183, 71, 217, 64, 178, 201, 235, 205, 231, 187, 47, 20, 123, 15, 20, 69, 45, 199, 254, 56, 67, - 33, 135, 207, 152, 169, 237, 2, 153, 44, 252, 67, 232, 70, 199, 177, 218, 111, 10, 89, 42, 155, - 171, 225, 45, 53, 71, 132, 34, 247, 202, 198, 223, 42, 22, 206, 158, 152, 46, 111, 174, 98, 67, - 159, 131, 12, 207, 71, 233, 45, 221, 78, 154, 245, 139, 116, 98, 0, 208, 118, 68, 3, 122, 111, - 55, 104, 163, 36, 200, 77, 230, 149, 55, 121, 235, 52, 245, 102, 115, 172, 83, 20, 206, 142, - 97, 154, 57, 242, 250, 155, 68, 99, 71, 170, 91, 180, 192, 115, 143, 177, 91, 133, 91, 238, - 173, 72, 164, 80, 121, 139, 68, 121, 165, 111, 32, 219, 134, 48, 92, 121, 190, 243, 71, 183, - 44, 195, 24, 239, 52, 88, 255, 231, 104, 55, 37, 52, 168, 216, 74, 103, 66, 89, 90, 248, 65, - 134, 29, 54, 34, 46, 220, 228, 236, 83, 85, 168, 173, 126, 231, 239, 116, 98, 222, 232, 243, - 98, 207, 158, 189, 168, 197, 211, 158, 73, 245, 204, 184, 88, 227, 193, 72, 56, 191, 184, 185, - 193, 252, 156, 189, 211, 79, 99, 35, 237, 17, 208, 73, 226, 215, 93, 137, 67, 28, 8, 52, 19, - 72, 35, 82, 27, 48, 206, 218, 75, 152, 205, 139, 135, 74, 100, 146, 167, 181, 158, 61, 159, 92, - 122, 95, 253, 250, 218, 147, 235, 143, 206, 137, 16, 205, 86, 109, 189, 163, 8, 62, 153, 100, - 66, 15, 244, 112, 135, 71, 91, 251, 35, 102, 100, 185, 203, 222, 234, 97, 135, 80, 0, 221, 248, - 253, 109, 64, 25, 97, 205, 92, 33, 227, 247, 193, 55, 128, 203, 177, 63, 126, 75, 9, 134, 167, - 123, 107, 250, 87, 16, 172, 146, 58, 179, 145, 47, 149, 114, 225, 11, 2, 232, 121, 249, 219, - 59, 18, 14, 73, 165, 248, 116, 58, 210, 28, 163, 147, 167, 232, 250, 201, 224, 244, 78, 218, - 70, 73, 76, 94, 233, 205, 204, 13, 103, 173, 123, 195, 169, 130, 42, 185, 180, 59, 156, 149, - 150, 246, 66, 255, 133, 23, 91, 123, 145, 18, 217, 25, 106, 100, 195, 207, 242, 64, 1, 23, 209, - 140, 109, 140, 211, 17, 31, 178, 212, 140, 169, 12, 121, 116, 224, 53, 225, 4, 221, 177, 53, - 127, 28, 193, 213, 46, 35, 113, 34, 50, 197, 16, 73, 65, 212, 114, 89, 137, 7, 216, 82, 0, 49, - 13, 79, 164, 147, 205, 102, 242, 144, 217, 233, 231, 46, 213, 78, 134, 120, 13, 148, 244, 194, - 109, 202, 242, 13, 94, 61, 231, 171, 210, 70, 107, 100, 186, 172, 35, 143, 187, 190, 190, 120, - 12, 181, 242, 171, 125, 183, 39, 22, 110, 186, 142, 218, 141, 19, 163, 138, 214, 162, 143, 16, - 33, 29, 209, 238, 235, 152, 29, 91, 139, 132, 118, 212, 19, 148, 26, 230, 231, 227, 202, 101, - 3, 164, 189, 59, 223, 125, 140, 86, 217, 153, 134, 70, 84, 161, 48, 50, 189, 180, 46, 148, 181, - 83, 213, 53, 247, 106, 208, 249, 91, 114, 9, 189, 15, 134, 219, 74, 89, 228, 125, 57, 159, 70, - 139, 97, 63, 89, 182, 145, 247, 251, 196, 70, 20, 60, 166, 244, 218, 78, 133, 253, 8, 241, 66, - 125, 200, 146, 222, 49, 90, 214, 217, 201, 151, 42, 209, 206, 165, 191, 68, 31, 112, 173, 183, - 113, 243, 193, 115, 3, 77, 152, 132, 85, 58, 243, 138, 211, 35, 49, 51, 131, 194, 105, 171, - 109, 97, 154, 6, 134, 53, 145, 98, 155, 79, 11, 175, 244, 192, 50, 108, 207, 208, 12, 48, 205, - 243, 47, 78, 77, 50, 196, 177, 188, 249, 207, 188, 223, 180, 42, 44, 153, 252, 147, 66, 159, - 140, 127, 56, 148, 124, 168, 32, 67, 56, 106, 19, 194, 202, 51, 51, 46, 214, 208, 34, 191, 165, - 93, 23, 169, 89, 199, 232, 26, 185, 72, 48, 111, 49, 215, 82, 251, 170, 151, 159, 204, 248, - 120, 183, 64, 199, 223, 110, 46, 90, 215, 236, 135, 90, 81, 185, 82, 153, 104, 143, 17, 178, - 107, 27, 123, 184, 19, 126, 47, 135, 138, 172, 199, 109, 240, 225, 3, 215, 141, 185, 78, 105, - 191, 85, 141, 113, 161, 86, 228, 111, 76, 38, 138, 72, 60, 148, 178, 52, 83, 191, 185, 19, 145, - 212, 142, 115, 27, 124, 64, 25, 2, 30, 167, 184, 64, 148, 109, 117, 145, 123, 158, 165, 95, 81, - 68, 39, 6, 27, 248, 161, 154, 139, 133, 93, 18, 50, 7, 29, 231, 239, 135, 251, 93, 117, 54, 38, - 27, 90, 173, 210, 243, 98, 238, 110, 41, 30, 187, 191, 219, 154, 10, 24, 231, 253, 128, 99, - 101, 248, 44, 107, 60, 225, 45, 145, 146, 231, 8, 146, 82, 120, 163, 56, 89, 165, 120, 21, 233, - 15, 24, 147, 145, 238, 236, 209, 28, 187, 168, 103, 92, 99, 111, 197, 157, 12, 236, 53, 126, - 174, 31, 243, 115, 190, 67, 186, 64, 253, 40, 172, 145, 222, 8, 27, 37, 35, 196, 131, 214, 139, - 26, 206, 229, 225, 159, 22, 184, 151, 170, 205, 128, 134, 98, 108, 40, 184, 80, 23, 145, 76, - 164, 182, 221, 61, 180, 207, 9, 187, 115, 242, 169, 46, 143, 223, 176, 36, 128, 109, 87, 15, - 237, 27, 96, 69, 52, 144, 109, 190, 217, 92, 196, 167, 101, 57, 70, 117, 122, 129, 239, 101, - 78, 137, 113, 238, 102, 221, 100, 172, 190, 230, 245, 68, 91, 6, 98, 97, 246, 46, 152, 152, - 224, 45, 36, 38, 154, 222, 77, 1, 215, 62, 197, 55, 83, 83, 202, 172, 52, 5, 37, 181, 209, 137, - 65, 109, 176, 168, 237, 20, 183, 46, 140, 19, 209, 239, 19, 183, 224, 221, 191, 163, 237, 151, - 208, 98, 130, 201, 75, 59, 159, 171, 198, 182, 42, 167, 1, 63, 28, 62, 104, 212, 8, 220, 216, - 199, 120, 127, 25, 160, 198, 186, 119, 84, 73, 29, 11, 195, 31, 239, 232, 116, 110, 212, 76, - 243, 148, 138, 1, 105, 166, 130, 98, 189, 28, 82, 20, 171, 118, 51, 132, 246, 238, 249, 220, - 210, 147, 164, 205, 72, 7, 175, 85, 217, 179, 230, 210, 85, 222, 69, 39, 151, 89, 225, 243, - 124, 210, 247, 204, 56, 171, 59, 149, 112, 29, 14, 11, 178, 214, 192, 43, 132, 151, 57, 62, - 152, 48, 74, 117, 104, 209, 63, 67, 126, 6, 64, 160, 94, 147, 216, 31, 4, 20, 190, 197, 180, - 129, 116, 146, 46, 25, 226, 124, 120, 56, 197, 23, 82, 144, 106, 119, 132, 101, 196, 201, 191, - 164, 15, 141, 212, 167, 169, 43, 151, 22, 190, 202, 152, 101, 82, 173, 171, 141, 253, 1, 113, - 215, 49, 30, 15, 8, 122, 42, 60, 46, 108, 11, 230, 175, 201, 64, 160, 6, 211, 214, 247, 72, 32, - 182, 29, 170, 133, 80, 63, 247, 9, 249, 118, 130, 44, 243, 185, 137, 8, 16, 121, 191, 92, 54, - 231, 184, 0, 223, 41, 178, 253, 12, 232, 48, 235, 39, 104, 191, 77, 189, 7, 122, 76, 189, 207, - 50, 15, 138, 172, 13, 163, 37, 121, 83, 211, 155, 42, 110, 190, 24, 238, 41, 35, 42, 197, 240, - 185, 56, 218, 65, 213, 86, 174, 114, 55, 182, 250, 117, 42, 109, 85, 44, 174, 101, 59, 124, - 170, 81, 166, 210, 142, 236, 105, 179, 13, 243, 8, 166, 64, 162, 209, 57, 237, 144, 142, 188, - 245, 219, 157, 171, 112, 228, 93, 2, 211, 143, 202, 226, 244, 194, 107, 14, 78, 122, 49, 150, - 234, 18, 78, 111, 178, 60, 106, 225, 19, 85, 72, 42, 211, 201, 54, 157, 93, 77, 61, 54, 124, - 218, 158, 31, 112, 30, 141, 199, 176, 135, 245, 84, 240, 215, 26, 219, 1, 21, 196, 97, 153, 19, - 141, 55, 103, 195, 147, 80, 132, 91, 21, 211, 73, 157, 11, 8, 177, 67, 45, 209, 119, 233, 219, - 124, 141, 52, 196, 84, 39, 249, 225, 155, 89, 206, 235, 70, 142, 136, 171, 238, 127, 63, 155, - 106, 121, 33, 1, 240, 8, 100, 222, 147, 77, 115, 82, 140, 244, 222, 5, 143, 55, 167, 71, 79, - 155, 27, 12, 194, 231, 90, 102, 15, 10, 136, 199, 77, 118, 166, 133, 87, 132, 161, 239, 211, - 196, 120, 57, 149, 139, 243, 131, 121, 235, 41, 213, 78, 225, 179, 16, 175, 238, 7, 73, 225, - 74, 250, 184, 105, 188, 21, 228, 190, 20, 163, 120, 14, 194, 195, 9, 34, 35, 98, 149, 233, 79, - 164, 116, 179, 133, 219, 251, 212, 194, 94, 83, 125, 78, 113, 9, 144, 80, 36, 184, 193, 86, - 168, 242, 115, 62, 119, 225, 212, 247, 42, 237, 173, 140, 90, 125, 42, 209, 168, 87, 5, 183, - 92, 1, 221, 167, 56, 73, 209, 44, 45, 18, 177, 121, 59, 204, 85, 25, 230, 206, 101, 161, 199, - 95, 186, 156, 152, 235, 141, 223, 26, 99, 47, 198, 92, 168, 2, 26, 255, 132, 126, 75, 30, 168, - 88, 12, 84, 157, 59, 106, 166, 127, 77, 82, 149, 49, 226, 171, 188, 95, 13, 255, 58, 191, 244, - 143, 128, 251, 165, 141, 149, 18, 190, 195, 70, 186, 129, 45, 19, 123, 0, 246, 162, 108, 42, - 163, 82, 112, 90, 101, 59, 173, 163, 182, 243, 241, 201, 78, 168, 6, 135, 191, 15, 66, 168, 19, - 150, 10, 37, 173, 88, 188, 72, 219, 182, 164, 163, 173, 238, 120, 154, 199, 176, 242, 19, 149, - 48, 4, 16, 234, 77, 95, 124, 144, 106, 115, 75, 119, 68, 184, 34, 91, 10, 122, 151, 236, 34, - 51, 69, 5, 209, 221, 157, 80, 74, 137, 94, 48, 14, 54, 35, 99, 16, 231, 202, 51, 155, 214, 227, - 128, 10, 173, 129, 98, 59, 62, 235, 203, 22, 198, 84, 95, 123, 109, 126, 7, 169, 173, 13, 240, - 240, 2, 150, 153, 212, 39, 183, 28, 17, 175, 149, 224, 53, 199, 160, 144, 179, 205, 0, 183, - 226, 243, 16, 209, 75, 155, 176, 80, 12, 161, 180, 188, 222, 101, 42, 105, 117, 207, 108, 166, - 240, 96, 10, 27, 101, 160, 89, 156, 5, 43, 137, 58, 32, 168, 160, 11, 82, 81, 89, 34, 254, 75, - 62, 83, 113, 79, 174, 59, 103, 172, 30, 231, 61, 145, 197, 211, 188, 184, 49, 168, 194, 13, - 185, 36, 113, 92, 99, 128, 155, 100, 143, 240, 81, 85, 13, 49, 232, 156, 183, 113, 141, 157, - 164, 34, 170, 148, 102, 48, 245, 128, 252, 234, 95, 218, 245, 174, 124, 71, 253, 127, 135, 191, - 233, 134, 86, 133, 72, 214, 126, 102, 118, 167, 149, 20, 70, 0, 97, 236, 187, 103, 160, 63, 95, - 191, 100, 61, 123, 173, 187, 217, 203, 56, 251, 72, 243, 180, 136, 88, 252, 106, 181, 155, 59, - 159, 101, 114, 1, 201, 74, 30, 229, 188, 6, 202, 195, 105, 242, 133, 101, 215, 135, 119, 98, - 157, 31, 160, 61, 64, 90, 229, 130, 90, 246, 202, 4, 127, 31, 191, 143, 250, 203, 49, 77, 95, - 68, 123, 207, 184, 47, 107, 200, 227, 228, 178, 21, 184, 163, 6, 26, 23, 11, 106, 159, 206, 99, - 201, 83, 58, 188, 54, 57, 181, 146, 137, 36, 139, 104, 79, 21, 147, 77, 105, 82, 20, 144, 12, - 82, 235, 59, 93, 192, 126, 111, 235, 68, 181, 59, 222, 188, 66, 204, 62, 30, 74, 105, 95, 139, - 91, 211, 25, 217, 140, 75, 158, 207, 77, 67, 206, 141, 191, 45, 113, 20, 53, 184, 255, 155, - 202, 94, 68, 205, 24, 1, 53, 108, 0, 7, 194, 245, 124, 15, 49, 24, 211, 156, 12, 96, 143, 196, - 68, 72, 47, 171, 95, 242, 43, 45, 94, 82, 212, 91, 238, 50, 242, 205, 249, 161, 208, 50, 109, - 147, + 224, 217, 202, 251, 63, 165, 133, 179, 239, 212, 52, 79, 220, 130, 145, 6, 113, 142, 173, 45, + 182, 254, 61, 182, 184, 58, 92, 63, 249, 128, 206, 26, 190, 171, 238, 150, 191, 142, 113, 52, + 52, 4, 216, 39, 10, 179, 202, 168, 193, 157, 99, 194, 144, 71, 194, 210, 188, 54, 54, 18, 234, + 209, 162, 120, 98, 208, 155, 103, 75, 21, 123, 79, 226, 17, 74, 247, 21, 96, 140, 112, 133, + 195, 33, 117, 46, 29, 156, 31, 66, 124, 106, 81, 49, 108, 49, 236, 219, 49, 166, 221, 165, 186, + 101, 149, 232, 121, 72, 103, 226, 59, 208, 128, 255, 189, 172, 199, 73, 140, 43, 116, 240, 77, + 134, 249, 38, 178, 23, 38, 254, 237, 56, 41, 236, 19, 47, 135, 221, 49, 86, 232, 151, 102, 135, + 126, 24, 79, 178, 195, 168, 33, 117, 36, 12, 8, 111, 161, 59, 178, 50, 48, 46, 219, 101, 76, + 112, 248, 43, 220, 244, 87, 251, 224, 40, 160, 145, 202, 134, 84, 147, 223, 106, 99, 156, 108, + 252, 217, 172, 190, 209, 176, 175, 82, 187, 78, 119, 86, 62, 217, 149, 102, 246, 82, 146, 7, + 222, 132, 170, 49, 101, 140, 181, 154, 124, 209, 242, 238, 232, 6, 132, 112, 199, 41, 54, 243, + 182, 200, 233, 194, 4, 174, 161, 236, 27, 229, 91, 236, 246, 245, 218, 246, 82, 88, 86, 163, + 162, 54, 214, 43, 252, 164, 119, 81, 1, 169, 237, 236, 187, 89, 108, 76, 40, 79, 191, 70, 230, + 70, 122, 187, 192, 225, 31, 249, 42, 208, 213, 121, 210, 231, 200, 165, 67, 198, 109, 98, 197, + 211, 122, 62, 42, 23, 232, 211, 18, 221, 199, 25, 86, 119, 164, 173, 184, 209, 166, 216, 70, + 51, 38, 86, 133, 226, 175, 101, 167, 66, 45, 153, 147, 252, 227, 215, 192, 191, 121, 207, 66, + 122, 237, 126, 25, 48, 245, 84, 15, 154, 221, 40, 155, 170, 185, 11, 3, 34, 134, 52, 6, 46, 54, + 249, 83, 72, 89, 215, 189, 55, 253, 40, 164, 189, 138, 41, 60, 224, 52, 200, 191, 16, 125, 55, + 14, 102, 59, 74, 237, 169, 83, 208, 177, 222, 149, 121, 226, 254, 157, 56, 63, 251, 140, 220, + 233, 32, 238, 242, 131, 126, 23, 106, 80, 169, 153, 167, 67, 72, 202, 171, 11, 19, 86, 130, 19, + 112, 34, 1, 35, 58, 2, 58, 86, 141, 178, 34, 223, 39, 236, 57, 227, 69, 194, 229, 209, 7, 14, + 63, 244, 235, 147, 32, 51, 99, 229, 102, 95, 89, 218, 104, 93, 152, 19, 245, 60, 214, 134, 123, + 4, 134, 69, 255, 31, 12, 49, 171, 97, 249, 171, 130, 69, 227, 157, 155, 45, 182, 200, 1, 101, + 187, 84, 44, 127, 150, 95, 106, 15, 234, 102, 20, 218, 48, 24, 192, 246, 67, 112, 67, 55, 243, + 145, 202, 30, 238, 0, 102, 30, 218, 192, 16, 74, 155, 183, 70, 116, 46, 100, 36, 159, 226, 232, + 30, 12, 99, 101, 162, 113, 145, 223, 144, 200, 219, 20, 164, 119, 175, 85, 84, 89, 30, 180, 7, + 113, 214, 227, 106, 77, 194, 51, 7, 161, 235, 95, 70, 106, 57, 248, 32, 18, 154, 74, 6, 64, + 217, 71, 183, 205, 235, 201, 178, 20, 47, 187, 231, 69, 20, 15, 123, 56, 254, 199, 45, 207, + 135, 33, 67, 2, 237, 169, 152, 67, 252, 44, 153, 177, 199, 70, 232, 89, 10, 111, 218, 225, 171, + 155, 42, 132, 71, 53, 45, 198, 202, 247, 34, 206, 22, 42, 223, 111, 46, 152, 158, 159, 67, 98, + 174, 71, 207, 12, 131, 78, 221, 45, 233, 116, 139, 245, 154, 118, 208, 0, 98, 111, 122, 3, 68, + 36, 163, 104, 55, 149, 230, 77, 200, 52, 235, 121, 55, 172, 115, 102, 245, 142, 206, 20, 83, + 242, 57, 154, 97, 99, 68, 155, 250, 180, 91, 170, 71, 177, 143, 115, 192, 238, 91, 133, 91, 80, + 164, 72, 173, 121, 68, 139, 121, 219, 32, 111, 165, 121, 92, 48, 134, 183, 71, 243, 190, 239, + 24, 195, 44, 231, 255, 88, 52, 52, 37, 55, 104, 103, 74, 216, 168, 248, 90, 89, 66, 54, 29, + 134, 65, 228, 220, 46, 34, 168, 85, 83, 236, 239, 231, 126, 173, 232, 222, 98, 116, 158, 207, + 98, 243, 211, 197, 168, 189, 204, 245, 73, 158, 193, 227, 88, 184, 184, 191, 56, 72, 156, 252, + 193, 185, 99, 79, 211, 189, 208, 17, 237, 35, 93, 215, 226, 73, 8, 28, 67, 137, 35, 72, 19, 52, + 206, 48, 27, 82, 205, 152, 75, 218, 100, 74, 135, 139, 158, 181, 167, 146, 122, 92, 159, 61, + 218, 250, 253, 95, 206, 143, 235, 147, 86, 205, 16, 137, 8, 163, 189, 109, 66, 100, 153, 62, + 135, 112, 244, 15, 35, 251, 91, 71, 203, 185, 100, 102, 135, 97, 234, 222, 248, 221, 0, 80, 25, + 64, 109, 253, 33, 92, 205, 97, 55, 193, 247, 227, 63, 177, 203, 128, 134, 9, 75, 126, 250, 107, + 123, 167, 146, 172, 16, 87, 47, 145, 179, 58, 11, 225, 114, 149, 249, 121, 232, 2, 14, 18, 59, + 219, 116, 248, 165, 73, 163, 28, 210, 58, 250, 232, 167, 147, 78, 244, 224, 201, 76, 73, 70, + 218, 204, 205, 233, 94, 123, 173, 103, 13, 42, 130, 169, 195, 156, 59, 180, 185, 66, 246, 150, + 149, 91, 23, 133, 255, 217, 18, 145, 123, 195, 100, 106, 25, 1, 64, 242, 207, 109, 140, 209, + 23, 31, 17, 211, 140, 169, 140, 212, 178, 224, 116, 121, 12, 221, 4, 225, 53, 28, 127, 53, 177, + 35, 46, 213, 193, 197, 50, 34, 113, 212, 65, 73, 16, 7, 137, 89, 114, 49, 0, 82, 216, 147, 164, + 79, 13, 144, 242, 102, 205, 46, 231, 233, 217, 120, 134, 78, 213, 194, 244, 148, 13, 13, 242, + 202, 109, 171, 231, 61, 94, 100, 107, 70, 210, 143, 35, 172, 186, 120, 190, 190, 187, 171, 242, + 181, 12, 22, 39, 183, 125, 218, 142, 186, 110, 138, 163, 19, 141, 16, 143, 162, 214, 238, 209, + 29, 33, 91, 29, 152, 235, 212, 118, 132, 139, 230, 26, 148, 19, 101, 202, 227, 231, 59, 189, + 164, 3, 86, 140, 125, 223, 70, 134, 153, 217, 50, 48, 161, 84, 148, 46, 180, 189, 53, 213, 83, + 181, 249, 208, 106, 247, 189, 9, 114, 91, 74, 219, 134, 15, 57, 125, 228, 89, 97, 139, 70, 159, + 145, 182, 89, 63, 70, 196, 251, 247, 244, 166, 60, 20, 253, 133, 78, 218, 125, 66, 241, 8, 49, + 222, 146, 200, 201, 217, 214, 90, 206, 209, 42, 151, 31, 68, 191, 165, 113, 183, 173, 112, 3, + 115, 193, 243, 85, 132, 152, 77, 211, 138, 243, 58, 131, 51, 49, 35, 109, 171, 105, 194, 134, + 6, 154, 97, 155, 98, 145, 53, 244, 175, 11, 79, 207, 108, 50, 192, 205, 48, 12, 208, 77, 78, + 47, 243, 188, 177, 196, 50, 223, 188, 207, 249, 153, 44, 42, 180, 159, 66, 147, 252, 148, 56, + 127, 140, 67, 32, 168, 124, 194, 19, 106, 56, 46, 51, 51, 202, 191, 34, 208, 214, 169, 23, 93, + 165, 26, 232, 199, 89, 111, 48, 72, 185, 251, 82, 215, 49, 204, 159, 151, 170, 64, 183, 120, + 248, 46, 110, 223, 199, 135, 236, 215, 90, 82, 185, 81, 90, 17, 143, 104, 153, 123, 27, 107, + 178, 47, 126, 19, 184, 199, 172, 138, 135, 3, 225, 240, 109, 78, 185, 141, 215, 141, 85, 191, + 105, 228, 86, 161, 113, 138, 38, 76, 111, 178, 148, 60, 72, 185, 191, 83, 52, 142, 212, 145, + 19, 64, 124, 27, 115, 167, 30, 2, 25, 109, 148, 64, 184, 158, 123, 145, 117, 68, 81, 95, 165, + 248, 27, 6, 39, 133, 139, 154, 161, 7, 50, 18, 93, 135, 239, 231, 29, 54, 117, 93, 251, 173, + 90, 27, 38, 238, 98, 243, 210, 187, 30, 41, 110, 10, 154, 219, 191, 128, 253, 231, 24, 44, 248, + 101, 99, 45, 225, 60, 107, 8, 231, 146, 145, 163, 120, 82, 146, 120, 165, 89, 56, 24, 15, 233, + 21, 236, 238, 145, 147, 168, 187, 28, 209, 111, 99, 92, 103, 236, 12, 157, 197, 31, 174, 126, + 53, 67, 190, 115, 243, 40, 253, 64, 186, 8, 222, 145, 172, 196, 35, 37, 27, 26, 139, 214, 131, + 159, 225, 229, 206, 170, 151, 184, 22, 98, 134, 128, 205, 80, 184, 40, 108, 164, 76, 145, 23, + 180, 61, 221, 182, 115, 187, 9, 207, 143, 46, 169, 242, 128, 36, 176, 223, 237, 15, 87, 109, + 52, 69, 96, 27, 217, 190, 109, 144, 101, 167, 196, 92, 122, 117, 70, 57, 78, 101, 239, 129, + 102, 238, 113, 137, 190, 172, 100, 221, 91, 68, 245, 230, 246, 97, 98, 6, 224, 152, 152, 46, + 154, 38, 36, 45, 215, 1, 77, 222, 83, 55, 197, 62, 52, 172, 202, 83, 209, 181, 37, 5, 176, 109, + 65, 137, 183, 20, 237, 168, 209, 19, 140, 46, 224, 183, 19, 239, 237, 163, 191, 221, 130, 98, + 208, 151, 159, 59, 75, 201, 42, 182, 198, 171, 28, 63, 1, 167, 8, 212, 104, 62, 120, 199, 216, + 220, 198, 160, 25, 127, 73, 84, 119, 186, 31, 195, 11, 29, 110, 116, 232, 239, 148, 243, 76, + 212, 166, 105, 1, 138, 28, 189, 98, 130, 118, 171, 20, 82, 238, 246, 132, 51, 147, 210, 220, + 249, 7, 72, 205, 164, 179, 217, 85, 175, 222, 85, 210, 230, 89, 151, 39, 69, 210, 124, 243, + 225, 171, 56, 204, 247, 29, 112, 149, 59, 214, 178, 11, 14, 151, 132, 43, 192, 48, 152, 62, 57, + 209, 104, 117, 74, 6, 126, 67, 63, 147, 94, 160, 64, 20, 4, 31, 216, 129, 180, 197, 190, 25, + 46, 146, 116, 56, 120, 124, 226, 144, 82, 23, 197, 101, 132, 119, 106, 164, 191, 201, 196, 167, + 212, 141, 15, 22, 151, 43, 169, 101, 152, 202, 190, 141, 171, 173, 82, 215, 113, 1, 253, 8, 15, + 30, 49, 46, 60, 42, 122, 175, 230, 11, 108, 6, 160, 64, 201, 72, 247, 214, 211, 170, 29, 182, + 32, 247, 63, 80, 133, 130, 118, 249, 9, 137, 185, 243, 44, 191, 121, 16, 8, 184, 231, 54, 92, + 178, 41, 223, 0, 48, 232, 12, 253, 191, 104, 39, 235, 122, 7, 189, 77, 50, 207, 189, 76, 13, + 172, 138, 15, 83, 121, 37, 163, 110, 42, 155, 211, 41, 238, 24, 190, 240, 197, 42, 35, 65, 218, + 56, 185, 114, 174, 86, 213, 117, 250, 182, 55, 44, 85, 109, 42, 124, 59, 101, 174, 210, 166, + 81, 170, 179, 105, 236, 142, 166, 8, 243, 13, 57, 209, 162, 64, 188, 142, 144, 237, 171, 157, + 219, 245, 2, 93, 228, 112, 226, 202, 143, 211, 14, 107, 194, 244, 150, 49, 122, 78, 111, 78, + 18, 234, 225, 106, 60, 178, 42, 72, 85, 19, 157, 54, 201, 211, 54, 61, 77, 93, 31, 158, 218, + 124, 199, 141, 30, 112, 84, 245, 135, 176, 219, 26, 215, 240, 97, 196, 21, 1, 55, 141, 19, 153, + 80, 147, 195, 103, 211, 21, 91, 132, 8, 11, 157, 73, 209, 45, 67, 177, 124, 219, 233, 119, 84, + 196, 52, 141, 155, 225, 249, 39, 70, 235, 206, 89, 238, 171, 136, 142, 106, 155, 63, 127, 240, + 1, 33, 121, 147, 222, 100, 8, 140, 82, 115, 77, 143, 5, 222, 244, 79, 71, 167, 55, 194, 12, 27, + 155, 15, 102, 90, 231, 77, 199, 136, 10, 87, 133, 166, 118, 211, 239, 161, 132, 149, 57, 120, + 196, 121, 131, 243, 139, 78, 213, 41, 235, 175, 16, 179, 225, 225, 73, 7, 238, 105, 184, 250, + 74, 190, 228, 21, 188, 14, 120, 163, 20, 34, 9, 195, 194, 233, 149, 98, 35, 179, 116, 164, 79, + 212, 251, 219, 133, 125, 83, 94, 194, 144, 9, 113, 78, 193, 184, 36, 80, 115, 242, 168, 86, + 212, 225, 119, 62, 173, 237, 42, 247, 42, 125, 90, 140, 5, 87, 168, 209, 221, 1, 92, 183, 209, + 73, 56, 167, 177, 18, 45, 44, 85, 204, 59, 121, 101, 206, 230, 25, 186, 95, 199, 161, 141, 235, + 152, 156, 47, 99, 26, 223, 2, 168, 92, 198, 126, 132, 255, 26, 88, 168, 30, 75, 59, 157, 84, + 12, 77, 127, 166, 106, 226, 49, 149, 82, 13, 95, 188, 171, 244, 191, 58, 255, 165, 251, 128, + 143, 190, 18, 149, 141, 129, 186, 70, 195, 0, 123, 19, 45, 42, 108, 162, 246, 90, 112, 82, 163, + 163, 173, 59, 101, 201, 241, 243, 182, 135, 6, 168, 78, 168, 66, 15, 191, 37, 10, 150, 19, 72, + 188, 88, 173, 163, 164, 182, 219, 154, 120, 238, 173, 19, 242, 176, 199, 16, 4, 48, 149, 124, + 95, 77, 234, 75, 115, 106, 144, 34, 184, 68, 119, 151, 122, 10, 91, 69, 51, 34, 236, 157, 221, + 209, 5, 94, 137, 74, 80, 35, 54, 14, 48, 202, 231, 16, 99, 227, 214, 155, 51, 129, 173, 10, + 128, 235, 62, 59, 98, 84, 198, 22, 203, 126, 109, 123, 95, 13, 173, 169, 7, 150, 2, 240, 240, + 183, 39, 212, 153, 149, 175, 17, 28, 160, 199, 53, 224, 0, 205, 179, 144, 16, 243, 226, 183, + 176, 155, 75, 209, 180, 161, 12, 80, 42, 101, 222, 188, 108, 207, 117, 105, 10, 96, 240, 166, + 89, 160, 101, 27, 137, 43, 5, 156, 160, 168, 32, 58, 89, 81, 82, 11, 62, 75, 254, 34, 174, 79, + 113, 83, 30, 172, 103, 59, 197, 145, 61, 231, 49, 184, 188, 211, 185, 13, 194, 168, 99, 92, + 113, 36, 143, 100, 155, 128, 13, 85, 81, 240, 183, 156, 232, 49, 164, 157, 141, 113, 102, 148, + 170, 34, 252, 128, 245, 48, 245, 218, 95, 234, 253, 71, 124, 174, 233, 191, 135, 127, 72, 133, + 86, 134, 118, 102, 126, 214, 70, 20, 149, 167, 187, 236, 97, 0, 95, 63, 160, 103, 123, 61, 100, + 191, 203, 217, 187, 173, 243, 72, 251, 56, 252, 88, 136, 180, 59, 155, 181, 106, 1, 114, 101, + 159, 229, 30, 74, 201, 195, 202, 6, 188, 101, 133, 242, 105, 98, 119, 135, 215, 61, 160, 31, + 157, 130, 229, 90, 64, 4, 202, 246, 90, 143, 191, 31, 127, 77, 49, 203, 250, 207, 123, 68, 95, + 200, 107, 47, 184, 21, 178, 228, 227, 26, 6, 163, 184, 159, 106, 11, 23, 83, 201, 99, 206, 57, + 54, 188, 58, 36, 137, 146, 181, 21, 79, 104, 139, 82, 105, 77, 147, 82, 12, 144, 20, 192, 93, + 59, 235, 68, 235, 111, 126, 188, 222, 59, 181, 30, 62, 204, 66, 139, 95, 105, 74, 217, 25, 211, + 91, 207, 158, 75, 140, 141, 206, 67, 77, 20, 113, 45, 191, 155, 255, 184, 53, 205, 68, 94, 202, + 108, 53, 1, 24, 245, 194, 7, 0, 24, 49, 15, 124, 96, 12, 156, 211, 72, 68, 196, 143, 242, 95, + 171, 47, 82, 94, 45, 43, 50, 238, 91, 212, 161, 249, 205, 242, 147, 109, 50, 208, ]; const SIGNATURE: [u8; 4628] = [ - 211, 210, 148, 168, 141, 152, 17, 222, 104, 63, 8, 6, 151, 147, 134, 100, 203, 10, 28, 42, 253, - 62, 96, 2, 224, 203, 230, 222, 125, 28, 214, 182, 153, 150, 13, 62, 242, 165, 47, 183, 164, 70, - 226, 64, 139, 61, 219, 229, 163, 172, 163, 231, 93, 220, 209, 156, 11, 251, 185, 238, 14, 187, - 158, 130, 63, 219, 81, 173, 58, 130, 119, 166, 1, 102, 187, 101, 126, 99, 182, 184, 197, 202, - 226, 73, 91, 109, 151, 104, 167, 139, 120, 69, 149, 32, 32, 127, 232, 111, 17, 176, 34, 6, 232, - 133, 88, 166, 96, 95, 233, 204, 16, 174, 61, 115, 51, 65, 131, 46, 238, 36, 243, 183, 92, 29, - 113, 46, 203, 58, 163, 160, 204, 98, 166, 192, 240, 178, 122, 207, 30, 106, 96, 151, 251, 106, - 66, 99, 97, 5, 85, 172, 235, 32, 10, 50, 102, 138, 242, 22, 19, 227, 44, 169, 145, 32, 228, - 107, 15, 70, 83, 245, 162, 233, 121, 49, 17, 168, 160, 52, 171, 250, 83, 23, 195, 158, 210, - 146, 12, 227, 5, 12, 141, 219, 53, 97, 120, 189, 78, 196, 94, 149, 77, 33, 212, 246, 171, 102, - 212, 103, 219, 112, 31, 221, 54, 212, 95, 35, 106, 242, 251, 129, 201, 98, 165, 69, 162, 80, - 23, 212, 208, 234, 213, 215, 30, 105, 186, 241, 69, 35, 82, 222, 250, 121, 94, 212, 205, 28, - 211, 71, 44, 42, 120, 53, 4, 137, 141, 219, 250, 215, 203, 147, 193, 209, 191, 99, 136, 105, - 161, 188, 116, 146, 164, 17, 51, 20, 105, 235, 7, 112, 105, 182, 94, 244, 88, 228, 249, 11, - 174, 87, 73, 73, 105, 156, 133, 35, 72, 143, 45, 95, 120, 98, 79, 45, 37, 194, 52, 108, 252, - 181, 50, 166, 132, 110, 228, 6, 197, 68, 190, 69, 125, 169, 57, 57, 196, 181, 95, 22, 197, 106, - 146, 218, 67, 53, 148, 115, 198, 234, 188, 72, 207, 112, 240, 50, 34, 181, 94, 44, 228, 63, - 189, 80, 205, 124, 148, 96, 243, 100, 55, 171, 132, 241, 186, 95, 99, 62, 227, 79, 113, 254, - 42, 82, 73, 236, 55, 154, 55, 97, 157, 235, 70, 8, 234, 161, 12, 27, 49, 78, 168, 6, 52, 154, - 162, 214, 226, 78, 198, 194, 151, 73, 128, 77, 109, 54, 29, 191, 19, 81, 116, 76, 125, 62, 188, - 225, 21, 48, 65, 43, 76, 93, 47, 19, 169, 63, 79, 29, 229, 158, 182, 194, 138, 239, 75, 234, 8, - 86, 150, 203, 223, 169, 113, 241, 160, 214, 119, 51, 241, 200, 30, 154, 50, 226, 2, 133, 136, - 97, 126, 118, 51, 185, 170, 1, 128, 6, 254, 77, 31, 57, 64, 214, 126, 57, 84, 217, 111, 46, - 181, 145, 205, 56, 243, 208, 58, 177, 14, 128, 92, 209, 110, 37, 140, 182, 244, 230, 103, 146, - 240, 167, 203, 106, 151, 87, 220, 17, 162, 121, 135, 85, 163, 111, 220, 154, 94, 66, 71, 209, - 86, 2, 228, 15, 160, 88, 195, 219, 157, 165, 197, 210, 14, 94, 37, 227, 157, 141, 179, 54, 245, - 200, 147, 243, 184, 39, 248, 73, 191, 74, 188, 18, 164, 94, 99, 132, 108, 221, 151, 76, 233, - 212, 237, 150, 32, 98, 219, 3, 24, 102, 221, 183, 195, 136, 31, 200, 121, 160, 137, 79, 129, - 21, 84, 248, 1, 229, 169, 251, 235, 30, 139, 232, 144, 77, 114, 226, 236, 30, 163, 242, 158, - 226, 47, 220, 178, 70, 136, 192, 251, 115, 24, 210, 73, 25, 233, 122, 253, 172, 126, 21, 4, - 107, 96, 80, 201, 22, 49, 189, 188, 105, 130, 114, 92, 215, 119, 116, 139, 53, 222, 50, 48, - 108, 232, 105, 13, 92, 38, 93, 199, 241, 32, 91, 97, 20, 99, 6, 107, 105, 38, 28, 180, 193, - 108, 72, 14, 114, 180, 61, 0, 49, 8, 143, 173, 95, 46, 25, 97, 241, 115, 63, 231, 145, 128, - 133, 47, 48, 111, 57, 189, 39, 172, 88, 194, 111, 252, 49, 217, 38, 162, 238, 169, 192, 89, - 120, 191, 148, 246, 40, 213, 141, 52, 194, 58, 111, 238, 252, 96, 83, 150, 252, 43, 237, 118, - 118, 185, 37, 105, 144, 134, 191, 248, 44, 237, 225, 38, 72, 37, 76, 209, 73, 58, 89, 132, 214, - 92, 226, 193, 202, 7, 147, 172, 95, 239, 90, 104, 125, 92, 254, 60, 49, 22, 163, 246, 161, 77, - 74, 29, 46, 126, 188, 67, 245, 138, 141, 59, 245, 16, 182, 84, 45, 120, 84, 244, 181, 80, 29, - 23, 17, 203, 133, 248, 249, 106, 130, 72, 254, 33, 154, 167, 227, 99, 214, 30, 202, 253, 234, - 1, 215, 95, 227, 154, 23, 42, 238, 19, 26, 119, 153, 227, 247, 18, 28, 237, 101, 56, 66, 159, - 30, 31, 119, 238, 50, 93, 24, 3, 87, 128, 184, 251, 10, 110, 92, 20, 93, 123, 31, 71, 84, 250, - 230, 55, 139, 203, 29, 217, 218, 57, 240, 254, 199, 146, 32, 230, 14, 71, 215, 84, 126, 162, - 203, 208, 185, 245, 238, 220, 197, 137, 232, 138, 55, 240, 152, 201, 208, 93, 231, 209, 144, - 104, 241, 167, 19, 182, 216, 193, 144, 218, 5, 132, 167, 86, 22, 152, 44, 230, 65, 122, 159, - 18, 175, 163, 205, 217, 248, 121, 179, 80, 118, 26, 43, 157, 122, 167, 211, 157, 230, 28, 154, - 169, 96, 249, 222, 15, 229, 150, 214, 58, 240, 153, 249, 207, 5, 103, 110, 191, 237, 3, 220, - 100, 212, 53, 27, 236, 157, 31, 224, 79, 39, 193, 110, 249, 135, 58, 60, 47, 239, 212, 125, - 215, 196, 62, 250, 196, 23, 110, 3, 249, 91, 220, 5, 223, 26, 175, 158, 158, 1, 48, 68, 146, - 114, 2, 59, 15, 64, 89, 21, 37, 17, 251, 81, 139, 178, 38, 154, 164, 67, 121, 205, 46, 217, - 177, 104, 209, 127, 76, 240, 149, 35, 127, 30, 1, 43, 134, 20, 227, 36, 6, 23, 188, 52, 189, - 66, 202, 239, 201, 248, 5, 51, 246, 11, 24, 38, 31, 18, 70, 196, 217, 75, 229, 189, 38, 121, - 34, 212, 139, 166, 156, 239, 231, 121, 37, 142, 159, 45, 20, 75, 39, 199, 66, 26, 175, 211, - 176, 155, 227, 193, 136, 38, 185, 132, 248, 201, 173, 210, 244, 130, 203, 248, 66, 217, 17, 2, - 152, 65, 97, 96, 69, 16, 237, 37, 134, 21, 114, 232, 101, 41, 143, 142, 158, 17, 120, 54, 117, - 162, 116, 28, 112, 74, 131, 251, 188, 108, 232, 52, 30, 50, 147, 136, 33, 226, 120, 145, 217, - 177, 187, 119, 139, 174, 47, 248, 3, 99, 163, 12, 65, 148, 69, 167, 68, 163, 46, 253, 220, 150, - 40, 124, 96, 179, 108, 155, 44, 52, 222, 233, 113, 128, 172, 2, 223, 208, 230, 245, 110, 65, - 158, 93, 187, 124, 241, 51, 94, 130, 180, 140, 195, 3, 217, 171, 30, 166, 254, 124, 38, 43, - 188, 60, 253, 155, 40, 145, 193, 114, 201, 84, 152, 93, 155, 191, 170, 151, 193, 196, 53, 61, - 5, 217, 68, 144, 246, 92, 235, 198, 116, 126, 59, 26, 146, 165, 0, 39, 63, 151, 219, 43, 90, - 98, 168, 246, 235, 218, 7, 154, 113, 190, 156, 105, 1, 50, 51, 56, 175, 151, 145, 72, 176, 37, - 9, 39, 59, 115, 218, 220, 66, 196, 10, 78, 68, 234, 109, 38, 137, 60, 176, 19, 221, 15, 125, - 227, 198, 210, 45, 165, 1, 127, 37, 177, 53, 111, 181, 211, 102, 207, 221, 115, 155, 206, 83, - 171, 152, 109, 142, 8, 240, 75, 254, 158, 53, 85, 62, 151, 181, 179, 237, 248, 71, 150, 160, - 148, 160, 244, 165, 118, 84, 37, 11, 163, 199, 183, 116, 28, 165, 68, 49, 112, 113, 116, 105, - 23, 95, 173, 144, 230, 162, 54, 71, 114, 138, 71, 148, 80, 93, 113, 85, 93, 202, 25, 111, 92, - 41, 148, 156, 91, 125, 35, 215, 49, 64, 92, 76, 13, 27, 149, 218, 143, 144, 91, 164, 194, 122, - 84, 236, 95, 150, 240, 32, 5, 241, 204, 209, 214, 69, 184, 255, 150, 119, 173, 190, 244, 193, - 235, 42, 214, 18, 40, 86, 185, 140, 48, 248, 73, 67, 178, 102, 31, 97, 88, 156, 108, 67, 244, - 42, 230, 40, 126, 127, 49, 204, 99, 214, 124, 241, 229, 252, 50, 204, 232, 96, 115, 157, 101, - 253, 129, 228, 194, 166, 81, 35, 52, 165, 81, 208, 7, 96, 192, 30, 246, 69, 29, 131, 224, 23, - 129, 235, 123, 200, 229, 54, 172, 239, 57, 111, 12, 19, 253, 125, 134, 149, 94, 123, 88, 98, - 17, 237, 101, 230, 240, 241, 34, 216, 28, 189, 18, 66, 142, 103, 98, 10, 18, 6, 78, 165, 119, - 7, 28, 133, 193, 182, 205, 74, 216, 242, 55, 129, 35, 78, 66, 225, 28, 117, 199, 85, 16, 149, - 198, 117, 36, 128, 244, 95, 233, 16, 158, 213, 79, 110, 90, 34, 217, 53, 242, 215, 222, 129, - 131, 158, 94, 29, 48, 206, 200, 197, 33, 21, 221, 97, 65, 58, 205, 30, 53, 205, 24, 172, 249, - 233, 185, 60, 59, 197, 121, 100, 97, 89, 136, 221, 184, 128, 70, 180, 240, 90, 108, 39, 33, 61, - 112, 63, 78, 221, 227, 155, 106, 250, 120, 210, 162, 211, 178, 9, 219, 0, 56, 136, 102, 246, - 201, 187, 171, 151, 182, 143, 248, 136, 226, 53, 190, 128, 128, 211, 96, 149, 223, 190, 212, - 102, 108, 101, 170, 37, 108, 232, 213, 203, 108, 17, 14, 251, 155, 109, 39, 116, 217, 144, 118, - 193, 42, 183, 26, 159, 15, 82, 7, 165, 64, 156, 61, 126, 154, 179, 167, 53, 144, 255, 241, 173, - 84, 106, 49, 164, 2, 185, 153, 240, 254, 174, 245, 187, 246, 180, 240, 242, 228, 58, 238, 202, - 236, 36, 124, 37, 47, 56, 184, 118, 215, 71, 22, 198, 250, 217, 214, 233, 128, 131, 188, 59, 9, - 71, 0, 188, 120, 150, 106, 246, 196, 28, 64, 28, 155, 108, 138, 234, 210, 116, 198, 190, 70, - 125, 85, 44, 203, 194, 57, 162, 2, 23, 62, 225, 177, 111, 250, 201, 48, 55, 214, 2, 53, 138, - 249, 119, 36, 225, 49, 79, 172, 165, 69, 167, 232, 253, 240, 69, 93, 77, 122, 27, 72, 0, 14, - 150, 133, 74, 108, 122, 38, 119, 112, 241, 190, 87, 234, 136, 33, 215, 104, 68, 238, 131, 248, - 99, 19, 53, 57, 52, 210, 60, 43, 224, 186, 215, 172, 234, 182, 49, 229, 184, 41, 243, 50, 203, - 255, 135, 123, 179, 182, 178, 191, 42, 93, 223, 25, 107, 113, 120, 150, 239, 71, 7, 63, 225, - 127, 85, 114, 235, 9, 36, 44, 159, 101, 212, 130, 81, 211, 198, 161, 34, 221, 138, 52, 236, - 209, 28, 232, 187, 64, 159, 224, 219, 61, 202, 174, 161, 93, 188, 119, 39, 76, 168, 104, 209, - 147, 224, 133, 137, 10, 9, 38, 10, 18, 15, 29, 64, 26, 104, 156, 79, 70, 54, 234, 105, 239, - 107, 208, 69, 23, 58, 130, 178, 173, 106, 215, 49, 209, 172, 122, 131, 103, 31, 62, 139, 247, - 238, 174, 245, 200, 98, 94, 53, 54, 4, 162, 156, 229, 159, 178, 102, 101, 227, 230, 148, 195, - 93, 254, 89, 102, 35, 206, 90, 247, 174, 41, 108, 253, 103, 58, 101, 102, 55, 64, 70, 210, 223, - 229, 4, 204, 254, 81, 255, 44, 169, 78, 207, 163, 62, 11, 12, 3, 159, 122, 95, 248, 155, 13, - 107, 187, 173, 80, 189, 236, 132, 104, 200, 72, 117, 31, 153, 191, 59, 61, 198, 197, 50, 193, - 102, 178, 24, 135, 136, 198, 176, 54, 57, 64, 151, 109, 21, 6, 129, 33, 240, 14, 2, 217, 112, - 112, 146, 201, 90, 200, 69, 178, 51, 235, 192, 25, 221, 233, 72, 184, 128, 37, 228, 32, 233, - 51, 162, 31, 42, 112, 12, 186, 197, 211, 195, 175, 177, 87, 50, 191, 35, 135, 120, 58, 92, 110, - 129, 137, 49, 219, 218, 45, 252, 209, 75, 215, 149, 109, 183, 142, 179, 0, 224, 85, 229, 135, - 216, 164, 225, 144, 215, 9, 209, 37, 84, 29, 235, 106, 155, 190, 71, 119, 98, 200, 103, 17, - 174, 250, 249, 53, 5, 8, 239, 215, 223, 185, 147, 44, 22, 202, 34, 166, 43, 95, 155, 153, 234, - 244, 250, 96, 95, 161, 23, 196, 174, 222, 191, 80, 166, 145, 27, 104, 85, 95, 212, 230, 36, - 238, 233, 90, 5, 197, 134, 170, 113, 121, 208, 242, 65, 72, 227, 93, 61, 127, 224, 231, 70, 33, - 246, 71, 0, 162, 185, 67, 241, 208, 242, 3, 102, 185, 31, 87, 1, 98, 164, 215, 211, 230, 82, - 196, 199, 83, 239, 255, 95, 172, 188, 185, 180, 117, 39, 150, 54, 133, 43, 29, 17, 97, 9, 21, - 171, 122, 88, 3, 129, 121, 190, 147, 110, 217, 47, 232, 136, 92, 111, 199, 61, 202, 244, 232, - 214, 72, 75, 134, 167, 208, 163, 162, 225, 221, 211, 58, 251, 223, 149, 49, 100, 96, 51, 53, - 121, 161, 136, 12, 238, 199, 158, 162, 82, 166, 146, 223, 202, 202, 130, 211, 189, 202, 215, - 31, 166, 168, 196, 135, 96, 223, 102, 98, 121, 243, 95, 237, 103, 225, 117, 60, 100, 210, 229, - 148, 249, 189, 105, 78, 69, 116, 12, 33, 87, 72, 84, 239, 99, 188, 105, 255, 18, 96, 78, 131, - 9, 212, 44, 188, 16, 85, 30, 33, 238, 244, 194, 217, 240, 61, 235, 167, 120, 199, 169, 161, 78, - 13, 151, 178, 251, 50, 160, 155, 207, 62, 60, 204, 41, 254, 102, 233, 65, 85, 89, 195, 202, 78, - 0, 88, 113, 135, 224, 237, 252, 154, 102, 190, 92, 187, 70, 168, 14, 221, 100, 132, 69, 175, - 243, 165, 74, 18, 165, 196, 232, 202, 211, 13, 238, 89, 8, 222, 53, 30, 95, 253, 48, 157, 69, - 229, 34, 117, 165, 232, 133, 46, 182, 140, 207, 27, 183, 133, 28, 244, 38, 181, 212, 75, 179, - 22, 162, 21, 199, 101, 80, 125, 185, 49, 166, 17, 247, 25, 51, 250, 253, 26, 111, 27, 237, 51, - 196, 80, 111, 79, 143, 79, 205, 132, 244, 166, 155, 171, 185, 159, 144, 207, 128, 114, 136, - 128, 28, 115, 70, 186, 110, 194, 228, 54, 177, 51, 0, 212, 145, 216, 165, 86, 242, 35, 31, 255, - 239, 149, 19, 193, 107, 84, 136, 61, 60, 95, 113, 160, 45, 116, 164, 101, 252, 166, 189, 110, - 1, 193, 132, 79, 213, 17, 102, 94, 191, 81, 173, 239, 169, 47, 255, 108, 74, 208, 144, 79, 212, - 205, 106, 193, 139, 69, 62, 152, 112, 3, 11, 23, 239, 187, 160, 193, 1, 110, 80, 224, 159, 39, - 11, 112, 1, 135, 250, 98, 251, 13, 143, 3, 165, 201, 68, 234, 194, 93, 3, 158, 165, 138, 194, - 187, 143, 230, 37, 195, 166, 48, 77, 104, 161, 6, 231, 44, 104, 66, 87, 214, 14, 85, 61, 27, - 86, 184, 156, 127, 19, 203, 217, 249, 222, 122, 29, 43, 3, 17, 169, 133, 209, 175, 244, 188, - 89, 15, 249, 37, 107, 149, 50, 132, 70, 60, 73, 26, 141, 86, 244, 30, 23, 10, 163, 125, 166, - 226, 230, 107, 149, 76, 227, 82, 209, 59, 152, 18, 101, 227, 25, 32, 243, 230, 74, 166, 16, 74, - 148, 151, 81, 201, 237, 81, 158, 181, 153, 242, 13, 162, 126, 248, 152, 18, 42, 91, 193, 214, - 189, 122, 226, 159, 68, 216, 163, 239, 177, 238, 5, 5, 4, 122, 181, 236, 98, 82, 63, 107, 124, - 30, 191, 211, 172, 89, 236, 51, 1, 53, 222, 192, 10, 230, 36, 232, 208, 87, 120, 184, 1, 7, 12, - 228, 122, 236, 93, 94, 164, 250, 166, 132, 31, 1, 56, 188, 168, 229, 11, 131, 172, 54, 147, - 243, 143, 255, 1, 36, 87, 94, 232, 90, 39, 158, 116, 15, 6, 15, 197, 34, 190, 68, 77, 177, 194, - 88, 242, 172, 37, 73, 222, 44, 194, 124, 193, 155, 154, 57, 219, 237, 202, 84, 151, 34, 35, - 188, 195, 10, 106, 188, 191, 102, 193, 213, 145, 0, 147, 174, 194, 89, 142, 206, 58, 110, 119, - 86, 149, 183, 167, 121, 167, 192, 80, 218, 163, 46, 191, 95, 39, 20, 213, 190, 103, 127, 74, - 255, 68, 88, 136, 163, 66, 169, 50, 232, 25, 215, 31, 51, 83, 132, 118, 28, 218, 91, 93, 176, - 205, 123, 188, 123, 242, 251, 115, 228, 125, 191, 84, 65, 22, 199, 218, 199, 146, 168, 112, 60, - 58, 170, 218, 4, 125, 91, 3, 72, 214, 77, 133, 243, 251, 43, 255, 176, 210, 151, 54, 197, 253, - 28, 238, 218, 170, 132, 136, 186, 241, 111, 11, 250, 118, 189, 236, 178, 150, 218, 159, 3, 171, - 162, 172, 185, 43, 55, 225, 200, 244, 119, 44, 173, 222, 87, 210, 77, 233, 105, 65, 63, 241, - 220, 130, 235, 123, 68, 199, 89, 234, 130, 139, 84, 16, 46, 30, 51, 197, 246, 172, 102, 14, 31, - 121, 214, 192, 54, 251, 252, 127, 196, 43, 157, 51, 245, 8, 39, 116, 217, 69, 253, 184, 246, - 240, 58, 223, 153, 155, 139, 179, 74, 124, 158, 225, 234, 166, 112, 203, 174, 128, 88, 160, 6, - 56, 1, 165, 38, 168, 64, 225, 137, 228, 223, 137, 228, 227, 160, 218, 243, 79, 69, 188, 64, - 122, 139, 191, 98, 107, 10, 232, 19, 36, 221, 94, 17, 27, 200, 137, 137, 252, 213, 7, 200, 97, - 46, 188, 4, 169, 193, 131, 129, 239, 179, 144, 118, 57, 113, 220, 70, 177, 106, 214, 225, 182, - 115, 175, 181, 84, 83, 129, 114, 107, 151, 62, 135, 103, 75, 176, 231, 65, 208, 112, 100, 2, - 193, 75, 99, 14, 122, 57, 122, 122, 136, 150, 170, 105, 208, 252, 246, 142, 161, 15, 29, 10, - 71, 3, 9, 99, 41, 23, 68, 58, 118, 190, 208, 151, 59, 149, 84, 26, 40, 211, 176, 63, 0, 159, - 235, 115, 84, 54, 11, 218, 183, 216, 147, 207, 96, 33, 99, 4, 48, 90, 92, 172, 36, 213, 233, - 247, 194, 124, 247, 225, 130, 159, 27, 111, 75, 52, 84, 38, 248, 18, 148, 32, 161, 117, 18, 86, - 131, 129, 161, 202, 51, 211, 103, 147, 215, 229, 230, 34, 187, 185, 93, 37, 53, 179, 202, 106, - 201, 105, 207, 212, 167, 152, 191, 200, 70, 141, 200, 230, 249, 244, 110, 199, 125, 36, 18, - 103, 217, 2, 167, 125, 170, 75, 20, 224, 92, 251, 26, 234, 35, 18, 81, 212, 186, 233, 98, 9, - 181, 64, 67, 28, 176, 15, 79, 242, 202, 244, 111, 248, 36, 122, 231, 2, 98, 216, 4, 226, 149, - 161, 9, 211, 139, 134, 249, 207, 79, 92, 247, 176, 52, 10, 6, 189, 39, 84, 99, 46, 179, 83, - 248, 75, 6, 122, 103, 129, 244, 143, 13, 154, 240, 8, 137, 52, 123, 8, 85, 51, 121, 201, 5, 60, - 6, 63, 113, 40, 31, 218, 47, 222, 201, 140, 58, 149, 243, 186, 131, 128, 27, 183, 173, 93, 190, - 200, 130, 254, 237, 51, 1, 124, 214, 240, 237, 61, 193, 63, 232, 243, 239, 191, 212, 101, 17, - 11, 103, 88, 134, 233, 64, 37, 213, 108, 143, 218, 121, 222, 82, 243, 207, 198, 193, 179, 230, - 164, 250, 40, 105, 206, 38, 45, 132, 45, 59, 226, 74, 112, 49, 36, 171, 82, 62, 2, 186, 195, - 145, 121, 205, 208, 179, 154, 229, 33, 2, 238, 95, 127, 57, 18, 173, 27, 13, 201, 63, 162, 199, - 142, 25, 155, 8, 100, 5, 134, 61, 12, 193, 135, 41, 192, 219, 121, 240, 176, 150, 91, 11, 145, - 142, 113, 75, 160, 220, 177, 141, 68, 39, 66, 72, 139, 99, 79, 7, 50, 51, 82, 31, 91, 72, 2, - 66, 106, 109, 161, 254, 134, 232, 96, 175, 140, 139, 53, 101, 221, 195, 36, 211, 16, 176, 156, - 218, 7, 170, 181, 82, 157, 200, 79, 190, 234, 162, 73, 180, 189, 200, 166, 49, 128, 228, 137, - 222, 19, 81, 45, 160, 102, 128, 139, 51, 56, 82, 105, 57, 159, 6, 166, 94, 222, 35, 188, 57, - 128, 158, 168, 117, 221, 154, 100, 226, 200, 203, 122, 75, 11, 141, 194, 152, 120, 142, 11, - 199, 111, 20, 203, 216, 76, 200, 125, 164, 117, 59, 208, 4, 150, 151, 103, 56, 85, 232, 180, - 61, 162, 23, 137, 143, 176, 79, 251, 184, 240, 175, 185, 78, 221, 175, 171, 5, 60, 128, 66, - 184, 204, 79, 38, 118, 121, 95, 196, 190, 181, 219, 200, 230, 61, 65, 232, 81, 196, 119, 85, - 221, 194, 91, 151, 45, 121, 159, 44, 13, 5, 123, 105, 112, 56, 161, 228, 44, 194, 110, 67, 209, - 231, 255, 69, 172, 165, 199, 105, 87, 100, 27, 177, 54, 255, 9, 223, 224, 31, 211, 231, 191, - 182, 123, 2, 81, 191, 246, 42, 45, 238, 165, 162, 137, 206, 103, 84, 51, 251, 210, 133, 98, - 127, 113, 125, 82, 151, 155, 212, 20, 97, 245, 122, 26, 119, 114, 198, 168, 208, 100, 58, 218, - 60, 148, 70, 69, 184, 81, 76, 242, 193, 17, 210, 107, 193, 166, 243, 46, 132, 21, 76, 66, 223, - 254, 226, 167, 155, 9, 247, 141, 185, 6, 18, 227, 95, 57, 77, 64, 34, 31, 218, 24, 0, 119, 138, - 140, 206, 185, 85, 219, 35, 47, 97, 180, 55, 251, 205, 153, 24, 216, 50, 241, 240, 143, 113, - 94, 237, 40, 17, 23, 148, 88, 178, 251, 127, 213, 99, 232, 195, 149, 104, 127, 145, 149, 39, - 54, 109, 168, 98, 167, 118, 4, 24, 27, 184, 146, 82, 182, 184, 28, 31, 55, 0, 248, 239, 243, - 24, 37, 102, 240, 140, 146, 162, 95, 130, 174, 146, 78, 23, 139, 143, 11, 208, 162, 152, 209, - 209, 34, 73, 106, 176, 210, 167, 62, 15, 7, 153, 182, 146, 79, 207, 222, 125, 115, 189, 104, - 132, 165, 217, 73, 128, 133, 48, 135, 128, 27, 184, 209, 86, 78, 140, 32, 21, 119, 66, 55, 240, - 255, 152, 89, 87, 200, 83, 20, 237, 126, 10, 111, 252, 169, 111, 232, 236, 170, 70, 246, 246, - 237, 226, 93, 194, 184, 150, 49, 132, 217, 40, 169, 38, 54, 5, 190, 131, 53, 10, 176, 235, 51, - 173, 172, 150, 131, 80, 153, 245, 213, 69, 215, 95, 38, 55, 152, 212, 204, 251, 105, 96, 48, - 108, 71, 41, 185, 57, 2, 177, 105, 90, 101, 226, 242, 232, 120, 11, 172, 225, 141, 16, 159, 49, - 135, 231, 41, 223, 102, 131, 101, 50, 39, 42, 245, 225, 244, 117, 188, 108, 55, 99, 182, 92, - 126, 254, 235, 223, 154, 228, 86, 224, 194, 25, 138, 83, 162, 169, 137, 207, 203, 220, 72, 164, - 83, 168, 179, 173, 138, 87, 191, 21, 66, 200, 90, 32, 246, 115, 81, 190, 231, 152, 187, 198, - 21, 62, 33, 215, 134, 5, 1, 157, 66, 244, 50, 118, 98, 194, 177, 254, 238, 65, 103, 110, 242, - 66, 133, 138, 149, 35, 21, 90, 161, 109, 253, 52, 78, 50, 248, 83, 238, 109, 113, 241, 177, - 177, 50, 141, 8, 7, 157, 62, 241, 177, 182, 213, 128, 152, 213, 100, 99, 173, 236, 22, 72, 218, - 37, 243, 140, 115, 39, 27, 74, 48, 14, 9, 75, 59, 62, 77, 227, 23, 139, 45, 44, 122, 96, 186, - 162, 108, 72, 95, 228, 41, 25, 26, 248, 195, 49, 209, 60, 218, 47, 90, 101, 34, 195, 90, 10, - 157, 21, 255, 76, 64, 223, 37, 29, 26, 46, 56, 120, 132, 21, 42, 245, 240, 85, 199, 19, 201, - 85, 193, 219, 221, 215, 223, 84, 246, 95, 245, 5, 75, 224, 171, 164, 25, 224, 150, 9, 216, 217, - 213, 15, 151, 241, 76, 233, 18, 40, 254, 100, 93, 154, 53, 251, 217, 138, 131, 51, 74, 10, 121, - 247, 180, 44, 8, 228, 61, 221, 148, 195, 96, 13, 218, 83, 72, 171, 45, 19, 4, 216, 206, 167, - 199, 5, 151, 63, 26, 213, 246, 170, 247, 140, 152, 237, 72, 148, 250, 153, 140, 67, 46, 66, - 232, 169, 48, 246, 190, 89, 66, 108, 236, 145, 63, 249, 218, 181, 10, 146, 35, 99, 161, 186, - 180, 125, 90, 167, 213, 198, 75, 29, 95, 57, 176, 116, 214, 117, 70, 0, 191, 237, 127, 153, - 134, 185, 97, 90, 225, 93, 237, 204, 247, 238, 213, 66, 28, 219, 91, 198, 120, 173, 144, 14, - 80, 139, 9, 213, 79, 27, 220, 47, 81, 240, 145, 90, 59, 170, 188, 247, 98, 84, 181, 173, 181, - 53, 155, 115, 80, 38, 180, 119, 243, 243, 137, 133, 227, 149, 157, 166, 189, 60, 49, 182, 74, - 147, 205, 106, 173, 150, 227, 134, 140, 130, 79, 2, 162, 192, 213, 192, 70, 137, 99, 137, 213, - 55, 198, 252, 229, 48, 48, 66, 222, 16, 7, 225, 202, 50, 122, 120, 90, 132, 169, 153, 166, 15, - 109, 48, 40, 71, 199, 36, 255, 202, 167, 23, 42, 247, 127, 185, 165, 157, 65, 160, 58, 144, 24, - 166, 128, 85, 244, 93, 79, 20, 14, 91, 83, 178, 79, 245, 120, 148, 23, 242, 208, 76, 160, 141, - 211, 104, 95, 185, 223, 122, 62, 120, 177, 74, 144, 93, 71, 251, 160, 208, 44, 192, 91, 222, - 171, 184, 125, 41, 186, 170, 254, 183, 129, 157, 10, 197, 117, 164, 203, 38, 57, 13, 175, 225, - 135, 210, 76, 231, 139, 53, 198, 74, 107, 109, 61, 235, 58, 158, 163, 118, 35, 20, 97, 222, - 127, 219, 228, 34, 216, 0, 55, 125, 197, 182, 153, 134, 169, 13, 195, 157, 128, 195, 229, 192, - 25, 177, 100, 249, 160, 58, 239, 77, 144, 166, 239, 105, 126, 136, 82, 25, 180, 244, 9, 185, - 133, 210, 67, 20, 165, 35, 179, 188, 130, 100, 132, 77, 12, 105, 73, 76, 246, 40, 152, 80, 83, - 253, 166, 73, 19, 224, 72, 83, 90, 227, 236, 57, 203, 16, 222, 91, 20, 99, 80, 183, 230, 4, 4, - 202, 65, 66, 43, 98, 21, 99, 247, 97, 50, 50, 223, 235, 238, 12, 198, 119, 152, 208, 139, 103, - 43, 98, 56, 233, 60, 161, 164, 1, 92, 129, 89, 124, 44, 177, 62, 130, 96, 38, 113, 17, 83, 160, - 216, 177, 146, 127, 111, 250, 201, 73, 112, 102, 102, 67, 112, 62, 116, 32, 31, 210, 124, 252, - 83, 215, 137, 44, 31, 2, 87, 3, 147, 134, 204, 245, 94, 215, 180, 17, 220, 47, 182, 25, 79, - 104, 255, 76, 81, 213, 23, 130, 99, 32, 232, 81, 190, 157, 93, 65, 225, 203, 197, 196, 98, 89, - 82, 44, 209, 164, 117, 110, 64, 54, 12, 232, 142, 136, 135, 113, 225, 206, 188, 180, 201, 41, - 39, 37, 49, 27, 21, 214, 194, 166, 113, 77, 89, 55, 2, 231, 221, 206, 129, 128, 27, 26, 17, - 249, 95, 85, 65, 55, 225, 214, 188, 164, 39, 35, 249, 236, 0, 0, 0, 115, 0, 0, 0, 0, 8, 0, 0, - 0, 41, 33, 28, 17, 0, 65, 62, 49, + 168, 148, 210, 211, 222, 17, 152, 141, 6, 8, 63, 104, 100, 134, 147, 151, 42, 28, 10, 203, 2, + 96, 62, 253, 222, 230, 203, 224, 182, 214, 28, 125, 62, 13, 150, 153, 183, 47, 165, 242, 64, + 226, 70, 164, 229, 219, 61, 139, 231, 163, 172, 163, 156, 209, 220, 93, 238, 185, 251, 11, 130, + 158, 187, 14, 173, 81, 219, 63, 166, 119, 130, 58, 101, 187, 102, 1, 184, 182, 99, 126, 73, + 226, 202, 197, 104, 151, 109, 91, 69, 120, 139, 167, 127, 32, 32, 149, 176, 17, 111, 232, 133, + 232, 6, 34, 95, 96, 166, 88, 174, 16, 204, 233, 65, 51, 115, 61, 36, 238, 46, 131, 29, 92, 183, + 243, 58, 203, 46, 113, 98, 204, 160, 163, 178, 240, 192, 166, 106, 30, 207, 122, 106, 251, 151, + 96, 5, 97, 99, 66, 32, 235, 172, 85, 138, 102, 50, 10, 227, 19, 22, 242, 32, 145, 169, 44, 70, + 15, 107, 228, 233, 162, 245, 83, 168, 17, 49, 121, 250, 171, 52, 160, 158, 195, 23, 83, 227, + 12, 146, 210, 219, 141, 12, 5, 189, 120, 97, 53, 149, 94, 196, 78, 246, 212, 33, 77, 103, 212, + 102, 171, 221, 31, 112, 219, 35, 95, 212, 54, 129, 251, 242, 106, 69, 165, 98, 201, 212, 23, + 80, 162, 215, 213, 234, 208, 241, 186, 105, 30, 222, 82, 35, 69, 212, 94, 121, 250, 71, 211, + 28, 205, 53, 120, 42, 44, 219, 141, 137, 4, 147, 203, 215, 250, 99, 191, 209, 193, 188, 161, + 105, 136, 17, 164, 146, 116, 235, 105, 20, 51, 182, 105, 112, 7, 228, 88, 244, 94, 87, 174, 11, + 249, 156, 105, 73, 73, 143, 72, 35, 133, 98, 120, 95, 45, 194, 37, 45, 79, 181, 252, 108, 52, + 110, 132, 166, 50, 68, 197, 6, 228, 169, 125, 69, 190, 181, 196, 57, 57, 106, 197, 22, 95, 53, + 67, 218, 146, 234, 198, 115, 148, 112, 207, 72, 188, 181, 34, 50, 240, 63, 228, 44, 94, 124, + 205, 80, 189, 100, 243, 96, 148, 241, 132, 171, 55, 62, 99, 95, 186, 254, 113, 79, 227, 236, + 73, 82, 42, 97, 55, 154, 55, 8, 70, 235, 157, 27, 12, 161, 234, 6, 168, 78, 49, 214, 162, 154, + 52, 194, 198, 78, 226, 77, 128, 73, 151, 191, 29, 54, 109, 76, 116, 81, 19, 225, 188, 62, 125, + 43, 65, 48, 21, 19, 47, 93, 76, 29, 79, 63, 169, 194, 182, 158, 229, 234, 75, 239, 138, 203, + 150, 86, 8, 241, 113, 169, 223, 51, 119, 214, 160, 154, 30, 200, 241, 133, 2, 226, 50, 118, + 126, 97, 136, 1, 170, 185, 51, 77, 254, 6, 128, 214, 64, 57, 31, 217, 84, 57, 126, 145, 181, + 46, 111, 208, 243, 56, 205, 128, 14, 177, 58, 37, 110, 209, 92, 230, 244, 182, 140, 167, 240, + 146, 103, 87, 151, 106, 203, 121, 162, 17, 220, 111, 163, 85, 135, 66, 94, 154, 220, 2, 86, + 209, 71, 88, 160, 15, 228, 165, 157, 219, 195, 94, 14, 210, 197, 141, 157, 227, 37, 200, 245, + 54, 179, 39, 184, 243, 147, 74, 191, 73, 248, 94, 164, 18, 188, 221, 108, 132, 99, 212, 233, + 76, 151, 98, 32, 150, 237, 102, 24, 3, 219, 136, 195, 183, 221, 160, 121, 200, 31, 21, 129, 79, + 137, 229, 1, 248, 84, 30, 235, 251, 169, 77, 144, 232, 139, 30, 236, 226, 114, 226, 158, 242, + 163, 70, 178, 220, 47, 115, 251, 192, 136, 25, 73, 210, 24, 172, 253, 122, 233, 107, 4, 21, + 126, 22, 201, 80, 96, 105, 188, 189, 49, 215, 92, 114, 130, 53, 139, 116, 119, 108, 48, 50, + 222, 92, 13, 105, 232, 241, 199, 93, 38, 20, 97, 91, 32, 105, 107, 6, 99, 193, 180, 28, 38, + 114, 14, 72, 108, 49, 0, 61, 180, 95, 173, 143, 8, 241, 97, 25, 46, 145, 231, 63, 115, 48, 47, + 133, 128, 39, 189, 57, 111, 111, 194, 88, 172, 38, 217, 49, 252, 192, 169, 238, 162, 148, 191, + 120, 89, 141, 213, 40, 246, 111, 58, 194, 52, 83, 96, 252, 238, 237, 43, 252, 150, 37, 185, + 118, 118, 191, 134, 144, 105, 225, 237, 44, 248, 76, 37, 72, 38, 89, 58, 73, 209, 226, 92, 214, + 132, 147, 7, 202, 193, 90, 239, 95, 172, 254, 92, 125, 104, 163, 22, 49, 60, 74, 77, 161, 246, + 188, 126, 46, 29, 141, 138, 245, 67, 182, 16, 245, 59, 84, 120, 45, 84, 29, 80, 181, 244, 133, + 203, 17, 23, 130, 106, 249, 248, 154, 33, 254, 72, 214, 99, 227, 167, 234, 253, 202, 30, 227, + 95, 215, 1, 238, 42, 23, 154, 153, 119, 26, 19, 28, 18, 247, 227, 66, 56, 101, 237, 119, 31, + 30, 159, 24, 93, 50, 238, 184, 128, 87, 3, 92, 110, 10, 251, 31, 123, 93, 20, 230, 250, 84, 71, + 29, 203, 139, 55, 240, 57, 218, 217, 32, 146, 199, 254, 215, 71, 14, 230, 203, 162, 126, 84, + 238, 245, 185, 208, 232, 137, 197, 220, 152, 240, 55, 138, 231, 93, 208, 201, 241, 104, 144, + 209, 216, 182, 19, 167, 5, 218, 144, 193, 22, 86, 167, 132, 65, 230, 44, 152, 175, 18, 159, + 122, 248, 217, 205, 163, 118, 80, 179, 121, 122, 157, 43, 26, 230, 157, 211, 167, 96, 169, 154, + 28, 229, 15, 222, 249, 240, 58, 214, 150, 5, 207, 249, 153, 237, 191, 110, 103, 212, 100, 220, + 3, 157, 236, 27, 53, 39, 79, 224, 31, 135, 249, 110, 193, 239, 47, 60, 58, 196, 215, 125, 212, + 23, 196, 250, 62, 91, 249, 3, 110, 26, 223, 5, 220, 1, 158, 158, 175, 114, 146, 68, 48, 64, 15, + 59, 2, 17, 37, 21, 89, 178, 139, 81, 251, 67, 164, 154, 38, 217, 46, 205, 121, 127, 209, 104, + 177, 35, 149, 240, 76, 43, 1, 30, 127, 36, 227, 20, 134, 52, 188, 23, 6, 239, 202, 66, 189, 51, + 5, 248, 201, 38, 24, 11, 246, 196, 70, 18, 31, 189, 229, 75, 217, 212, 34, 121, 38, 239, 156, + 166, 139, 142, 37, 121, 231, 75, 20, 45, 159, 26, 66, 199, 39, 155, 176, 211, 175, 38, 136, + 193, 227, 201, 248, 132, 185, 130, 244, 210, 173, 217, 66, 248, 203, 65, 152, 2, 17, 16, 69, + 96, 97, 21, 134, 37, 237, 41, 101, 232, 114, 17, 158, 142, 143, 162, 117, 54, 120, 74, 112, 28, + 116, 108, 188, 251, 131, 50, 30, 52, 232, 226, 33, 136, 147, 177, 217, 145, 120, 174, 139, 119, + 187, 99, 3, 248, 47, 148, 65, 12, 163, 163, 68, 167, 69, 150, 220, 253, 46, 179, 96, 124, 40, + 52, 44, 155, 108, 128, 113, 233, 222, 208, 223, 2, 172, 65, 110, 245, 230, 124, 187, 93, 158, + 130, 94, 51, 241, 3, 195, 140, 180, 166, 30, 171, 217, 43, 38, 124, 254, 155, 253, 60, 188, + 114, 193, 145, 40, 93, 152, 84, 201, 151, 170, 191, 155, 61, 53, 196, 193, 144, 68, 217, 5, + 198, 235, 92, 246, 26, 59, 126, 116, 39, 0, 165, 146, 43, 219, 151, 63, 246, 168, 98, 90, 154, + 7, 218, 235, 105, 156, 190, 113, 56, 51, 50, 1, 72, 145, 151, 175, 39, 9, 37, 176, 220, 218, + 115, 59, 78, 10, 196, 66, 38, 109, 234, 68, 19, 176, 60, 137, 227, 125, 15, 221, 165, 45, 210, + 198, 177, 37, 127, 1, 211, 181, 111, 53, 115, 221, 207, 102, 171, 83, 206, 155, 8, 142, 109, + 152, 158, 254, 75, 240, 151, 62, 85, 53, 248, 237, 179, 181, 148, 160, 150, 71, 118, 165, 244, + 160, 163, 11, 37, 84, 28, 116, 183, 199, 112, 49, 68, 165, 23, 105, 116, 113, 230, 144, 173, + 95, 114, 71, 54, 162, 80, 148, 71, 138, 93, 85, 113, 93, 92, 111, 25, 202, 91, 156, 148, 41, + 49, 215, 35, 125, 13, 76, 92, 64, 143, 218, 149, 27, 194, 164, 91, 144, 95, 236, 84, 122, 5, + 32, 240, 150, 214, 209, 204, 241, 150, 255, 184, 69, 244, 190, 173, 119, 214, 42, 235, 193, + 185, 86, 40, 18, 73, 248, 48, 140, 31, 102, 178, 67, 108, 156, 88, 97, 230, 42, 244, 67, 49, + 127, 126, 40, 124, 214, 99, 204, 50, 252, 229, 241, 115, 96, 232, 204, 129, 253, 101, 157, 81, + 166, 194, 228, 81, 165, 52, 35, 192, 96, 7, 208, 29, 69, 246, 30, 129, 23, 224, 131, 229, 200, + 123, 235, 57, 239, 172, 54, 253, 19, 12, 111, 94, 149, 134, 125, 17, 98, 88, 123, 240, 230, + 101, 237, 28, 216, 34, 241, 142, 66, 18, 189, 18, 10, 98, 103, 119, 165, 78, 6, 193, 133, 28, + 7, 216, 74, 205, 182, 35, 129, 55, 242, 28, 225, 66, 78, 16, 85, 199, 117, 36, 117, 198, 149, + 233, 95, 244, 128, 79, 213, 158, 16, 217, 34, 90, 110, 222, 215, 242, 53, 94, 158, 131, 129, + 200, 206, 48, 29, 221, 21, 33, 197, 205, 58, 65, 97, 24, 205, 53, 30, 185, 233, 249, 172, 121, + 197, 59, 60, 136, 89, 97, 100, 70, 128, 184, 221, 108, 90, 240, 180, 112, 61, 33, 39, 227, 221, + 78, 63, 120, 250, 106, 155, 178, 211, 162, 210, 56, 0, 219, 9, 201, 246, 102, 136, 182, 151, + 171, 187, 226, 136, 248, 143, 128, 128, 190, 53, 223, 149, 96, 211, 108, 102, 212, 190, 108, + 37, 170, 101, 108, 203, 213, 232, 155, 251, 14, 17, 217, 116, 39, 109, 42, 193, 118, 144, 15, + 159, 26, 183, 64, 165, 7, 82, 154, 126, 61, 156, 144, 53, 167, 179, 84, 173, 241, 255, 2, 164, + 49, 106, 254, 240, 153, 185, 246, 187, 245, 174, 228, 242, 240, 180, 236, 202, 238, 58, 47, 37, + 124, 36, 215, 118, 184, 56, 250, 198, 22, 71, 128, 233, 214, 217, 9, 59, 188, 131, 120, 188, 0, + 71, 196, 246, 106, 150, 155, 28, 64, 28, 210, 234, 138, 108, 70, 190, 198, 116, 203, 44, 85, + 125, 2, 162, 57, 194, 177, 225, 62, 23, 48, 201, 250, 111, 53, 2, 214, 55, 36, 119, 249, 138, + 172, 79, 49, 225, 232, 167, 69, 165, 93, 69, 240, 253, 72, 27, 122, 77, 133, 150, 14, 0, 38, + 122, 108, 74, 190, 241, 112, 119, 33, 136, 234, 87, 238, 68, 104, 215, 19, 99, 248, 131, 210, + 52, 57, 53, 186, 224, 43, 60, 182, 234, 172, 215, 41, 184, 229, 49, 255, 203, 50, 243, 182, + 179, 123, 135, 93, 42, 191, 178, 113, 107, 25, 223, 71, 239, 150, 120, 127, 225, 63, 7, 9, 235, + 114, 85, 101, 159, 44, 36, 211, 81, 130, 212, 221, 34, 161, 198, 209, 236, 52, 138, 64, 187, + 232, 28, 61, 219, 224, 159, 93, 161, 174, 202, 76, 39, 119, 188, 147, 209, 104, 168, 10, 137, + 133, 224, 18, 10, 38, 9, 26, 64, 29, 15, 70, 79, 156, 104, 239, 105, 234, 54, 23, 69, 208, 107, + 173, 178, 130, 58, 209, 49, 215, 106, 103, 131, 122, 172, 247, 139, 62, 31, 200, 245, 174, 238, + 54, 53, 94, 98, 229, 156, 162, 4, 101, 102, 178, 159, 195, 148, 230, 227, 102, 89, 254, 93, + 247, 90, 206, 35, 253, 108, 41, 174, 102, 101, 58, 103, 210, 70, 64, 55, 204, 4, 229, 223, 44, + 255, 81, 254, 163, 207, 78, 169, 3, 12, 11, 62, 248, 95, 122, 159, 187, 107, 13, 155, 236, 189, + 80, 173, 72, 200, 104, 132, 191, 153, 31, 117, 197, 198, 61, 59, 178, 102, 193, 50, 198, 136, + 135, 24, 64, 57, 54, 176, 6, 21, 109, 151, 14, 240, 33, 129, 112, 112, 217, 2, 200, 90, 201, + 146, 235, 51, 178, 69, 233, 221, 25, 192, 37, 128, 184, 72, 51, 233, 32, 228, 112, 42, 31, 162, + 211, 197, 186, 12, 87, 177, 175, 195, 135, 35, 191, 50, 110, 92, 58, 120, 219, 49, 137, 129, + 209, 252, 45, 218, 109, 149, 215, 75, 0, 179, 142, 183, 135, 229, 85, 224, 144, 225, 164, 216, + 37, 209, 9, 215, 106, 235, 29, 84, 119, 71, 190, 155, 17, 103, 200, 98, 53, 249, 250, 174, 215, + 239, 8, 5, 44, 147, 185, 223, 166, 34, 202, 22, 153, 155, 95, 43, 96, 250, 244, 234, 196, 23, + 161, 95, 80, 191, 222, 174, 104, 27, 145, 166, 230, 212, 95, 85, 90, 233, 238, 36, 170, 134, + 197, 5, 242, 208, 121, 113, 93, 227, 72, 65, 231, 224, 127, 61, 71, 246, 33, 70, 67, 185, 162, + 0, 3, 242, 208, 241, 87, 31, 185, 102, 215, 164, 98, 1, 196, 82, 230, 211, 255, 239, 83, 199, + 185, 188, 172, 95, 150, 39, 117, 180, 29, 43, 133, 54, 21, 9, 97, 17, 3, 88, 122, 171, 147, + 190, 121, 129, 232, 47, 217, 110, 199, 111, 92, 136, 232, 244, 202, 61, 134, 75, 72, 214, 162, + 163, 208, 167, 58, 211, 221, 225, 49, 149, 223, 251, 53, 51, 96, 100, 12, 136, 161, 121, 162, + 158, 199, 238, 223, 146, 166, 82, 211, 130, 202, 202, 31, 215, 202, 189, 135, 196, 168, 166, + 98, 102, 223, 96, 237, 95, 243, 121, 60, 117, 225, 103, 148, 229, 210, 100, 78, 105, 189, 249, + 33, 12, 116, 69, 239, 84, 72, 87, 255, 105, 188, 99, 131, 78, 96, 18, 188, 44, 212, 9, 33, 30, + 85, 16, 217, 194, 244, 238, 167, 235, 61, 240, 161, 169, 199, 120, 178, 151, 13, 78, 155, 160, + 50, 251, 204, 60, 62, 207, 233, 102, 254, 41, 195, 89, 85, 65, 88, 0, 78, 202, 237, 224, 135, + 113, 190, 102, 154, 252, 168, 70, 187, 92, 132, 100, 221, 14, 165, 243, 175, 69, 196, 165, 18, + 74, 13, 211, 202, 232, 222, 8, 89, 238, 253, 95, 30, 53, 229, 69, 157, 48, 232, 165, 117, 34, + 140, 182, 46, 133, 133, 183, 27, 207, 181, 38, 244, 28, 22, 179, 75, 212, 101, 199, 21, 162, + 49, 185, 125, 80, 25, 247, 17, 166, 26, 253, 250, 51, 51, 237, 27, 111, 79, 111, 80, 196, 132, + 205, 79, 143, 171, 155, 166, 244, 207, 144, 159, 185, 128, 136, 114, 128, 186, 70, 115, 28, 54, + 228, 194, 110, 212, 0, 51, 177, 86, 165, 216, 145, 255, 31, 35, 242, 193, 19, 149, 239, 61, + 136, 84, 107, 160, 113, 95, 60, 101, 164, 116, 45, 110, 189, 166, 252, 79, 132, 193, 1, 94, + 102, 17, 213, 239, 173, 81, 191, 108, 255, 47, 169, 79, 144, 208, 74, 193, 106, 205, 212, 152, + 62, 69, 139, 23, 11, 3, 112, 193, 160, 187, 239, 224, 80, 110, 1, 112, 11, 39, 159, 98, 250, + 135, 1, 3, 143, 13, 251, 234, 68, 201, 165, 158, 3, 93, 194, 187, 194, 138, 165, 195, 37, 230, + 143, 104, 77, 48, 166, 44, 231, 6, 161, 214, 87, 66, 104, 27, 61, 85, 14, 127, 156, 184, 86, + 249, 217, 203, 19, 43, 29, 122, 222, 133, 169, 17, 3, 188, 244, 175, 209, 37, 249, 15, 89, 132, + 50, 149, 107, 26, 73, 60, 70, 30, 244, 86, 141, 125, 163, 10, 23, 107, 230, 226, 166, 82, 227, + 76, 149, 18, 152, 59, 209, 32, 25, 227, 101, 166, 74, 230, 243, 151, 148, 74, 16, 81, 237, 201, + 81, 242, 153, 181, 158, 248, 126, 162, 13, 91, 42, 18, 152, 122, 189, 214, 193, 216, 68, 159, + 226, 238, 177, 239, 163, 122, 4, 5, 5, 82, 98, 236, 181, 30, 124, 107, 63, 89, 172, 211, 191, + 53, 1, 51, 236, 230, 10, 192, 222, 87, 208, 232, 36, 7, 1, 184, 120, 236, 122, 228, 12, 250, + 164, 94, 93, 1, 31, 132, 166, 229, 168, 188, 56, 54, 172, 131, 11, 255, 143, 243, 147, 94, 87, + 36, 1, 158, 39, 90, 232, 15, 6, 15, 116, 68, 190, 34, 197, 88, 194, 177, 77, 73, 37, 172, 242, + 124, 194, 44, 222, 57, 154, 155, 193, 84, 202, 237, 219, 188, 35, 34, 151, 188, 106, 10, 195, + 213, 193, 102, 191, 174, 147, 0, 145, 206, 142, 89, 194, 86, 119, 110, 58, 121, 167, 183, 149, + 218, 80, 192, 167, 95, 191, 46, 163, 190, 213, 20, 39, 255, 74, 127, 103, 163, 136, 88, 68, + 232, 50, 169, 66, 51, 31, 215, 25, 28, 118, 132, 83, 176, 93, 91, 218, 123, 188, 123, 205, 228, + 115, 251, 242, 65, 84, 191, 125, 199, 218, 199, 22, 60, 112, 168, 146, 4, 218, 170, 58, 72, 3, + 91, 125, 243, 133, 77, 214, 176, 255, 43, 251, 197, 54, 151, 210, 218, 238, 28, 253, 186, 136, + 132, 170, 250, 11, 111, 241, 178, 236, 189, 118, 3, 159, 218, 150, 185, 172, 162, 171, 200, + 225, 55, 43, 173, 44, 119, 244, 77, 210, 87, 222, 63, 65, 105, 233, 235, 130, 220, 241, 89, + 199, 68, 123, 84, 139, 130, 234, 51, 30, 46, 16, 102, 172, 246, 197, 214, 121, 31, 14, 252, + 251, 54, 192, 157, 43, 196, 127, 39, 8, 245, 51, 253, 69, 217, 116, 58, 240, 246, 184, 139, + 155, 153, 223, 158, 124, 74, 179, 112, 166, 234, 225, 88, 128, 174, 203, 1, 56, 6, 160, 64, + 168, 38, 165, 223, 228, 137, 225, 160, 227, 228, 137, 69, 79, 243, 218, 139, 122, 64, 188, 10, + 107, 98, 191, 221, 36, 19, 232, 200, 27, 17, 94, 213, 252, 137, 137, 46, 97, 200, 7, 193, 169, + 4, 188, 179, 239, 129, 131, 113, 57, 118, 144, 106, 177, 70, 220, 115, 182, 225, 214, 83, 84, + 181, 175, 151, 107, 114, 129, 75, 103, 135, 62, 208, 65, 231, 176, 193, 2, 100, 112, 122, 14, + 99, 75, 136, 122, 122, 57, 208, 105, 170, 150, 161, 142, 246, 252, 71, 10, 29, 15, 41, 99, 9, + 3, 118, 58, 68, 23, 59, 151, 208, 190, 40, 26, 84, 149, 0, 63, 176, 211, 84, 115, 235, 159, + 183, 218, 11, 54, 96, 207, 147, 216, 48, 4, 99, 33, 36, 172, 92, 90, 194, 247, 233, 213, 130, + 225, 247, 124, 75, 111, 27, 159, 248, 38, 84, 52, 161, 32, 148, 18, 131, 86, 18, 117, 51, 202, + 161, 129, 215, 147, 103, 211, 187, 34, 230, 229, 53, 37, 93, 185, 201, 106, 202, 179, 167, 212, + 207, 105, 70, 200, 191, 152, 249, 230, 200, 141, 125, 199, 110, 244, 217, 103, 18, 36, 170, + 125, 167, 2, 92, 224, 20, 75, 35, 234, 26, 251, 186, 212, 81, 18, 181, 9, 98, 233, 176, 28, 67, + 64, 202, 242, 79, 15, 36, 248, 111, 244, 98, 2, 231, 122, 149, 226, 4, 216, 139, 211, 9, 161, + 79, 207, 249, 134, 52, 176, 247, 92, 39, 189, 6, 10, 179, 46, 99, 84, 6, 75, 248, 83, 244, 129, + 103, 122, 240, 154, 13, 143, 123, 52, 137, 8, 121, 51, 85, 8, 6, 60, 5, 201, 31, 40, 113, 63, + 201, 222, 47, 218, 243, 149, 58, 140, 27, 128, 131, 186, 190, 93, 173, 183, 237, 254, 130, 200, + 214, 124, 1, 51, 193, 61, 237, 240, 239, 243, 232, 63, 17, 101, 212, 191, 134, 88, 103, 11, + 213, 37, 64, 233, 121, 218, 143, 108, 207, 243, 82, 222, 230, 179, 193, 198, 105, 40, 250, 164, + 132, 45, 38, 206, 74, 226, 59, 45, 171, 36, 49, 112, 186, 2, 62, 82, 205, 121, 145, 195, 229, + 154, 179, 208, 95, 238, 2, 33, 173, 18, 57, 127, 63, 201, 13, 27, 25, 142, 199, 162, 5, 100, 8, + 155, 193, 12, 61, 134, 219, 192, 41, 135, 150, 176, 240, 121, 142, 145, 11, 91, 220, 160, 75, + 113, 39, 68, 141, 177, 99, 139, 72, 66, 51, 50, 7, 79, 72, 91, 31, 82, 109, 106, 66, 2, 232, + 134, 254, 161, 139, 140, 175, 96, 195, 221, 101, 53, 176, 16, 211, 36, 170, 7, 218, 156, 200, + 157, 82, 181, 162, 234, 190, 79, 200, 189, 180, 73, 228, 128, 49, 166, 81, 19, 222, 137, 128, + 102, 160, 45, 82, 56, 51, 139, 6, 159, 57, 105, 35, 222, 94, 166, 158, 128, 57, 188, 154, 221, + 117, 168, 203, 200, 226, 100, 141, 11, 75, 122, 142, 120, 152, 194, 20, 111, 199, 11, 200, 76, + 216, 203, 59, 117, 164, 125, 151, 150, 4, 208, 232, 85, 56, 103, 23, 162, 61, 180, 79, 176, + 143, 137, 175, 240, 184, 251, 175, 221, 78, 185, 128, 60, 5, 171, 79, 204, 184, 66, 95, 121, + 118, 38, 219, 181, 190, 196, 65, 61, 230, 200, 119, 196, 81, 232, 91, 194, 221, 85, 159, 121, + 45, 151, 123, 5, 13, 44, 161, 56, 112, 105, 110, 194, 44, 228, 255, 231, 209, 67, 199, 165, + 172, 69, 27, 100, 87, 105, 9, 255, 54, 177, 211, 31, 224, 223, 123, 182, 191, 231, 246, 191, + 81, 2, 165, 238, 45, 42, 103, 206, 137, 162, 210, 251, 51, 84, 113, 127, 98, 133, 155, 151, 82, + 125, 245, 97, 20, 212, 114, 119, 26, 122, 100, 208, 168, 198, 148, 60, 218, 58, 81, 184, 69, + 70, 17, 193, 242, 76, 166, 193, 107, 210, 21, 132, 46, 243, 254, 223, 66, 76, 9, 155, 167, 226, + 6, 185, 141, 247, 57, 95, 227, 18, 31, 34, 64, 77, 119, 0, 24, 218, 185, 206, 140, 138, 47, 35, + 219, 85, 251, 55, 180, 97, 216, 24, 153, 205, 143, 240, 241, 50, 40, 237, 94, 113, 88, 148, 23, + 17, 213, 127, 251, 178, 149, 195, 232, 99, 149, 145, 127, 104, 168, 109, 54, 39, 4, 118, 167, + 98, 146, 184, 27, 24, 28, 184, 182, 82, 248, 0, 55, 31, 37, 24, 243, 239, 146, 140, 240, 102, + 174, 130, 95, 162, 139, 23, 78, 146, 162, 208, 11, 143, 34, 209, 209, 152, 210, 176, 106, 73, + 7, 15, 62, 167, 79, 146, 182, 153, 115, 125, 222, 207, 165, 132, 104, 189, 133, 128, 73, 217, + 27, 128, 135, 48, 78, 86, 209, 184, 119, 21, 32, 140, 255, 240, 55, 66, 200, 87, 89, 152, 126, + 237, 20, 83, 169, 252, 111, 10, 170, 236, 232, 111, 237, 246, 246, 70, 184, 194, 93, 226, 217, + 132, 49, 150, 54, 38, 169, 40, 53, 131, 190, 5, 51, 235, 176, 10, 131, 150, 172, 173, 213, 245, + 153, 80, 38, 95, 215, 69, 204, 212, 152, 55, 48, 96, 105, 251, 185, 41, 71, 108, 105, 177, 2, + 57, 242, 226, 101, 90, 172, 11, 120, 232, 159, 16, 141, 225, 41, 231, 135, 49, 101, 131, 102, + 223, 245, 42, 39, 50, 188, 117, 244, 225, 182, 99, 55, 108, 235, 254, 126, 92, 86, 228, 154, + 223, 138, 25, 194, 224, 137, 169, 162, 83, 72, 220, 203, 207, 179, 168, 83, 164, 191, 87, 138, + 173, 90, 200, 66, 21, 81, 115, 246, 32, 187, 152, 231, 190, 33, 62, 21, 198, 1, 5, 134, 215, + 50, 244, 66, 157, 177, 194, 98, 118, 103, 65, 238, 254, 133, 66, 242, 110, 21, 35, 149, 138, + 253, 109, 161, 90, 248, 50, 78, 52, 113, 109, 238, 83, 50, 177, 177, 241, 157, 7, 8, 141, 182, + 177, 241, 62, 213, 152, 128, 213, 236, 173, 99, 100, 37, 218, 72, 22, 39, 115, 140, 243, 14, + 48, 74, 27, 62, 59, 75, 9, 139, 23, 227, 77, 96, 122, 44, 45, 72, 108, 162, 186, 25, 41, 228, + 95, 49, 195, 248, 26, 47, 218, 60, 209, 195, 34, 101, 90, 21, 157, 10, 90, 223, 64, 76, 255, + 46, 26, 29, 37, 21, 132, 120, 56, 85, 240, 245, 42, 85, 201, 19, 199, 215, 221, 219, 193, 95, + 246, 84, 223, 224, 75, 5, 245, 224, 25, 164, 171, 217, 216, 9, 150, 241, 151, 15, 213, 40, 18, + 233, 76, 154, 93, 100, 254, 138, 217, 251, 53, 10, 74, 51, 131, 44, 180, 247, 121, 221, 61, + 228, 8, 13, 96, 195, 148, 171, 72, 83, 218, 216, 4, 19, 45, 5, 199, 167, 206, 213, 26, 63, 151, + 140, 247, 170, 246, 148, 72, 237, 152, 67, 140, 153, 250, 169, 232, 66, 46, 89, 190, 246, 48, + 145, 236, 108, 66, 181, 218, 249, 63, 99, 35, 146, 10, 125, 180, 186, 161, 198, 213, 167, 90, + 57, 95, 29, 75, 117, 214, 116, 176, 237, 191, 0, 70, 185, 134, 153, 127, 93, 225, 90, 97, 238, + 247, 204, 237, 219, 28, 66, 213, 173, 120, 198, 91, 139, 80, 14, 144, 27, 79, 213, 9, 240, 81, + 47, 220, 170, 59, 90, 145, 84, 98, 247, 188, 53, 181, 173, 181, 38, 80, 115, 155, 243, 243, + 119, 180, 149, 227, 133, 137, 60, 189, 166, 157, 147, 74, 182, 49, 150, 173, 106, 205, 130, + 140, 134, 227, 192, 162, 2, 79, 137, 70, 192, 213, 55, 213, 137, 99, 48, 229, 252, 198, 16, + 222, 66, 48, 50, 202, 225, 7, 132, 90, 120, 122, 15, 166, 153, 169, 71, 40, 48, 109, 202, 255, + 36, 199, 247, 42, 23, 167, 157, 165, 185, 127, 144, 58, 160, 65, 85, 128, 166, 24, 20, 79, 93, + 244, 178, 83, 91, 14, 148, 120, 245, 79, 76, 208, 242, 23, 104, 211, 141, 160, 122, 223, 185, + 95, 74, 177, 120, 62, 251, 71, 93, 144, 192, 44, 208, 160, 184, 171, 222, 91, 170, 186, 41, + 125, 157, 129, 183, 254, 164, 117, 197, 10, 13, 57, 38, 203, 210, 135, 225, 175, 53, 139, 231, + 76, 109, 107, 74, 198, 158, 58, 235, 61, 20, 35, 118, 163, 219, 127, 222, 97, 0, 216, 34, 228, + 182, 197, 125, 55, 13, 169, 134, 153, 195, 128, 157, 195, 177, 25, 192, 229, 58, 160, 249, 100, + 166, 144, 77, 239, 136, 126, 105, 239, 244, 180, 25, 82, 210, 133, 185, 9, 35, 165, 20, 67, + 100, 130, 188, 179, 105, 12, 77, 132, 40, 246, 76, 73, 253, 83, 80, 152, 224, 19, 73, 166, 227, + 90, 83, 72, 16, 203, 57, 236, 99, 20, 91, 222, 4, 230, 183, 80, 66, 65, 202, 4, 99, 21, 98, 43, + 50, 50, 97, 247, 12, 238, 235, 223, 208, 152, 119, 198, 98, 43, 103, 139, 161, 60, 233, 56, + 129, 92, 1, 164, 177, 44, 124, 89, 38, 96, 130, 62, 160, 83, 17, 113, 127, 146, 177, 216, 73, + 201, 250, 111, 67, 102, 102, 112, 32, 116, 62, 112, 252, 124, 210, 31, 44, 137, 215, 83, 3, 87, + 2, 31, 245, 204, 134, 147, 17, 180, 215, 94, 25, 182, 47, 220, 76, 255, 104, 79, 130, 23, 213, + 81, 81, 232, 32, 99, 65, 93, 157, 190, 196, 197, 203, 225, 44, 82, 89, 98, 110, 117, 164, 209, + 232, 12, 54, 64, 113, 135, 136, 142, 180, 188, 206, 225, 37, 39, 41, 201, 214, 21, 27, 49, 77, + 113, 166, 194, 231, 2, 55, 89, 128, 129, 206, 221, 249, 17, 26, 27, 55, 65, 85, 95, 164, 188, + 214, 225, 236, 249, 35, 39, 115, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8, 17, 28, 33, 41, 49, 62, 65, + 0, ]; fn test_gen_key_pair() { @@ -422,7 +421,6 @@ fn test_gen_key_pair() { let seed = KeyReadArgs::new(KeyId::KeyId0); let public_key = ml_dsa87.key_pair(&seed, &mut trng).unwrap(); - assert_eq!(public_key, Mldsa87PubKey::from(PUBKEY)); } diff --git a/sw-emulator/lib/periph/src/ml_dsa87.rs b/sw-emulator/lib/periph/src/ml_dsa87.rs index 172424f52c..d12ae0047c 100644 --- a/sw-emulator/lib/periph/src/ml_dsa87.rs +++ b/sw-emulator/lib/periph/src/ml_dsa87.rs @@ -12,7 +12,7 @@ File contains Ml_Dsa87 peripheral implementation. --*/ -use crate::helpers::{bytes_from_words_le, words_from_bytes_le}; +use crate::helpers::{bytes_from_words_be, words_from_bytes_be}; use crate::{KeyUsage, KeyVault}; use caliptra_emu_bus::{ActionHandle, BusError, Clock, ReadOnlyRegister, ReadWriteRegister, Timer}; use caliptra_emu_derive::Bus; @@ -311,21 +311,21 @@ impl Mldsa87 { } fn gen_key(&mut self) { - let seed_bytes = &bytes_from_words_le(&self.seed); + let seed_bytes = &bytes_from_words_be(&self.seed); let mut rng = StdRng::from_seed(*seed_bytes); let (pk, sk) = try_keygen_with_rng(&mut rng).unwrap(); - self.pubkey = words_from_bytes_le(&pk.into_bytes()); + self.pubkey = words_from_bytes_be(&pk.into_bytes()); self.private_key = sk.into_bytes(); } fn sign(&mut self) { - let sign_seed = &bytes_from_words_le(&self.sign_rnd); + let sign_seed = &bytes_from_words_be(&self.sign_rnd); let mut rng = StdRng::from_seed(*sign_seed); let secret_key = PrivateKey::try_from_bytes(self.private_key).unwrap(); - let message = &bytes_from_words_le(&self.msg); + let message = &bytes_from_words_be(&self.msg); // The Ml_Dsa87 signature is 4595 len but the reg is one byte longer let signature = secret_key @@ -336,18 +336,18 @@ impl Mldsa87 { sig[..SIG_LEN].copy_from_slice(&signature); sig }; - self.signature = words_from_bytes_le(&signature_extended); + self.signature = words_from_bytes_be(&signature_extended); } fn verify(&mut self) { - let message = &bytes_from_words_le(&self.msg); + let message = &bytes_from_words_be(&self.msg); let public_key = { - let key_bytes = &bytes_from_words_le(&self.pubkey); - PublicKey::try_from_bytes(*key_bytes).unwrap() + let key_bytes = bytes_from_words_be(&self.pubkey); + PublicKey::try_from_bytes(key_bytes).unwrap() }; - let signature = &bytes_from_words_le(&self.signature); + let signature = &bytes_from_words_be(&self.signature); let success = public_key.verify(message, &signature[..SIG_LEN].try_into().unwrap(), &[]); @@ -399,7 +399,7 @@ impl Mldsa87 { // TODO read the first 32 bytes from KV? if let Some(seed) = seed { - self.seed = words_from_bytes_le( + self.seed = words_from_bytes_be( &<[u8; ML_DSA87_SEED_SIZE]>::try_from(&seed[..ML_DSA87_SEED_SIZE]).unwrap(), ); } @@ -546,9 +546,7 @@ mod tests { clock.increment_and_process_timer_actions(1, &mut ml_dsa87); } - let mut public_key = bytes_from_words_le(&ml_dsa87.pubkey); - public_key.to_little_endian(); // Change DWORDs to little-endian. TODO is this needed? - + let public_key = bytes_from_words_be(&ml_dsa87.pubkey); assert_eq!(&public_key, &PUB_KEY); } @@ -609,9 +607,7 @@ mod tests { clock.increment_and_process_timer_actions(1, &mut ml_dsa87); } - let mut signature = bytes_from_words_le(&ml_dsa87.signature); - signature.to_little_endian(); // Change DWORDs to little-endian. - + let signature = bytes_from_words_be(&ml_dsa87.signature); assert_eq!(&signature, &SIGNATURE); } @@ -676,9 +672,7 @@ mod tests { clock.increment_and_process_timer_actions(1, &mut ml_dsa87); } - let mut result = bytes_from_words_le(&ml_dsa87.verify_res); - result.to_little_endian(); - + let result = bytes_from_words_be(&ml_dsa87.verify_res); assert_eq!(result, &SIGNATURE[..ML_DSA87_VERIFICATION_SIZE]); // Bad signature @@ -715,9 +709,7 @@ mod tests { clock.increment_and_process_timer_actions(1, &mut ml_dsa87); } - let mut result = bytes_from_words_le(&ml_dsa87.verify_res); - result.to_little_endian(); - + let result = bytes_from_words_be(&ml_dsa87.verify_res); assert_eq!(&result, &[0; 64]); } @@ -788,9 +780,7 @@ mod tests { clock.increment_and_process_timer_actions(1, &mut ml_dsa87); } - let mut public_key = bytes_from_words_le(&ml_dsa87.pubkey); - public_key.to_little_endian(); // Change DWORDs to little-endian. TODO is this needed? - + let public_key = bytes_from_words_be(&ml_dsa87.pubkey); assert_eq!(&public_key, &PUB_KEY); } } diff --git a/sw-emulator/lib/periph/src/test_data/ml_dsa87_test_data.rs b/sw-emulator/lib/periph/src/test_data/ml_dsa87_test_data.rs index ae7ad651dd..662251a087 100644 --- a/sw-emulator/lib/periph/src/test_data/ml_dsa87_test_data.rs +++ b/sw-emulator/lib/periph/src/test_data/ml_dsa87_test_data.rs @@ -13,358 +13,358 @@ File contains Ml_Dsa87 test data. --*/ const PUB_KEY: [u8; PK_LEN] = [ - 52, 152, 227, 234, 105, 55, 255, 65, 137, 203, 5, 1, 211, 240, 107, 159, 182, 8, 61, 203, 11, - 191, 157, 61, 159, 112, 7, 148, 6, 233, 81, 189, 2, 151, 181, 250, 11, 56, 158, 74, 79, 188, - 166, 67, 129, 147, 229, 96, 207, 106, 145, 5, 209, 203, 80, 220, 21, 23, 242, 46, 167, 58, 52, - 16, 241, 200, 170, 244, 43, 185, 255, 63, 236, 97, 191, 221, 154, 191, 151, 88, 179, 190, 245, - 105, 244, 67, 25, 10, 49, 238, 161, 215, 224, 24, 183, 116, 33, 227, 142, 82, 3, 93, 193, 13, - 126, 253, 190, 209, 98, 183, 232, 115, 239, 163, 19, 40, 84, 94, 212, 161, 89, 193, 239, 153, - 149, 231, 100, 94, 63, 162, 41, 200, 143, 99, 35, 125, 83, 145, 49, 127, 13, 245, 246, 182, - 192, 194, 243, 77, 222, 11, 6, 111, 4, 52, 135, 88, 169, 143, 109, 43, 49, 38, 173, 48, 206, - 153, 244, 59, 75, 140, 71, 32, 143, 185, 221, 71, 9, 142, 171, 214, 243, 168, 183, 41, 235, - 130, 100, 118, 137, 172, 38, 226, 206, 120, 242, 1, 28, 160, 121, 217, 199, 213, 214, 208, 86, - 105, 94, 107, 73, 128, 101, 157, 137, 184, 147, 114, 136, 224, 175, 118, 173, 83, 54, 13, 55, - 90, 81, 191, 131, 41, 164, 235, 58, 238, 146, 100, 42, 139, 89, 161, 55, 83, 47, 87, 163, 65, - 47, 149, 161, 32, 254, 196, 113, 73, 114, 194, 134, 103, 243, 157, 62, 19, 162, 103, 164, 80, - 2, 174, 106, 99, 122, 229, 27, 47, 201, 76, 28, 182, 201, 202, 47, 242, 138, 122, 220, 220, - 206, 177, 121, 29, 232, 31, 109, 207, 247, 97, 16, 101, 154, 81, 133, 142, 80, 255, 53, 88, - 147, 175, 41, 112, 53, 198, 168, 13, 87, 96, 93, 70, 3, 254, 53, 251, 167, 195, 141, 34, 179, - 63, 221, 234, 161, 71, 72, 56, 7, 181, 114, 98, 120, 2, 240, 238, 43, 172, 25, 246, 209, 1, - 152, 109, 46, 250, 153, 114, 40, 219, 48, 65, 227, 174, 169, 216, 25, 250, 184, 193, 93, 202, - 103, 11, 224, 169, 206, 71, 82, 195, 18, 199, 39, 249, 4, 91, 61, 157, 33, 136, 233, 104, 76, - 155, 86, 229, 225, 205, 237, 125, 32, 210, 231, 100, 111, 182, 235, 64, 159, 75, 214, 177, 121, - 28, 137, 171, 137, 153, 171, 140, 39, 131, 153, 240, 82, 90, 92, 218, 62, 97, 148, 139, 138, - 45, 124, 112, 119, 0, 186, 9, 201, 7, 53, 90, 221, 184, 32, 166, 11, 229, 255, 160, 69, 32, - 178, 17, 97, 80, 84, 189, 199, 170, 197, 231, 251, 106, 100, 170, 175, 0, 182, 188, 211, 94, - 107, 244, 104, 11, 172, 70, 245, 177, 232, 169, 1, 196, 220, 206, 45, 103, 39, 144, 53, 219, - 18, 167, 174, 58, 147, 180, 234, 110, 183, 246, 17, 186, 186, 195, 238, 236, 42, 5, 162, 234, - 27, 189, 234, 126, 46, 140, 133, 72, 215, 112, 76, 9, 141, 81, 219, 211, 31, 156, 196, 59, 65, - 246, 104, 203, 139, 91, 31, 246, 250, 252, 220, 72, 248, 215, 215, 216, 164, 176, 7, 113, 89, - 33, 125, 45, 221, 111, 71, 211, 135, 121, 174, 33, 172, 28, 252, 34, 45, 207, 224, 203, 97, - 192, 85, 198, 76, 206, 38, 212, 70, 200, 184, 94, 220, 38, 175, 29, 167, 12, 221, 1, 135, 205, - 136, 173, 205, 172, 145, 145, 179, 85, 70, 127, 206, 209, 231, 109, 1, 224, 152, 95, 223, 133, - 158, 21, 224, 146, 130, 186, 47, 141, 249, 221, 38, 198, 194, 161, 235, 198, 22, 8, 193, 213, - 5, 216, 44, 243, 58, 240, 11, 139, 131, 151, 114, 205, 69, 118, 95, 14, 55, 78, 55, 248, 133, - 99, 8, 125, 40, 94, 128, 235, 26, 63, 31, 10, 57, 8, 13, 209, 155, 248, 5, 221, 56, 34, 138, - 163, 248, 54, 46, 196, 127, 70, 166, 65, 4, 158, 13, 200, 139, 249, 213, 83, 43, 19, 49, 247, - 156, 58, 58, 105, 24, 236, 227, 183, 164, 82, 82, 35, 251, 188, 56, 35, 83, 233, 232, 123, 160, - 122, 11, 213, 25, 211, 212, 78, 163, 190, 69, 229, 103, 142, 176, 157, 48, 90, 201, 220, 244, - 92, 78, 4, 245, 73, 44, 120, 164, 214, 191, 48, 107, 254, 211, 95, 164, 11, 172, 19, 63, 13, - 207, 255, 205, 70, 164, 178, 86, 236, 37, 135, 174, 245, 86, 110, 191, 131, 40, 70, 189, 229, - 51, 240, 79, 133, 167, 160, 237, 219, 236, 214, 243, 32, 170, 152, 89, 254, 39, 241, 115, 199, - 157, 236, 88, 201, 83, 105, 155, 100, 235, 84, 150, 37, 109, 85, 142, 115, 242, 58, 120, 31, - 79, 223, 14, 107, 0, 165, 134, 58, 208, 165, 86, 221, 70, 55, 4, 217, 229, 190, 93, 122, 162, - 124, 32, 88, 91, 102, 136, 115, 108, 237, 250, 62, 155, 66, 34, 41, 117, 163, 130, 66, 79, 3, - 42, 110, 250, 105, 179, 237, 135, 163, 118, 216, 190, 23, 96, 120, 144, 94, 206, 72, 13, 125, - 219, 145, 155, 218, 90, 80, 4, 32, 21, 13, 207, 42, 83, 96, 38, 82, 219, 148, 120, 201, 198, - 87, 101, 28, 169, 218, 97, 194, 43, 210, 104, 73, 210, 65, 71, 180, 68, 247, 153, 177, 138, - 115, 204, 210, 8, 199, 245, 202, 151, 150, 218, 62, 79, 27, 53, 61, 38, 141, 170, 48, 224, 223, - 44, 189, 94, 232, 185, 89, 23, 87, 105, 221, 151, 143, 44, 103, 60, 151, 4, 58, 19, 86, 82, - 224, 172, 245, 237, 178, 1, 63, 225, 69, 142, 212, 255, 195, 248, 98, 118, 113, 135, 216, 228, - 14, 10, 153, 35, 35, 119, 220, 9, 90, 111, 9, 31, 241, 193, 199, 128, 205, 118, 76, 217, 114, - 191, 117, 118, 144, 220, 208, 78, 81, 197, 128, 84, 189, 29, 204, 84, 77, 212, 158, 173, 41, - 171, 124, 153, 83, 166, 247, 62, 187, 171, 197, 53, 83, 120, 119, 155, 238, 17, 214, 216, 249, - 173, 145, 38, 165, 38, 208, 146, 36, 213, 153, 27, 120, 199, 57, 105, 160, 70, 192, 214, 255, - 187, 101, 125, 103, 185, 30, 196, 233, 220, 200, 42, 213, 11, 10, 104, 92, 231, 142, 56, 165, - 88, 37, 55, 62, 168, 249, 205, 65, 45, 89, 200, 54, 7, 196, 172, 44, 144, 181, 81, 199, 162, - 171, 77, 38, 103, 94, 238, 47, 252, 159, 73, 44, 245, 78, 181, 119, 228, 215, 30, 94, 9, 55, - 50, 182, 185, 168, 22, 245, 219, 109, 127, 59, 89, 208, 186, 15, 14, 67, 203, 172, 1, 31, 210, - 208, 210, 221, 51, 187, 240, 187, 72, 190, 59, 1, 175, 90, 136, 7, 147, 103, 118, 12, 146, 232, - 84, 93, 35, 125, 97, 238, 252, 8, 229, 204, 120, 27, 30, 85, 225, 101, 211, 167, 59, 103, 181, - 202, 230, 180, 255, 106, 145, 235, 7, 251, 68, 90, 71, 234, 29, 213, 218, 104, 247, 165, 148, - 39, 235, 77, 18, 193, 215, 239, 247, 192, 29, 181, 177, 163, 225, 126, 188, 1, 16, 159, 97, 71, - 22, 3, 232, 216, 113, 109, 185, 247, 56, 240, 201, 134, 65, 125, 114, 27, 21, 227, 35, 74, 249, - 35, 192, 40, 93, 254, 97, 81, 95, 229, 78, 252, 121, 252, 165, 50, 32, 13, 205, 165, 21, 9, 0, - 74, 85, 21, 85, 121, 146, 164, 169, 221, 14, 251, 173, 64, 21, 226, 111, 51, 91, 211, 20, 25, - 87, 208, 48, 168, 182, 232, 27, 199, 238, 159, 172, 117, 67, 40, 100, 225, 108, 133, 75, 193, - 215, 239, 60, 228, 170, 203, 71, 72, 122, 63, 176, 217, 50, 89, 216, 203, 143, 113, 140, 75, - 230, 198, 155, 153, 190, 105, 97, 95, 6, 66, 196, 87, 64, 21, 229, 219, 4, 54, 177, 164, 47, - 87, 70, 137, 7, 236, 154, 9, 215, 110, 123, 101, 180, 121, 9, 125, 150, 139, 149, 158, 178, - 159, 106, 148, 40, 87, 59, 53, 160, 98, 146, 157, 221, 65, 168, 196, 77, 1, 33, 79, 98, 73, - 209, 28, 98, 28, 134, 71, 117, 162, 49, 193, 38, 170, 35, 168, 7, 45, 144, 106, 75, 66, 228, - 98, 44, 55, 195, 124, 237, 51, 235, 60, 43, 27, 188, 5, 205, 12, 99, 136, 94, 78, 103, 51, 63, - 32, 67, 103, 242, 39, 137, 79, 208, 170, 162, 9, 249, 46, 73, 57, 216, 145, 50, 151, 64, 92, - 160, 68, 76, 217, 194, 96, 241, 8, 137, 2, 66, 180, 76, 76, 5, 19, 94, 190, 172, 53, 53, 131, - 54, 101, 201, 136, 130, 56, 185, 105, 213, 120, 183, 151, 33, 88, 233, 79, 104, 136, 61, 237, - 83, 30, 118, 161, 88, 252, 108, 193, 219, 62, 233, 6, 49, 32, 1, 216, 106, 181, 88, 231, 22, - 110, 195, 46, 217, 70, 229, 124, 45, 173, 253, 144, 228, 20, 177, 158, 181, 47, 31, 33, 187, - 231, 31, 94, 76, 38, 183, 81, 208, 17, 98, 16, 248, 155, 210, 101, 157, 47, 18, 95, 145, 33, - 55, 84, 1, 57, 224, 20, 94, 184, 103, 214, 139, 56, 103, 187, 83, 227, 6, 202, 122, 15, 91, - 111, 215, 133, 71, 240, 1, 10, 194, 103, 53, 208, 227, 46, 115, 79, 117, 90, 105, 194, 93, 213, - 157, 109, 6, 123, 128, 218, 60, 35, 55, 151, 50, 210, 145, 78, 151, 71, 114, 200, 71, 177, 154, - 230, 180, 12, 51, 231, 36, 128, 136, 233, 220, 209, 15, 169, 205, 113, 90, 51, 3, 152, 176, - 190, 65, 54, 185, 172, 181, 216, 239, 99, 83, 99, 102, 92, 22, 139, 159, 182, 100, 214, 173, - 178, 137, 97, 214, 135, 171, 247, 59, 78, 142, 22, 79, 17, 211, 111, 223, 38, 163, 12, 164, - 162, 142, 66, 114, 238, 253, 51, 173, 130, 0, 189, 56, 54, 189, 116, 107, 165, 99, 147, 62, - 175, 5, 200, 47, 132, 112, 180, 7, 243, 117, 72, 242, 221, 185, 211, 248, 18, 31, 106, 160, - 100, 118, 251, 76, 238, 255, 91, 99, 128, 28, 191, 106, 218, 184, 48, 82, 93, 84, 240, 232, 71, - 131, 236, 147, 48, 28, 56, 210, 252, 59, 144, 78, 102, 143, 34, 102, 165, 187, 105, 56, 170, - 253, 233, 110, 49, 228, 24, 174, 141, 65, 136, 77, 207, 35, 245, 190, 221, 77, 243, 36, 172, - 254, 151, 80, 250, 52, 9, 94, 98, 92, 243, 118, 181, 76, 161, 155, 215, 248, 129, 65, 85, 13, - 159, 171, 4, 107, 109, 127, 2, 210, 25, 168, 231, 109, 89, 214, 53, 169, 161, 30, 54, 110, 107, - 220, 239, 93, 95, 91, 178, 199, 129, 123, 87, 168, 214, 11, 220, 190, 225, 228, 147, 91, 37, - 250, 210, 89, 76, 150, 45, 79, 15, 71, 234, 79, 67, 48, 216, 228, 53, 201, 207, 138, 85, 66, - 184, 42, 241, 111, 84, 171, 217, 160, 53, 117, 218, 157, 38, 133, 153, 100, 14, 0, 195, 79, 44, - 107, 229, 225, 101, 56, 107, 5, 154, 64, 146, 164, 41, 227, 129, 91, 75, 254, 196, 219, 59, 89, - 162, 172, 178, 25, 225, 129, 199, 161, 162, 82, 249, 228, 120, 140, 176, 190, 87, 80, 83, 214, - 94, 187, 147, 70, 251, 213, 155, 38, 59, 125, 199, 85, 16, 252, 194, 130, 178, 63, 235, 176, 4, - 51, 103, 82, 18, 220, 85, 8, 79, 104, 111, 86, 153, 154, 33, 154, 86, 187, 25, 246, 169, 74, - 237, 34, 232, 33, 71, 176, 115, 183, 125, 96, 11, 66, 253, 181, 15, 132, 252, 17, 166, 115, - 117, 160, 37, 108, 94, 221, 234, 49, 44, 174, 213, 155, 67, 28, 150, 61, 9, 48, 169, 197, 200, - 181, 161, 130, 123, 53, 103, 78, 173, 221, 244, 54, 190, 193, 10, 239, 17, 21, 203, 183, 151, - 248, 241, 234, 158, 74, 20, 193, 238, 210, 226, 212, 143, 179, 160, 38, 217, 164, 250, 82, 219, - 208, 249, 223, 146, 34, 241, 59, 98, 17, 30, 100, 66, 238, 123, 87, 196, 86, 168, 205, 132, - 240, 24, 32, 140, 22, 129, 164, 243, 229, 204, 0, 36, 47, 41, 103, 24, 199, 226, 91, 245, 23, - 93, 199, 60, 134, 44, 150, 124, 216, 153, 251, 64, 85, 99, 232, 209, 30, 11, 160, 73, 126, 60, - 83, 225, 248, 174, 98, 108, 38, 60, 187, 25, 42, 145, 138, 16, 137, 19, 34, 199, 29, 209, 202, - 133, 75, 180, 107, 173, 18, 199, 130, 76, 102, 37, 235, 107, 58, 64, 118, 95, 221, 88, 54, 112, - 48, 19, 208, 58, 62, 47, 253, 223, 150, 231, 89, 180, 101, 97, 237, 114, 212, 173, 57, 91, 88, - 71, 59, 253, 142, 100, 46, 98, 19, 100, 90, 164, 25, 119, 148, 202, 219, 214, 136, 199, 255, - 49, 62, 244, 190, 61, 179, 119, 106, 39, 2, 223, 151, 173, 23, 44, 77, 181, 36, 83, 32, 135, - 84, 39, 7, 218, 239, 205, 152, 253, 50, 208, 6, 53, 95, 187, 3, 221, 87, 219, 23, 203, 52, 127, - 244, 186, 105, 56, 29, 253, 44, 87, 71, 106, 14, 67, 202, 52, 240, 132, 82, 123, 184, 63, 55, - 42, 116, 23, 54, 86, 239, 15, 3, 214, 247, 202, 5, 194, 0, 27, 62, 142, 221, 82, 154, 71, 165, - 159, 51, 19, 97, 48, 50, 57, 147, 83, 172, 194, 158, 235, 34, 44, 132, 190, 163, 88, 110, 188, - 92, 249, 204, 202, 139, 106, 100, 206, 0, 154, 30, 211, 172, 72, 179, 241, 25, 246, 226, 225, - 55, 53, 47, 186, 99, 58, 243, 232, 27, 79, 189, 123, 254, 112, 160, 26, 148, 246, 174, 115, - 211, 112, 131, 197, 45, 51, 202, 199, 41, 190, 168, 93, 105, 120, 3, 97, 167, 162, 80, 49, 186, - 103, 204, 209, 80, 70, 90, 209, 26, 9, 214, 74, 83, 32, 177, 13, 250, 146, 228, 76, 206, 124, - 211, 228, 127, 195, 89, 87, 239, 1, 78, 15, 120, 22, 73, 255, 206, 77, 42, 75, 157, 47, 47, 90, - 55, 46, 233, 74, 88, 159, 146, 88, 224, 236, 125, 69, 83, 202, 158, 213, 138, 144, 156, 209, - 39, 151, 170, 216, 234, 19, 186, 201, 126, 122, 73, 86, 101, 183, 51, 8, 115, 145, 11, 86, 1, - 91, 252, 106, 157, 242, 11, 148, 154, 218, 204, 12, 168, 238, 251, 251, 255, 67, 64, 179, 166, - 56, 255, 151, 8, 163, 14, 34, 40, 220, 73, 38, 45, 176, 233, 56, 253, 32, 212, 100, 231, 237, - 92, 199, 31, 23, 1, 146, 161, 252, 108, 121, 242, 47, 55, 71, 241, 13, 34, 19, 218, 254, 217, - 50, 108, 170, 91, 80, 155, 139, 223, 148, 107, 183, 30, 243, 71, 185, 145, 52, 82, 218, 99, - 165, 247, 35, 71, 128, 210, 158, 189, 60, 242, 13, 108, 93, 9, 66, 244, 81, 221, 138, 32, 136, - 113, 8, 33, 4, 118, 170, 58, 235, 35, 51, 251, 102, 216, 240, 93, 241, 248, 106, 63, 181, 106, - 232, 72, 197, 31, 246, 229, 125, 159, 209, 24, 224, 0, 165, 210, 173, + 234, 227, 152, 52, 65, 255, 55, 105, 1, 5, 203, 137, 159, 107, 240, 211, 203, 61, 8, 182, 61, + 157, 191, 11, 148, 7, 112, 159, 189, 81, 233, 6, 250, 181, 151, 2, 74, 158, 56, 11, 67, 166, + 188, 79, 96, 229, 147, 129, 5, 145, 106, 207, 220, 80, 203, 209, 46, 242, 23, 21, 16, 52, 58, + 167, 244, 170, 200, 241, 63, 255, 185, 43, 221, 191, 97, 236, 88, 151, 191, 154, 105, 245, 190, + 179, 10, 25, 67, 244, 215, 161, 238, 49, 116, 183, 24, 224, 82, 142, 227, 33, 13, 193, 93, 3, + 209, 190, 253, 126, 115, 232, 183, 98, 40, 19, 163, 239, 161, 212, 94, 84, 153, 239, 193, 89, + 94, 100, 231, 149, 200, 41, 162, 63, 125, 35, 99, 143, 127, 49, 145, 83, 182, 246, 245, 13, 77, + 243, 194, 192, 111, 6, 11, 222, 88, 135, 52, 4, 43, 109, 143, 169, 48, 173, 38, 49, 59, 244, + 153, 206, 32, 71, 140, 75, 71, 221, 185, 143, 214, 171, 142, 9, 41, 183, 168, 243, 118, 100, + 130, 235, 226, 38, 172, 137, 1, 242, 120, 206, 217, 121, 160, 28, 208, 214, 213, 199, 107, 94, + 105, 86, 157, 101, 128, 73, 114, 147, 184, 137, 118, 175, 224, 136, 13, 54, 83, 173, 191, 81, + 90, 55, 235, 164, 41, 131, 100, 146, 238, 58, 161, 89, 139, 42, 87, 47, 83, 55, 149, 47, 65, + 163, 196, 254, 32, 161, 194, 114, 73, 113, 157, 243, 103, 134, 103, 162, 19, 62, 174, 2, 80, + 164, 229, 122, 99, 106, 76, 201, 47, 27, 202, 201, 182, 28, 122, 138, 242, 47, 177, 206, 220, + 220, 31, 232, 29, 121, 97, 247, 207, 109, 81, 154, 101, 16, 255, 80, 142, 133, 175, 147, 88, + 53, 198, 53, 112, 41, 96, 87, 13, 168, 254, 3, 70, 93, 195, 167, 251, 53, 63, 179, 34, 141, 71, + 161, 234, 221, 181, 7, 56, 72, 2, 120, 98, 114, 172, 43, 238, 240, 1, 209, 246, 25, 250, 46, + 109, 152, 219, 40, 114, 153, 174, 227, 65, 48, 250, 25, 216, 169, 202, 93, 193, 184, 169, 224, + 11, 103, 195, 82, 71, 206, 249, 39, 199, 18, 157, 61, 91, 4, 104, 233, 136, 33, 229, 86, 155, + 76, 125, 237, 205, 225, 100, 231, 210, 32, 64, 235, 182, 111, 177, 214, 75, 159, 171, 137, 28, + 121, 140, 171, 153, 137, 240, 153, 131, 39, 218, 92, 90, 82, 139, 148, 97, 62, 112, 124, 45, + 138, 9, 186, 0, 119, 90, 53, 7, 201, 166, 32, 184, 221, 160, 255, 229, 11, 17, 178, 32, 69, + 189, 84, 80, 97, 231, 197, 170, 199, 170, 100, 106, 251, 188, 182, 0, 175, 244, 107, 94, 211, + 70, 172, 11, 104, 169, 232, 177, 245, 206, 220, 196, 1, 144, 39, 103, 45, 167, 18, 219, 53, + 180, 147, 58, 174, 246, 183, 110, 234, 195, 186, 186, 17, 5, 42, 236, 238, 189, 27, 234, 162, + 140, 46, 126, 234, 112, 215, 72, 133, 81, 141, 9, 76, 156, 31, 211, 219, 246, 65, 59, 196, 91, + 139, 203, 104, 252, 250, 246, 31, 215, 248, 72, 220, 176, 164, 216, 215, 33, 89, 113, 7, 111, + 221, 45, 125, 121, 135, 211, 71, 28, 172, 33, 174, 207, 45, 34, 252, 192, 97, 203, 224, 206, + 76, 198, 85, 200, 70, 212, 38, 38, 220, 94, 184, 12, 167, 29, 175, 205, 135, 1, 221, 172, 205, + 173, 136, 85, 179, 145, 145, 209, 206, 127, 70, 224, 1, 109, 231, 133, 223, 95, 152, 146, 224, + 21, 158, 141, 47, 186, 130, 198, 38, 221, 249, 198, 235, 161, 194, 213, 193, 8, 22, 243, 44, + 216, 5, 139, 11, 240, 58, 205, 114, 151, 131, 14, 95, 118, 69, 248, 55, 78, 55, 125, 8, 99, + 133, 235, 128, 94, 40, 10, 31, 63, 26, 209, 13, 8, 57, 221, 5, 248, 155, 163, 138, 34, 56, 196, + 46, 54, 248, 65, 166, 70, 127, 200, 13, 158, 4, 83, 213, 249, 139, 247, 49, 19, 43, 105, 58, + 58, 156, 183, 227, 236, 24, 35, 82, 82, 164, 35, 56, 188, 251, 123, 232, 233, 83, 213, 11, 122, + 160, 78, 212, 211, 25, 229, 69, 190, 163, 157, 176, 142, 103, 220, 201, 90, 48, 4, 78, 92, 244, + 120, 44, 73, 245, 48, 191, 214, 164, 95, 211, 254, 107, 19, 172, 11, 164, 255, 207, 13, 63, + 178, 164, 70, 205, 135, 37, 236, 86, 110, 86, 245, 174, 70, 40, 131, 191, 240, 51, 229, 189, + 160, 167, 133, 79, 214, 236, 219, 237, 152, 170, 32, 243, 241, 39, 254, 89, 236, 157, 199, 115, + 105, 83, 201, 88, 84, 235, 100, 155, 85, 109, 37, 150, 58, 242, 115, 142, 223, 79, 31, 120, + 165, 0, 107, 14, 165, 208, 58, 134, 55, 70, 221, 86, 190, 229, 217, 4, 124, 162, 122, 93, 102, + 91, 88, 32, 237, 108, 115, 136, 66, 155, 62, 250, 163, 117, 41, 34, 3, 79, 66, 130, 105, 250, + 110, 42, 163, 135, 237, 179, 23, 190, 216, 118, 94, 144, 120, 96, 125, 13, 72, 206, 218, 155, + 145, 219, 32, 4, 80, 90, 42, 207, 13, 21, 82, 38, 96, 83, 201, 120, 148, 219, 28, 101, 87, 198, + 194, 97, 218, 169, 73, 104, 210, 43, 180, 71, 65, 210, 177, 153, 247, 68, 210, 204, 115, 138, + 202, 245, 199, 8, 62, 218, 150, 151, 61, 53, 27, 79, 48, 170, 141, 38, 189, 44, 223, 224, 89, + 185, 232, 94, 221, 105, 87, 23, 103, 44, 143, 151, 58, 4, 151, 60, 224, 82, 86, 19, 178, 237, + 245, 172, 69, 225, 63, 1, 195, 255, 212, 142, 113, 118, 98, 248, 14, 228, 216, 135, 35, 35, + 153, 10, 90, 9, 220, 119, 241, 31, 9, 111, 205, 128, 199, 193, 114, 217, 76, 118, 144, 118, + 117, 191, 81, 78, 208, 220, 189, 84, 128, 197, 77, 84, 204, 29, 41, 173, 158, 212, 83, 153, + 124, 171, 187, 62, 247, 166, 83, 53, 197, 171, 238, 155, 119, 120, 249, 216, 214, 17, 165, 38, + 145, 173, 36, 146, 208, 38, 120, 27, 153, 213, 160, 105, 57, 199, 255, 214, 192, 70, 103, 125, + 101, 187, 233, 196, 30, 185, 213, 42, 200, 220, 92, 104, 10, 11, 165, 56, 142, 231, 62, 55, 37, + 88, 65, 205, 249, 168, 54, 200, 89, 45, 44, 172, 196, 7, 199, 81, 181, 144, 38, 77, 171, 162, + 47, 238, 94, 103, 44, 73, 159, 252, 119, 181, 78, 245, 94, 30, 215, 228, 182, 50, 55, 9, 245, + 22, 168, 185, 59, 127, 109, 219, 15, 186, 208, 89, 172, 203, 67, 14, 208, 210, 31, 1, 187, 51, + 221, 210, 190, 72, 187, 240, 90, 175, 1, 59, 103, 147, 7, 136, 232, 146, 12, 118, 125, 35, 93, + 84, 8, 252, 238, 97, 27, 120, 204, 229, 101, 225, 85, 30, 103, 59, 167, 211, 180, 230, 202, + 181, 235, 145, 106, 255, 90, 68, 251, 7, 213, 29, 234, 71, 165, 247, 104, 218, 77, 235, 39, + 148, 239, 215, 193, 18, 181, 29, 192, 247, 126, 225, 163, 177, 159, 16, 1, 188, 3, 22, 71, 97, + 109, 113, 216, 232, 240, 56, 247, 185, 125, 65, 134, 201, 227, 21, 27, 114, 35, 249, 74, 35, + 254, 93, 40, 192, 229, 95, 81, 97, 252, 121, 252, 78, 13, 32, 50, 165, 9, 21, 165, 205, 21, 85, + 74, 0, 164, 146, 121, 85, 251, 14, 221, 169, 226, 21, 64, 173, 211, 91, 51, 111, 208, 87, 25, + 20, 232, 182, 168, 48, 159, 238, 199, 27, 40, 67, 117, 172, 133, 108, 225, 100, 239, 215, 193, + 75, 203, 170, 228, 60, 63, 122, 72, 71, 89, 50, 217, 176, 113, 143, 203, 216, 198, 230, 75, + 140, 105, 190, 153, 155, 66, 6, 95, 97, 21, 64, 87, 196, 54, 4, 219, 229, 87, 47, 164, 177, + 236, 7, 137, 70, 110, 215, 9, 154, 121, 180, 101, 123, 139, 150, 125, 9, 159, 178, 158, 149, + 87, 40, 148, 106, 98, 160, 53, 59, 65, 221, 157, 146, 1, 77, 196, 168, 73, 98, 79, 33, 28, 98, + 28, 209, 162, 117, 71, 134, 170, 38, 193, 49, 45, 7, 168, 35, 66, 75, 106, 144, 55, 44, 98, + 228, 51, 237, 124, 195, 27, 43, 60, 235, 12, 205, 5, 188, 78, 94, 136, 99, 32, 63, 51, 103, 39, + 242, 103, 67, 170, 208, 79, 137, 46, 249, 9, 162, 145, 216, 57, 73, 92, 64, 151, 50, 217, 76, + 68, 160, 8, 241, 96, 194, 180, 66, 2, 137, 19, 5, 76, 76, 53, 172, 190, 94, 101, 54, 131, 53, + 56, 130, 136, 201, 120, 213, 105, 185, 88, 33, 151, 183, 136, 104, 79, 233, 30, 83, 237, 61, + 252, 88, 161, 118, 62, 219, 193, 108, 32, 49, 6, 233, 181, 106, 216, 1, 110, 22, 231, 88, 70, + 217, 46, 195, 173, 45, 124, 229, 20, 228, 144, 253, 47, 181, 158, 177, 231, 187, 33, 31, 38, + 76, 94, 31, 17, 208, 81, 183, 155, 248, 16, 98, 47, 157, 101, 210, 33, 145, 95, 18, 57, 1, 84, + 55, 184, 94, 20, 224, 56, 139, 214, 103, 227, 83, 187, 103, 15, 122, 202, 6, 133, 215, 111, 91, + 10, 1, 240, 71, 208, 53, 103, 194, 79, 115, 46, 227, 194, 105, 90, 117, 109, 157, 213, 93, 218, + 128, 123, 6, 151, 55, 35, 60, 78, 145, 210, 50, 200, 114, 71, 151, 230, 154, 177, 71, 231, 51, + 12, 180, 233, 136, 128, 36, 169, 15, 209, 220, 51, 90, 113, 205, 190, 176, 152, 3, 172, 185, + 54, 65, 99, 239, 216, 181, 92, 102, 99, 83, 182, 159, 139, 22, 178, 173, 214, 100, 135, 214, + 97, 137, 78, 59, 247, 171, 17, 79, 22, 142, 38, 223, 111, 211, 162, 164, 12, 163, 238, 114, 66, + 142, 130, 173, 51, 253, 54, 56, 189, 0, 165, 107, 116, 189, 175, 62, 147, 99, 132, 47, 200, 5, + 243, 7, 180, 112, 221, 242, 72, 117, 18, 248, 211, 185, 100, 160, 106, 31, 238, 76, 251, 118, + 128, 99, 91, 255, 218, 106, 191, 28, 93, 82, 48, 184, 71, 232, 240, 84, 48, 147, 236, 131, 252, + 210, 56, 28, 102, 78, 144, 59, 165, 102, 34, 143, 170, 56, 105, 187, 49, 110, 233, 253, 141, + 174, 24, 228, 207, 77, 136, 65, 221, 190, 245, 35, 172, 36, 243, 77, 250, 80, 151, 254, 98, 94, + 9, 52, 181, 118, 243, 92, 215, 155, 161, 76, 85, 65, 129, 248, 4, 171, 159, 13, 2, 127, 109, + 107, 231, 168, 25, 210, 53, 214, 89, 109, 54, 30, 161, 169, 239, 220, 107, 110, 178, 91, 95, + 93, 87, 123, 129, 199, 220, 11, 214, 168, 147, 228, 225, 190, 210, 250, 37, 91, 45, 150, 76, + 89, 234, 71, 15, 79, 216, 48, 67, 79, 207, 201, 53, 228, 184, 66, 85, 138, 84, 111, 241, 42, + 53, 160, 217, 171, 38, 157, 218, 117, 14, 100, 153, 133, 44, 79, 195, 0, 101, 225, 229, 107, + 154, 5, 107, 56, 41, 164, 146, 64, 75, 91, 129, 227, 59, 219, 196, 254, 178, 172, 162, 89, 199, + 129, 225, 25, 249, 82, 162, 161, 176, 140, 120, 228, 83, 80, 87, 190, 147, 187, 94, 214, 155, + 213, 251, 70, 199, 125, 59, 38, 194, 252, 16, 85, 235, 63, 178, 130, 103, 51, 4, 176, 85, 220, + 18, 82, 111, 104, 79, 8, 33, 154, 153, 86, 25, 187, 86, 154, 237, 74, 169, 246, 71, 33, 232, + 34, 125, 183, 115, 176, 253, 66, 11, 96, 252, 132, 15, 181, 117, 115, 166, 17, 94, 108, 37, + 160, 44, 49, 234, 221, 67, 155, 213, 174, 9, 61, 150, 28, 200, 197, 169, 48, 123, 130, 161, + 181, 173, 78, 103, 53, 190, 54, 244, 221, 17, 239, 10, 193, 151, 183, 203, 21, 158, 234, 241, + 248, 238, 193, 20, 74, 143, 212, 226, 210, 217, 38, 160, 179, 219, 82, 250, 164, 146, 223, 249, + 208, 98, 59, 241, 34, 66, 100, 30, 17, 196, 87, 123, 238, 132, 205, 168, 86, 140, 32, 24, 240, + 243, 164, 129, 22, 36, 0, 204, 229, 24, 103, 41, 47, 245, 91, 226, 199, 60, 199, 93, 23, 124, + 150, 44, 134, 64, 251, 153, 216, 209, 232, 99, 85, 73, 160, 11, 30, 225, 83, 60, 126, 108, 98, + 174, 248, 25, 187, 60, 38, 16, 138, 145, 42, 199, 34, 19, 137, 133, 202, 209, 29, 173, 107, + 180, 75, 76, 130, 199, 18, 107, 235, 37, 102, 95, 118, 64, 58, 112, 54, 88, 221, 58, 208, 19, + 48, 223, 253, 47, 62, 180, 89, 231, 150, 114, 237, 97, 101, 91, 57, 173, 212, 253, 59, 71, 88, + 98, 46, 100, 142, 164, 90, 100, 19, 202, 148, 119, 25, 199, 136, 214, 219, 244, 62, 49, 255, + 119, 179, 61, 190, 223, 2, 39, 106, 44, 23, 173, 151, 83, 36, 181, 77, 39, 84, 135, 32, 205, + 239, 218, 7, 208, 50, 253, 152, 187, 95, 53, 6, 219, 87, 221, 3, 127, 52, 203, 23, 56, 105, + 186, 244, 87, 44, 253, 29, 67, 14, 106, 71, 132, 240, 52, 202, 63, 184, 123, 82, 23, 116, 42, + 55, 15, 239, 86, 54, 202, 247, 214, 3, 27, 0, 194, 5, 82, 221, 142, 62, 159, 165, 71, 154, 48, + 97, 19, 51, 83, 147, 57, 50, 235, 158, 194, 172, 190, 132, 44, 34, 188, 110, 88, 163, 202, 204, + 249, 92, 206, 100, 106, 139, 211, 30, 154, 0, 241, 179, 72, 172, 225, 226, 246, 25, 186, 47, + 53, 55, 232, 243, 58, 99, 123, 189, 79, 27, 26, 160, 112, 254, 115, 174, 246, 148, 197, 131, + 112, 211, 199, 202, 51, 45, 93, 168, 190, 41, 97, 3, 120, 105, 49, 80, 162, 167, 209, 204, 103, + 186, 209, 90, 70, 80, 74, 214, 9, 26, 13, 177, 32, 83, 76, 228, 146, 250, 228, 211, 124, 206, + 87, 89, 195, 127, 15, 78, 1, 239, 255, 73, 22, 120, 75, 42, 77, 206, 90, 47, 47, 157, 74, 233, + 46, 55, 88, 146, 159, 88, 69, 125, 236, 224, 213, 158, 202, 83, 209, 156, 144, 138, 216, 170, + 151, 39, 201, 186, 19, 234, 86, 73, 122, 126, 8, 51, 183, 101, 86, 11, 145, 115, 106, 252, 91, + 1, 148, 11, 242, 157, 12, 204, 218, 154, 251, 251, 238, 168, 179, 64, 67, 255, 151, 255, 56, + 166, 34, 14, 163, 8, 38, 73, 220, 40, 56, 233, 176, 45, 100, 212, 32, 253, 199, 92, 237, 231, + 146, 1, 23, 31, 121, 108, 252, 161, 71, 55, 47, 242, 19, 34, 13, 241, 50, 217, 254, 218, 80, + 91, 170, 108, 148, 223, 139, 155, 243, 30, 183, 107, 52, 145, 185, 71, 165, 99, 218, 82, 128, + 71, 35, 247, 60, 189, 158, 210, 93, 108, 13, 242, 81, 244, 66, 9, 136, 32, 138, 221, 4, 33, 8, + 113, 235, 58, 170, 118, 102, 251, 51, 35, 241, 93, 240, 216, 181, 63, 106, 248, 197, 72, 232, + 106, 125, 229, 246, 31, 224, 24, 209, 159, 173, 210, 165, 0, ]; const SIGN_RND: [u8; 32] = [0; 32]; const SIGNATURE: [u8; SIG_LEN + 1] = [ - 146, 98, 33, 94, 128, 134, 54, 161, 227, 123, 186, 25, 186, 83, 67, 252, 173, 17, 220, 107, - 123, 229, 10, 112, 100, 188, 141, 62, 218, 107, 1, 81, 10, 73, 168, 140, 179, 106, 35, 157, 83, - 47, 79, 233, 253, 4, 172, 236, 204, 51, 15, 205, 43, 101, 103, 45, 214, 41, 66, 96, 66, 192, - 198, 192, 233, 206, 212, 214, 193, 172, 249, 172, 2, 166, 189, 195, 50, 232, 131, 142, 234, - 114, 214, 19, 170, 26, 202, 167, 60, 251, 242, 32, 76, 132, 234, 236, 66, 0, 112, 188, 56, 53, - 124, 101, 93, 104, 79, 187, 240, 249, 16, 250, 192, 160, 207, 29, 24, 40, 197, 99, 73, 113, 78, - 207, 110, 110, 244, 139, 144, 220, 234, 192, 28, 83, 25, 246, 58, 44, 7, 80, 232, 61, 19, 14, - 221, 92, 173, 196, 93, 136, 227, 135, 69, 248, 90, 94, 168, 34, 77, 208, 15, 147, 136, 2, 158, - 50, 21, 172, 10, 246, 52, 48, 104, 109, 143, 149, 206, 15, 99, 41, 155, 209, 190, 198, 179, - 219, 194, 97, 95, 219, 150, 184, 102, 212, 88, 159, 170, 122, 2, 76, 65, 85, 56, 209, 119, 24, - 123, 94, 219, 77, 193, 55, 23, 123, 173, 6, 231, 75, 86, 53, 51, 166, 92, 147, 215, 170, 247, - 232, 147, 190, 2, 51, 30, 91, 15, 2, 237, 43, 167, 204, 18, 182, 75, 51, 138, 150, 50, 27, 41, - 117, 126, 215, 73, 86, 118, 99, 193, 25, 108, 2, 242, 35, 42, 207, 149, 247, 64, 177, 145, 185, - 75, 141, 203, 147, 34, 211, 22, 37, 163, 198, 215, 171, 242, 162, 193, 31, 201, 189, 252, 126, - 110, 88, 67, 66, 108, 249, 3, 172, 139, 151, 95, 241, 2, 175, 109, 118, 127, 67, 212, 0, 202, - 120, 68, 248, 221, 12, 6, 17, 69, 77, 61, 28, 154, 62, 78, 153, 251, 74, 103, 190, 190, 233, - 64, 156, 233, 181, 67, 72, 222, 226, 183, 130, 57, 228, 212, 37, 147, 192, 201, 249, 255, 153, - 166, 30, 170, 41, 152, 146, 23, 237, 134, 181, 110, 159, 106, 0, 193, 198, 86, 16, 151, 187, - 229, 94, 201, 152, 36, 95, 0, 234, 224, 91, 207, 146, 0, 136, 236, 194, 92, 5, 92, 8, 86, 180, - 99, 32, 54, 247, 175, 220, 198, 250, 70, 1, 167, 146, 58, 252, 33, 98, 146, 123, 53, 12, 253, - 131, 109, 147, 136, 194, 101, 122, 217, 107, 32, 0, 48, 230, 208, 247, 150, 241, 147, 26, 185, - 155, 136, 28, 161, 210, 112, 13, 84, 132, 160, 87, 96, 29, 76, 50, 183, 108, 61, 114, 16, 161, - 11, 125, 168, 58, 154, 144, 105, 242, 11, 128, 102, 116, 23, 33, 18, 79, 8, 228, 223, 91, 49, - 91, 65, 123, 36, 64, 218, 77, 224, 51, 69, 202, 197, 252, 187, 13, 145, 183, 240, 161, 179, - 142, 53, 146, 162, 169, 54, 47, 63, 185, 213, 234, 238, 202, 140, 231, 174, 240, 116, 36, 136, - 136, 150, 197, 198, 67, 96, 142, 59, 123, 14, 174, 42, 85, 19, 41, 133, 83, 6, 76, 173, 250, - 231, 155, 104, 153, 119, 95, 250, 166, 179, 178, 155, 219, 52, 122, 209, 187, 22, 112, 136, - 214, 255, 56, 21, 96, 93, 230, 191, 21, 143, 239, 91, 30, 61, 51, 151, 29, 39, 241, 104, 232, - 181, 7, 49, 87, 174, 141, 169, 202, 75, 251, 103, 42, 141, 180, 53, 228, 227, 83, 156, 242, - 173, 28, 204, 185, 95, 66, 65, 253, 244, 75, 70, 197, 188, 101, 2, 171, 247, 224, 227, 157, - 198, 122, 178, 210, 45, 176, 59, 222, 52, 169, 91, 245, 122, 18, 1, 66, 136, 180, 208, 218, 84, - 128, 114, 46, 73, 20, 106, 204, 150, 115, 233, 34, 129, 33, 134, 98, 194, 44, 210, 143, 16, 41, - 110, 252, 52, 166, 112, 38, 74, 52, 106, 103, 121, 207, 175, 131, 141, 108, 134, 174, 42, 159, - 28, 125, 222, 9, 25, 120, 129, 208, 200, 42, 16, 84, 249, 70, 22, 171, 107, 143, 49, 217, 124, - 157, 232, 9, 222, 19, 210, 44, 137, 254, 250, 145, 107, 199, 132, 12, 141, 223, 32, 94, 56, - 255, 110, 6, 154, 79, 206, 232, 35, 240, 156, 196, 147, 241, 39, 57, 188, 111, 176, 27, 42, 6, - 114, 248, 177, 180, 21, 235, 4, 144, 53, 24, 26, 230, 167, 128, 211, 131, 201, 130, 157, 113, - 159, 180, 100, 18, 218, 13, 88, 172, 50, 253, 126, 124, 92, 146, 56, 163, 86, 52, 205, 226, 52, - 14, 98, 42, 177, 117, 67, 41, 12, 92, 111, 63, 41, 16, 167, 85, 130, 35, 83, 241, 99, 75, 47, - 69, 170, 154, 88, 172, 166, 87, 181, 222, 246, 179, 42, 197, 116, 180, 80, 230, 238, 45, 209, - 230, 185, 243, 11, 13, 215, 75, 89, 124, 88, 28, 46, 56, 196, 111, 216, 79, 239, 186, 140, 123, - 93, 36, 244, 217, 179, 148, 22, 52, 127, 186, 33, 77, 7, 34, 252, 55, 244, 43, 70, 128, 166, - 11, 8, 115, 137, 7, 212, 233, 179, 31, 225, 0, 255, 38, 94, 72, 230, 247, 16, 58, 23, 244, 231, - 164, 66, 174, 201, 125, 21, 79, 111, 8, 30, 93, 55, 245, 138, 179, 106, 125, 177, 202, 204, - 154, 206, 236, 78, 97, 118, 28, 132, 168, 123, 21, 136, 139, 107, 197, 188, 205, 95, 184, 239, - 73, 229, 190, 177, 248, 235, 19, 162, 191, 240, 19, 40, 110, 126, 56, 231, 140, 135, 214, 248, - 181, 137, 35, 233, 74, 7, 96, 145, 95, 234, 194, 46, 239, 124, 51, 224, 91, 229, 90, 60, 43, - 47, 32, 60, 212, 132, 104, 38, 9, 210, 104, 117, 107, 18, 157, 29, 135, 242, 204, 45, 232, 167, - 122, 11, 193, 234, 106, 235, 219, 253, 217, 172, 94, 157, 200, 91, 250, 71, 179, 234, 84, 115, - 224, 156, 16, 156, 212, 118, 51, 240, 177, 229, 11, 95, 44, 7, 25, 201, 124, 31, 74, 5, 152, - 188, 34, 29, 221, 75, 118, 168, 228, 44, 211, 169, 41, 250, 170, 81, 61, 136, 148, 156, 39, 35, - 34, 79, 162, 39, 248, 220, 20, 245, 131, 79, 170, 122, 22, 229, 210, 232, 120, 49, 166, 120, - 138, 90, 124, 115, 118, 128, 251, 139, 148, 202, 122, 99, 11, 196, 51, 160, 195, 177, 230, 127, - 41, 197, 16, 23, 11, 132, 69, 108, 201, 41, 32, 157, 19, 224, 210, 132, 66, 87, 101, 194, 170, - 128, 12, 148, 251, 33, 5, 46, 76, 225, 162, 217, 168, 192, 251, 99, 164, 81, 140, 76, 128, 116, - 180, 231, 231, 169, 221, 145, 207, 100, 233, 139, 107, 216, 38, 218, 244, 132, 3, 125, 194, - 161, 91, 137, 111, 180, 49, 114, 245, 38, 124, 247, 131, 103, 133, 202, 6, 73, 252, 72, 170, - 200, 66, 191, 203, 229, 45, 24, 97, 9, 149, 209, 189, 39, 1, 115, 152, 105, 221, 49, 179, 92, - 119, 152, 68, 233, 173, 136, 59, 108, 68, 10, 216, 190, 237, 10, 220, 79, 85, 138, 155, 16, - 126, 205, 159, 231, 184, 122, 61, 90, 227, 34, 3, 8, 217, 196, 255, 67, 205, 5, 143, 248, 201, - 28, 191, 227, 86, 227, 146, 189, 123, 74, 100, 117, 29, 65, 119, 44, 1, 118, 83, 125, 83, 51, - 221, 6, 155, 122, 245, 243, 193, 246, 142, 129, 214, 77, 198, 238, 234, 118, 254, 187, 232, - 117, 11, 152, 68, 182, 57, 3, 80, 67, 31, 174, 36, 25, 200, 45, 198, 194, 172, 105, 176, 186, - 155, 215, 178, 127, 21, 139, 233, 185, 86, 193, 108, 210, 243, 220, 233, 125, 93, 251, 72, 103, - 16, 124, 196, 71, 245, 126, 138, 185, 196, 30, 221, 4, 138, 155, 31, 28, 114, 8, 27, 189, 199, - 146, 236, 78, 117, 243, 215, 204, 87, 188, 129, 205, 28, 235, 26, 25, 216, 230, 128, 49, 187, - 5, 26, 182, 35, 8, 120, 184, 56, 135, 153, 167, 175, 239, 253, 211, 77, 117, 125, 157, 41, 56, - 87, 75, 198, 150, 95, 205, 214, 60, 18, 153, 9, 72, 196, 232, 109, 152, 233, 65, 56, 109, 89, - 186, 196, 109, 21, 59, 73, 35, 52, 195, 104, 201, 63, 15, 202, 215, 243, 104, 164, 187, 168, - 237, 122, 112, 66, 137, 74, 122, 195, 28, 57, 224, 104, 151, 65, 45, 254, 123, 106, 143, 234, - 94, 14, 29, 118, 48, 90, 157, 107, 35, 125, 102, 157, 255, 7, 123, 14, 6, 55, 106, 143, 107, - 135, 83, 29, 122, 184, 169, 141, 112, 47, 70, 191, 68, 72, 127, 190, 168, 63, 79, 120, 226, 7, - 199, 249, 102, 117, 125, 64, 224, 28, 222, 182, 214, 219, 202, 157, 102, 222, 77, 145, 131, - 158, 83, 140, 150, 139, 109, 93, 57, 57, 142, 148, 71, 216, 127, 162, 104, 8, 126, 103, 157, - 82, 188, 55, 143, 34, 217, 53, 26, 241, 209, 23, 78, 77, 206, 70, 70, 149, 230, 170, 197, 1, - 190, 44, 20, 236, 154, 125, 111, 124, 209, 41, 133, 54, 0, 10, 34, 97, 195, 193, 212, 244, 99, - 110, 243, 162, 146, 111, 210, 80, 136, 89, 36, 37, 226, 177, 6, 98, 66, 135, 80, 3, 160, 113, - 77, 120, 99, 208, 72, 105, 23, 123, 74, 9, 194, 163, 143, 195, 178, 222, 163, 31, 171, 1, 114, - 58, 75, 90, 249, 123, 255, 67, 86, 106, 86, 247, 246, 209, 255, 156, 32, 110, 68, 22, 15, 221, - 140, 40, 167, 55, 105, 142, 232, 210, 170, 173, 177, 183, 124, 185, 78, 13, 170, 133, 132, 146, - 23, 220, 116, 48, 4, 27, 13, 249, 155, 224, 131, 237, 83, 143, 228, 5, 181, 31, 203, 113, 229, - 68, 32, 134, 46, 96, 76, 166, 21, 148, 135, 78, 173, 169, 139, 185, 73, 238, 192, 23, 95, 213, - 24, 4, 39, 76, 117, 254, 1, 120, 140, 33, 190, 0, 239, 231, 126, 61, 202, 158, 245, 247, 130, - 126, 110, 20, 40, 100, 175, 121, 242, 141, 14, 136, 104, 72, 28, 198, 15, 41, 237, 46, 55, 190, - 155, 142, 222, 228, 194, 141, 159, 49, 107, 199, 192, 211, 142, 107, 56, 186, 23, 16, 125, 206, - 190, 145, 71, 125, 210, 204, 187, 83, 166, 22, 40, 247, 12, 225, 246, 3, 1, 23, 62, 60, 99, - 171, 250, 31, 152, 130, 13, 44, 93, 12, 89, 132, 212, 123, 114, 82, 78, 177, 65, 103, 199, 148, - 118, 13, 79, 249, 206, 166, 62, 59, 223, 135, 171, 186, 137, 85, 163, 20, 202, 6, 236, 236, 92, - 227, 35, 99, 47, 165, 18, 173, 70, 165, 127, 209, 226, 172, 169, 162, 131, 238, 87, 11, 64, - 126, 186, 130, 27, 155, 86, 140, 190, 176, 175, 251, 78, 216, 253, 178, 247, 69, 108, 27, 31, - 107, 111, 31, 49, 84, 200, 123, 147, 232, 94, 21, 79, 19, 254, 100, 211, 92, 143, 153, 80, 194, - 42, 235, 244, 18, 179, 66, 17, 252, 197, 8, 247, 122, 166, 219, 106, 194, 236, 203, 180, 38, - 147, 82, 236, 229, 121, 147, 162, 197, 227, 142, 216, 225, 150, 157, 153, 30, 88, 3, 62, 157, - 101, 2, 138, 157, 47, 45, 44, 163, 105, 49, 109, 29, 69, 248, 59, 173, 213, 248, 39, 149, 17, - 248, 172, 207, 109, 167, 252, 123, 107, 26, 77, 28, 148, 134, 74, 195, 6, 109, 210, 44, 255, - 148, 200, 125, 10, 194, 5, 130, 85, 36, 192, 203, 249, 7, 53, 21, 86, 114, 236, 206, 157, 105, - 34, 91, 81, 56, 168, 52, 235, 229, 162, 3, 75, 123, 175, 93, 197, 22, 111, 88, 58, 246, 140, - 85, 134, 60, 81, 125, 166, 53, 143, 31, 41, 46, 148, 167, 64, 61, 199, 254, 29, 109, 44, 75, 1, - 165, 224, 251, 107, 119, 130, 225, 98, 50, 120, 35, 7, 138, 70, 125, 202, 199, 71, 99, 103, 67, - 71, 221, 175, 107, 229, 122, 25, 162, 122, 80, 91, 116, 226, 175, 216, 220, 166, 125, 234, 77, - 72, 54, 206, 20, 62, 115, 120, 38, 193, 207, 181, 101, 62, 173, 225, 135, 32, 65, 0, 252, 71, - 173, 4, 20, 171, 197, 54, 179, 213, 91, 42, 22, 248, 2, 96, 231, 86, 150, 204, 208, 135, 138, - 179, 177, 13, 58, 79, 50, 8, 199, 174, 162, 137, 242, 45, 135, 46, 25, 162, 137, 205, 25, 199, - 165, 1, 234, 4, 169, 249, 149, 99, 208, 88, 217, 131, 126, 161, 108, 115, 69, 38, 76, 20, 132, - 123, 5, 81, 58, 180, 3, 3, 233, 129, 220, 96, 52, 115, 238, 207, 200, 185, 155, 148, 147, 75, - 29, 254, 239, 18, 161, 110, 201, 33, 40, 90, 18, 31, 66, 15, 212, 175, 150, 14, 11, 142, 201, - 45, 50, 15, 20, 39, 213, 61, 158, 150, 110, 132, 117, 143, 9, 215, 215, 11, 238, 183, 156, 142, - 200, 190, 193, 221, 105, 236, 109, 9, 219, 160, 67, 122, 143, 109, 175, 42, 56, 88, 55, 56, 89, - 61, 98, 97, 213, 142, 167, 25, 168, 129, 59, 134, 59, 4, 95, 85, 117, 105, 149, 134, 21, 115, - 167, 178, 21, 124, 231, 65, 85, 14, 26, 232, 102, 11, 204, 206, 59, 162, 123, 179, 159, 214, - 253, 117, 246, 58, 42, 90, 25, 72, 127, 216, 238, 125, 180, 41, 115, 213, 251, 3, 79, 62, 13, - 96, 118, 237, 158, 58, 251, 62, 98, 156, 196, 174, 82, 245, 37, 237, 57, 191, 48, 60, 56, 224, - 201, 14, 161, 170, 245, 208, 153, 137, 28, 157, 43, 25, 249, 157, 232, 39, 192, 13, 168, 6, - 212, 118, 141, 55, 83, 243, 229, 26, 21, 207, 241, 14, 231, 13, 18, 64, 104, 30, 180, 30, 108, - 225, 235, 68, 149, 208, 35, 220, 20, 57, 161, 102, 10, 196, 72, 173, 80, 0, 87, 80, 136, 16, - 202, 114, 115, 15, 168, 76, 28, 220, 45, 157, 232, 82, 161, 52, 111, 192, 193, 17, 193, 29, - 141, 239, 252, 51, 78, 252, 122, 174, 150, 148, 68, 140, 212, 184, 243, 169, 137, 130, 7, 80, - 240, 19, 9, 171, 195, 91, 166, 200, 164, 142, 171, 252, 148, 146, 252, 92, 67, 13, 125, 228, - 246, 199, 47, 239, 155, 75, 103, 39, 178, 14, 190, 253, 180, 20, 64, 140, 154, 0, 220, 253, - 253, 253, 191, 229, 152, 236, 107, 216, 65, 41, 125, 12, 93, 169, 212, 239, 212, 63, 24, 242, - 97, 102, 73, 120, 223, 170, 62, 174, 254, 127, 219, 111, 46, 196, 100, 179, 218, 236, 49, 110, - 201, 236, 222, 247, 186, 38, 107, 229, 98, 121, 36, 12, 60, 28, 63, 52, 252, 252, 211, 70, 81, - 123, 189, 3, 204, 201, 162, 148, 169, 95, 33, 164, 126, 224, 183, 232, 27, 30, 27, 40, 148, 92, - 201, 2, 19, 248, 138, 18, 169, 255, 92, 110, 218, 110, 226, 237, 2, 185, 37, 190, 162, 180, 72, - 238, 90, 242, 174, 7, 136, 217, 170, 205, 56, 35, 123, 28, 72, 13, 68, 61, 88, 210, 134, 9, - 248, 95, 195, 19, 101, 213, 8, 8, 145, 253, 197, 63, 210, 98, 67, 188, 99, 51, 119, 236, 240, - 103, 177, 218, 220, 218, 157, 227, 47, 217, 175, 9, 162, 47, 221, 228, 178, 222, 82, 191, 149, - 62, 97, 59, 95, 198, 124, 87, 239, 205, 54, 83, 172, 225, 39, 114, 243, 45, 215, 60, 244, 7, - 79, 94, 73, 71, 155, 116, 230, 77, 133, 237, 114, 20, 132, 19, 243, 249, 132, 51, 238, 209, - 231, 78, 69, 1, 151, 207, 178, 65, 135, 28, 54, 9, 33, 209, 44, 127, 192, 35, 180, 236, 164, - 236, 67, 214, 144, 242, 250, 120, 171, 137, 167, 242, 236, 245, 131, 229, 60, 93, 114, 34, 23, - 149, 10, 129, 49, 103, 118, 22, 0, 224, 22, 218, 15, 235, 161, 74, 33, 198, 85, 27, 213, 248, - 151, 87, 253, 54, 215, 243, 252, 168, 208, 227, 6, 167, 144, 203, 59, 125, 234, 215, 31, 175, - 83, 147, 83, 76, 222, 122, 108, 71, 115, 7, 183, 69, 201, 65, 209, 120, 96, 88, 50, 128, 43, - 141, 128, 65, 120, 180, 225, 2, 137, 9, 20, 93, 251, 177, 201, 77, 67, 44, 52, 95, 63, 191, 36, - 172, 171, 71, 222, 4, 167, 102, 232, 18, 5, 191, 218, 176, 238, 123, 117, 172, 155, 124, 85, - 91, 209, 120, 187, 79, 226, 130, 43, 249, 101, 232, 103, 29, 88, 225, 96, 98, 20, 22, 57, 153, - 197, 201, 8, 188, 11, 163, 252, 43, 164, 112, 27, 146, 101, 96, 138, 64, 152, 152, 102, 42, - 139, 167, 211, 117, 188, 189, 66, 186, 198, 44, 86, 62, 58, 82, 128, 86, 68, 205, 88, 37, 180, - 65, 127, 149, 191, 222, 117, 91, 122, 138, 26, 228, 35, 40, 10, 174, 228, 1, 255, 235, 34, 110, - 72, 100, 18, 71, 105, 185, 114, 3, 115, 97, 133, 27, 148, 192, 1, 91, 165, 111, 76, 70, 102, - 23, 24, 252, 49, 136, 90, 163, 224, 65, 23, 9, 0, 163, 196, 137, 96, 1, 193, 76, 38, 84, 154, - 209, 229, 144, 228, 82, 229, 150, 31, 3, 221, 94, 252, 1, 226, 38, 40, 160, 153, 28, 80, 141, - 186, 84, 134, 19, 114, 172, 28, 236, 184, 91, 208, 61, 248, 184, 99, 136, 187, 75, 134, 179, - 64, 95, 95, 206, 186, 156, 252, 179, 227, 55, 121, 50, 72, 173, 162, 133, 70, 131, 174, 214, - 118, 239, 141, 130, 237, 141, 248, 252, 50, 176, 164, 183, 174, 56, 109, 124, 142, 50, 25, 164, - 164, 160, 54, 242, 175, 228, 17, 108, 31, 73, 203, 211, 31, 240, 234, 148, 252, 101, 155, 14, - 184, 203, 31, 94, 45, 5, 127, 176, 236, 24, 119, 177, 249, 182, 24, 244, 79, 205, 184, 6, 106, - 33, 71, 31, 246, 33, 223, 47, 233, 192, 76, 252, 106, 49, 108, 143, 146, 87, 77, 208, 67, 99, - 151, 165, 122, 57, 231, 253, 231, 102, 67, 83, 12, 153, 198, 169, 28, 187, 77, 79, 115, 149, - 244, 161, 141, 64, 9, 215, 211, 182, 175, 205, 33, 194, 41, 159, 129, 178, 140, 123, 117, 182, - 210, 146, 17, 198, 82, 220, 105, 92, 183, 240, 13, 28, 73, 34, 175, 8, 203, 69, 208, 254, 127, - 109, 174, 232, 176, 142, 254, 220, 56, 80, 43, 137, 66, 143, 222, 152, 191, 1, 143, 204, 231, - 122, 92, 123, 217, 221, 99, 65, 27, 149, 57, 33, 209, 42, 4, 139, 156, 211, 77, 91, 17, 4, 198, - 51, 0, 173, 41, 212, 24, 210, 67, 129, 167, 50, 127, 125, 62, 95, 12, 31, 185, 99, 211, 108, - 210, 77, 243, 237, 2, 16, 142, 213, 239, 239, 163, 228, 242, 127, 101, 189, 32, 247, 4, 64, - 182, 10, 20, 202, 83, 166, 152, 137, 175, 83, 121, 85, 247, 202, 37, 130, 148, 198, 15, 118, - 106, 184, 43, 103, 171, 211, 198, 21, 61, 34, 176, 225, 83, 225, 103, 238, 169, 252, 16, 212, - 138, 185, 142, 104, 233, 193, 67, 134, 191, 25, 169, 106, 202, 233, 37, 82, 107, 58, 163, 240, - 70, 52, 243, 130, 10, 225, 246, 40, 164, 210, 76, 197, 35, 162, 125, 51, 17, 74, 68, 67, 232, - 231, 223, 57, 239, 252, 117, 34, 92, 36, 213, 118, 142, 232, 4, 184, 59, 108, 115, 194, 67, - 133, 223, 219, 135, 195, 121, 120, 170, 224, 143, 124, 195, 116, 29, 125, 204, 252, 155, 104, - 28, 246, 42, 144, 139, 101, 190, 226, 38, 172, 10, 153, 187, 77, 97, 104, 234, 208, 168, 237, - 123, 49, 147, 199, 167, 139, 232, 27, 188, 52, 250, 76, 90, 44, 181, 45, 26, 166, 222, 251, - 142, 56, 142, 165, 121, 57, 102, 76, 112, 189, 192, 89, 33, 117, 31, 13, 200, 217, 143, 206, - 156, 191, 173, 52, 100, 11, 179, 34, 16, 48, 109, 40, 150, 164, 193, 27, 155, 32, 8, 203, 145, - 134, 254, 69, 154, 129, 234, 146, 173, 252, 223, 8, 143, 23, 78, 248, 250, 232, 69, 10, 161, - 127, 56, 56, 75, 237, 80, 33, 90, 34, 73, 251, 215, 88, 110, 94, 185, 79, 151, 135, 155, 71, - 122, 7, 50, 139, 98, 165, 221, 37, 20, 30, 86, 120, 66, 233, 136, 71, 212, 100, 42, 230, 236, - 229, 26, 233, 163, 86, 86, 153, 63, 232, 108, 20, 181, 39, 120, 230, 98, 116, 189, 36, 132, - 252, 193, 21, 90, 65, 68, 31, 183, 9, 137, 176, 183, 114, 83, 35, 130, 119, 189, 74, 207, 141, - 53, 165, 189, 29, 177, 230, 240, 40, 136, 118, 131, 4, 202, 149, 85, 90, 73, 232, 215, 251, - 143, 73, 63, 198, 106, 52, 23, 102, 187, 155, 206, 192, 225, 217, 98, 0, 186, 103, 147, 182, - 212, 192, 112, 114, 157, 234, 157, 104, 183, 202, 2, 103, 34, 162, 129, 21, 0, 32, 21, 21, 75, - 190, 5, 207, 69, 157, 81, 110, 243, 239, 53, 117, 200, 69, 125, 85, 180, 44, 34, 118, 217, 196, - 74, 22, 122, 151, 223, 227, 15, 19, 84, 129, 177, 59, 0, 117, 221, 78, 200, 46, 239, 93, 19, - 238, 200, 161, 187, 231, 76, 141, 6, 137, 49, 12, 83, 65, 240, 104, 31, 166, 205, 94, 174, 102, - 168, 188, 173, 121, 194, 129, 85, 225, 197, 28, 127, 89, 181, 21, 60, 234, 221, 26, 7, 147, - 165, 219, 165, 123, 164, 115, 240, 154, 77, 103, 128, 101, 243, 12, 137, 199, 147, 62, 124, - 220, 143, 67, 213, 119, 182, 52, 7, 100, 150, 194, 164, 17, 88, 138, 82, 41, 198, 120, 40, 115, - 239, 114, 12, 246, 178, 128, 173, 28, 48, 55, 9, 13, 85, 60, 168, 23, 202, 91, 85, 208, 207, - 86, 160, 30, 194, 161, 108, 20, 94, 120, 73, 152, 218, 161, 198, 65, 116, 49, 212, 153, 232, - 179, 84, 119, 45, 155, 168, 40, 178, 205, 154, 64, 56, 8, 182, 178, 208, 3, 21, 147, 11, 238, - 15, 185, 175, 182, 206, 70, 177, 106, 191, 12, 13, 185, 161, 35, 162, 250, 230, 235, 80, 27, - 87, 255, 252, 250, 155, 189, 88, 5, 168, 4, 124, 97, 106, 38, 145, 163, 34, 18, 203, 62, 180, - 127, 74, 42, 53, 62, 215, 85, 48, 104, 94, 128, 235, 118, 64, 151, 144, 139, 215, 45, 118, 255, - 23, 27, 216, 15, 71, 231, 21, 60, 143, 105, 161, 100, 224, 80, 205, 78, 78, 35, 11, 116, 51, - 66, 87, 227, 137, 253, 237, 168, 9, 255, 226, 244, 124, 224, 243, 82, 121, 93, 235, 17, 41, - 179, 239, 160, 49, 221, 221, 6, 91, 132, 28, 143, 209, 94, 185, 87, 73, 146, 118, 99, 121, 98, - 163, 248, 201, 253, 217, 48, 247, 167, 86, 32, 235, 159, 226, 223, 75, 127, 19, 181, 207, 213, - 185, 118, 36, 144, 29, 75, 74, 132, 67, 238, 148, 92, 149, 9, 231, 107, 229, 15, 244, 54, 198, - 60, 34, 134, 96, 91, 53, 153, 11, 44, 171, 0, 187, 207, 180, 179, 25, 35, 233, 69, 19, 1, 164, - 75, 251, 88, 145, 70, 60, 99, 158, 123, 218, 4, 245, 211, 144, 10, 132, 252, 24, 31, 80, 220, - 149, 126, 38, 137, 165, 115, 0, 52, 37, 32, 61, 0, 128, 227, 28, 211, 77, 212, 122, 182, 1, - 146, 179, 127, 185, 45, 255, 8, 130, 248, 122, 115, 232, 225, 253, 255, 92, 4, 18, 216, 113, - 77, 229, 77, 182, 154, 80, 83, 236, 227, 195, 150, 13, 250, 24, 206, 1, 240, 215, 183, 192, - 203, 86, 209, 86, 230, 194, 236, 51, 0, 64, 58, 162, 173, 195, 174, 220, 200, 209, 104, 34, 26, - 5, 28, 243, 236, 32, 178, 8, 164, 98, 188, 148, 27, 153, 132, 91, 229, 245, 255, 14, 129, 128, - 173, 166, 41, 83, 161, 2, 37, 118, 32, 60, 240, 214, 78, 34, 85, 24, 36, 131, 229, 232, 180, - 86, 90, 27, 200, 91, 27, 6, 44, 239, 64, 132, 220, 135, 16, 4, 0, 52, 246, 18, 48, 5, 65, 141, - 148, 194, 83, 90, 196, 64, 130, 27, 62, 151, 128, 104, 40, 121, 137, 28, 123, 18, 121, 253, - 250, 86, 84, 174, 131, 52, 115, 28, 143, 56, 96, 228, 215, 68, 78, 93, 160, 100, 241, 133, 114, - 89, 167, 131, 6, 82, 143, 48, 12, 93, 213, 85, 78, 194, 70, 178, 179, 184, 201, 47, 179, 1, - 149, 252, 148, 224, 146, 168, 5, 83, 218, 250, 212, 21, 241, 191, 233, 185, 65, 198, 37, 255, - 162, 167, 245, 139, 175, 74, 10, 24, 149, 140, 186, 35, 226, 1, 154, 21, 88, 120, 36, 8, 53, - 70, 165, 52, 174, 5, 95, 59, 113, 165, 115, 47, 108, 128, 203, 133, 50, 217, 255, 157, 136, 79, - 151, 137, 80, 22, 2, 89, 223, 228, 45, 208, 203, 157, 102, 176, 97, 70, 53, 54, 224, 217, 138, - 202, 7, 142, 148, 250, 63, 102, 185, 91, 122, 120, 46, 153, 242, 66, 207, 197, 191, 31, 82, 56, - 14, 176, 125, 4, 166, 166, 15, 55, 160, 11, 17, 95, 44, 9, 53, 67, 120, 35, 166, 180, 187, 117, - 171, 105, 82, 22, 17, 47, 96, 227, 49, 112, 8, 31, 133, 113, 38, 97, 12, 10, 95, 73, 176, 27, - 240, 232, 105, 220, 12, 192, 234, 88, 223, 128, 209, 57, 140, 30, 203, 120, 36, 87, 185, 208, - 164, 20, 120, 95, 198, 207, 109, 16, 141, 168, 189, 157, 125, 21, 24, 127, 64, 27, 230, 32, 14, - 158, 7, 122, 53, 17, 233, 201, 56, 63, 129, 39, 251, 24, 122, 45, 159, 205, 204, 194, 145, 131, - 247, 234, 35, 21, 103, 73, 60, 195, 61, 158, 228, 122, 236, 0, 13, 69, 74, 245, 110, 146, 37, - 40, 24, 54, 156, 3, 79, 10, 170, 241, 27, 29, 157, 79, 101, 84, 191, 227, 175, 76, 172, 61, 82, - 90, 34, 220, 92, 29, 29, 39, 75, 161, 74, 174, 14, 83, 198, 143, 73, 173, 228, 181, 215, 145, - 5, 38, 67, 91, 87, 19, 3, 124, 49, 252, 85, 135, 190, 77, 134, 150, 195, 42, 134, 130, 154, - 135, 255, 122, 157, 216, 101, 33, 95, 50, 170, 204, 206, 210, 157, 72, 34, 137, 231, 69, 34, - 72, 27, 111, 93, 155, 131, 90, 183, 102, 146, 204, 137, 167, 241, 41, 166, 185, 32, 28, 38, - 144, 0, 219, 7, 238, 252, 169, 59, 132, 91, 179, 142, 60, 123, 128, 178, 71, 232, 229, 232, - 227, 237, 137, 87, 186, 191, 146, 92, 40, 234, 225, 210, 207, 213, 119, 118, 56, 218, 197, 185, - 131, 34, 248, 242, 222, 143, 135, 75, 62, 230, 212, 155, 150, 193, 143, 46, 27, 165, 127, 51, - 210, 7, 254, 219, 202, 155, 80, 69, 19, 235, 202, 201, 160, 200, 192, 130, 71, 0, 0, 247, 240, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8, 0, 0, 0, 33, 28, 19, 12, 0, 54, 48, 39, + 94, 33, 98, 146, 161, 54, 134, 128, 25, 186, 123, 227, 252, 67, 83, 186, 107, 220, 17, 173, + 112, 10, 229, 123, 62, 141, 188, 100, 81, 1, 107, 218, 140, 168, 73, 10, 157, 35, 106, 179, + 233, 79, 47, 83, 236, 172, 4, 253, 205, 15, 51, 204, 45, 103, 101, 43, 96, 66, 41, 214, 192, + 198, 192, 66, 214, 212, 206, 233, 172, 249, 172, 193, 195, 189, 166, 2, 142, 131, 232, 50, 19, + 214, 114, 234, 167, 202, 26, 170, 32, 242, 251, 60, 236, 234, 132, 76, 188, 112, 0, 66, 101, + 124, 53, 56, 187, 79, 104, 93, 250, 16, 249, 240, 29, 207, 160, 192, 99, 197, 40, 24, 207, 78, + 113, 73, 139, 244, 110, 110, 192, 234, 220, 144, 246, 25, 83, 28, 80, 7, 44, 58, 14, 19, 61, + 232, 196, 173, 92, 221, 135, 227, 136, 93, 94, 90, 248, 69, 208, 77, 34, 168, 2, 136, 147, 15, + 172, 21, 50, 158, 48, 52, 246, 10, 149, 143, 109, 104, 41, 99, 15, 206, 198, 190, 209, 155, 97, + 194, 219, 179, 184, 150, 219, 95, 159, 88, 212, 102, 76, 2, 122, 170, 209, 56, 85, 65, 94, 123, + 24, 119, 55, 193, 77, 219, 6, 173, 123, 23, 53, 86, 75, 231, 147, 92, 166, 51, 232, 247, 170, + 215, 51, 2, 190, 147, 2, 15, 91, 30, 204, 167, 43, 237, 51, 75, 182, 18, 27, 50, 150, 138, 215, + 126, 117, 41, 99, 118, 86, 73, 2, 108, 25, 193, 207, 42, 35, 242, 177, 64, 247, 149, 141, 75, + 185, 145, 211, 34, 147, 203, 198, 163, 37, 22, 162, 242, 171, 215, 189, 201, 31, 193, 88, 110, + 126, 252, 249, 108, 66, 67, 151, 139, 172, 3, 175, 2, 241, 95, 67, 127, 118, 109, 120, 202, 0, + 212, 12, 221, 248, 68, 77, 69, 17, 6, 62, 154, 28, 61, 74, 251, 153, 78, 233, 190, 190, 103, + 181, 233, 156, 64, 226, 222, 72, 67, 228, 57, 130, 183, 192, 147, 37, 212, 153, 255, 249, 201, + 41, 170, 30, 166, 237, 23, 146, 152, 159, 110, 181, 134, 198, 193, 0, 106, 187, 151, 16, 86, + 152, 201, 94, 229, 234, 0, 95, 36, 146, 207, 91, 224, 194, 236, 136, 0, 8, 92, 5, 92, 32, 99, + 180, 86, 220, 175, 247, 54, 1, 70, 250, 198, 252, 58, 146, 167, 123, 146, 98, 33, 131, 253, 12, + 53, 194, 136, 147, 109, 107, 217, 122, 101, 230, 48, 0, 32, 241, 150, 247, 208, 155, 185, 26, + 147, 210, 161, 28, 136, 132, 84, 13, 112, 29, 96, 87, 160, 108, 183, 50, 76, 161, 16, 114, 61, + 58, 168, 125, 11, 242, 105, 144, 154, 116, 102, 128, 11, 79, 18, 33, 23, 91, 223, 228, 8, 123, + 65, 91, 49, 77, 218, 64, 36, 202, 69, 51, 224, 13, 187, 252, 197, 161, 240, 183, 145, 146, 53, + 142, 179, 47, 54, 169, 162, 234, 213, 185, 63, 231, 140, 202, 238, 36, 116, 240, 174, 197, 150, + 136, 136, 142, 96, 67, 198, 174, 14, 123, 59, 41, 19, 85, 42, 76, 6, 83, 133, 155, 231, 250, + 173, 95, 119, 153, 104, 178, 179, 166, 250, 122, 52, 219, 155, 112, 22, 187, 209, 56, 255, 214, + 136, 230, 93, 96, 21, 239, 143, 21, 191, 51, 61, 30, 91, 241, 39, 29, 151, 7, 181, 232, 104, + 141, 174, 87, 49, 251, 75, 202, 169, 180, 141, 42, 103, 83, 227, 228, 53, 28, 173, 242, 156, + 66, 95, 185, 204, 75, 244, 253, 65, 101, 188, 197, 70, 224, 247, 171, 2, 122, 198, 157, 227, + 176, 45, 210, 178, 169, 52, 222, 59, 18, 122, 245, 91, 180, 136, 66, 1, 128, 84, 218, 208, 20, + 73, 46, 114, 115, 150, 204, 106, 33, 129, 34, 233, 44, 194, 98, 134, 41, 16, 143, 210, 166, 52, + 252, 110, 52, 74, 38, 112, 207, 121, 103, 106, 108, 141, 131, 175, 159, 42, 174, 134, 9, 222, + 125, 28, 208, 129, 120, 25, 84, 16, 42, 200, 171, 22, 70, 249, 217, 49, 143, 107, 9, 232, 157, + 124, 44, 210, 19, 222, 145, 250, 254, 137, 12, 132, 199, 107, 94, 32, 223, 141, 6, 110, 255, + 56, 232, 206, 79, 154, 196, 156, 240, 35, 57, 39, 241, 147, 27, 176, 111, 188, 248, 114, 6, 42, + 235, 21, 180, 177, 24, 53, 144, 4, 128, 167, 230, 26, 130, 201, 131, 211, 180, 159, 113, 157, + 13, 218, 18, 100, 253, 50, 172, 88, 146, 92, 124, 126, 52, 86, 163, 56, 14, 52, 226, 205, 117, + 177, 42, 98, 92, 12, 41, 67, 16, 41, 63, 111, 35, 130, 85, 167, 75, 99, 241, 83, 154, 170, 69, + 47, 87, 166, 172, 88, 179, 246, 222, 181, 180, 116, 197, 42, 45, 238, 230, 80, 243, 185, 230, + 209, 75, 215, 13, 11, 28, 88, 124, 89, 111, 196, 56, 46, 186, 239, 79, 216, 36, 93, 123, 140, + 148, 179, 217, 244, 186, 127, 52, 22, 34, 7, 77, 33, 43, 244, 55, 252, 11, 166, 128, 70, 7, + 137, 115, 8, 31, 179, 233, 212, 38, 255, 0, 225, 247, 230, 72, 94, 244, 23, 58, 16, 174, 66, + 164, 231, 79, 21, 125, 201, 93, 30, 8, 111, 179, 138, 245, 55, 202, 177, 125, 106, 236, 206, + 154, 204, 28, 118, 97, 78, 21, 123, 168, 132, 197, 107, 139, 136, 184, 95, 205, 188, 190, 229, + 73, 239, 19, 235, 248, 177, 19, 240, 191, 162, 56, 126, 110, 40, 214, 135, 140, 231, 35, 137, + 181, 248, 96, 7, 74, 233, 194, 234, 95, 145, 51, 124, 239, 46, 90, 229, 91, 224, 32, 47, 43, + 60, 104, 132, 212, 60, 104, 210, 9, 38, 157, 18, 107, 117, 204, 242, 135, 29, 122, 167, 232, + 45, 106, 234, 193, 11, 217, 253, 219, 235, 200, 157, 94, 172, 179, 71, 250, 91, 224, 115, 84, + 234, 212, 156, 16, 156, 177, 240, 51, 118, 44, 95, 11, 229, 124, 201, 25, 7, 152, 5, 74, 31, + 221, 29, 34, 188, 228, 168, 118, 75, 41, 169, 211, 44, 61, 81, 170, 250, 39, 156, 148, 136, + 162, 79, 34, 35, 20, 220, 248, 39, 170, 79, 131, 245, 210, 229, 22, 122, 166, 49, 120, 232, + 124, 90, 138, 120, 251, 128, 118, 115, 122, 202, 148, 139, 51, 196, 11, 99, 230, 177, 195, 160, + 16, 197, 41, 127, 69, 132, 11, 23, 32, 41, 201, 108, 210, 224, 19, 157, 101, 87, 66, 132, 12, + 128, 170, 194, 5, 33, 251, 148, 162, 225, 76, 46, 251, 192, 168, 217, 140, 81, 164, 99, 180, + 116, 128, 76, 221, 169, 231, 231, 233, 100, 207, 145, 38, 216, 107, 139, 3, 132, 244, 218, 91, + 161, 194, 125, 49, 180, 111, 137, 124, 38, 245, 114, 133, 103, 131, 247, 252, 73, 6, 202, 66, + 200, 170, 72, 45, 229, 203, 191, 149, 9, 97, 24, 1, 39, 189, 209, 221, 105, 152, 115, 119, 92, + 179, 49, 173, 233, 68, 152, 68, 108, 59, 136, 237, 190, 216, 10, 85, 79, 220, 10, 126, 16, 155, + 138, 184, 231, 159, 205, 227, 90, 61, 122, 217, 8, 3, 34, 205, 67, 255, 196, 201, 248, 143, 5, + 86, 227, 191, 28, 123, 189, 146, 227, 29, 117, 100, 74, 1, 44, 119, 65, 83, 125, 83, 118, 155, + 6, 221, 51, 193, 243, 245, 122, 214, 129, 142, 246, 234, 238, 198, 77, 232, 187, 254, 118, 68, + 152, 11, 117, 80, 3, 57, 182, 36, 174, 31, 67, 198, 45, 200, 25, 176, 105, 172, 194, 178, 215, + 155, 186, 233, 139, 21, 127, 108, 193, 86, 185, 233, 220, 243, 210, 72, 251, 93, 125, 196, 124, + 16, 103, 138, 126, 245, 71, 221, 30, 196, 185, 31, 155, 138, 4, 27, 8, 114, 28, 236, 146, 199, + 189, 215, 243, 117, 78, 129, 188, 87, 204, 26, 235, 28, 205, 128, 230, 216, 25, 26, 5, 187, 49, + 120, 8, 35, 182, 153, 135, 56, 184, 253, 239, 175, 167, 125, 117, 77, 211, 87, 56, 41, 157, 95, + 150, 198, 75, 18, 60, 214, 205, 196, 72, 9, 153, 233, 152, 109, 232, 89, 109, 56, 65, 21, 109, + 196, 186, 52, 35, 73, 59, 63, 201, 104, 195, 243, 215, 202, 15, 168, 187, 164, 104, 66, 112, + 122, 237, 195, 122, 74, 137, 104, 224, 57, 28, 254, 45, 65, 151, 234, 143, 106, 123, 118, 29, + 14, 94, 107, 157, 90, 48, 157, 102, 125, 35, 14, 123, 7, 255, 143, 106, 55, 6, 29, 83, 135, + 107, 141, 169, 184, 122, 191, 70, 47, 112, 190, 127, 72, 68, 120, 79, 63, 168, 249, 199, 7, + 226, 64, 125, 117, 102, 182, 222, 28, 224, 157, 202, 219, 214, 145, 77, 222, 102, 140, 83, 158, + 131, 93, 109, 139, 150, 148, 142, 57, 57, 162, 127, 216, 71, 103, 126, 8, 104, 55, 188, 82, + 157, 53, 217, 34, 143, 23, 209, 241, 26, 70, 206, 77, 78, 170, 230, 149, 70, 44, 190, 1, 197, + 125, 154, 236, 20, 41, 209, 124, 111, 10, 0, 54, 133, 193, 195, 97, 34, 110, 99, 244, 212, 111, + 146, 162, 243, 89, 136, 80, 210, 177, 226, 37, 36, 135, 66, 98, 6, 113, 160, 3, 80, 208, 99, + 120, 77, 123, 23, 105, 72, 163, 194, 9, 74, 222, 178, 195, 143, 1, 171, 31, 163, 90, 75, 58, + 114, 67, 255, 123, 249, 247, 86, 106, 86, 156, 255, 209, 246, 22, 68, 110, 32, 40, 140, 221, + 15, 142, 105, 55, 167, 173, 170, 210, 232, 185, 124, 183, 177, 133, 170, 13, 78, 220, 23, 146, + 132, 27, 4, 48, 116, 224, 155, 249, 13, 143, 83, 237, 131, 31, 181, 5, 228, 68, 229, 113, 203, + 96, 46, 134, 32, 148, 21, 166, 76, 169, 173, 78, 135, 238, 73, 185, 139, 213, 95, 23, 192, 76, + 39, 4, 24, 120, 1, 254, 117, 0, 190, 33, 140, 61, 126, 231, 239, 247, 245, 158, 202, 20, 110, + 126, 130, 121, 175, 100, 40, 136, 14, 141, 242, 198, 28, 72, 104, 46, 237, 41, 15, 142, 155, + 190, 55, 141, 194, 228, 222, 199, 107, 49, 159, 107, 142, 211, 192, 16, 23, 186, 56, 145, 190, + 206, 125, 204, 210, 125, 71, 22, 166, 83, 187, 225, 12, 247, 40, 23, 1, 3, 246, 171, 99, 60, + 62, 130, 152, 31, 250, 12, 93, 44, 13, 123, 212, 132, 89, 177, 78, 82, 114, 148, 199, 103, 65, + 249, 79, 13, 118, 59, 62, 166, 206, 186, 171, 135, 223, 20, 163, 85, 137, 236, 236, 6, 202, 99, + 35, 227, 92, 173, 18, 165, 47, 209, 127, 165, 70, 162, 169, 172, 226, 11, 87, 238, 131, 130, + 186, 126, 64, 140, 86, 155, 27, 251, 175, 176, 190, 178, 253, 216, 78, 27, 108, 69, 247, 31, + 111, 107, 31, 123, 200, 84, 49, 21, 94, 232, 147, 100, 254, 19, 79, 153, 143, 92, 211, 235, 42, + 194, 80, 66, 179, 18, 244, 8, 197, 252, 17, 219, 166, 122, 247, 203, 236, 194, 106, 82, 147, + 38, 180, 147, 121, 229, 236, 142, 227, 197, 162, 157, 150, 225, 216, 3, 88, 30, 153, 2, 101, + 157, 62, 45, 47, 157, 138, 49, 105, 163, 44, 248, 69, 29, 109, 248, 213, 173, 59, 248, 17, 149, + 39, 167, 109, 207, 172, 26, 107, 123, 252, 134, 148, 28, 77, 109, 6, 195, 74, 148, 255, 44, + 210, 194, 10, 125, 200, 36, 85, 130, 5, 7, 249, 203, 192, 114, 86, 21, 53, 105, 157, 206, 236, + 56, 81, 91, 34, 229, 235, 52, 168, 123, 75, 3, 162, 22, 197, 93, 175, 246, 58, 88, 111, 60, + 134, 85, 140, 53, 166, 125, 81, 46, 41, 31, 143, 61, 64, 167, 148, 109, 29, 254, 199, 165, 1, + 75, 44, 119, 107, 251, 224, 50, 98, 225, 130, 138, 7, 35, 120, 199, 202, 125, 70, 67, 103, 99, + 71, 107, 175, 221, 71, 162, 25, 122, 229, 116, 91, 80, 122, 220, 216, 175, 226, 77, 234, 125, + 166, 20, 206, 54, 72, 38, 120, 115, 62, 101, 181, 207, 193, 135, 225, 173, 62, 252, 0, 65, 32, + 20, 4, 173, 71, 179, 54, 197, 171, 22, 42, 91, 213, 231, 96, 2, 248, 208, 204, 150, 86, 177, + 179, 138, 135, 50, 79, 58, 13, 162, 174, 199, 8, 135, 45, 242, 137, 137, 162, 25, 46, 165, 199, + 25, 205, 169, 4, 234, 1, 208, 99, 149, 249, 126, 131, 217, 88, 69, 115, 108, 161, 132, 20, 76, + 38, 58, 81, 5, 123, 233, 3, 3, 180, 52, 96, 220, 129, 200, 207, 238, 115, 147, 148, 155, 185, + 239, 254, 29, 75, 201, 110, 161, 18, 18, 90, 40, 33, 212, 15, 66, 31, 11, 14, 150, 175, 50, 45, + 201, 142, 213, 39, 20, 15, 110, 150, 158, 61, 9, 143, 117, 132, 238, 11, 215, 215, 200, 142, + 156, 183, 105, 221, 193, 190, 219, 9, 109, 236, 143, 122, 67, 160, 56, 42, 175, 109, 89, 56, + 55, 88, 213, 97, 98, 61, 168, 25, 167, 142, 59, 134, 59, 129, 117, 85, 95, 4, 21, 134, 149, + 105, 21, 178, 167, 115, 85, 65, 231, 124, 102, 232, 26, 14, 59, 206, 204, 11, 159, 179, 123, + 162, 246, 117, 253, 214, 25, 90, 42, 58, 238, 216, 127, 72, 115, 41, 180, 125, 79, 3, 251, 213, + 118, 96, 13, 62, 251, 58, 158, 237, 196, 156, 98, 62, 37, 245, 82, 174, 48, 191, 57, 237, 201, + 224, 56, 60, 245, 170, 161, 14, 28, 137, 153, 208, 249, 25, 43, 157, 192, 39, 232, 157, 212, 6, + 168, 13, 83, 55, 141, 118, 21, 26, 229, 243, 231, 14, 241, 207, 104, 64, 18, 13, 108, 30, 180, + 30, 149, 68, 235, 225, 20, 220, 35, 208, 10, 102, 161, 57, 80, 173, 72, 196, 136, 80, 87, 0, + 115, 114, 202, 16, 28, 76, 168, 15, 232, 157, 45, 220, 111, 52, 161, 82, 193, 17, 193, 192, + 252, 239, 141, 29, 122, 252, 78, 51, 68, 148, 150, 174, 243, 184, 212, 140, 7, 130, 137, 169, + 9, 19, 240, 80, 166, 91, 195, 171, 171, 142, 164, 200, 252, 146, 148, 252, 125, 13, 67, 92, 47, + 199, 246, 228, 103, 75, 155, 239, 190, 14, 178, 39, 64, 20, 180, 253, 220, 0, 154, 140, 191, + 253, 253, 253, 107, 236, 152, 229, 125, 41, 65, 216, 212, 169, 93, 12, 24, 63, 212, 239, 73, + 102, 97, 242, 62, 170, 223, 120, 219, 127, 254, 174, 100, 196, 46, 111, 49, 236, 218, 179, 222, + 236, 201, 110, 107, 38, 186, 247, 36, 121, 98, 229, 63, 28, 60, 12, 211, 252, 252, 52, 189, + 123, 81, 70, 162, 201, 204, 3, 33, 95, 169, 148, 183, 224, 126, 164, 27, 30, 27, 232, 201, 92, + 148, 40, 138, 248, 19, 2, 92, 255, 169, 18, 226, 110, 218, 110, 37, 185, 2, 237, 72, 180, 162, + 190, 174, 242, 90, 238, 170, 217, 136, 7, 123, 35, 56, 205, 68, 13, 72, 28, 134, 210, 88, 61, + 195, 95, 248, 9, 8, 213, 101, 19, 197, 253, 145, 8, 67, 98, 210, 63, 119, 51, 99, 188, 177, + 103, 240, 236, 157, 218, 220, 218, 175, 217, 47, 227, 221, 47, 162, 9, 82, 222, 178, 228, 97, + 62, 149, 191, 124, 198, 95, 59, 54, 205, 239, 87, 39, 225, 172, 83, 215, 45, 243, 114, 79, 7, + 244, 60, 155, 71, 73, 94, 133, 77, 230, 116, 132, 20, 114, 237, 132, 249, 243, 19, 231, 209, + 238, 51, 151, 1, 69, 78, 135, 65, 178, 207, 33, 9, 54, 28, 192, 127, 44, 209, 164, 236, 180, + 35, 144, 214, 67, 236, 171, 120, 250, 242, 236, 242, 167, 137, 60, 229, 131, 245, 23, 34, 114, + 93, 49, 129, 10, 149, 0, 22, 118, 103, 15, 218, 22, 224, 33, 74, 161, 235, 213, 27, 85, 198, + 253, 87, 151, 248, 252, 243, 215, 54, 6, 227, 208, 168, 59, 203, 144, 167, 31, 215, 234, 125, + 83, 147, 83, 175, 108, 122, 222, 76, 183, 7, 115, 71, 209, 65, 201, 69, 50, 88, 96, 120, 128, + 141, 43, 128, 225, 180, 120, 65, 20, 9, 137, 2, 201, 177, 251, 93, 52, 44, 67, 77, 36, 191, 63, + 95, 222, 71, 171, 172, 232, 102, 167, 4, 218, 191, 5, 18, 117, 123, 238, 176, 85, 124, 155, + 172, 187, 120, 209, 91, 43, 130, 226, 79, 103, 232, 101, 249, 96, 225, 88, 29, 57, 22, 20, 98, + 8, 201, 197, 153, 252, 163, 11, 188, 27, 112, 164, 43, 138, 96, 101, 146, 102, 152, 152, 64, + 211, 167, 139, 42, 66, 189, 188, 117, 86, 44, 198, 186, 128, 82, 58, 62, 88, 205, 68, 86, 127, + 65, 180, 37, 117, 222, 191, 149, 26, 138, 122, 91, 10, 40, 35, 228, 255, 1, 228, 174, 72, 110, + 34, 235, 105, 71, 18, 100, 115, 3, 114, 185, 148, 27, 133, 97, 165, 91, 1, 192, 102, 70, 76, + 111, 49, 252, 24, 23, 224, 163, 90, 136, 0, 9, 23, 65, 96, 137, 196, 163, 38, 76, 193, 1, 229, + 209, 154, 84, 229, 82, 228, 144, 221, 3, 31, 150, 226, 1, 252, 94, 153, 160, 40, 38, 186, 141, + 80, 28, 114, 19, 134, 84, 184, 236, 28, 172, 248, 61, 208, 91, 187, 136, 99, 184, 64, 179, 134, + 75, 186, 206, 95, 95, 227, 179, 252, 156, 72, 50, 121, 55, 70, 133, 162, 173, 118, 214, 174, + 131, 237, 130, 141, 239, 50, 252, 248, 141, 174, 183, 164, 176, 142, 124, 109, 56, 164, 164, + 25, 50, 175, 242, 54, 160, 31, 108, 17, 228, 31, 211, 203, 73, 252, 148, 234, 240, 184, 14, + 155, 101, 45, 94, 31, 203, 236, 176, 127, 5, 249, 177, 119, 24, 79, 244, 24, 182, 106, 6, 184, + 205, 246, 31, 71, 33, 233, 47, 223, 33, 106, 252, 76, 192, 146, 143, 108, 49, 67, 208, 77, 87, + 122, 165, 151, 99, 231, 253, 231, 57, 12, 83, 67, 102, 28, 169, 198, 153, 115, 79, 77, 187, + 141, 161, 244, 149, 211, 215, 9, 64, 33, 205, 175, 182, 129, 159, 41, 194, 117, 123, 140, 178, + 17, 146, 210, 182, 105, 220, 82, 198, 13, 240, 183, 92, 175, 34, 73, 28, 208, 69, 203, 8, 174, + 109, 127, 254, 254, 142, 176, 232, 43, 80, 56, 220, 222, 143, 66, 137, 143, 1, 191, 152, 92, + 122, 231, 204, 99, 221, 217, 123, 57, 149, 27, 65, 4, 42, 209, 33, 77, 211, 156, 139, 198, 4, + 17, 91, 41, 173, 0, 51, 67, 210, 24, 212, 127, 50, 167, 129, 12, 95, 62, 125, 211, 99, 185, 31, + 243, 77, 210, 108, 142, 16, 2, 237, 163, 239, 239, 213, 101, 127, 242, 228, 4, 247, 32, 189, + 20, 10, 182, 64, 152, 166, 83, 202, 121, 83, 175, 137, 37, 202, 247, 85, 15, 198, 148, 130, 43, + 184, 106, 118, 198, 211, 171, 103, 176, 34, 61, 21, 103, 225, 83, 225, 16, 252, 169, 238, 142, + 185, 138, 212, 67, 193, 233, 104, 169, 25, 191, 134, 37, 233, 202, 106, 163, 58, 107, 82, 243, + 52, 70, 240, 246, 225, 10, 130, 76, 210, 164, 40, 125, 162, 35, 197, 68, 74, 17, 51, 223, 231, + 232, 67, 117, 252, 239, 57, 213, 36, 92, 34, 4, 232, 142, 118, 115, 108, 59, 184, 223, 133, 67, + 194, 121, 195, 135, 219, 143, 224, 170, 120, 29, 116, 195, 124, 155, 252, 204, 125, 42, 246, + 28, 104, 190, 101, 139, 144, 10, 172, 38, 226, 97, 77, 187, 153, 168, 208, 234, 104, 147, 49, + 123, 237, 232, 139, 167, 199, 250, 52, 188, 27, 181, 44, 90, 76, 222, 166, 26, 45, 142, 56, + 142, 251, 102, 57, 121, 165, 192, 189, 112, 76, 31, 117, 33, 89, 143, 217, 200, 13, 173, 191, + 156, 206, 179, 11, 100, 52, 109, 48, 16, 34, 193, 164, 150, 40, 8, 32, 155, 27, 254, 134, 145, + 203, 234, 129, 154, 69, 223, 252, 173, 146, 78, 23, 143, 8, 69, 232, 250, 248, 56, 127, 161, + 10, 80, 237, 75, 56, 73, 34, 90, 33, 110, 88, 215, 251, 151, 79, 185, 94, 122, 71, 155, 135, + 98, 139, 50, 7, 20, 37, 221, 165, 66, 120, 86, 30, 212, 71, 136, 233, 236, 230, 42, 100, 163, + 233, 26, 229, 63, 153, 86, 86, 181, 20, 108, 232, 98, 230, 120, 39, 132, 36, 189, 116, 90, 21, + 193, 252, 183, 31, 68, 65, 183, 176, 137, 9, 130, 35, 83, 114, 207, 74, 189, 119, 189, 165, 53, + 141, 240, 230, 177, 29, 131, 118, 136, 40, 85, 149, 202, 4, 215, 232, 73, 90, 63, 73, 143, 251, + 23, 52, 106, 198, 206, 155, 187, 102, 98, 217, 225, 192, 147, 103, 186, 0, 112, 192, 212, 182, + 157, 234, 157, 114, 2, 202, 183, 104, 129, 162, 34, 103, 21, 32, 0, 21, 5, 190, 75, 21, 81, + 157, 69, 207, 53, 239, 243, 110, 125, 69, 200, 117, 34, 44, 180, 85, 74, 196, 217, 118, 223, + 151, 122, 22, 84, 19, 15, 227, 0, 59, 177, 129, 200, 78, 221, 117, 19, 93, 239, 46, 187, 161, + 200, 238, 6, 141, 76, 231, 83, 12, 49, 137, 31, 104, 240, 65, 174, 94, 205, 166, 173, 188, 168, + 102, 85, 129, 194, 121, 127, 28, 197, 225, 60, 21, 181, 89, 7, 26, 221, 234, 165, 219, 165, + 147, 240, 115, 164, 123, 128, 103, 77, 154, 137, 12, 243, 101, 124, 62, 147, 199, 213, 67, 143, + 220, 7, 52, 182, 119, 164, 194, 150, 100, 82, 138, 88, 17, 40, 120, 198, 41, 12, 114, 239, 115, + 173, 128, 178, 246, 9, 55, 48, 28, 168, 60, 85, 13, 85, 91, 202, 23, 160, 86, 207, 208, 108, + 161, 194, 30, 73, 120, 94, 20, 198, 161, 218, 152, 212, 49, 116, 65, 84, 179, 232, 153, 168, + 155, 45, 119, 154, 205, 178, 40, 182, 8, 56, 64, 21, 3, 208, 178, 15, 238, 11, 147, 206, 182, + 175, 185, 191, 106, 177, 70, 161, 185, 13, 12, 230, 250, 162, 35, 87, 27, 80, 235, 155, 250, + 252, 255, 168, 5, 88, 189, 106, 97, 124, 4, 34, 163, 145, 38, 180, 62, 203, 18, 53, 42, 74, + 127, 48, 85, 215, 62, 235, 128, 94, 104, 144, 151, 64, 118, 118, 45, 215, 139, 216, 27, 23, + 255, 21, 231, 71, 15, 161, 105, 143, 60, 205, 80, 224, 100, 11, 35, 78, 78, 87, 66, 51, 116, + 237, 253, 137, 227, 226, 255, 9, 168, 243, 224, 124, 244, 235, 93, 121, 82, 239, 179, 41, 17, + 221, 221, 49, 160, 28, 132, 91, 6, 185, 94, 209, 143, 118, 146, 73, 87, 163, 98, 121, 99, 217, + 253, 201, 248, 86, 167, 247, 48, 226, 159, 235, 32, 19, 127, 75, 223, 185, 213, 207, 181, 29, + 144, 36, 118, 67, 132, 74, 75, 149, 92, 148, 238, 229, 107, 231, 9, 198, 54, 244, 15, 96, 134, + 34, 60, 11, 153, 53, 91, 187, 0, 171, 44, 25, 179, 180, 207, 19, 69, 233, 35, 251, 75, 164, 1, + 60, 70, 145, 88, 218, 123, 158, 99, 144, 211, 245, 4, 24, 252, 132, 10, 149, 220, 80, 31, 165, + 137, 38, 126, 37, 52, 0, 115, 128, 0, 61, 32, 77, 211, 28, 227, 1, 182, 122, 212, 185, 127, + 179, 146, 130, 8, 255, 45, 232, 115, 122, 248, 92, 255, 253, 225, 113, 216, 18, 4, 182, 77, + 229, 77, 236, 83, 80, 154, 13, 150, 195, 227, 1, 206, 24, 250, 192, 183, 215, 240, 86, 209, 86, + 203, 51, 236, 194, 230, 162, 58, 64, 0, 220, 174, 195, 173, 34, 104, 209, 200, 243, 28, 5, 26, + 8, 178, 32, 236, 148, 188, 98, 164, 91, 132, 153, 27, 14, 255, 245, 229, 166, 173, 128, 129, 2, + 161, 83, 41, 60, 32, 118, 37, 34, 78, 214, 240, 131, 36, 24, 85, 86, 180, 232, 229, 91, 200, + 27, 90, 239, 44, 6, 27, 135, 220, 132, 64, 52, 0, 4, 16, 5, 48, 18, 246, 194, 148, 141, 65, 64, + 196, 90, 83, 151, 62, 27, 130, 121, 40, 104, 128, 18, 123, 28, 137, 86, 250, 253, 121, 52, 131, + 174, 84, 56, 143, 28, 115, 68, 215, 228, 96, 100, 160, 93, 78, 89, 114, 133, 241, 82, 6, 131, + 167, 93, 12, 48, 143, 194, 78, 85, 213, 184, 179, 178, 70, 1, 179, 47, 201, 224, 148, 252, 149, + 83, 5, 168, 146, 21, 212, 250, 218, 185, 233, 191, 241, 255, 37, 198, 65, 139, 245, 167, 162, + 24, 10, 74, 175, 35, 186, 140, 149, 21, 154, 1, 226, 8, 36, 120, 88, 52, 165, 70, 53, 59, 95, + 5, 174, 47, 115, 165, 113, 133, 203, 128, 108, 157, 255, 217, 50, 137, 151, 79, 136, 89, 2, 22, + 80, 208, 45, 228, 223, 176, 102, 157, 203, 54, 53, 70, 97, 202, 138, 217, 224, 250, 148, 142, + 7, 91, 185, 102, 63, 153, 46, 120, 122, 197, 207, 66, 242, 56, 82, 31, 191, 4, 125, 176, 14, + 55, 15, 166, 166, 95, 17, 11, 160, 67, 53, 9, 44, 180, 166, 35, 120, 105, 171, 117, 187, 47, + 17, 22, 82, 112, 49, 227, 96, 113, 133, 31, 8, 10, 12, 97, 38, 27, 176, 73, 95, 220, 105, 232, + 240, 88, 234, 192, 12, 57, 209, 128, 223, 120, 203, 30, 140, 208, 185, 87, 36, 95, 120, 20, + 164, 16, 109, 207, 198, 157, 189, 168, 141, 127, 24, 21, 125, 32, 230, 27, 64, 122, 7, 158, 14, + 201, 233, 17, 53, 39, 129, 63, 56, 45, 122, 24, 251, 194, 204, 205, 159, 234, 247, 131, 145, + 73, 103, 21, 35, 158, 61, 195, 60, 0, 236, 122, 228, 245, 74, 69, 13, 40, 37, 146, 110, 3, 156, + 54, 24, 241, 170, 10, 79, 79, 157, 29, 27, 227, 191, 84, 101, 61, 172, 76, 175, 220, 34, 90, + 82, 39, 29, 29, 92, 174, 74, 161, 75, 143, 198, 83, 14, 181, 228, 173, 73, 38, 5, 145, 215, 19, + 87, 91, 67, 252, 49, 124, 3, 77, 190, 135, 85, 42, 195, 150, 134, 135, 154, 130, 134, 216, 157, + 122, 255, 50, 95, 33, 101, 210, 206, 204, 170, 137, 34, 72, 157, 72, 34, 69, 231, 155, 93, 111, + 27, 102, 183, 90, 131, 167, 137, 204, 146, 185, 166, 41, 241, 144, 38, 28, 32, 238, 7, 219, 0, + 132, 59, 169, 252, 60, 142, 179, 91, 71, 178, 128, 123, 227, 232, 229, 232, 186, 87, 137, 237, + 40, 92, 146, 191, 207, 210, 225, 234, 56, 118, 119, 213, 131, 185, 197, 218, 222, 242, 248, 34, + 62, 75, 135, 143, 150, 155, 212, 230, 27, 46, 143, 193, 210, 51, 127, 165, 202, 219, 254, 7, + 19, 69, 80, 155, 160, 201, 202, 235, 71, 130, 192, 200, 240, 247, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8, 12, 19, 28, 33, 39, 48, 54, 0, ]; From d1447abaab089898e0e9b0ddef69ec1bfac1d2b5 Mon Sep 17 00:00:00 2001 From: Jeff Andersen Date: Tue, 3 Dec 2024 16:31:38 -0800 Subject: [PATCH 34/51] Disable FPGA workflows in main-2.x (#1833) Can re-enable when the FPGA CI works again in that branch. --- .github/workflows/fpga.yml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.github/workflows/fpga.yml b/.github/workflows/fpga.yml index 092741cd25..b43eecdc04 100644 --- a/.github/workflows/fpga.yml +++ b/.github/workflows/fpga.yml @@ -4,7 +4,8 @@ name: FPGA Build on: push: branches: ["main"] - pull_request: + # Disabled in main-2.x until FPGA CI works again. + # pull_request: workflow_call: inputs: artifact-suffix: From 177fc32fabfc16c32ca6e1a65fbd2b82f07da0ce Mon Sep 17 00:00:00 2001 From: Jeff Andersen Date: Tue, 26 Nov 2024 13:46:41 -0800 Subject: [PATCH 35/51] Add a new crypto helper and move the module up a layer. The move will allow crypto helpers to be used from runtime-update flows. The new helper will be used in cases where borrowing RomEnv is not allowed. --- rom/dev/src/{flow/cold_reset => }/crypto.rs | 32 +++++++++++++++++---- rom/dev/src/flow/cold_reset/dice.rs | 2 +- rom/dev/src/flow/cold_reset/fmc_alias.rs | 5 ++-- rom/dev/src/flow/cold_reset/idev_id.rs | 4 +-- rom/dev/src/flow/cold_reset/ldev_id.rs | 2 +- rom/dev/src/flow/cold_reset/mod.rs | 1 - rom/dev/src/flow/cold_reset/x509.rs | 2 +- rom/dev/src/main.rs | 1 + 8 files changed, 35 insertions(+), 14 deletions(-) rename rom/dev/src/{flow/cold_reset => }/crypto.rs (91%) diff --git a/rom/dev/src/flow/cold_reset/crypto.rs b/rom/dev/src/crypto.rs similarity index 91% rename from rom/dev/src/flow/cold_reset/crypto.rs rename to rom/dev/src/crypto.rs index 7432bdbe8b..6bf2bfa9b6 100644 --- a/rom/dev/src/flow/cold_reset/crypto.rs +++ b/rom/dev/src/crypto.rs @@ -157,7 +157,8 @@ impl Crypto { /// * `mode` - HMAC Mode #[inline(always)] pub fn hmac_kdf( - env: &mut RomEnv, + hmac: &mut Hmac, + trng: &mut Trng, key: KeyId, label: &[u8], context: Option<&[u8]>, @@ -165,11 +166,11 @@ impl Crypto { mode: HmacMode, ) -> CaliptraResult<()> { hmac_kdf( - &mut env.hmac, + hmac, KeyReadArgs::new(key).into(), label, context, - &mut env.trng, + trng, KeyWriteArgs::new( output, KeyUsage::default() @@ -181,6 +182,27 @@ impl Crypto { ) } + /// Version of hmac_kdf() that takes a RomEnv. + #[inline(always)] + pub fn env_hmac_kdf( + env: &mut RomEnv, + key: KeyId, + label: &[u8], + context: Option<&[u8]>, + output: KeyId, + mode: HmacMode, + ) -> CaliptraResult<()> { + Crypto::hmac_kdf( + &mut env.hmac, + &mut env.trng, + key, + label, + context, + output, + mode, + ) + } + /// Generate ECC Key Pair /// /// # Arguments @@ -199,7 +221,7 @@ impl Crypto { label: &[u8], priv_key: KeyId, ) -> CaliptraResult { - Crypto::hmac_kdf(env, cdi, label, None, KEY_ID_TMP, HmacMode::Hmac512)?; + Crypto::env_hmac_kdf(env, cdi, label, None, KEY_ID_TMP, HmacMode::Hmac512)?; let key_out = Ecc384PrivKeyOut::Key(KeyWriteArgs::new( priv_key, @@ -271,7 +293,7 @@ impl Crypto { key_pair_seed: KeyId, ) -> CaliptraResult { // Generate the seed for key pair generation. - Crypto::hmac_kdf(env, cdi, label, None, key_pair_seed, HmacMode::Hmac512)?; + Crypto::env_hmac_kdf(env, cdi, label, None, key_pair_seed, HmacMode::Hmac512)?; // Generate the public key. let pub_key = env diff --git a/rom/dev/src/flow/cold_reset/dice.rs b/rom/dev/src/flow/cold_reset/dice.rs index 92b5a19c56..5edbfa1614 100644 --- a/rom/dev/src/flow/cold_reset/dice.rs +++ b/rom/dev/src/flow/cold_reset/dice.rs @@ -13,7 +13,7 @@ Abstract: --*/ -use super::crypto::{Ecc384KeyPair, MlDsaKeyPair}; +use crate::crypto::{Ecc384KeyPair, MlDsaKeyPair}; use zeroize::Zeroize; /// DICE Layer Input diff --git a/rom/dev/src/flow/cold_reset/fmc_alias.rs b/rom/dev/src/flow/cold_reset/fmc_alias.rs index 3ce68c231f..c77d0f6910 100644 --- a/rom/dev/src/flow/cold_reset/fmc_alias.rs +++ b/rom/dev/src/flow/cold_reset/fmc_alias.rs @@ -13,12 +13,11 @@ Abstract: --*/ -use super::crypto::{Crypto, Ecc384KeyPair}; use super::dice::{DiceInput, DiceOutput}; use super::fw_processor::FwProcInfo; use super::x509::X509; use crate::cprintln; -use crate::flow::cold_reset::crypto::{MlDsaKeyPair, PubKey}; +use crate::crypto::{Crypto, Ecc384KeyPair, MlDsaKeyPair, PubKey}; use crate::flow::cold_reset::{copy_tbs, TbsType}; use crate::print::HexBytes; use crate::rom_env::RomEnv; @@ -126,7 +125,7 @@ impl FmcAliasLayer { fn derive_cdi(env: &mut RomEnv, measurements: &Array4x12, cdi: KeyId) -> CaliptraResult<()> { let mut measurements: [u8; 48] = measurements.into(); - let result = Crypto::hmac_kdf( + let result = Crypto::env_hmac_kdf( env, cdi, b"alias_fmc_cdi", diff --git a/rom/dev/src/flow/cold_reset/idev_id.rs b/rom/dev/src/flow/cold_reset/idev_id.rs index e761df95bc..aa7f5afb18 100644 --- a/rom/dev/src/flow/cold_reset/idev_id.rs +++ b/rom/dev/src/flow/cold_reset/idev_id.rs @@ -13,10 +13,10 @@ Abstract: --*/ -use super::crypto::*; use super::dice::*; use super::x509::*; use crate::cprintln; +use crate::crypto::{Crypto, Ecc384KeyPair, Ecdsa384SignatureAdapter, MlDsaKeyPair, PubKey}; use crate::print::HexBytes; use crate::rom_env::RomEnv; #[cfg(not(feature = "no-cfi"))] @@ -180,7 +180,7 @@ impl InitDevIdLayer { /// * `cdi` - Key Slot to store the generated CDI #[cfg_attr(not(feature = "no-cfi"), cfi_impl_fn)] fn derive_cdi(env: &mut RomEnv, uds: KeyId, cdi: KeyId) -> CaliptraResult<()> { - Crypto::hmac_kdf(env, uds, b"idevid_cdi", None, cdi, HmacMode::Hmac512)?; + Crypto::env_hmac_kdf(env, uds, b"idevid_cdi", None, cdi, HmacMode::Hmac512)?; cprintln!("[idev] Erasing UDS.KEYID = {}", uds as u8); env.key_vault.erase_key(uds)?; diff --git a/rom/dev/src/flow/cold_reset/ldev_id.rs b/rom/dev/src/flow/cold_reset/ldev_id.rs index 5b7386dd1b..898ce72c80 100644 --- a/rom/dev/src/flow/cold_reset/ldev_id.rs +++ b/rom/dev/src/flow/cold_reset/ldev_id.rs @@ -13,10 +13,10 @@ Abstract: --*/ -use super::crypto::*; use super::dice::*; use super::x509::*; use crate::cprintln; +use crate::crypto::{Crypto, Ecc384KeyPair, MlDsaKeyPair, PubKey}; use crate::flow::cold_reset::{copy_tbs, TbsType}; use crate::print::HexBytes; use crate::rom_env::RomEnv; diff --git a/rom/dev/src/flow/cold_reset/mod.rs b/rom/dev/src/flow/cold_reset/mod.rs index 0b07a8d003..54cbf908dd 100644 --- a/rom/dev/src/flow/cold_reset/mod.rs +++ b/rom/dev/src/flow/cold_reset/mod.rs @@ -12,7 +12,6 @@ Abstract: --*/ -mod crypto; mod dice; mod fmc_alias; mod fw_processor; diff --git a/rom/dev/src/flow/cold_reset/x509.rs b/rom/dev/src/flow/cold_reset/x509.rs index c48a63429b..6ff1dc68aa 100644 --- a/rom/dev/src/flow/cold_reset/x509.rs +++ b/rom/dev/src/flow/cold_reset/x509.rs @@ -11,8 +11,8 @@ Abstract: File contains X509 Certificate & CSR related utility functions --*/ -use super::crypto::{Crypto, PubKey}; use crate::cprintln; +use crate::crypto::{Crypto, PubKey}; use crate::rom_env::RomEnv; use caliptra_drivers::*; use core::mem::size_of; diff --git a/rom/dev/src/main.rs b/rom/dev/src/main.rs index e8464de91d..f27bb8ff96 100644 --- a/rom/dev/src/main.rs +++ b/rom/dev/src/main.rs @@ -41,6 +41,7 @@ core::arch::global_asm!(include_str!(concat!( "/start_preprocessed.S" ))); +mod crypto; mod exception; mod fht; mod flow; From 6dc66ed04de888850acd6e500bbf0e657880cb84 Mon Sep 17 00:00:00 2001 From: Jeff Andersen Date: Tue, 26 Nov 2024 15:05:54 -0800 Subject: [PATCH 36/51] Change runtime's HMAC helper from a simple HMAC to a KDF. In order to use the resulting key in FIPS, each operation will need to be an approved KDF. --- runtime/src/hmac.rs | 29 +++++++++++++++++++---------- 1 file changed, 19 insertions(+), 10 deletions(-) diff --git a/runtime/src/hmac.rs b/runtime/src/hmac.rs index a0a56aa9a7..cffc7666ff 100644 --- a/runtime/src/hmac.rs +++ b/runtime/src/hmac.rs @@ -82,20 +82,29 @@ fn ecc384_key_gen( pub enum Hmac {} impl Hmac { - /// "Hash" the data in the provided KV slot by HMACing it with an empty slice. - /// This mechanism is necessary because the hardware does not directly support - /// hashing data in KV slots. + /// Calculate HMAC-384 KDF /// /// # Arguments /// /// * `drivers` - Drivers - /// * `input` - KeyId containing the input data - /// * `output` - KeyId which the output hash should be written to + /// * `key` - HMAC384 key slot + /// * `label` - Input label + /// * `context` - Input context + /// * `output` - Key slot to store the output #[cfg_attr(not(feature = "no-cfi"), cfi_impl_fn)] - pub fn hmac384_hash(drivers: &mut Drivers, input: KeyId, output: KeyId) -> CaliptraResult<()> { - drivers.hmac.hmac( - &KeyReadArgs::new(input).into(), - &HmacData::Slice(&[]), + pub fn hmac_kdf( + drivers: &mut Drivers, + key: KeyId, + label: &[u8], + context: Option<&[u8]>, + mode: HmacMode, + output: KeyId, + ) -> CaliptraResult<()> { + hmac_kdf( + &mut drivers.hmac, + KeyReadArgs::new(key).into(), + label, + context, &mut drivers.trng, KeyWriteArgs::new( output, @@ -104,7 +113,7 @@ impl Hmac { .set_ecc_key_gen_seed_en(), ) .into(), - HmacMode::Hmac384, + mode, ) } From cabaa7dcfd7acc6da397ddd1d8e3fbe1cef7e309 Mon Sep 17 00:00:00 2001 From: Jeff Andersen Date: Tue, 26 Nov 2024 14:54:53 -0800 Subject: [PATCH 37/51] Move common helper code into the test helper library. --- Cargo.lock | 1 + .../rom_integration_tests/test_warm_reset.rs | 17 ++-------- runtime/Cargo.toml | 1 + .../test_warm_reset.rs | 31 +++---------------- test/src/lib.rs | 20 ++++++++++++ .../fake_collateral_boot_test.rs | 15 ++------- .../caliptra_integration_tests/jtag_test.rs | 20 +++--------- .../caliptra_integration_tests/smoke_test.rs | 11 ++----- .../caliptra_integration_tests/warm_reset.rs | 26 +++------------- test/tests/fips_test_suite/common.rs | 7 ----- test/tests/fips_test_suite/fw_load.rs | 23 +++----------- 11 files changed, 48 insertions(+), 124 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 8711351e01..de5a4aade4 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -819,6 +819,7 @@ dependencies = [ "caliptra-kat", "caliptra-lms-types", "caliptra-registers", + "caliptra-test", "caliptra-x509", "caliptra_common", "cfg-if 1.0.0", diff --git a/rom/dev/tests/rom_integration_tests/test_warm_reset.rs b/rom/dev/tests/rom_integration_tests/test_warm_reset.rs index 2ddaeb1806..ecce2a6260 100644 --- a/rom/dev/tests/rom_integration_tests/test_warm_reset.rs +++ b/rom/dev/tests/rom_integration_tests/test_warm_reset.rs @@ -9,18 +9,10 @@ use caliptra_common::RomBootStatus::*; use caliptra_drivers::CaliptraError; use caliptra_hw_model::DeviceLifecycle; use caliptra_hw_model::{BootParams, Fuses, HwModel, InitParams, SecurityState}; -use caliptra_test::swap_word_bytes_inplace; -use openssl::sha::sha384; -use zerocopy::AsBytes; +use caliptra_test::image_pk_desc_hash; use crate::helpers; -fn bytes_to_be_words_48(buf: &[u8; 48]) -> [u32; 12] { - let mut result: [u32; 12] = zerocopy::transmute!(*buf); - swap_word_bytes_inplace(&mut result); - result -} - #[test] fn test_warm_reset_success() { let security_state = *SecurityState::default() @@ -38,13 +30,8 @@ fn test_warm_reset_success() { }, ) .unwrap(); - let vendor_pk_desc_hash = bytes_to_be_words_48(&sha384( - image.manifest.preamble.vendor_pub_key_info.as_bytes(), - )); - let owner_pk_desc_hash = bytes_to_be_words_48(&sha384( - image.manifest.preamble.owner_pub_key_info.as_bytes(), - )); + let (vendor_pk_desc_hash, owner_pk_desc_hash) = image_pk_desc_hash(&image.manifest); let mut hw = caliptra_hw_model::new( InitParams { diff --git a/runtime/Cargo.toml b/runtime/Cargo.toml index 4cd392abb0..74eb20feba 100644 --- a/runtime/Cargo.toml +++ b/runtime/Cargo.toml @@ -45,6 +45,7 @@ caliptra-image-gen.workspace = true caliptra-image-crypto.workspace = true caliptra-auth-man-gen.workspace = true caliptra-image-serde.workspace = true +caliptra-test.workspace = true caliptra-cfi-lib-git = { workspace = true, features = ["cfi-test"] } openssl.workspace = true sha2 = { version = "0.10.2", default-features = false, features = ["compress"] } diff --git a/runtime/tests/runtime_integration_tests/test_warm_reset.rs b/runtime/tests/runtime_integration_tests/test_warm_reset.rs index ad8a998086..3652c2e643 100644 --- a/runtime/tests/runtime_integration_tests/test_warm_reset.rs +++ b/runtime/tests/runtime_integration_tests/test_warm_reset.rs @@ -8,21 +8,8 @@ use caliptra_builder::{ use caliptra_error::CaliptraError; use caliptra_hw_model::{BootParams, DeviceLifecycle, Fuses, HwModel, InitParams, SecurityState}; use caliptra_registers::mbox::enums::MboxStatusE; +use caliptra_test::image_pk_desc_hash; use dpe::DPE_PROFILE; -use openssl::sha::sha384; -use zerocopy::AsBytes; - -fn swap_word_bytes_inplace(words: &mut [u32]) { - for word in words.iter_mut() { - *word = word.swap_bytes() - } -} - -fn bytes_to_be_words_48(buf: &[u8; 48]) -> [u32; 12] { - let mut result: [u32; 12] = zerocopy::transmute!(*buf); - swap_word_bytes_inplace(&mut result); - result -} #[test] fn test_rt_journey_pcr_validation() { @@ -40,12 +27,8 @@ fn test_rt_journey_pcr_validation() { }, ) .unwrap(); - let vendor_pk_desc_hash = bytes_to_be_words_48(&sha384( - image.manifest.preamble.vendor_pub_key_info.as_bytes(), - )); - let owner_pk_desc_hash = bytes_to_be_words_48(&sha384( - image.manifest.preamble.owner_pub_key_info.as_bytes(), - )); + + let (vendor_pk_desc_hash, owner_pk_desc_hash) = image_pk_desc_hash(&image.manifest); let mut model = caliptra_hw_model::new( InitParams { @@ -107,12 +90,8 @@ fn test_mbox_busy_during_warm_reset() { }, ) .unwrap(); - let vendor_pk_desc_hash = bytes_to_be_words_48(&sha384( - image.manifest.preamble.vendor_pub_key_info.as_bytes(), - )); - let owner_pk_desc_hash = bytes_to_be_words_48(&sha384( - image.manifest.preamble.owner_pub_key_info.as_bytes(), - )); + + let (vendor_pk_desc_hash, owner_pk_desc_hash) = image_pk_desc_hash(&image.manifest); let mut model = caliptra_hw_model::new( InitParams { diff --git a/test/src/lib.rs b/test/src/lib.rs index 297ca24f42..5d3186a374 100644 --- a/test/src/lib.rs +++ b/test/src/lib.rs @@ -6,6 +6,7 @@ use caliptra_builder::{ FwId, ImageOptions, }; use caliptra_hw_model::{BootParams, DefaultHwModel, HwModel, InitParams}; +use zerocopy::AsBytes; pub mod crypto; pub mod derive; @@ -13,6 +14,8 @@ mod redact; mod unwrap_single; pub mod x509; +use caliptra_image_types::ImageManifest; +use openssl::sha::sha384; pub use redact::{redact_cert, RedactOpts}; pub use unwrap_single::UnwrapSingle; @@ -28,6 +31,23 @@ pub fn swap_word_bytes_inplace(words: &mut [u32]) { } } +pub fn bytes_to_be_words_48(buf: &[u8; 48]) -> [u32; 12] { + let mut result: [u32; 12] = zerocopy::transmute!(*buf); + swap_word_bytes_inplace(&mut result); + result +} + +// Returns the vendor and owner public key descriptor hashes from the image. +pub fn image_pk_desc_hash(manifest: &ImageManifest) -> ([u32; 12], [u32; 12]) { + let vendor_pk_desc_hash = + bytes_to_be_words_48(&sha384(manifest.preamble.vendor_pub_key_info.as_bytes())); + + let owner_pk_desc_hash = + bytes_to_be_words_48(&sha384(manifest.preamble.owner_pub_key_info.as_bytes())); + + (vendor_pk_desc_hash, owner_pk_desc_hash) +} + // Run a test which boots ROM -> FMC -> test_bin. If test_bin_name is None, // run the production runtime image. pub fn run_test( diff --git a/test/tests/caliptra_integration_tests/fake_collateral_boot_test.rs b/test/tests/caliptra_integration_tests/fake_collateral_boot_test.rs index 811583c884..e6a4f32ef2 100755 --- a/test/tests/caliptra_integration_tests/fake_collateral_boot_test.rs +++ b/test/tests/caliptra_integration_tests/fake_collateral_boot_test.rs @@ -13,7 +13,7 @@ use caliptra_common::mailbox_api::{ use caliptra_hw_model::{BootParams, HwModel, InitParams}; use caliptra_test::{ derive::{DoeInput, DoeOutput, LDevId}, - swap_word_bytes, swap_word_bytes_inplace, + image_pk_desc_hash, swap_word_bytes, x509::{DiceFwid, DiceTcbInfo}, }; use openssl::sha::sha384; @@ -42,12 +42,6 @@ fn get_idevid_pubkey() -> openssl::pkey::PKey { csr.public_key().unwrap() } -fn bytes_to_be_words_48(buf: &[u8; 48]) -> [u32; 12] { - let mut result: [u32; 12] = zerocopy::transmute!(*buf); - swap_word_bytes_inplace(&mut result); - result -} - // [CAP2][TODO] This test is disabled because it needs to be updated. //#[test] fn fake_boot_test() { @@ -64,13 +58,8 @@ fn fake_boot_test() { }, ) .unwrap(); - let vendor_pk_desc_hash = bytes_to_be_words_48(&sha384( - image.manifest.preamble.vendor_pub_key_info.as_bytes(), - )); - let owner_pk_desc_hash = bytes_to_be_words_48(&sha384( - image.manifest.preamble.owner_pub_key_info.as_bytes(), - )); + let (vendor_pk_desc_hash, owner_pk_desc_hash) = image_pk_desc_hash(&image.manifest); let mut hw = caliptra_hw_model::new( InitParams { diff --git a/test/tests/caliptra_integration_tests/jtag_test.rs b/test/tests/caliptra_integration_tests/jtag_test.rs index e3615b85d6..34739103fc 100644 --- a/test/tests/caliptra_integration_tests/jtag_test.rs +++ b/test/tests/caliptra_integration_tests/jtag_test.rs @@ -4,17 +4,9 @@ use caliptra_builder::{firmware, get_elf_path, ImageOptions}; use caliptra_api_types::DeviceLifecycle; use caliptra_hw_model::{BootParams, Fuses, HwModel, InitParams, SecurityState}; -use caliptra_test::swap_word_bytes_inplace; -use openssl::sha::sha384; +use caliptra_test::image_pk_desc_hash; use std::io::{BufRead, BufReader, Write}; use std::process::{ChildStdin, Command, Stdio}; -use zerocopy::AsBytes; - -fn bytes_to_be_words_48(buf: &[u8; 48]) -> [u32; 12] { - let mut result: [u32; 12] = zerocopy::transmute!(*buf); - swap_word_bytes_inplace(&mut result); - result -} #[derive(PartialEq, Debug)] enum RegAccess { @@ -95,14 +87,12 @@ fn gdb_test() { }, ) .unwrap(); - let vendor_pk_desc_hash = sha384(image.manifest.preamble.vendor_pub_key_info.as_bytes()); - let owner_pk_desc_hash = sha384(image.manifest.preamble.owner_pub_key_info.as_bytes()); - let vendor_pk_desc_hash_words = bytes_to_be_words_48(&vendor_pk_desc_hash); - let owner_pk_desc_hash_words = bytes_to_be_words_48(&owner_pk_desc_hash); + + let (vendor_pk_desc_hash, owner_pk_desc_hash) = image_pk_desc_hash(&image.manifest); let fuses = Fuses { - key_manifest_pk_hash: vendor_pk_desc_hash_words, - owner_pk_hash: owner_pk_desc_hash_words, + key_manifest_pk_hash: vendor_pk_desc_hash, + owner_pk_hash: owner_pk_desc_hash, fmc_key_manifest_svn: 0b1111111, lms_verify: true, ..Default::default() diff --git a/test/tests/caliptra_integration_tests/smoke_test.rs b/test/tests/caliptra_integration_tests/smoke_test.rs index c7b710b2f5..b8422efd5f 100644 --- a/test/tests/caliptra_integration_tests/smoke_test.rs +++ b/test/tests/caliptra_integration_tests/smoke_test.rs @@ -11,12 +11,13 @@ use caliptra_drivers::CaliptraError; use caliptra_hw_model::{BootParams, HwModel, InitParams, SecurityState}; use caliptra_hw_model_types::{RandomEtrngResponses, RandomNibbles}; use caliptra_test::derive::{PcrRtCurrentInput, RtAliasKey}; -use caliptra_test::{derive, redact_cert, run_test, RedactOpts, UnwrapSingle}; use caliptra_test::{ + bytes_to_be_words_48, derive::{DoeInput, DoeOutput, FmcAliasKey, IDevId, LDevId, Pcr0, Pcr0Input}, - swap_word_bytes, swap_word_bytes_inplace, + swap_word_bytes, x509::{DiceFwid, DiceTcbInfo}, }; +use caliptra_test::{derive, redact_cert, run_test, RedactOpts, UnwrapSingle}; use openssl::nid::Nid; use openssl::sha::{sha384, Sha384}; use rand::rngs::StdRng; @@ -134,12 +135,6 @@ fn test_golden_ldevid_pubkey_matches_generated() { .public_eq(&ldevid_pubkey)); } -fn bytes_to_be_words_48(buf: &[u8; 48]) -> [u32; 12] { - let mut result: [u32; 12] = zerocopy::transmute!(*buf); - swap_word_bytes_inplace(&mut result); - result -} - #[test] fn smoke_test() { let security_state = *SecurityState::default() diff --git a/test/tests/caliptra_integration_tests/warm_reset.rs b/test/tests/caliptra_integration_tests/warm_reset.rs index eb6d6a8110..49699f4b15 100644 --- a/test/tests/caliptra_integration_tests/warm_reset.rs +++ b/test/tests/caliptra_integration_tests/warm_reset.rs @@ -8,15 +8,7 @@ use caliptra_builder::{ }; use caliptra_common::mailbox_api::CommandId; use caliptra_hw_model::{mbox_write_fifo, BootParams, HwModel, InitParams, SecurityState}; -use caliptra_test::swap_word_bytes_inplace; -use openssl::sha::sha384; -use zerocopy::AsBytes; - -fn bytes_to_be_words_48(buf: &[u8; 48]) -> [u32; 12] { - let mut result: [u32; 12] = zerocopy::transmute!(*buf); - swap_word_bytes_inplace(&mut result); - result -} +use caliptra_test::image_pk_desc_hash; #[test] fn warm_reset_basic() { @@ -35,12 +27,8 @@ fn warm_reset_basic() { }, ) .unwrap(); - let vendor_pk_desc_hash = bytes_to_be_words_48(&sha384( - image.manifest.preamble.vendor_pub_key_info.as_bytes(), - )); - let owner_pk_desc_hash = bytes_to_be_words_48(&sha384( - image.manifest.preamble.owner_pub_key_info.as_bytes(), - )); + + let (vendor_pk_desc_hash, owner_pk_desc_hash) = image_pk_desc_hash(&image.manifest); let mut hw = caliptra_hw_model::new( InitParams { @@ -99,12 +87,8 @@ fn warm_reset_during_fw_load() { }, ) .unwrap(); - let vendor_pk_desc_hash = bytes_to_be_words_48(&sha384( - image.manifest.preamble.vendor_pub_key_info.as_bytes(), - )); - let owner_pk_desc_hash = bytes_to_be_words_48(&sha384( - image.manifest.preamble.owner_pub_key_info.as_bytes(), - )); + + let (vendor_pk_desc_hash, owner_pk_desc_hash) = image_pk_desc_hash(&image.manifest); let mut hw = caliptra_hw_model::new( InitParams { diff --git a/test/tests/fips_test_suite/common.rs b/test/tests/fips_test_suite/common.rs index 5fb21e790a..e96fa409a5 100755 --- a/test/tests/fips_test_suite/common.rs +++ b/test/tests/fips_test_suite/common.rs @@ -6,7 +6,6 @@ use caliptra_builder::{version, ImageOptions}; use caliptra_common::mailbox_api::*; use caliptra_drivers::FipsTestHook; use caliptra_hw_model::{BootParams, DefaultHwModel, HwModel, InitParams, ModelError, ShaAccMode}; -use caliptra_test::swap_word_bytes_inplace; use dpe::{ commands::*, response::{ @@ -423,12 +422,6 @@ pub fn verify_output_inhibited(hw: &mut T) { verify_sha_engine_output_inhibited(hw); } -pub fn bytes_to_be_words_48(buf: &[u8; 48]) -> [u32; 12] { - let mut result: [u32; 12] = zerocopy::transmute!(*buf); - swap_word_bytes_inplace(&mut result); - result -} - pub fn hook_code_read(hw: &mut T) -> u8 { ((hw.soc_ifc().cptra_dbg_manuf_service_reg().read() & HOOK_CODE_MASK) >> HOOK_CODE_OFFSET) as u8 } diff --git a/test/tests/fips_test_suite/fw_load.rs b/test/tests/fips_test_suite/fw_load.rs index 3821bb7c24..efd441995d 100755 --- a/test/tests/fips_test_suite/fw_load.rs +++ b/test/tests/fips_test_suite/fw_load.rs @@ -19,7 +19,7 @@ use caliptra_image_types::SHA384_DIGEST_WORD_SIZE; use caliptra_image_types::{ FwImageType, ImageBundle, VENDOR_ECC_MAX_KEY_COUNT, VENDOR_LMS_MAX_KEY_COUNT, }; -use openssl::sha::sha384; +use caliptra_test::image_pk_desc_hash; use common::*; use zerocopy::AsBytes; @@ -1195,27 +1195,12 @@ fn fw_load_bad_pub_key_flow(fw_image: ImageBundle, exp_error_code: u32) { // Generate pub key hashes and set fuses // Use a fresh image (will NOT be loaded) let pk_hash_src_image = build_fw_image(ImageOptions::default()); - let vendor_pk_desc_hash = sha384( - pk_hash_src_image - .manifest - .preamble - .vendor_pub_key_info - .as_bytes(), - ); - let owner_pk_desc_hash = sha384( - pk_hash_src_image - .manifest - .preamble - .owner_pub_key_info - .as_bytes(), - ); - let vendor_pk_desc_hash_words = bytes_to_be_words_48(&vendor_pk_desc_hash); - let owner_pk_desc_hash_words = bytes_to_be_words_48(&owner_pk_desc_hash); + let (vendor_pk_desc_hash, owner_pk_desc_hash) = image_pk_desc_hash(&pk_hash_src_image.manifest); let fuses = Fuses { life_cycle: DeviceLifecycle::Production, - key_manifest_pk_hash: vendor_pk_desc_hash_words, - owner_pk_hash: owner_pk_desc_hash_words, + key_manifest_pk_hash: vendor_pk_desc_hash, + owner_pk_hash: owner_pk_desc_hash, lms_verify: true, ..Default::default() }; From fde2b8a7b3c4024d4956e776ff3a82027afb4cb3 Mon Sep 17 00:00:00 2001 From: Vishal Mhatre <38512878+mhatrevi@users.noreply.github.com> Date: Wed, 4 Dec 2024 09:00:25 -0800 Subject: [PATCH 38/51] [feat] Update SHA2 driver to support SHA2-512 digests (#1826) --- common/src/error_handler.rs | 4 +- common/src/verifier.rs | 4 +- drivers/src/lib.rs | 4 +- drivers/src/pcr_bank.rs | 11 +- drivers/src/{sha384.rs => sha2_512_384.rs} | 197 ++++++++++++-------- drivers/test-fw/src/bin/sha384_tests.rs | 64 +++---- error/src/lib.rs | 2 +- fmc/src/flow/crypto.rs | 2 +- fmc/src/flow/pcr.rs | 4 +- fmc/src/fmc_env.rs | 8 +- hw-model/test-fw/test_pcr_extend.rs | 8 +- kat/src/kats_env.rs | 6 +- kat/src/lib.rs | 2 +- kat/src/sha384_kat.rs | 10 +- rom/dev/src/crypto.rs | 18 +- rom/dev/src/flow/cold_reset/fmc_alias.rs | 2 +- rom/dev/src/flow/cold_reset/fw_processor.rs | 23 ++- rom/dev/src/flow/fake.rs | 6 +- rom/dev/src/flow/update_reset.rs | 4 +- rom/dev/src/main.rs | 10 +- rom/dev/src/pcr.rs | 10 +- rom/dev/src/rom_env.rs | 8 +- runtime/src/authorize_and_stash.rs | 2 +- runtime/src/certify_key_extended.rs | 2 +- runtime/src/dpe_crypto.rs | 16 +- runtime/src/drivers.rs | 14 +- runtime/src/fips.rs | 10 +- runtime/src/hmac.rs | 4 +- runtime/src/invoke_dpe.rs | 2 +- runtime/src/pcr.rs | 4 +- runtime/src/set_auth_manifest.rs | 32 ++-- runtime/src/stash_measurement.rs | 4 +- runtime/test-fw/src/mbox_responder.rs | 4 +- 33 files changed, 289 insertions(+), 212 deletions(-) rename drivers/src/{sha384.rs => sha2_512_384.rs} (71%) diff --git a/common/src/error_handler.rs b/common/src/error_handler.rs index 77a3f250a4..f8662bfcfa 100644 --- a/common/src/error_handler.rs +++ b/common/src/error_handler.rs @@ -1,7 +1,7 @@ // Licensed under the Apache-2.0 license use caliptra_drivers::{ cprintln, report_fw_error_fatal, report_fw_error_non_fatal, Ecc384, Hmac, KeyVault, Mailbox, - Sha256, Sha2_512_384Acc, Sha384, SocIfc, + Sha256, Sha2_512_384, Sha2_512_384Acc, SocIfc, }; #[allow(clippy::empty_loop)] @@ -19,7 +19,7 @@ pub fn handle_fatal_error(code: u32) -> ! { Ecc384::zeroize(); Hmac::zeroize(); Sha256::zeroize(); - Sha384::zeroize(); + Sha2_512_384::zeroize(); Sha2_512_384Acc::zeroize(); // Zeroize the key vault. diff --git a/common/src/verifier.rs b/common/src/verifier.rs index ae558cff94..62d8a47205 100644 --- a/common/src/verifier.rs +++ b/common/src/verifier.rs @@ -22,7 +22,7 @@ use caliptra_drivers::memory_layout::ICCM_RANGE; /// ROM Verification Environemnt pub struct FirmwareImageVerificationEnv<'a, 'b> { pub sha256: &'a mut Sha256, - pub sha384: &'a mut Sha384, + pub sha2_512_384: &'a mut Sha2_512_384, pub soc_ifc: &'a mut SocIfc, pub ecc384: &'a mut Ecc384, pub data_vault: &'a mut DataVault, @@ -40,7 +40,7 @@ impl<'a, 'b> ImageVerificationEnv for &mut FirmwareImageVerificationEnv<'a, 'b> .ok_or(err)? .get(..len as usize) .ok_or(err)?; - Ok(self.sha384.digest(data)?.0) + Ok(self.sha2_512_384.sha384_digest(data)?.0) } /// ECC-384 Verification routine diff --git a/drivers/src/lib.rs b/drivers/src/lib.rs index 31a54c33e1..f83ca623ab 100644 --- a/drivers/src/lib.rs +++ b/drivers/src/lib.rs @@ -48,8 +48,8 @@ pub mod pic; pub mod printer; mod sha1; mod sha256; +mod sha2_512_384; mod sha2_512_384acc; -mod sha384; mod soc_ifc; mod trng; mod trng_ext; @@ -102,8 +102,8 @@ pub use persistent::{ pub use pic::{IntSource, Pic}; pub use sha1::{Sha1, Sha1Digest, Sha1DigestOp}; pub use sha256::{Sha256, Sha256Alg, Sha256DigestOp}; +pub use sha2_512_384::{Sha2DigestOp, Sha2_512_384, Sha384Digest}; pub use sha2_512_384acc::{Sha2_512_384Acc, Sha2_512_384AccOp, ShaAccLockState}; -pub use sha384::{Sha384, Sha384Digest, Sha384DigestOp}; pub use soc_ifc::{report_boot_status, Lifecycle, MfgFlags, ResetReason, SocIfc}; pub use trng::Trng; diff --git a/drivers/src/pcr_bank.rs b/drivers/src/pcr_bank.rs index e77b692556..d5f7eeea45 100644 --- a/drivers/src/pcr_bank.rs +++ b/drivers/src/pcr_bank.rs @@ -12,7 +12,7 @@ Abstract: --*/ -use crate::{Array4x12, CaliptraError, CaliptraResult, Sha384}; +use crate::{Array4x12, CaliptraError, CaliptraResult, Sha2_512_384}; use caliptra_registers::pv::PvReg; /// PCR Identifier @@ -263,7 +263,12 @@ impl PcrBank { /// * `sha` - SHA2-384 Engine /// * `data` - Data to extend /// - pub fn extend_pcr(&self, id: PcrId, sha: &mut Sha384, data: &[u8]) -> CaliptraResult<()> { - sha.pcr_extend(id, data) + pub fn extend_pcr( + &self, + id: PcrId, + sha2: &mut Sha2_512_384, + data: &[u8], + ) -> CaliptraResult<()> { + sha2.pcr_extend(id, data) } } diff --git a/drivers/src/sha384.rs b/drivers/src/sha2_512_384.rs similarity index 71% rename from drivers/src/sha384.rs rename to drivers/src/sha2_512_384.rs index 15dc33668b..8e62763b90 100644 --- a/drivers/src/sha384.rs +++ b/drivers/src/sha2_512_384.rs @@ -4,11 +4,11 @@ Licensed under the Apache-2.0 license. File Name: - sha384.rs + sha2_512_384.rs Abstract: - File contains API for SHA-384 Cryptography operations + File contains API for SHA2-512/384 Cryptography operations --*/ @@ -16,25 +16,41 @@ use core::usize; use crate::kv_access::{KvAccess, KvAccessErr}; use crate::PcrId; -use crate::{array::Array4x32, wait, Array4x12, Array4x8}; +use crate::{array::Array4x32, wait, Array4x12, Array4x16, Array4x8}; #[cfg(not(feature = "no-cfi"))] use caliptra_cfi_derive::cfi_impl_fn; use caliptra_error::{CaliptraError, CaliptraResult}; use caliptra_registers::sha512::Sha512Reg; -const SHA384_BLOCK_BYTE_SIZE: usize = 128; -const SHA384_BLOCK_LEN_OFFSET: usize = 112; -const SHA384_MAX_DATA_SIZE: usize = 1024 * 1024; +// Block size, block length offset and max data size are same for both SHA2-384 and SHA2-512. +const SHA512_BLOCK_BYTE_SIZE: usize = 128; +const SHA512_BLOCK_LEN_OFFSET: usize = 112; +const SHA512_MAX_DATA_SIZE: usize = 1024 * 1024; const SHA384_HASH_SIZE: usize = 48; +#[derive(Copy, Clone)] +pub enum ShaMode { + Sha384, + Sha512, +} + +impl ShaMode { + fn reg_value(&self) -> u32 { + match self { + Self::Sha384 => 0b10, + Self::Sha512 => 0b11, + } + } +} + /// SHA-384 Digest pub type Sha384Digest<'a> = &'a mut Array4x12; -pub struct Sha384 { +pub struct Sha2_512_384 { sha512: Sha512Reg, } -impl Sha384 { +impl Sha2_512_384 { pub fn new(sha512: Sha512Reg) -> Self { Self { sha512 } } @@ -42,12 +58,12 @@ impl Sha384 { /// /// # Returns /// - /// * `Sha384Digest` - Object representing the digest operation - pub fn digest_init(&mut self) -> CaliptraResult> { - let op = Sha384DigestOp { + /// * `Sha2DigestOp` - Object representing the digest operation + pub fn sha384_digest_init(&mut self) -> CaliptraResult> { + let op = Sha2DigestOp { sha: self, - state: Sha384DigestState::Init, - buf: [0u8; SHA384_BLOCK_BYTE_SIZE], + state: Sha2DigestState::Init, + buf: [0u8; SHA512_BLOCK_BYTE_SIZE], buf_idx: 0, data_size: 0, }; @@ -55,21 +71,14 @@ impl Sha384 { Ok(op) } - /// Calculate the digest for specified data - /// - /// # Arguments - /// - /// * `data` - Data to used to update the digest - /// - #[cfg_attr(not(feature = "no-cfi"), cfi_impl_fn)] - pub fn digest(&mut self, buf: &[u8]) -> CaliptraResult { + fn sha_digest_helper(&mut self, buf: &[u8], mode: ShaMode) -> CaliptraResult<()> { #[cfg(feature = "fips-test-hooks")] unsafe { crate::FipsTestHook::error_if_hook_set(crate::FipsTestHook::SHA384_DIGEST_FAILURE)? } // Check if the buffer is not large - if buf.len() > SHA384_MAX_DATA_SIZE { + if buf.len() > SHA512_MAX_DATA_SIZE { return Err(CaliptraError::DRIVER_SHA384_MAX_DATA_ERR); } @@ -84,28 +93,67 @@ impl Sha384 { // cannot reason about `offset` parameter to optimize out // the panic. if let Some(slice) = buf.get(offset..) { - self.digest_partial_block(slice, first, buf.len())?; + self.digest_partial_block(mode, slice, first, buf.len())?; break; } else { - return Err(CaliptraError::DRIVER_SHA384_INVALID_SLICE); + return Err(CaliptraError::DRIVER_SHA2_INVALID_SLICE); } } _ => { // PANIC-FREE: Use buf.get() instead if buf[] as the compiler // cannot reason about `offset` parameter to optimize out // the panic call. - if let Some(slice) = buf.get(offset..offset + SHA384_BLOCK_BYTE_SIZE) { - let block = <&[u8; SHA384_BLOCK_BYTE_SIZE]>::try_from(slice).unwrap(); - self.digest_block(block, first, false)?; - bytes_remaining -= SHA384_BLOCK_BYTE_SIZE; + if let Some(slice) = buf.get(offset..offset + SHA512_BLOCK_BYTE_SIZE) { + let block = <&[u8; SHA512_BLOCK_BYTE_SIZE]>::try_from(slice).unwrap(); + self.digest_block(mode, block, first, false)?; + bytes_remaining -= SHA512_BLOCK_BYTE_SIZE; first = false; } else { - return Err(CaliptraError::DRIVER_SHA384_INVALID_SLICE); + return Err(CaliptraError::DRIVER_SHA2_INVALID_SLICE); } } } } - let digest = self.read_digest(); + Ok(()) + } + + /// Calculate the SHA2-384 digest for specified data + /// + /// # Arguments + /// + /// * `data` - Data to used to update the digest + /// + #[cfg_attr(not(feature = "no-cfi"), cfi_impl_fn)] + pub fn sha384_digest(&mut self, buf: &[u8]) -> CaliptraResult { + self.sha_digest_helper(buf, ShaMode::Sha384)?; + + let digest = self.sha384_read_digest(); + + #[cfg(feature = "fips-test-hooks")] + let digest = unsafe { + crate::FipsTestHook::corrupt_data_if_hook_set( + crate::FipsTestHook::SHA384_CORRUPT_DIGEST, + &digest, + ) + }; + + self.zeroize_internal(); + + Ok(digest) + } + + /// Calculate the SHA2-512 digest for specified data + /// + /// # Arguments + /// + /// * `data` - Data to used to update the digest + /// + #[cfg_attr(not(feature = "no-cfi"), cfi_impl_fn)] + pub fn sha512_digest(&mut self, buf: &[u8]) -> CaliptraResult { + self.sha_digest_helper(buf, ShaMode::Sha512)?; + + wait::until(|| self.sha512.regs().status().read().valid()); + let digest = Array4x16::read_from_reg(self.sha512.regs().digest()); #[cfg(feature = "fips-test-hooks")] let digest = unsafe { @@ -145,7 +193,7 @@ impl Sha384 { /// # Arguments /// /// * `buf` - Digest buffer - fn read_digest(&mut self) -> Array4x12 { + fn sha384_read_digest(&mut self) -> Array4x12 { let sha = self.sha512.regs(); // digest_block() only waits until the peripheral is ready for the next // command; the result register may not be valid yet @@ -191,7 +239,7 @@ impl Sha384 { pub fn pcr_extend(&mut self, id: PcrId, data: &[u8]) -> CaliptraResult<()> { let total_bytes = data.len() + SHA384_HASH_SIZE; - if total_bytes > (SHA384_BLOCK_BYTE_SIZE - 1) { + if total_bytes > (SHA512_BLOCK_BYTE_SIZE - 1) { return Err(CaliptraError::DRIVER_SHA384_MAX_DATA_ERR); } @@ -201,7 +249,7 @@ impl Sha384 { // Prepare the data block; first SHA384_HASH_SIZE bytes are not filled // to account for the PCR retrieved. The retrieved PCR is unaffected as // writing to the first SHA384_HASH_SIZE bytes is skipped by the hardware. - let mut block = [0u8; SHA384_BLOCK_BYTE_SIZE]; + let mut block = [0u8; SHA512_BLOCK_BYTE_SIZE]; // PANIC-FREE: Following check optimizes the out of bounds // panic in copy_from_slice @@ -211,7 +259,7 @@ impl Sha384 { block[SHA384_HASH_SIZE..total_bytes].copy_from_slice(data); if let Some(slice) = block.get(..total_bytes) { - self.digest_partial_block(slice, true, total_bytes)?; + self.digest_partial_block(ShaMode::Sha384, slice, true, total_bytes)?; } else { return Err(CaliptraError::DRIVER_SHA384_MAX_DATA_ERR); } @@ -243,18 +291,19 @@ impl Sha384 { /// * `buf_size` - Total buffer size fn digest_partial_block( &mut self, + mode: ShaMode, slice: &[u8], first: bool, buf_size: usize, ) -> CaliptraResult<()> { /// Set block length - fn set_block_len(buf_size: usize, block: &mut [u8; SHA384_BLOCK_BYTE_SIZE]) { + fn set_block_len(buf_size: usize, block: &mut [u8; SHA512_BLOCK_BYTE_SIZE]) { let bit_len = (buf_size as u128) << 3; - block[SHA384_BLOCK_LEN_OFFSET..].copy_from_slice(&bit_len.to_be_bytes()); + block[SHA512_BLOCK_LEN_OFFSET..].copy_from_slice(&bit_len.to_be_bytes()); } // Construct the block - let mut block = [0u8; SHA384_BLOCK_BYTE_SIZE]; + let mut block = [0u8; SHA512_BLOCK_BYTE_SIZE]; let mut last = false; // PANIC-FREE: Following check optimizes the out of bounds @@ -264,19 +313,19 @@ impl Sha384 { } block[..slice.len()].copy_from_slice(slice); block[slice.len()] = 0b1000_0000; - if slice.len() < SHA384_BLOCK_LEN_OFFSET { + if slice.len() < SHA512_BLOCK_LEN_OFFSET { set_block_len(buf_size, &mut block); last = true; } // Calculate the digest of the op - self.digest_block(&block, first, last)?; + self.digest_block(mode, &block, first, last)?; // Add a padding block if one is needed - if slice.len() >= SHA384_BLOCK_LEN_OFFSET { + if slice.len() >= SHA512_BLOCK_LEN_OFFSET { block.fill(0); set_block_len(buf_size, &mut block); - self.digest_block(&block, false, true)?; + self.digest_block(mode, &block, false, true)?; } Ok(()) @@ -291,13 +340,14 @@ impl Sha384 { /// * `last` - Flag indicating if this is the last block fn digest_block( &mut self, - block: &[u8; SHA384_BLOCK_BYTE_SIZE], + mode: ShaMode, + block: &[u8; SHA512_BLOCK_BYTE_SIZE], first: bool, last: bool, ) -> CaliptraResult<()> { let sha512 = self.sha512.regs_mut(); Array4x32::from(block).write_to_reg(sha512.block()); - self.digest_op(first, last) + self.digest_op(mode, first, last) } // Perform the digest operation in the hardware @@ -306,9 +356,7 @@ impl Sha384 { // /// * `first` - Flag indicating if this is the first block /// * `last` - Flag indicating if this is the last block - fn digest_op(&mut self, first: bool, last: bool) -> CaliptraResult<()> { - const MODE_SHA384: u32 = 0b10; - + fn digest_op(&mut self, mode: ShaMode, first: bool, last: bool) -> CaliptraResult<()> { let sha = self.sha512.regs_mut(); // Wait for the hardware to be ready @@ -316,7 +364,7 @@ impl Sha384 { // Submit the first/next block for hashing. sha.ctrl() - .write(|w| w.mode(MODE_SHA384).init(first).next(!first).last(last)); + .write(|w| w.mode(mode.reg_value()).init(first).next(!first).last(last)); // Wait for the digest operation to finish wait::until(|| sha.status().read().ready()); @@ -327,7 +375,7 @@ impl Sha384 { /// SHA-384 Digest state #[derive(Debug, Copy, Clone, Eq, PartialEq)] -enum Sha384DigestState { +enum Sha2DigestState { /// Initial state Init, @@ -339,15 +387,15 @@ enum Sha384DigestState { } /// Multi step SHA-384 digest operation -pub struct Sha384DigestOp<'a> { +pub struct Sha2DigestOp<'a, const HASH_SIZE: u16> { /// SHA-384 Engine - sha: &'a mut Sha384, + sha: &'a mut Sha2_512_384, /// State - state: Sha384DigestState, + state: Sha2DigestState, /// Staging buffer - buf: [u8; SHA384_BLOCK_BYTE_SIZE], + buf: [u8; SHA512_BLOCK_BYTE_SIZE], /// Current staging buffer index buf_idx: usize, @@ -356,18 +404,32 @@ pub struct Sha384DigestOp<'a> { data_size: usize, } -impl<'a> Sha384DigestOp<'a> { +impl<'a, const HASH_SIZE: u16> Sha2DigestOp<'a, HASH_SIZE> { + /// Check if this the first digest operation + fn is_first(&self) -> bool { + self.state == Sha2DigestState::Init + } + + /// Reset internal buffer state + fn reset_buf_state(&mut self) { + self.buf.fill(0); + self.buf_idx = 0; + self.state = Sha2DigestState::Pending; + } +} + +impl<'a> Sha2DigestOp<'a, 384> { /// Update the digest with data /// /// # Arguments /// /// * `data` - Data to used to update the digest pub fn update(&mut self, data: &[u8]) -> CaliptraResult<()> { - if self.state == Sha384DigestState::Final { + if self.state == Sha2DigestState::Final { return Err(CaliptraError::DRIVER_SHA384_INVALID_STATE_ERR); } - if self.data_size + data.len() > SHA384_MAX_DATA_SIZE { + if self.data_size + data.len() > SHA512_MAX_DATA_SIZE { return Err(CaliptraError::DRIVER_SHA384_MAX_DATA_ERR); } @@ -386,7 +448,8 @@ impl<'a> Sha384DigestOp<'a> { // If the buffer is full calculate the digest of accumulated data if self.buf_idx == self.buf.len() { - self.sha.digest_block(&self.buf, self.is_first(), false)?; + self.sha + .digest_block(ShaMode::Sha384, &self.buf, self.is_first(), false)?; self.reset_buf_state(); } } @@ -396,39 +459,27 @@ impl<'a> Sha384DigestOp<'a> { /// Finalize the digest operations pub fn finalize(mut self, digest: &mut Array4x12) -> CaliptraResult<()> { - if self.state == Sha384DigestState::Final { + if self.state == Sha2DigestState::Final { return Err(CaliptraError::DRIVER_SHA384_INVALID_STATE_ERR); } if self.buf_idx > self.buf.len() { - return Err(CaliptraError::DRIVER_SHA384_INVALID_SLICE); + return Err(CaliptraError::DRIVER_SHA2_INVALID_SLICE); } // Calculate the digest of the final block let buf = &self.buf[..self.buf_idx]; self.sha - .digest_partial_block(buf, self.is_first(), self.data_size)?; + .digest_partial_block(ShaMode::Sha384, buf, self.is_first(), self.data_size)?; // Set the state of the operation to final - self.state = Sha384DigestState::Final; + self.state = Sha2DigestState::Final; // Copy digest - *digest = self.sha.read_digest(); + *digest = self.sha.sha384_read_digest(); Ok(()) } - - /// Check if this the first digest operation - fn is_first(&self) -> bool { - self.state == Sha384DigestState::Init - } - - /// Reset internal buffer state - fn reset_buf_state(&mut self) { - self.buf.fill(0); - self.buf_idx = 0; - self.state = Sha384DigestState::Pending; - } } /// SHA-384 key access error trait diff --git a/drivers/test-fw/src/bin/sha384_tests.rs b/drivers/test-fw/src/bin/sha384_tests.rs index 667cb486bf..ead03d3f4f 100644 --- a/drivers/test-fw/src/bin/sha384_tests.rs +++ b/drivers/test-fw/src/bin/sha384_tests.rs @@ -16,14 +16,14 @@ Abstract: #![no_main] use caliptra_cfi_lib::CfiCounter; -use caliptra_drivers::{Array4x12, PcrBank, PcrId, Sha384}; +use caliptra_drivers::{Array4x12, PcrBank, PcrId, Sha2_512_384}; use caliptra_kat::Sha384Kat; use caliptra_registers::{pv::PvReg, sha512::Sha512Reg}; use caliptra_test_harness::test_suite; fn test_digest0() { - let mut sha384 = unsafe { Sha384::new(Sha512Reg::new()) }; + let mut sha2 = unsafe { Sha2_512_384::new(Sha512Reg::new()) }; let expected: [u8; 48] = [ 0x38, 0xB0, 0x60, 0xA7, 0x51, 0xAC, 0x96, 0x38, 0x4C, 0xD9, 0x32, 0x7E, 0xB1, 0xB1, 0xE3, 0x6A, 0x21, 0xFD, 0xB7, 0x11, 0x14, 0xBE, 0x07, 0x43, 0x4C, 0x0C, 0xC7, 0xBF, 0x63, 0xF6, @@ -32,12 +32,12 @@ fn test_digest0() { ]; let data = &[]; - let digest = sha384.digest(data).unwrap(); + let digest = sha2.sha384_digest(data).unwrap(); assert_eq!(digest, Array4x12::from(expected)); } fn test_digest1() { - let mut sha384 = unsafe { Sha384::new(Sha512Reg::new()) }; + let mut sha384 = unsafe { Sha2_512_384::new(Sha512Reg::new()) }; let expected: [u8; 48] = [ 0xCB, 0x00, 0x75, 0x3F, 0x45, 0xA3, 0x5E, 0x8B, 0xB5, 0xA0, 0x3D, 0x69, 0x9A, 0xC6, 0x50, 0x07, 0x27, 0x2C, 0x32, 0xAB, 0x0E, 0xDE, 0xD1, 0x63, 0x1A, 0x8B, 0x60, 0x5A, 0x43, 0xFF, @@ -45,12 +45,12 @@ fn test_digest1() { 0xC8, 0x25, 0xA7, ]; let data = "abc".as_bytes(); - let digest = sha384.digest(data.into()).unwrap(); + let digest = sha384.sha384_digest(data.into()).unwrap(); assert_eq!(digest, Array4x12::from(expected)); } fn test_digest2() { - let mut sha384 = unsafe { Sha384::new(Sha512Reg::new()) }; + let mut sha384 = unsafe { Sha2_512_384::new(Sha512Reg::new()) }; let expected: [u8; 48] = [ 0x33, 0x91, 0xFD, 0xDD, 0xFC, 0x8D, 0xC7, 0x39, 0x37, 0x07, 0xA6, 0x5B, 0x1B, 0x47, 0x09, 0x39, 0x7C, 0xF8, 0xB1, 0xD1, 0x62, 0xAF, 0x05, 0xAB, 0xFE, 0x8F, 0x45, 0x0D, 0xE5, 0xF3, @@ -58,12 +58,12 @@ fn test_digest2() { 0xC8, 0x45, 0x2B, ]; let data = "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq".as_bytes(); - let digest = sha384.digest(data.into()).unwrap(); + let digest = sha384.sha384_digest(data.into()).unwrap(); assert_eq!(digest, Array4x12::from(expected)); } fn test_digest3() { - let mut sha384 = unsafe { Sha384::new(Sha512Reg::new()) }; + let mut sha384 = unsafe { Sha2_512_384::new(Sha512Reg::new()) }; let expected: [u8; 48] = [ 0x09, 0x33, 0x0C, 0x33, 0xF7, 0x11, 0x47, 0xE8, 0x3D, 0x19, 0x2F, 0xC7, 0x82, 0xCD, 0x1B, 0x47, 0x53, 0x11, 0x1B, 0x17, 0x3B, 0x3B, 0x05, 0xD2, 0x2F, 0xA0, 0x80, 0x86, 0xE3, 0xB0, @@ -71,12 +71,12 @@ fn test_digest3() { 0x74, 0x60, 0x39, ]; let data = "abcdefghbcdefghicdefghijdefghijkefghijklfghijklmghijklmnhijklmnoijklmnopjklmnopqklmnopqrlmnopqrsmnopqrstnopqrstu".as_bytes(); - let digest = sha384.digest(data.into()).unwrap(); + let digest = sha384.sha384_digest(data.into()).unwrap(); assert_eq!(digest, Array4x12::from(expected)); } fn test_op0() { - let mut sha384 = unsafe { Sha384::new(Sha512Reg::new()) }; + let mut sha384 = unsafe { Sha2_512_384::new(Sha512Reg::new()) }; let expected: [u8; 48] = [ 0x38, 0xB0, 0x60, 0xA7, 0x51, 0xAC, 0x96, 0x38, 0x4C, 0xD9, 0x32, 0x7E, 0xB1, 0xB1, 0xE3, 0x6A, 0x21, 0xFD, 0xB7, 0x11, 0x14, 0xBE, 0x07, 0x43, 0x4C, 0x0C, 0xC7, 0xBF, 0x63, 0xF6, @@ -84,14 +84,14 @@ fn test_op0() { 0x98, 0xB9, 0x5B, ]; let mut digest = Array4x12::default(); - let digest_op = sha384.digest_init().unwrap(); + let digest_op = sha384.sha384_digest_init().unwrap(); let actual = digest_op.finalize(&mut digest); assert!(actual.is_ok()); assert_eq!(digest, Array4x12::from(expected)); } fn test_op1() { - let mut sha384 = unsafe { Sha384::new(Sha512Reg::new()) }; + let mut sha384 = unsafe { Sha2_512_384::new(Sha512Reg::new()) }; let expected: [u8; 48] = [ 0x38, 0xB0, 0x60, 0xA7, 0x51, 0xAC, 0x96, 0x38, 0x4C, 0xD9, 0x32, 0x7E, 0xB1, 0xB1, 0xE3, 0x6A, 0x21, 0xFD, 0xB7, 0x11, 0x14, 0xBE, 0x07, 0x43, 0x4C, 0x0C, 0xC7, 0xBF, 0x63, 0xF6, @@ -99,14 +99,14 @@ fn test_op1() { 0x98, 0xB9, 0x5B, ]; let mut digest = Array4x12::default(); - let digest_op = sha384.digest_init().unwrap(); + let digest_op = sha384.sha384_digest_init().unwrap(); let actual = digest_op.finalize(&mut digest); assert!(actual.is_ok()); assert_eq!(digest, Array4x12::from(expected)); } fn test_op2() { - let mut sha384 = unsafe { Sha384::new(Sha512Reg::new()) }; + let mut sha384 = unsafe { Sha2_512_384::new(Sha512Reg::new()) }; let expected: [u8; 48] = [ 0xCB, 0x00, 0x75, 0x3F, 0x45, 0xA3, 0x5E, 0x8B, 0xB5, 0xA0, 0x3D, 0x69, 0x9A, 0xC6, 0x50, 0x07, 0x27, 0x2C, 0x32, 0xAB, 0x0E, 0xDE, 0xD1, 0x63, 0x1A, 0x8B, 0x60, 0x5A, 0x43, 0xFF, @@ -116,7 +116,7 @@ fn test_op2() { let data = "abc".as_bytes(); let mut digest = Array4x12::default(); - let mut digest_op = sha384.digest_init().unwrap(); + let mut digest_op = sha384.sha384_digest_init().unwrap(); assert!(digest_op.update(data).is_ok()); let actual = digest_op.finalize(&mut digest); assert!(actual.is_ok()); @@ -124,7 +124,7 @@ fn test_op2() { } fn test_op3() { - let mut sha384 = unsafe { Sha384::new(Sha512Reg::new()) }; + let mut sha384 = unsafe { Sha2_512_384::new(Sha512Reg::new()) }; let expected: [u8; 48] = [ 0x33, 0x91, 0xFD, 0xDD, 0xFC, 0x8D, 0xC7, 0x39, 0x37, 0x07, 0xA6, 0x5B, 0x1B, 0x47, 0x09, 0x39, 0x7C, 0xF8, 0xB1, 0xD1, 0x62, 0xAF, 0x05, 0xAB, 0xFE, 0x8F, 0x45, 0x0D, 0xE5, 0xF3, @@ -133,7 +133,7 @@ fn test_op3() { ]; let data = "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq".as_bytes(); let mut digest = Array4x12::default(); - let mut digest_op = sha384.digest_init().unwrap(); + let mut digest_op = sha384.sha384_digest_init().unwrap(); assert!(digest_op.update(data).is_ok()); let actual = digest_op.finalize(&mut digest); assert!(actual.is_ok()); @@ -141,7 +141,7 @@ fn test_op3() { } fn test_op4() { - let mut sha384 = unsafe { Sha384::new(Sha512Reg::new()) }; + let mut sha384 = unsafe { Sha2_512_384::new(Sha512Reg::new()) }; let expected: [u8; 48] = [ 0x09, 0x33, 0x0C, 0x33, 0xF7, 0x11, 0x47, 0xE8, 0x3D, 0x19, 0x2F, 0xC7, 0x82, 0xCD, 0x1B, 0x47, 0x53, 0x11, 0x1B, 0x17, 0x3B, 0x3B, 0x05, 0xD2, 0x2F, 0xA0, 0x80, 0x86, 0xE3, 0xB0, @@ -150,7 +150,7 @@ fn test_op4() { ]; let data = "abcdefghbcdefghicdefghijdefghijkefghijklfghijklmghijklmnhijklmnoijklmnopjklmnopqklmnopqrlmnopqrsmnopqrstnopqrstu".as_bytes(); let mut digest = Array4x12::default(); - let mut digest_op = sha384.digest_init().unwrap(); + let mut digest_op = sha384.sha384_digest_init().unwrap(); assert!(digest_op.update(data).is_ok()); let actual = digest_op.finalize(&mut digest); assert!(actual.is_ok()); @@ -158,7 +158,7 @@ fn test_op4() { } fn test_op5() { - let mut sha384 = unsafe { Sha384::new(Sha512Reg::new()) }; + let mut sha384 = unsafe { Sha2_512_384::new(Sha512Reg::new()) }; let expected: [u8; 48] = [ 0x9D, 0x0E, 0x18, 0x09, 0x71, 0x64, 0x74, 0xCB, 0x08, 0x6E, 0x83, 0x4E, 0x31, 0x0A, 0x4A, 0x1C, 0xED, 0x14, 0x9E, 0x9C, 0x00, 0xF2, 0x48, 0x52, 0x79, 0x72, 0xCE, 0xC5, 0x70, 0x4C, @@ -167,7 +167,7 @@ fn test_op5() { ]; const DATA: [u8; 1000] = [0x61; 1000]; let mut digest = Array4x12::default(); - let mut digest_op = sha384.digest_init().unwrap(); + let mut digest_op = sha384.sha384_digest_init().unwrap(); for _ in 0..1_000 { assert!(digest_op.update(&DATA).is_ok()); } @@ -177,7 +177,7 @@ fn test_op5() { } fn test_op6() { - let mut sha384 = unsafe { Sha384::new(Sha512Reg::new()) }; + let mut sha384 = unsafe { Sha2_512_384::new(Sha512Reg::new()) }; let expected: [u8; 48] = [ 0x9c, 0x2f, 0x48, 0x76, 0x0d, 0x13, 0xac, 0x42, 0xea, 0xd1, 0x96, 0xe5, 0x4d, 0xcb, 0xaa, 0x5e, 0x58, 0x72, 0x06, 0x62, 0xa9, 0x6b, 0x91, 0x94, 0xe9, 0x81, 0x33, 0x29, 0xbd, 0xb6, @@ -186,7 +186,7 @@ fn test_op6() { ]; let data = "abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyz".as_bytes(); let mut digest = Array4x12::default(); - let mut digest_op = sha384.digest_init().unwrap(); + let mut digest_op = sha384.sha384_digest_init().unwrap(); for idx in 0..data.len() { assert!(digest_op.update(&data[idx..idx + 1]).is_ok()); } @@ -196,7 +196,7 @@ fn test_op6() { } fn test_op7() { - let mut sha384 = unsafe { Sha384::new(Sha512Reg::new()) }; + let mut sha384 = unsafe { Sha2_512_384::new(Sha512Reg::new()) }; let expected: [u8; 48] = [ 0x67, 0x4b, 0x2e, 0x80, 0xff, 0x8d, 0x94, 0x00, 0x8d, 0xe7, 0x40, 0x9c, 0x7b, 0x1f, 0x87, 0x8f, 0x9f, 0xae, 0x3a, 0x0a, 0x6d, 0xae, 0x2f, 0x98, 0x2c, 0xca, 0x7e, 0x3a, 0xae, 0xf9, @@ -205,7 +205,7 @@ fn test_op7() { ]; let data = "abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwx".as_bytes(); let mut digest = Array4x12::default(); - let mut digest_op = sha384.digest_init().unwrap(); + let mut digest_op = sha384.sha384_digest_init().unwrap(); for idx in 0..data.len() { assert!(digest_op.update(&data[idx..idx + 1]).is_ok()); } @@ -215,7 +215,7 @@ fn test_op7() { } fn test_op8() { - let mut sha384 = unsafe { Sha384::new(Sha512Reg::new()) }; + let mut sha384 = unsafe { Sha2_512_384::new(Sha512Reg::new()) }; let expected: [u8; 48] = [ 0x55, 0x23, 0xcf, 0xb7, 0x7f, 0x9c, 0x55, 0xe0, 0xcc, 0xaf, 0xec, 0x5b, 0x87, 0xd7, 0x9c, 0xde, 0x64, 0x30, 0x12, 0x28, 0x3b, 0x71, 0x18, 0x8e, 0x40, 0x8c, 0x5a, 0xea, 0xe9, 0x19, @@ -224,7 +224,7 @@ fn test_op8() { ]; let data = "abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefgh".as_bytes(); let mut digest = Array4x12::default(); - let mut digest_op = sha384.digest_init().unwrap(); + let mut digest_op = sha384.sha384_digest_init().unwrap(); for idx in 0..data.len() { assert!(digest_op.update(&data[idx..idx + 1]).is_ok()); } @@ -234,7 +234,7 @@ fn test_op8() { } fn test_pcr_hash_extend_single_block() { - let mut sha384 = unsafe { Sha384::new(Sha512Reg::new()) }; + let mut sha384 = unsafe { Sha2_512_384::new(Sha512Reg::new()) }; let mut pcr_bank = unsafe { PcrBank::new(PvReg::new()) }; // fn change_endianess(arr: mut &[u8]) { @@ -287,7 +287,7 @@ fn test_pcr_hash_extend_single_block() { } fn test_pcr_hash_extend_single_block_2() { - let mut sha384 = unsafe { Sha384::new(Sha512Reg::new()) }; + let mut sha384 = unsafe { Sha2_512_384::new(Sha512Reg::new()) }; let mut pcr_bank = unsafe { PcrBank::new(PvReg::new()) }; let expected_round_1: [u8; 48] = [ @@ -328,7 +328,7 @@ fn test_pcr_hash_extend_single_block_2() { } fn test_pcr_hash_extend_single_block_3() { - let mut sha384 = unsafe { Sha384::new(Sha512Reg::new()) }; + let mut sha384 = unsafe { Sha2_512_384::new(Sha512Reg::new()) }; let mut pcr_bank = unsafe { PcrBank::new(PvReg::new()) }; let expected_round_1: [u8; 48] = [ @@ -371,7 +371,7 @@ fn test_pcr_hash_extend_single_block_3() { } fn test_pcr_hash_extend_limit() { - let mut sha384 = unsafe { Sha384::new(Sha512Reg::new()) }; + let mut sha384 = unsafe { Sha2_512_384::new(Sha512Reg::new()) }; let data_allowed: [u8; 79] = [0u8; 79]; let data_not_allowed: [u8; 80] = [0u8; 80]; @@ -386,7 +386,7 @@ fn test_kat() { // Init CFI CfiCounter::reset(&mut || Ok([0xDEADBEEFu32; 12])); - let mut sha384 = unsafe { Sha384::new(Sha512Reg::new()) }; + let mut sha384 = unsafe { Sha2_512_384::new(Sha512Reg::new()) }; assert_eq!(Sha384Kat::default().execute(&mut sha384).is_ok(), true); } diff --git a/error/src/lib.rs b/error/src/lib.rs index 1bd65a3840..c580108c2d 100644 --- a/error/src/lib.rs +++ b/error/src/lib.rs @@ -48,7 +48,7 @@ impl CaliptraError { pub const DRIVER_SHA384_INVALID_STATE_ERR: CaliptraError = CaliptraError::new_const(0x00030007); pub const DRIVER_SHA384_MAX_DATA_ERR: CaliptraError = CaliptraError::new_const(0x00030008); pub const DRIVER_SHA384_INVALID_KEY_SIZE: CaliptraError = CaliptraError::new_const(0x00030009); - pub const DRIVER_SHA384_INVALID_SLICE: CaliptraError = CaliptraError::new_const(0x0003000A); + pub const DRIVER_SHA2_INVALID_SLICE: CaliptraError = CaliptraError::new_const(0x0003000A); pub const DRIVER_SHA384_INDEX_OUT_OF_BOUNDS: CaliptraError = CaliptraError::new_const(0x0003000B); diff --git a/fmc/src/flow/crypto.rs b/fmc/src/flow/crypto.rs index 0abc8a9ecc..e59530700b 100644 --- a/fmc/src/flow/crypto.rs +++ b/fmc/src/flow/crypto.rs @@ -59,7 +59,7 @@ impl Crypto { /// * `Array4x12` - Digest #[cfg_attr(not(feature = "no-cfi"), cfi_impl_fn)] pub fn sha384_digest(env: &mut FmcEnv, data: &[u8]) -> CaliptraResult { - env.sha384.digest(data) + env.sha2_512_384.sha384_digest(data) } /// Calculate HMAC-384 KDF diff --git a/fmc/src/flow/pcr.rs b/fmc/src/flow/pcr.rs index eb1f9124f6..7de4fa7762 100644 --- a/fmc/src/flow/pcr.rs +++ b/fmc/src/flow/pcr.rs @@ -61,9 +61,9 @@ pub fn extend_pcr_common(env: &mut FmcEnv) -> CaliptraResult<()> { #[cfg_attr(not(feature = "no-cfi"), cfi_mod_fn)] fn extend_and_log(env: &mut FmcEnv, entry_id: PcrLogEntryId, data: &[u8]) -> CaliptraResult<()> { env.pcr_bank - .extend_pcr(RT_FW_CURRENT_PCR, &mut env.sha384, data)?; + .extend_pcr(RT_FW_CURRENT_PCR, &mut env.sha2_512_384, data)?; env.pcr_bank - .extend_pcr(RT_FW_JOURNEY_PCR, &mut env.sha384, data)?; + .extend_pcr(RT_FW_JOURNEY_PCR, &mut env.sha2_512_384, data)?; log_pcr( env.persistent_data.get_mut(), diff --git a/fmc/src/fmc_env.rs b/fmc/src/fmc_env.rs index 28db1bcd38..4dae5e97fc 100644 --- a/fmc/src/fmc_env.rs +++ b/fmc/src/fmc_env.rs @@ -17,7 +17,7 @@ Abstract: use caliptra_drivers::{ CaliptraResult, DataVault, Ecc384, Hmac, KeyVault, Mailbox, PcrBank, PersistentDataAccessor, - Sha1, Sha256, Sha2_512_384Acc, Sha384, SocIfc, Trng, + Sha1, Sha256, Sha2_512_384, Sha2_512_384Acc, SocIfc, Trng, }; use caliptra_registers::{ csrng::CsrngReg, dv::DvReg, ecc::EccReg, entropy_src::EntropySrcReg, hmac::HmacReg, kv::KvReg, @@ -33,8 +33,8 @@ pub struct FmcEnv { // SHA2-256 Engine pub sha256: Sha256, - // SHA2-384 Engine - pub sha384: Sha384, + // SHA2-512/384 Engine + pub sha2_512_384: Sha2_512_384, // SHA2-512/384 Accelerator pub sha2_512_384_acc: Sha2_512_384Acc, @@ -86,7 +86,7 @@ impl FmcEnv { Ok(Self { sha1: Sha1::default(), sha256: Sha256::new(Sha256Reg::new()), - sha384: Sha384::new(Sha512Reg::new()), + sha2_512_384: Sha2_512_384::new(Sha512Reg::new()), sha2_512_384_acc: Sha2_512_384Acc::new(Sha512AccCsr::new()), hmac384: Hmac::new(HmacReg::new()), ecc384: Ecc384::new(EccReg::new()), diff --git a/hw-model/test-fw/test_pcr_extend.rs b/hw-model/test-fw/test_pcr_extend.rs index 6c1cfb1b6f..e06958e55c 100644 --- a/hw-model/test-fw/test_pcr_extend.rs +++ b/hw-model/test-fw/test_pcr_extend.rs @@ -6,7 +6,7 @@ #![no_std] use caliptra_cfi_lib::CfiCounter; -use caliptra_drivers::{Array4x12, PcrBank, PcrId, Sha384}; +use caliptra_drivers::{Array4x12, PcrBank, PcrId, Sha2_512_384}; use caliptra_registers::{pv::PvReg, sha512::Sha512Reg}; #[allow(unused)] use caliptra_test_harness::println; @@ -28,11 +28,11 @@ extern "C" fn main() { // Init CFI CfiCounter::reset(&mut || Ok([0xDEADBEEFu32; 12])); - let mut sha384 = unsafe { Sha384::new(Sha512Reg::new()) }; + let mut sha2 = unsafe { Sha2_512_384::new(Sha512Reg::new()) }; let pcr_bank = unsafe { PcrBank::new(PvReg::new()) }; pcr_bank - .extend_pcr(PcrId::PcrId1, &mut sha384, &[0_u8; 4]) + .extend_pcr(PcrId::PcrId1, &mut sha2, &[0_u8; 4]) .unwrap(); let pcr1 = pcr_bank.read_pcr(PcrId::PcrId1); @@ -46,7 +46,7 @@ extern "C" fn main() { assert_eq!(pcr1, Array4x12::from(expected_pcr1)); - let digest = sha384.digest(&expected_pcr1).unwrap(); + let digest = sha2.sha384_digest(&expected_pcr1).unwrap(); let expected_digest = [ 0x5f, 0xeb, 0xea, 0xe8, 0x58, 0x75, 0x73, 0x40, 0x29, 0x58, 0xa9, 0x24, 0xba, 0x75, 0xc7, diff --git a/kat/src/kats_env.rs b/kat/src/kats_env.rs index fc5827b141..03ba9c12c3 100644 --- a/kat/src/kats_env.rs +++ b/kat/src/kats_env.rs @@ -1,7 +1,7 @@ // Licensed under the Apache-2.0 license use caliptra_drivers::{ - Ecc384, Hmac, Lms, Sha1, Sha256, Sha2_512_384Acc, Sha384, ShaAccLockState, Trng, + Ecc384, Hmac, Lms, Sha1, Sha256, Sha2_512_384, Sha2_512_384Acc, ShaAccLockState, Trng, }; pub struct KatsEnv<'a> { @@ -11,8 +11,8 @@ pub struct KatsEnv<'a> { // SHA2-256 Engine pub sha256: &'a mut Sha256, - // SHA2-384 Engine - pub sha384: &'a mut Sha384, + // SHA2-512/384 Engine + pub sha2_512_384: &'a mut Sha2_512_384, // SHA2-512/384 Accelerator pub sha2_512_384_acc: &'a mut Sha2_512_384Acc, diff --git a/kat/src/lib.rs b/kat/src/lib.rs index 660661bd63..3ae06e68fa 100644 --- a/kat/src/lib.rs +++ b/kat/src/lib.rs @@ -50,7 +50,7 @@ pub fn execute_kat(env: &mut KatsEnv) -> CaliptraResult<()> { Sha256Kat::default().execute(env.sha256)?; cprintln!("[kat] SHA2-384"); - Sha384Kat::default().execute(env.sha384)?; + Sha384Kat::default().execute(env.sha2_512_384)?; cprintln!("[kat] SHA2-512-ACC"); Sha2_512_384AccKat::default().execute(env.sha2_512_384_acc, env.sha_acc_lock_state)?; diff --git a/kat/src/sha384_kat.rs b/kat/src/sha384_kat.rs index c6a2f027fa..89089986ae 100644 --- a/kat/src/sha384_kat.rs +++ b/kat/src/sha384_kat.rs @@ -12,7 +12,7 @@ Abstract: --*/ -use caliptra_drivers::{Array4x12, CaliptraError, CaliptraResult, Sha384}; +use caliptra_drivers::{Array4x12, CaliptraError, CaliptraResult, Sha2_512_384}; pub const SHA384_EXPECTED_DIGEST: Array4x12 = Array4x12::new([ 0x38b060a7, 0x51ac9638, 0x4cd9327e, 0xb1b1e36a, 0x21fdb711, 0x14be0743, 0x4c0cc7bf, 0x63f6e1da, @@ -35,14 +35,14 @@ impl Sha384Kat { /// # Returns /// /// * `CaliptraResult` - Result denoting the KAT outcome. - pub fn execute(&self, sha: &mut Sha384) -> CaliptraResult<()> { + pub fn execute(&self, sha: &mut Sha2_512_384) -> CaliptraResult<()> { self.kat_no_data(sha) } - fn kat_no_data(&self, sha: &mut Sha384) -> CaliptraResult<()> { + fn kat_no_data(&self, sha2: &mut Sha2_512_384) -> CaliptraResult<()> { let data = &[]; - let digest = sha - .digest(data) + let digest = sha2 + .sha384_digest(data) .map_err(|_| CaliptraError::KAT_SHA384_DIGEST_FAILURE)?; if digest != SHA384_EXPECTED_DIGEST { diff --git a/rom/dev/src/crypto.rs b/rom/dev/src/crypto.rs index 6bf2bfa9b6..2a48ad0428 100644 --- a/rom/dev/src/crypto.rs +++ b/rom/dev/src/crypto.rs @@ -110,7 +110,23 @@ impl Crypto { /// * `Array4x12` - Digest #[inline(always)] pub fn sha384_digest(env: &mut RomEnv, data: &[u8]) -> CaliptraResult { - env.sha384.digest(data) + env.sha2_512_384.sha384_digest(data) + } + + /// Calculate SHA2-512 Digest + /// + /// # Arguments + /// + /// * `env` - ROM Environment + /// * `data` - Input data to hash + /// + /// # Returns + /// + /// * `Array4x16` - Digest + #[inline(always)] + #[allow(dead_code)] + pub fn sha512_digest(env: &mut RomEnv, data: &[u8]) -> CaliptraResult { + env.sha2_512_384.sha512_digest(data) } /// Calculate HMAC diff --git a/rom/dev/src/flow/cold_reset/fmc_alias.rs b/rom/dev/src/flow/cold_reset/fmc_alias.rs index c77d0f6910..aa130dc04d 100644 --- a/rom/dev/src/flow/cold_reset/fmc_alias.rs +++ b/rom/dev/src/flow/cold_reset/fmc_alias.rs @@ -202,7 +202,7 @@ impl FmcAliasLayer { let fuse_svn = fw_proc_info.effective_fuse_svn as u8; let mut fuse_info_digest = Array4x12::default(); - let mut hasher = env.sha384.digest_init()?; + let mut hasher = env.sha2_512_384.sha384_digest_init()?; hasher.update(&[ env.soc_ifc.lifecycle() as u8, env.soc_ifc.debug_locked() as u8, diff --git a/rom/dev/src/flow/cold_reset/fw_processor.rs b/rom/dev/src/flow/cold_reset/fw_processor.rs index a5fd27070a..dc290b86a4 100644 --- a/rom/dev/src/flow/cold_reset/fw_processor.rs +++ b/rom/dev/src/flow/cold_reset/fw_processor.rs @@ -65,8 +65,8 @@ impl FirmwareProcessor { // sha256 sha256: &mut env.sha256, - // SHA2-384 Engine - sha384: &mut env.sha384, + // SHA2-512/384 Engine + sha2_512_384: &mut env.sha2_512_384, // SHA2-512/384 Accelerator sha2_512_384_acc: &mut env.sha2_512_384_acc, @@ -108,7 +108,7 @@ impl FirmwareProcessor { let mut venv = FirmwareImageVerificationEnv { sha256: &mut env.sha256, - sha384: &mut env.sha384, + sha2_512_384: &mut env.sha2_512_384, soc_ifc: &mut env.soc_ifc, ecc384: &mut env.ecc384, data_vault: &mut env.data_vault, @@ -296,7 +296,12 @@ impl FirmwareProcessor { return Err(CaliptraError::FW_PROC_MAILBOX_STASH_MEASUREMENT_MAX_LIMIT); } - Self::stash_measurement(pcr_bank, env.sha384, persistent_data, &mut txn)?; + Self::stash_measurement( + pcr_bank, + env.sha2_512_384, + persistent_data, + &mut txn, + )?; // Generate and send response (with FIPS approved status) let mut resp = StashMeasurementResp { @@ -373,7 +378,7 @@ impl FirmwareProcessor { #[cfg(feature = "fake-rom")] let venv = &mut FakeRomImageVerificationEnv { sha256: venv.sha256, - sha384: venv.sha384, + sha2_512_384: venv.sha2_512_384, soc_ifc: venv.soc_ifc, data_vault: venv.data_vault, ecc384: venv.ecc384, @@ -663,7 +668,7 @@ impl FirmwareProcessor { /// Err - StashMeasurementReadFailure fn stash_measurement( pcr_bank: &mut PcrBank, - sha384: &mut Sha384, + sha2: &mut Sha2_512_384, persistent_data: &mut PersistentData, txn: &mut MailboxRecvTxn, ) -> CaliptraResult<()> { @@ -671,7 +676,7 @@ impl FirmwareProcessor { Self::copy_req_verify_chksum(txn, measurement.as_bytes_mut())?; // Extend measurement into PCR31. - Self::extend_measurement(pcr_bank, sha384, persistent_data, &measurement)?; + Self::extend_measurement(pcr_bank, sha2, persistent_data, &measurement)?; Ok(()) } @@ -689,14 +694,14 @@ impl FirmwareProcessor { /// Error code on failure. fn extend_measurement( pcr_bank: &mut PcrBank, - sha384: &mut Sha384, + sha2: &mut Sha2_512_384, persistent_data: &mut PersistentData, stash_measurement: &StashMeasurementReq, ) -> CaliptraResult<()> { // Extend measurement into PCR31. pcr_bank.extend_pcr( PCR_ID_STASH_MEASUREMENT, - sha384, + sha2, stash_measurement.measurement.as_bytes(), )?; diff --git a/rom/dev/src/flow/fake.rs b/rom/dev/src/flow/fake.rs index b8a8f7dc7d..091650c013 100644 --- a/rom/dev/src/flow/fake.rs +++ b/rom/dev/src/flow/fake.rs @@ -222,10 +222,10 @@ pub fn copy_canned_fmc_alias_cert(env: &mut RomEnv) -> CaliptraResult<()> { Ok(()) } -// ROM Verification Environemnt +// ROM Verification Environment pub(crate) struct FakeRomImageVerificationEnv<'a, 'b> { pub(crate) sha256: &'a mut Sha256, - pub(crate) sha384: &'a mut Sha384, + pub(crate) sha2_512_384: &'a mut Sha2_512_384, pub(crate) soc_ifc: &'a mut SocIfc, pub(crate) data_vault: &'a mut DataVault, pub(crate) ecc384: &'a mut Ecc384, @@ -242,7 +242,7 @@ impl<'a, 'b> ImageVerificationEnv for &mut FakeRomImageVerificationEnv<'a, 'b> { .ok_or(err)? .get(..len as usize) .ok_or(err)?; - Ok(self.sha384.digest(data)?.0) + Ok(self.sha2_512_384.sha384_digest(data)?.0) } /// ECC-384 Verification routine diff --git a/rom/dev/src/flow/update_reset.rs b/rom/dev/src/flow/update_reset.rs index 947e7dde2a..9f154650fb 100644 --- a/rom/dev/src/flow/update_reset.rs +++ b/rom/dev/src/flow/update_reset.rs @@ -67,7 +67,7 @@ impl UpdateResetFlow { let mut venv = FirmwareImageVerificationEnv { sha256: &mut env.sha256, - sha384: &mut env.sha384, + sha2_512_384: &mut env.sha2_512_384, soc_ifc: &mut env.soc_ifc, ecc384: &mut env.ecc384, data_vault: &mut env.data_vault, @@ -147,7 +147,7 @@ impl UpdateResetFlow { #[cfg(feature = "fake-rom")] let env = &mut FakeRomImageVerificationEnv { sha256: env.sha256, - sha384: env.sha384, + sha2_512_384: env.sha2_512_384, soc_ifc: env.soc_ifc, data_vault: env.data_vault, ecc384: env.ecc384, diff --git a/rom/dev/src/main.rs b/rom/dev/src/main.rs index f27bb8ff96..48853aa3d2 100644 --- a/rom/dev/src/main.rs +++ b/rom/dev/src/main.rs @@ -26,8 +26,8 @@ use core::hint::black_box; use caliptra_drivers::{ cprintln, report_boot_status, report_fw_error_fatal, report_fw_error_non_fatal, CaliptraError, - Ecc384, Hmac, KeyVault, Mailbox, ResetReason, Sha256, Sha2_512_384Acc, Sha384, ShaAccLockState, - SocIfc, Trng, + Ecc384, Hmac, KeyVault, Mailbox, ResetReason, Sha256, Sha2_512_384, Sha2_512_384Acc, + ShaAccLockState, SocIfc, Trng, }; use caliptra_error::CaliptraResult; use caliptra_image_types::RomInfo; @@ -134,8 +134,8 @@ pub extern "C" fn rom_entry() -> ! { // sha256 sha256: &mut env.sha256, - // SHA2-384 Engine - sha384: &mut env.sha384, + // SHA2-512/384 Engine + sha2_512_384: &mut env.sha2_512_384, // SHA2-512/384 Accelerator sha2_512_384_acc: &mut env.sha2_512_384_acc, @@ -366,7 +366,7 @@ fn handle_fatal_error(code: u32) -> ! { Ecc384::zeroize(); Hmac::zeroize(); Sha256::zeroize(); - Sha384::zeroize(); + Sha2_512_384::zeroize(); Sha2_512_384Acc::zeroize(); // Zeroize the key vault. diff --git a/rom/dev/src/pcr.rs b/rom/dev/src/pcr.rs index 54d3d02b05..47b2cf81f5 100644 --- a/rom/dev/src/pcr.rs +++ b/rom/dev/src/pcr.rs @@ -29,7 +29,7 @@ use caliptra_common::{ PcrLogEntry, PcrLogEntryId, }; use caliptra_drivers::{ - CaliptraError, CaliptraResult, PcrBank, PersistentData, PersistentDataAccessor, Sha384, + CaliptraError, CaliptraResult, PcrBank, PersistentData, PersistentDataAccessor, Sha2_512_384, }; use caliptra_image_verify::ImageVerificationInfo; @@ -38,16 +38,16 @@ use zerocopy::AsBytes; struct PcrExtender<'a> { persistent_data: &'a mut PersistentData, pcr_bank: &'a mut PcrBank, - sha384: &'a mut Sha384, + sha2_512_384: &'a mut Sha2_512_384, } impl PcrExtender<'_> { #[cfg_attr(not(feature = "no-cfi"), cfi_impl_fn)] #[inline(never)] fn extend(&mut self, data: &[u8], pcr_entry_id: PcrLogEntryId) -> CaliptraResult<()> { self.pcr_bank - .extend_pcr(PCR_ID_FMC_CURRENT, self.sha384, data)?; + .extend_pcr(PCR_ID_FMC_CURRENT, self.sha2_512_384, data)?; self.pcr_bank - .extend_pcr(PCR_ID_FMC_JOURNEY, self.sha384, data)?; + .extend_pcr(PCR_ID_FMC_JOURNEY, self.sha2_512_384, data)?; let pcr_ids: u32 = (1 << PCR_ID_FMC_CURRENT as u8) | (1 << PCR_ID_FMC_JOURNEY as u8); log_pcr(self.persistent_data, pcr_entry_id, pcr_ids, data) @@ -75,7 +75,7 @@ pub(crate) fn extend_pcrs( let mut pcr = PcrExtender { persistent_data: persistent_data.get_mut(), pcr_bank: env.pcr_bank, - sha384: env.sha384, + sha2_512_384: env.sha2_512_384, }; let device_status: [u8; 9] = [ diff --git a/rom/dev/src/rom_env.rs b/rom/dev/src/rom_env.rs index 78a0a29abd..9ab6e40d52 100644 --- a/rom/dev/src/rom_env.rs +++ b/rom/dev/src/rom_env.rs @@ -18,7 +18,7 @@ Abstract: use crate::fht::FhtDataStore; use caliptra_drivers::{ DataVault, DeobfuscationEngine, Ecc384, Hmac, KeyVault, Lms, Mailbox, Mldsa87, PcrBank, - PersistentDataAccessor, Sha1, Sha256, Sha2_512_384Acc, Sha384, SocIfc, Trng, + PersistentDataAccessor, Sha1, Sha256, Sha2_512_384, Sha2_512_384Acc, SocIfc, Trng, }; use caliptra_error::CaliptraResult; use caliptra_registers::{ @@ -38,8 +38,8 @@ pub struct RomEnv { // SHA2-256 Engine pub sha256: Sha256, - // SHA2-384 Engine - pub sha384: Sha384, + // SHA2-512/384 Engine + pub sha2_512_384: Sha2_512_384, // SHA2-512/384 Accelerator pub sha2_512_384_acc: Sha2_512_384Acc, @@ -94,7 +94,7 @@ impl RomEnv { doe: DeobfuscationEngine::new(DoeReg::new()), sha1: Sha1::default(), sha256: Sha256::new(Sha256Reg::new()), - sha384: Sha384::new(Sha512Reg::new()), + sha2_512_384: Sha2_512_384::new(Sha512Reg::new()), sha2_512_384_acc: Sha2_512_384Acc::new(Sha512AccCsr::new()), hmac: Hmac::new(HmacReg::new()), ecc384: Ecc384::new(EccReg::new()), diff --git a/runtime/src/authorize_and_stash.rs b/runtime/src/authorize_and_stash.rs index 9a1de26c0f..f3e48521c4 100644 --- a/runtime/src/authorize_and_stash.rs +++ b/runtime/src/authorize_and_stash.rs @@ -28,7 +28,7 @@ use caliptra_common::mailbox_api::{ use caliptra_drivers::{ pcr_log::PCR_ID_STASH_MEASUREMENT, Array4x12, Array4xN, AuthManifestImageMetadataList, CaliptraError, CaliptraResult, Ecc384, Ecc384PubKey, Ecc384Signature, HashValue, Lms, - PersistentData, RomPqcVerifyConfig, Sha256, Sha384, SocIfc, + PersistentData, RomPqcVerifyConfig, Sha256, Sha2_512_384, SocIfc, }; use caliptra_image_types::{ ImageDigest, ImageEccPubKey, ImageEccSignature, ImageLmsPublicKey, ImageLmsSignature, diff --git a/runtime/src/certify_key_extended.rs b/runtime/src/certify_key_extended.rs index 8c33768ad3..a426fb5a34 100644 --- a/runtime/src/certify_key_extended.rs +++ b/runtime/src/certify_key_extended.rs @@ -52,7 +52,7 @@ impl CertifyKeyExtendedCmd { let key_id_rt_priv_key = Drivers::get_key_id_rt_priv_key(drivers)?; let pdata = drivers.persistent_data.get_mut(); let crypto = DpeCrypto::new( - &mut drivers.sha384, + &mut drivers.sha2_512_384, &mut drivers.trng, &mut drivers.ecc384, &mut drivers.hmac, diff --git a/runtime/src/dpe_crypto.rs b/runtime/src/dpe_crypto.rs index 46f29b4996..01d8e32994 100644 --- a/runtime/src/dpe_crypto.rs +++ b/runtime/src/dpe_crypto.rs @@ -20,14 +20,14 @@ use caliptra_common::keyids::{KEY_ID_DPE_CDI, KEY_ID_DPE_PRIV_KEY, KEY_ID_TMP}; use caliptra_drivers::{ cprintln, hmac_kdf, Array4x12, Ecc384, Ecc384PrivKeyIn, Ecc384PubKey, Ecc384Scalar, Ecc384Seed, Hmac, HmacData, HmacKey, HmacMode, HmacTag, KeyId, KeyReadArgs, KeyUsage, KeyVault, - KeyWriteArgs, Sha384, Sha384DigestOp, Trng, + KeyWriteArgs, Sha2DigestOp, Sha2_512_384, Trng, }; use crypto::{AlgLen, Crypto, CryptoBuf, CryptoError, Digest, EcdsaPub, EcdsaSig, Hasher, HmacSig}; use zerocopy::AsBytes; use zeroize::Zeroize; pub struct DpeCrypto<'a> { - sha384: &'a mut Sha384, + sha2_512_384: &'a mut Sha2_512_384, trng: &'a mut Trng, ecc384: &'a mut Ecc384, hmac: &'a mut Hmac, @@ -40,7 +40,7 @@ pub struct DpeCrypto<'a> { impl<'a> DpeCrypto<'a> { #[allow(clippy::too_many_arguments)] pub fn new( - sha384: &'a mut Sha384, + sha2_512_384: &'a mut Sha2_512_384, trng: &'a mut Trng, ecc384: &'a mut Ecc384, hmac: &'a mut Hmac, @@ -50,7 +50,7 @@ impl<'a> DpeCrypto<'a> { key_id_rt_priv_key: KeyId, ) -> Self { Self { - sha384, + sha2_512_384, trng, ecc384, hmac, @@ -71,11 +71,11 @@ impl Drop for DpeCrypto<'_> { } pub struct DpeHasher<'a> { - op: Sha384DigestOp<'a>, + op: Sha2DigestOp<'a, 384>, } impl<'a> DpeHasher<'a> { - pub fn new(op: Sha384DigestOp<'a>) -> Self { + pub fn new(op: Sha2DigestOp<'a, 384>) -> Self { Self { op } } } @@ -121,8 +121,8 @@ impl<'a> Crypto for DpeCrypto<'a> { AlgLen::Bit256 => Err(CryptoError::Size), AlgLen::Bit384 => { let op = self - .sha384 - .digest_init() + .sha2_512_384 + .sha384_digest_init() .map_err(|e| CryptoError::HashError(u32::from(e)))?; Ok(DpeHasher::new(op)) } diff --git a/runtime/src/drivers.rs b/runtime/src/drivers.rs index 659be4b62b..293fa74488 100644 --- a/runtime/src/drivers.rs +++ b/runtime/src/drivers.rs @@ -33,8 +33,8 @@ use caliptra_drivers::{ DataVault, Ecc384, KeyVault, Lms, PersistentDataAccessor, Pic, ResetReason, Sha1, SocIfc, }; use caliptra_drivers::{ - hand_off::DataStore, Ecc384PubKey, Hmac, PcrBank, PcrId, Sha256, Sha256Alg, Sha2_512_384Acc, - Sha384, Trng, + hand_off::DataStore, Ecc384PubKey, Hmac, PcrBank, PcrId, Sha256, Sha256Alg, Sha2_512_384, + Sha2_512_384Acc, Trng, }; use caliptra_image_types::ImageManifest; use caliptra_registers::el2_pic_ctrl::El2PicCtrl; @@ -75,8 +75,8 @@ pub struct Drivers { pub soc_ifc: SocIfc, pub sha256: Sha256, - // SHA2-384 Engine - pub sha384: Sha384, + // SHA2-512/384 Engine + pub sha2_512_384: Sha2_512_384, // SHA2-512/384 Accelerator pub sha2_512_384_acc: Sha2_512_384Acc, @@ -131,7 +131,7 @@ impl Drivers { key_vault: KeyVault::new(KvReg::new()), soc_ifc: SocIfc::new(SocIfcReg::new()), sha256: Sha256::new(Sha256Reg::new()), - sha384: Sha384::new(Sha512Reg::new()), + sha2_512_384: Sha2_512_384::new(Sha512Reg::new()), sha2_512_384_acc: Sha2_512_384Acc::new(Sha512AccCsr::new()), hmac: Hmac::new(HmacReg::new()), ecc384: Ecc384::new(EccReg::new()), @@ -368,7 +368,7 @@ impl Drivers { const PAUSER_COUNT: usize = 5; let mbox_valid_pauser: [u32; PAUSER_COUNT] = drivers.soc_ifc.mbox_valid_pauser(); let mbox_pauser_lock: [bool; PAUSER_COUNT] = drivers.soc_ifc.mbox_pauser_lock(); - let mut digest_op = drivers.sha384.digest_init()?; + let mut digest_op = drivers.sha2_512_384.sha384_digest_init()?; for i in 0..PAUSER_COUNT { if mbox_pauser_lock[i] { digest_op.update(mbox_valid_pauser[i].as_bytes())?; @@ -381,7 +381,7 @@ impl Drivers { let key_id_rt_priv_key = Drivers::get_key_id_rt_priv_key(drivers)?; let pdata = drivers.persistent_data.get_mut(); let mut crypto = DpeCrypto::new( - &mut drivers.sha384, + &mut drivers.sha2_512_384, &mut drivers.trng, &mut drivers.ecc384, &mut drivers.hmac, diff --git a/runtime/src/fips.rs b/runtime/src/fips.rs index 0d963101c9..5768c17e25 100644 --- a/runtime/src/fips.rs +++ b/runtime/src/fips.rs @@ -20,8 +20,8 @@ use caliptra_drivers::Ecc384; use caliptra_drivers::Hmac; use caliptra_drivers::KeyVault; use caliptra_drivers::Sha256; +use caliptra_drivers::Sha2_512_384; use caliptra_drivers::Sha2_512_384Acc; -use caliptra_drivers::Sha384; use caliptra_registers::mbox::enums::MboxStatusE; use zeroize::Zeroize; @@ -40,7 +40,7 @@ impl FipsModule { Ecc384::zeroize(); Hmac::zeroize(); Sha256::zeroize(); - Sha384::zeroize(); + Sha2_512_384::zeroize(); Sha2_512_384Acc::zeroize(); // Zeroize the key vault. @@ -113,7 +113,7 @@ pub mod fips_self_test_cmd { let mut venv = FirmwareImageVerificationEnv { sha256: &mut env.sha256, - sha384: &mut env.sha384, + sha2_512_384: &mut env.sha2_512_384, soc_ifc: &mut env.soc_ifc, ecc384: &mut env.ecc384, data_vault: &mut env.data_vault, @@ -153,8 +153,8 @@ pub mod fips_self_test_cmd { // sha256 sha256: &mut env.sha256, - // SHA2-384 Engine - sha384: &mut env.sha384, + // SHA2-512/384 Engine + sha2_512_384: &mut env.sha2_512_384, // SHA2-512/384 Accelerator sha2_512_384_acc: &mut env.sha2_512_384_acc, diff --git a/runtime/src/hmac.rs b/runtime/src/hmac.rs index cffc7666ff..88e01b9257 100644 --- a/runtime/src/hmac.rs +++ b/runtime/src/hmac.rs @@ -152,7 +152,7 @@ impl Hmac { // Done in a closure to ensure state is always cleaned up. let hmac_result = || -> CaliptraResult { - let mut hasher = drivers.sha384.digest_init()?; + let mut hasher = drivers.sha2_512_384.sha384_digest_init()?; hasher.update(keypair.pub_key.x.as_bytes())?; hasher.update(keypair.pub_key.y.as_bytes())?; @@ -171,7 +171,7 @@ impl Hmac { }(); // Clean up state. - unsafe { caliptra_drivers::Sha384::zeroize() } + unsafe { caliptra_drivers::Sha2_512_384::zeroize() } pubkey_digest.zeroize(); keypair.pub_key.zeroize(); drivers.key_vault.erase_key(keypair.priv_key)?; diff --git a/runtime/src/invoke_dpe.rs b/runtime/src/invoke_dpe.rs index 0ee8773768..63c615bbdc 100644 --- a/runtime/src/invoke_dpe.rs +++ b/runtime/src/invoke_dpe.rs @@ -52,7 +52,7 @@ impl InvokeDpeCmd { let pdata = drivers.persistent_data.get_mut(); let crypto = DpeCrypto::new( - &mut drivers.sha384, + &mut drivers.sha2_512_384, &mut drivers.trng, &mut drivers.ecc384, &mut drivers.hmac, diff --git a/runtime/src/pcr.rs b/runtime/src/pcr.rs index 1cbd1a1875..4da78e0a49 100644 --- a/runtime/src/pcr.rs +++ b/runtime/src/pcr.rs @@ -51,7 +51,7 @@ impl GetPcrQuoteCmd { let args: QuotePcrsReq = QuotePcrsReq::read_from(cmd_bytes) .ok_or(CaliptraError::RUNTIME_MAILBOX_INVALID_PARAMS)?; - let pcr_hash = drivers.sha384.gen_pcr_hash(args.nonce.into())?; + let pcr_hash = drivers.sha2_512_384.gen_pcr_hash(args.nonce.into())?; let signature = drivers.ecc384.pcr_sign_flow(&mut drivers.trng)?; let raw_pcrs = drivers.pcr_bank.read_all_pcrs(); @@ -93,7 +93,7 @@ impl ExtendPcrCmd { drivers .pcr_bank - .extend_pcr(pcr_index, &mut drivers.sha384, &cmd.data)?; + .extend_pcr(pcr_index, &mut drivers.sha2_512_384, &cmd.data)?; Ok(MailboxResp::default()) } diff --git a/runtime/src/set_auth_manifest.rs b/runtime/src/set_auth_manifest.rs index 666f2c8f12..9c2d84a582 100644 --- a/runtime/src/set_auth_manifest.rs +++ b/runtime/src/set_auth_manifest.rs @@ -29,7 +29,7 @@ use caliptra_common::mailbox_api::{ use caliptra_drivers::{ pcr_log::PCR_ID_STASH_MEASUREMENT, Array4x12, Array4xN, AuthManifestImageMetadataList, CaliptraError, CaliptraResult, Ecc384, Ecc384PubKey, Ecc384Signature, HashValue, Lms, - PersistentData, RomPqcVerifyConfig, Sha256, Sha384, SocIfc, + PersistentData, RomPqcVerifyConfig, Sha256, Sha2_512_384, SocIfc, }; use caliptra_image_types::{ ImageDigest, ImageEccPubKey, ImageEccSignature, ImageLmsPublicKey, ImageLmsSignature, @@ -48,7 +48,7 @@ use zerocopy::{AsBytes, FromBytes}; pub struct SetAuthManifestCmd; impl SetAuthManifestCmd { fn sha384_digest( - sha384: &mut Sha384, + sha2: &mut Sha2_512_384, manifest: &[u8], offset: u32, len: u32, @@ -59,7 +59,7 @@ impl SetAuthManifestCmd { .ok_or(err)? .get(..len as usize) .ok_or(err)?; - Ok(sha384.digest(data)?.0) + Ok(sha2.sha384_digest(data)?.0) } fn ecc384_verify( @@ -99,14 +99,14 @@ impl SetAuthManifestCmd { fn verify_vendor_signed_data( auth_manifest_preamble: &AuthManifestPreamble, fw_preamble: &ImagePreamble, - sha384: &mut Sha384, + sha2: &mut Sha2_512_384, ecc384: &mut Ecc384, sha256: &mut Sha256, soc_ifc: &SocIfc, ) -> CaliptraResult<()> { let range = AuthManifestPreamble::vendor_signed_data_range(); let digest_vendor = Self::sha384_digest( - sha384, + sha2, auth_manifest_preamble.as_bytes(), range.start, range.len() as u32, @@ -156,14 +156,14 @@ impl SetAuthManifestCmd { fn verify_owner_pub_keys( auth_manifest_preamble: &AuthManifestPreamble, fw_preamble: &ImagePreamble, - sha384: &mut Sha384, + sha2: &mut Sha2_512_384, ecc384: &mut Ecc384, sha256: &mut Sha256, soc_ifc: &SocIfc, ) -> CaliptraResult<()> { let range = AuthManifestPreamble::owner_pub_keys_range(); let digest_owner = Self::sha384_digest( - sha384, + sha2, auth_manifest_preamble.as_bytes(), range.start, range.len() as u32, @@ -214,7 +214,7 @@ impl SetAuthManifestCmd { fn verify_vendor_image_metadata_col( auth_manifest_preamble: &AuthManifestPreamble, image_metadata_col_digest: &ImageDigest, - sha384: &mut Sha384, + sha2: &mut Sha2_512_384, ecc384: &mut Ecc384, sha256: &mut Sha256, soc_ifc: &SocIfc, @@ -275,7 +275,7 @@ impl SetAuthManifestCmd { fn verify_owner_image_metadata_col( auth_manifest_preamble: &AuthManifestPreamble, image_metadata_col_digest: &ImageDigest, - sha384: &mut Sha384, + sha2: &mut Sha2_512_384, ecc384: &mut Ecc384, sha256: &mut Sha256, soc_ifc: &SocIfc, @@ -334,7 +334,7 @@ impl SetAuthManifestCmd { cmd_buf: &[u8], auth_manifest_preamble: &AuthManifestPreamble, image_metadata_col: &mut AuthManifestImageMetadataCollection, - sha384: &mut Sha384, + sha2: &mut Sha2_512_384, ecc384: &mut Ecc384, sha256: &mut Sha256, soc_ifc: &SocIfc, @@ -359,12 +359,12 @@ impl SetAuthManifestCmd { Err(CaliptraError::RUNTIME_AUTH_MANIFEST_IMAGE_METADATA_LIST_INVALID_ENTRY_COUNT)?; } - let digest_metadata_col = Self::sha384_digest(sha384, buf, 0, col_size as u32)?; + let digest_metadata_col = Self::sha384_digest(sha2, buf, 0, col_size as u32)?; Self::verify_vendor_image_metadata_col( auth_manifest_preamble, &digest_metadata_col, - sha384, + sha2, ecc384, sha256, soc_ifc, @@ -373,7 +373,7 @@ impl SetAuthManifestCmd { Self::verify_owner_image_metadata_col( auth_manifest_preamble, &digest_metadata_col, - sha384, + sha2, ecc384, sha256, soc_ifc, @@ -433,7 +433,7 @@ impl SetAuthManifestCmd { Self::verify_vendor_signed_data( &auth_manifest_preamble, &persistent_data.manifest1.preamble, - &mut drivers.sha384, + &mut drivers.sha2_512_384, &mut drivers.ecc384, &mut drivers.sha256, &drivers.soc_ifc, @@ -443,7 +443,7 @@ impl SetAuthManifestCmd { Self::verify_owner_pub_keys( &auth_manifest_preamble, &persistent_data.manifest1.preamble, - &mut drivers.sha384, + &mut drivers.sha2_512_384, &mut drivers.ecc384, &mut drivers.sha256, &drivers.soc_ifc, @@ -455,7 +455,7 @@ impl SetAuthManifestCmd { .ok_or(CaliptraError::RUNTIME_AUTH_MANIFEST_IMAGE_METADATA_LIST_INVALID_SIZE)?, &auth_manifest_preamble, &mut persistent_data.auth_manifest_image_metadata_col, - &mut drivers.sha384, + &mut drivers.sha2_512_384, &mut drivers.ecc384, &mut drivers.sha256, &drivers.soc_ifc, diff --git a/runtime/src/stash_measurement.rs b/runtime/src/stash_measurement.rs index 12856259da..8d7b279f8c 100644 --- a/runtime/src/stash_measurement.rs +++ b/runtime/src/stash_measurement.rs @@ -54,7 +54,7 @@ impl StashMeasurementCmd { let key_id_rt_priv_key = Drivers::get_key_id_rt_priv_key(drivers)?; let pdata = drivers.persistent_data.get_mut(); let mut crypto = DpeCrypto::new( - &mut drivers.sha384, + &mut drivers.sha2_512_384, &mut drivers.trng, &mut drivers.ecc384, &mut drivers.hmac, @@ -106,7 +106,7 @@ impl StashMeasurementCmd { // Extend the measurement into PCR31 drivers.pcr_bank.extend_pcr( PCR_ID_STASH_MEASUREMENT, - &mut drivers.sha384, + &mut drivers.sha2_512_384, measurement.as_bytes(), )?; } diff --git a/runtime/test-fw/src/mbox_responder.rs b/runtime/test-fw/src/mbox_responder.rs index 39b85aeb4a..09b08fa391 100644 --- a/runtime/test-fw/src/mbox_responder.rs +++ b/runtime/test-fw/src/mbox_responder.rs @@ -118,7 +118,7 @@ pub fn handle_command(drivers: &mut Drivers) -> CaliptraResult { const PAUSER_COUNT: usize = 5; let mbox_valid_pauser: [u32; PAUSER_COUNT] = drivers.soc_ifc.mbox_valid_pauser(); let mbox_pauser_lock: [bool; PAUSER_COUNT] = drivers.soc_ifc.mbox_pauser_lock(); - let mut digest_op = drivers.sha384.digest_init().unwrap(); + let mut digest_op = drivers.sha2_512_384.sha384_digest_init().unwrap(); for i in 0..PAUSER_COUNT { if mbox_pauser_lock[i] { digest_op.update(mbox_valid_pauser[i].as_bytes()).unwrap(); @@ -130,7 +130,7 @@ pub fn handle_command(drivers: &mut Drivers) -> CaliptraResult { write_response(&mut drivers.mbox, valid_pauser_hash.as_bytes()); } CommandId(OPCODE_HASH_DPE_TCI_DATA) => { - let mut hasher = drivers.sha384.digest_init().unwrap(); + let mut hasher = drivers.sha2_512_384.sha384_digest_init().unwrap(); for context in drivers.persistent_data.get().dpe.contexts { if context.state != ContextState::Inactive { hasher.update(context.tci.tci_current.as_bytes()).unwrap(); From 1e238e5e87adbf32345dc3c853eed3f5aca0ccf9 Mon Sep 17 00:00:00 2001 From: Jeff Andersen Date: Tue, 26 Nov 2024 15:01:37 -0800 Subject: [PATCH 39/51] Populate LDevID CDI in the fake ROM boot flow. ROM will use the LDevID CDI to compute the firmware's hash chain. --- rom/dev/src/flow/fake.rs | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/rom/dev/src/flow/fake.rs b/rom/dev/src/flow/fake.rs index 091650c013..6ca822fd9d 100644 --- a/rom/dev/src/flow/fake.rs +++ b/rom/dev/src/flow/fake.rs @@ -26,6 +26,7 @@ use crate::print::HexBytes; use crate::rom_env::RomEnv; use caliptra_common::RomBootStatus::*; use caliptra_common::{ + keyids::KEY_ID_ROM_FMC_CDI, memory_layout::{FMCALIAS_TBS_ORG, FMCALIAS_TBS_SIZE, LDEVID_TBS_ORG, LDEVID_TBS_SIZE}, FirmwareHandoffTable, }; @@ -154,6 +155,8 @@ impl FakeRomFlow { // SKIP Execute IDEVID layer // LDEVID cert copy_canned_ldev_cert(env)?; + // LDEVID cdi + initialize_fake_ldevid_cdi(env)?; // Unlock the SHA Acc by creating a SHA Acc operation and dropping it. // In real ROM, this is done as part of executing the SHA-ACC KAT. @@ -187,6 +190,17 @@ impl FakeRomFlow { } } +// Used to derive the firmware's hash chain. +fn initialize_fake_ldevid_cdi(env: &mut RomEnv) -> CaliptraResult<()> { + env.hmac.hmac( + &HmacKey::Array4x12(&Array4x12::default()), + &HmacData::Slice(b""), + &mut env.trng, + KeyWriteArgs::new(KEY_ID_ROM_FMC_CDI, KeyUsage::default().set_hmac_key_en()).into(), + HmacMode::Hmac384, + ) +} + pub fn copy_canned_ldev_cert(env: &mut RomEnv) -> CaliptraResult<()> { // Store signature env.data_vault.set_ldev_dice_signature(&FAKE_LDEV_SIG); From 5d85868159f2f1f16df34d79d4d008cab5bba824 Mon Sep 17 00:00:00 2001 From: Christopher Swenson Date: Wed, 4 Dec 2024 13:31:41 -0800 Subject: [PATCH 40/51] emulator: Add Zba,Zbc,Zbs instruction sets (#1824) And enables support in code generation to use them. This saves X, Y, and Z bytes in the ROM, FMC, and Runtime, respectively. This has the negative side effect of making tests a little slower to run due to the quantity of macros used in generating all the test cases. This work extends the previous Zbb bit manipulation instruction set we supported to include the rest of the b family, all of which are supported by our VeeR CPU. We also add missing tests for the Zbb instruction set. --- .cargo/config | 3 + sw-emulator/lib/cpu/src/instr/bit.rs | 1701 +++++++++++++++++ sw-emulator/lib/cpu/src/instr/mod.rs | 1 + sw-emulator/lib/cpu/src/instr/op.rs | 42 +- sw-emulator/lib/cpu/src/instr/op_imm.rs | 134 +- sw-emulator/lib/cpu/src/instr/test_encoder.rs | 134 ++ sw-emulator/lib/cpu/src/instr/test_macros.rs | 715 +++++++ sw-emulator/lib/cpu/src/types.rs | 33 +- 8 files changed, 2628 insertions(+), 135 deletions(-) create mode 100644 sw-emulator/lib/cpu/src/instr/bit.rs diff --git a/.cargo/config b/.cargo/config index f7c588b097..073d01a90b 100644 --- a/.cargo/config +++ b/.cargo/config @@ -2,5 +2,8 @@ rustflags = [ "-C", "target-feature=+relax", "-C", "target-feature=+unaligned-scalar-mem", + "-C", "target-feature=+zba", "-C", "target-feature=+zbb", + "-C", "target-feature=+zbc", + "-C", "target-feature=+zbs", ] diff --git a/sw-emulator/lib/cpu/src/instr/bit.rs b/sw-emulator/lib/cpu/src/instr/bit.rs new file mode 100644 index 0000000000..a9f71b642b --- /dev/null +++ b/sw-emulator/lib/cpu/src/instr/bit.rs @@ -0,0 +1,1701 @@ +/*++ + +Licensed under the Apache-2.0 license. + +File Name: + + bit.rs + +Abstract: + + File contains implementation of bit manipulation instructions (Zba, Zbb, Zbc, Zbs). + +--*/ + +use crate::cpu::Cpu; +use crate::types::{RvInstr32I, RvInstr32OpFunct7, RvInstr32OpImmFunct7, RvInstr32R}; +use crate::xreg_file::XReg; +use caliptra_emu_bus::Bus; +use caliptra_emu_types::RvData; + +/// Carry-less multiply, low part +fn clmul(a: u32, b: u32) -> u32 { + let mut output = 0; + for i in 0..32 { + if (b >> i) & 1 == 1 { + output ^= a << i; + } + } + output +} + +/// Carry-less multiply, high part +fn clmulh(a: u32, b: u32) -> u32 { + let mut output = 0; + for i in 1..32 { + if (b >> i) & 1 == 1 { + output ^= a >> (32 - i); + } + } + output +} + +/// Carry-less multiply, reversed +fn clmulr(a: u32, b: u32) -> u32 { + let mut output = 0; + for i in 0..32 { + if (b >> i) & 1 == 1 { + output ^= a >> (32 - i - 1); + } + } + output +} + +impl Cpu { + /// If this matches a bit manipulation instruction, execute it and return Some(result). + /// Otherwise, return None. + pub(crate) fn exec_bit_instr_op( + &mut self, + instr: RvInstr32R, + val1: u32, + val2: u32, + ) -> Option { + // Decode the instruction + match (RvInstr32OpFunct7::from(instr.funct7()), instr.funct3()) { + // Shift 1 and Add, sh1add + (RvInstr32OpFunct7::Sh1add, 2) => Some(val1.wrapping_shl(1).wrapping_add(val2)), + // Shift 2 and Add, sh2add + (RvInstr32OpFunct7::Sh1add, 4) => Some(val1.wrapping_shl(2).wrapping_add(val2)), + // Shift 3 and Add, sh3add + (RvInstr32OpFunct7::Sh1add, 6) => Some(val1.wrapping_shl(3).wrapping_add(val2)), + // Bit Set, bset + (RvInstr32OpFunct7::Bset, 1) => Some(val1 | (1 << (val2 & 0x1f))), + // Single-Bit Invert, binv + (RvInstr32OpFunct7::Binv, 1) => Some(val1 ^ (1 << (val2 & 0x1f))), + // Bit Clear, bclr + (RvInstr32OpFunct7::Bclr, 1) => Some(val1 & !(1 << (val2 & 0x1f))), + // Bit Extract, bext + (RvInstr32OpFunct7::Bclr, 5) => Some((val1 >> (val2 & 0x1f)) & 1), + // Carry-less multiply low part, clmul + (RvInstr32OpFunct7::MinMaxClmul, 1) => Some(clmul(val1, val2)), + // Carry-less multiply high part, clmulh + (RvInstr32OpFunct7::MinMaxClmul, 3) => Some(clmulh(val1, val2)), + // Carry-less multiply reversed, clmulr + (RvInstr32OpFunct7::MinMaxClmul, 2) => Some(clmulr(val1, val2)), + // Maximum, max + (RvInstr32OpFunct7::MinMaxClmul, 6) => Some(i32::max(val1 as i32, val2 as i32) as u32), + // Maximum unsigned, maxu + (RvInstr32OpFunct7::MinMaxClmul, 7) => Some(u32::max(val1, val2)), + // Minimum, min + (RvInstr32OpFunct7::MinMaxClmul, 4) => Some(i32::min(val1 as i32, val2 as i32) as u32), + // Minimum unsigned, min + (RvInstr32OpFunct7::MinMaxClmul, 5) => Some(u32::min(val1, val2)), + // And Invert, andn + (RvInstr32OpFunct7::Andn, 7) => Some(val1 & !val2), + // Or Invert, orn + (RvInstr32OpFunct7::Orn, 6) => Some(val1 | !val2), + // Exclusive Nor, xnor + (RvInstr32OpFunct7::Xnor, 4) => Some(!(val1 ^ val2)), + // Zero-extend halfword, zext.h + (RvInstr32OpFunct7::Zext, 4) if instr.rs2() == XReg::X0 => Some(val1 & 0xffff), + // Rotate left, rol + (RvInstr32OpFunct7::Rotate, 1) => Some(val1.rotate_left(val2 & 0x1f)), + // Rotate right, ror + (RvInstr32OpFunct7::Rotate, 5) => Some(val1.rotate_right(val2 & 0x1f)), + _ => None, + } + } + pub(crate) fn exec_bit_instr_op_imm(&mut self, instr: RvInstr32I, reg: u32) -> Option { + // Decode the instruction + let imm = instr.imm(); + match (RvInstr32OpImmFunct7::from(instr.funct7()), instr.funct3()) { + // Bit Set Immediate, bseti + (RvInstr32OpImmFunct7::Orc, 1) => Some(reg | (1 << (imm & 0x1f))), + // Bitwise OR-Combine byte granule, orc.b + (RvInstr32OpImmFunct7::Orc, 5) if instr.funct5() == 0b0_0111 => { + let reg_bytes = reg.to_le_bytes(); + Some(u32::from_le_bytes(core::array::from_fn(|i| { + if reg_bytes[i] != 0 { + 0xff + } else { + 0x00 + } + }))) + } + // Single-Bit Invert Immediate, bseti + (RvInstr32OpImmFunct7::Rev8, 1) => Some(reg ^ (1 << (imm & 0x1f))), + // Bit Clear Immediate, bclri + (RvInstr32OpImmFunct7::Bclr, 1) => Some(reg & !(1 << (imm & 0x1f))), + // Bit Extract Immediate, bexti + (RvInstr32OpImmFunct7::Bclr, 5) => Some((reg >> (imm & 0x1f)) & 1), + // Rotate Right Immediate, rori + (RvInstr32OpImmFunct7::Bitmanip, 5) => Some(reg.rotate_right(instr.shamt())), + // Count leading zeroes, clz + (RvInstr32OpImmFunct7::Bitmanip, 1) if instr.funct5() == 0b0_0000 => { + Some(reg.leading_zeros()) + } + // Count trailing zeroes, ctz + (RvInstr32OpImmFunct7::Bitmanip, 1) if instr.funct5() == 0b0_0001 => { + Some(reg.trailing_zeros()) + } + // Count set bits, cpop + (RvInstr32OpImmFunct7::Bitmanip, 1) if instr.funct5() == 0b0_0010 => { + Some(reg.count_ones()) + } + // Sign-extend byte, sext.b + (RvInstr32OpImmFunct7::Bitmanip, 1) if instr.funct5() == 0b0_0100 => { + Some(reg as i8 as i32 as u32) + } + // Sign-extend halfword, sext.h + (RvInstr32OpImmFunct7::Bitmanip, 1) if instr.funct5() == 0b0_0101 => { + Some(reg as i16 as i32 as u32) + } + // Byte-reverse register + (RvInstr32OpImmFunct7::Rev8, 5) if instr.funct5() == 0b1_1000 => Some(reg.swap_bytes()), + _ => None, + } + } +} + +#[cfg(test)] +#[allow(clippy::identity_op)] +#[rustfmt::skip] +mod tests { + use crate::{ + test_imm_dest_bypass, test_imm_op, test_imm_src1_bypass, test_imm_src1_eq_dest, test_imm_zero_dest, test_imm_zero_src1, test_r_dest_bypass, test_r_op, test_r_src1_eq_dest, test_rr_dest_bypass, test_rr_op, test_rr_src12_bypass, test_rr_src12_eq_dest, test_rr_src1_eq_dest, test_rr_src21_bypass, test_rr_src2_eq_dest, test_rr_zerodest, test_rr_zerosrc1, test_rr_zerosrc12, test_rr_zerosrc2 + }; + + // --------------------------------------------------------------------------------------------- + // Tests for Shift 1 Add (`sh1add`) Instruction + // + // Test suite based on riscv-tests + // https://github.com/riscv-software-src/riscv-tests/blob/master/isa/rv32uzba/sh1add.S + // --------------------------------------------------------------------------------------------- + test_rr_op!(test_sh1add_2, sh1add, 0x0000_0000, 0x0000_0000, 0x0000_0000); + test_rr_op!(test_sh1add_3, sh1add, 0x0000_0003, 0x0000_0001, 0x0000_0001); + test_rr_op!(test_sh1add_4, sh1add, 0x0000_000d, 0x0000_0003, 0x0000_0007); + test_rr_op!(test_sh1add_5, sh1add, 0xffff_8000, 0x0000_0000, 0xffff_8000); + test_rr_op!(test_sh1add_6, sh1add, 0x0000_0000, 0x8000_0000, 0x0000_0000); + test_rr_op!(test_sh1add_7, sh1add, 0xffff_8000, 0x8000_0000, 0xffff_8000); + test_rr_op!(test_sh1add_8, sh1add, 0x0000_7fff, 0x0000_0000, 0x0000_7fff); + test_rr_op!(test_sh1add_9, sh1add, 0xffff_fffe, 0x7fff_ffff, 0x0000_0000); + test_rr_op!(test_sh1add_10, sh1add, 0x0000_7ffd, 0x7fff_ffff, 0x0000_7fff); + test_rr_op!(test_sh1add_11, sh1add, 0x0000_7fff, 0x8000_0000, 0x0000_7fff); + test_rr_op!(test_sh1add_12, sh1add, 0xffff_7ffe, 0x7fff_ffff, 0xffff_8000); + test_rr_op!(test_sh1add_13, sh1add, 0xffff_ffff, 0x0000_0000, 0xffff_ffff); + test_rr_op!(test_sh1add_14, sh1add, 0xffff_ffff, 0xffff_ffff, 0x0000_0001); + test_rr_op!(test_sh1add_15, sh1add, 0xffff_fffd, 0xffff_ffff, 0xffff_ffff); + test_rr_op!(test_sh1add_16, sh1add, 0x8000_0001, 0x0000_0001, 0x7fff_ffff); + + test_rr_src1_eq_dest!(test_sh1add_17, sh1add, 37, 13, 11); + test_rr_src2_eq_dest!(test_sh1add_18, sh1add, 39, 14, 11); + test_rr_src12_eq_dest!(test_sh1add_19, sh1add, 39, 13); + + test_rr_dest_bypass!(test_sh1add_20, 0 , sh1add, 37, 13, 11); + test_rr_dest_bypass!(test_sh1add_21, 1 , sh1add, 39, 14, 11); + test_rr_dest_bypass!(test_sh1add_22, 2 , sh1add, 41, 15, 11); + + test_rr_src12_bypass!(test_sha1add_23, 0, 0, sh1add, 37, 13, 11); + test_rr_src12_bypass!(test_sha1add_24, 0, 1, sh1add, 39, 14, 11); + test_rr_src12_bypass!(test_sha1add_25, 0, 2, sh1add, 41, 15, 11); + test_rr_src12_bypass!(test_sha1add_26, 1, 0, sh1add, 37, 13, 11); + test_rr_src12_bypass!(test_sha1add_27, 1, 1, sh1add, 39, 14, 11); + test_rr_src12_bypass!(test_sha1add_28, 2, 0, sh1add, 41, 15, 11); + + test_rr_src21_bypass!(test_sha1add_29, 0, 0, sh1add, 37, 13, 11); + test_rr_src21_bypass!(test_sha1add_30, 0, 1, sh1add, 39, 14, 11); + test_rr_src21_bypass!(test_sha1add_31, 0, 2, sh1add, 41, 15, 11); + test_rr_src21_bypass!(test_sha1add_32, 1, 0, sh1add, 37, 13, 11); + test_rr_src21_bypass!(test_sha1add_33, 1, 1, sh1add, 39, 14, 11); + test_rr_src21_bypass!(test_sha1add_34, 2, 0, sh1add, 41, 15, 11); + + test_rr_zerosrc1!(test_sh1add_35, sh1add, 15, 15); + test_rr_zerosrc2!(test_sh1add_36, sh1add, 64, 32); + test_rr_zerosrc12!(test_sh1add_37, sh1add, 0); + test_rr_zerodest!(test_sh1add_38, sh1add, 16, 30); + + // --------------------------------------------------------------------------------------------- + // Tests for Shift 2 Add (`sh2add`) Instruction + // + // Test suite based on riscv-tests + // https://github.com/riscv-software-src/riscv-tests/blob/master/isa/rv32uzba/sh2add.S + // --------------------------------------------------------------------------------------------- + + test_rr_op!(test_sh2add_2, sh2add, 0x00000000, 0x00000000, 0x00000000); + test_rr_op!(test_sh2add_3, sh2add, 0x00000005, 0x00000001, 0x00000001); + test_rr_op!(test_sh2add_4, sh2add, 0x00000013, 0x00000003, 0x00000007); + + test_rr_op!(test_sh2add_5, sh2add, 0xffff8000, 0x00000000, 0xffff8000); + test_rr_op!(test_sh2add_6, sh2add, 0x00000000, 0x80000000, 0x00000000); + test_rr_op!(test_sh2add_7, sh2add, 0xffff8000, 0x80000000, 0xffff8000); + + test_rr_op!(test_sh2add_8, sh2add, 0x00007fff, 0x00000000, 0x00007fff); + test_rr_op!(test_sh2add_9, sh2add, 0xfffffffc, 0x7fffffff, 0x00000000); + test_rr_op!(test_sh2add_10, sh2add, 0x00007ffb, 0x7fffffff, 0x00007fff); + + test_rr_op!(test_sh2add_11, sh2add, 0x00007fff, 0x80000000, 0x00007fff); + test_rr_op!(test_sh2add_12, sh2add, 0xffff7ffc, 0x7fffffff, 0xffff8000); + + test_rr_op!(test_sh2add_13, sh2add, 0xffffffff, 0x00000000, 0xffffffff); + test_rr_op!(test_sh2add_14, sh2add, 0xfffffffd, 0xffffffff, 0x00000001); + test_rr_op!(test_sh2add_15, sh2add, 0xfffffffb, 0xffffffff, 0xffffffff); + + test_rr_op!(test_sh2add_16, sh2add, 0x80000003, 0x00000001, 0x7fffffff); + + test_rr_src1_eq_dest!(test_sh2add_17, sh2add, 63, 13, 11); + test_rr_src2_eq_dest!(test_sh2add_18, sh2add, 67, 14, 11); + test_rr_src12_eq_dest!(test_sh2add_19, sh2add, 65, 13); + + test_rr_dest_bypass!(test_sh2add_20, 0, sh2add, 63, 13, 11); + test_rr_dest_bypass!(test_sh2add_21, 1, sh2add, 67, 14, 11); + test_rr_dest_bypass!(test_sh2add_22, 2, sh2add, 71, 15, 11); + + test_rr_src12_bypass!(test_sh2add_23, 0, 0, sh2add, 63, 13, 11); + test_rr_src12_bypass!(test_sh2add_24, 0, 1, sh2add, 67, 14, 11); + test_rr_src12_bypass!(test_sh2add_25, 0, 2, sh2add, 71, 15, 11); + test_rr_src12_bypass!(test_sh2add_26, 1, 0, sh2add, 63, 13, 11); + test_rr_src12_bypass!(test_sh2add_27, 1, 1, sh2add, 67, 14, 11); + test_rr_src12_bypass!(test_sh2add_28, 2, 0, sh2add, 71, 15, 11); + + test_rr_src21_bypass!(test_sh2add_29, 0, 0, sh2add, 63, 13, 11); + test_rr_src21_bypass!(test_sh2add_30, 0, 1, sh2add, 67, 14, 11); + test_rr_src21_bypass!(test_sh2add_31, 0, 2, sh2add, 71, 15, 11); + test_rr_src21_bypass!(test_sh2add_32, 1, 0, sh2add, 63, 13, 11); + test_rr_src21_bypass!(test_sh2add_33, 1, 1, sh2add, 67, 14, 11); + test_rr_src21_bypass!(test_sh2add_34, 2, 0, sh2add, 71, 15, 11); + + test_rr_zerosrc1!(test_sh2add_35, sh2add, 15, 15); + test_rr_zerosrc2!(test_sh2add_36, sh2add, 128, 32); + test_rr_zerosrc12!(test_sh2add_37, sh2add, 0); + test_rr_zerodest!(test_sh2add_38, sh2add, 16, 30); + + // --------------------------------------------------------------------------------------------- + // Tests for Shift 3 Add (`sh3add`) Instruction + // + // Test suite based on riscv-tests + // https://github.com/riscv-software-src/riscv-tests/blob/master/isa/rv32uzba/sh3add.S + // --------------------------------------------------------------------------------------------- + + test_rr_op!(test_sh3add_2, sh3add, 0x00000000, 0x00000000, 0x00000000); + test_rr_op!(test_sh3add_3, sh3add, 0x00000009, 0x00000001, 0x00000001); + test_rr_op!(test_sh3add_4, sh3add, 0x0000001f, 0x00000003, 0x00000007); + + test_rr_op!(test_sh3add_5, sh3add, 0xffff8000, 0x00000000, 0xffff8000); + test_rr_op!(test_sh3add_6, sh3add, 0x00000000, 0x80000000, 0x00000000); + test_rr_op!(test_sh3add_7, sh3add, 0xffff8000, 0x80000000, 0xffff8000); + + test_rr_op!(test_sh3add_8, sh3add, 0x00007fff, 0x00000000, 0x00007fff); + test_rr_op!(test_sh3add_9, sh3add, 0xfffffff8, 0x7fffffff, 0x00000000); + test_rr_op!(test_sh3add_10, sh3add, 0x00007ff7, 0x7fffffff, 0x00007fff); + + test_rr_op!(test_sh3add_11, sh3add, 0x00007fff, 0x80000000, 0x00007fff); + test_rr_op!(test_sh3add_12, sh3add, 0xffff7ff8, 0x7fffffff, 0xffff8000); + + test_rr_op!(test_sh3add_13, sh3add, 0xffffffff, 0x00000000, 0xffffffff); + test_rr_op!(test_sh3add_14, sh3add, 0xfffffff9, 0xffffffff, 0x00000001); + test_rr_op!(test_sh3add_15, sh3add, 0xfffffff7, 0xffffffff, 0xffffffff); + + test_rr_op!(test_sh3add_16, sh3add, 0x80000007, 0x00000001, 0x7fffffff); + + test_rr_src1_eq_dest!(test_sh3add_17, sh3add, 115, 13, 11); + test_rr_src2_eq_dest!(test_sh3add_18, sh3add, 123, 14, 11); + test_rr_src12_eq_dest!(test_sh3add_19, sh3add, 117, 13); + + test_rr_dest_bypass!(test_sh3add_20, 0, sh3add, 115, 13, 11); + test_rr_dest_bypass!(test_sh3add_21, 1, sh3add, 123, 14, 11); + test_rr_dest_bypass!(test_sh3add_22, 2, sh3add, 131, 15, 11); + + test_rr_src12_bypass!(test_sh3add_23, 0, 0, sh3add, 115, 13, 11); + test_rr_src12_bypass!(test_sh3add_24, 0, 1, sh3add, 123, 14, 11); + test_rr_src12_bypass!(test_sh3add_25, 0, 2, sh3add, 131, 15, 11); + test_rr_src12_bypass!(test_sh3add_26, 1, 0, sh3add, 115, 13, 11); + test_rr_src12_bypass!(test_sh3add_27, 1, 1, sh3add, 123, 14, 11); + test_rr_src12_bypass!(test_sh3add_28, 2, 0, sh3add, 131, 15, 11); + + test_rr_src21_bypass!(test_sh3add_29, 0, 0, sh3add, 115, 13, 11); + test_rr_src21_bypass!(test_sh3add_30, 0, 1, sh3add, 123, 14, 11); + test_rr_src21_bypass!(test_sh3add_31, 0, 2, sh3add, 131, 15, 11); + test_rr_src21_bypass!(test_sh3add_32, 1, 0, sh3add, 115, 13, 11); + test_rr_src21_bypass!(test_sh3add_33, 1, 1, sh3add, 123, 14, 11); + test_rr_src21_bypass!(test_sh3add_34, 2, 0, sh3add, 131, 15, 11); + + test_rr_zerosrc1!(test_sh3add_35, sh3add, 15, 15); + test_rr_zerosrc2!(test_sh3add_36, sh3add, 256, 32); + test_rr_zerosrc12!(test_sh3add_37, sh3add, 0); + test_rr_zerodest!(test_sh3add_38, sh3add, 16, 30); + + // --------------------------------------------------------------------------------------------- + // Tests for Bit Set (`bset`) Instruction + // + // Test suite based on riscv-tests + // https://github.com/riscv-software-src/riscv-tests/blob/master/isa/rv64uzbs/bset.S + // --------------------------------------------------------------------------------------------- + + test_rr_op!(test_bset_2, bset, 0xff00ff01, 0xff00ff00, 0); + test_rr_op!(test_bset_3, bset, 0x00ff00ff, 0x00ff00ff, 1); + test_rr_op!(test_bset_4, bset, 0xff00ff00, 0xff00ff00, 8); + test_rr_op!(test_bset_5, bset, 0x0ff04ff0, 0x0ff00ff0, 14); + test_rr_op!(test_bset_6, bset, 0x0ff00ff0, 0x0ff00ff0, 27); + + test_rr_op!(test_bset_7, bset, 0x00000001, 0x00000001, 0); + test_rr_op!(test_bset_8, bset, 0x00000003, 0x00000001, 1); + test_rr_op!(test_bset_9, bset, 0x00000081, 0x00000001, 7); + test_rr_op!(test_bset_10, bset, 0x00004001, 0x00000001, 14); + test_rr_op!(test_bset_11, bset, 0x80000001, 0x00000001, 31); + + test_rr_op!(test_bset_12, bset, 0x21212121, 0x21212121, 0); + test_rr_op!(test_bset_13, bset, 0x21212123, 0x21212121, 1); + test_rr_op!(test_bset_14, bset, 0x212121a1, 0x21212121, 7); + test_rr_op!(test_bset_15, bset, 0x21212121, 0x21212121, 13); + test_rr_op!(test_bset_16, bset, 0x84848484, 0x84848484, 31); + + test_rr_op!(test_bset_17, bset, 0x21212121, 0x21212121, 0xffffffc0); + test_rr_op!(test_bset_18, bset, 0x21212123, 0x21212121, 0xffffffc1); + test_rr_op!(test_bset_19, bset, 0x212121a1, 0x21212121, 0xffffffc7); + test_rr_op!(test_bset_20, bset, 0x8484c484, 0x84848484, 0xffffffce); + + test_rr_src1_eq_dest!(test_bset_22, bset, 0x00000081, 0x00000001, 7); + test_rr_src2_eq_dest!(test_bset_23, bset, 0x00005551, 0x00005551, 14); + test_rr_src12_eq_dest!(test_bset_24, bset, 11, 3); + + test_rr_dest_bypass!(test_bset_25, 0, bset, 0xff00ff01, 0xff00ff00, 0); + test_rr_dest_bypass!(test_bset_26, 1, bset, 0x00ff00ff, 0x00ff00ff, 1); + test_rr_dest_bypass!(test_bset_27, 2, bset, 0xff00ff00, 0xff00ff00, 8); + + test_rr_src12_bypass!(test_bset_28, 0, 0, bset, 0xff00ff01, 0xff00ff00, 0); + test_rr_src12_bypass!(test_bset_29, 0, 1, bset, 0x00ff00ff, 0x00ff00ff, 1); + test_rr_src12_bypass!(test_bset_30, 0, 2, bset, 0xff00ff00, 0xff00ff00, 8); + test_rr_src12_bypass!(test_bset_31, 1, 0, bset, 0xff00ff01, 0xff00ff00, 0); + test_rr_src12_bypass!(test_bset_32, 1, 1, bset, 0x00ff00ff, 0x00ff00ff, 1); + test_rr_src12_bypass!(test_bset_33, 2, 0, bset, 0xff00ff00, 0xff00ff00, 8); + + test_rr_src21_bypass!(test_bset_34, 0, 0, bset, 0xff00ff00, 0xff00ff00, 8); + test_rr_src21_bypass!(test_bset_35, 0, 1, bset, 0x0ff04ff0, 0x0ff00ff0, 14); + test_rr_src21_bypass!(test_bset_36, 0, 2, bset, 0x0ff00ff0, 0x0ff00ff0, 27); + test_rr_src21_bypass!(test_bset_37, 1, 0, bset, 0xff00ff00, 0xff00ff00, 8); + test_rr_src21_bypass!(test_bset_38, 1, 1, bset, 0x0ff04ff0, 0x0ff00ff0, 14); + test_rr_src21_bypass!(test_bset_39, 2, 0, bset, 0x0ff00ff0, 0x0ff00ff0, 27); + + test_rr_zerosrc1!(test_bset_40, bset, 0x00008000, 15); + test_rr_zerosrc2!(test_bset_41, bset, 33, 32); + test_rr_zerosrc12!(test_bset_42, bset, 1); + test_rr_zerodest!(test_bset_43, bset, 1024, 2048); + + // --------------------------------------------------------------------------------------------- + // Tests for Bit Clear (`bclr`) Instruction + // + // Test suite based on riscv-tests + // https://github.com/riscv-software-src/riscv-tests/blob/master/isa/rv64uzbs/bclr.S + // --------------------------------------------------------------------------------------------- + + test_rr_op!(test_bclr_2, bclr, 0xff00ff00, 0xff00ff00, 0); + test_rr_op!(test_bclr_3, bclr, 0x00ff00fd, 0x00ff00ff, 1); + test_rr_op!(test_bclr_4, bclr, 0xff00fe00, 0xff00ff00, 8); + test_rr_op!(test_bclr_5, bclr, 0x0ff00ff0, 0x0ff00ff0, 14); + test_rr_op!(test_bclr_6, bclr, 0x07f00ff0, 0x0ff00ff0, 27); + + test_rr_op!(test_bclr_7, bclr, 0xfffffffe, 0xffffffff, 0); + test_rr_op!(test_bclr_8, bclr, 0xfffffffd, 0xffffffff, 1); + test_rr_op!(test_bclr_9, bclr, 0xffffff7f, 0xffffffff, 7); + test_rr_op!(test_bclr_10, bclr, 0xffffbfff, 0xffffffff, 14); + test_rr_op!(test_bclr_11, bclr, 0xf7ffffff, 0xffffffff, 27); + + test_rr_op!(test_bclr_12, bclr, 0x21212120, 0x21212121, 0); + test_rr_op!(test_bclr_13, bclr, 0x21212121, 0x21212121, 1); + test_rr_op!(test_bclr_14, bclr, 0x21212121, 0x21212121, 7); + test_rr_op!(test_bclr_15, bclr, 0x21210121, 0x21212121, 13); + test_rr_op!(test_bclr_16, bclr, 0x04848484, 0x84848484, 31); + + // Verify that shifts only use bottom five (rv32) bits + + test_rr_op!(test_bclr_17, bclr, 0x21212120, 0x21212121, 0xffffffc0); + test_rr_op!(test_bclr_18, bclr, 0x21212121, 0x21212121, 0xffffffc1); + test_rr_op!(test_bclr_19, bclr, 0x21212121, 0x21212121, 0xffffffc7); + test_rr_op!(test_bclr_20, bclr, 0x84848484, 0x84848484, 0xffffffce); + + test_rr_src1_eq_dest!(test_bclr_22, bclr, 0x00000001, 0x00000001, 7); + test_rr_src2_eq_dest!(test_bclr_23, bclr, 0x00001551, 0x00005551, 14); + test_rr_src12_eq_dest!(test_bclr_24, bclr, 3, 3); + + test_rr_dest_bypass!(test_bclr_25, 0, bclr, 0xff00ff00, 0xff00ff00, 0); + test_rr_dest_bypass!(test_bclr_26, 1, bclr, 0x00ff00fd, 0x00ff00ff, 1); + test_rr_dest_bypass!(test_bclr_27, 2, bclr, 0xff00fe00, 0xff00ff00, 8); + + test_rr_src12_bypass!(test_bclr_28, 0, 0, bclr, 0xff00ff00, 0xff00ff00, 0); + test_rr_src12_bypass!(test_bclr_29, 0, 1, bclr, 0x00ff00fd, 0x00ff00ff, 1); + test_rr_src12_bypass!(test_bclr_30, 0, 2, bclr, 0xff00fe00, 0xff00ff00, 8); + test_rr_src12_bypass!(test_bclr_31, 1, 0, bclr, 0xff00ff00, 0xff00ff00, 0); + test_rr_src12_bypass!(test_bclr_32, 1, 1, bclr, 0x00ff00fd, 0x00ff00ff, 1); + test_rr_src12_bypass!(test_bclr_33, 2, 0, bclr, 0xff00fe00, 0xff00ff00, 8); + + test_rr_src21_bypass!(test_bclr_34, 0, 0, bclr, 0xff00fe00, 0xff00ff00, 8); + test_rr_src21_bypass!(test_bclr_35, 0, 1, bclr, 0x0ff00ff0, 0x0ff00ff0, 14); + test_rr_src21_bypass!(test_bclr_36, 0, 2, bclr, 0x07f00ff0, 0x0ff00ff0, 27); + test_rr_src21_bypass!(test_bclr_37, 1, 0, bclr, 0xff00fe00, 0xff00ff00, 8); + test_rr_src21_bypass!(test_bclr_38, 1, 1, bclr, 0x0ff00ff0, 0x0ff00ff0, 14); + test_rr_src21_bypass!(test_bclr_39, 2, 0, bclr, 0x07f00ff0, 0x0ff00ff0, 27); + + test_rr_zerosrc1!(test_bclr_40, bclr, 0, 15); + test_rr_zerosrc2!(test_bclr_41, bclr, 32, 32); + test_rr_zerosrc12!(test_bclr_42, bclr, 0); + test_rr_zerodest!(test_bclr_43, bclr, 1024, 2048); + + // --------------------------------------------------------------------------------------------- + // Tests for Bit Extract (`bext`) Instruction + // + // Test suite based on riscv-tests + // https://github.com/riscv-software-src/riscv-tests/blob/master/isa/rv64uzbs/bext.S + // --------------------------------------------------------------------------------------------- + + test_rr_op!(test_bext_2, bext, 0, 0xff00ff00, 0); + test_rr_op!(test_bext_3, bext, 1, 0x00ff00ff, 1); + test_rr_op!(test_bext_4, bext, 1, 0xff00ff00, 8); + test_rr_op!(test_bext_5, bext, 0, 0x0ff00ff0, 14); + test_rr_op!(test_bext_6, bext, 1, 0x0ff00ff0, 27); + + test_rr_op!(test_bext_7, bext, 1, 0xffffffff, 0); + test_rr_op!(test_bext_8, bext, 1, 0xffffffff, 1); + test_rr_op!(test_bext_9, bext, 1, 0xffffffff, 7); + test_rr_op!(test_bext_10, bext, 1, 0xffffffff, 14); + test_rr_op!(test_bext_11, bext, 1, 0xffffffff, 27); + + test_rr_op!(test_bext_12, bext, 1, 0x21212121, 0); + test_rr_op!(test_bext_13, bext, 0, 0x21212121, 1); + test_rr_op!(test_bext_14, bext, 0, 0x21212121, 7); + test_rr_op!(test_bext_15, bext, 1, 0x21212121, 13); + test_rr_op!(test_bext_16, bext, 1, 0x84848484, 31); + + // Verify that shifts only use bottom five bits + + test_rr_op!(test_bext_17, bext, 1, 0x21212121, 0xffffffc0); + test_rr_op!(test_bext_18, bext, 0, 0x21212121, 0xffffffc1); + test_rr_op!(test_bext_19, bext, 0, 0x21212121, 0xffffffc7); + test_rr_op!(test_bext_20, bext, 0, 0x84848484, 0xffffffce); + + test_rr_src1_eq_dest!(test_bext_22, bext, 0, 0x00000001, 7); + test_rr_src2_eq_dest!(test_bext_23, bext, 1, 0x00005551, 14); + test_rr_src12_eq_dest!(test_bext_24, bext, 0, 3); + + test_rr_dest_bypass!(test_bext_25, 0, bext, 0, 0xff00ff00, 0); + test_rr_dest_bypass!(test_bext_26, 1, bext, 1, 0x00ff00ff, 1); + test_rr_dest_bypass!(test_bext_27, 2, bext, 1, 0xff00ff00, 8); + + test_rr_src12_bypass!(test_bext_28, 0, 0, bext, 0, 0xff00ff00, 0); + test_rr_src12_bypass!(test_bext_29, 0, 1, bext, 1, 0x00ff00ff, 1); + test_rr_src12_bypass!(test_bext_30, 0, 2, bext, 1, 0xff00ff00, 8); + test_rr_src12_bypass!(test_bext_31, 1, 0, bext, 0, 0xff00ff00, 0); + test_rr_src12_bypass!(test_bext_32, 1, 1, bext, 1, 0x00ff00ff, 1); + test_rr_src12_bypass!(test_bext_33, 2, 0, bext, 1, 0xff00ff00, 8); + + test_rr_src21_bypass!(test_bext_34, 0, 0, bext, 1, 0xff00ff00, 8); + test_rr_src21_bypass!(test_bext_35, 0, 1, bext, 0, 0x0ff00ff0, 14); + test_rr_src21_bypass!(test_bext_36, 0, 2, bext, 1, 0x0ff00ff0, 27); + test_rr_src21_bypass!(test_bext_37, 1, 0, bext, 1, 0xff00ff00, 8); + test_rr_src21_bypass!(test_bext_38, 1, 1, bext, 0, 0x0ff00ff0, 14); + test_rr_src21_bypass!(test_bext_39, 2, 0, bext, 1, 0x0ff00ff0, 27); + + test_rr_zerosrc1!(test_bext_40, bext, 0, 15); + test_rr_zerosrc2!(test_bext_41, bext, 0, 32); + test_rr_zerosrc12!(test_bext_42, bext, 0); + test_rr_zerodest!(test_bext_43, bext, 1024, 2048); + + // --------------------------------------------------------------------------------------------- + // Tests for Bit Set Immediate (`bseti`) Instruction + // + // Test suite based on riscv-tests + // https://github.com/riscv-software-src/riscv-tests/blob/master/isa/rv64uzbs/bseti.S + // --------------------------------------------------------------------------------------------- + + test_imm_op!(test_bseti_2, bseti, 0xff00ff01, 0xff00ff00, 0); + test_imm_op!(test_bseti_3, bseti, 0x00ff00ff, 0x00ff00ff, 1); + test_imm_op!(test_bseti_4, bseti, 0xff00ff00, 0xff00ff00, 8); + test_imm_op!(test_bseti_5, bseti, 0x0ff04ff0, 0x0ff00ff0, 14); + test_imm_op!(test_bseti_6, bseti, 0x0ff00ff0, 0x0ff00ff0, 27); + + test_imm_op!(test_bseti_7, bseti, 0x00000001, 0x00000001, 0); + test_imm_op!(test_bseti_8, bseti, 0x00000003, 0x00000001, 1); + test_imm_op!(test_bseti_9, bseti, 0x00000081, 0x00000001, 7); + test_imm_op!(test_bseti_10, bseti, 0x00004001, 0x00000001, 14); + test_imm_op!(test_bseti_11, bseti, 0x80000001, 0x00000001, 31); + + test_imm_op!(test_bseti_12, bseti, 0x21212121, 0x21212121, 0); + test_imm_op!(test_bseti_13, bseti, 0x21212123, 0x21212121, 1); + test_imm_op!(test_bseti_14, bseti, 0x212121a1, 0x21212121, 7); + test_imm_op!(test_bseti_15, bseti, 0x21212121, 0x21212121, 13); + test_imm_op!(test_bseti_16, bseti, 0x84848484, 0x84848484, 31); + + test_imm_src1_eq_dest!(test_bseti_17, bseti, 0x00000081, 0x00000001, 7); + + test_imm_dest_bypass!(test_bseti_18, 0, bseti, 0xff00ff01, 0xff00ff00, 0); + test_imm_dest_bypass!(test_bseti_19, 1, bseti, 0x00ff00ff, 0x00ff00ff, 1); + test_imm_dest_bypass!(test_bseti_20, 2, bseti, 0xff00ff00, 0xff00ff00, 8); + + test_imm_src1_bypass!(test_bseti_21, 0, bseti, 0xff00ff00, 0xff00ff00, 8); + test_imm_src1_bypass!(test_bseti_22, 1, bseti, 0x0ff04ff0, 0x0ff00ff0, 14); + test_imm_src1_bypass!(test_bseti_23, 2, bseti, 0x0ff00ff0, 0x0ff00ff0, 27); + + test_imm_zero_src1!(test_bseti_24, bseti, 0x00008000, 15); + test_imm_zero_dest!(test_bseti_25, bseti, 1024, 10); + + // --------------------------------------------------------------------------------------------- + // Tests for Bit Clear Immediate (`bclri`) Instruction + // + // Test suite based on riscv-tests + // https://github.com/riscv-software-src/riscv-tests/blob/master/isa/rv64uzbs/bclri.S + // --------------------------------------------------------------------------------------------- + + test_imm_op!(test_bclri_2, bclri, 0xff00ff00, 0xff00ff00, 0); + test_imm_op!(test_bclri_3, bclri, 0x00ff00fd, 0x00ff00ff, 1); + test_imm_op!(test_bclri_4, bclri, 0xff00fe00, 0xff00ff00, 8); + test_imm_op!(test_bclri_5, bclri, 0x0ff00ff0, 0x0ff00ff0, 14); + test_imm_op!(test_bclri_6, bclri, 0x07f00ff0, 0x0ff00ff0, 27); + + test_imm_op!(test_bclri_7, bclri, 0xfffffffe, 0xffffffff, 0); + test_imm_op!(test_bclri_8, bclri, 0xfffffffd, 0xffffffff, 1); + test_imm_op!(test_bclri_9, bclri, 0xffffff7f, 0xffffffff, 7); + test_imm_op!(test_bclri_10, bclri, 0xffffbfff, 0xffffffff, 14); + test_imm_op!(test_bclri_11, bclri, 0xf7ffffff, 0xffffffff, 27); + + test_imm_op!(test_bclri_12, bclri, 0x21212120, 0x21212121, 0); + test_imm_op!(test_bclri_13, bclri, 0x21212121, 0x21212121, 1); + test_imm_op!(test_bclri_14, bclri, 0x21212121, 0x21212121, 7); + test_imm_op!(test_bclri_15, bclri, 0x21210121, 0x21212121, 13); + test_imm_op!(test_bclri_16, bclri, 0x04848484, 0x84848484, 31); + + test_imm_src1_eq_dest!(test_bclri_17, bclri, 0x00000001, 0x00000001, 7); + + test_imm_dest_bypass!(test_bclri_18, 0, bclri, 0xff00fe00, 0xff00ff00, 8); + test_imm_dest_bypass!(test_bclri_19, 1, bclri, 0x0ff00ff0, 0x0ff00ff0, 14); + test_imm_dest_bypass!(test_bclri_20, 2, bclri, 0x07f00ff0, 0x0ff00ff0, 27); + + test_imm_src1_bypass!(test_bclri_21, 0, bclri, 0xff00fe00, 0xff00ff00, 8); + test_imm_src1_bypass!(test_bclri_22, 1, bclri, 0x0ff00ff0, 0x0ff00ff0, 14); + test_imm_src1_bypass!(test_bclri_23, 2, bclri, 0x07f00ff0, 0x0ff00ff0, 27); + + test_imm_zero_src1!(test_bclri_24, bclri, 0, 31); + test_imm_zero_dest!(test_bclri_25, bclri, 33, 20); + + // --------------------------------------------------------------------------------------------- + // Tests for Bit Extract Immediate (`bexti`) Instruction + // + // Test suite based on riscv-tests + // https://github.com/riscv-software-src/riscv-tests/blob/master/isa/rv64uzbs/bexti.S + // --------------------------------------------------------------------------------------------- + + test_imm_op!(test_bexti_2, bexti, 0, 0xff00ff00, 0); + test_imm_op!(test_bexti_3, bexti, 1, 0x00ff00ff, 1); + test_imm_op!(test_bexti_4, bexti, 1, 0xff00ff00, 8); + test_imm_op!(test_bexti_5, bexti, 0, 0x0ff00ff0, 14); + test_imm_op!(test_bexti_6, bexti, 1, 0x0ff00ff0, 27); + + test_imm_op!(test_bexti_7, bexti, 1, 0xffffffff, 0); + test_imm_op!(test_bexti_8, bexti, 1, 0xffffffff, 1); + test_imm_op!(test_bexti_9, bexti, 1, 0xffffffff, 7); + test_imm_op!(test_bexti_10, bexti, 1, 0xffffffff, 14); + test_imm_op!(test_bexti_11, bexti, 1, 0xffffffff, 27); + + test_imm_op!(test_bexti_12, bexti, 1, 0x21212121, 0); + test_imm_op!(test_bexti_13, bexti, 0, 0x21212121, 1); + test_imm_op!(test_bexti_14, bexti, 0, 0x21212121, 7); + test_imm_op!(test_bexti_15, bexti, 1, 0x21212121, 13); + test_imm_op!(test_bexti_16, bexti, 1, 0x84848484, 31); + + test_imm_src1_eq_dest!(test_bexti_17, bexti, 0, 0x00000001, 7); + + test_imm_dest_bypass!(test_bexti_18, 0, bexti, 1, 0xff00ff00, 8); + test_imm_dest_bypass!(test_bexti_19, 1, bexti, 0, 0x0ff00ff0, 14); + test_imm_dest_bypass!(test_bexti_20, 2, bexti, 1, 0x0ff00ff0, 27); + + test_imm_src1_bypass!(test_bexti_21, 0, bexti, 1, 0xff00ff00, 8); + test_imm_src1_bypass!(test_bexti_22, 1, bexti, 0, 0x0ff00ff0, 14); + test_imm_src1_bypass!(test_bexti_23, 2, bexti, 1, 0x0ff00ff0, 27); + + test_imm_zero_src1!(test_bexti_24, bexti, 0, 31); + test_imm_zero_dest!(test_bexti_25, bexti, 33, 20); + + // --------------------------------------------------------------------------------------------- + // Tests for And Invert (`andn`) Instruction + // + // Test suite based on riscv-tests + // https://github.com/riscv-software-src/riscv-tests/blob/master/isa/rv64uzbb/andn.S + // --------------------------------------------------------------------------------------------- + + test_rr_op!(test_andn_2, andn, 0xf000f000, 0xff00ff00, 0x0f0f0f0f); + test_rr_op!(test_andn_3, andn, 0x0f000f00, 0x0ff00ff0, 0xf0f0f0f0); + test_rr_op!(test_andn_4, andn, 0x00f000f0, 0x00ff00ff, 0x0f0f0f0f); + test_rr_op!(test_andn_5, andn, 0x000f000f, 0xf00ff00f, 0xf0f0f0f0); + + test_rr_src1_eq_dest!(test_andn_6, andn, 0xf000f000, 0xff00ff00, 0x0f0f0f0f); + test_rr_src2_eq_dest!(test_andn_7, andn, 0x0f000f00, 0x0ff00ff0, 0xf0f0f0f0); + test_rr_src12_eq_dest!(test_andn_8, andn, 0x00000000, 0xff00ff00); + + test_rr_dest_bypass!(test_andn_9, 0, andn, 0xf000f000, 0xff00ff00, 0x0f0f0f0f); + test_rr_dest_bypass!(test_andn_10, 1, andn, 0x0f000f00, 0x0ff00ff0, 0xf0f0f0f0); + test_rr_dest_bypass!(test_andn_11, 2, andn, 0x00f000f0, 0x00ff00ff, 0x0f0f0f0f); + + test_rr_src12_bypass!(test_andn_12, 0, 0, andn, 0xf000f000, 0xff00ff00, 0x0f0f0f0f); + test_rr_src12_bypass!(test_andn_13, 0, 1, andn, 0x0f000f00, 0x0ff00ff0, 0xf0f0f0f0); + test_rr_src12_bypass!(test_andn_14, 0, 2, andn, 0x00f000f0, 0x00ff00ff, 0x0f0f0f0f); + test_rr_src12_bypass!(test_andn_15, 1, 0, andn, 0xf000f000, 0xff00ff00, 0x0f0f0f0f); + test_rr_src12_bypass!(test_andn_16, 1, 1, andn, 0x0f000f00, 0x0ff00ff0, 0xf0f0f0f0); + test_rr_src12_bypass!(test_andn_17, 2, 0, andn, 0x00f000f0, 0x00ff00ff, 0x0f0f0f0f); + + test_rr_src21_bypass!(test_andn_18, 0, 0, andn, 0xf000f000, 0xff00ff00, 0x0f0f0f0f); + test_rr_src21_bypass!(test_andn_19, 0, 1, andn, 0x0f000f00, 0x0ff00ff0, 0xf0f0f0f0); + test_rr_src21_bypass!(test_andn_20, 0, 2, andn, 0x00f000f0, 0x00ff00ff, 0x0f0f0f0f); + test_rr_src21_bypass!(test_andn_21, 1, 0, andn, 0xf000f000, 0xff00ff00, 0x0f0f0f0f); + test_rr_src21_bypass!(test_andn_22, 1, 1, andn, 0x0f000f00, 0x0ff00ff0, 0xf0f0f0f0); + test_rr_src21_bypass!(test_andn_23, 2, 0, andn, 0x00f000f0, 0x00ff00ff, 0x0f0f0f0f); + + test_rr_zerosrc1!(test_andn_24, andn, 0, 0xff00ff00); + test_rr_zerosrc2!(test_andn_25, andn, 0x00ff00ff, 0x00ff00ff); + test_rr_zerosrc12!(test_andn_26, andn, 0); + test_rr_zerodest!(test_andn_27, andn, 0x11111111, 0x22222222); + + // --------------------------------------------------------------------------------------------- + // Tests for Or Invert (`orn`) Instruction + // + // Test suite based on riscv-tests + // https://github.com/riscv-software-src/riscv-tests/blob/master/isa/rv64uzbb/orn.S + // --------------------------------------------------------------------------------------------- + + test_rr_op!(test_orn_2, orn, 0xfff0fff0, 0xff00ff00, 0x0f0f0f0f); + test_rr_op!(test_orn_3, orn, 0x0fff0fff, 0x0ff00ff0, 0xf0f0f0f0); + test_rr_op!(test_orn_4, orn, 0xf0fff0ff, 0x00ff00ff, 0x0f0f0f0f); + test_rr_op!(test_orn_5, orn, 0xff0fff0f, 0xf00ff00f, 0xf0f0f0f0); + + test_rr_src1_eq_dest!(test_orn_6, orn, 0xfff0fff0, 0xff00ff00, 0x0f0f0f0f); + test_rr_src2_eq_dest!(test_orn_7, orn, 0xfff0fff0, 0xff00ff00, 0x0f0f0f0f); + test_rr_src12_eq_dest!(test_orn_8, orn, 0xffffffff, 0xff00ff00); + + test_rr_dest_bypass!(test_orn_9, 0, orn, 0xfff0fff0, 0xff00ff00, 0x0f0f0f0f); + test_rr_dest_bypass!(test_orn_10, 1, orn, 0x0fff0fff, 0x0ff00ff0, 0xf0f0f0f0); + test_rr_dest_bypass!(test_orn_11, 2, orn, 0xf0fff0ff, 0x00ff00ff, 0x0f0f0f0f); + + test_rr_src12_bypass!(test_orn_12, 0, 0, orn, 0xfff0fff0, 0xff00ff00, 0x0f0f0f0f); + test_rr_src12_bypass!(test_orn_13, 0, 1, orn, 0x0fff0fff, 0x0ff00ff0, 0xf0f0f0f0); + test_rr_src12_bypass!(test_orn_14, 0, 2, orn, 0xf0fff0ff, 0x00ff00ff, 0x0f0f0f0f); + test_rr_src12_bypass!(test_orn_15, 1, 0, orn, 0xfff0fff0, 0xff00ff00, 0x0f0f0f0f); + test_rr_src12_bypass!(test_orn_16, 1, 1, orn, 0x0fff0fff, 0x0ff00ff0, 0xf0f0f0f0); + test_rr_src12_bypass!(test_orn_17, 2, 0, orn, 0xf0fff0ff, 0x00ff00ff, 0x0f0f0f0f); + + test_rr_src21_bypass!(test_orn_18, 0, 0, orn, 0xfff0fff0, 0xff00ff00, 0x0f0f0f0f); + test_rr_src21_bypass!(test_orn_19, 0, 1, orn, 0x0fff0fff, 0x0ff00ff0, 0xf0f0f0f0); + test_rr_src21_bypass!(test_orn_20, 0, 2, orn, 0xf0fff0ff, 0x00ff00ff, 0x0f0f0f0f); + test_rr_src21_bypass!(test_orn_21, 1, 0, orn, 0xfff0fff0, 0xff00ff00, 0x0f0f0f0f); + test_rr_src21_bypass!(test_orn_22, 1, 1, orn, 0x0fff0fff, 0x0ff00ff0, 0xf0f0f0f0); + test_rr_src21_bypass!(test_orn_23, 2, 0, orn, 0xf0fff0ff, 0x00ff00ff, 0x0f0f0f0f); + + test_rr_zerosrc1!(test_orn_24, orn, 0x00ff00ff, 0xff00ff00); + test_rr_zerosrc2!(test_orn_25, orn, 0xffffffff, 0x00ff00ff); + test_rr_zerosrc12!(test_orn_26, orn, 0xffffffff); + test_rr_zerodest!(test_orn_27, orn, 0x11111111, 0x22222222); + + // --------------------------------------------------------------------------------------------- + // Tests for Exclusive NOR (`xnor`) Instruction + // + // Test suite based on riscv-tests + // https://github.com/riscv-software-src/riscv-tests/blob/master/isa/rv64uzbb/xnor.S + // --------------------------------------------------------------------------------------------- + + test_rr_op!(test_xnor_2, xnor, 0x0ff00ff0, 0xff00ff00, 0x0f0f0f0f); + test_rr_op!(test_xnor_3, xnor, 0x00ff00ff, 0x0ff00ff0, 0xf0f0f0f0); + test_rr_op!(test_xnor_4, xnor, 0xf00ff00f, 0x00ff00ff, 0x0f0f0f0f); + test_rr_op!(test_xnor_5, xnor, 0xff00ff00, 0xf00ff00f, 0xf0f0f0f0); + + test_rr_src1_eq_dest!(test_xnor_6, xnor, 0x0ff00ff0, 0xff00ff00, 0x0f0f0f0f); + test_rr_src2_eq_dest!(test_xnor_7, xnor, 0x0ff00ff0, 0xff00ff00, 0x0f0f0f0f); + test_rr_src12_eq_dest!(test_xnor_8, xnor, 0xffffffff, 0xff00ff00); + + test_rr_dest_bypass!(test_xnor_9, 0, xnor, 0x0ff00ff0, 0xff00ff00, 0x0f0f0f0f); + test_rr_dest_bypass!(test_xnor_10, 1, xnor, 0x00ff00ff, 0x0ff00ff0, 0xf0f0f0f0); + test_rr_dest_bypass!(test_xnor_11, 2, xnor, 0xf00ff00f, 0x00ff00ff, 0x0f0f0f0f); + + test_rr_src12_bypass!(test_xnor_12, 0, 0, xnor, 0x0ff00ff0, 0xff00ff00, 0x0f0f0f0f); + test_rr_src12_bypass!(test_xnor_13, 0, 1, xnor, 0x00ff00ff, 0x0ff00ff0, 0xf0f0f0f0); + test_rr_src12_bypass!(test_xnor_14, 0, 2, xnor, 0xf00ff00f, 0x00ff00ff, 0x0f0f0f0f); + test_rr_src12_bypass!(test_xnor_15, 1, 0, xnor, 0x0ff00ff0, 0xff00ff00, 0x0f0f0f0f); + test_rr_src12_bypass!(test_xnor_16, 1, 1, xnor, 0x00ff00ff, 0x0ff00ff0, 0xf0f0f0f0); + test_rr_src12_bypass!(test_xnor_17, 2, 0, xnor, 0xf00ff00f, 0x00ff00ff, 0x0f0f0f0f); + + test_rr_src21_bypass!(test_xnor_18, 0, 0, xnor, 0x0ff00ff0, 0xff00ff00, 0x0f0f0f0f); + test_rr_src21_bypass!(test_xnor_19, 0, 1, xnor, 0x00ff00ff, 0x0ff00ff0, 0xf0f0f0f0); + test_rr_src21_bypass!(test_xnor_20, 0, 2, xnor, 0xf00ff00f, 0x00ff00ff, 0x0f0f0f0f); + test_rr_src21_bypass!(test_xnor_21, 1, 0, xnor, 0x0ff00ff0, 0xff00ff00, 0x0f0f0f0f); + test_rr_src21_bypass!(test_xnor_22, 1, 1, xnor, 0x00ff00ff, 0x0ff00ff0, 0xf0f0f0f0); + test_rr_src21_bypass!(test_xnor_23, 2, 0, xnor, 0xf00ff00f, 0x00ff00ff, 0x0f0f0f0f); + + test_rr_zerosrc1!(test_xnor_24, xnor, 0x00ff00ff, 0xff00ff00); + test_rr_zerosrc2!(test_xnor_25, xnor, 0xff00ff00, 0x00ff00ff); + test_rr_zerosrc12!(test_xnor_26, xnor, 0xffffffff); + test_rr_zerodest!(test_xnor_27, xnor, 0x11111111, 0x22222222); + + // --------------------------------------------------------------------------------------------- + // Tests for Maximum (`max`) Instruction + // + // Test suite based on riscv-tests + // https://github.com/riscv-software-src/riscv-tests/blob/master/isa/rv64uzbb/max.S + // --------------------------------------------------------------------------------------------- + + test_rr_op!(test_max_2, max, 0x00000000, 0x00000000, 0x00000000); + test_rr_op!(test_max_3, max, 0x00000001, 0x00000001, 0x00000001); + test_rr_op!(test_max_4, max, 0x00000007, 0x00000003, 0x00000007); + test_rr_op!(test_max_5, max, 0x00000007, 0x00000007, 0x00000003); + + test_rr_op!(test_max_6, max, 0x00000000, 0x00000000, 0xffff8000); + test_rr_op!(test_max_7, max, 0x00000000, 0x80000000, 0x00000000); + test_rr_op!(test_max_8, max, 0xffff8000, 0x80000000, 0xffff8000); + + test_rr_op!(test_max_9, max, 0x00007fff, 0x00000000, 0x00007fff); + test_rr_op!(test_max_10, max, 0x7fffffff, 0x7fffffff, 0x00000000); + test_rr_op!(test_max_11, max, 0x7fffffff, 0x7fffffff, 0x00007fff); + + test_rr_op!(test_max_12, max, 0x00007fff, 0x80000000, 0x00007fff); + test_rr_op!(test_max_13, max, 0x7fffffff, 0x7fffffff, 0xffff8000); + + test_rr_op!(test_max_14, max, 0x00000000, 0x00000000, 0xffffffff); + test_rr_op!(test_max_15, max, 0x00000001, 0xffffffff, 0x00000001); + test_rr_op!(test_max_16, max, 0xffffffff, 0xffffffff, 0xffffffff); + + test_rr_src1_eq_dest!(test_max_17, max, 14, 14, 13); + test_rr_src2_eq_dest!(test_max_18, max, 13, 11, 13); + test_rr_src12_eq_dest!(test_max_19, max, 13, 13); + + test_rr_dest_bypass!(test_max_20, 0, max, 13, 11, 13); + test_rr_dest_bypass!(test_max_21, 1, max, 14, 14, 13); + test_rr_dest_bypass!(test_max_22, 2, max, 13, 12, 13); + + test_rr_src12_bypass!(test_max_23, 0, 0, max, 14, 14, 13); + test_rr_src12_bypass!(test_max_24, 0, 1, max, 13, 11, 13); + test_rr_src12_bypass!(test_max_25, 0, 2, max, 15, 15, 13); + test_rr_src12_bypass!(test_max_26, 1, 0, max, 13, 10, 13); + test_rr_src12_bypass!(test_max_27, 1, 1, max, 16, 16, 13); + test_rr_src12_bypass!(test_max_28, 2, 0, max, 13, 9, 13); + + test_rr_src21_bypass!(test_max_29, 0, 0, max, 17, 17, 13); + test_rr_src21_bypass!(test_max_30, 0, 1, max, 13, 8, 13); + test_rr_src21_bypass!(test_max_31, 0, 2, max, 18, 18, 13); + test_rr_src21_bypass!(test_max_32, 1, 0, max, 13, 7, 13); + test_rr_src21_bypass!(test_max_33, 1, 1, max, 19, 19, 13); + test_rr_src21_bypass!(test_max_34, 2, 0, max, 13, 6, 13); + + test_rr_zerosrc1!(test_max_35, max, 0, 0xffffffff); + test_rr_zerosrc2!(test_max_36, max, 0, 0xffffffff); + test_rr_zerosrc12!(test_max_37, max, 0); + test_rr_zerodest!(test_max_38, max, 16, 30); + + // --------------------------------------------------------------------------------------------- + // Tests for Maximum Unsigned (`maxu`) Instruction + // + // Test suite based on riscv-tests + // https://github.com/riscv-software-src/riscv-tests/blob/master/isa/rv64uzbb/maxu.S + // --------------------------------------------------------------------------------------------- + + test_rr_op!(test_maxu_2, maxu, 0x00000000, 0x00000000, 0x00000000); + test_rr_op!(test_maxu_3, maxu, 0x00000001, 0x00000001, 0x00000001); + test_rr_op!(test_maxu_4, maxu, 0x00000007, 0x00000003, 0x00000007); + test_rr_op!(test_maxu_5, maxu, 0x00000007, 0x00000007, 0x00000003); + + test_rr_op!(test_maxu_6, maxu, 0xffff8000, 0x00000000, 0xffff8000); + test_rr_op!(test_maxu_7, maxu, 0x80000000, 0x80000000, 0x00000000); + test_rr_op!(test_maxu_8, maxu, 0xffff8000, 0x80000000, 0xffff8000); + + test_rr_op!(test_maxu_9, maxu, 0x00007fff, 0x00000000, 0x00007fff); + test_rr_op!(test_maxu_10, maxu, 0x7fffffff, 0x7fffffff, 0x00000000); + test_rr_op!(test_maxu_11, maxu, 0x7fffffff, 0x7fffffff, 0x00007fff); + + test_rr_op!(test_maxu_12, maxu, 0x80000000, 0x80000000, 0x00007fff); + test_rr_op!(test_maxu_13, maxu, 0xffff8000, 0x7fffffff, 0xffff8000); + + test_rr_op!(test_maxu_14, maxu, 0xffffffff, 0x00000000, 0xffffffff); + test_rr_op!(test_maxu_15, maxu, 0xffffffff, 0xffffffff, 0x00000001); + test_rr_op!(test_maxu_16, maxu, 0xffffffff, 0xffffffff, 0xffffffff); + + test_rr_src1_eq_dest!(test_maxu_17, maxu, 14, 14, 13); + test_rr_src2_eq_dest!(test_maxu_18, maxu, 13, 11, 13); + test_rr_src12_eq_dest!(test_maxu_19, maxu, 13, 13); + + test_rr_dest_bypass!(test_maxu_20, 0, maxu, 13, 11, 13); + test_rr_dest_bypass!(test_maxu_21, 1, maxu, 14, 14, 13); + test_rr_dest_bypass!(test_maxu_22, 2, maxu, 13, 12, 13); + + test_rr_src12_bypass!(test_maxu_23, 0, 0, maxu, 14, 14, 13); + test_rr_src12_bypass!(test_maxu_24, 0, 1, maxu, 13, 11, 13); + test_rr_src12_bypass!(test_maxu_25, 0, 2, maxu, 15, 15, 13); + test_rr_src12_bypass!(test_maxu_26, 1, 0, maxu, 13, 10, 13); + test_rr_src12_bypass!(test_maxu_27, 1, 1, maxu, 16, 16, 13); + test_rr_src12_bypass!(test_maxu_28, 2, 0, maxu, 13, 9, 13); + + test_rr_src21_bypass!(test_maxu_29, 0, 0, maxu, 17, 17, 13); + test_rr_src21_bypass!(test_maxu_30, 0, 1, maxu, 13, 8, 13); + test_rr_src21_bypass!(test_maxu_31, 0, 2, maxu, 18, 18, 13); + test_rr_src21_bypass!(test_maxu_32, 1, 0, maxu, 13, 7, 13); + test_rr_src21_bypass!(test_maxu_33, 1, 1, maxu, 19, 19, 13); + test_rr_src21_bypass!(test_maxu_34, 2, 0, maxu, 13, 6, 13); + + test_rr_zerosrc1!(test_maxu_35, maxu, 0xffffffff, 0xffffffff); + test_rr_zerosrc2!(test_maxu_36, maxu, 0xffffffff, 0xffffffff); + test_rr_zerosrc12!(test_maxu_37, maxu, 0); + test_rr_zerodest!(test_maxu_38, maxu, 16, 30); + + // --------------------------------------------------------------------------------------------- + // Tests for Maximum (`min`) Instruction + // + // Test suite based on riscv-tests + // https://github.com/riscv-software-src/riscv-tests/blob/master/isa/rv64uzbb/min.S + // --------------------------------------------------------------------------------------------- + + test_rr_op!(test_min_2, min, 0x00000000, 0x00000000, 0x00000000); + test_rr_op!(test_min_3, min, 0x00000001, 0x00000001, 0x00000001); + test_rr_op!(test_min_4, min, 0x00000003, 0x00000003, 0x00000007); + test_rr_op!(test_min_5, min, 0x00000003, 0x00000007, 0x00000003); + + test_rr_op!(test_min_6, min, 0xffff8000, 0x00000000, 0xffff8000); + test_rr_op!(test_min_7, min, 0x80000000, 0x80000000, 0x00000000); + test_rr_op!(test_min_8, min, 0x80000000, 0x80000000, 0xffff8000); + + test_rr_op!(test_min_9, min, 0x00000000, 0x00000000, 0x00007fff); + test_rr_op!(test_min_10, min, 0x00000000, 0x7fffffff, 0x00000000); + test_rr_op!(test_min_11, min, 0x00007fff, 0x7fffffff, 0x00007fff); + + test_rr_op!(test_min_12, min, 0x80000000, 0x80000000, 0x00007fff); + test_rr_op!(test_min_13, min, 0xffff8000, 0x7fffffff, 0xffff8000); + + test_rr_op!(test_min_14, min, 0xffffffff, 0x00000000, 0xffffffff); + test_rr_op!(test_min_15, min, 0xffffffff, 0xffffffff, 0x00000001); + test_rr_op!(test_min_16, min, 0xffffffff, 0xffffffff, 0xffffffff); + + test_rr_src1_eq_dest!(test_min_17, min, 13, 14, 13); + test_rr_src2_eq_dest!(test_min_18, min, 11, 11, 13); + test_rr_src12_eq_dest!(test_min_19, min, 13, 13); + + test_rr_dest_bypass!(test_min_20, 0, min, 11, 11, 13); + test_rr_dest_bypass!(test_min_21, 1, min, 13, 14, 13); + test_rr_dest_bypass!(test_min_22, 2, min, 12, 12, 13); + + test_rr_src12_bypass!(test_min_23, 0, 0, min, 13, 14, 13); + test_rr_src12_bypass!(test_min_24, 0, 1, min, 11, 11, 13); + test_rr_src12_bypass!(test_min_25, 0, 2, min, 13, 15, 13); + test_rr_src12_bypass!(test_min_26, 1, 0, min, 10, 10, 13); + test_rr_src12_bypass!(test_min_27, 1, 1, min, 13, 16, 13); + test_rr_src12_bypass!(test_min_28, 2, 0, min, 9, 9, 13); + + test_rr_src21_bypass!(test_min_29, 0, 0, min, 13, 17, 13); + test_rr_src21_bypass!(test_min_30, 0, 1, min, 8, 8, 13); + test_rr_src21_bypass!(test_min_31, 0, 2, min, 13, 18, 13); + test_rr_src21_bypass!(test_min_32, 1, 0, min, 7, 7, 13); + test_rr_src21_bypass!(test_min_33, 1, 1, min, 13, 19, 13); + test_rr_src21_bypass!(test_min_34, 2, 0, min, 6, 6, 13); + + test_rr_zerosrc1!(test_min_35, min, 0xffffffff, 0xffffffff); + test_rr_zerosrc2!(test_min_36, min, 0xffffffff, 0xffffffff); + test_rr_zerosrc12!(test_min_37, min, 0); + test_rr_zerodest!(test_min_38, min, 16, 30); + + // --------------------------------------------------------------------------------------------- + // Tests for Minimum Unsigned (`minu`) Instruction + // + // Test suite based on riscv-tests + // https://github.com/riscv-software-src/riscv-tests/blob/master/isa/rv64uzbb/minu.S + // --------------------------------------------------------------------------------------------- + + test_rr_op!(test_minu_2, minu, 0x00000000, 0x00000000, 0x00000000); + test_rr_op!(test_minu_3, minu, 0x00000001, 0x00000001, 0x00000001); + test_rr_op!(test_minu_4, minu, 0x00000003, 0x00000003, 0x00000007); + test_rr_op!(test_minu_5, minu, 0x00000003, 0x00000007, 0x00000003); + + test_rr_op!(test_minu_6, minu, 0x00000000, 0x00000000, 0xffff8000); + test_rr_op!(test_minu_7, minu, 0x00000000, 0x80000000, 0x00000000); + test_rr_op!(test_minu_8, minu, 0x80000000, 0x80000000, 0xffff8000); + + test_rr_op!(test_minu_9, minu, 0x00000000, 0x00000000, 0x00007fff); + test_rr_op!(test_minu_10, minu, 0x00000000, 0x7fffffff, 0x00000000); + test_rr_op!(test_minu_11, minu, 0x00007fff, 0x7fffffff, 0x00007fff); + + test_rr_op!(test_minu_12, minu, 0x00007fff, 0x80000000, 0x00007fff); + test_rr_op!(test_minu_13, minu, 0x7fffffff, 0x7fffffff, 0xffff8000); + + test_rr_op!(test_minu_14, minu, 0x00000000, 0x00000000, 0xffffffff); + test_rr_op!(test_minu_15, minu, 0x00000001, 0xffffffff, 0x00000001); + test_rr_op!(test_minu_16, minu, 0xffffffff, 0xffffffff, 0xffffffff); + + test_rr_src1_eq_dest!(test_minu_17, minu, 13, 14, 13); + test_rr_src2_eq_dest!(test_minu_18, minu, 11, 11, 13); + test_rr_src12_eq_dest!(test_minu_19, minu, 13, 13); + + test_rr_dest_bypass!(test_minu_20, 0, minu, 11, 11, 13); + test_rr_dest_bypass!(test_minu_21, 1, minu, 13, 14, 13); + test_rr_dest_bypass!(test_minu_22, 2, minu, 12, 12, 13); + + test_rr_src12_bypass!(test_minu_23, 0, 0, minu, 13, 14, 13); + test_rr_src12_bypass!(test_minu_24, 0, 1, minu, 11, 11, 13); + test_rr_src12_bypass!(test_minu_25, 0, 2, minu, 13, 15, 13); + test_rr_src12_bypass!(test_minu_26, 1, 0, minu, 10, 10, 13); + test_rr_src12_bypass!(test_minu_27, 1, 1, minu, 13, 16, 13); + test_rr_src12_bypass!(test_minu_28, 2, 0, minu, 9, 9, 13); + + test_rr_src21_bypass!(test_minu_29, 0, 0, minu, 13, 17, 13); + test_rr_src21_bypass!(test_minu_30, 0, 1, minu, 8, 8, 13); + test_rr_src21_bypass!(test_minu_31, 0, 2, minu, 13, 18, 13); + test_rr_src21_bypass!(test_minu_32, 1, 0, minu, 7, 7, 13); + test_rr_src21_bypass!(test_minu_33, 1, 1, minu, 13, 19, 13); + test_rr_src21_bypass!(test_minu_34, 2, 0, minu, 6, 6, 13); + + test_rr_zerosrc1!(test_minu_35, minu, 0, 0xffffffff); + test_rr_zerosrc2!(test_minu_36, minu, 0, 0xffffffff); + test_rr_zerosrc12!(test_minu_37, minu, 0); + test_rr_zerodest!(test_minu_38, minu, 16, 30); + + // --------------------------------------------------------------------------------------------- + // Tests for Zero Extend Halfword (`zext.h`) Instruction + // + // Test suite based on riscv-tests + // https://github.com/riscv-software-src/riscv-tests/blob/master/isa/rv64uzbb/zext_h.S + // --------------------------------------------------------------------------------------------- + + test_r_op!(test_zexth_2, zext_h, 0x00000000, 0x00000000); + test_r_op!(test_zexth_3, zext_h, 0x00000001, 0x00000001); + test_r_op!(test_zexth_4, zext_h, 0x00000003, 0x00000003); + + test_r_op!(test_zexth_5, zext_h, 0x00008000, 0xffff8000); + test_r_op!(test_zexth_6, zext_h, 0x00000000, 0x00800000); + test_r_op!(test_zexth_7, zext_h, 0x00008000, 0xffff8000); + + test_r_op!(test_zexth_8, zext_h, 0x00007fff, 0x00007fff); + test_r_op!(test_zexth_9, zext_h, 0x0000ffff, 0x7fffffff); + test_r_op!(test_zexth_10, zext_h, 0x0000ffff, 0x0007ffff); + + test_r_op!(test_zexth_11, zext_h, 0x00000000, 0x80000000); + test_r_op!(test_zexth_12, zext_h, 0x00005000, 0x121f5000); + + test_r_op!(test_zexth_13, zext_h, 0x00000000, 0x00000000); + test_r_op!(test_zexth_14, zext_h, 0x0000000e, 0x0000000e); + test_r_op!(test_zexth_15, zext_h, 0x00001341, 0x20401341); + + test_r_src1_eq_dest!(test_zexth_16, zext_h, 0x0000000d, 13); + test_r_src1_eq_dest!(test_zexth_17, zext_h, 0x0000000b, 11); + + test_r_dest_bypass!(test_zexth_18, 0, zext_h, 0x0000000d, 13); + test_r_dest_bypass!(test_zexth_29, 1, zext_h, 0x00000013, 19); + test_r_dest_bypass!(test_zexth_20, 2, zext_h, 0x00000022, 34); + + test_r_op!(test_zexth_21, zext_h, 0x00008000, 0x007f8000); + test_r_op!(test_zexth_22, zext_h, 0x00008000, 0x00808000); + test_r_op!(test_zexth_23, zext_h, 0x00008000, 0x01808000); + + test_r_op!(test_zexth_24, zext_h, 0x00007fff, 0x00007fff); + test_r_op!(test_zexth_25, zext_h, 0x0000ffff, 0x7fffffff); + test_r_op!(test_zexth_26, zext_h, 0x0000ffff, 0x0007ffff); + + // --------------------------------------------------------------------------------------------- + // Tests for Rotate Left (`rol`) Instruction + // + // Test suite based on riscv-tests + // https://github.com/riscv-software-src/riscv-tests/blob/master/isa/rv32uzbb/rol.S + // --------------------------------------------------------------------------------------------- + + test_rr_op!(test_rol_2, rol, 0x00000001, 0x00000001, 0); + test_rr_op!(test_rol_3, rol, 0x00000002, 0x00000001, 1); + test_rr_op!(test_rol_4, rol, 0x00000080, 0x00000001, 7); + test_rr_op!(test_rol_5, rol, 0x00004000, 0x00000001, 14); + test_rr_op!(test_rol_6, rol, 0x80000000, 0x00000001, 31); + + test_rr_op!(test_rol_7, rol, 0xffffffff, 0xffffffff, 0); + test_rr_op!(test_rol_8, rol, 0xffffffff, 0xffffffff, 1); + test_rr_op!(test_rol_9, rol, 0xffffffff, 0xffffffff, 7); + test_rr_op!(test_rol_10, rol, 0xffffffff, 0xffffffff, 14); + test_rr_op!(test_rol_11, rol, 0xffffffff, 0xffffffff, 31); + + test_rr_op!(test_rol_12, rol, 0x21212121, 0x21212121, 0); + test_rr_op!(test_rol_13, rol, 0x42424242, 0x21212121, 1); + test_rr_op!(test_rol_14, rol, 0x90909090, 0x21212121, 7); + test_rr_op!(test_rol_15, rol, 0x48484848, 0x21212121, 14); + test_rr_op!(test_rol_16, rol, 0x90909090, 0x21212121, 31); + + // Verify that rotates only use bottom five bits + + test_rr_op!(test_rol_17, rol, 0x21212121, 0x21212121, 0xffffffe0); + test_rr_op!(test_rol_18, rol, 0x42424242, 0x21212121, 0xffffffe1); + test_rr_op!(test_rol_19, rol, 0x90909090, 0x21212121, 0xffffffe7); + test_rr_op!(test_rol_20, rol, 0x48484848, 0x21212121, 0xffffffee); + test_rr_op!(test_rol_21, rol, 0x90909090, 0x21212121, 0xffffffff); + + // Verify that rotates ignore top 32 (using true 64-bit values) + + test_rr_op!(test_rol_44, rol, 0x12345678, 0x12345678, 0); + test_rr_op!(test_rol_45, rol, 0x23456781, 0x12345678, 4); + test_rr_op!(test_rol_46, rol, 0x92345678, 0x92345678, 0); + test_rr_op!(test_rol_47, rol, 0x93456789, 0x99345678, 4); + + test_rr_src1_eq_dest!(test_rol_22, rol, 0x00000080, 0x00000001, 7); + test_rr_src2_eq_dest!(test_rol_23, rol, 0x00004000, 0x00000001, 14); + test_rr_src12_eq_dest!(test_rol_24, rol, 24, 3); + + test_rr_dest_bypass!(test_rol_25, 0, rol, 0x00000080, 0x00000001, 7); + test_rr_dest_bypass!(test_rol_26, 1, rol, 0x00004000, 0x00000001, 14); + test_rr_dest_bypass!(test_rol_27, 2, rol, 0x80000000, 0x00000001, 31); + + test_rr_src12_bypass!(test_rol_28, 0, 0, rol, 0x00000080, 0x00000001, 7); + test_rr_src12_bypass!(test_rol_29, 0, 1, rol, 0x00004000, 0x00000001, 14); + test_rr_src12_bypass!(test_rol_30, 0, 2, rol, 0x80000000, 0x00000001, 31); + test_rr_src12_bypass!(test_rol_31, 1, 0, rol, 0x00000080, 0x00000001, 7); + test_rr_src12_bypass!(test_rol_32, 1, 1, rol, 0x00004000, 0x00000001, 14); + test_rr_src12_bypass!(test_rol_33, 2, 0, rol, 0x80000000, 0x00000001, 31); + + test_rr_src21_bypass!(test_rol_34, 0, 0, rol, 0x00000080, 0x00000001, 7); + test_rr_src21_bypass!(test_rol_35, 0, 1, rol, 0x00004000, 0x00000001, 14); + test_rr_src21_bypass!(test_rol_36, 0, 2, rol, 0x80000000, 0x00000001, 31); + test_rr_src21_bypass!(test_rol_37, 1, 0, rol, 0x00000080, 0x00000001, 7); + test_rr_src21_bypass!(test_rol_38, 1, 1, rol, 0x00004000, 0x00000001, 14); + test_rr_src21_bypass!(test_rol_39, 2, 0, rol, 0x80000000, 0x00000001, 31); + + test_rr_zerosrc1!(test_rol_40, rol, 0, 15); + test_rr_zerosrc2!(test_rol_41, rol, 32, 32); + test_rr_zerosrc12!(test_rol_42, rol, 0); + test_rr_zerodest!(test_rol_43, rol, 1024, 2048); + + // --------------------------------------------------------------------------------------------- + // Tests for Rotate Right (`ror`) Instruction + // + // Test suite based on riscv-tests + // https://github.com/riscv-software-src/riscv-tests/blob/master/isa/rv32uzbb/ror.S + // --------------------------------------------------------------------------------------------- + + test_rr_op!(test_ror_2, ror, 0x00000001, 0x00000001, 0); + test_rr_op!(test_ror_3, ror, 0x80000000, 0x00000001, 1); + test_rr_op!(test_ror_4, ror, 0x02000000, 0x00000001, 7); + test_rr_op!(test_ror_5, ror, 0x00040000, 0x00000001, 14); + test_rr_op!(test_ror_6, ror, 0x00000002, 0x00000001, 31); + + test_rr_op!(test_ror_7, ror, 0xffffffff, 0xffffffff, 0); + test_rr_op!(test_ror_8, ror, 0xffffffff, 0xffffffff, 1); + test_rr_op!(test_ror_9, ror, 0xffffffff, 0xffffffff, 7); + test_rr_op!(test_ror_10, ror, 0xffffffff, 0xffffffff, 14); + test_rr_op!(test_ror_11, ror, 0xffffffff, 0xffffffff, 31); + + test_rr_op!(test_ror_12, ror, 0x21212121, 0x21212121, 0); + test_rr_op!(test_ror_13, ror, 0x90909090, 0x21212121, 1); + test_rr_op!(test_ror_14, ror, 0x42424242, 0x21212121, 7); + test_rr_op!(test_ror_15, ror, 0x84848484, 0x21212121, 14); + test_rr_op!(test_ror_16, ror, 0x42424242, 0x21212121, 31); + + // Verify that shifts only use bottom six(rv64) or five(rv32) bits + + test_rr_op!(test_ror_17, ror, 0x21212121, 0x21212121, 0xffffffc0); + test_rr_op!(test_ror_18, ror, 0x90909090, 0x21212121, 0xffffffc1); + test_rr_op!(test_ror_19, ror, 0x42424242, 0x21212121, 0xffffffc7); + test_rr_op!(test_ror_20, ror, 0x84848484, 0x21212121, 0xffffffce); + + test_rr_op!(test_ror_21, ror, 0x42424242, 0x21212121, 0xffffffff); + + test_rr_src1_eq_dest!(test_ror_22, ror, 0x02000000, 0x00000001, 7); + test_rr_src2_eq_dest!(test_ror_23, ror, 0x00040000, 0x00000001, 14); + test_rr_src12_eq_dest!(test_ror_24, ror, 0x60000000, 3); + + test_rr_dest_bypass!(test_ror_25, 0, ror, 0x02000000, 0x00000001, 7); + test_rr_dest_bypass!(test_ror_26, 1, ror, 0x00040000, 0x00000001, 14); + test_rr_dest_bypass!(test_ror_27, 2, ror, 0x00000002, 0x00000001, 31); + + test_rr_src12_bypass!(test_ror_28, 0, 0, ror, 0x02000000, 0x00000001, 7); + test_rr_src12_bypass!(test_ror_29, 0, 1, ror, 0x00040000, 0x00000001, 14); + test_rr_src12_bypass!(test_ror_30, 0, 2, ror, 0x00000002, 0x00000001, 31); + test_rr_src12_bypass!(test_ror_31, 1, 0, ror, 0x02000000, 0x00000001, 7); + test_rr_src12_bypass!(test_ror_32, 1, 1, ror, 0x00040000, 0x00000001, 14); + test_rr_src12_bypass!(test_ror_33, 2, 0, ror, 0x00000002, 0x00000001, 31); + + test_rr_src21_bypass!(test_ror_34, 0, 0, ror, 0x02000000, 0x00000001, 7); + test_rr_src21_bypass!(test_ror_35, 0, 1, ror, 0x00040000, 0x00000001, 14); + test_rr_src21_bypass!(test_ror_36, 0, 2, ror, 0x00000002, 0x00000001, 31); + test_rr_src21_bypass!(test_ror_37, 1, 0, ror, 0x02000000, 0x00000001, 7); + test_rr_src21_bypass!(test_ror_38, 1, 1, ror, 0x00040000, 0x00000001, 14); + test_rr_src21_bypass!(test_ror_39, 2, 0, ror, 0x00000002, 0x00000001, 31); + + test_rr_zerosrc1!(test_ror_40, ror, 0, 15); + test_rr_zerosrc2!(test_ror_41, ror, 32, 32); + test_rr_zerosrc12!(test_ror_42, ror, 0); + test_rr_zerodest!(test_ror_43, ror, 1024, 2048); + + // --------------------------------------------------------------------------------------------- + // Tests for Rotate Right Immediate (`rori`) Instruction + // + // Test suite based on riscv-tests + // https://github.com/riscv-software-src/riscv-tests/blob/master/isa/rv32uzbb/rori.S + // --------------------------------------------------------------------------------------------- + + test_imm_op!(test_rori_2, rori, 0x00000001, 0x00000001, 0); + test_imm_op!(test_rori_3, rori, 0x80000000, 0x00000001, 1); + test_imm_op!(test_rori_4, rori, 0x02000000, 0x00000001, 7); + test_imm_op!(test_rori_5, rori, 0x00040000, 0x00000001, 14); + test_imm_op!(test_rori_6, rori, 0x00000002, 0x00000001, 31); + + test_imm_op!(test_rori_7, rori, 0xffffffff, 0xffffffff, 0); + test_imm_op!(test_rori_8, rori, 0xffffffff, 0xffffffff, 1); + test_imm_op!(test_rori_9, rori, 0xffffffff, 0xffffffff, 7); + test_imm_op!(test_rori_10, rori, 0xffffffff, 0xffffffff, 14); + test_imm_op!(test_rori_11, rori, 0xffffffff, 0xffffffff, 31); + + test_imm_op!(test_rori_12, rori, 0x21212121, 0x21212121, 0); + test_imm_op!(test_rori_13, rori, 0x90909090, 0x21212121, 1); + test_imm_op!(test_rori_14, rori, 0x42424242, 0x21212121, 7); + test_imm_op!(test_rori_15, rori, 0x84848484, 0x21212121, 14); + test_imm_op!(test_rori_16, rori, 0x42424242, 0x21212121, 31); + + test_imm_src1_eq_dest!(test_rori_20, rori, 0x02000000, 0x00000001, 7); + + test_imm_dest_bypass!(test_rori_21, 0, rori, 0x02000000, 0x00000001, 7); + test_imm_dest_bypass!(test_rori_22, 1, rori, 0x00040000, 0x00000001, 14); + test_imm_dest_bypass!(test_rori_23, 2, rori, 0x00000002, 0x00000001, 31); + + test_imm_src1_bypass!(test_rori_24, 0, rori, 0x02000000, 0x00000001, 7); + test_imm_src1_bypass!(test_rori_25, 1, rori, 0x00040000, 0x00000001, 14); + test_imm_src1_bypass!(test_rori_26, 2, rori, 0x00000002, 0x00000001, 31); + + test_imm_zero_src1!(test_rori_27, rori, 0, 31); + test_imm_zero_dest!(test_rori_28, rori, 33, 20); + + // --------------------------------------------------------------------------------------------- + // Tests for Bitwise OR-Combine, byte granule (`orc.b`) Instruction + // + // Test suite based on riscv-tests + // https://github.com/riscv-software-src/riscv-tests/blob/master/isa/rv32uzbb/orc_b.S + // --------------------------------------------------------------------------------------------- + + test_r_op!(test_orcb_2, orc_b, 0x00000000, 0x00000000); + test_r_op!(test_orcb_3, orc_b, 0x000000ff, 0x00000001); + test_r_op!(test_orcb_4, orc_b, 0x000000ff, 0x00000003); + + test_r_op!(test_orcb_5, orc_b, 0xffffff00, 0xffff8000); + test_r_op!(test_orcb_6, orc_b, 0x00ff0000, 0x00800000); + test_r_op!(test_orcb_7, orc_b, 0xffffff00, 0xffff8000); + + test_r_op!(test_orcb_8, orc_b, 0x0000ffff, 0x00007fff); + test_r_op!(test_orcb_9, orc_b, 0xffffffff, 0x7fffffff); + test_r_op!(test_orcb_10, orc_b, 0x00ffffff, 0x0007ffff); + + test_r_op!(test_orcb_11, orc_b, 0xff000000, 0x80000000); + test_r_op!(test_orcb_12, orc_b, 0xffffff00, 0x121f5000); + + test_r_op!(test_orcb_13, orc_b, 0x00000000, 0x00000000); + test_r_op!(test_orcb_14, orc_b, 0x000000ff, 0x0000000e); + test_r_op!(test_orcb_15, orc_b, 0xffffffff, 0x20401341); + + test_r_src1_eq_dest!(test_orcb_16, orc_b, 0xff, 13); + test_r_src1_eq_dest!(test_orcb_17, orc_b, 0xff, 11); + + test_r_dest_bypass!(test_orcb_18, 0, orc_b, 0xff, 13); + test_r_dest_bypass!(test_orcb_29, 1, orc_b, 0xff, 19); + test_r_dest_bypass!(test_orcb_20, 2, orc_b, 0xff, 34); + + test_r_op!(test_orcb_21, orc_b, 0x00ffff00, 0x007f8000); + test_r_op!(test_orcb_22, orc_b, 0x00ffff00, 0x00808000); + test_r_op!(test_orcb_23, orc_b, 0xffffff00, 0x01808000); + + test_r_op!(test_orcb_24, orc_b, 0x0000ffff, 0x00007fff); + test_r_op!(test_orcb_25, orc_b, 0xffffffff, 0x7fffffff); + test_r_op!(test_orcb_26, orc_b, 0x00ffffff, 0x0007ffff); + + // --------------------------------------------------------------------------------------------- + // Tests for Byte-reverse (`rev8`) Instruction + // + // Test suite based on riscv-tests + // https://github.com/riscv-software-src/riscv-tests/blob/master/isa/rv32uzbb/rev8.S + // --------------------------------------------------------------------------------------------- + + test_r_op!(test_rev8_2, rev8, 0x00000000, 0x00000000); + test_r_op!(test_rev8_3, rev8, 0x01000000, 0x00000001); + test_r_op!(test_rev8_4, rev8, 0x03000000, 0x00000003); + + test_r_op!(test_rev8_5, rev8, 0x0080ffff, 0xffff8000); + test_r_op!(test_rev8_6, rev8, 0x00008000, 0x00800000); + test_r_op!(test_rev8_7, rev8, 0x0080ffff, 0xffff8000); + + test_r_op!(test_rev8_8, rev8, 0xff7f0000, 0x00007fff); + test_r_op!(test_rev8_9, rev8, 0xffffff7f, 0x7fffffff); + test_r_op!(test_rev8_10, rev8, 0xffff0700, 0x0007ffff); + + test_r_op!(test_rev8_11, rev8, 0x00000080, 0x80000000); + test_r_op!(test_rev8_12, rev8, 0x00501f12, 0x121f5000); + + test_r_op!(test_rev8_13, rev8, 0x00000000, 0x00000000); + test_r_op!(test_rev8_14, rev8, 0x0e000000, 0x0000000e); + test_r_op!(test_rev8_15, rev8, 0x41134020, 0x20401341); + + test_r_src1_eq_dest!(test_rev8_16, rev8, 0x0d000000, 13); + test_r_src1_eq_dest!(test_rev8_17, rev8, 0x0b000000, 11); + + test_r_dest_bypass!(test_rev8_18, 0, rev8, 0x0d000000, 13); + test_r_dest_bypass!(test_rev8_29, 1, rev8, 0x13000000, 19); + test_r_dest_bypass!(test_rev8_20, 2, rev8, 0x22000000, 34); + + test_r_op!(test_rev8_21, rev8, 0x00807f00, 0x007f8000); + test_r_op!(test_rev8_22, rev8, 0x00808000, 0x00808000); + test_r_op!(test_rev8_23, rev8, 0x00808001, 0x01808000); + + test_r_op!(test_rev8_24, rev8, 0xff7f0000, 0x00007fff); + test_r_op!(test_rev8_25, rev8, 0xffffff7f, 0x7fffffff); + test_r_op!(test_rev8_26, rev8, 0xffff0700, 0x0007ffff); + + // --------------------------------------------------------------------------------------------- + // Tests for Count leading zero bits (`clz`) Instruction + // + // Test suite based on riscv-tests + // https://github.com/riscv-software-src/riscv-tests/blob/master/isa/rv32uzbb/clz.S + // --------------------------------------------------------------------------------------------- + + test_r_op!(test_clz_2, clz, 32, 0x00000000); + test_r_op!(test_clz_3, clz, 31, 0x00000001); + test_r_op!(test_clz_4, clz, 30, 0x00000003); + + test_r_op!(test_clz_5, clz, 0, 0xffff8000); + test_r_op!(test_clz_6, clz, 8, 0x00800000); + test_r_op!(test_clz_7, clz, 0, 0xffff8000); + + test_r_op!(test_clz_8, clz, 17, 0x00007fff); + test_r_op!(test_clz_9, clz, 1, 0x7fffffff); + test_r_op!(test_clz_10, clz, 13, 0x0007ffff); + + test_r_op!(test_clz_11, clz, 0, 0x80000000); + test_r_op!(test_clz_12, clz, 3, 0x121f5000); + + test_r_op!(test_clz_13, clz, 5, 0x04000000); + test_r_op!(test_clz_14, clz, 28, 0x0000000e); + test_r_op!(test_clz_15, clz, 2, 0x20401341); + + test_r_src1_eq_dest!(test_clz_16, clz, 28, 13); + test_r_src1_eq_dest!(test_clz_17, clz, 28, 11); + + test_r_dest_bypass!(test_clz_18, 0, clz, 28, 13); + test_r_dest_bypass!(test_clz_29, 1, clz, 27, 19); + test_r_dest_bypass!(test_clz_20, 2, clz, 26, 34); + + test_r_op!(test_clz_21, clz, 5, 0x070f8000); + test_r_op!(test_clz_22, clz, 4, 0x08008000); + test_r_op!(test_clz_23, clz, 3, 0x18008000); + + test_r_op!(test_clz_24, clz, 17, 0x00007fff); + test_r_op!(test_clz_25, clz, 1, 0x7fffffff); + test_r_op!(test_clz_26, clz, 13, 0x0007ffff); + + // --------------------------------------------------------------------------------------------- + // Tests for Count trailing zero bits (`ctz`) Instruction + // + // Test suite based on riscv-tests + // https://github.com/riscv-software-src/riscv-tests/blob/master/isa/rv32uzbb/ctz.S + // --------------------------------------------------------------------------------------------- + + test_r_op!(test_ctz_2, ctz, 32, 0x00000000); + test_r_op!(test_ctz_3, ctz, 0, 0x00000001); + test_r_op!(test_ctz_4, ctz, 0, 0x00000003); + + test_r_op!(test_ctz_5, ctz, 15, 0xffff8000); + test_r_op!(test_ctz_6, ctz, 23, 0x00800000); + test_r_op!(test_ctz_7, ctz, 15, 0xffff8000); + + test_r_op!(test_ctz_8, ctz, 0, 0x00007fff); + test_r_op!(test_ctz_9, ctz, 0, 0x7fffffff); + test_r_op!(test_ctz_10, ctz, 0, 0x0007ffff); + + test_r_op!(test_ctz_11, ctz, 31, 0x80000000); + test_r_op!(test_ctz_12, ctz, 12, 0x121f5000); + + test_r_op!(test_ctz_13, ctz, 30, 0xc0000000); + test_r_op!(test_ctz_14, ctz, 1, 0x0000000e); + test_r_op!(test_ctz_15, ctz, 0, 0x20401341); + + test_r_src1_eq_dest!(test_ctz_16, ctz, 0, 13); + test_r_src1_eq_dest!(test_ctz_17, ctz, 0, 11); + + test_r_dest_bypass!(test_ctz_18, 0, ctz, 0, 13); + test_r_dest_bypass!(test_ctz_29, 1, ctz, 0, 19); + test_r_dest_bypass!(test_ctz_20, 2, ctz, 1, 34); + + test_r_op!(test_ctz_21, ctz, 15, 0x007f8000); + test_r_op!(test_ctz_22, ctz, 15, 0x00808000); + test_r_op!(test_ctz_23, ctz, 12, 0x01809000); + + test_r_op!(test_ctz_24, ctz, 0, 0x00007fff); + test_r_op!(test_ctz_25, ctz, 0, 0x7fffffff); + test_r_op!(test_ctz_26, ctz, 0, 0x0007ffff); + + // --------------------------------------------------------------------------------------------- + // Tests for Count set bits (`cpop`) Instruction + // + // Test suite based on riscv-tests + // https://github.com/riscv-software-src/riscv-tests/blob/master/isa/rv32uzbb/cpop.S + // --------------------------------------------------------------------------------------------- + + test_r_op!(test_cpop_2, cpop, 0, 0x00000000); + test_r_op!(test_cpop_3, cpop, 1, 0x00000001); + test_r_op!(test_cpop_4, cpop, 2, 0x00000003); + + test_r_op!(test_cpop_5, cpop, 17, 0xffff8000); + test_r_op!(test_cpop_6, cpop, 1, 0x00800000); + test_r_op!(test_cpop_7, cpop, 18, 0xffff6000); + + test_r_op!(test_cpop_8, cpop, 15, 0x00007fff); + test_r_op!(test_cpop_9, cpop, 31, 0x7fffffff); + test_r_op!(test_cpop_10, cpop, 19, 0x0007ffff); + + test_r_op!(test_cpop_11, cpop, 1, 0x80000000); + test_r_op!(test_cpop_12, cpop, 9, 0x121f5000); + + test_r_op!(test_cpop_13, cpop, 0, 0x00000000); + test_r_op!(test_cpop_14, cpop, 3, 0x0000000e); + test_r_op!(test_cpop_15, cpop, 7, 0x20401341); + + test_r_src1_eq_dest!(test_cpop_16, cpop, 3, 13); + test_r_src1_eq_dest!(test_cpop_17, cpop, 3, 11); + + test_r_dest_bypass!(test_cpop_18, 0, cpop, 3, 13); + test_r_dest_bypass!(test_cpop_29, 1, cpop, 3, 19); + test_r_dest_bypass!(test_cpop_20, 2, cpop, 2, 34); + + test_r_op!(test_cpop_21, cpop, 8, 0x007f8000); + test_r_op!(test_cpop_22, cpop, 2, 0x00808000); + test_r_op!(test_cpop_23, cpop, 3, 0x01808000); + + test_r_op!(test_cpop_24, cpop, 17, 0x30007fff); + test_r_op!(test_cpop_25, cpop, 30, 0x77ffffff); + test_r_op!(test_cpop_26, cpop, 19, 0x0007ffff); + + // --------------------------------------------------------------------------------------------- + // Tests for Sign-extend byte (`sext.b`) Instruction + // + // Test suite based on riscv-tests + // https://github.com/riscv-software-src/riscv-tests/blob/master/isa/rv64uzbb/sext_b.S + // --------------------------------------------------------------------------------------------- + + test_r_op!(test_sext_b_2, sext_b, 0x00000000, 0x00000000); + test_r_op!(test_sext_b_3, sext_b, 0x00000001, 0x00000001); + test_r_op!(test_sext_b_4, sext_b, 0x00000003, 0x00000003); + + test_r_op!(test_sext_b_5, sext_b, 0x00000000, 0xffff8000); + test_r_op!(test_sext_b_6, sext_b, 0x00000000, 0x00800000); + test_r_op!(test_sext_b_7, sext_b, 0x00000000, 0xffff8000); + + test_r_op!(test_sext_b_8, sext_b, 0xffffffff, 0x00007fff); + test_r_op!(test_sext_b_9, sext_b, 0xffffffff, 0x7fffffff); + test_r_op!(test_sext_b_10, sext_b, 0xffffffff, 0x0007ffff); + + test_r_op!(test_sext_b_11, sext_b, 0x00000000, 0x80000000); + test_r_op!(test_sext_b_12, sext_b, 0x00000000, 0x121f5000); + + test_r_op!(test_sext_b_13, sext_b, 0x00000000, 0x00000000); + test_r_op!(test_sext_b_14, sext_b, 0x0000000e, 0x0000000e); + test_r_op!(test_sext_b_15, sext_b, 0x00000041, 0x20401341); + + test_r_src1_eq_dest!(test_sext_b_16, sext_b, 0x0000000d, 13); + test_r_src1_eq_dest!(test_sext_b_17, sext_b, 0x0000000b, 11); + + test_r_dest_bypass!(test_sext_b_18, 0, sext_b, 0x0000000d, 13); + test_r_dest_bypass!(test_sext_b_29, 1, sext_b, 0x00000013, 19); + test_r_dest_bypass!(test_sext_b_20, 2, sext_b, 0x00000022, 34); + + test_r_op!(test_sext_b_21, sext_b, 0x00000000, 0x007f8000); + test_r_op!(test_sext_b_22, sext_b, 0x00000000, 0x00808000); + test_r_op!(test_sext_b_23, sext_b, 0x00000000, 0x01808000); + + test_r_op!(test_sext_b_24, sext_b, 0xffffffff, 0x00007fff); + test_r_op!(test_sext_b_25, sext_b, 0xffffffff, 0x7fffffff); + test_r_op!(test_sext_b_26, sext_b, 0xffffffff, 0x0007ffff); + + // --------------------------------------------------------------------------------------------- + // Tests for Sign-extend halfword (`sext.h`) Instruction + // + // Test suite based on riscv-tests + // https://github.com/riscv-software-src/riscv-tests/blob/master/isa/rv64uzbb/sext_h.S + // --------------------------------------------------------------------------------------------- + + test_r_op!(test_sext_h_2, sext_h, 0x00000000, 0x00000000); + test_r_op!(test_sext_h_3, sext_h, 0x00000001, 0x00000001); + test_r_op!(test_sext_h_4, sext_h, 0x00000003, 0x00000003); + + test_r_op!(test_sext_h_5, sext_h, 0xffff8000, 0xffff8000); + test_r_op!(test_sext_h_6, sext_h, 0x00000000, 0x00800000); + test_r_op!(test_sext_h_7, sext_h, 0xffff8000, 0xffff8000); + + test_r_op!(test_sext_h_8, sext_h, 0x00007fff, 0x00007fff); + test_r_op!(test_sext_h_9, sext_h, 0xffffffff, 0x7fffffff); + test_r_op!(test_sext_h_10, sext_h, 0xffffffff, 0x0007ffff); + + test_r_op!(test_sext_h_11, sext_h, 0x00000000, 0x80000000); + test_r_op!(test_sext_h_12, sext_h, 0x00005000, 0x121f5000); + + test_r_op!(test_sext_h_13, sext_h, 0x00000000, 0x00000000); + test_r_op!(test_sext_h_14, sext_h, 0x0000000e, 0x0000000e); + test_r_op!(test_sext_h_15, sext_h, 0x00001341, 0x20401341); + + test_r_src1_eq_dest!(test_sext_h_16, sext_h, 0x0000000d, 13); + test_r_src1_eq_dest!(test_sext_h_17, sext_h, 0x0000000b, 11); + + test_r_dest_bypass!(test_sext_h_18, 0, sext_h, 0x0000000d, 13); + test_r_dest_bypass!(test_sext_h_29, 1, sext_h, 0x00000013, 19); + test_r_dest_bypass!(test_sext_h_20, 2, sext_h, 0x00000022, 34); + + test_r_op!(test_sext_h_21, sext_h, 0xffff8000, 0x007f8000); + test_r_op!(test_sext_h_22, sext_h, 0xffff8000, 0x00808000); + test_r_op!(test_sext_h_23, sext_h, 0xffff8000, 0x01808000); + + test_r_op!(test_sext_h_24, sext_h, 0x00007fff, 0x00007fff); + test_r_op!(test_sext_h_25, sext_h, 0xffffffff, 0x7fffffff); + test_r_op!(test_sext_h_26, sext_h, 0xffffffff, 0x0007ffff); + + // --------------------------------------------------------------------------------------------- + // Tests for Singe-bit invert (`binv`) Instruction + // + // Test suite based on riscv-tests + // https://github.com/riscv-software-src/riscv-tests/blob/master/isa/rv64uzbs/binv.S + // --------------------------------------------------------------------------------------------- + + test_rr_op!(test_binv_2, binv, 0x00000000, 0x00000001, 0); + test_rr_op!(test_binv_3, binv, 0x00000003, 0x00000001, 1); + test_rr_op!(test_binv_4, binv, 0x00000081, 0x00000001, 7); + test_rr_op!(test_binv_5, binv, 0x00004001, 0x00000001, 14); + test_rr_op!(test_binv_6, binv, 0x80000001, 0x00000001, 31); + + test_rr_op!(test_binv_7, binv, 0xfffffffe, 0xffffffff, 0); + test_rr_op!(test_binv_8, binv, 0xfffffffd, 0xffffffff, 1); + test_rr_op!(test_binv_9, binv, 0xffffff7f, 0xffffffff, 7); + test_rr_op!(test_binv_10, binv, 0xffffbfff, 0xffffffff, 14); + test_rr_op!(test_binv_11, binv, 0x7fffffff, 0xffffffff, 31); + + test_rr_op!(test_binv_12, binv, 0x21212120, 0x21212121, 0); + test_rr_op!(test_binv_13, binv, 0x21212123, 0x21212121, 1); + test_rr_op!(test_binv_14, binv, 0x212121a1, 0x21212121, 7); + test_rr_op!(test_binv_15, binv, 0x21216121, 0x21212121, 14); + test_rr_op!(test_binv_16, binv, 0xa1212121, 0x21212121, 31); + + // Verify that shifts only use bottom six(rv64) or five(rv32) bits + + test_rr_op!(test_binv_17, binv, 0x21212120, 0x21212121, 0xffffffc0); + test_rr_op!(test_binv_18, binv, 0x21212123, 0x21212121, 0xffffffc1); + test_rr_op!(test_binv_19, binv, 0x212121a1, 0x21212121, 0xffffffc7); + test_rr_op!(test_binv_20, binv, 0x21216121, 0x21212121, 0xffffffce); + + test_rr_src1_eq_dest!(test_binv_22, binv, 0x00000081, 0x00000001, 7); + test_rr_src2_eq_dest!(test_binv_23, binv, 0x00004001, 0x00000001, 14); + test_rr_src12_eq_dest!(test_binv_24, binv, 11, 3); + + test_rr_dest_bypass!(test_binv_25, 0, binv, 0x00000081, 0x00000001, 7); + test_rr_dest_bypass!(test_binv_26, 1, binv, 0x00004001, 0x00000001, 14); + test_rr_dest_bypass!(test_binv_27, 2, binv, 0x80000001, 0x00000001, 31); + + test_rr_src12_bypass!(test_binv_28, 0, 0, binv, 0x00000081, 0x00000001, 7); + test_rr_src12_bypass!(test_binv_29, 0, 1, binv, 0x00004001, 0x00000001, 14); + test_rr_src12_bypass!(test_binv_30, 0, 2, binv, 0x80000001, 0x00000001, 31); + test_rr_src12_bypass!(test_binv_31, 1, 0, binv, 0x00000081, 0x00000001, 7); + test_rr_src12_bypass!(test_binv_32, 1, 1, binv, 0x00004001, 0x00000001, 14); + test_rr_src12_bypass!(test_binv_33, 2, 0, binv, 0x80000001, 0x00000001, 31); + + test_rr_src21_bypass!(test_binv_34, 0, 0, binv, 0x00000081, 0x00000001, 7); + test_rr_src21_bypass!(test_binv_35, 0, 1, binv, 0x00004001, 0x00000001, 14); + test_rr_src21_bypass!(test_binv_36, 0, 2, binv, 0x80000001, 0x00000001, 31); + test_rr_src21_bypass!(test_binv_37, 1, 0, binv, 0x00000081, 0x00000001, 7); + test_rr_src21_bypass!(test_binv_38, 1, 1, binv, 0x00004001, 0x00000001, 14); + test_rr_src21_bypass!(test_binv_39, 2, 0, binv, 0x80000001, 0x00000001, 31); + + test_rr_zerosrc1!(test_binv_40, binv, 0x00008000, 15); + test_rr_zerosrc2!(test_binv_41, binv, 33, 32); + test_rr_zerosrc12!(test_binv_42, binv, 1); + test_rr_zerodest!(test_binv_43, binv, 1024, 2048); + + // --------------------------------------------------------------------------------------------- + // Tests for Singe-bit invert immediate (`binvi`) Instruction + // + // Test suite based on riscv-tests + // https://github.com/riscv-software-src/riscv-tests/blob/master/isa/rv64uzbs/binvi.S + // --------------------------------------------------------------------------------------------- + + test_imm_op!(test_binvi_2, binvi, 0x00000000, 0x00000001, 0); + test_imm_op!(test_binvi_3, binvi, 0x00000003, 0x00000001, 1); + test_imm_op!(test_binvi_4, binvi, 0x00000081, 0x00000001, 7); + test_imm_op!(test_binvi_5, binvi, 0x00004001, 0x00000001, 14); + test_imm_op!(test_binvi_6, binvi, 0x80000001, 0x00000001, 31); + + test_imm_op!(test_binvi_7, binvi, 0xfffffffe, 0xffffffff, 0); + test_imm_op!(test_binvi_8, binvi, 0xfffffffd, 0xffffffff, 1); + test_imm_op!(test_binvi_9, binvi, 0xffffff7f, 0xffffffff, 7); + test_imm_op!(test_binvi_10, binvi, 0xffffbfff, 0xffffffff, 14); + test_imm_op!(test_binvi_11, binvi, 0x7fffffff, 0xffffffff, 31); + + test_imm_op!(test_binvi_12, binvi, 0x21212120, 0x21212121, 0); + test_imm_op!(test_binvi_13, binvi, 0x21212123, 0x21212121, 1); + test_imm_op!(test_binvi_14, binvi, 0x212121a1, 0x21212121, 7); + test_imm_op!(test_binvi_15, binvi, 0x21216121, 0x21212121, 14); + test_imm_op!(test_binvi_16, binvi, 0xa1212121, 0x21212121, 31); + + test_imm_src1_eq_dest!(test_binvi_17, binvi, 0x00000081, 0x00000001, 7); + + test_imm_dest_bypass!(test_binvi_18, 0, binvi, 0x00000081, 0x00000001, 7); + test_imm_dest_bypass!(test_binvi_19, 1, binvi, 0x00004001, 0x00000001, 14); + test_imm_dest_bypass!(test_binvi_20, 2, binvi, 0x80000001, 0x00000001, 31); + + test_imm_src1_bypass!(test_binvi_21, 0, binvi, 0x00000081, 0x00000001, 7); + test_imm_src1_bypass!(test_binvi_22, 1, binvi, 0x00004001, 0x00000001, 14); + test_imm_src1_bypass!(test_binvi_23, 2, binvi, 0x80000001, 0x00000001, 31); + + test_imm_zero_src1!(test_binvi_24, binvi, 0x00008000, 15); + test_imm_zero_dest!(test_binvi_25, binvi, 1024, 10); + + // --------------------------------------------------------------------------------------------- + // Tests for Carry-less multiply low-part (`clmul`) Instruction + // + // Test suite based on riscv-tests + // https://github.com/riscv-software-src/riscv-tests/blob/master/isa/rv32uzbc/clmul.S + // --------------------------------------------------------------------------------------------- + + test_rr_op!(test_clmul_32, clmul, 0x00005a00, 0x00007e00, 0xb6db6db7); + test_rr_op!(test_clmul_33, clmul, 0x00005b40, 0x00007fc0, 0xb6db6db7); + + test_rr_op!(test_clmul_2, clmul, 0x00000000, 0x00000000, 0x00000000); + test_rr_op!(test_clmul_3, clmul, 0x00000001, 0x00000001, 0x00000001); + test_rr_op!(test_clmul_4, clmul, 0x00000009, 0x00000003, 0x00000007); + + test_rr_op!(test_clmul_5, clmul, 0x00000000, 0x00000000, 0xffff8000); + test_rr_op!(test_clmul_6, clmul, 0x00000000, 0x80000000, 0x00000000); + test_rr_op!(test_clmul_7, clmul, 0x00000000, 0x80000000, 0xffff8000); + + test_rr_op!(test_clmul_30, clmul, 0xfffc324f, 0xaaaaaaab, 0x0002fe7d); + test_rr_op!(test_clmul_31, clmul, 0xfffc324f, 0x0002fe7d, 0xaaaaaaab); + + test_rr_op!(test_clmul_34, clmul, 0x00000000, 0xff000000, 0xff000000); + + test_rr_op!(test_clmul_35, clmul, 0x55555555, 0xffffffff, 0xffffffff); + test_rr_op!(test_clmul_36, clmul, 0xffffffff, 0xffffffff, 0x00000001); + test_rr_op!(test_clmul_37, clmul, 0xffffffff, 0x00000001, 0xffffffff); + + test_rr_src1_eq_dest!(test_clmul_8, clmul, 0x7f, 13, 11); + test_rr_src2_eq_dest!(test_clmul_9, clmul, 0x62, 14, 11); + test_rr_src12_eq_dest!(test_clmul_10, clmul, 0x51, 13); + + test_rr_dest_bypass!(test_clmul_11, 0, clmul, 0x7f, 13, 11); + test_rr_dest_bypass!(test_clmul_12, 1, clmul, 0x62, 14, 11); + test_rr_dest_bypass!(test_clmul_13, 2, clmul, 0x69, 15, 11); + + test_rr_src12_bypass!(test_clmul_14, 0, 0, clmul, 0x7f, 13, 11); + test_rr_src12_bypass!(test_clmul_15, 0, 1, clmul, 0x62, 14, 11); + test_rr_src12_bypass!(test_clmul_16, 0, 2, clmul, 0x69, 15, 11); + test_rr_src12_bypass!(test_clmul_17, 1, 0, clmul, 0x7f, 13, 11); + test_rr_src12_bypass!(test_clmul_18, 1, 1, clmul, 0x62, 14, 11); + test_rr_src12_bypass!(test_clmul_19, 2, 0, clmul, 0x69, 15, 11); + + test_rr_src21_bypass!(test_clmul_20, 0, 0, clmul, 0x7f, 13, 11); + test_rr_src21_bypass!(test_clmul_21, 0, 1, clmul, 0x62, 14, 11); + test_rr_src21_bypass!(test_clmul_22, 0, 2, clmul, 0x69, 15, 11); + test_rr_src21_bypass!(test_clmul_23, 1, 0, clmul, 0x7f, 13, 11); + test_rr_src21_bypass!(test_clmul_24, 1, 1, clmul, 0x62, 14, 11); + test_rr_src21_bypass!(test_clmul_25, 2, 0, clmul, 0x69, 15, 11); + + test_rr_zerosrc1!(test_clmul_26, clmul, 0, 31); + test_rr_zerosrc2!(test_clmul_27, clmul, 0, 32); + test_rr_zerosrc12!(test_clmul_28, clmul, 0); + test_rr_zerodest!(test_clmul_29, clmul, 33, 34); + + // --------------------------------------------------------------------------------------------- + // Tests for Carry-less multiply high-part (`clmulh`) Instruction + // + // Test suite based on riscv-tests + // https://github.com/riscv-software-src/riscv-tests/blob/master/isa/rv32uzbc/clmulh.S + // --------------------------------------------------------------------------------------------- + + test_rr_op!(test_clmulh_32, clmulh, 0x00003600, 0x00007e00, 0xb6db6db7); + test_rr_op!(test_clmulh_33, clmulh, 0x000036c0, 0x00007fc0, 0xb6db6db7); + + test_rr_op!(test_clmulh_2, clmulh, 0x00000000, 0x00000000, 0x00000000); + test_rr_op!(test_clmulh_3, clmulh, 0x00000000, 0x00000001, 0x00000001); + test_rr_op!(test_clmulh_4, clmulh, 0x00000000, 0x00000003, 0x00000007); + + test_rr_op!(test_clmulh_5, clmulh, 0x00000000, 0x00000000, 0xffff8000); + test_rr_op!(test_clmulh_6, clmulh, 0x00000000, 0x80000000, 0x00000000); + test_rr_op!(test_clmulh_7, clmulh, 0x7fffc000, 0x80000000, 0xffff8000); + + test_rr_op!(test_clmulh_30, clmulh, 0x000133cd, 0xaaaaaaab, 0x0002fe7d); + test_rr_op!(test_clmulh_31, clmulh, 0x000133cd, 0x0002fe7d, 0xaaaaaaab); + + test_rr_op!(test_clmulh_34, clmulh, 0x55550000, 0xff000000, 0xff000000); + + test_rr_op!(test_clmulh_35, clmulh, 0x55555555, 0xffffffff, 0xffffffff); + test_rr_op!(test_clmulh_36, clmulh, 0x00000000, 0xffffffff, 0x00000001); + test_rr_op!(test_clmulh_37, clmulh, 0x00000000, 0x00000001, 0xffffffff); + + test_rr_src1_eq_dest!(test_clmulh_8, clmulh, 0, 13, 11); + test_rr_src2_eq_dest!(test_clmulh_9, clmulh, 0, 14, 11); + test_rr_src12_eq_dest!(test_clmulh_10, clmulh, 0, 13); + + test_rr_dest_bypass!(test_clmulh_11, 0, clmulh, 0, 13, 11); + test_rr_dest_bypass!(test_clmulh_12, 1, clmulh, 0, 14, 11); + test_rr_dest_bypass!(test_clmulh_13, 2, clmulh, 0, 15, 11); + + test_rr_src12_bypass!(test_clmulh_14, 0, 0, clmulh, 0, 13, 11); + test_rr_src12_bypass!(test_clmulh_15, 0, 1, clmulh, 0, 14, 11); + test_rr_src12_bypass!(test_clmulh_16, 0, 2, clmulh, 0, 15, 11); + test_rr_src12_bypass!(test_clmulh_17, 1, 0, clmulh, 0, 13, 11); + test_rr_src12_bypass!(test_clmulh_18, 1, 1, clmulh, 0, 14, 11); + test_rr_src12_bypass!(test_clmulh_19, 2, 0, clmulh, 0, 15, 11); + + test_rr_src21_bypass!(test_clmulh_20, 0, 0, clmulh, 0, 13, 11); + test_rr_src21_bypass!(test_clmulh_21, 0, 1, clmulh, 0, 14, 11); + test_rr_src21_bypass!(test_clmulh_22, 0, 2, clmulh, 0, 15, 11); + test_rr_src21_bypass!(test_clmulh_23, 1, 0, clmulh, 0, 13, 11); + test_rr_src21_bypass!(test_clmulh_24, 1, 1, clmulh, 0, 14, 11); + test_rr_src21_bypass!(test_clmulh_25, 2, 0, clmulh, 0, 15, 11); + + test_rr_zerosrc1!(test_clmulh_26, clmulh, 0, 31); + test_rr_zerosrc2!(test_clmulh_27, clmulh, 0, 32); + test_rr_zerosrc12!(test_clmulh_28, clmulh, 0); + test_rr_zerodest!(test_clmulh_29, clmulh, 33, 34); + + // --------------------------------------------------------------------------------------------- + // Tests for Carry-less multiply reversed (`clmulr`) Instruction + // + // Test suite based on riscv-tests + // https://github.com/riscv-software-src/riscv-tests/blob/master/isa/rv32uzbc/clmulr.S + // --------------------------------------------------------------------------------------------- + + test_rr_op!(test_clmulr_32, clmulr, 0x00006c00, 0x00007e00, 0xb6db6db7); + test_rr_op!(test_clmulr_33, clmulr, 0x00006d80, 0x00007fc0, 0xb6db6db7); + + test_rr_op!(test_clmulr_2, clmulr, 0x00000000, 0x00000000, 0x00000000); + test_rr_op!(test_clmulr_3, clmulr, 0x00000000, 0x00000001, 0x00000001); + test_rr_op!(test_clmulr_4, clmulr, 0x00000000, 0x00000003, 0x00000007); + + test_rr_op!(test_clmulr_5, clmulr, 0x00000000, 0x00000000, 0xffff8000); + test_rr_op!(test_clmulr_6, clmulr, 0x00000000, 0x80000000, 0x00000000); + test_rr_op!(test_clmulr_7, clmulr, 0xffff8000, 0x80000000, 0xffff8000); + + test_rr_op!(test_clmulr_30, clmulr, 0x0002679b, 0xaaaaaaab, 0x0002fe7d); + test_rr_op!(test_clmulr_31, clmulr, 0x0002679b, 0x0002fe7d, 0xaaaaaaab); + + test_rr_op!(test_clmulr_34, clmulr, 0xaaaa0000, 0xff000000, 0xff000000); + + test_rr_op!(test_clmulr_35, clmulr, 0xaaaaaaaa, 0xffffffff, 0xffffffff); + test_rr_op!(test_clmulr_36, clmulr, 0x00000001, 0xffffffff, 0x00000001); + test_rr_op!(test_clmulr_37, clmulr, 0x00000001, 0x00000001, 0xffffffff); + + test_rr_src1_eq_dest!(test_clmulr_8, clmulr, 0, 13, 11); + test_rr_src2_eq_dest!(test_clmulr_9, clmulr, 0, 14, 11); + test_rr_src12_eq_dest!(test_clmulr_10, clmulr, 0, 13); + + test_rr_dest_bypass!(test_clmulr_11, 0, clmulr, 0, 13, 11); + test_rr_dest_bypass!(test_clmulr_12, 1, clmulr, 0, 14, 11); + test_rr_dest_bypass!(test_clmulr_13, 2, clmulr, 0, 15, 11); + + test_rr_src12_bypass!(test_clmulr_14, 0, 0, clmulr, 0, 13, 11); + test_rr_src12_bypass!(test_clmulr_15, 0, 1, clmulr, 0, 14, 11); + test_rr_src12_bypass!(test_clmulr_16, 0, 2, clmulr, 0, 15, 11); + test_rr_src12_bypass!(test_clmulr_17, 1, 0, clmulr, 0, 13, 11); + test_rr_src12_bypass!(test_clmulr_18, 1, 1, clmulr, 0, 14, 11); + test_rr_src12_bypass!(test_clmulr_19, 2, 0, clmulr, 0, 15, 11); + + test_rr_src21_bypass!(test_clmulr_20, 0, 0, clmulr, 0, 13, 11); + test_rr_src21_bypass!(test_clmulr_21, 0, 1, clmulr, 0, 14, 11); + test_rr_src21_bypass!(test_clmulr_22, 0, 2, clmulr, 0, 15, 11); + test_rr_src21_bypass!(test_clmulr_23, 1, 0, clmulr, 0, 13, 11); + test_rr_src21_bypass!(test_clmulr_24, 1, 1, clmulr, 0, 14, 11); + test_rr_src21_bypass!(test_clmulr_25, 2, 0, clmulr, 0, 15, 11); + + test_rr_zerosrc1!(test_clmulr_26, clmulr, 0, 31); + test_rr_zerosrc2!(test_clmulr_27, clmulr, 0, 32); + test_rr_zerosrc12!(test_clmulr_28, clmulr, 0); + test_rr_zerodest!(test_clmulr_29, clmulr, 33, 34); +} diff --git a/sw-emulator/lib/cpu/src/instr/mod.rs b/sw-emulator/lib/cpu/src/instr/mod.rs index 6bcf263a14..08aee4a1a1 100644 --- a/sw-emulator/lib/cpu/src/instr/mod.rs +++ b/sw-emulator/lib/cpu/src/instr/mod.rs @@ -16,6 +16,7 @@ References: --*/ mod auipc; +mod bit; mod branch; mod compression; mod fence; diff --git a/sw-emulator/lib/cpu/src/instr/op.rs b/sw-emulator/lib/cpu/src/instr/op.rs index faf0e25328..1ef616c525 100644 --- a/sw-emulator/lib/cpu/src/instr/op.rs +++ b/sw-emulator/lib/cpu/src/instr/op.rs @@ -18,7 +18,6 @@ References: use crate::cpu::Cpu; use crate::types::{RvInstr32OpFunct3, RvInstr32OpFunct7, RvInstr32Opcode, RvInstr32R}; -use crate::xreg_file::XReg; use caliptra_emu_bus::Bus; use caliptra_emu_types::{RvData, RvException}; @@ -161,44 +160,11 @@ impl Cpu { } } - // AND with inverted operand - (RvInstr32OpFunct3::Seven, RvInstr32OpFunct7::Andn) => val1 & !val2, - - // OR with inverted operand - (RvInstr32OpFunct3::Six, RvInstr32OpFunct7::Orn) => val1 | !val2, - - // Exclusive NOR - (RvInstr32OpFunct3::Four, RvInstr32OpFunct7::Xnor) => !(val1 ^ val2), - - // Maximum - (RvInstr32OpFunct3::Six, RvInstr32OpFunct7::MinMaxClmul) => { - i32::max(val1 as i32, val2 as i32) as u32 - } - - // Maximum unsigned - (RvInstr32OpFunct3::Seven, RvInstr32OpFunct7::MinMaxClmul) => u32::max(val1, val2), - - // Minimum - (RvInstr32OpFunct3::Four, RvInstr32OpFunct7::MinMaxClmul) => { - i32::min(val1 as i32, val2 as i32) as u32 - } - - // Minimum unsigned - (RvInstr32OpFunct3::Five, RvInstr32OpFunct7::MinMaxClmul) => u32::min(val1, val2), - - // Zero-extend halfword - (RvInstr32OpFunct3::Four, RvInstr32OpFunct7::Zext) if instr.rs2() == XReg::X0 => { - val1 & 0xffff - } - - // Rotate left - (RvInstr32OpFunct3::One, RvInstr32OpFunct7::Rotate) => val1.rotate_left(val2 & 0x1f), - - // Rotate right - (RvInstr32OpFunct3::Five, RvInstr32OpFunct7::Rotate) => val1.rotate_right(val2 & 0x1f), - // Illegal instruction - _ => Err(RvException::illegal_instr(instr.0))?, + _ => match self.exec_bit_instr_op(instr, val1, val2) { + Some(val) => val, + _ => Err(RvException::illegal_instr(instr.0))?, + }, }; self.write_xreg(instr.rd(), data) diff --git a/sw-emulator/lib/cpu/src/instr/op_imm.rs b/sw-emulator/lib/cpu/src/instr/op_imm.rs index 2a155d479c..b6498f73b5 100644 --- a/sw-emulator/lib/cpu/src/instr/op_imm.rs +++ b/sw-emulator/lib/cpu/src/instr/op_imm.rs @@ -39,107 +39,69 @@ impl Cpu { // Read the content of source register let reg = self.read_xreg(instr.rs())?; - let data = match instr.funct3().into() { - // Add Immediate (`addi`) Instruction - RvInstr32OpImmFunct3::Addi => reg.wrapping_add(instr.imm() as u32) as RvData, - - RvInstr32OpImmFunct3::Sli => { - match instr.funct7().into() { - // Shift Left Logical Immediate (`slli`) Instruction - RvInstr32OpImmFunct7::Slli => reg.wrapping_shl(instr.shamt()) as RvData, - - // Count leading zeroes - RvInstr32OpImmFunct7::Bitmanip if instr.funct5() == 0b0_0000 => { - reg.leading_zeros() - } - - // Count trailing zeroes - RvInstr32OpImmFunct7::Bitmanip if instr.funct5() == 0b0_0001 => { - reg.trailing_zeros() - } - - // Count set bits - RvInstr32OpImmFunct7::Bitmanip if instr.funct5() == 0b0_0010 => { - reg.count_ones() - } - - // Sign-extend byte - RvInstr32OpImmFunct7::Bitmanip if instr.funct5() == 0b0_0100 => { - reg as i8 as i32 as u32 + let data = if let Some(data) = self.exec_bit_instr_op_imm(instr, reg) { + data + } else { + match instr.funct3().into() { + // Add Immediate (`addi`) Instruction + RvInstr32OpImmFunct3::Addi => reg.wrapping_add(instr.imm() as u32) as RvData, + + RvInstr32OpImmFunct3::Sli => { + match instr.funct7().into() { + // Shift Left Logical Immediate (`slli`) Instruction + RvInstr32OpImmFunct7::Slli => reg.wrapping_shl(instr.shamt()) as RvData, + + // Illegal Instruction + _ => Err(RvException::illegal_instr(instr.0))?, } + } - // Sign-extend halfword - RvInstr32OpImmFunct7::Bitmanip if instr.funct5() == 0b0_0101 => { - reg as i16 as i32 as u32 + // Set Less Than Immediate (`slti`) Instruction + RvInstr32OpImmFunct3::Slti => { + if (reg as i32) < instr.imm() { + 1 + } else { + 0 } - - // Illegal Instruction - _ => Err(RvException::illegal_instr(instr.0))?, } - } - // Set Less Than Immediate (`slti`) Instruction - RvInstr32OpImmFunct3::Slti => { - if (reg as i32) < instr.imm() { - 1 - } else { - 0 + // Set Less Than Immediate Unsigned (`sltiu`) Instruction + RvInstr32OpImmFunct3::Sltiu => { + if reg < instr.imm() as u32 { + 1 + } else { + 0 + } } - } - // Set Less Than Immediate Unsigned (`sltiu`) Instruction - RvInstr32OpImmFunct3::Sltiu => { - if reg < instr.imm() as u32 { - 1 - } else { - 0 - } - } + // Xor Immediate (`xori`) Instruction + RvInstr32OpImmFunct3::Xori => reg ^ instr.imm() as u32, - // Xor Immediate (`xori`) Instruction - RvInstr32OpImmFunct3::Xori => reg ^ instr.imm() as u32, + // Shift Right Immediate Instruction + RvInstr32OpImmFunct3::Sri => { + match instr.funct7().into() { + // Shift Right Logical Immediate (`srli`) Instruction + RvInstr32OpImmFunct7::Srli => reg.wrapping_shr(instr.shamt()) as RvData, - // Shift Right Immediate Instruction - RvInstr32OpImmFunct3::Sri => { - match instr.funct7().into() { - // Shift Right Logical Immediate (`srli`) Instruction - RvInstr32OpImmFunct7::Srli => reg.wrapping_shr(instr.shamt()) as RvData, + // Shift Right Arithmetic Immediate (`srai`) Instruction + RvInstr32OpImmFunct7::Srai => { + (reg as i32).wrapping_shr(instr.shamt()) as RvData + } - // Shift Right Arithmetic Immediate (`srai`) Instruction - RvInstr32OpImmFunct7::Srai => { - (reg as i32).wrapping_shr(instr.shamt()) as RvData - } - // Rotate Right Immediate (`rori`) - RvInstr32OpImmFunct7::Bitmanip => reg.rotate_right(instr.shamt()), - - // Bitwise OR-Combine, byte granule - RvInstr32OpImmFunct7::Orc if instr.funct5() == 0b0_0111 => { - let reg_bytes = reg.to_le_bytes(); - u32::from_le_bytes(core::array::from_fn(|i| { - if reg_bytes[i] != 0 { - 0xff - } else { - 0x00 - } - })) + // Illegal Instruction + _ => Err(RvException::illegal_instr(instr.0))?, } - - // Byte-reverse register - RvInstr32OpImmFunct7::Rev8 if instr.funct5() == 0b1_1000 => reg.swap_bytes(), - - // Illegal Instruction - _ => Err(RvException::illegal_instr(instr.0))?, } - } - // Or Immediate (`ori`) Instruction - RvInstr32OpImmFunct3::Ori => reg | instr.imm() as u32, + // Or Immediate (`ori`) Instruction + RvInstr32OpImmFunct3::Ori => reg | instr.imm() as u32, - // And Immediate (`ori`) Instruction - RvInstr32OpImmFunct3::Andi => reg & instr.imm() as u32, + // And Immediate (`ori`) Instruction + RvInstr32OpImmFunct3::Andi => reg & instr.imm() as u32, - // Illegal Instruction - _ => Err(RvException::illegal_instr(instr.0))?, + // Illegal Instruction + _ => Err(RvException::illegal_instr(instr.0))?, + } }; // Save the contents to register diff --git a/sw-emulator/lib/cpu/src/instr/test_encoder.rs b/sw-emulator/lib/cpu/src/instr/test_encoder.rs index a238445315..3bf8b8deb4 100644 --- a/sw-emulator/lib/cpu/src/instr/test_encoder.rs +++ b/sw-emulator/lib/cpu/src/instr/test_encoder.rs @@ -162,6 +162,12 @@ pub mod tests { addi(XReg::X0, XReg::X0, 0) } + pub fn sign_extend(x: u32) -> u32 { + let x = x as i32; + let x = x | (-(((x) >> 11) & 1) << 11); + x as u32 + } + /// Encode Add Upper Immediate to program counter (`auipc`) instruction pub fn auipc(rd: XReg, imm: i32) -> u32 { let mut instr = RvInstr32U(0); @@ -194,6 +200,124 @@ pub mod tests { op_instr!(and, Seven, And); op_instr!(remu, Seven, Remu); + // bit manipulation extension + op_instr!(sh1add, Two, Sh1add); + op_instr!(sh2add, Four, Sh1add); + op_instr!(sh3add, Six, Sh1add); + op_instr!(bset, One, Bset); + op_instr!(binv, One, Binv); + op_instr!(bclr, One, Bclr); + op_instr!(bext, Five, Bclr); + op_instr!(andn, Seven, Sub); + op_instr!(orn, Six, Sub); + op_instr!(xnor, Four, Sub); + op_instr!(max, Six, MinMaxClmul); + op_instr!(maxu, Seven, MinMaxClmul); + op_instr!(min, Four, MinMaxClmul); + op_instr!(minu, Five, MinMaxClmul); + op_instr!(rol, One, Rotate); + op_instr!(ror, Five, Rotate); + op_instr!(clmul, One, MinMaxClmul); + op_instr!(clmulh, Three, MinMaxClmul); + op_instr!(clmulr, Two, MinMaxClmul); + op_imm_instr!(bseti, Sli, Orc); + op_imm_instr!(binvi, Sli, Rev8); + op_imm_instr!(bclri, Sli, Bclr); + op_imm_instr!(bexti, Sri, Bclr); + op_imm_instr!(rori, Sri, Bitmanip); + + pub fn clz(rd: XReg, rs: XReg) -> u32 { + let mut instr = RvInstr32I(0); + instr.set_opcode(RvInstr32Opcode::OpImm); + instr.set_rd(rd); + instr.set_rs(rs); + instr.set_imm(0x600); + instr.set_funct3(1); + instr.0 + } + + pub fn cpop(rd: XReg, rs: XReg) -> u32 { + let mut instr = RvInstr32I(0); + instr.set_opcode(RvInstr32Opcode::OpImm); + instr.set_rd(rd); + instr.set_rs(rs); + instr.set_imm(0x602); + instr.set_funct3(1); + instr.0 + } + + pub fn ctz(rd: XReg, rs: XReg) -> u32 { + let mut instr = RvInstr32I(0); + instr.set_opcode(RvInstr32Opcode::OpImm); + instr.set_rd(rd); + instr.set_rs(rs); + instr.set_imm(0x601); + instr.set_funct3(1); + instr.0 + } + + pub fn orc_b(rd: XReg, rs: XReg) -> u32 { + let mut instr = RvInstr32I(0); + instr.set_opcode(RvInstr32Opcode::OpImm); + instr.set_rd(rd); + instr.set_rs(rs); + instr.set_imm(0x287); + instr.set_funct3(5); + instr.0 + } + + pub fn rev8(rd: XReg, rs: XReg) -> u32 { + let mut instr = RvInstr32I(0); + instr.set_opcode(RvInstr32Opcode::OpImm); + instr.set_rd(rd); + instr.set_rs(rs); + instr.set_imm(0x698); + instr.set_funct3(5); + instr.0 + } + + pub fn sext_b(rd: XReg, rs: XReg) -> u32 { + let mut instr = RvInstr32I(0); + instr.set_opcode(RvInstr32Opcode::OpImm); + instr.set_rd(rd); + instr.set_rs(rs); + instr.set_imm(0x604); + instr.set_funct3(1); + instr.0 + } + + pub fn sext_h(rd: XReg, rs: XReg) -> u32 { + let mut instr = RvInstr32I(0); + instr.set_opcode(RvInstr32Opcode::OpImm); + instr.set_rd(rd); + instr.set_rs(rs); + instr.set_imm(0x605); + instr.set_funct3(1); + instr.0 + } + + pub fn zext_h(rd: XReg, rs: XReg) -> u32 { + let mut instr = RvInstr32R(0); + instr.set_opcode(RvInstr32Opcode::Op); + instr.set_rd(rd); + instr.set_rs1(rs); + instr.set_rs2(XReg::X0); + instr.set_funct3(4); + instr.set_funct7(RvInstr32OpFunct7::Zext.into()); + instr.0 + } + + // load immediate (first instruction) + pub fn li0(rd: XReg, imm: u32) -> u32 { + let v = (imm >> 12) + if imm & 0x800 == 0x800 { 1 } else { 0 }; + lui(rd, v as i32) + } + + // load immediate (second instruction) + pub fn li1(rd: XReg, imm: u32) -> u32 { + addi(rd, rd, (imm & 0xfff) as i32) + } + /// Encode Load Upper Immediate (`lui`) instruction pub fn lui(rd: XReg, imm: i32) -> u32 { let mut instr = RvInstr32U(0); @@ -236,4 +360,14 @@ pub mod tests { op_system_instr!(csrrwi, Csrrwi); op_system_instr!(csrrsi, Csrrsi); op_system_instr!(csrrci, Csrrci); + + #[test] + fn test_sign_extend() { + for i in 0..0x800 { + assert_eq!(i, sign_extend(i)); + } + for i in 0x800..0x1000 { + assert_eq!(0xffff_f000 | i, sign_extend(i)); + } + } } diff --git a/sw-emulator/lib/cpu/src/instr/test_macros.rs b/sw-emulator/lib/cpu/src/instr/test_macros.rs index 95e8cd9af8..c7e41f09d9 100644 --- a/sw-emulator/lib/cpu/src/instr/test_macros.rs +++ b/sw-emulator/lib/cpu/src/instr/test_macros.rs @@ -61,6 +61,167 @@ mod test { }; } + #[macro_export] + macro_rules! test_imm_dest_bypass { + ($test:ident, 0, $instr:ident, $result:expr, $val1:expr, $val2:expr) => { + #[test] + fn $test() { + use $crate::xreg_file::XReg; + use $crate::instr::test_encoder::tests; + + $crate::isa_test!( + 0x0000 => $crate::text![ + tests::addi(XReg::X4, XReg::X0, 0); // 0x0000 + tests::li0(XReg::X1, $val1); // 0x0004 + tests::li1(XReg::X1, $val1); // 0x0008 + tests::$instr(XReg::X14, XReg::X1, tests::sign_extend($val2)); // 0x000C + tests::addi(XReg::X6, XReg::X14, 0); // 0x0010 + tests::addi(XReg::X4, XReg::X4, 1); // 0x0014 + tests::addi(XReg::X5, XReg::X0, 2); // 0x0018 + tests::bne(XReg::X4, XReg::X5, 0xFFE8); // 0x001C + ], + 0x1000 => vec![0], + {}, + { + XReg::X6 = $result; + } + ); + } + }; + ($test:ident, 1, $instr:ident, $result:expr, $val1:expr, $val2:expr) => { + #[test] + fn $test() { + use $crate::xreg_file::XReg; + use $crate::instr::test_encoder::tests; + + $crate::isa_test!( + 0x0000 => $crate::text![ + tests::addi(XReg::X4, XReg::X0, 0); // 0x0000 + tests::li0(XReg::X1, $val1); // 0x0004 + tests::li1(XReg::X1, $val1); // 0x0008 + tests::$instr(XReg::X14, XReg::X1, tests::sign_extend($val2)); // 0x000C + tests::nop(); // 0x0010 + tests::addi(XReg::X6, XReg::X14, 0); // 0x0014 + tests::addi(XReg::X4, XReg::X4, 1); // 0x0018 + tests::addi(XReg::X5, XReg::X0, 2); // 0x001C + tests::bne(XReg::X4, XReg::X5, 0xFFE4); // 0x0020 + ], + 0x1000 => vec![0], + {}, + { + XReg::X6 = $result; + } + ); + } + }; + ($test:ident, 2, $instr:ident, $result:expr, $val1:expr, $val2:expr) => { + #[test] + fn $test() { + use $crate::xreg_file::XReg; + use $crate::instr::test_encoder::tests; + + $crate::isa_test!( + 0x0000 => $crate::text![ + tests::addi(XReg::X4, XReg::X0, 0); // 0x0000 + tests::li0(XReg::X1, $val1); // 0x0004 + tests::li1(XReg::X1, $val1); // 0x0008 + tests::$instr(XReg::X14, XReg::X1, tests::sign_extend($val2)); // 0x000C + tests::nop(); // 0x0010 + tests::nop(); // 0x0014 + tests::addi(XReg::X6, XReg::X14, 0); // 0x0018 + tests::addi(XReg::X4, XReg::X4, 1); // 0x001C + tests::addi(XReg::X5, XReg::X0, 2); // 0x0020 + tests::bne(XReg::X4, XReg::X5, 0xFFE0); // 0x0024 + ], + 0x1000 => vec![0], + {}, + { + XReg::X6 = $result; + } + ); + } + }; + } + + #[macro_export] + macro_rules! test_imm_src1_bypass { + ($test:ident, 0, $instr:ident, $result:expr, $val1:expr, $val2:expr) => { + #[test] + fn $test() { + use $crate::xreg_file::XReg; + use $crate::instr::test_encoder::tests; + + $crate::isa_test!( + 0x0000 => $crate::text![ + tests::addi(XReg::X4, XReg::X0, 0); // 0x0000 + tests::li0(XReg::X1, $val1); // 0x0004 + tests::li1(XReg::X1, $val1); // 0x0008 + tests::$instr(XReg::X14, XReg::X1, tests::sign_extend($val2)); // 0x000C + tests::addi(XReg::X4, XReg::X4, 1); // 0x0010 + tests::addi(XReg::X5, XReg::X0, 2); // 0x0014 + tests::bne(XReg::X4, XReg::X5, 0xFFEC); // 0x0018 + ], + 0x1000 => vec![0], + {}, + { + XReg::X14 = $result; + } + ); + } + }; + ($test:ident, 1, $instr:ident, $result:expr, $val1:expr, $val2:expr) => { + #[test] + fn $test() { + use $crate::xreg_file::XReg; + use $crate::instr::test_encoder::tests; + + $crate::isa_test!( + 0x0000 => $crate::text![ + tests::addi(XReg::X4, XReg::X0, 0); // 0x0000 + tests::li0(XReg::X1, $val1); // 0x0004 + tests::li1(XReg::X1, $val1); // 0x0008 + tests::nop(); // 0x000C + tests::$instr(XReg::X14, XReg::X1, tests::sign_extend($val2)); // 0x0010 + tests::addi(XReg::X4, XReg::X4, 1); // 0x0014 + tests::addi(XReg::X5, XReg::X0, 2); // 0x0018 + tests::bne(XReg::X4, XReg::X5, 0xFFE8); // 0x001C + ], + 0x1000 => vec![0], + {}, + { + XReg::X14 = $result; + } + ); + } + }; + ($test:ident, 2, $instr:ident, $result:expr, $val1:expr, $val2:expr) => { + #[test] + fn $test() { + use $crate::xreg_file::XReg; + use $crate::instr::test_encoder::tests; + + $crate::isa_test!( + 0x0000 => $crate::text![ + tests::addi(XReg::X4, XReg::X0, 0); // 0x0000 + tests::li0(XReg::X1, $val1); // 0x0004 + tests::li1(XReg::X1, $val1); // 0x0008 + tests::nop(); // 0x000C + tests::nop(); // 0x0010 + tests::$instr(XReg::X14, XReg::X1, tests::sign_extend($val2)); // 0x0014 + tests::addi(XReg::X4, XReg::X4, 1); // 0x0018 + tests::addi(XReg::X5, XReg::X0, 2); // 0x001C + tests::bne(XReg::X4, XReg::X5, 0xFFE4); // 0x0020 + ], + 0x1000 => vec![0], + {}, + { + XReg::X14 = $result; + } + ); + } + }; + } + #[macro_export] macro_rules! test_imm_src1_eq_dest { ($test:ident, $instr:ident, $result:expr, $data:expr, $imm:expr) => { @@ -157,6 +318,30 @@ mod test { }; } + #[macro_export] + macro_rules! test_r_op { + ($test:ident, $instr:ident, $result:expr, $val1:expr) => { + #[test] + fn $test() { + use $crate::xreg_file::XReg; + use $crate::instr::test_encoder::tests; + + $crate::isa_test!( + 0x0000 => $crate::text![ + tests::$instr(XReg::X14, XReg::X1); + ], + 0x1000 => vec![0], + { + XReg::X1 = $val1; + }, + { + XReg::X14 = $result; + } + ); + } + }; + } + #[macro_export] macro_rules! test_rr_op { ($test:ident, $instr:ident, $result:expr, $val1:expr, $val2:expr) => { @@ -182,6 +367,30 @@ mod test { }; } + #[macro_export] + macro_rules! test_r_src1_eq_dest{ + ($test:ident, $instr:ident, $result:expr, $val1:expr) => { + #[test] + fn $test() { + use $crate::xreg_file::XReg; + use $crate::instr::test_encoder::tests; + + $crate::isa_test!( + 0x0000 => $crate::text![ + tests::$instr(XReg::X1, XReg::X1); + ], + 0x1000 => vec![0], + { + XReg::X1 = $val1; + }, + { + XReg::X1 = $result; + } + ); + } + }; + } + #[macro_export] macro_rules! test_rr_src1_eq_dest{ ($test:ident, $instr:ident, $result:expr, $val1:expr, $val2:expr) => { @@ -256,6 +465,512 @@ mod test { }; } + #[macro_export] + macro_rules! test_r_dest_bypass { + ($test:ident, 0, $instr:ident, $result:expr, $val1:expr) => { + #[test] + fn $test() { + use $crate::xreg_file::XReg; + use $crate::instr::test_encoder::tests; + + $crate::isa_test!( + 0x0000 => $crate::text![ + tests::addi(XReg::X4, XReg::X0, 0); // 0x0000 + tests::li0(XReg::X1, $val1); // 0x0004 + tests::li1(XReg::X1, $val1); // 0x0008 + tests::$instr(XReg::X14, XReg::X1); // 0x000C + tests::addi(XReg::X6, XReg::X14, 0); // 0x0010 + tests::addi(XReg::X4, XReg::X4, 1); // 0x0014 + tests::addi(XReg::X5, XReg::X0, 2); // 0x0018 + tests::bne(XReg::X4, XReg::X5, 0xFFE8); // 0x001C + ], + 0x1000 => vec![0], + {}, + { + XReg::X6 = $result; + } + ); + } + }; + ($test:ident, 1, $instr:ident, $result:expr, $val1:expr) => { + #[test] + fn $test() { + use $crate::xreg_file::XReg; + use $crate::instr::test_encoder::tests; + + $crate::isa_test!( + 0x0000 => $crate::text![ + tests::addi(XReg::X4, XReg::X0, 0); // 0x0000 + tests::li0(XReg::X1, $val1); // 0x0004 + tests::li1(XReg::X1, $val1); // 0x0008 + tests::$instr(XReg::X14, XReg::X1); // 0x000C + tests::nop(); // 0x0010 + tests::addi(XReg::X6, XReg::X14, 0); // 0x0014 + tests::addi(XReg::X4, XReg::X4, 1); // 0x0018 + tests::addi(XReg::X5, XReg::X0, 2); // 0x001C + tests::bne(XReg::X4, XReg::X5, 0xFFE4); // 0x0020 + ], + 0x1000 => vec![0], + {}, + { + XReg::X6 = $result; + } + ); + } + }; + ($test:ident, 2, $instr:ident, $result:expr, $val1:expr) => { + #[test] + fn $test() { + use $crate::xreg_file::XReg; + use $crate::instr::test_encoder::tests; + + $crate::isa_test!( + 0x0000 => $crate::text![ + tests::addi(XReg::X4, XReg::X0, 0); // 0x0000 + tests::li0(XReg::X1, $val1); // 0x0004 + tests::li1(XReg::X1, $val1); // 0x0008 + tests::$instr(XReg::X14, XReg::X1); // 0x000C + tests::nop(); // 0x0010 + tests::nop(); // 0x0014 + tests::addi(XReg::X6, XReg::X14, 0); // 0x0018 + tests::addi(XReg::X4, XReg::X4, 1); // 0x001C + tests::addi(XReg::X5, XReg::X0, 2); // 0x0020 + tests::bne(XReg::X4, XReg::X5, 0xFFE0); // 0x0024 + ], + 0x1000 => vec![0], + {}, + { + XReg::X6 = $result; + } + ); + } + }; + } + + #[macro_export] + macro_rules! test_rr_dest_bypass { + ($test:ident, 0, $instr:ident, $result:expr, $val1:expr, $val2:expr) => { + #[test] + fn $test() { + use $crate::xreg_file::XReg; + use $crate::instr::test_encoder::tests; + + $crate::isa_test!( + 0x0000 => $crate::text![ + tests::addi(XReg::X4, XReg::X0, 0); // 0x0000 + tests::li0(XReg::X1, $val1); // 0x0004 + tests::li1(XReg::X1, $val1); // 0x0008 + tests::li0(XReg::X2, $val2); // 0x000C + tests::li1(XReg::X2, $val2); // 0x0010 + tests::$instr(XReg::X14, XReg::X1, XReg::X2); // 0x0014 + tests::addi(XReg::X6, XReg::X14, 0); // 0x0018 + tests::addi(XReg::X4, XReg::X4, 1); // 0x001C + tests::addi(XReg::X5, XReg::X0, 2); // 0x0020 + tests::bne(XReg::X4, XReg::X5, 0xFFE0); // 0x0024 + ], + 0x1000 => vec![0], + {}, + { + XReg::X6 = $result; + } + ); + } + }; + ($test:ident, 1, $instr:ident, $result:expr, $val1:expr, $val2:expr) => { + #[test] + fn $test() { + use $crate::xreg_file::XReg; + use $crate::instr::test_encoder::tests; + + $crate::isa_test!( + 0x0000 => $crate::text![ + tests::addi(XReg::X4, XReg::X0, 0); // 0x0000 + tests::li0(XReg::X1, $val1); // 0x0004 + tests::li1(XReg::X1, $val1); // 0x0008 + tests::li0(XReg::X2, $val2); // 0x000C + tests::li1(XReg::X2, $val2); // 0x0010 + tests::$instr(XReg::X14, XReg::X1, XReg::X2); // 0x0014 + tests::nop(); // 0x0018 + tests::addi(XReg::X6, XReg::X14, 0); // 0x001C + tests::addi(XReg::X4, XReg::X4, 1); // 0x0020 + tests::addi(XReg::X5, XReg::X0, 2); // 0x0024 + tests::bne(XReg::X4, XReg::X5, 0xFFDC); // 0x0028 + ], + 0x1000 => vec![0], + {}, + { + XReg::X6 = $result; + } + ); + } + }; + ($test:ident, 2, $instr:ident, $result:expr, $val1:expr, $val2:expr) => { + #[test] + fn $test() { + use $crate::xreg_file::XReg; + use $crate::instr::test_encoder::tests; + + $crate::isa_test!( + 0x0000 => $crate::text![ + tests::addi(XReg::X4, XReg::X0, 0); // 0x0000 + tests::li0(XReg::X1, $val1); // 0x0004 + tests::li1(XReg::X1, $val1); // 0x0008 + tests::li0(XReg::X2, $val2); // 0x000C + tests::li1(XReg::X2, $val2); // 0x0010 + tests::$instr(XReg::X14, XReg::X1, XReg::X2); // 0x0014 + tests::nop(); // 0x0018 + tests::nop(); // 0x001C + tests::addi(XReg::X6, XReg::X14, 0); // 0x0020 + tests::addi(XReg::X4, XReg::X4, 1); // 0x0024 + tests::addi(XReg::X5, XReg::X0, 2); // 0x0028 + tests::bne(XReg::X4, XReg::X5, 0xFFD8); // 0x002C + ], + 0x1000 => vec![0], + {}, + { + XReg::X6 = $result; + } + ); + } + }; + } + + #[macro_export] + macro_rules! test_rr_src12_bypass { + ($test:ident, 0, 0, $instr:ident, $result:expr, $val1:expr, $val2:expr) => { + #[test] + fn $test() { + use $crate::xreg_file::XReg; + use $crate::instr::test_encoder::tests; + + $crate::isa_test!( + 0x0000 => $crate::text![ + tests::addi(XReg::X4, XReg::X0, 0); // 0x0000 + tests::li0(XReg::X1, $val1); // 0x0004 + tests::li1(XReg::X1, $val1); // 0x0008 + tests::li0(XReg::X2, $val2); // 0x000C + tests::li1(XReg::X2, $val2); // 0x0010 + tests::$instr(XReg::X14, XReg::X1, XReg::X2); // 0x0014 + tests::addi(XReg::X4, XReg::X4, 1); // 0x0018 + tests::addi(XReg::X5, XReg::X0, 2); // 0x001C + tests::bne(XReg::X4, XReg::X5, 0xFFE4); // 0x0020 + ], + 0x1000 => vec![0], + {}, + { + XReg::X14 = $result; + } + ); + } + }; + ($test:ident, 0, 1, $instr:ident, $result:expr, $val1:expr, $val2:expr) => { + #[test] + fn $test() { + use $crate::xreg_file::XReg; + use $crate::instr::test_encoder::tests; + + $crate::isa_test!( + 0x0000 => $crate::text![ + tests::addi(XReg::X4, XReg::X0, 0); // 0x0000 + tests::li0(XReg::X1, $val1); // 0x0004 + tests::li1(XReg::X1, $val1); // 0x0008 + tests::li0(XReg::X2, $val2); // 0x000C + tests::li1(XReg::X2, $val2); // 0x0010 + tests::nop(); // 0x0014 + tests::$instr(XReg::X14, XReg::X1, XReg::X2); // 0x0018 + tests::addi(XReg::X4, XReg::X4, 1); // 0x001C + tests::addi(XReg::X5, XReg::X0, 2); // 0x0020 + tests::bne(XReg::X4, XReg::X5, 0xFFE0); // 0x0024 + ], + 0x1000 => vec![0], + {}, + { + XReg::X14 = $result; + } + ); + } + }; + ($test:ident, 0, 2, $instr:ident, $result:expr, $val1:expr, $val2:expr) => { + #[test] + fn $test() { + use $crate::xreg_file::XReg; + use $crate::instr::test_encoder::tests; + + $crate::isa_test!( + 0x0000 => $crate::text![ + tests::addi(XReg::X4, XReg::X0, 0); // 0x0000 + tests::li0(XReg::X1, $val1); // 0x0004 + tests::li1(XReg::X1, $val1); // 0x0008 + tests::li0(XReg::X2, $val2); // 0x000C + tests::li1(XReg::X2, $val2); // 0x0010 + tests::nop(); // 0x0014 + tests::nop(); // 0x0018 + tests::$instr(XReg::X14, XReg::X1, XReg::X2); // 0x001C + tests::addi(XReg::X4, XReg::X4, 1); // 0x0020 + tests::addi(XReg::X5, XReg::X0, 2); // 0x0024 + tests::bne(XReg::X4, XReg::X5, 0xFFDC); // 0x0028 + ], + 0x1000 => vec![0], + {}, + { + XReg::X14 = $result; + } + ); + } + }; + ($test:ident, 1, 0, $instr:ident, $result:expr, $val1:expr, $val2:expr) => { + #[test] + fn $test() { + use $crate::xreg_file::XReg; + use $crate::instr::test_encoder::tests; + + $crate::isa_test!( + 0x0000 => $crate::text![ + tests::addi(XReg::X4, XReg::X0, 0); // 0x0000 + tests::li0(XReg::X1, $val1); // 0x0004 + tests::li1(XReg::X1, $val1); // 0x0008 + tests::nop(); // 0x000C + tests::li0(XReg::X2, $val2); // 0x0010 + tests::li1(XReg::X2, $val2); // 0x0014 + tests::$instr(XReg::X14, XReg::X1, XReg::X2); // 0x0018 + tests::addi(XReg::X4, XReg::X4, 1); // 0x001C + tests::addi(XReg::X5, XReg::X0, 2); // 0x0020 + tests::bne(XReg::X4, XReg::X5, 0xFFE0); // 0x0024 + ], + 0x1000 => vec![0], + {}, + { + XReg::X14 = $result; + } + ); + } + }; + ($test:ident, 1, 1, $instr:ident, $result:expr, $val1:expr, $val2:expr) => { + #[test] + fn $test() { + use $crate::xreg_file::XReg; + use $crate::instr::test_encoder::tests; + + $crate::isa_test!( + 0x0000 => $crate::text![ + tests::addi(XReg::X4, XReg::X0, 0); // 0x0000 + tests::li0(XReg::X1, $val1); // 0x0004 + tests::li1(XReg::X1, $val1); // 0x0008 + tests::nop(); // 0x000C + tests::li0(XReg::X2, $val2); // 0x0010 + tests::li1(XReg::X2, $val2); // 0x0014 + tests::nop(); // 0x0018 + tests::$instr(XReg::X14, XReg::X1, XReg::X2); // 0x001C + tests::addi(XReg::X4, XReg::X4, 1); // 0x0020 + tests::addi(XReg::X5, XReg::X0, 2); // 0x0024 + tests::bne(XReg::X4, XReg::X5, 0xFFDC); // 0x0028 + ], + 0x1000 => vec![0], + {}, + { + XReg::X14 = $result; + } + ); + } + }; + ($test:ident, 2, 0, $instr:ident, $result:expr, $val1:expr, $val2:expr) => { + #[test] + fn $test() { + use $crate::xreg_file::XReg; + use $crate::instr::test_encoder::tests; + + $crate::isa_test!( + 0x0000 => $crate::text![ + tests::addi(XReg::X4, XReg::X0, 0); // 0x0000 + tests::li0(XReg::X1, $val1); // 0x0004 + tests::li1(XReg::X1, $val1); // 0x0008 + tests::nop(); // 0x000C + tests::nop(); // 0x0010 + tests::li0(XReg::X2, $val2); // 0x0014 + tests::li1(XReg::X2, $val2); // 0x0018 + tests::$instr(XReg::X14, XReg::X1, XReg::X2); // 0x001C + tests::addi(XReg::X4, XReg::X4, 1); // 0x0020 + tests::addi(XReg::X5, XReg::X0, 2); // 0x0024 + tests::bne(XReg::X4, XReg::X5, 0xFFDC); // 0x0028 + ], + 0x1000 => vec![0], + {}, + { + XReg::X14 = $result; + } + ); + } + }; + } + + #[macro_export] + macro_rules! test_rr_src21_bypass { + ($test:ident, 0, 0, $instr:ident, $result:expr, $val1:expr, $val2:expr) => { + #[test] + fn $test() { + use $crate::xreg_file::XReg; + use $crate::instr::test_encoder::tests; + + $crate::isa_test!( + 0x0000 => $crate::text![ + tests::addi(XReg::X4, XReg::X0, 0); // 0x0000 + tests::li0(XReg::X2, $val2); // 0x0004 + tests::li1(XReg::X2, $val2); // 0x0008 + tests::li0(XReg::X1, $val1); // 0x000C + tests::li1(XReg::X1, $val1); // 0x0010 + tests::$instr(XReg::X14, XReg::X1, XReg::X2); // 0x0014 + tests::addi(XReg::X4, XReg::X4, 1); // 0x0018 + tests::addi(XReg::X5, XReg::X0, 2); // 0x001C + tests::bne(XReg::X4, XReg::X5, 0xFFE4); // 0x0020 + ], + 0x1000 => vec![0], + {}, + { + XReg::X14 = $result; + } + ); + } + }; + ($test:ident, 0, 1, $instr:ident, $result:expr, $val1:expr, $val2:expr) => { + #[test] + fn $test() { + use $crate::xreg_file::XReg; + use $crate::instr::test_encoder::tests; + + $crate::isa_test!( + 0x0000 => $crate::text![ + tests::addi(XReg::X4, XReg::X0, 0); // 0x0000 + tests::li0(XReg::X2, $val2); // 0x0004 + tests::li1(XReg::X2, $val2); // 0x0008 + tests::li0(XReg::X1, $val1); // 0x000C + tests::li1(XReg::X1, $val1); // 0x0010 + tests::nop(); // 0x0014 + tests::$instr(XReg::X14, XReg::X1, XReg::X2); // 0x0018 + tests::addi(XReg::X4, XReg::X4, 1); // 0x001C + tests::addi(XReg::X5, XReg::X0, 2); // 0x0020 + tests::bne(XReg::X4, XReg::X5, 0xFFE0); // 0x0024 + ], + 0x1000 => vec![0], + {}, + { + XReg::X14 = $result; + } + ); + } + }; + ($test:ident, 0, 2, $instr:ident, $result:expr, $val1:expr, $val2:expr) => { + #[test] + fn $test() { + use $crate::xreg_file::XReg; + use $crate::instr::test_encoder::tests; + + $crate::isa_test!( + 0x0000 => $crate::text![ + tests::addi(XReg::X4, XReg::X0, 0); // 0x0000 + tests::li0(XReg::X2, $val2); // 0x0004 + tests::li1(XReg::X2, $val2); // 0x0008 + tests::li0(XReg::X1, $val1); // 0x000C + tests::li1(XReg::X1, $val1); // 0x0010 + tests::nop(); // 0x0014 + tests::nop(); // 0x0018 + tests::$instr(XReg::X14, XReg::X1, XReg::X2); // 0x001C + tests::addi(XReg::X4, XReg::X4, 1); // 0x0020 + tests::addi(XReg::X5, XReg::X0, 2); // 0x0024 + tests::bne(XReg::X4, XReg::X5, 0xFFDC); // 0x0028 + ], + 0x1000 => vec![0], + {}, + { + XReg::X14 = $result; + } + ); + } + }; + ($test:ident, 1, 0, $instr:ident, $result:expr, $val1:expr, $val2:expr) => { + #[test] + fn $test() { + use $crate::xreg_file::XReg; + use $crate::instr::test_encoder::tests; + + $crate::isa_test!( + 0x0000 => $crate::text![ + tests::addi(XReg::X4, XReg::X0, 0); // 0x0000 + tests::li0(XReg::X2, $val2); // 0x0004 + tests::li1(XReg::X2, $val2); // 0x0008 + tests::nop(); // 0x000C + tests::li0(XReg::X1, $val1); // 0x0010 + tests::li1(XReg::X1, $val1); // 0x0014 + tests::$instr(XReg::X14, XReg::X1, XReg::X2); // 0x0018 + tests::addi(XReg::X4, XReg::X4, 1); // 0x001C + tests::addi(XReg::X5, XReg::X0, 2); // 0x0020 + tests::bne(XReg::X4, XReg::X5, 0xFFE0); // 0x0024 + ], + 0x1000 => vec![0], + {}, + { + XReg::X14 = $result; + } + ); + } + }; + ($test:ident, 1, 1, $instr:ident, $result:expr, $val1:expr, $val2:expr) => { + #[test] + fn $test() { + use $crate::xreg_file::XReg; + use $crate::instr::test_encoder::tests; + + $crate::isa_test!( + 0x0000 => $crate::text![ + tests::addi(XReg::X4, XReg::X0, 0); // 0x0000 + tests::li0(XReg::X2, $val2); // 0x0004 + tests::li1(XReg::X2, $val2); // 0x000C + tests::nop(); // 0x0008 + tests::li0(XReg::X1, $val1); // 0x0010 + tests::li1(XReg::X1, $val1); // 0x0014 + tests::nop(); // 0x0018 + tests::$instr(XReg::X14, XReg::X1, XReg::X2); // 0x001C + tests::addi(XReg::X4, XReg::X4, 1); // 0x0020 + tests::addi(XReg::X5, XReg::X0, 2); // 0x0024 + tests::bne(XReg::X4, XReg::X5, 0xFFDC); // 0x0028 + ], + 0x1000 => vec![0], + {}, + { + XReg::X14 = $result; + } + ); + } + }; + ($test:ident, 2, 0, $instr:ident, $result:expr, $val1:expr, $val2:expr) => { + #[test] + fn $test() { + use $crate::xreg_file::XReg; + use $crate::instr::test_encoder::tests; + + $crate::isa_test!( + 0x0000 => $crate::text![ + tests::addi(XReg::X4, XReg::X0, 0); // 0x0000 + tests::li0(XReg::X2, $val2); // 0x0004 + tests::li1(XReg::X2, $val2); // 0x0008 + tests::nop(); // 0x000C + tests::nop(); // 0x0010 + tests::li0(XReg::X1, $val1); // 0x0014 + tests::li1(XReg::X1, $val1); // 0x0018 + tests::$instr(XReg::X14, XReg::X1, XReg::X2); // 0x001C + tests::addi(XReg::X4, XReg::X4, 1); // 0x0020 + tests::addi(XReg::X5, XReg::X0, 2); // 0x0024 + tests::bne(XReg::X4, XReg::X5, 0xFFDC); // 0x0028 + ], + 0x1000 => vec![0], + {}, + { + XReg::X14 = $result; + } + ); + } + }; + } + #[macro_export] macro_rules! test_rr_zerosrc1 { ($test:ident, $instr:ident, $result:expr, $val:expr) => { diff --git a/sw-emulator/lib/cpu/src/types.rs b/sw-emulator/lib/cpu/src/types.rs index c44ec0e726..6f593939bb 100644 --- a/sw-emulator/lib/cpu/src/types.rs +++ b/sw-emulator/lib/cpu/src/types.rs @@ -129,9 +129,11 @@ emu_enum! { // Bitmanip instructions Bitmanip = 0b011_0000, - + // OR-Combine byte granule Orc = 0b001_0100, - + // Bit clear + Bclr = 0b010_0100, + // Byte reverse Rev8 = 0b011_0100, }; Invalid @@ -302,19 +304,24 @@ emu_enum! { { /// Add function Add = 0b000_0000, - /// Multiply function Mul = 0b000_0001, - /// Sub function Sub = 0b010_0000, - - // Min, Max, or Clmul + /// Min, Max, or Clmul MinMaxClmul = 0b000_0101, - + /// Zero-extend Zext = 0b000_0100, - + /// Rotate Rotate = 0b011_0000, + /// Shift 1 and add + Sh1add = 0b001_0000, + /// Bit set + Bset = 0b001_0100, + /// Bit clear + Bclr = 0b010_0100, + /// Bit invert + Binv = 0b011_0100, }; Invalid } @@ -366,14 +373,18 @@ impl RvInstr32OpFunct7 { /// Remainder Unsigned function pub const Remu: RvInstr32OpFunct7 = RvInstr32OpFunct7::Mul; - // AND with inverted operand + /// AND with inverted operand pub const Andn: RvInstr32OpFunct7 = RvInstr32OpFunct7::Sub; - // OR with inverted operand + /// OR with inverted operand pub const Orn: RvInstr32OpFunct7 = RvInstr32OpFunct7::Sub; - // XNOR with inverted operand + /// XNOR with inverted operand pub const Xnor: RvInstr32OpFunct7 = RvInstr32OpFunct7::Sub; + + // Bit manipulation extension + /// Shift 1 and adds + pub const Sh1add: RvInstr32OpFunct7 = RvInstr32OpFunct7::Sh1add; } emu_enum! { From 94875e36b0089aa0a57a27700e8c76cd4252157b Mon Sep 17 00:00:00 2001 From: Arthur Heymans Date: Sat, 7 Dec 2024 03:33:05 +0100 Subject: [PATCH 41/51] Mldsa87: Update tests with endianness non invariant seed and messages (#1835) Use randomly generated numbers to validate the emulator code. --- drivers/test-fw/src/bin/mldsa87_tests.rs | 716 +++++++++--------- sw-emulator/lib/periph/src/ml_dsa87.rs | 86 ++- .../src/test_data/ml_dsa87_test_data.rs | 370 --------- 3 files changed, 422 insertions(+), 750 deletions(-) delete mode 100644 sw-emulator/lib/periph/src/test_data/ml_dsa87_test_data.rs diff --git a/drivers/test-fw/src/bin/mldsa87_tests.rs b/drivers/test-fw/src/bin/mldsa87_tests.rs index 1ec433e1aa..b11711983e 100644 --- a/drivers/test-fw/src/bin/mldsa87_tests.rs +++ b/drivers/test-fw/src/bin/mldsa87_tests.rs @@ -30,361 +30,366 @@ use caliptra_registers::soc_ifc_trng::SocIfcTrngReg; use caliptra_test_harness::test_suite; const PUBKEY: [u8; 2592] = [ - 224, 217, 202, 251, 63, 165, 133, 179, 239, 212, 52, 79, 220, 130, 145, 6, 113, 142, 173, 45, - 182, 254, 61, 182, 184, 58, 92, 63, 249, 128, 206, 26, 190, 171, 238, 150, 191, 142, 113, 52, - 52, 4, 216, 39, 10, 179, 202, 168, 193, 157, 99, 194, 144, 71, 194, 210, 188, 54, 54, 18, 234, - 209, 162, 120, 98, 208, 155, 103, 75, 21, 123, 79, 226, 17, 74, 247, 21, 96, 140, 112, 133, - 195, 33, 117, 46, 29, 156, 31, 66, 124, 106, 81, 49, 108, 49, 236, 219, 49, 166, 221, 165, 186, - 101, 149, 232, 121, 72, 103, 226, 59, 208, 128, 255, 189, 172, 199, 73, 140, 43, 116, 240, 77, - 134, 249, 38, 178, 23, 38, 254, 237, 56, 41, 236, 19, 47, 135, 221, 49, 86, 232, 151, 102, 135, - 126, 24, 79, 178, 195, 168, 33, 117, 36, 12, 8, 111, 161, 59, 178, 50, 48, 46, 219, 101, 76, - 112, 248, 43, 220, 244, 87, 251, 224, 40, 160, 145, 202, 134, 84, 147, 223, 106, 99, 156, 108, - 252, 217, 172, 190, 209, 176, 175, 82, 187, 78, 119, 86, 62, 217, 149, 102, 246, 82, 146, 7, - 222, 132, 170, 49, 101, 140, 181, 154, 124, 209, 242, 238, 232, 6, 132, 112, 199, 41, 54, 243, - 182, 200, 233, 194, 4, 174, 161, 236, 27, 229, 91, 236, 246, 245, 218, 246, 82, 88, 86, 163, - 162, 54, 214, 43, 252, 164, 119, 81, 1, 169, 237, 236, 187, 89, 108, 76, 40, 79, 191, 70, 230, - 70, 122, 187, 192, 225, 31, 249, 42, 208, 213, 121, 210, 231, 200, 165, 67, 198, 109, 98, 197, - 211, 122, 62, 42, 23, 232, 211, 18, 221, 199, 25, 86, 119, 164, 173, 184, 209, 166, 216, 70, - 51, 38, 86, 133, 226, 175, 101, 167, 66, 45, 153, 147, 252, 227, 215, 192, 191, 121, 207, 66, - 122, 237, 126, 25, 48, 245, 84, 15, 154, 221, 40, 155, 170, 185, 11, 3, 34, 134, 52, 6, 46, 54, - 249, 83, 72, 89, 215, 189, 55, 253, 40, 164, 189, 138, 41, 60, 224, 52, 200, 191, 16, 125, 55, - 14, 102, 59, 74, 237, 169, 83, 208, 177, 222, 149, 121, 226, 254, 157, 56, 63, 251, 140, 220, - 233, 32, 238, 242, 131, 126, 23, 106, 80, 169, 153, 167, 67, 72, 202, 171, 11, 19, 86, 130, 19, - 112, 34, 1, 35, 58, 2, 58, 86, 141, 178, 34, 223, 39, 236, 57, 227, 69, 194, 229, 209, 7, 14, - 63, 244, 235, 147, 32, 51, 99, 229, 102, 95, 89, 218, 104, 93, 152, 19, 245, 60, 214, 134, 123, - 4, 134, 69, 255, 31, 12, 49, 171, 97, 249, 171, 130, 69, 227, 157, 155, 45, 182, 200, 1, 101, - 187, 84, 44, 127, 150, 95, 106, 15, 234, 102, 20, 218, 48, 24, 192, 246, 67, 112, 67, 55, 243, - 145, 202, 30, 238, 0, 102, 30, 218, 192, 16, 74, 155, 183, 70, 116, 46, 100, 36, 159, 226, 232, - 30, 12, 99, 101, 162, 113, 145, 223, 144, 200, 219, 20, 164, 119, 175, 85, 84, 89, 30, 180, 7, - 113, 214, 227, 106, 77, 194, 51, 7, 161, 235, 95, 70, 106, 57, 248, 32, 18, 154, 74, 6, 64, - 217, 71, 183, 205, 235, 201, 178, 20, 47, 187, 231, 69, 20, 15, 123, 56, 254, 199, 45, 207, - 135, 33, 67, 2, 237, 169, 152, 67, 252, 44, 153, 177, 199, 70, 232, 89, 10, 111, 218, 225, 171, - 155, 42, 132, 71, 53, 45, 198, 202, 247, 34, 206, 22, 42, 223, 111, 46, 152, 158, 159, 67, 98, - 174, 71, 207, 12, 131, 78, 221, 45, 233, 116, 139, 245, 154, 118, 208, 0, 98, 111, 122, 3, 68, - 36, 163, 104, 55, 149, 230, 77, 200, 52, 235, 121, 55, 172, 115, 102, 245, 142, 206, 20, 83, - 242, 57, 154, 97, 99, 68, 155, 250, 180, 91, 170, 71, 177, 143, 115, 192, 238, 91, 133, 91, 80, - 164, 72, 173, 121, 68, 139, 121, 219, 32, 111, 165, 121, 92, 48, 134, 183, 71, 243, 190, 239, - 24, 195, 44, 231, 255, 88, 52, 52, 37, 55, 104, 103, 74, 216, 168, 248, 90, 89, 66, 54, 29, - 134, 65, 228, 220, 46, 34, 168, 85, 83, 236, 239, 231, 126, 173, 232, 222, 98, 116, 158, 207, - 98, 243, 211, 197, 168, 189, 204, 245, 73, 158, 193, 227, 88, 184, 184, 191, 56, 72, 156, 252, - 193, 185, 99, 79, 211, 189, 208, 17, 237, 35, 93, 215, 226, 73, 8, 28, 67, 137, 35, 72, 19, 52, - 206, 48, 27, 82, 205, 152, 75, 218, 100, 74, 135, 139, 158, 181, 167, 146, 122, 92, 159, 61, - 218, 250, 253, 95, 206, 143, 235, 147, 86, 205, 16, 137, 8, 163, 189, 109, 66, 100, 153, 62, - 135, 112, 244, 15, 35, 251, 91, 71, 203, 185, 100, 102, 135, 97, 234, 222, 248, 221, 0, 80, 25, - 64, 109, 253, 33, 92, 205, 97, 55, 193, 247, 227, 63, 177, 203, 128, 134, 9, 75, 126, 250, 107, - 123, 167, 146, 172, 16, 87, 47, 145, 179, 58, 11, 225, 114, 149, 249, 121, 232, 2, 14, 18, 59, - 219, 116, 248, 165, 73, 163, 28, 210, 58, 250, 232, 167, 147, 78, 244, 224, 201, 76, 73, 70, - 218, 204, 205, 233, 94, 123, 173, 103, 13, 42, 130, 169, 195, 156, 59, 180, 185, 66, 246, 150, - 149, 91, 23, 133, 255, 217, 18, 145, 123, 195, 100, 106, 25, 1, 64, 242, 207, 109, 140, 209, - 23, 31, 17, 211, 140, 169, 140, 212, 178, 224, 116, 121, 12, 221, 4, 225, 53, 28, 127, 53, 177, - 35, 46, 213, 193, 197, 50, 34, 113, 212, 65, 73, 16, 7, 137, 89, 114, 49, 0, 82, 216, 147, 164, - 79, 13, 144, 242, 102, 205, 46, 231, 233, 217, 120, 134, 78, 213, 194, 244, 148, 13, 13, 242, - 202, 109, 171, 231, 61, 94, 100, 107, 70, 210, 143, 35, 172, 186, 120, 190, 190, 187, 171, 242, - 181, 12, 22, 39, 183, 125, 218, 142, 186, 110, 138, 163, 19, 141, 16, 143, 162, 214, 238, 209, - 29, 33, 91, 29, 152, 235, 212, 118, 132, 139, 230, 26, 148, 19, 101, 202, 227, 231, 59, 189, - 164, 3, 86, 140, 125, 223, 70, 134, 153, 217, 50, 48, 161, 84, 148, 46, 180, 189, 53, 213, 83, - 181, 249, 208, 106, 247, 189, 9, 114, 91, 74, 219, 134, 15, 57, 125, 228, 89, 97, 139, 70, 159, - 145, 182, 89, 63, 70, 196, 251, 247, 244, 166, 60, 20, 253, 133, 78, 218, 125, 66, 241, 8, 49, - 222, 146, 200, 201, 217, 214, 90, 206, 209, 42, 151, 31, 68, 191, 165, 113, 183, 173, 112, 3, - 115, 193, 243, 85, 132, 152, 77, 211, 138, 243, 58, 131, 51, 49, 35, 109, 171, 105, 194, 134, - 6, 154, 97, 155, 98, 145, 53, 244, 175, 11, 79, 207, 108, 50, 192, 205, 48, 12, 208, 77, 78, - 47, 243, 188, 177, 196, 50, 223, 188, 207, 249, 153, 44, 42, 180, 159, 66, 147, 252, 148, 56, - 127, 140, 67, 32, 168, 124, 194, 19, 106, 56, 46, 51, 51, 202, 191, 34, 208, 214, 169, 23, 93, - 165, 26, 232, 199, 89, 111, 48, 72, 185, 251, 82, 215, 49, 204, 159, 151, 170, 64, 183, 120, - 248, 46, 110, 223, 199, 135, 236, 215, 90, 82, 185, 81, 90, 17, 143, 104, 153, 123, 27, 107, - 178, 47, 126, 19, 184, 199, 172, 138, 135, 3, 225, 240, 109, 78, 185, 141, 215, 141, 85, 191, - 105, 228, 86, 161, 113, 138, 38, 76, 111, 178, 148, 60, 72, 185, 191, 83, 52, 142, 212, 145, - 19, 64, 124, 27, 115, 167, 30, 2, 25, 109, 148, 64, 184, 158, 123, 145, 117, 68, 81, 95, 165, - 248, 27, 6, 39, 133, 139, 154, 161, 7, 50, 18, 93, 135, 239, 231, 29, 54, 117, 93, 251, 173, - 90, 27, 38, 238, 98, 243, 210, 187, 30, 41, 110, 10, 154, 219, 191, 128, 253, 231, 24, 44, 248, - 101, 99, 45, 225, 60, 107, 8, 231, 146, 145, 163, 120, 82, 146, 120, 165, 89, 56, 24, 15, 233, - 21, 236, 238, 145, 147, 168, 187, 28, 209, 111, 99, 92, 103, 236, 12, 157, 197, 31, 174, 126, - 53, 67, 190, 115, 243, 40, 253, 64, 186, 8, 222, 145, 172, 196, 35, 37, 27, 26, 139, 214, 131, - 159, 225, 229, 206, 170, 151, 184, 22, 98, 134, 128, 205, 80, 184, 40, 108, 164, 76, 145, 23, - 180, 61, 221, 182, 115, 187, 9, 207, 143, 46, 169, 242, 128, 36, 176, 223, 237, 15, 87, 109, - 52, 69, 96, 27, 217, 190, 109, 144, 101, 167, 196, 92, 122, 117, 70, 57, 78, 101, 239, 129, - 102, 238, 113, 137, 190, 172, 100, 221, 91, 68, 245, 230, 246, 97, 98, 6, 224, 152, 152, 46, - 154, 38, 36, 45, 215, 1, 77, 222, 83, 55, 197, 62, 52, 172, 202, 83, 209, 181, 37, 5, 176, 109, - 65, 137, 183, 20, 237, 168, 209, 19, 140, 46, 224, 183, 19, 239, 237, 163, 191, 221, 130, 98, - 208, 151, 159, 59, 75, 201, 42, 182, 198, 171, 28, 63, 1, 167, 8, 212, 104, 62, 120, 199, 216, - 220, 198, 160, 25, 127, 73, 84, 119, 186, 31, 195, 11, 29, 110, 116, 232, 239, 148, 243, 76, - 212, 166, 105, 1, 138, 28, 189, 98, 130, 118, 171, 20, 82, 238, 246, 132, 51, 147, 210, 220, - 249, 7, 72, 205, 164, 179, 217, 85, 175, 222, 85, 210, 230, 89, 151, 39, 69, 210, 124, 243, - 225, 171, 56, 204, 247, 29, 112, 149, 59, 214, 178, 11, 14, 151, 132, 43, 192, 48, 152, 62, 57, - 209, 104, 117, 74, 6, 126, 67, 63, 147, 94, 160, 64, 20, 4, 31, 216, 129, 180, 197, 190, 25, - 46, 146, 116, 56, 120, 124, 226, 144, 82, 23, 197, 101, 132, 119, 106, 164, 191, 201, 196, 167, - 212, 141, 15, 22, 151, 43, 169, 101, 152, 202, 190, 141, 171, 173, 82, 215, 113, 1, 253, 8, 15, - 30, 49, 46, 60, 42, 122, 175, 230, 11, 108, 6, 160, 64, 201, 72, 247, 214, 211, 170, 29, 182, - 32, 247, 63, 80, 133, 130, 118, 249, 9, 137, 185, 243, 44, 191, 121, 16, 8, 184, 231, 54, 92, - 178, 41, 223, 0, 48, 232, 12, 253, 191, 104, 39, 235, 122, 7, 189, 77, 50, 207, 189, 76, 13, - 172, 138, 15, 83, 121, 37, 163, 110, 42, 155, 211, 41, 238, 24, 190, 240, 197, 42, 35, 65, 218, - 56, 185, 114, 174, 86, 213, 117, 250, 182, 55, 44, 85, 109, 42, 124, 59, 101, 174, 210, 166, - 81, 170, 179, 105, 236, 142, 166, 8, 243, 13, 57, 209, 162, 64, 188, 142, 144, 237, 171, 157, - 219, 245, 2, 93, 228, 112, 226, 202, 143, 211, 14, 107, 194, 244, 150, 49, 122, 78, 111, 78, - 18, 234, 225, 106, 60, 178, 42, 72, 85, 19, 157, 54, 201, 211, 54, 61, 77, 93, 31, 158, 218, - 124, 199, 141, 30, 112, 84, 245, 135, 176, 219, 26, 215, 240, 97, 196, 21, 1, 55, 141, 19, 153, - 80, 147, 195, 103, 211, 21, 91, 132, 8, 11, 157, 73, 209, 45, 67, 177, 124, 219, 233, 119, 84, - 196, 52, 141, 155, 225, 249, 39, 70, 235, 206, 89, 238, 171, 136, 142, 106, 155, 63, 127, 240, - 1, 33, 121, 147, 222, 100, 8, 140, 82, 115, 77, 143, 5, 222, 244, 79, 71, 167, 55, 194, 12, 27, - 155, 15, 102, 90, 231, 77, 199, 136, 10, 87, 133, 166, 118, 211, 239, 161, 132, 149, 57, 120, - 196, 121, 131, 243, 139, 78, 213, 41, 235, 175, 16, 179, 225, 225, 73, 7, 238, 105, 184, 250, - 74, 190, 228, 21, 188, 14, 120, 163, 20, 34, 9, 195, 194, 233, 149, 98, 35, 179, 116, 164, 79, - 212, 251, 219, 133, 125, 83, 94, 194, 144, 9, 113, 78, 193, 184, 36, 80, 115, 242, 168, 86, - 212, 225, 119, 62, 173, 237, 42, 247, 42, 125, 90, 140, 5, 87, 168, 209, 221, 1, 92, 183, 209, - 73, 56, 167, 177, 18, 45, 44, 85, 204, 59, 121, 101, 206, 230, 25, 186, 95, 199, 161, 141, 235, - 152, 156, 47, 99, 26, 223, 2, 168, 92, 198, 126, 132, 255, 26, 88, 168, 30, 75, 59, 157, 84, - 12, 77, 127, 166, 106, 226, 49, 149, 82, 13, 95, 188, 171, 244, 191, 58, 255, 165, 251, 128, - 143, 190, 18, 149, 141, 129, 186, 70, 195, 0, 123, 19, 45, 42, 108, 162, 246, 90, 112, 82, 163, - 163, 173, 59, 101, 201, 241, 243, 182, 135, 6, 168, 78, 168, 66, 15, 191, 37, 10, 150, 19, 72, - 188, 88, 173, 163, 164, 182, 219, 154, 120, 238, 173, 19, 242, 176, 199, 16, 4, 48, 149, 124, - 95, 77, 234, 75, 115, 106, 144, 34, 184, 68, 119, 151, 122, 10, 91, 69, 51, 34, 236, 157, 221, - 209, 5, 94, 137, 74, 80, 35, 54, 14, 48, 202, 231, 16, 99, 227, 214, 155, 51, 129, 173, 10, - 128, 235, 62, 59, 98, 84, 198, 22, 203, 126, 109, 123, 95, 13, 173, 169, 7, 150, 2, 240, 240, - 183, 39, 212, 153, 149, 175, 17, 28, 160, 199, 53, 224, 0, 205, 179, 144, 16, 243, 226, 183, - 176, 155, 75, 209, 180, 161, 12, 80, 42, 101, 222, 188, 108, 207, 117, 105, 10, 96, 240, 166, - 89, 160, 101, 27, 137, 43, 5, 156, 160, 168, 32, 58, 89, 81, 82, 11, 62, 75, 254, 34, 174, 79, - 113, 83, 30, 172, 103, 59, 197, 145, 61, 231, 49, 184, 188, 211, 185, 13, 194, 168, 99, 92, - 113, 36, 143, 100, 155, 128, 13, 85, 81, 240, 183, 156, 232, 49, 164, 157, 141, 113, 102, 148, - 170, 34, 252, 128, 245, 48, 245, 218, 95, 234, 253, 71, 124, 174, 233, 191, 135, 127, 72, 133, - 86, 134, 118, 102, 126, 214, 70, 20, 149, 167, 187, 236, 97, 0, 95, 63, 160, 103, 123, 61, 100, - 191, 203, 217, 187, 173, 243, 72, 251, 56, 252, 88, 136, 180, 59, 155, 181, 106, 1, 114, 101, - 159, 229, 30, 74, 201, 195, 202, 6, 188, 101, 133, 242, 105, 98, 119, 135, 215, 61, 160, 31, - 157, 130, 229, 90, 64, 4, 202, 246, 90, 143, 191, 31, 127, 77, 49, 203, 250, 207, 123, 68, 95, - 200, 107, 47, 184, 21, 178, 228, 227, 26, 6, 163, 184, 159, 106, 11, 23, 83, 201, 99, 206, 57, - 54, 188, 58, 36, 137, 146, 181, 21, 79, 104, 139, 82, 105, 77, 147, 82, 12, 144, 20, 192, 93, - 59, 235, 68, 235, 111, 126, 188, 222, 59, 181, 30, 62, 204, 66, 139, 95, 105, 74, 217, 25, 211, - 91, 207, 158, 75, 140, 141, 206, 67, 77, 20, 113, 45, 191, 155, 255, 184, 53, 205, 68, 94, 202, - 108, 53, 1, 24, 245, 194, 7, 0, 24, 49, 15, 124, 96, 12, 156, 211, 72, 68, 196, 143, 242, 95, - 171, 47, 82, 94, 45, 43, 50, 238, 91, 212, 161, 249, 205, 242, 147, 109, 50, 208, + 3, 150, 29, 157, 48, 42, 75, 210, 178, 196, 237, 151, 124, 210, 172, 220, 249, 189, 35, 58, 18, + 100, 160, 211, 251, 233, 195, 1, 144, 192, 226, 244, 91, 121, 82, 155, 217, 208, 41, 223, 176, + 224, 57, 48, 173, 127, 130, 88, 110, 49, 240, 93, 249, 186, 238, 46, 84, 80, 51, 189, 239, 242, + 249, 11, 28, 106, 86, 190, 50, 98, 92, 205, 217, 43, 193, 113, 25, 158, 165, 78, 2, 53, 189, + 136, 146, 67, 110, 103, 53, 86, 72, 35, 60, 12, 240, 46, 243, 43, 133, 40, 29, 227, 236, 158, + 119, 47, 124, 81, 191, 129, 111, 220, 51, 62, 250, 38, 124, 148, 59, 145, 183, 194, 15, 192, + 47, 18, 228, 8, 4, 187, 122, 114, 138, 136, 116, 208, 34, 75, 9, 238, 61, 255, 216, 69, 228, + 60, 231, 58, 84, 143, 27, 165, 237, 110, 168, 14, 30, 252, 247, 144, 174, 68, 145, 255, 203, + 210, 73, 210, 149, 32, 6, 104, 51, 128, 70, 220, 156, 144, 242, 227, 192, 91, 6, 201, 161, 68, + 178, 227, 89, 202, 38, 185, 211, 237, 234, 43, 172, 137, 245, 119, 227, 151, 65, 153, 15, 23, + 192, 193, 131, 91, 152, 123, 179, 24, 36, 140, 216, 133, 193, 92, 118, 35, 240, 28, 218, 194, + 185, 138, 109, 215, 193, 191, 167, 102, 56, 57, 96, 164, 37, 140, 59, 199, 133, 12, 239, 21, + 56, 8, 206, 100, 5, 190, 234, 74, 127, 90, 226, 157, 84, 230, 142, 202, 147, 196, 77, 118, 83, + 224, 46, 227, 250, 242, 52, 161, 156, 218, 37, 81, 254, 78, 107, 140, 165, 151, 205, 190, 91, + 232, 29, 183, 159, 132, 153, 221, 196, 158, 191, 59, 254, 85, 35, 109, 153, 54, 152, 90, 102, + 150, 193, 244, 3, 26, 16, 192, 50, 145, 194, 9, 98, 107, 72, 81, 252, 42, 37, 64, 251, 170, + 119, 144, 255, 237, 34, 134, 120, 68, 245, 6, 194, 4, 217, 21, 253, 61, 47, 154, 105, 205, 160, + 58, 191, 26, 51, 83, 188, 114, 40, 206, 91, 5, 209, 176, 97, 206, 73, 121, 109, 182, 81, 95, + 52, 113, 156, 29, 77, 12, 219, 76, 168, 121, 178, 194, 158, 140, 209, 94, 126, 100, 7, 151, + 197, 56, 120, 53, 41, 92, 128, 30, 13, 80, 216, 255, 78, 180, 30, 206, 186, 8, 214, 34, 87, + 122, 55, 144, 85, 97, 78, 224, 11, 168, 88, 23, 100, 223, 118, 252, 126, 206, 93, 89, 98, 138, + 107, 55, 154, 199, 214, 11, 36, 24, 148, 120, 173, 133, 177, 81, 172, 155, 82, 126, 108, 187, + 123, 142, 191, 103, 39, 192, 226, 210, 180, 113, 136, 179, 13, 139, 56, 10, 134, 61, 163, 161, + 102, 81, 41, 6, 164, 77, 16, 226, 57, 88, 15, 21, 41, 246, 135, 20, 54, 254, 36, 223, 4, 70, + 142, 71, 9, 11, 203, 254, 247, 15, 57, 183, 166, 98, 34, 81, 199, 92, 79, 100, 147, 146, 61, + 12, 178, 96, 107, 181, 243, 76, 17, 209, 132, 245, 122, 70, 99, 2, 100, 80, 6, 63, 249, 91, 36, + 136, 58, 203, 168, 197, 107, 151, 198, 86, 79, 117, 238, 210, 133, 208, 76, 105, 108, 86, 122, + 174, 163, 196, 18, 175, 11, 248, 252, 188, 130, 117, 230, 180, 194, 114, 116, 139, 120, 237, 6, + 64, 231, 173, 55, 233, 165, 230, 69, 7, 211, 37, 101, 141, 101, 19, 235, 113, 213, 49, 230, 15, + 8, 33, 117, 165, 236, 34, 131, 167, 207, 198, 194, 17, 85, 84, 8, 186, 172, 254, 93, 181, 157, + 106, 34, 36, 19, 143, 147, 199, 156, 207, 9, 2, 115, 4, 126, 131, 64, 110, 228, 27, 97, 208, + 127, 250, 143, 5, 153, 215, 17, 100, 36, 69, 156, 209, 238, 245, 160, 33, 228, 198, 109, 84, 1, + 8, 14, 89, 178, 154, 101, 42, 80, 55, 72, 115, 201, 68, 226, 159, 36, 168, 178, 166, 59, 203, + 64, 7, 248, 160, 110, 176, 236, 201, 93, 71, 129, 206, 150, 244, 83, 32, 5, 117, 74, 89, 111, + 104, 113, 22, 15, 15, 215, 225, 246, 152, 137, 55, 125, 71, 221, 79, 151, 57, 102, 109, 61, + 178, 127, 3, 48, 144, 209, 58, 254, 112, 104, 4, 109, 187, 121, 52, 63, 224, 67, 177, 131, 192, + 129, 95, 64, 149, 140, 142, 102, 195, 133, 111, 70, 194, 164, 81, 185, 85, 216, 147, 146, 250, + 61, 158, 11, 114, 91, 38, 45, 252, 119, 93, 56, 59, 154, 87, 90, 144, 73, 180, 179, 173, 56, + 90, 153, 69, 14, 28, 49, 202, 94, 7, 227, 64, 222, 242, 254, 45, 192, 122, 123, 66, 116, 246, + 64, 98, 151, 242, 124, 31, 180, 205, 177, 118, 195, 60, 117, 17, 93, 81, 109, 128, 26, 20, 63, + 248, 131, 2, 113, 238, 159, 38, 99, 91, 158, 93, 86, 42, 9, 198, 233, 239, 66, 252, 141, 70, + 95, 19, 200, 153, 15, 166, 68, 19, 113, 51, 215, 50, 178, 48, 58, 24, 12, 72, 50, 29, 233, 144, + 204, 98, 83, 216, 55, 46, 216, 186, 138, 40, 37, 74, 178, 139, 201, 216, 228, 231, 27, 52, 44, + 146, 53, 19, 58, 149, 229, 97, 251, 29, 232, 147, 254, 149, 158, 84, 233, 233, 240, 16, 138, + 78, 212, 166, 116, 152, 165, 144, 150, 154, 5, 138, 203, 197, 251, 149, 192, 26, 217, 192, 117, + 20, 49, 216, 179, 69, 16, 235, 191, 139, 194, 107, 120, 90, 60, 116, 81, 127, 10, 95, 85, 162, + 220, 114, 7, 57, 171, 140, 151, 207, 79, 63, 173, 254, 163, 239, 204, 144, 18, 5, 17, 151, 232, + 122, 22, 31, 105, 237, 141, 140, 10, 152, 125, 230, 205, 240, 212, 253, 69, 146, 47, 18, 156, + 6, 235, 15, 199, 183, 131, 211, 84, 233, 84, 133, 130, 245, 35, 208, 0, 246, 89, 60, 88, 56, + 202, 244, 192, 144, 198, 49, 177, 5, 17, 183, 52, 192, 117, 58, 6, 252, 113, 217, 8, 224, 202, + 103, 214, 26, 154, 219, 164, 51, 27, 27, 223, 89, 251, 102, 5, 156, 212, 219, 215, 218, 142, + 167, 206, 70, 192, 33, 133, 40, 57, 43, 129, 142, 78, 77, 133, 8, 164, 0, 137, 76, 24, 77, 214, + 157, 187, 162, 142, 102, 37, 108, 164, 234, 64, 56, 55, 54, 51, 226, 184, 241, 224, 211, 65, + 206, 179, 114, 191, 54, 55, 206, 97, 198, 42, 76, 18, 58, 82, 198, 30, 27, 27, 185, 110, 135, + 164, 2, 239, 206, 2, 70, 174, 109, 221, 197, 170, 244, 133, 217, 28, 231, 72, 127, 167, 217, + 219, 97, 189, 134, 135, 47, 125, 24, 146, 201, 236, 198, 172, 73, 145, 149, 128, 196, 36, 141, + 146, 193, 210, 243, 232, 21, 157, 3, 190, 185, 216, 183, 49, 52, 54, 143, 112, 129, 44, 144, + 50, 164, 142, 206, 107, 161, 89, 93, 107, 95, 88, 37, 203, 125, 26, 70, 23, 35, 248, 121, 121, + 45, 230, 123, 157, 46, 135, 8, 140, 125, 190, 188, 181, 206, 180, 34, 164, 240, 250, 83, 253, + 30, 35, 123, 228, 23, 145, 72, 149, 79, 248, 94, 194, 236, 30, 17, 34, 240, 240, 61, 76, 204, + 28, 38, 157, 77, 153, 242, 173, 84, 47, 178, 129, 237, 200, 146, 88, 223, 173, 184, 42, 201, + 138, 47, 239, 45, 224, 203, 151, 34, 13, 3, 65, 243, 24, 244, 47, 138, 122, 121, 152, 102, 107, + 251, 132, 95, 163, 125, 23, 190, 169, 122, 29, 80, 142, 193, 101, 38, 7, 7, 94, 90, 88, 227, + 20, 148, 33, 11, 41, 172, 217, 79, 181, 46, 33, 102, 17, 153, 8, 65, 93, 20, 82, 187, 78, 126, + 92, 122, 24, 191, 191, 135, 17, 214, 224, 155, 6, 165, 102, 68, 34, 165, 95, 82, 144, 29, 61, + 96, 172, 4, 132, 177, 70, 243, 72, 171, 56, 23, 210, 231, 53, 99, 10, 145, 93, 98, 171, 3, 104, + 89, 61, 99, 126, 237, 243, 13, 139, 21, 7, 243, 151, 94, 83, 73, 18, 124, 217, 84, 101, 192, + 37, 147, 228, 64, 108, 4, 31, 174, 9, 18, 186, 53, 33, 13, 247, 75, 246, 163, 180, 52, 201, + 234, 35, 6, 168, 123, 240, 137, 126, 122, 90, 127, 138, 29, 150, 47, 11, 132, 59, 117, 221, + 104, 180, 27, 206, 17, 20, 29, 32, 95, 43, 210, 228, 153, 122, 164, 138, 41, 159, 42, 213, 35, + 81, 113, 98, 145, 198, 255, 38, 156, 73, 208, 29, 15, 82, 66, 52, 211, 241, 22, 156, 155, 194, + 92, 85, 145, 31, 53, 133, 16, 48, 124, 194, 243, 163, 234, 228, 107, 131, 18, 41, 250, 71, 253, + 97, 5, 114, 70, 48, 243, 78, 228, 66, 76, 162, 134, 108, 148, 174, 103, 245, 182, 51, 49, 57, + 98, 136, 205, 147, 249, 212, 223, 130, 204, 66, 154, 112, 148, 69, 121, 98, 153, 175, 0, 201, + 50, 145, 240, 148, 155, 58, 55, 155, 115, 148, 186, 18, 245, 130, 134, 218, 157, 90, 165, 53, + 218, 101, 238, 204, 141, 27, 143, 27, 229, 187, 88, 34, 215, 210, 141, 109, 194, 78, 253, 213, + 116, 71, 28, 157, 150, 242, 18, 166, 68, 218, 72, 227, 155, 43, 34, 100, 118, 71, 180, 211, 31, + 112, 63, 42, 186, 121, 220, 130, 77, 104, 125, 202, 231, 102, 100, 229, 12, 168, 247, 78, 151, + 251, 6, 36, 217, 88, 154, 149, 232, 244, 212, 56, 185, 249, 184, 135, 208, 93, 234, 176, 130, + 224, 182, 124, 205, 113, 142, 10, 54, 176, 112, 13, 13, 194, 219, 95, 160, 36, 171, 254, 132, + 152, 195, 32, 10, 147, 17, 188, 214, 39, 163, 204, 17, 87, 162, 203, 252, 242, 139, 86, 166, + 27, 164, 15, 56, 30, 117, 106, 2, 195, 177, 149, 196, 54, 255, 77, 145, 175, 192, 38, 39, 210, + 244, 143, 76, 78, 179, 196, 242, 172, 230, 89, 14, 189, 217, 189, 164, 138, 183, 4, 236, 223, + 176, 177, 133, 123, 163, 131, 51, 247, 164, 201, 56, 40, 210, 164, 157, 158, 212, 159, 62, 23, + 252, 182, 208, 26, 116, 46, 208, 224, 40, 48, 136, 145, 235, 235, 187, 144, 246, 59, 134, 227, + 138, 10, 157, 170, 79, 190, 223, 223, 227, 216, 7, 195, 71, 166, 48, 136, 132, 111, 177, 152, + 178, 66, 83, 2, 52, 173, 34, 115, 90, 123, 56, 93, 115, 202, 134, 191, 148, 88, 135, 7, 124, + 64, 112, 73, 34, 66, 84, 206, 216, 25, 138, 194, 39, 224, 117, 187, 60, 15, 89, 60, 37, 99, + 208, 18, 67, 244, 100, 130, 184, 167, 98, 12, 28, 132, 153, 71, 178, 32, 208, 0, 105, 198, 251, + 187, 50, 229, 165, 252, 1, 172, 23, 253, 55, 112, 84, 156, 171, 93, 225, 159, 10, 170, 65, 214, + 252, 4, 70, 92, 15, 242, 130, 215, 225, 230, 236, 198, 15, 238, 90, 91, 238, 154, 68, 248, 29, + 138, 92, 76, 64, 3, 139, 41, 167, 128, 23, 95, 55, 242, 79, 161, 200, 153, 225, 80, 20, 229, + 48, 204, 61, 124, 109, 3, 226, 224, 148, 204, 121, 243, 131, 186, 20, 192, 94, 111, 232, 234, + 128, 98, 2, 196, 247, 252, 33, 135, 44, 48, 42, 48, 201, 228, 149, 119, 135, 26, 106, 32, 184, + 156, 250, 193, 181, 148, 210, 25, 105, 253, 55, 148, 43, 64, 122, 174, 101, 236, 217, 43, 241, + 181, 204, 98, 89, 153, 253, 32, 214, 85, 190, 203, 75, 40, 47, 212, 245, 233, 60, 215, 211, 48, + 92, 133, 184, 59, 33, 217, 185, 12, 60, 223, 68, 120, 69, 135, 180, 118, 102, 143, 95, 187, 3, + 205, 189, 131, 86, 63, 140, 49, 97, 150, 13, 90, 179, 189, 4, 51, 75, 64, 55, 90, 116, 126, + 108, 249, 254, 93, 245, 21, 26, 253, 143, 56, 55, 136, 100, 90, 60, 113, 108, 247, 244, 219, + 68, 78, 194, 241, 140, 79, 3, 182, 138, 255, 86, 35, 157, 237, 203, 185, 44, 59, 50, 254, 215, + 229, 223, 229, 106, 19, 45, 246, 195, 225, 5, 155, 3, 230, 37, 120, 91, 78, 237, 121, 64, 184, + 73, 219, 38, 252, 1, 137, 203, 125, 168, 17, 173, 115, 132, 207, 235, 205, 145, 153, 67, 251, + 162, 136, 185, 109, 112, 116, 51, 229, 93, 24, 32, 153, 253, 71, 227, 169, 212, 105, 154, 103, + 105, 110, 153, 83, 247, 116, 192, 131, 149, 8, 159, 104, 225, 162, 105, 9, 100, 219, 240, 188, + 173, 66, 58, 170, 196, 189, 235, 42, 31, 78, 105, 94, 72, 3, 31, 189, 159, 58, 203, 35, 228, + 41, 96, 53, 24, 230, 207, 104, 27, 32, 229, 196, 101, 23, 251, 91, 70, 110, 19, 51, 182, 249, + 49, 17, 238, 114, 156, 202, 10, 139, 187, 18, 31, 181, 164, 48, 98, 54, 211, 108, 143, 125, + 156, 101, 122, 178, 81, 20, 247, 65, 76, 221, 106, 199, 71, 57, 156, 145, 107, 62, 162, 52, 2, + 154, 59, 199, 71, 118, 159, 35, 153, 194, 83, 221, 101, 115, 149, 162, 142, 189, 102, 246, 174, + 78, 254, 185, 81, 147, 216, 90, 75, 19, 195, 201, 190, 110, 74, 235, 203, 117, 101, 182, 95, + 51, 162, 25, 14, 63, 165, 185, 81, 96, 16, 79, 88, 23, 234, 136, 96, 9, 238, 245, 67, 107, 195, + 90, 152, 14, 66, 26, 98, 54, 57, 203, 112, 5, 171, 220, 155, 57, 42, 66, 225, 252, 70, 199, + 196, 80, 251, 58, 17, 125, 111, 71, 195, 249, 64, 74, 167, 126, 117, 155, 177, 130, 38, 37, 76, + 104, 198, 167, 130, 21, 118, 45, 83, 70, 111, 232, 1, 146, 41, 98, 51, 36, 221, 92, 223, 108, + 214, 239, 30, 155, 61, 47, 216, 93, 169, 58, 67, 150, 76, 192, 186, 36, 58, 106, 82, 65, 112, + 237, 176, 198, 22, 181, 152, 71, 152, 72, 225, 98, 96, 10, 250, 108, 114, 138, 248, 250, 82, + 19, 56, 48, 85, 203, 100, 92, 255, 0, 213, 29, 120, 6, 181, 40, 168, 169, 222, 58, 48, 111, 29, + 57, 193, 108, 34, 24, 19, 124, 222, 145, 33, 128, 29, 241, 154, 117, 94, 125, 107, 220, 9, 62, + 173, 44, 224, 207, 185, 171, 134, 141, 190, 212, 173, 204, 164, 61, 166, 230, 126, 62, 159, + 177, 142, 241, 186, 78, 144, 57, 9, 58, 156, 99, 151, 160, 150, 157, 214, 130, 147, 129, 22, + 49, 233, 163, 238, 125, 109, 84, 209, 245, 198, 32, 212, 10, 7, 10, 152, 138, 201, 40, 8, 255, + 34, 194, 49, 78, 173, 114, 214, 200, 28, 7, 120, 194, 237, 241, 95, 104, 243, 30, 63, 213, 52, + 65, 154, 152, 52, 164, 150, 186, 207, 163, 1, 10, 151, 8, 84, 179, 105, 1, 15, 183, 5, 23, 21, + 165, 155, 103, 187, 84, 66, 131, 251, 238, 29, 21, 120, 68, 207, 251, 25, 203, 149, 198, 166, + 176, 155, 119, 42, 254, 120, 242, 31, 43, 214, 120, 71, 206, 83, 4, 142, 54, 106, 23, 165, 101, + 235, 83, 122, 221, 100, 7, 12, 61, 168, ]; const SIGNATURE: [u8; 4628] = [ - 168, 148, 210, 211, 222, 17, 152, 141, 6, 8, 63, 104, 100, 134, 147, 151, 42, 28, 10, 203, 2, - 96, 62, 253, 222, 230, 203, 224, 182, 214, 28, 125, 62, 13, 150, 153, 183, 47, 165, 242, 64, - 226, 70, 164, 229, 219, 61, 139, 231, 163, 172, 163, 156, 209, 220, 93, 238, 185, 251, 11, 130, - 158, 187, 14, 173, 81, 219, 63, 166, 119, 130, 58, 101, 187, 102, 1, 184, 182, 99, 126, 73, - 226, 202, 197, 104, 151, 109, 91, 69, 120, 139, 167, 127, 32, 32, 149, 176, 17, 111, 232, 133, - 232, 6, 34, 95, 96, 166, 88, 174, 16, 204, 233, 65, 51, 115, 61, 36, 238, 46, 131, 29, 92, 183, - 243, 58, 203, 46, 113, 98, 204, 160, 163, 178, 240, 192, 166, 106, 30, 207, 122, 106, 251, 151, - 96, 5, 97, 99, 66, 32, 235, 172, 85, 138, 102, 50, 10, 227, 19, 22, 242, 32, 145, 169, 44, 70, - 15, 107, 228, 233, 162, 245, 83, 168, 17, 49, 121, 250, 171, 52, 160, 158, 195, 23, 83, 227, - 12, 146, 210, 219, 141, 12, 5, 189, 120, 97, 53, 149, 94, 196, 78, 246, 212, 33, 77, 103, 212, - 102, 171, 221, 31, 112, 219, 35, 95, 212, 54, 129, 251, 242, 106, 69, 165, 98, 201, 212, 23, - 80, 162, 215, 213, 234, 208, 241, 186, 105, 30, 222, 82, 35, 69, 212, 94, 121, 250, 71, 211, - 28, 205, 53, 120, 42, 44, 219, 141, 137, 4, 147, 203, 215, 250, 99, 191, 209, 193, 188, 161, - 105, 136, 17, 164, 146, 116, 235, 105, 20, 51, 182, 105, 112, 7, 228, 88, 244, 94, 87, 174, 11, - 249, 156, 105, 73, 73, 143, 72, 35, 133, 98, 120, 95, 45, 194, 37, 45, 79, 181, 252, 108, 52, - 110, 132, 166, 50, 68, 197, 6, 228, 169, 125, 69, 190, 181, 196, 57, 57, 106, 197, 22, 95, 53, - 67, 218, 146, 234, 198, 115, 148, 112, 207, 72, 188, 181, 34, 50, 240, 63, 228, 44, 94, 124, - 205, 80, 189, 100, 243, 96, 148, 241, 132, 171, 55, 62, 99, 95, 186, 254, 113, 79, 227, 236, - 73, 82, 42, 97, 55, 154, 55, 8, 70, 235, 157, 27, 12, 161, 234, 6, 168, 78, 49, 214, 162, 154, - 52, 194, 198, 78, 226, 77, 128, 73, 151, 191, 29, 54, 109, 76, 116, 81, 19, 225, 188, 62, 125, - 43, 65, 48, 21, 19, 47, 93, 76, 29, 79, 63, 169, 194, 182, 158, 229, 234, 75, 239, 138, 203, - 150, 86, 8, 241, 113, 169, 223, 51, 119, 214, 160, 154, 30, 200, 241, 133, 2, 226, 50, 118, - 126, 97, 136, 1, 170, 185, 51, 77, 254, 6, 128, 214, 64, 57, 31, 217, 84, 57, 126, 145, 181, - 46, 111, 208, 243, 56, 205, 128, 14, 177, 58, 37, 110, 209, 92, 230, 244, 182, 140, 167, 240, - 146, 103, 87, 151, 106, 203, 121, 162, 17, 220, 111, 163, 85, 135, 66, 94, 154, 220, 2, 86, - 209, 71, 88, 160, 15, 228, 165, 157, 219, 195, 94, 14, 210, 197, 141, 157, 227, 37, 200, 245, - 54, 179, 39, 184, 243, 147, 74, 191, 73, 248, 94, 164, 18, 188, 221, 108, 132, 99, 212, 233, - 76, 151, 98, 32, 150, 237, 102, 24, 3, 219, 136, 195, 183, 221, 160, 121, 200, 31, 21, 129, 79, - 137, 229, 1, 248, 84, 30, 235, 251, 169, 77, 144, 232, 139, 30, 236, 226, 114, 226, 158, 242, - 163, 70, 178, 220, 47, 115, 251, 192, 136, 25, 73, 210, 24, 172, 253, 122, 233, 107, 4, 21, - 126, 22, 201, 80, 96, 105, 188, 189, 49, 215, 92, 114, 130, 53, 139, 116, 119, 108, 48, 50, - 222, 92, 13, 105, 232, 241, 199, 93, 38, 20, 97, 91, 32, 105, 107, 6, 99, 193, 180, 28, 38, - 114, 14, 72, 108, 49, 0, 61, 180, 95, 173, 143, 8, 241, 97, 25, 46, 145, 231, 63, 115, 48, 47, - 133, 128, 39, 189, 57, 111, 111, 194, 88, 172, 38, 217, 49, 252, 192, 169, 238, 162, 148, 191, - 120, 89, 141, 213, 40, 246, 111, 58, 194, 52, 83, 96, 252, 238, 237, 43, 252, 150, 37, 185, - 118, 118, 191, 134, 144, 105, 225, 237, 44, 248, 76, 37, 72, 38, 89, 58, 73, 209, 226, 92, 214, - 132, 147, 7, 202, 193, 90, 239, 95, 172, 254, 92, 125, 104, 163, 22, 49, 60, 74, 77, 161, 246, - 188, 126, 46, 29, 141, 138, 245, 67, 182, 16, 245, 59, 84, 120, 45, 84, 29, 80, 181, 244, 133, - 203, 17, 23, 130, 106, 249, 248, 154, 33, 254, 72, 214, 99, 227, 167, 234, 253, 202, 30, 227, - 95, 215, 1, 238, 42, 23, 154, 153, 119, 26, 19, 28, 18, 247, 227, 66, 56, 101, 237, 119, 31, - 30, 159, 24, 93, 50, 238, 184, 128, 87, 3, 92, 110, 10, 251, 31, 123, 93, 20, 230, 250, 84, 71, - 29, 203, 139, 55, 240, 57, 218, 217, 32, 146, 199, 254, 215, 71, 14, 230, 203, 162, 126, 84, - 238, 245, 185, 208, 232, 137, 197, 220, 152, 240, 55, 138, 231, 93, 208, 201, 241, 104, 144, - 209, 216, 182, 19, 167, 5, 218, 144, 193, 22, 86, 167, 132, 65, 230, 44, 152, 175, 18, 159, - 122, 248, 217, 205, 163, 118, 80, 179, 121, 122, 157, 43, 26, 230, 157, 211, 167, 96, 169, 154, - 28, 229, 15, 222, 249, 240, 58, 214, 150, 5, 207, 249, 153, 237, 191, 110, 103, 212, 100, 220, - 3, 157, 236, 27, 53, 39, 79, 224, 31, 135, 249, 110, 193, 239, 47, 60, 58, 196, 215, 125, 212, - 23, 196, 250, 62, 91, 249, 3, 110, 26, 223, 5, 220, 1, 158, 158, 175, 114, 146, 68, 48, 64, 15, - 59, 2, 17, 37, 21, 89, 178, 139, 81, 251, 67, 164, 154, 38, 217, 46, 205, 121, 127, 209, 104, - 177, 35, 149, 240, 76, 43, 1, 30, 127, 36, 227, 20, 134, 52, 188, 23, 6, 239, 202, 66, 189, 51, - 5, 248, 201, 38, 24, 11, 246, 196, 70, 18, 31, 189, 229, 75, 217, 212, 34, 121, 38, 239, 156, - 166, 139, 142, 37, 121, 231, 75, 20, 45, 159, 26, 66, 199, 39, 155, 176, 211, 175, 38, 136, - 193, 227, 201, 248, 132, 185, 130, 244, 210, 173, 217, 66, 248, 203, 65, 152, 2, 17, 16, 69, - 96, 97, 21, 134, 37, 237, 41, 101, 232, 114, 17, 158, 142, 143, 162, 117, 54, 120, 74, 112, 28, - 116, 108, 188, 251, 131, 50, 30, 52, 232, 226, 33, 136, 147, 177, 217, 145, 120, 174, 139, 119, - 187, 99, 3, 248, 47, 148, 65, 12, 163, 163, 68, 167, 69, 150, 220, 253, 46, 179, 96, 124, 40, - 52, 44, 155, 108, 128, 113, 233, 222, 208, 223, 2, 172, 65, 110, 245, 230, 124, 187, 93, 158, - 130, 94, 51, 241, 3, 195, 140, 180, 166, 30, 171, 217, 43, 38, 124, 254, 155, 253, 60, 188, - 114, 193, 145, 40, 93, 152, 84, 201, 151, 170, 191, 155, 61, 53, 196, 193, 144, 68, 217, 5, - 198, 235, 92, 246, 26, 59, 126, 116, 39, 0, 165, 146, 43, 219, 151, 63, 246, 168, 98, 90, 154, - 7, 218, 235, 105, 156, 190, 113, 56, 51, 50, 1, 72, 145, 151, 175, 39, 9, 37, 176, 220, 218, - 115, 59, 78, 10, 196, 66, 38, 109, 234, 68, 19, 176, 60, 137, 227, 125, 15, 221, 165, 45, 210, - 198, 177, 37, 127, 1, 211, 181, 111, 53, 115, 221, 207, 102, 171, 83, 206, 155, 8, 142, 109, - 152, 158, 254, 75, 240, 151, 62, 85, 53, 248, 237, 179, 181, 148, 160, 150, 71, 118, 165, 244, - 160, 163, 11, 37, 84, 28, 116, 183, 199, 112, 49, 68, 165, 23, 105, 116, 113, 230, 144, 173, - 95, 114, 71, 54, 162, 80, 148, 71, 138, 93, 85, 113, 93, 92, 111, 25, 202, 91, 156, 148, 41, - 49, 215, 35, 125, 13, 76, 92, 64, 143, 218, 149, 27, 194, 164, 91, 144, 95, 236, 84, 122, 5, - 32, 240, 150, 214, 209, 204, 241, 150, 255, 184, 69, 244, 190, 173, 119, 214, 42, 235, 193, - 185, 86, 40, 18, 73, 248, 48, 140, 31, 102, 178, 67, 108, 156, 88, 97, 230, 42, 244, 67, 49, - 127, 126, 40, 124, 214, 99, 204, 50, 252, 229, 241, 115, 96, 232, 204, 129, 253, 101, 157, 81, - 166, 194, 228, 81, 165, 52, 35, 192, 96, 7, 208, 29, 69, 246, 30, 129, 23, 224, 131, 229, 200, - 123, 235, 57, 239, 172, 54, 253, 19, 12, 111, 94, 149, 134, 125, 17, 98, 88, 123, 240, 230, - 101, 237, 28, 216, 34, 241, 142, 66, 18, 189, 18, 10, 98, 103, 119, 165, 78, 6, 193, 133, 28, - 7, 216, 74, 205, 182, 35, 129, 55, 242, 28, 225, 66, 78, 16, 85, 199, 117, 36, 117, 198, 149, - 233, 95, 244, 128, 79, 213, 158, 16, 217, 34, 90, 110, 222, 215, 242, 53, 94, 158, 131, 129, - 200, 206, 48, 29, 221, 21, 33, 197, 205, 58, 65, 97, 24, 205, 53, 30, 185, 233, 249, 172, 121, - 197, 59, 60, 136, 89, 97, 100, 70, 128, 184, 221, 108, 90, 240, 180, 112, 61, 33, 39, 227, 221, - 78, 63, 120, 250, 106, 155, 178, 211, 162, 210, 56, 0, 219, 9, 201, 246, 102, 136, 182, 151, - 171, 187, 226, 136, 248, 143, 128, 128, 190, 53, 223, 149, 96, 211, 108, 102, 212, 190, 108, - 37, 170, 101, 108, 203, 213, 232, 155, 251, 14, 17, 217, 116, 39, 109, 42, 193, 118, 144, 15, - 159, 26, 183, 64, 165, 7, 82, 154, 126, 61, 156, 144, 53, 167, 179, 84, 173, 241, 255, 2, 164, - 49, 106, 254, 240, 153, 185, 246, 187, 245, 174, 228, 242, 240, 180, 236, 202, 238, 58, 47, 37, - 124, 36, 215, 118, 184, 56, 250, 198, 22, 71, 128, 233, 214, 217, 9, 59, 188, 131, 120, 188, 0, - 71, 196, 246, 106, 150, 155, 28, 64, 28, 210, 234, 138, 108, 70, 190, 198, 116, 203, 44, 85, - 125, 2, 162, 57, 194, 177, 225, 62, 23, 48, 201, 250, 111, 53, 2, 214, 55, 36, 119, 249, 138, - 172, 79, 49, 225, 232, 167, 69, 165, 93, 69, 240, 253, 72, 27, 122, 77, 133, 150, 14, 0, 38, - 122, 108, 74, 190, 241, 112, 119, 33, 136, 234, 87, 238, 68, 104, 215, 19, 99, 248, 131, 210, - 52, 57, 53, 186, 224, 43, 60, 182, 234, 172, 215, 41, 184, 229, 49, 255, 203, 50, 243, 182, - 179, 123, 135, 93, 42, 191, 178, 113, 107, 25, 223, 71, 239, 150, 120, 127, 225, 63, 7, 9, 235, - 114, 85, 101, 159, 44, 36, 211, 81, 130, 212, 221, 34, 161, 198, 209, 236, 52, 138, 64, 187, - 232, 28, 61, 219, 224, 159, 93, 161, 174, 202, 76, 39, 119, 188, 147, 209, 104, 168, 10, 137, - 133, 224, 18, 10, 38, 9, 26, 64, 29, 15, 70, 79, 156, 104, 239, 105, 234, 54, 23, 69, 208, 107, - 173, 178, 130, 58, 209, 49, 215, 106, 103, 131, 122, 172, 247, 139, 62, 31, 200, 245, 174, 238, - 54, 53, 94, 98, 229, 156, 162, 4, 101, 102, 178, 159, 195, 148, 230, 227, 102, 89, 254, 93, - 247, 90, 206, 35, 253, 108, 41, 174, 102, 101, 58, 103, 210, 70, 64, 55, 204, 4, 229, 223, 44, - 255, 81, 254, 163, 207, 78, 169, 3, 12, 11, 62, 248, 95, 122, 159, 187, 107, 13, 155, 236, 189, - 80, 173, 72, 200, 104, 132, 191, 153, 31, 117, 197, 198, 61, 59, 178, 102, 193, 50, 198, 136, - 135, 24, 64, 57, 54, 176, 6, 21, 109, 151, 14, 240, 33, 129, 112, 112, 217, 2, 200, 90, 201, - 146, 235, 51, 178, 69, 233, 221, 25, 192, 37, 128, 184, 72, 51, 233, 32, 228, 112, 42, 31, 162, - 211, 197, 186, 12, 87, 177, 175, 195, 135, 35, 191, 50, 110, 92, 58, 120, 219, 49, 137, 129, - 209, 252, 45, 218, 109, 149, 215, 75, 0, 179, 142, 183, 135, 229, 85, 224, 144, 225, 164, 216, - 37, 209, 9, 215, 106, 235, 29, 84, 119, 71, 190, 155, 17, 103, 200, 98, 53, 249, 250, 174, 215, - 239, 8, 5, 44, 147, 185, 223, 166, 34, 202, 22, 153, 155, 95, 43, 96, 250, 244, 234, 196, 23, - 161, 95, 80, 191, 222, 174, 104, 27, 145, 166, 230, 212, 95, 85, 90, 233, 238, 36, 170, 134, - 197, 5, 242, 208, 121, 113, 93, 227, 72, 65, 231, 224, 127, 61, 71, 246, 33, 70, 67, 185, 162, - 0, 3, 242, 208, 241, 87, 31, 185, 102, 215, 164, 98, 1, 196, 82, 230, 211, 255, 239, 83, 199, - 185, 188, 172, 95, 150, 39, 117, 180, 29, 43, 133, 54, 21, 9, 97, 17, 3, 88, 122, 171, 147, - 190, 121, 129, 232, 47, 217, 110, 199, 111, 92, 136, 232, 244, 202, 61, 134, 75, 72, 214, 162, - 163, 208, 167, 58, 211, 221, 225, 49, 149, 223, 251, 53, 51, 96, 100, 12, 136, 161, 121, 162, - 158, 199, 238, 223, 146, 166, 82, 211, 130, 202, 202, 31, 215, 202, 189, 135, 196, 168, 166, - 98, 102, 223, 96, 237, 95, 243, 121, 60, 117, 225, 103, 148, 229, 210, 100, 78, 105, 189, 249, - 33, 12, 116, 69, 239, 84, 72, 87, 255, 105, 188, 99, 131, 78, 96, 18, 188, 44, 212, 9, 33, 30, - 85, 16, 217, 194, 244, 238, 167, 235, 61, 240, 161, 169, 199, 120, 178, 151, 13, 78, 155, 160, - 50, 251, 204, 60, 62, 207, 233, 102, 254, 41, 195, 89, 85, 65, 88, 0, 78, 202, 237, 224, 135, - 113, 190, 102, 154, 252, 168, 70, 187, 92, 132, 100, 221, 14, 165, 243, 175, 69, 196, 165, 18, - 74, 13, 211, 202, 232, 222, 8, 89, 238, 253, 95, 30, 53, 229, 69, 157, 48, 232, 165, 117, 34, - 140, 182, 46, 133, 133, 183, 27, 207, 181, 38, 244, 28, 22, 179, 75, 212, 101, 199, 21, 162, - 49, 185, 125, 80, 25, 247, 17, 166, 26, 253, 250, 51, 51, 237, 27, 111, 79, 111, 80, 196, 132, - 205, 79, 143, 171, 155, 166, 244, 207, 144, 159, 185, 128, 136, 114, 128, 186, 70, 115, 28, 54, - 228, 194, 110, 212, 0, 51, 177, 86, 165, 216, 145, 255, 31, 35, 242, 193, 19, 149, 239, 61, - 136, 84, 107, 160, 113, 95, 60, 101, 164, 116, 45, 110, 189, 166, 252, 79, 132, 193, 1, 94, - 102, 17, 213, 239, 173, 81, 191, 108, 255, 47, 169, 79, 144, 208, 74, 193, 106, 205, 212, 152, - 62, 69, 139, 23, 11, 3, 112, 193, 160, 187, 239, 224, 80, 110, 1, 112, 11, 39, 159, 98, 250, - 135, 1, 3, 143, 13, 251, 234, 68, 201, 165, 158, 3, 93, 194, 187, 194, 138, 165, 195, 37, 230, - 143, 104, 77, 48, 166, 44, 231, 6, 161, 214, 87, 66, 104, 27, 61, 85, 14, 127, 156, 184, 86, - 249, 217, 203, 19, 43, 29, 122, 222, 133, 169, 17, 3, 188, 244, 175, 209, 37, 249, 15, 89, 132, - 50, 149, 107, 26, 73, 60, 70, 30, 244, 86, 141, 125, 163, 10, 23, 107, 230, 226, 166, 82, 227, - 76, 149, 18, 152, 59, 209, 32, 25, 227, 101, 166, 74, 230, 243, 151, 148, 74, 16, 81, 237, 201, - 81, 242, 153, 181, 158, 248, 126, 162, 13, 91, 42, 18, 152, 122, 189, 214, 193, 216, 68, 159, - 226, 238, 177, 239, 163, 122, 4, 5, 5, 82, 98, 236, 181, 30, 124, 107, 63, 89, 172, 211, 191, - 53, 1, 51, 236, 230, 10, 192, 222, 87, 208, 232, 36, 7, 1, 184, 120, 236, 122, 228, 12, 250, - 164, 94, 93, 1, 31, 132, 166, 229, 168, 188, 56, 54, 172, 131, 11, 255, 143, 243, 147, 94, 87, - 36, 1, 158, 39, 90, 232, 15, 6, 15, 116, 68, 190, 34, 197, 88, 194, 177, 77, 73, 37, 172, 242, - 124, 194, 44, 222, 57, 154, 155, 193, 84, 202, 237, 219, 188, 35, 34, 151, 188, 106, 10, 195, - 213, 193, 102, 191, 174, 147, 0, 145, 206, 142, 89, 194, 86, 119, 110, 58, 121, 167, 183, 149, - 218, 80, 192, 167, 95, 191, 46, 163, 190, 213, 20, 39, 255, 74, 127, 103, 163, 136, 88, 68, - 232, 50, 169, 66, 51, 31, 215, 25, 28, 118, 132, 83, 176, 93, 91, 218, 123, 188, 123, 205, 228, - 115, 251, 242, 65, 84, 191, 125, 199, 218, 199, 22, 60, 112, 168, 146, 4, 218, 170, 58, 72, 3, - 91, 125, 243, 133, 77, 214, 176, 255, 43, 251, 197, 54, 151, 210, 218, 238, 28, 253, 186, 136, - 132, 170, 250, 11, 111, 241, 178, 236, 189, 118, 3, 159, 218, 150, 185, 172, 162, 171, 200, - 225, 55, 43, 173, 44, 119, 244, 77, 210, 87, 222, 63, 65, 105, 233, 235, 130, 220, 241, 89, - 199, 68, 123, 84, 139, 130, 234, 51, 30, 46, 16, 102, 172, 246, 197, 214, 121, 31, 14, 252, - 251, 54, 192, 157, 43, 196, 127, 39, 8, 245, 51, 253, 69, 217, 116, 58, 240, 246, 184, 139, - 155, 153, 223, 158, 124, 74, 179, 112, 166, 234, 225, 88, 128, 174, 203, 1, 56, 6, 160, 64, - 168, 38, 165, 223, 228, 137, 225, 160, 227, 228, 137, 69, 79, 243, 218, 139, 122, 64, 188, 10, - 107, 98, 191, 221, 36, 19, 232, 200, 27, 17, 94, 213, 252, 137, 137, 46, 97, 200, 7, 193, 169, - 4, 188, 179, 239, 129, 131, 113, 57, 118, 144, 106, 177, 70, 220, 115, 182, 225, 214, 83, 84, - 181, 175, 151, 107, 114, 129, 75, 103, 135, 62, 208, 65, 231, 176, 193, 2, 100, 112, 122, 14, - 99, 75, 136, 122, 122, 57, 208, 105, 170, 150, 161, 142, 246, 252, 71, 10, 29, 15, 41, 99, 9, - 3, 118, 58, 68, 23, 59, 151, 208, 190, 40, 26, 84, 149, 0, 63, 176, 211, 84, 115, 235, 159, - 183, 218, 11, 54, 96, 207, 147, 216, 48, 4, 99, 33, 36, 172, 92, 90, 194, 247, 233, 213, 130, - 225, 247, 124, 75, 111, 27, 159, 248, 38, 84, 52, 161, 32, 148, 18, 131, 86, 18, 117, 51, 202, - 161, 129, 215, 147, 103, 211, 187, 34, 230, 229, 53, 37, 93, 185, 201, 106, 202, 179, 167, 212, - 207, 105, 70, 200, 191, 152, 249, 230, 200, 141, 125, 199, 110, 244, 217, 103, 18, 36, 170, - 125, 167, 2, 92, 224, 20, 75, 35, 234, 26, 251, 186, 212, 81, 18, 181, 9, 98, 233, 176, 28, 67, - 64, 202, 242, 79, 15, 36, 248, 111, 244, 98, 2, 231, 122, 149, 226, 4, 216, 139, 211, 9, 161, - 79, 207, 249, 134, 52, 176, 247, 92, 39, 189, 6, 10, 179, 46, 99, 84, 6, 75, 248, 83, 244, 129, - 103, 122, 240, 154, 13, 143, 123, 52, 137, 8, 121, 51, 85, 8, 6, 60, 5, 201, 31, 40, 113, 63, - 201, 222, 47, 218, 243, 149, 58, 140, 27, 128, 131, 186, 190, 93, 173, 183, 237, 254, 130, 200, - 214, 124, 1, 51, 193, 61, 237, 240, 239, 243, 232, 63, 17, 101, 212, 191, 134, 88, 103, 11, - 213, 37, 64, 233, 121, 218, 143, 108, 207, 243, 82, 222, 230, 179, 193, 198, 105, 40, 250, 164, - 132, 45, 38, 206, 74, 226, 59, 45, 171, 36, 49, 112, 186, 2, 62, 82, 205, 121, 145, 195, 229, - 154, 179, 208, 95, 238, 2, 33, 173, 18, 57, 127, 63, 201, 13, 27, 25, 142, 199, 162, 5, 100, 8, - 155, 193, 12, 61, 134, 219, 192, 41, 135, 150, 176, 240, 121, 142, 145, 11, 91, 220, 160, 75, - 113, 39, 68, 141, 177, 99, 139, 72, 66, 51, 50, 7, 79, 72, 91, 31, 82, 109, 106, 66, 2, 232, - 134, 254, 161, 139, 140, 175, 96, 195, 221, 101, 53, 176, 16, 211, 36, 170, 7, 218, 156, 200, - 157, 82, 181, 162, 234, 190, 79, 200, 189, 180, 73, 228, 128, 49, 166, 81, 19, 222, 137, 128, - 102, 160, 45, 82, 56, 51, 139, 6, 159, 57, 105, 35, 222, 94, 166, 158, 128, 57, 188, 154, 221, - 117, 168, 203, 200, 226, 100, 141, 11, 75, 122, 142, 120, 152, 194, 20, 111, 199, 11, 200, 76, - 216, 203, 59, 117, 164, 125, 151, 150, 4, 208, 232, 85, 56, 103, 23, 162, 61, 180, 79, 176, - 143, 137, 175, 240, 184, 251, 175, 221, 78, 185, 128, 60, 5, 171, 79, 204, 184, 66, 95, 121, - 118, 38, 219, 181, 190, 196, 65, 61, 230, 200, 119, 196, 81, 232, 91, 194, 221, 85, 159, 121, - 45, 151, 123, 5, 13, 44, 161, 56, 112, 105, 110, 194, 44, 228, 255, 231, 209, 67, 199, 165, - 172, 69, 27, 100, 87, 105, 9, 255, 54, 177, 211, 31, 224, 223, 123, 182, 191, 231, 246, 191, - 81, 2, 165, 238, 45, 42, 103, 206, 137, 162, 210, 251, 51, 84, 113, 127, 98, 133, 155, 151, 82, - 125, 245, 97, 20, 212, 114, 119, 26, 122, 100, 208, 168, 198, 148, 60, 218, 58, 81, 184, 69, - 70, 17, 193, 242, 76, 166, 193, 107, 210, 21, 132, 46, 243, 254, 223, 66, 76, 9, 155, 167, 226, - 6, 185, 141, 247, 57, 95, 227, 18, 31, 34, 64, 77, 119, 0, 24, 218, 185, 206, 140, 138, 47, 35, - 219, 85, 251, 55, 180, 97, 216, 24, 153, 205, 143, 240, 241, 50, 40, 237, 94, 113, 88, 148, 23, - 17, 213, 127, 251, 178, 149, 195, 232, 99, 149, 145, 127, 104, 168, 109, 54, 39, 4, 118, 167, - 98, 146, 184, 27, 24, 28, 184, 182, 82, 248, 0, 55, 31, 37, 24, 243, 239, 146, 140, 240, 102, - 174, 130, 95, 162, 139, 23, 78, 146, 162, 208, 11, 143, 34, 209, 209, 152, 210, 176, 106, 73, - 7, 15, 62, 167, 79, 146, 182, 153, 115, 125, 222, 207, 165, 132, 104, 189, 133, 128, 73, 217, - 27, 128, 135, 48, 78, 86, 209, 184, 119, 21, 32, 140, 255, 240, 55, 66, 200, 87, 89, 152, 126, - 237, 20, 83, 169, 252, 111, 10, 170, 236, 232, 111, 237, 246, 246, 70, 184, 194, 93, 226, 217, - 132, 49, 150, 54, 38, 169, 40, 53, 131, 190, 5, 51, 235, 176, 10, 131, 150, 172, 173, 213, 245, - 153, 80, 38, 95, 215, 69, 204, 212, 152, 55, 48, 96, 105, 251, 185, 41, 71, 108, 105, 177, 2, - 57, 242, 226, 101, 90, 172, 11, 120, 232, 159, 16, 141, 225, 41, 231, 135, 49, 101, 131, 102, - 223, 245, 42, 39, 50, 188, 117, 244, 225, 182, 99, 55, 108, 235, 254, 126, 92, 86, 228, 154, - 223, 138, 25, 194, 224, 137, 169, 162, 83, 72, 220, 203, 207, 179, 168, 83, 164, 191, 87, 138, - 173, 90, 200, 66, 21, 81, 115, 246, 32, 187, 152, 231, 190, 33, 62, 21, 198, 1, 5, 134, 215, - 50, 244, 66, 157, 177, 194, 98, 118, 103, 65, 238, 254, 133, 66, 242, 110, 21, 35, 149, 138, - 253, 109, 161, 90, 248, 50, 78, 52, 113, 109, 238, 83, 50, 177, 177, 241, 157, 7, 8, 141, 182, - 177, 241, 62, 213, 152, 128, 213, 236, 173, 99, 100, 37, 218, 72, 22, 39, 115, 140, 243, 14, - 48, 74, 27, 62, 59, 75, 9, 139, 23, 227, 77, 96, 122, 44, 45, 72, 108, 162, 186, 25, 41, 228, - 95, 49, 195, 248, 26, 47, 218, 60, 209, 195, 34, 101, 90, 21, 157, 10, 90, 223, 64, 76, 255, - 46, 26, 29, 37, 21, 132, 120, 56, 85, 240, 245, 42, 85, 201, 19, 199, 215, 221, 219, 193, 95, - 246, 84, 223, 224, 75, 5, 245, 224, 25, 164, 171, 217, 216, 9, 150, 241, 151, 15, 213, 40, 18, - 233, 76, 154, 93, 100, 254, 138, 217, 251, 53, 10, 74, 51, 131, 44, 180, 247, 121, 221, 61, - 228, 8, 13, 96, 195, 148, 171, 72, 83, 218, 216, 4, 19, 45, 5, 199, 167, 206, 213, 26, 63, 151, - 140, 247, 170, 246, 148, 72, 237, 152, 67, 140, 153, 250, 169, 232, 66, 46, 89, 190, 246, 48, - 145, 236, 108, 66, 181, 218, 249, 63, 99, 35, 146, 10, 125, 180, 186, 161, 198, 213, 167, 90, - 57, 95, 29, 75, 117, 214, 116, 176, 237, 191, 0, 70, 185, 134, 153, 127, 93, 225, 90, 97, 238, - 247, 204, 237, 219, 28, 66, 213, 173, 120, 198, 91, 139, 80, 14, 144, 27, 79, 213, 9, 240, 81, - 47, 220, 170, 59, 90, 145, 84, 98, 247, 188, 53, 181, 173, 181, 38, 80, 115, 155, 243, 243, - 119, 180, 149, 227, 133, 137, 60, 189, 166, 157, 147, 74, 182, 49, 150, 173, 106, 205, 130, - 140, 134, 227, 192, 162, 2, 79, 137, 70, 192, 213, 55, 213, 137, 99, 48, 229, 252, 198, 16, - 222, 66, 48, 50, 202, 225, 7, 132, 90, 120, 122, 15, 166, 153, 169, 71, 40, 48, 109, 202, 255, - 36, 199, 247, 42, 23, 167, 157, 165, 185, 127, 144, 58, 160, 65, 85, 128, 166, 24, 20, 79, 93, - 244, 178, 83, 91, 14, 148, 120, 245, 79, 76, 208, 242, 23, 104, 211, 141, 160, 122, 223, 185, - 95, 74, 177, 120, 62, 251, 71, 93, 144, 192, 44, 208, 160, 184, 171, 222, 91, 170, 186, 41, - 125, 157, 129, 183, 254, 164, 117, 197, 10, 13, 57, 38, 203, 210, 135, 225, 175, 53, 139, 231, - 76, 109, 107, 74, 198, 158, 58, 235, 61, 20, 35, 118, 163, 219, 127, 222, 97, 0, 216, 34, 228, - 182, 197, 125, 55, 13, 169, 134, 153, 195, 128, 157, 195, 177, 25, 192, 229, 58, 160, 249, 100, - 166, 144, 77, 239, 136, 126, 105, 239, 244, 180, 25, 82, 210, 133, 185, 9, 35, 165, 20, 67, - 100, 130, 188, 179, 105, 12, 77, 132, 40, 246, 76, 73, 253, 83, 80, 152, 224, 19, 73, 166, 227, - 90, 83, 72, 16, 203, 57, 236, 99, 20, 91, 222, 4, 230, 183, 80, 66, 65, 202, 4, 99, 21, 98, 43, - 50, 50, 97, 247, 12, 238, 235, 223, 208, 152, 119, 198, 98, 43, 103, 139, 161, 60, 233, 56, - 129, 92, 1, 164, 177, 44, 124, 89, 38, 96, 130, 62, 160, 83, 17, 113, 127, 146, 177, 216, 73, - 201, 250, 111, 67, 102, 102, 112, 32, 116, 62, 112, 252, 124, 210, 31, 44, 137, 215, 83, 3, 87, - 2, 31, 245, 204, 134, 147, 17, 180, 215, 94, 25, 182, 47, 220, 76, 255, 104, 79, 130, 23, 213, - 81, 81, 232, 32, 99, 65, 93, 157, 190, 196, 197, 203, 225, 44, 82, 89, 98, 110, 117, 164, 209, - 232, 12, 54, 64, 113, 135, 136, 142, 180, 188, 206, 225, 37, 39, 41, 201, 214, 21, 27, 49, 77, - 113, 166, 194, 231, 2, 55, 89, 128, 129, 206, 221, 249, 17, 26, 27, 55, 65, 85, 95, 164, 188, - 214, 225, 236, 249, 35, 39, 115, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8, 17, 28, 33, 41, 49, 62, 65, - 0, + 44, 163, 134, 8, 175, 100, 32, 226, 37, 211, 242, 103, 165, 67, 156, 114, 252, 141, 252, 112, + 136, 62, 82, 144, 194, 70, 221, 212, 106, 9, 135, 165, 141, 147, 157, 23, 237, 225, 245, 253, + 243, 244, 5, 208, 8, 198, 17, 243, 50, 21, 133, 110, 159, 3, 54, 118, 6, 38, 111, 137, 24, 77, + 147, 30, 26, 94, 167, 113, 133, 120, 77, 119, 125, 202, 196, 67, 110, 59, 62, 66, 129, 38, 38, + 35, 19, 28, 146, 143, 128, 98, 123, 210, 222, 148, 187, 49, 2, 59, 245, 167, 77, 131, 199, 212, + 214, 236, 114, 251, 181, 175, 203, 171, 109, 238, 223, 207, 100, 238, 63, 239, 203, 100, 99, + 201, 0, 38, 242, 220, 73, 176, 93, 137, 84, 27, 184, 101, 138, 143, 242, 145, 72, 226, 6, 216, + 67, 117, 32, 3, 31, 185, 138, 57, 15, 62, 222, 20, 146, 137, 117, 130, 210, 196, 166, 102, 34, + 44, 162, 31, 225, 124, 84, 234, 228, 156, 211, 210, 249, 31, 198, 179, 27, 29, 74, 60, 160, + 194, 92, 178, 7, 127, 114, 33, 38, 35, 89, 55, 21, 182, 248, 223, 40, 4, 224, 209, 6, 171, 45, + 197, 135, 125, 209, 89, 183, 158, 12, 201, 70, 86, 165, 94, 25, 48, 217, 218, 198, 225, 182, + 175, 105, 100, 167, 138, 138, 177, 226, 159, 221, 33, 139, 135, 163, 213, 153, 147, 128, 187, + 211, 194, 144, 70, 9, 111, 161, 32, 234, 29, 195, 28, 62, 172, 63, 50, 213, 12, 206, 97, 66, + 163, 11, 66, 227, 190, 109, 149, 98, 102, 123, 210, 31, 185, 191, 121, 30, 93, 184, 230, 48, + 222, 28, 129, 5, 86, 99, 186, 88, 241, 229, 231, 5, 25, 209, 230, 48, 94, 209, 234, 134, 54, + 103, 46, 211, 248, 244, 4, 177, 54, 132, 199, 173, 80, 110, 157, 38, 171, 196, 242, 97, 150, 2, + 78, 145, 8, 174, 21, 175, 183, 175, 48, 11, 151, 224, 231, 239, 53, 164, 76, 19, 156, 110, 102, + 162, 102, 18, 166, 196, 183, 157, 251, 21, 214, 243, 207, 149, 170, 109, 107, 197, 134, 124, + 59, 215, 38, 48, 98, 23, 14, 111, 118, 185, 8, 46, 225, 229, 37, 223, 206, 177, 23, 14, 172, + 54, 33, 192, 34, 68, 182, 72, 110, 184, 211, 211, 49, 92, 54, 113, 118, 103, 38, 139, 15, 204, + 18, 91, 75, 37, 27, 27, 183, 48, 199, 248, 158, 205, 218, 248, 21, 163, 190, 133, 171, 233, + 224, 112, 130, 183, 112, 227, 123, 33, 245, 94, 50, 146, 166, 147, 254, 91, 4, 125, 52, 6, 253, + 124, 24, 253, 62, 146, 61, 172, 241, 24, 49, 88, 108, 234, 146, 211, 17, 10, 108, 19, 243, 220, + 82, 158, 172, 40, 86, 58, 109, 85, 193, 96, 161, 203, 121, 137, 86, 152, 248, 225, 70, 227, 27, + 94, 159, 44, 153, 76, 228, 108, 162, 210, 29, 133, 122, 28, 157, 117, 27, 202, 83, 101, 45, 63, + 238, 136, 40, 152, 230, 224, 40, 182, 67, 236, 167, 68, 137, 63, 222, 23, 27, 56, 159, 101, + 126, 189, 151, 103, 63, 70, 96, 147, 148, 21, 145, 125, 169, 244, 226, 91, 102, 251, 201, 239, + 63, 93, 217, 135, 197, 152, 172, 137, 194, 94, 127, 168, 122, 51, 187, 244, 192, 213, 250, 97, + 77, 62, 241, 75, 22, 122, 194, 4, 135, 193, 36, 213, 115, 41, 52, 43, 100, 184, 182, 132, 205, + 210, 107, 185, 48, 143, 198, 26, 124, 175, 18, 194, 196, 166, 220, 102, 192, 111, 141, 102, + 242, 248, 118, 226, 19, 232, 99, 14, 23, 254, 255, 249, 31, 36, 88, 86, 113, 16, 153, 103, 43, + 73, 26, 52, 224, 206, 147, 71, 177, 144, 109, 200, 255, 87, 100, 115, 145, 113, 187, 128, 75, + 176, 185, 78, 189, 253, 136, 170, 223, 82, 214, 7, 145, 179, 31, 75, 12, 202, 238, 115, 254, + 147, 9, 18, 50, 35, 139, 3, 118, 140, 50, 95, 14, 214, 14, 66, 144, 66, 22, 222, 34, 177, 210, + 20, 239, 242, 19, 237, 151, 249, 228, 120, 143, 97, 244, 59, 49, 160, 47, 20, 159, 170, 146, + 178, 120, 116, 230, 74, 119, 10, 66, 100, 212, 205, 177, 81, 181, 122, 119, 16, 7, 228, 134, + 108, 244, 166, 204, 139, 148, 40, 8, 244, 203, 48, 179, 195, 66, 11, 117, 161, 145, 217, 200, + 203, 48, 0, 67, 35, 252, 101, 47, 138, 69, 34, 127, 6, 8, 224, 48, 24, 219, 16, 215, 92, 201, + 226, 224, 100, 92, 239, 175, 21, 128, 169, 149, 79, 12, 133, 110, 135, 219, 228, 196, 100, 158, + 59, 151, 224, 98, 142, 140, 146, 195, 156, 245, 137, 118, 85, 173, 77, 95, 129, 150, 16, 238, + 191, 94, 48, 111, 200, 27, 55, 97, 225, 23, 230, 191, 188, 15, 182, 159, 207, 85, 168, 130, 9, + 43, 1, 222, 84, 225, 141, 182, 46, 174, 129, 136, 19, 16, 42, 184, 194, 48, 163, 8, 9, 46, 137, + 193, 149, 46, 34, 119, 0, 196, 45, 89, 63, 117, 116, 177, 75, 0, 50, 160, 82, 191, 119, 252, + 222, 199, 151, 223, 84, 61, 53, 89, 214, 109, 226, 117, 132, 194, 219, 24, 55, 141, 215, 202, + 162, 230, 178, 34, 175, 54, 92, 225, 252, 157, 111, 168, 153, 48, 194, 168, 230, 252, 213, 26, + 219, 105, 38, 21, 199, 22, 146, 176, 230, 61, 43, 214, 40, 178, 78, 53, 85, 49, 64, 153, 235, + 148, 192, 145, 215, 220, 46, 187, 138, 224, 223, 210, 23, 39, 244, 39, 138, 232, 176, 106, 176, + 102, 195, 93, 169, 2, 193, 235, 255, 111, 109, 228, 172, 14, 36, 31, 83, 82, 197, 73, 252, 209, + 28, 142, 160, 75, 134, 113, 104, 140, 40, 10, 98, 144, 32, 230, 51, 61, 209, 94, 221, 150, 149, + 136, 82, 3, 237, 53, 246, 126, 97, 45, 63, 151, 96, 168, 98, 226, 161, 211, 77, 25, 29, 11, + 109, 5, 249, 236, 112, 211, 250, 180, 83, 36, 229, 93, 239, 109, 40, 217, 123, 88, 237, 226, + 98, 1, 88, 210, 135, 126, 241, 110, 33, 77, 196, 217, 13, 240, 97, 250, 47, 85, 161, 241, 166, + 181, 34, 78, 133, 30, 93, 205, 1, 149, 230, 226, 84, 191, 132, 245, 87, 41, 11, 201, 157, 12, + 39, 132, 241, 21, 60, 191, 87, 250, 207, 177, 48, 237, 47, 83, 187, 121, 22, 233, 35, 134, 246, + 223, 150, 41, 71, 1, 148, 7, 118, 204, 203, 45, 110, 2, 66, 143, 118, 187, 138, 0, 142, 242, + 123, 101, 138, 72, 196, 164, 124, 4, 134, 90, 24, 226, 146, 144, 205, 65, 110, 124, 171, 236, + 177, 90, 54, 97, 149, 219, 113, 236, 119, 250, 192, 250, 1, 174, 95, 226, 171, 59, 84, 185, + 252, 195, 2, 178, 27, 45, 101, 176, 179, 210, 137, 136, 49, 28, 96, 8, 209, 3, 15, 7, 121, 27, + 104, 157, 112, 71, 176, 190, 238, 91, 156, 241, 153, 244, 87, 188, 55, 127, 186, 31, 1, 133, + 89, 123, 8, 96, 29, 84, 169, 204, 177, 11, 43, 121, 140, 175, 109, 187, 95, 199, 244, 26, 19, + 50, 11, 253, 53, 83, 223, 218, 130, 226, 100, 79, 33, 174, 152, 237, 38, 198, 244, 165, 163, + 221, 90, 50, 234, 246, 53, 129, 129, 0, 247, 207, 18, 113, 217, 64, 80, 18, 88, 208, 144, 241, + 80, 16, 81, 78, 87, 50, 213, 228, 203, 190, 228, 81, 145, 5, 60, 84, 164, 142, 14, 183, 154, + 71, 245, 98, 28, 41, 211, 157, 16, 220, 111, 36, 108, 211, 67, 5, 143, 44, 49, 4, 116, 29, 185, + 8, 198, 73, 250, 208, 30, 242, 7, 185, 160, 102, 80, 29, 192, 234, 92, 136, 206, 34, 212, 119, + 221, 30, 121, 124, 224, 52, 205, 130, 107, 66, 204, 145, 11, 255, 228, 134, 98, 82, 117, 199, + 113, 236, 10, 147, 5, 86, 47, 219, 205, 168, 238, 253, 43, 152, 70, 203, 28, 66, 20, 37, 66, + 84, 1, 86, 161, 214, 249, 121, 208, 218, 177, 24, 161, 215, 165, 226, 113, 6, 60, 182, 204, + 183, 130, 152, 75, 191, 160, 104, 249, 127, 15, 126, 26, 55, 72, 61, 109, 61, 149, 125, 109, + 73, 96, 81, 16, 123, 11, 4, 93, 196, 222, 175, 189, 207, 121, 139, 3, 201, 204, 79, 177, 238, + 77, 212, 38, 64, 85, 169, 10, 23, 156, 133, 220, 110, 145, 101, 49, 102, 174, 176, 158, 60, + 172, 35, 172, 101, 112, 63, 221, 32, 32, 186, 96, 52, 2, 167, 22, 142, 173, 9, 235, 96, 21, 88, + 82, 245, 242, 28, 39, 21, 193, 102, 30, 188, 17, 187, 65, 90, 8, 48, 8, 72, 184, 212, 142, 50, + 132, 212, 109, 147, 76, 69, 240, 244, 239, 147, 147, 62, 172, 159, 90, 75, 50, 177, 167, 118, + 183, 70, 102, 41, 119, 143, 1, 243, 163, 142, 228, 85, 124, 83, 232, 20, 190, 145, 217, 228, + 112, 65, 180, 179, 44, 236, 98, 5, 198, 208, 180, 123, 137, 110, 163, 95, 163, 72, 131, 41, + 214, 247, 79, 139, 130, 145, 237, 178, 230, 254, 112, 100, 193, 58, 36, 47, 241, 82, 192, 81, + 150, 13, 186, 185, 139, 202, 207, 202, 234, 12, 105, 169, 236, 208, 10, 190, 217, 110, 253, + 252, 142, 180, 251, 6, 63, 24, 173, 97, 59, 37, 189, 67, 157, 72, 219, 43, 96, 217, 88, 179, + 96, 169, 17, 56, 114, 138, 115, 147, 57, 187, 138, 165, 86, 74, 214, 136, 59, 8, 73, 139, 253, + 245, 21, 102, 3, 131, 63, 131, 102, 172, 112, 39, 40, 6, 240, 154, 133, 96, 20, 71, 199, 58, + 114, 185, 90, 226, 154, 159, 235, 189, 181, 110, 203, 23, 247, 22, 217, 48, 168, 45, 208, 33, + 65, 177, 202, 240, 191, 212, 223, 100, 200, 149, 28, 177, 13, 242, 88, 209, 153, 91, 56, 186, + 87, 77, 100, 162, 116, 237, 88, 2, 70, 163, 254, 190, 204, 55, 22, 1, 24, 71, 138, 37, 178, 25, + 232, 3, 47, 63, 74, 19, 141, 71, 31, 153, 55, 5, 247, 214, 177, 166, 98, 10, 107, 169, 139, + 245, 231, 180, 61, 12, 125, 34, 212, 165, 29, 225, 60, 96, 166, 223, 148, 201, 44, 33, 100, 72, + 150, 96, 253, 201, 29, 12, 155, 92, 177, 153, 175, 163, 26, 136, 77, 108, 131, 48, 132, 59, 98, + 248, 199, 200, 68, 99, 87, 77, 160, 62, 66, 51, 179, 121, 2, 207, 227, 102, 198, 186, 34, 126, + 211, 196, 112, 69, 193, 105, 58, 52, 23, 53, 182, 103, 243, 139, 213, 7, 93, 37, 57, 142, 180, + 108, 60, 62, 171, 135, 81, 168, 77, 95, 22, 135, 27, 124, 102, 51, 70, 15, 221, 116, 255, 158, + 123, 164, 77, 172, 1, 93, 38, 20, 212, 49, 103, 82, 177, 71, 198, 119, 4, 137, 38, 142, 34, 61, + 197, 196, 8, 159, 170, 216, 162, 50, 59, 193, 216, 67, 252, 100, 206, 237, 216, 64, 34, 178, + 139, 171, 172, 186, 143, 253, 22, 225, 11, 54, 210, 165, 246, 117, 172, 112, 243, 173, 80, 68, + 73, 254, 56, 209, 92, 230, 234, 117, 140, 155, 248, 155, 0, 227, 26, 222, 31, 188, 138, 215, + 164, 49, 254, 165, 239, 45, 137, 105, 9, 47, 146, 98, 90, 77, 194, 107, 247, 8, 140, 212, 215, + 63, 64, 26, 147, 246, 200, 65, 243, 120, 96, 70, 81, 186, 216, 226, 55, 57, 44, 36, 57, 186, 4, + 210, 122, 49, 106, 132, 209, 39, 95, 209, 52, 48, 22, 214, 93, 49, 47, 75, 127, 41, 251, 47, + 57, 216, 49, 161, 162, 45, 85, 196, 91, 132, 213, 111, 84, 83, 135, 14, 80, 142, 73, 24, 1, 88, + 70, 51, 215, 73, 188, 42, 11, 78, 138, 181, 217, 146, 178, 24, 43, 50, 48, 116, 247, 61, 84, + 18, 91, 151, 210, 238, 68, 54, 35, 187, 31, 153, 24, 249, 111, 246, 195, 189, 189, 243, 122, + 45, 235, 5, 69, 245, 101, 233, 123, 187, 202, 236, 246, 139, 238, 101, 95, 11, 205, 206, 112, + 114, 126, 67, 72, 32, 63, 62, 181, 251, 4, 156, 137, 170, 236, 18, 247, 64, 135, 171, 252, 156, + 75, 65, 147, 58, 245, 24, 12, 116, 154, 190, 5, 21, 95, 139, 223, 58, 2, 132, 231, 139, 123, + 232, 234, 205, 136, 166, 122, 27, 204, 202, 222, 55, 217, 21, 193, 149, 69, 226, 154, 127, 24, + 95, 61, 201, 249, 39, 18, 167, 69, 7, 244, 141, 55, 244, 117, 34, 151, 102, 121, 118, 1, 197, + 181, 250, 19, 54, 179, 30, 196, 185, 67, 33, 139, 58, 230, 13, 203, 132, 3, 26, 96, 212, 232, + 165, 232, 44, 159, 17, 22, 252, 6, 21, 213, 16, 95, 252, 50, 173, 41, 29, 72, 38, 169, 62, 32, + 220, 17, 242, 162, 186, 199, 24, 136, 22, 166, 249, 161, 11, 179, 224, 225, 95, 4, 32, 148, + 189, 199, 183, 150, 222, 231, 236, 14, 55, 58, 104, 17, 200, 63, 233, 31, 44, 9, 160, 95, 244, + 79, 176, 178, 181, 35, 64, 68, 10, 179, 108, 11, 142, 24, 230, 94, 27, 62, 163, 241, 57, 194, + 2, 242, 175, 187, 184, 73, 180, 83, 210, 238, 157, 69, 179, 51, 239, 91, 113, 201, 228, 133, + 131, 173, 194, 115, 49, 6, 39, 17, 134, 113, 76, 19, 229, 254, 1, 236, 198, 76, 92, 250, 167, + 64, 68, 85, 136, 186, 71, 224, 113, 57, 166, 161, 129, 165, 250, 201, 208, 16, 31, 9, 241, 6, + 7, 44, 197, 71, 118, 174, 190, 37, 206, 122, 9, 133, 100, 228, 87, 147, 57, 190, 24, 32, 253, + 4, 177, 245, 230, 171, 60, 90, 77, 11, 144, 136, 200, 119, 52, 249, 179, 253, 120, 86, 185, 29, + 77, 189, 194, 170, 240, 117, 91, 49, 195, 97, 199, 70, 133, 111, 187, 187, 17, 110, 68, 245, + 219, 226, 43, 174, 70, 57, 158, 130, 47, 43, 11, 229, 39, 128, 153, 226, 73, 218, 53, 93, 180, + 239, 250, 248, 74, 243, 212, 206, 185, 109, 161, 192, 194, 60, 61, 40, 1, 157, 158, 131, 58, + 154, 173, 203, 34, 220, 102, 237, 15, 249, 18, 246, 62, 18, 118, 43, 22, 54, 234, 110, 139, 74, + 138, 121, 24, 131, 237, 152, 157, 38, 183, 40, 125, 151, 182, 215, 33, 71, 138, 32, 128, 145, + 132, 159, 105, 75, 126, 132, 61, 31, 161, 3, 65, 44, 93, 96, 43, 88, 138, 70, 91, 20, 125, 31, + 130, 25, 157, 215, 224, 141, 131, 100, 107, 227, 8, 248, 53, 70, 10, 27, 84, 10, 139, 180, 111, + 198, 39, 152, 74, 170, 75, 30, 197, 235, 89, 252, 234, 133, 80, 209, 107, 125, 129, 215, 162, + 228, 179, 244, 78, 64, 211, 27, 104, 209, 109, 152, 232, 214, 252, 154, 253, 17, 115, 183, 214, + 1, 141, 110, 159, 130, 90, 72, 18, 99, 228, 241, 113, 194, 55, 115, 141, 107, 160, 229, 186, + 46, 58, 199, 97, 185, 161, 74, 91, 190, 148, 186, 31, 130, 77, 59, 184, 244, 138, 113, 42, 192, + 175, 79, 80, 31, 133, 72, 95, 100, 180, 13, 234, 39, 187, 243, 33, 48, 233, 61, 154, 42, 215, + 114, 156, 118, 179, 203, 170, 71, 135, 151, 134, 145, 142, 197, 124, 52, 50, 195, 45, 206, 182, + 249, 35, 51, 118, 54, 189, 67, 70, 68, 132, 221, 246, 5, 29, 187, 138, 32, 204, 99, 129, 94, + 68, 116, 66, 171, 120, 139, 95, 113, 185, 95, 81, 85, 99, 117, 90, 216, 188, 64, 195, 222, 126, + 215, 180, 58, 188, 51, 169, 173, 227, 215, 182, 250, 3, 119, 41, 131, 11, 53, 11, 108, 63, 215, + 91, 57, 70, 255, 83, 74, 168, 15, 42, 13, 46, 210, 156, 18, 18, 164, 84, 95, 169, 124, 4, 251, + 80, 33, 32, 97, 117, 255, 226, 136, 50, 155, 196, 68, 251, 126, 182, 71, 243, 243, 155, 53, + 204, 202, 36, 203, 109, 41, 162, 245, 198, 246, 198, 253, 230, 112, 103, 111, 12, 23, 66, 176, + 164, 45, 85, 55, 165, 101, 1, 116, 73, 188, 119, 186, 105, 74, 8, 87, 154, 104, 125, 122, 105, + 50, 124, 172, 78, 197, 110, 131, 6, 7, 43, 212, 225, 14, 12, 149, 117, 49, 164, 167, 128, 242, + 80, 68, 58, 182, 83, 161, 94, 175, 21, 119, 23, 157, 203, 247, 52, 54, 195, 205, 154, 191, 159, + 203, 32, 117, 99, 146, 8, 129, 84, 96, 108, 189, 45, 145, 193, 124, 76, 249, 7, 240, 19, 151, + 169, 242, 127, 11, 61, 108, 19, 141, 52, 26, 197, 127, 96, 27, 116, 69, 210, 111, 46, 161, 233, + 94, 48, 233, 37, 188, 90, 27, 214, 7, 123, 144, 45, 127, 114, 223, 112, 129, 72, 23, 187, 32, + 25, 135, 166, 35, 80, 182, 170, 145, 166, 195, 126, 36, 211, 163, 48, 235, 106, 17, 146, 209, + 13, 9, 34, 114, 206, 19, 165, 233, 157, 103, 122, 66, 83, 240, 223, 46, 203, 7, 170, 118, 160, + 111, 107, 64, 230, 159, 20, 25, 9, 192, 119, 242, 169, 143, 155, 224, 118, 13, 30, 175, 226, + 165, 35, 241, 250, 73, 219, 86, 140, 133, 50, 106, 74, 131, 132, 217, 221, 160, 122, 89, 230, + 23, 142, 80, 200, 171, 27, 231, 75, 94, 189, 100, 216, 234, 115, 167, 217, 190, 245, 73, 74, + 37, 183, 182, 180, 157, 83, 47, 14, 242, 247, 175, 9, 121, 75, 183, 48, 65, 74, 202, 95, 115, + 116, 68, 163, 95, 141, 113, 29, 96, 18, 162, 3, 82, 55, 162, 16, 240, 30, 157, 115, 8, 150, + 194, 38, 230, 0, 194, 2, 72, 177, 145, 242, 204, 115, 143, 42, 173, 248, 22, 24, 28, 139, 199, + 207, 137, 98, 214, 49, 13, 172, 8, 202, 131, 87, 235, 173, 15, 245, 235, 101, 125, 210, 24, 75, + 82, 3, 22, 87, 16, 255, 196, 16, 143, 142, 242, 123, 117, 133, 62, 44, 210, 50, 193, 172, 112, + 105, 141, 52, 210, 166, 249, 46, 157, 161, 237, 244, 155, 107, 228, 254, 108, 28, 43, 98, 227, + 117, 172, 119, 200, 125, 173, 209, 225, 223, 17, 130, 20, 62, 125, 98, 56, 138, 191, 241, 186, + 217, 100, 17, 191, 63, 163, 123, 135, 2, 43, 58, 116, 43, 143, 200, 39, 67, 215, 33, 143, 74, + 148, 103, 216, 211, 104, 81, 38, 128, 128, 187, 164, 145, 78, 37, 193, 172, 26, 165, 63, 216, + 74, 213, 154, 113, 227, 111, 42, 158, 193, 32, 102, 163, 153, 0, 176, 140, 69, 184, 9, 98, 232, + 254, 111, 27, 38, 47, 16, 240, 109, 203, 70, 190, 24, 73, 67, 244, 27, 116, 99, 114, 158, 63, + 113, 213, 221, 61, 1, 58, 173, 241, 44, 51, 114, 143, 116, 211, 64, 169, 198, 61, 107, 211, + 192, 84, 169, 245, 140, 178, 43, 114, 198, 169, 161, 55, 236, 73, 16, 253, 180, 150, 238, 248, + 17, 71, 126, 114, 100, 67, 121, 65, 9, 11, 181, 212, 175, 214, 139, 86, 189, 196, 237, 184, + 122, 29, 74, 205, 99, 140, 30, 49, 57, 168, 80, 50, 37, 71, 222, 42, 122, 192, 61, 9, 201, 101, + 239, 87, 249, 136, 241, 27, 16, 11, 235, 146, 139, 206, 167, 13, 78, 116, 137, 217, 184, 4, + 229, 78, 75, 144, 2, 129, 203, 88, 59, 147, 68, 204, 211, 195, 206, 84, 253, 87, 236, 18, 115, + 251, 81, 31, 82, 173, 41, 131, 18, 186, 72, 86, 181, 160, 167, 32, 235, 27, 10, 239, 154, 74, + 157, 211, 221, 89, 56, 196, 231, 16, 88, 5, 39, 40, 142, 242, 143, 50, 164, 122, 36, 123, 227, + 116, 134, 12, 160, 46, 87, 98, 138, 70, 202, 87, 53, 189, 30, 252, 79, 61, 28, 36, 242, 233, 5, + 108, 58, 174, 47, 168, 172, 190, 181, 65, 240, 181, 187, 184, 78, 71, 58, 202, 247, 109, 192, + 204, 211, 138, 250, 169, 189, 95, 133, 127, 29, 91, 75, 73, 246, 135, 220, 13, 176, 124, 25, + 56, 59, 67, 119, 204, 69, 57, 143, 18, 74, 91, 243, 197, 84, 193, 13, 232, 223, 193, 1, 135, + 241, 103, 171, 230, 167, 218, 61, 133, 65, 122, 126, 238, 94, 196, 15, 183, 148, 40, 181, 209, + 133, 145, 94, 213, 232, 74, 49, 180, 217, 66, 235, 102, 206, 10, 97, 177, 156, 194, 56, 119, + 22, 0, 11, 157, 179, 169, 76, 231, 130, 110, 105, 39, 247, 200, 116, 138, 238, 174, 92, 205, + 42, 158, 80, 119, 234, 68, 143, 85, 96, 98, 157, 146, 177, 172, 229, 33, 70, 31, 13, 194, 215, + 17, 245, 54, 25, 201, 113, 58, 207, 203, 221, 77, 132, 145, 52, 208, 150, 222, 117, 170, 42, + 150, 87, 215, 209, 118, 40, 169, 48, 195, 152, 211, 67, 200, 143, 103, 254, 232, 61, 211, 24, + 99, 120, 163, 149, 128, 57, 139, 170, 192, 230, 217, 219, 220, 241, 162, 129, 58, 88, 221, 31, + 46, 194, 77, 228, 178, 84, 220, 237, 254, 252, 139, 208, 214, 189, 35, 190, 229, 205, 103, 139, + 34, 208, 47, 83, 20, 118, 33, 252, 33, 250, 178, 79, 118, 255, 157, 209, 17, 181, 185, 84, 155, + 132, 159, 27, 17, 83, 247, 176, 13, 182, 9, 218, 178, 43, 10, 54, 196, 17, 24, 226, 15, 69, + 250, 198, 156, 69, 28, 0, 110, 79, 241, 78, 89, 154, 209, 92, 201, 20, 101, 148, 251, 52, 255, + 2, 95, 63, 219, 228, 223, 189, 68, 254, 241, 73, 12, 171, 64, 9, 91, 37, 207, 56, 33, 19, 44, + 232, 137, 241, 167, 66, 139, 246, 39, 15, 36, 158, 87, 117, 59, 29, 152, 2, 171, 45, 18, 13, + 81, 184, 178, 115, 251, 126, 86, 2, 56, 173, 187, 85, 172, 245, 69, 212, 127, 103, 146, 115, + 159, 106, 240, 131, 136, 145, 140, 236, 146, 148, 42, 13, 38, 49, 170, 207, 225, 28, 170, 216, + 241, 50, 69, 165, 147, 204, 115, 48, 203, 7, 189, 45, 134, 165, 106, 3, 239, 45, 224, 202, 221, + 171, 73, 46, 74, 86, 167, 255, 162, 1, 224, 33, 98, 110, 193, 221, 152, 127, 234, 83, 132, 9, + 25, 235, 10, 141, 141, 145, 6, 128, 245, 144, 170, 19, 5, 51, 226, 151, 219, 209, 231, 228, + 186, 146, 37, 67, 248, 4, 149, 71, 250, 126, 230, 206, 90, 127, 168, 32, 78, 172, 217, 8, 45, + 206, 178, 123, 95, 238, 214, 196, 176, 68, 250, 159, 89, 40, 239, 209, 106, 183, 148, 63, 179, + 231, 78, 13, 238, 62, 117, 81, 176, 217, 238, 228, 203, 198, 83, 213, 12, 141, 192, 156, 165, + 242, 205, 137, 30, 157, 244, 143, 177, 90, 83, 176, 107, 128, 164, 188, 163, 166, 46, 206, 196, + 31, 250, 28, 102, 20, 143, 53, 159, 251, 209, 44, 4, 108, 32, 118, 81, 223, 6, 219, 168, 79, + 133, 109, 8, 234, 154, 176, 149, 120, 192, 91, 46, 146, 119, 131, 237, 65, 163, 223, 164, 205, + 153, 167, 164, 49, 131, 157, 195, 111, 122, 246, 137, 78, 41, 216, 131, 162, 22, 122, 89, 199, + 130, 191, 65, 61, 175, 110, 170, 19, 96, 237, 40, 109, 206, 185, 178, 9, 61, 196, 177, 66, 76, + 67, 159, 189, 26, 99, 40, 125, 220, 60, 68, 120, 173, 135, 130, 141, 214, 192, 249, 76, 81, + 148, 221, 154, 254, 62, 187, 174, 61, 161, 146, 75, 155, 144, 49, 70, 135, 196, 191, 36, 88, + 184, 146, 162, 249, 134, 250, 188, 87, 101, 224, 240, 42, 127, 30, 143, 94, 92, 96, 14, 194, + 194, 44, 165, 197, 150, 234, 85, 132, 75, 9, 102, 53, 140, 131, 236, 39, 48, 17, 68, 187, 59, + 80, 58, 110, 112, 92, 186, 147, 70, 224, 5, 187, 225, 32, 77, 19, 56, 75, 134, 74, 249, 5, 28, + 211, 89, 60, 216, 71, 191, 42, 30, 77, 142, 231, 108, 27, 144, 90, 205, 54, 103, 126, 19, 90, + 84, 139, 111, 0, 147, 5, 93, 10, 72, 7, 136, 189, 100, 199, 186, 162, 155, 30, 203, 111, 198, + 103, 160, 178, 224, 16, 27, 72, 169, 41, 49, 28, 111, 50, 65, 222, 0, 132, 14, 83, 81, 132, 14, + 49, 36, 56, 165, 57, 67, 12, 229, 198, 152, 255, 91, 182, 41, 199, 106, 26, 31, 11, 229, 145, + 237, 99, 4, 26, 135, 228, 135, 83, 34, 200, 94, 26, 104, 92, 244, 87, 74, 114, 185, 116, 173, + 186, 35, 244, 26, 123, 187, 223, 5, 70, 88, 153, 208, 106, 108, 10, 90, 57, 168, 156, 223, 2, + 56, 166, 162, 230, 80, 170, 41, 181, 123, 193, 20, 54, 240, 32, 72, 54, 19, 153, 190, 27, 23, + 53, 246, 48, 206, 222, 53, 248, 157, 2, 101, 60, 154, 101, 132, 120, 63, 53, 148, 54, 76, 50, + 30, 213, 149, 134, 190, 138, 210, 240, 87, 22, 0, 182, 205, 241, 202, 72, 35, 156, 28, 160, + 123, 85, 180, 31, 22, 207, 152, 193, 202, 138, 91, 180, 27, 243, 139, 70, 255, 203, 31, 151, + 46, 238, 52, 18, 26, 176, 224, 214, 82, 48, 162, 16, 144, 46, 75, 19, 101, 93, 206, 34, 85, + 248, 81, 232, 87, 29, 57, 124, 198, 47, 191, 6, 108, 81, 146, 52, 192, 185, 3, 139, 104, 180, + 43, 134, 254, 161, 74, 149, 84, 213, 80, 220, 17, 112, 22, 37, 12, 110, 231, 33, 147, 35, 59, + 98, 198, 233, 1, 46, 13, 137, 252, 135, 103, 242, 227, 27, 56, 22, 58, 194, 48, 131, 4, 40, + 137, 197, 109, 202, 51, 228, 161, 254, 45, 46, 98, 73, 87, 55, 182, 250, 62, 252, 244, 150, 70, + 149, 158, 50, 35, 166, 226, 51, 172, 208, 95, 183, 96, 55, 185, 94, 48, 186, 5, 194, 19, 254, + 103, 96, 24, 148, 84, 113, 240, 47, 94, 214, 252, 53, 91, 249, 19, 90, 236, 96, 169, 69, 235, + 56, 154, 168, 129, 209, 196, 37, 195, 21, 144, 103, 124, 241, 171, 147, 237, 141, 223, 195, + 227, 242, 90, 95, 248, 187, 27, 96, 73, 74, 254, 195, 122, 225, 245, 249, 161, 92, 81, 240, + 108, 14, 235, 247, 33, 227, 6, 189, 33, 225, 120, 180, 121, 133, 87, 11, 102, 242, 192, 174, + 97, 185, 136, 124, 36, 252, 35, 244, 193, 215, 52, 20, 255, 1, 177, 179, 82, 106, 72, 97, 11, + 81, 30, 66, 88, 97, 110, 130, 59, 61, 151, 160, 220, 251, 255, 5, 36, 124, 148, 161, 165, 197, + 221, 222, 1, 48, 70, 90, 114, 156, 189, 202, 211, 220, 46, 53, 156, 192, 11, 24, 79, 91, 92, + 216, 240, 251, 24, 26, 52, 68, 140, 166, 192, 247, 251, 21, 54, 65, 119, 141, 144, 162, 194, + 216, 225, 231, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 13, 22, 32, 36, 44, 53, 64, 0, +]; + +const MESSAGE: [u8; 64] = [ + 29, 204, 154, 221, 65, 56, 204, 167, 12, 130, 160, 47, 200, 7, 250, 159, 194, 82, 16, 98, 102, + 89, 177, 73, 39, 15, 105, 116, 233, 169, 31, 160, 5, 186, 46, 229, 44, 126, 198, 98, 20, 39, + 194, 203, 249, 170, 183, 196, 80, 111, 6, 194, 23, 17, 183, 73, 119, 95, 8, 123, 190, 17, 14, + 186, ]; fn test_gen_key_pair() { @@ -437,7 +442,6 @@ fn test_sign() { .unwrap() }; - let msg = Mldsa87Msg::default(); let sign_rnd = Mldsa87SignRnd::default(); // Deterministic signing let seed = KeyReadArgs::new(KeyId::KeyId0); // Reuse SEED @@ -445,7 +449,7 @@ fn test_sign() { .sign( &seed, &Mldsa87PubKey::from(PUBKEY), - &msg, + &MESSAGE.into(), &sign_rnd, &mut trng, ) @@ -457,13 +461,11 @@ fn test_sign() { fn test_verify() { let mut ml_dsa87 = unsafe { Mldsa87::new(MldsaReg::new()) }; - let msg = Mldsa87Msg::default(); - assert_eq!( ml_dsa87 .verify( &Mldsa87PubKey::from(PUBKEY), - &msg, + &MESSAGE.into(), &Mldsa87Signature::from(SIGNATURE) ) .unwrap(), diff --git a/sw-emulator/lib/periph/src/ml_dsa87.rs b/sw-emulator/lib/periph/src/ml_dsa87.rs index d12ae0047c..a6627d86a9 100644 --- a/sw-emulator/lib/periph/src/ml_dsa87.rs +++ b/sw-emulator/lib/periph/src/ml_dsa87.rs @@ -12,7 +12,7 @@ File contains Ml_Dsa87 peripheral implementation. --*/ -use crate::helpers::{bytes_from_words_be, words_from_bytes_be}; +use crate::helpers::{bytes_from_words_be, words_from_bytes_be, words_from_bytes_le}; use crate::{KeyUsage, KeyVault}; use caliptra_emu_bus::{ActionHandle, BusError, Clock, ReadOnlyRegister, ReadWriteRegister, Timer}; use caliptra_emu_derive::Bus; @@ -397,9 +397,10 @@ impl Mldsa87 { None => (KvRdSeedStatus::ERROR::SUCCESS.value, Some(result.unwrap())), }; - // TODO read the first 32 bytes from KV? + // Read the first 32 bytes from KV? + // Key vault already stores seed in hardware format if let Some(seed) = seed { - self.seed = words_from_bytes_be( + self.seed = words_from_bytes_le( &<[u8; ML_DSA87_SEED_SIZE]>::try_from(&seed[..ML_DSA87_SEED_SIZE]).unwrap(), ); } @@ -437,6 +438,7 @@ mod tests { use caliptra_emu_bus::Bus; use caliptra_emu_crypto::EndianessTransform; use caliptra_emu_types::RvAddr; + use rand::Rng; use tock_registers::registers::InMemoryRegister; use super::*; @@ -455,8 +457,6 @@ mod tests { const OFFSET_KV_RD_SEED_CONTROL: RvAddr = 0x8000; const OFFSET_KV_RD_SEED_STATUS: RvAddr = 0x8004; - include!("./test_data/ml_dsa87_test_data.rs"); - fn make_word(idx: usize, arr: &[u8]) -> RvData { let mut res: RvData = 0; for i in 0..4 { @@ -522,7 +522,7 @@ mod tests { let mut ml_dsa87 = Mldsa87::new(&clock, key_vault); - let mut seed = [0u8; 32]; + let mut seed = rand::thread_rng().gen::<[u8; 32]>(); seed.to_big_endian(); // Change DWORDs to big-endian. TODO is this needed? for i in (0..seed.len()).step_by(4) { ml_dsa87 @@ -547,7 +547,12 @@ mod tests { } let public_key = bytes_from_words_be(&ml_dsa87.pubkey); - assert_eq!(&public_key, &PUB_KEY); + + // Swap endianness again + seed.to_big_endian(); + let mut rng = StdRng::from_seed(seed); + let (pk, _sk) = try_keygen_with_rng(&mut rng).unwrap(); + assert_eq!(&public_key, &pk.into_bytes()); } #[test] @@ -557,16 +562,21 @@ mod tests { let mut ml_dsa87 = Mldsa87::new(&clock, key_vault); - let mut seed = [0u8; 32]; - seed.to_big_endian(); // Change DWORDs to big-endian. TODO is this needed? + let mut seed = rand::thread_rng().gen::<[u8; 32]>(); + seed.to_big_endian(); // Change DWORDs to big-endian. for i in (0..seed.len()).step_by(4) { ml_dsa87 .write(RvSize::Word, OFFSET_SEED + i as RvAddr, make_word(i, &seed)) .unwrap(); } - let mut msg = [0u8; 64]; - msg.to_big_endian(); // Change DWORDs to big-endian. TODO is this necessary + let mut msg: [u8; 64] = { + let part0 = rand::thread_rng().gen::<[u8; 32]>(); + let part1 = rand::thread_rng().gen::<[u8; 32]>(); + let concat: Vec = part0.iter().chain(part1.iter()).copied().collect(); + concat.as_slice().try_into().unwrap() + }; + msg.to_big_endian(); // Change DWORDs to big-endian. for i in (0..msg.len()).step_by(4) { ml_dsa87 @@ -574,10 +584,10 @@ mod tests { .unwrap(); } - let mut sign_rnd = SIGN_RND; + let mut sign_rnd = rand::thread_rng().gen::<[u8; 32]>(); sign_rnd.to_big_endian(); // Change DWORDs to big-endian. - for i in (0..SIGN_RND.len()).step_by(4) { + for i in (0..sign_rnd.len()).step_by(4) { ml_dsa87 .write( RvSize::Word, @@ -608,7 +618,17 @@ mod tests { } let signature = bytes_from_words_be(&ml_dsa87.signature); - assert_eq!(&signature, &SIGNATURE); + + // Swap endianness again to restore original endianness. + seed.to_big_endian(); + msg.to_big_endian(); + sign_rnd.to_big_endian(); + let mut keygen_rng = StdRng::from_seed(seed); + let (_pk, sk) = try_keygen_with_rng(&mut keygen_rng).unwrap(); + let mut sign_rng = StdRng::from_seed(sign_rnd); + let test_signature = sk.try_sign_with_rng(&mut sign_rng, &msg, &[]).unwrap(); + + assert_eq!(&signature[..SIG_LEN], &test_signature); } #[test] @@ -618,16 +638,29 @@ mod tests { let mut ml_dsa87 = Mldsa87::new(&clock, key_vault); - let msg = [0u8; 64]; + let mut msg: [u8; 64] = { + let part0 = rand::thread_rng().gen::<[u8; 32]>(); + let part1 = rand::thread_rng().gen::<[u8; 32]>(); + let concat: Vec = part0.iter().chain(part1.iter()).copied().collect(); + concat.as_slice().try_into().unwrap() + }; + + let seed = rand::thread_rng().gen::<[u8; 32]>(); + let mut keygen_rng = StdRng::from_seed(seed); + let (pk, sk) = try_keygen_with_rng(&mut keygen_rng).unwrap(); + let sign_rnd = rand::thread_rng().gen::<[u8; 32]>(); + let mut sign_rng = StdRng::from_seed(sign_rnd); + let test_signature = sk.try_sign_with_rng(&mut sign_rng, &msg, &[]).unwrap(); + + msg.to_big_endian(); // Change DWORDs to big-endian. for i in (0..msg.len()).step_by(4) { ml_dsa87 .write(RvSize::Word, OFFSET_MSG + i as RvAddr, make_word(i, &msg)) .unwrap(); } - let mut pub_key = PUB_KEY; + let mut pub_key = pk.into_bytes(); pub_key.to_big_endian(); - for i in (0..pub_key.len()).step_by(4) { ml_dsa87 .write( @@ -639,7 +672,11 @@ mod tests { } // Good signature - let mut signature = SIGNATURE; + let mut signature = { + let mut sig = [0; SIG_LEN + 1]; + sig[..SIG_LEN].copy_from_slice(&test_signature); + sig + }; signature.to_big_endian(); for i in (0..signature.len()).step_by(4) { @@ -673,7 +710,7 @@ mod tests { } let result = bytes_from_words_be(&ml_dsa87.verify_res); - assert_eq!(result, &SIGNATURE[..ML_DSA87_VERIFICATION_SIZE]); + assert_eq!(result, &test_signature[..ML_DSA87_VERIFICATION_SIZE]); // Bad signature let mut signature = [0; SIG_LEN + 1]; @@ -718,7 +755,9 @@ mod tests { // Test for getting the seed from the key-vault. for key_id in 0..KeyVault::KEY_COUNT { let clock = Clock::new(); - let mut seed = [0u8; 32]; + let mut seed = rand::thread_rng().gen::<[u8; 32]>(); + let mut keygen_rng = StdRng::from_seed(seed); + let (pk, _sk) = try_keygen_with_rng(&mut keygen_rng).unwrap(); seed.to_big_endian(); // Change DWORDs to big-endian. let mut key_vault = KeyVault::new(); @@ -731,9 +770,10 @@ mod tests { let mut ml_dsa87 = Mldsa87::new(&clock, key_vault); - // We expect the output to match seed 0. Write a different seed first to make sure the Kv seed is used + // We expect the output to match the generated random seed. + // Write a different seed first to make sure the Kv seed is used let mut seed = [0xABu8; 32]; - seed.to_big_endian(); // Change DWORDs to big-endian. TODO is this needed? + seed.to_big_endian(); // Change DWORDs to big-endian. for i in (0..seed.len()).step_by(4) { ml_dsa87 .write(RvSize::Word, OFFSET_SEED + i as RvAddr, make_word(i, &seed)) @@ -781,7 +821,7 @@ mod tests { } let public_key = bytes_from_words_be(&ml_dsa87.pubkey); - assert_eq!(&public_key, &PUB_KEY); + assert_eq!(&public_key, &pk.into_bytes()); } } } diff --git a/sw-emulator/lib/periph/src/test_data/ml_dsa87_test_data.rs b/sw-emulator/lib/periph/src/test_data/ml_dsa87_test_data.rs deleted file mode 100644 index 662251a087..0000000000 --- a/sw-emulator/lib/periph/src/test_data/ml_dsa87_test_data.rs +++ /dev/null @@ -1,370 +0,0 @@ -/*++ - -Licensed under the Apache-2.0 license. - -File Name: - -ml_dsa87_test_data.rs - -Abstract: - -File contains Ml_Dsa87 test data. - ---*/ - -const PUB_KEY: [u8; PK_LEN] = [ - 234, 227, 152, 52, 65, 255, 55, 105, 1, 5, 203, 137, 159, 107, 240, 211, 203, 61, 8, 182, 61, - 157, 191, 11, 148, 7, 112, 159, 189, 81, 233, 6, 250, 181, 151, 2, 74, 158, 56, 11, 67, 166, - 188, 79, 96, 229, 147, 129, 5, 145, 106, 207, 220, 80, 203, 209, 46, 242, 23, 21, 16, 52, 58, - 167, 244, 170, 200, 241, 63, 255, 185, 43, 221, 191, 97, 236, 88, 151, 191, 154, 105, 245, 190, - 179, 10, 25, 67, 244, 215, 161, 238, 49, 116, 183, 24, 224, 82, 142, 227, 33, 13, 193, 93, 3, - 209, 190, 253, 126, 115, 232, 183, 98, 40, 19, 163, 239, 161, 212, 94, 84, 153, 239, 193, 89, - 94, 100, 231, 149, 200, 41, 162, 63, 125, 35, 99, 143, 127, 49, 145, 83, 182, 246, 245, 13, 77, - 243, 194, 192, 111, 6, 11, 222, 88, 135, 52, 4, 43, 109, 143, 169, 48, 173, 38, 49, 59, 244, - 153, 206, 32, 71, 140, 75, 71, 221, 185, 143, 214, 171, 142, 9, 41, 183, 168, 243, 118, 100, - 130, 235, 226, 38, 172, 137, 1, 242, 120, 206, 217, 121, 160, 28, 208, 214, 213, 199, 107, 94, - 105, 86, 157, 101, 128, 73, 114, 147, 184, 137, 118, 175, 224, 136, 13, 54, 83, 173, 191, 81, - 90, 55, 235, 164, 41, 131, 100, 146, 238, 58, 161, 89, 139, 42, 87, 47, 83, 55, 149, 47, 65, - 163, 196, 254, 32, 161, 194, 114, 73, 113, 157, 243, 103, 134, 103, 162, 19, 62, 174, 2, 80, - 164, 229, 122, 99, 106, 76, 201, 47, 27, 202, 201, 182, 28, 122, 138, 242, 47, 177, 206, 220, - 220, 31, 232, 29, 121, 97, 247, 207, 109, 81, 154, 101, 16, 255, 80, 142, 133, 175, 147, 88, - 53, 198, 53, 112, 41, 96, 87, 13, 168, 254, 3, 70, 93, 195, 167, 251, 53, 63, 179, 34, 141, 71, - 161, 234, 221, 181, 7, 56, 72, 2, 120, 98, 114, 172, 43, 238, 240, 1, 209, 246, 25, 250, 46, - 109, 152, 219, 40, 114, 153, 174, 227, 65, 48, 250, 25, 216, 169, 202, 93, 193, 184, 169, 224, - 11, 103, 195, 82, 71, 206, 249, 39, 199, 18, 157, 61, 91, 4, 104, 233, 136, 33, 229, 86, 155, - 76, 125, 237, 205, 225, 100, 231, 210, 32, 64, 235, 182, 111, 177, 214, 75, 159, 171, 137, 28, - 121, 140, 171, 153, 137, 240, 153, 131, 39, 218, 92, 90, 82, 139, 148, 97, 62, 112, 124, 45, - 138, 9, 186, 0, 119, 90, 53, 7, 201, 166, 32, 184, 221, 160, 255, 229, 11, 17, 178, 32, 69, - 189, 84, 80, 97, 231, 197, 170, 199, 170, 100, 106, 251, 188, 182, 0, 175, 244, 107, 94, 211, - 70, 172, 11, 104, 169, 232, 177, 245, 206, 220, 196, 1, 144, 39, 103, 45, 167, 18, 219, 53, - 180, 147, 58, 174, 246, 183, 110, 234, 195, 186, 186, 17, 5, 42, 236, 238, 189, 27, 234, 162, - 140, 46, 126, 234, 112, 215, 72, 133, 81, 141, 9, 76, 156, 31, 211, 219, 246, 65, 59, 196, 91, - 139, 203, 104, 252, 250, 246, 31, 215, 248, 72, 220, 176, 164, 216, 215, 33, 89, 113, 7, 111, - 221, 45, 125, 121, 135, 211, 71, 28, 172, 33, 174, 207, 45, 34, 252, 192, 97, 203, 224, 206, - 76, 198, 85, 200, 70, 212, 38, 38, 220, 94, 184, 12, 167, 29, 175, 205, 135, 1, 221, 172, 205, - 173, 136, 85, 179, 145, 145, 209, 206, 127, 70, 224, 1, 109, 231, 133, 223, 95, 152, 146, 224, - 21, 158, 141, 47, 186, 130, 198, 38, 221, 249, 198, 235, 161, 194, 213, 193, 8, 22, 243, 44, - 216, 5, 139, 11, 240, 58, 205, 114, 151, 131, 14, 95, 118, 69, 248, 55, 78, 55, 125, 8, 99, - 133, 235, 128, 94, 40, 10, 31, 63, 26, 209, 13, 8, 57, 221, 5, 248, 155, 163, 138, 34, 56, 196, - 46, 54, 248, 65, 166, 70, 127, 200, 13, 158, 4, 83, 213, 249, 139, 247, 49, 19, 43, 105, 58, - 58, 156, 183, 227, 236, 24, 35, 82, 82, 164, 35, 56, 188, 251, 123, 232, 233, 83, 213, 11, 122, - 160, 78, 212, 211, 25, 229, 69, 190, 163, 157, 176, 142, 103, 220, 201, 90, 48, 4, 78, 92, 244, - 120, 44, 73, 245, 48, 191, 214, 164, 95, 211, 254, 107, 19, 172, 11, 164, 255, 207, 13, 63, - 178, 164, 70, 205, 135, 37, 236, 86, 110, 86, 245, 174, 70, 40, 131, 191, 240, 51, 229, 189, - 160, 167, 133, 79, 214, 236, 219, 237, 152, 170, 32, 243, 241, 39, 254, 89, 236, 157, 199, 115, - 105, 83, 201, 88, 84, 235, 100, 155, 85, 109, 37, 150, 58, 242, 115, 142, 223, 79, 31, 120, - 165, 0, 107, 14, 165, 208, 58, 134, 55, 70, 221, 86, 190, 229, 217, 4, 124, 162, 122, 93, 102, - 91, 88, 32, 237, 108, 115, 136, 66, 155, 62, 250, 163, 117, 41, 34, 3, 79, 66, 130, 105, 250, - 110, 42, 163, 135, 237, 179, 23, 190, 216, 118, 94, 144, 120, 96, 125, 13, 72, 206, 218, 155, - 145, 219, 32, 4, 80, 90, 42, 207, 13, 21, 82, 38, 96, 83, 201, 120, 148, 219, 28, 101, 87, 198, - 194, 97, 218, 169, 73, 104, 210, 43, 180, 71, 65, 210, 177, 153, 247, 68, 210, 204, 115, 138, - 202, 245, 199, 8, 62, 218, 150, 151, 61, 53, 27, 79, 48, 170, 141, 38, 189, 44, 223, 224, 89, - 185, 232, 94, 221, 105, 87, 23, 103, 44, 143, 151, 58, 4, 151, 60, 224, 82, 86, 19, 178, 237, - 245, 172, 69, 225, 63, 1, 195, 255, 212, 142, 113, 118, 98, 248, 14, 228, 216, 135, 35, 35, - 153, 10, 90, 9, 220, 119, 241, 31, 9, 111, 205, 128, 199, 193, 114, 217, 76, 118, 144, 118, - 117, 191, 81, 78, 208, 220, 189, 84, 128, 197, 77, 84, 204, 29, 41, 173, 158, 212, 83, 153, - 124, 171, 187, 62, 247, 166, 83, 53, 197, 171, 238, 155, 119, 120, 249, 216, 214, 17, 165, 38, - 145, 173, 36, 146, 208, 38, 120, 27, 153, 213, 160, 105, 57, 199, 255, 214, 192, 70, 103, 125, - 101, 187, 233, 196, 30, 185, 213, 42, 200, 220, 92, 104, 10, 11, 165, 56, 142, 231, 62, 55, 37, - 88, 65, 205, 249, 168, 54, 200, 89, 45, 44, 172, 196, 7, 199, 81, 181, 144, 38, 77, 171, 162, - 47, 238, 94, 103, 44, 73, 159, 252, 119, 181, 78, 245, 94, 30, 215, 228, 182, 50, 55, 9, 245, - 22, 168, 185, 59, 127, 109, 219, 15, 186, 208, 89, 172, 203, 67, 14, 208, 210, 31, 1, 187, 51, - 221, 210, 190, 72, 187, 240, 90, 175, 1, 59, 103, 147, 7, 136, 232, 146, 12, 118, 125, 35, 93, - 84, 8, 252, 238, 97, 27, 120, 204, 229, 101, 225, 85, 30, 103, 59, 167, 211, 180, 230, 202, - 181, 235, 145, 106, 255, 90, 68, 251, 7, 213, 29, 234, 71, 165, 247, 104, 218, 77, 235, 39, - 148, 239, 215, 193, 18, 181, 29, 192, 247, 126, 225, 163, 177, 159, 16, 1, 188, 3, 22, 71, 97, - 109, 113, 216, 232, 240, 56, 247, 185, 125, 65, 134, 201, 227, 21, 27, 114, 35, 249, 74, 35, - 254, 93, 40, 192, 229, 95, 81, 97, 252, 121, 252, 78, 13, 32, 50, 165, 9, 21, 165, 205, 21, 85, - 74, 0, 164, 146, 121, 85, 251, 14, 221, 169, 226, 21, 64, 173, 211, 91, 51, 111, 208, 87, 25, - 20, 232, 182, 168, 48, 159, 238, 199, 27, 40, 67, 117, 172, 133, 108, 225, 100, 239, 215, 193, - 75, 203, 170, 228, 60, 63, 122, 72, 71, 89, 50, 217, 176, 113, 143, 203, 216, 198, 230, 75, - 140, 105, 190, 153, 155, 66, 6, 95, 97, 21, 64, 87, 196, 54, 4, 219, 229, 87, 47, 164, 177, - 236, 7, 137, 70, 110, 215, 9, 154, 121, 180, 101, 123, 139, 150, 125, 9, 159, 178, 158, 149, - 87, 40, 148, 106, 98, 160, 53, 59, 65, 221, 157, 146, 1, 77, 196, 168, 73, 98, 79, 33, 28, 98, - 28, 209, 162, 117, 71, 134, 170, 38, 193, 49, 45, 7, 168, 35, 66, 75, 106, 144, 55, 44, 98, - 228, 51, 237, 124, 195, 27, 43, 60, 235, 12, 205, 5, 188, 78, 94, 136, 99, 32, 63, 51, 103, 39, - 242, 103, 67, 170, 208, 79, 137, 46, 249, 9, 162, 145, 216, 57, 73, 92, 64, 151, 50, 217, 76, - 68, 160, 8, 241, 96, 194, 180, 66, 2, 137, 19, 5, 76, 76, 53, 172, 190, 94, 101, 54, 131, 53, - 56, 130, 136, 201, 120, 213, 105, 185, 88, 33, 151, 183, 136, 104, 79, 233, 30, 83, 237, 61, - 252, 88, 161, 118, 62, 219, 193, 108, 32, 49, 6, 233, 181, 106, 216, 1, 110, 22, 231, 88, 70, - 217, 46, 195, 173, 45, 124, 229, 20, 228, 144, 253, 47, 181, 158, 177, 231, 187, 33, 31, 38, - 76, 94, 31, 17, 208, 81, 183, 155, 248, 16, 98, 47, 157, 101, 210, 33, 145, 95, 18, 57, 1, 84, - 55, 184, 94, 20, 224, 56, 139, 214, 103, 227, 83, 187, 103, 15, 122, 202, 6, 133, 215, 111, 91, - 10, 1, 240, 71, 208, 53, 103, 194, 79, 115, 46, 227, 194, 105, 90, 117, 109, 157, 213, 93, 218, - 128, 123, 6, 151, 55, 35, 60, 78, 145, 210, 50, 200, 114, 71, 151, 230, 154, 177, 71, 231, 51, - 12, 180, 233, 136, 128, 36, 169, 15, 209, 220, 51, 90, 113, 205, 190, 176, 152, 3, 172, 185, - 54, 65, 99, 239, 216, 181, 92, 102, 99, 83, 182, 159, 139, 22, 178, 173, 214, 100, 135, 214, - 97, 137, 78, 59, 247, 171, 17, 79, 22, 142, 38, 223, 111, 211, 162, 164, 12, 163, 238, 114, 66, - 142, 130, 173, 51, 253, 54, 56, 189, 0, 165, 107, 116, 189, 175, 62, 147, 99, 132, 47, 200, 5, - 243, 7, 180, 112, 221, 242, 72, 117, 18, 248, 211, 185, 100, 160, 106, 31, 238, 76, 251, 118, - 128, 99, 91, 255, 218, 106, 191, 28, 93, 82, 48, 184, 71, 232, 240, 84, 48, 147, 236, 131, 252, - 210, 56, 28, 102, 78, 144, 59, 165, 102, 34, 143, 170, 56, 105, 187, 49, 110, 233, 253, 141, - 174, 24, 228, 207, 77, 136, 65, 221, 190, 245, 35, 172, 36, 243, 77, 250, 80, 151, 254, 98, 94, - 9, 52, 181, 118, 243, 92, 215, 155, 161, 76, 85, 65, 129, 248, 4, 171, 159, 13, 2, 127, 109, - 107, 231, 168, 25, 210, 53, 214, 89, 109, 54, 30, 161, 169, 239, 220, 107, 110, 178, 91, 95, - 93, 87, 123, 129, 199, 220, 11, 214, 168, 147, 228, 225, 190, 210, 250, 37, 91, 45, 150, 76, - 89, 234, 71, 15, 79, 216, 48, 67, 79, 207, 201, 53, 228, 184, 66, 85, 138, 84, 111, 241, 42, - 53, 160, 217, 171, 38, 157, 218, 117, 14, 100, 153, 133, 44, 79, 195, 0, 101, 225, 229, 107, - 154, 5, 107, 56, 41, 164, 146, 64, 75, 91, 129, 227, 59, 219, 196, 254, 178, 172, 162, 89, 199, - 129, 225, 25, 249, 82, 162, 161, 176, 140, 120, 228, 83, 80, 87, 190, 147, 187, 94, 214, 155, - 213, 251, 70, 199, 125, 59, 38, 194, 252, 16, 85, 235, 63, 178, 130, 103, 51, 4, 176, 85, 220, - 18, 82, 111, 104, 79, 8, 33, 154, 153, 86, 25, 187, 86, 154, 237, 74, 169, 246, 71, 33, 232, - 34, 125, 183, 115, 176, 253, 66, 11, 96, 252, 132, 15, 181, 117, 115, 166, 17, 94, 108, 37, - 160, 44, 49, 234, 221, 67, 155, 213, 174, 9, 61, 150, 28, 200, 197, 169, 48, 123, 130, 161, - 181, 173, 78, 103, 53, 190, 54, 244, 221, 17, 239, 10, 193, 151, 183, 203, 21, 158, 234, 241, - 248, 238, 193, 20, 74, 143, 212, 226, 210, 217, 38, 160, 179, 219, 82, 250, 164, 146, 223, 249, - 208, 98, 59, 241, 34, 66, 100, 30, 17, 196, 87, 123, 238, 132, 205, 168, 86, 140, 32, 24, 240, - 243, 164, 129, 22, 36, 0, 204, 229, 24, 103, 41, 47, 245, 91, 226, 199, 60, 199, 93, 23, 124, - 150, 44, 134, 64, 251, 153, 216, 209, 232, 99, 85, 73, 160, 11, 30, 225, 83, 60, 126, 108, 98, - 174, 248, 25, 187, 60, 38, 16, 138, 145, 42, 199, 34, 19, 137, 133, 202, 209, 29, 173, 107, - 180, 75, 76, 130, 199, 18, 107, 235, 37, 102, 95, 118, 64, 58, 112, 54, 88, 221, 58, 208, 19, - 48, 223, 253, 47, 62, 180, 89, 231, 150, 114, 237, 97, 101, 91, 57, 173, 212, 253, 59, 71, 88, - 98, 46, 100, 142, 164, 90, 100, 19, 202, 148, 119, 25, 199, 136, 214, 219, 244, 62, 49, 255, - 119, 179, 61, 190, 223, 2, 39, 106, 44, 23, 173, 151, 83, 36, 181, 77, 39, 84, 135, 32, 205, - 239, 218, 7, 208, 50, 253, 152, 187, 95, 53, 6, 219, 87, 221, 3, 127, 52, 203, 23, 56, 105, - 186, 244, 87, 44, 253, 29, 67, 14, 106, 71, 132, 240, 52, 202, 63, 184, 123, 82, 23, 116, 42, - 55, 15, 239, 86, 54, 202, 247, 214, 3, 27, 0, 194, 5, 82, 221, 142, 62, 159, 165, 71, 154, 48, - 97, 19, 51, 83, 147, 57, 50, 235, 158, 194, 172, 190, 132, 44, 34, 188, 110, 88, 163, 202, 204, - 249, 92, 206, 100, 106, 139, 211, 30, 154, 0, 241, 179, 72, 172, 225, 226, 246, 25, 186, 47, - 53, 55, 232, 243, 58, 99, 123, 189, 79, 27, 26, 160, 112, 254, 115, 174, 246, 148, 197, 131, - 112, 211, 199, 202, 51, 45, 93, 168, 190, 41, 97, 3, 120, 105, 49, 80, 162, 167, 209, 204, 103, - 186, 209, 90, 70, 80, 74, 214, 9, 26, 13, 177, 32, 83, 76, 228, 146, 250, 228, 211, 124, 206, - 87, 89, 195, 127, 15, 78, 1, 239, 255, 73, 22, 120, 75, 42, 77, 206, 90, 47, 47, 157, 74, 233, - 46, 55, 88, 146, 159, 88, 69, 125, 236, 224, 213, 158, 202, 83, 209, 156, 144, 138, 216, 170, - 151, 39, 201, 186, 19, 234, 86, 73, 122, 126, 8, 51, 183, 101, 86, 11, 145, 115, 106, 252, 91, - 1, 148, 11, 242, 157, 12, 204, 218, 154, 251, 251, 238, 168, 179, 64, 67, 255, 151, 255, 56, - 166, 34, 14, 163, 8, 38, 73, 220, 40, 56, 233, 176, 45, 100, 212, 32, 253, 199, 92, 237, 231, - 146, 1, 23, 31, 121, 108, 252, 161, 71, 55, 47, 242, 19, 34, 13, 241, 50, 217, 254, 218, 80, - 91, 170, 108, 148, 223, 139, 155, 243, 30, 183, 107, 52, 145, 185, 71, 165, 99, 218, 82, 128, - 71, 35, 247, 60, 189, 158, 210, 93, 108, 13, 242, 81, 244, 66, 9, 136, 32, 138, 221, 4, 33, 8, - 113, 235, 58, 170, 118, 102, 251, 51, 35, 241, 93, 240, 216, 181, 63, 106, 248, 197, 72, 232, - 106, 125, 229, 246, 31, 224, 24, 209, 159, 173, 210, 165, 0, -]; - -const SIGN_RND: [u8; 32] = [0; 32]; -const SIGNATURE: [u8; SIG_LEN + 1] = [ - 94, 33, 98, 146, 161, 54, 134, 128, 25, 186, 123, 227, 252, 67, 83, 186, 107, 220, 17, 173, - 112, 10, 229, 123, 62, 141, 188, 100, 81, 1, 107, 218, 140, 168, 73, 10, 157, 35, 106, 179, - 233, 79, 47, 83, 236, 172, 4, 253, 205, 15, 51, 204, 45, 103, 101, 43, 96, 66, 41, 214, 192, - 198, 192, 66, 214, 212, 206, 233, 172, 249, 172, 193, 195, 189, 166, 2, 142, 131, 232, 50, 19, - 214, 114, 234, 167, 202, 26, 170, 32, 242, 251, 60, 236, 234, 132, 76, 188, 112, 0, 66, 101, - 124, 53, 56, 187, 79, 104, 93, 250, 16, 249, 240, 29, 207, 160, 192, 99, 197, 40, 24, 207, 78, - 113, 73, 139, 244, 110, 110, 192, 234, 220, 144, 246, 25, 83, 28, 80, 7, 44, 58, 14, 19, 61, - 232, 196, 173, 92, 221, 135, 227, 136, 93, 94, 90, 248, 69, 208, 77, 34, 168, 2, 136, 147, 15, - 172, 21, 50, 158, 48, 52, 246, 10, 149, 143, 109, 104, 41, 99, 15, 206, 198, 190, 209, 155, 97, - 194, 219, 179, 184, 150, 219, 95, 159, 88, 212, 102, 76, 2, 122, 170, 209, 56, 85, 65, 94, 123, - 24, 119, 55, 193, 77, 219, 6, 173, 123, 23, 53, 86, 75, 231, 147, 92, 166, 51, 232, 247, 170, - 215, 51, 2, 190, 147, 2, 15, 91, 30, 204, 167, 43, 237, 51, 75, 182, 18, 27, 50, 150, 138, 215, - 126, 117, 41, 99, 118, 86, 73, 2, 108, 25, 193, 207, 42, 35, 242, 177, 64, 247, 149, 141, 75, - 185, 145, 211, 34, 147, 203, 198, 163, 37, 22, 162, 242, 171, 215, 189, 201, 31, 193, 88, 110, - 126, 252, 249, 108, 66, 67, 151, 139, 172, 3, 175, 2, 241, 95, 67, 127, 118, 109, 120, 202, 0, - 212, 12, 221, 248, 68, 77, 69, 17, 6, 62, 154, 28, 61, 74, 251, 153, 78, 233, 190, 190, 103, - 181, 233, 156, 64, 226, 222, 72, 67, 228, 57, 130, 183, 192, 147, 37, 212, 153, 255, 249, 201, - 41, 170, 30, 166, 237, 23, 146, 152, 159, 110, 181, 134, 198, 193, 0, 106, 187, 151, 16, 86, - 152, 201, 94, 229, 234, 0, 95, 36, 146, 207, 91, 224, 194, 236, 136, 0, 8, 92, 5, 92, 32, 99, - 180, 86, 220, 175, 247, 54, 1, 70, 250, 198, 252, 58, 146, 167, 123, 146, 98, 33, 131, 253, 12, - 53, 194, 136, 147, 109, 107, 217, 122, 101, 230, 48, 0, 32, 241, 150, 247, 208, 155, 185, 26, - 147, 210, 161, 28, 136, 132, 84, 13, 112, 29, 96, 87, 160, 108, 183, 50, 76, 161, 16, 114, 61, - 58, 168, 125, 11, 242, 105, 144, 154, 116, 102, 128, 11, 79, 18, 33, 23, 91, 223, 228, 8, 123, - 65, 91, 49, 77, 218, 64, 36, 202, 69, 51, 224, 13, 187, 252, 197, 161, 240, 183, 145, 146, 53, - 142, 179, 47, 54, 169, 162, 234, 213, 185, 63, 231, 140, 202, 238, 36, 116, 240, 174, 197, 150, - 136, 136, 142, 96, 67, 198, 174, 14, 123, 59, 41, 19, 85, 42, 76, 6, 83, 133, 155, 231, 250, - 173, 95, 119, 153, 104, 178, 179, 166, 250, 122, 52, 219, 155, 112, 22, 187, 209, 56, 255, 214, - 136, 230, 93, 96, 21, 239, 143, 21, 191, 51, 61, 30, 91, 241, 39, 29, 151, 7, 181, 232, 104, - 141, 174, 87, 49, 251, 75, 202, 169, 180, 141, 42, 103, 83, 227, 228, 53, 28, 173, 242, 156, - 66, 95, 185, 204, 75, 244, 253, 65, 101, 188, 197, 70, 224, 247, 171, 2, 122, 198, 157, 227, - 176, 45, 210, 178, 169, 52, 222, 59, 18, 122, 245, 91, 180, 136, 66, 1, 128, 84, 218, 208, 20, - 73, 46, 114, 115, 150, 204, 106, 33, 129, 34, 233, 44, 194, 98, 134, 41, 16, 143, 210, 166, 52, - 252, 110, 52, 74, 38, 112, 207, 121, 103, 106, 108, 141, 131, 175, 159, 42, 174, 134, 9, 222, - 125, 28, 208, 129, 120, 25, 84, 16, 42, 200, 171, 22, 70, 249, 217, 49, 143, 107, 9, 232, 157, - 124, 44, 210, 19, 222, 145, 250, 254, 137, 12, 132, 199, 107, 94, 32, 223, 141, 6, 110, 255, - 56, 232, 206, 79, 154, 196, 156, 240, 35, 57, 39, 241, 147, 27, 176, 111, 188, 248, 114, 6, 42, - 235, 21, 180, 177, 24, 53, 144, 4, 128, 167, 230, 26, 130, 201, 131, 211, 180, 159, 113, 157, - 13, 218, 18, 100, 253, 50, 172, 88, 146, 92, 124, 126, 52, 86, 163, 56, 14, 52, 226, 205, 117, - 177, 42, 98, 92, 12, 41, 67, 16, 41, 63, 111, 35, 130, 85, 167, 75, 99, 241, 83, 154, 170, 69, - 47, 87, 166, 172, 88, 179, 246, 222, 181, 180, 116, 197, 42, 45, 238, 230, 80, 243, 185, 230, - 209, 75, 215, 13, 11, 28, 88, 124, 89, 111, 196, 56, 46, 186, 239, 79, 216, 36, 93, 123, 140, - 148, 179, 217, 244, 186, 127, 52, 22, 34, 7, 77, 33, 43, 244, 55, 252, 11, 166, 128, 70, 7, - 137, 115, 8, 31, 179, 233, 212, 38, 255, 0, 225, 247, 230, 72, 94, 244, 23, 58, 16, 174, 66, - 164, 231, 79, 21, 125, 201, 93, 30, 8, 111, 179, 138, 245, 55, 202, 177, 125, 106, 236, 206, - 154, 204, 28, 118, 97, 78, 21, 123, 168, 132, 197, 107, 139, 136, 184, 95, 205, 188, 190, 229, - 73, 239, 19, 235, 248, 177, 19, 240, 191, 162, 56, 126, 110, 40, 214, 135, 140, 231, 35, 137, - 181, 248, 96, 7, 74, 233, 194, 234, 95, 145, 51, 124, 239, 46, 90, 229, 91, 224, 32, 47, 43, - 60, 104, 132, 212, 60, 104, 210, 9, 38, 157, 18, 107, 117, 204, 242, 135, 29, 122, 167, 232, - 45, 106, 234, 193, 11, 217, 253, 219, 235, 200, 157, 94, 172, 179, 71, 250, 91, 224, 115, 84, - 234, 212, 156, 16, 156, 177, 240, 51, 118, 44, 95, 11, 229, 124, 201, 25, 7, 152, 5, 74, 31, - 221, 29, 34, 188, 228, 168, 118, 75, 41, 169, 211, 44, 61, 81, 170, 250, 39, 156, 148, 136, - 162, 79, 34, 35, 20, 220, 248, 39, 170, 79, 131, 245, 210, 229, 22, 122, 166, 49, 120, 232, - 124, 90, 138, 120, 251, 128, 118, 115, 122, 202, 148, 139, 51, 196, 11, 99, 230, 177, 195, 160, - 16, 197, 41, 127, 69, 132, 11, 23, 32, 41, 201, 108, 210, 224, 19, 157, 101, 87, 66, 132, 12, - 128, 170, 194, 5, 33, 251, 148, 162, 225, 76, 46, 251, 192, 168, 217, 140, 81, 164, 99, 180, - 116, 128, 76, 221, 169, 231, 231, 233, 100, 207, 145, 38, 216, 107, 139, 3, 132, 244, 218, 91, - 161, 194, 125, 49, 180, 111, 137, 124, 38, 245, 114, 133, 103, 131, 247, 252, 73, 6, 202, 66, - 200, 170, 72, 45, 229, 203, 191, 149, 9, 97, 24, 1, 39, 189, 209, 221, 105, 152, 115, 119, 92, - 179, 49, 173, 233, 68, 152, 68, 108, 59, 136, 237, 190, 216, 10, 85, 79, 220, 10, 126, 16, 155, - 138, 184, 231, 159, 205, 227, 90, 61, 122, 217, 8, 3, 34, 205, 67, 255, 196, 201, 248, 143, 5, - 86, 227, 191, 28, 123, 189, 146, 227, 29, 117, 100, 74, 1, 44, 119, 65, 83, 125, 83, 118, 155, - 6, 221, 51, 193, 243, 245, 122, 214, 129, 142, 246, 234, 238, 198, 77, 232, 187, 254, 118, 68, - 152, 11, 117, 80, 3, 57, 182, 36, 174, 31, 67, 198, 45, 200, 25, 176, 105, 172, 194, 178, 215, - 155, 186, 233, 139, 21, 127, 108, 193, 86, 185, 233, 220, 243, 210, 72, 251, 93, 125, 196, 124, - 16, 103, 138, 126, 245, 71, 221, 30, 196, 185, 31, 155, 138, 4, 27, 8, 114, 28, 236, 146, 199, - 189, 215, 243, 117, 78, 129, 188, 87, 204, 26, 235, 28, 205, 128, 230, 216, 25, 26, 5, 187, 49, - 120, 8, 35, 182, 153, 135, 56, 184, 253, 239, 175, 167, 125, 117, 77, 211, 87, 56, 41, 157, 95, - 150, 198, 75, 18, 60, 214, 205, 196, 72, 9, 153, 233, 152, 109, 232, 89, 109, 56, 65, 21, 109, - 196, 186, 52, 35, 73, 59, 63, 201, 104, 195, 243, 215, 202, 15, 168, 187, 164, 104, 66, 112, - 122, 237, 195, 122, 74, 137, 104, 224, 57, 28, 254, 45, 65, 151, 234, 143, 106, 123, 118, 29, - 14, 94, 107, 157, 90, 48, 157, 102, 125, 35, 14, 123, 7, 255, 143, 106, 55, 6, 29, 83, 135, - 107, 141, 169, 184, 122, 191, 70, 47, 112, 190, 127, 72, 68, 120, 79, 63, 168, 249, 199, 7, - 226, 64, 125, 117, 102, 182, 222, 28, 224, 157, 202, 219, 214, 145, 77, 222, 102, 140, 83, 158, - 131, 93, 109, 139, 150, 148, 142, 57, 57, 162, 127, 216, 71, 103, 126, 8, 104, 55, 188, 82, - 157, 53, 217, 34, 143, 23, 209, 241, 26, 70, 206, 77, 78, 170, 230, 149, 70, 44, 190, 1, 197, - 125, 154, 236, 20, 41, 209, 124, 111, 10, 0, 54, 133, 193, 195, 97, 34, 110, 99, 244, 212, 111, - 146, 162, 243, 89, 136, 80, 210, 177, 226, 37, 36, 135, 66, 98, 6, 113, 160, 3, 80, 208, 99, - 120, 77, 123, 23, 105, 72, 163, 194, 9, 74, 222, 178, 195, 143, 1, 171, 31, 163, 90, 75, 58, - 114, 67, 255, 123, 249, 247, 86, 106, 86, 156, 255, 209, 246, 22, 68, 110, 32, 40, 140, 221, - 15, 142, 105, 55, 167, 173, 170, 210, 232, 185, 124, 183, 177, 133, 170, 13, 78, 220, 23, 146, - 132, 27, 4, 48, 116, 224, 155, 249, 13, 143, 83, 237, 131, 31, 181, 5, 228, 68, 229, 113, 203, - 96, 46, 134, 32, 148, 21, 166, 76, 169, 173, 78, 135, 238, 73, 185, 139, 213, 95, 23, 192, 76, - 39, 4, 24, 120, 1, 254, 117, 0, 190, 33, 140, 61, 126, 231, 239, 247, 245, 158, 202, 20, 110, - 126, 130, 121, 175, 100, 40, 136, 14, 141, 242, 198, 28, 72, 104, 46, 237, 41, 15, 142, 155, - 190, 55, 141, 194, 228, 222, 199, 107, 49, 159, 107, 142, 211, 192, 16, 23, 186, 56, 145, 190, - 206, 125, 204, 210, 125, 71, 22, 166, 83, 187, 225, 12, 247, 40, 23, 1, 3, 246, 171, 99, 60, - 62, 130, 152, 31, 250, 12, 93, 44, 13, 123, 212, 132, 89, 177, 78, 82, 114, 148, 199, 103, 65, - 249, 79, 13, 118, 59, 62, 166, 206, 186, 171, 135, 223, 20, 163, 85, 137, 236, 236, 6, 202, 99, - 35, 227, 92, 173, 18, 165, 47, 209, 127, 165, 70, 162, 169, 172, 226, 11, 87, 238, 131, 130, - 186, 126, 64, 140, 86, 155, 27, 251, 175, 176, 190, 178, 253, 216, 78, 27, 108, 69, 247, 31, - 111, 107, 31, 123, 200, 84, 49, 21, 94, 232, 147, 100, 254, 19, 79, 153, 143, 92, 211, 235, 42, - 194, 80, 66, 179, 18, 244, 8, 197, 252, 17, 219, 166, 122, 247, 203, 236, 194, 106, 82, 147, - 38, 180, 147, 121, 229, 236, 142, 227, 197, 162, 157, 150, 225, 216, 3, 88, 30, 153, 2, 101, - 157, 62, 45, 47, 157, 138, 49, 105, 163, 44, 248, 69, 29, 109, 248, 213, 173, 59, 248, 17, 149, - 39, 167, 109, 207, 172, 26, 107, 123, 252, 134, 148, 28, 77, 109, 6, 195, 74, 148, 255, 44, - 210, 194, 10, 125, 200, 36, 85, 130, 5, 7, 249, 203, 192, 114, 86, 21, 53, 105, 157, 206, 236, - 56, 81, 91, 34, 229, 235, 52, 168, 123, 75, 3, 162, 22, 197, 93, 175, 246, 58, 88, 111, 60, - 134, 85, 140, 53, 166, 125, 81, 46, 41, 31, 143, 61, 64, 167, 148, 109, 29, 254, 199, 165, 1, - 75, 44, 119, 107, 251, 224, 50, 98, 225, 130, 138, 7, 35, 120, 199, 202, 125, 70, 67, 103, 99, - 71, 107, 175, 221, 71, 162, 25, 122, 229, 116, 91, 80, 122, 220, 216, 175, 226, 77, 234, 125, - 166, 20, 206, 54, 72, 38, 120, 115, 62, 101, 181, 207, 193, 135, 225, 173, 62, 252, 0, 65, 32, - 20, 4, 173, 71, 179, 54, 197, 171, 22, 42, 91, 213, 231, 96, 2, 248, 208, 204, 150, 86, 177, - 179, 138, 135, 50, 79, 58, 13, 162, 174, 199, 8, 135, 45, 242, 137, 137, 162, 25, 46, 165, 199, - 25, 205, 169, 4, 234, 1, 208, 99, 149, 249, 126, 131, 217, 88, 69, 115, 108, 161, 132, 20, 76, - 38, 58, 81, 5, 123, 233, 3, 3, 180, 52, 96, 220, 129, 200, 207, 238, 115, 147, 148, 155, 185, - 239, 254, 29, 75, 201, 110, 161, 18, 18, 90, 40, 33, 212, 15, 66, 31, 11, 14, 150, 175, 50, 45, - 201, 142, 213, 39, 20, 15, 110, 150, 158, 61, 9, 143, 117, 132, 238, 11, 215, 215, 200, 142, - 156, 183, 105, 221, 193, 190, 219, 9, 109, 236, 143, 122, 67, 160, 56, 42, 175, 109, 89, 56, - 55, 88, 213, 97, 98, 61, 168, 25, 167, 142, 59, 134, 59, 129, 117, 85, 95, 4, 21, 134, 149, - 105, 21, 178, 167, 115, 85, 65, 231, 124, 102, 232, 26, 14, 59, 206, 204, 11, 159, 179, 123, - 162, 246, 117, 253, 214, 25, 90, 42, 58, 238, 216, 127, 72, 115, 41, 180, 125, 79, 3, 251, 213, - 118, 96, 13, 62, 251, 58, 158, 237, 196, 156, 98, 62, 37, 245, 82, 174, 48, 191, 57, 237, 201, - 224, 56, 60, 245, 170, 161, 14, 28, 137, 153, 208, 249, 25, 43, 157, 192, 39, 232, 157, 212, 6, - 168, 13, 83, 55, 141, 118, 21, 26, 229, 243, 231, 14, 241, 207, 104, 64, 18, 13, 108, 30, 180, - 30, 149, 68, 235, 225, 20, 220, 35, 208, 10, 102, 161, 57, 80, 173, 72, 196, 136, 80, 87, 0, - 115, 114, 202, 16, 28, 76, 168, 15, 232, 157, 45, 220, 111, 52, 161, 82, 193, 17, 193, 192, - 252, 239, 141, 29, 122, 252, 78, 51, 68, 148, 150, 174, 243, 184, 212, 140, 7, 130, 137, 169, - 9, 19, 240, 80, 166, 91, 195, 171, 171, 142, 164, 200, 252, 146, 148, 252, 125, 13, 67, 92, 47, - 199, 246, 228, 103, 75, 155, 239, 190, 14, 178, 39, 64, 20, 180, 253, 220, 0, 154, 140, 191, - 253, 253, 253, 107, 236, 152, 229, 125, 41, 65, 216, 212, 169, 93, 12, 24, 63, 212, 239, 73, - 102, 97, 242, 62, 170, 223, 120, 219, 127, 254, 174, 100, 196, 46, 111, 49, 236, 218, 179, 222, - 236, 201, 110, 107, 38, 186, 247, 36, 121, 98, 229, 63, 28, 60, 12, 211, 252, 252, 52, 189, - 123, 81, 70, 162, 201, 204, 3, 33, 95, 169, 148, 183, 224, 126, 164, 27, 30, 27, 232, 201, 92, - 148, 40, 138, 248, 19, 2, 92, 255, 169, 18, 226, 110, 218, 110, 37, 185, 2, 237, 72, 180, 162, - 190, 174, 242, 90, 238, 170, 217, 136, 7, 123, 35, 56, 205, 68, 13, 72, 28, 134, 210, 88, 61, - 195, 95, 248, 9, 8, 213, 101, 19, 197, 253, 145, 8, 67, 98, 210, 63, 119, 51, 99, 188, 177, - 103, 240, 236, 157, 218, 220, 218, 175, 217, 47, 227, 221, 47, 162, 9, 82, 222, 178, 228, 97, - 62, 149, 191, 124, 198, 95, 59, 54, 205, 239, 87, 39, 225, 172, 83, 215, 45, 243, 114, 79, 7, - 244, 60, 155, 71, 73, 94, 133, 77, 230, 116, 132, 20, 114, 237, 132, 249, 243, 19, 231, 209, - 238, 51, 151, 1, 69, 78, 135, 65, 178, 207, 33, 9, 54, 28, 192, 127, 44, 209, 164, 236, 180, - 35, 144, 214, 67, 236, 171, 120, 250, 242, 236, 242, 167, 137, 60, 229, 131, 245, 23, 34, 114, - 93, 49, 129, 10, 149, 0, 22, 118, 103, 15, 218, 22, 224, 33, 74, 161, 235, 213, 27, 85, 198, - 253, 87, 151, 248, 252, 243, 215, 54, 6, 227, 208, 168, 59, 203, 144, 167, 31, 215, 234, 125, - 83, 147, 83, 175, 108, 122, 222, 76, 183, 7, 115, 71, 209, 65, 201, 69, 50, 88, 96, 120, 128, - 141, 43, 128, 225, 180, 120, 65, 20, 9, 137, 2, 201, 177, 251, 93, 52, 44, 67, 77, 36, 191, 63, - 95, 222, 71, 171, 172, 232, 102, 167, 4, 218, 191, 5, 18, 117, 123, 238, 176, 85, 124, 155, - 172, 187, 120, 209, 91, 43, 130, 226, 79, 103, 232, 101, 249, 96, 225, 88, 29, 57, 22, 20, 98, - 8, 201, 197, 153, 252, 163, 11, 188, 27, 112, 164, 43, 138, 96, 101, 146, 102, 152, 152, 64, - 211, 167, 139, 42, 66, 189, 188, 117, 86, 44, 198, 186, 128, 82, 58, 62, 88, 205, 68, 86, 127, - 65, 180, 37, 117, 222, 191, 149, 26, 138, 122, 91, 10, 40, 35, 228, 255, 1, 228, 174, 72, 110, - 34, 235, 105, 71, 18, 100, 115, 3, 114, 185, 148, 27, 133, 97, 165, 91, 1, 192, 102, 70, 76, - 111, 49, 252, 24, 23, 224, 163, 90, 136, 0, 9, 23, 65, 96, 137, 196, 163, 38, 76, 193, 1, 229, - 209, 154, 84, 229, 82, 228, 144, 221, 3, 31, 150, 226, 1, 252, 94, 153, 160, 40, 38, 186, 141, - 80, 28, 114, 19, 134, 84, 184, 236, 28, 172, 248, 61, 208, 91, 187, 136, 99, 184, 64, 179, 134, - 75, 186, 206, 95, 95, 227, 179, 252, 156, 72, 50, 121, 55, 70, 133, 162, 173, 118, 214, 174, - 131, 237, 130, 141, 239, 50, 252, 248, 141, 174, 183, 164, 176, 142, 124, 109, 56, 164, 164, - 25, 50, 175, 242, 54, 160, 31, 108, 17, 228, 31, 211, 203, 73, 252, 148, 234, 240, 184, 14, - 155, 101, 45, 94, 31, 203, 236, 176, 127, 5, 249, 177, 119, 24, 79, 244, 24, 182, 106, 6, 184, - 205, 246, 31, 71, 33, 233, 47, 223, 33, 106, 252, 76, 192, 146, 143, 108, 49, 67, 208, 77, 87, - 122, 165, 151, 99, 231, 253, 231, 57, 12, 83, 67, 102, 28, 169, 198, 153, 115, 79, 77, 187, - 141, 161, 244, 149, 211, 215, 9, 64, 33, 205, 175, 182, 129, 159, 41, 194, 117, 123, 140, 178, - 17, 146, 210, 182, 105, 220, 82, 198, 13, 240, 183, 92, 175, 34, 73, 28, 208, 69, 203, 8, 174, - 109, 127, 254, 254, 142, 176, 232, 43, 80, 56, 220, 222, 143, 66, 137, 143, 1, 191, 152, 92, - 122, 231, 204, 99, 221, 217, 123, 57, 149, 27, 65, 4, 42, 209, 33, 77, 211, 156, 139, 198, 4, - 17, 91, 41, 173, 0, 51, 67, 210, 24, 212, 127, 50, 167, 129, 12, 95, 62, 125, 211, 99, 185, 31, - 243, 77, 210, 108, 142, 16, 2, 237, 163, 239, 239, 213, 101, 127, 242, 228, 4, 247, 32, 189, - 20, 10, 182, 64, 152, 166, 83, 202, 121, 83, 175, 137, 37, 202, 247, 85, 15, 198, 148, 130, 43, - 184, 106, 118, 198, 211, 171, 103, 176, 34, 61, 21, 103, 225, 83, 225, 16, 252, 169, 238, 142, - 185, 138, 212, 67, 193, 233, 104, 169, 25, 191, 134, 37, 233, 202, 106, 163, 58, 107, 82, 243, - 52, 70, 240, 246, 225, 10, 130, 76, 210, 164, 40, 125, 162, 35, 197, 68, 74, 17, 51, 223, 231, - 232, 67, 117, 252, 239, 57, 213, 36, 92, 34, 4, 232, 142, 118, 115, 108, 59, 184, 223, 133, 67, - 194, 121, 195, 135, 219, 143, 224, 170, 120, 29, 116, 195, 124, 155, 252, 204, 125, 42, 246, - 28, 104, 190, 101, 139, 144, 10, 172, 38, 226, 97, 77, 187, 153, 168, 208, 234, 104, 147, 49, - 123, 237, 232, 139, 167, 199, 250, 52, 188, 27, 181, 44, 90, 76, 222, 166, 26, 45, 142, 56, - 142, 251, 102, 57, 121, 165, 192, 189, 112, 76, 31, 117, 33, 89, 143, 217, 200, 13, 173, 191, - 156, 206, 179, 11, 100, 52, 109, 48, 16, 34, 193, 164, 150, 40, 8, 32, 155, 27, 254, 134, 145, - 203, 234, 129, 154, 69, 223, 252, 173, 146, 78, 23, 143, 8, 69, 232, 250, 248, 56, 127, 161, - 10, 80, 237, 75, 56, 73, 34, 90, 33, 110, 88, 215, 251, 151, 79, 185, 94, 122, 71, 155, 135, - 98, 139, 50, 7, 20, 37, 221, 165, 66, 120, 86, 30, 212, 71, 136, 233, 236, 230, 42, 100, 163, - 233, 26, 229, 63, 153, 86, 86, 181, 20, 108, 232, 98, 230, 120, 39, 132, 36, 189, 116, 90, 21, - 193, 252, 183, 31, 68, 65, 183, 176, 137, 9, 130, 35, 83, 114, 207, 74, 189, 119, 189, 165, 53, - 141, 240, 230, 177, 29, 131, 118, 136, 40, 85, 149, 202, 4, 215, 232, 73, 90, 63, 73, 143, 251, - 23, 52, 106, 198, 206, 155, 187, 102, 98, 217, 225, 192, 147, 103, 186, 0, 112, 192, 212, 182, - 157, 234, 157, 114, 2, 202, 183, 104, 129, 162, 34, 103, 21, 32, 0, 21, 5, 190, 75, 21, 81, - 157, 69, 207, 53, 239, 243, 110, 125, 69, 200, 117, 34, 44, 180, 85, 74, 196, 217, 118, 223, - 151, 122, 22, 84, 19, 15, 227, 0, 59, 177, 129, 200, 78, 221, 117, 19, 93, 239, 46, 187, 161, - 200, 238, 6, 141, 76, 231, 83, 12, 49, 137, 31, 104, 240, 65, 174, 94, 205, 166, 173, 188, 168, - 102, 85, 129, 194, 121, 127, 28, 197, 225, 60, 21, 181, 89, 7, 26, 221, 234, 165, 219, 165, - 147, 240, 115, 164, 123, 128, 103, 77, 154, 137, 12, 243, 101, 124, 62, 147, 199, 213, 67, 143, - 220, 7, 52, 182, 119, 164, 194, 150, 100, 82, 138, 88, 17, 40, 120, 198, 41, 12, 114, 239, 115, - 173, 128, 178, 246, 9, 55, 48, 28, 168, 60, 85, 13, 85, 91, 202, 23, 160, 86, 207, 208, 108, - 161, 194, 30, 73, 120, 94, 20, 198, 161, 218, 152, 212, 49, 116, 65, 84, 179, 232, 153, 168, - 155, 45, 119, 154, 205, 178, 40, 182, 8, 56, 64, 21, 3, 208, 178, 15, 238, 11, 147, 206, 182, - 175, 185, 191, 106, 177, 70, 161, 185, 13, 12, 230, 250, 162, 35, 87, 27, 80, 235, 155, 250, - 252, 255, 168, 5, 88, 189, 106, 97, 124, 4, 34, 163, 145, 38, 180, 62, 203, 18, 53, 42, 74, - 127, 48, 85, 215, 62, 235, 128, 94, 104, 144, 151, 64, 118, 118, 45, 215, 139, 216, 27, 23, - 255, 21, 231, 71, 15, 161, 105, 143, 60, 205, 80, 224, 100, 11, 35, 78, 78, 87, 66, 51, 116, - 237, 253, 137, 227, 226, 255, 9, 168, 243, 224, 124, 244, 235, 93, 121, 82, 239, 179, 41, 17, - 221, 221, 49, 160, 28, 132, 91, 6, 185, 94, 209, 143, 118, 146, 73, 87, 163, 98, 121, 99, 217, - 253, 201, 248, 86, 167, 247, 48, 226, 159, 235, 32, 19, 127, 75, 223, 185, 213, 207, 181, 29, - 144, 36, 118, 67, 132, 74, 75, 149, 92, 148, 238, 229, 107, 231, 9, 198, 54, 244, 15, 96, 134, - 34, 60, 11, 153, 53, 91, 187, 0, 171, 44, 25, 179, 180, 207, 19, 69, 233, 35, 251, 75, 164, 1, - 60, 70, 145, 88, 218, 123, 158, 99, 144, 211, 245, 4, 24, 252, 132, 10, 149, 220, 80, 31, 165, - 137, 38, 126, 37, 52, 0, 115, 128, 0, 61, 32, 77, 211, 28, 227, 1, 182, 122, 212, 185, 127, - 179, 146, 130, 8, 255, 45, 232, 115, 122, 248, 92, 255, 253, 225, 113, 216, 18, 4, 182, 77, - 229, 77, 236, 83, 80, 154, 13, 150, 195, 227, 1, 206, 24, 250, 192, 183, 215, 240, 86, 209, 86, - 203, 51, 236, 194, 230, 162, 58, 64, 0, 220, 174, 195, 173, 34, 104, 209, 200, 243, 28, 5, 26, - 8, 178, 32, 236, 148, 188, 98, 164, 91, 132, 153, 27, 14, 255, 245, 229, 166, 173, 128, 129, 2, - 161, 83, 41, 60, 32, 118, 37, 34, 78, 214, 240, 131, 36, 24, 85, 86, 180, 232, 229, 91, 200, - 27, 90, 239, 44, 6, 27, 135, 220, 132, 64, 52, 0, 4, 16, 5, 48, 18, 246, 194, 148, 141, 65, 64, - 196, 90, 83, 151, 62, 27, 130, 121, 40, 104, 128, 18, 123, 28, 137, 86, 250, 253, 121, 52, 131, - 174, 84, 56, 143, 28, 115, 68, 215, 228, 96, 100, 160, 93, 78, 89, 114, 133, 241, 82, 6, 131, - 167, 93, 12, 48, 143, 194, 78, 85, 213, 184, 179, 178, 70, 1, 179, 47, 201, 224, 148, 252, 149, - 83, 5, 168, 146, 21, 212, 250, 218, 185, 233, 191, 241, 255, 37, 198, 65, 139, 245, 167, 162, - 24, 10, 74, 175, 35, 186, 140, 149, 21, 154, 1, 226, 8, 36, 120, 88, 52, 165, 70, 53, 59, 95, - 5, 174, 47, 115, 165, 113, 133, 203, 128, 108, 157, 255, 217, 50, 137, 151, 79, 136, 89, 2, 22, - 80, 208, 45, 228, 223, 176, 102, 157, 203, 54, 53, 70, 97, 202, 138, 217, 224, 250, 148, 142, - 7, 91, 185, 102, 63, 153, 46, 120, 122, 197, 207, 66, 242, 56, 82, 31, 191, 4, 125, 176, 14, - 55, 15, 166, 166, 95, 17, 11, 160, 67, 53, 9, 44, 180, 166, 35, 120, 105, 171, 117, 187, 47, - 17, 22, 82, 112, 49, 227, 96, 113, 133, 31, 8, 10, 12, 97, 38, 27, 176, 73, 95, 220, 105, 232, - 240, 88, 234, 192, 12, 57, 209, 128, 223, 120, 203, 30, 140, 208, 185, 87, 36, 95, 120, 20, - 164, 16, 109, 207, 198, 157, 189, 168, 141, 127, 24, 21, 125, 32, 230, 27, 64, 122, 7, 158, 14, - 201, 233, 17, 53, 39, 129, 63, 56, 45, 122, 24, 251, 194, 204, 205, 159, 234, 247, 131, 145, - 73, 103, 21, 35, 158, 61, 195, 60, 0, 236, 122, 228, 245, 74, 69, 13, 40, 37, 146, 110, 3, 156, - 54, 24, 241, 170, 10, 79, 79, 157, 29, 27, 227, 191, 84, 101, 61, 172, 76, 175, 220, 34, 90, - 82, 39, 29, 29, 92, 174, 74, 161, 75, 143, 198, 83, 14, 181, 228, 173, 73, 38, 5, 145, 215, 19, - 87, 91, 67, 252, 49, 124, 3, 77, 190, 135, 85, 42, 195, 150, 134, 135, 154, 130, 134, 216, 157, - 122, 255, 50, 95, 33, 101, 210, 206, 204, 170, 137, 34, 72, 157, 72, 34, 69, 231, 155, 93, 111, - 27, 102, 183, 90, 131, 167, 137, 204, 146, 185, 166, 41, 241, 144, 38, 28, 32, 238, 7, 219, 0, - 132, 59, 169, 252, 60, 142, 179, 91, 71, 178, 128, 123, 227, 232, 229, 232, 186, 87, 137, 237, - 40, 92, 146, 191, 207, 210, 225, 234, 56, 118, 119, 213, 131, 185, 197, 218, 222, 242, 248, 34, - 62, 75, 135, 143, 150, 155, 212, 230, 27, 46, 143, 193, 210, 51, 127, 165, 202, 219, 254, 7, - 19, 69, 80, 155, 160, 201, 202, 235, 71, 130, 192, 200, 240, 247, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8, 12, 19, 28, 33, 39, 48, 54, 0, -]; From 716d695ad0106e2e1b112316c37344c1354d0f2d Mon Sep 17 00:00:00 2001 From: Vishal Mhatre <38512878+mhatrevi@users.noreply.github.com> Date: Mon, 9 Dec 2024 09:08:25 -0800 Subject: [PATCH 42/51] [feat] Update DCCM size from 128 KB to 256 KB (#1838) --- drivers/src/memory_layout.rs | 4 ++-- hw-model/tests/model_tests.rs | 2 +- rom/dev/src/rom.ld | 8 ++++---- rom/dev/tools/test-fmc/src/fmc.ld | 8 ++++---- rom/dev/tools/test-rt/src/rt.ld | 8 ++++---- sw-emulator/lib/cpu/src/cpu.rs | 2 +- sw-emulator/lib/periph/src/root_bus.rs | 2 +- 7 files changed, 17 insertions(+), 17 deletions(-) diff --git a/drivers/src/memory_layout.rs b/drivers/src/memory_layout.rs index 28c2cb0e6c..d362ca5501 100644 --- a/drivers/src/memory_layout.rs +++ b/drivers/src/memory_layout.rs @@ -63,7 +63,7 @@ pub const ROM_RELAXATION_PADDING: u32 = 4 * 1024; pub const ROM_SIZE: u32 = 96 * 1024; pub const MBOX_SIZE: u32 = 128 * 1024; pub const ICCM_SIZE: u32 = 128 * 1024; -pub const DCCM_SIZE: u32 = 128 * 1024; +pub const DCCM_SIZE: u32 = 256 * 1024; pub const ROM_DATA_SIZE: u32 = 996; pub const MAN1_SIZE: u32 = 8 * 1024; pub const MAN2_SIZE: u32 = 8 * 1024; @@ -79,7 +79,7 @@ pub const DPE_SIZE: u32 = 5 * 1024; pub const PCR_RESET_COUNTER_SIZE: u32 = 1024; pub const AUTH_MAN_IMAGE_METADATA_MAX_SIZE: u32 = 7 * 1024; pub const IDEVID_CSR_SIZE: u32 = 1024; -pub const DATA_SIZE: u32 = 20 * 1024; +pub const DATA_SIZE: u32 = 148 * 1024; pub const STACK_SIZE: u32 = 64 * 1024; pub const ROM_STACK_SIZE: u32 = 14 * 1024; pub const ESTACK_SIZE: u32 = 1024; diff --git a/hw-model/tests/model_tests.rs b/hw-model/tests/model_tests.rs index 25c8ac5cb9..158e793753 100644 --- a/hw-model/tests/model_tests.rs +++ b/hw-model/tests/model_tests.rs @@ -210,7 +210,7 @@ fn test_uninitialized_dccm_read() { ); const DCCM_ADDR: u32 = 0x5000_0000; - const DCCM_SIZE: u32 = 128 * 1024; + const DCCM_SIZE: u32 = 256 * 1024; model.soc_ifc().cptra_rsvd_reg().at(0).write(|_| DCCM_ADDR); model.soc_ifc().cptra_rsvd_reg().at(1).write(|_| DCCM_SIZE); diff --git a/rom/dev/src/rom.ld b/rom/dev/src/rom.ld index bc3e6908f6..1e7fc8d241 100644 --- a/rom/dev/src/rom.ld +++ b/rom/dev/src/rom.ld @@ -20,9 +20,9 @@ ROM_ORG = 0x00000000; ICCM_ORG = 0x40000000; DCCM_ORG = 0x50000000; DATA_ORG = 0x50000000; -STACK_ORG = 0x5001C000; -ESTACK_ORG = 0x5001F800; -NSTACK_ORG = 0x5001FC00; +STACK_ORG = 0x5003C000; +ESTACK_ORG = 0x5003F800; +NSTACK_ORG = 0x5003FC00; CFI_STATE_ORG = 0x500003E4; @@ -34,7 +34,7 @@ CFI_STATE_ORG = 0x500003E4; ROM_RELAXATION_PADDING = 8k; ROM_SIZE = 96K; ICCM_SIZE = 128K; -DCCM_SIZE = 128K; +DCCM_SIZE = 256K; DATA_SIZE = 996; STACK_SIZE = 14K; ESTACK_SIZE = 1K; diff --git a/rom/dev/tools/test-fmc/src/fmc.ld b/rom/dev/tools/test-fmc/src/fmc.ld index df23e4b606..d583576037 100644 --- a/rom/dev/tools/test-fmc/src/fmc.ld +++ b/rom/dev/tools/test-fmc/src/fmc.ld @@ -20,12 +20,12 @@ ENTRY(_start) ICCM_ORG = 0x40000000; DCCM_ORG = 0x50000000; DATA_ORG = 0x50004C00; -STACK_ORG = 0x5001C000; -ESTACK_ORG = 0x5001F800; -NSTACK_ORG = 0x5001FC00; +STACK_ORG = 0x5003C000; +ESTACK_ORG = 0x5003F800; +NSTACK_ORG = 0x5003FC00; ICCM_SIZE = 16K; -DCCM_SIZE = 128K; +DCCM_SIZE = 256K; DATA_SIZE = 93K; STACK_SIZE = 14K; ESTACK_SIZE = 1K; diff --git a/rom/dev/tools/test-rt/src/rt.ld b/rom/dev/tools/test-rt/src/rt.ld index edfd86cc0d..25d24673d3 100644 --- a/rom/dev/tools/test-rt/src/rt.ld +++ b/rom/dev/tools/test-rt/src/rt.ld @@ -20,12 +20,12 @@ ENTRY(_start) ICCM_ORG = 0x40004000; /* Range [0x40000000 - 0x40003FFF] is reserved for FMC */ DCCM_ORG = 0x50000000; DATA_ORG = 0x50004C00; -STACK_ORG = 0x5001C000; -ESTACK_ORG = 0x5001F800; -NSTACK_ORG = 0x5001FC00; +STACK_ORG = 0x5003C000; +ESTACK_ORG = 0x5003F800; +NSTACK_ORG = 0x5003FC00; ICCM_SIZE = 112K; -DCCM_SIZE = 128K; +DCCM_SIZE = 256K; DATA_SIZE = 93K; STACK_SIZE = 14K; ESTACK_SIZE = 1K; diff --git a/sw-emulator/lib/cpu/src/cpu.rs b/sw-emulator/lib/cpu/src/cpu.rs index 942ca383ea..78c1680f99 100644 --- a/sw-emulator/lib/cpu/src/cpu.rs +++ b/sw-emulator/lib/cpu/src/cpu.rs @@ -576,7 +576,7 @@ impl Cpu { const REDIRECT_ENTRY_SIZE: u32 = 4; const MAX_IRQ: u32 = 32; const DCCM_ORG: u32 = 0x5000_0000; - const DCCM_SIZE: u32 = 128 * 1024; + const DCCM_SIZE: u32 = 256 * 1024; let vec_table = self.ext_int_vec; if vec_table < DCCM_ORG || vec_table + MAX_IRQ * REDIRECT_ENTRY_SIZE > DCCM_ORG + DCCM_SIZE diff --git a/sw-emulator/lib/periph/src/root_bus.rs b/sw-emulator/lib/periph/src/root_bus.rs index 879ee666d2..1864c0d714 100644 --- a/sw-emulator/lib/periph/src/root_bus.rs +++ b/sw-emulator/lib/periph/src/root_bus.rs @@ -314,7 +314,7 @@ pub struct CaliptraRootBus { impl CaliptraRootBus { pub const ROM_SIZE: usize = 96 * 1024; pub const ICCM_SIZE: usize = 128 * 1024; - pub const DCCM_SIZE: usize = 128 * 1024; + pub const DCCM_SIZE: usize = 256 * 1024; pub fn new(clock: &Clock, mut args: CaliptraRootBusArgs) -> Self { let mut key_vault = KeyVault::new(); From 814c76be0f659cc414e7f1ea45bcc91775d751c7 Mon Sep 17 00:00:00 2001 From: Vishal Mhatre <38512878+mhatrevi@users.noreply.github.com> Date: Fri, 13 Dec 2024 16:39:00 -0800 Subject: [PATCH 43/51] [feat] Firmware image generation and verification with MLDSA keys. (#1830) This change updates the image generator to generate an image with MLDSA public keys and signatures. Additionally, this change updates the image verifier for verifying the image signatures with the MLDSA public keys. --- .gitignore | 2 + Cargo.lock | 2 + builder/src/lib.rs | 8 +- common/src/lib.rs | 2 +- common/src/verifier.rs | 64 +- drivers/src/data_vault.rs | 10 +- drivers/src/fuse_log.rs | 8 +- drivers/src/memory_layout.rs | 6 +- drivers/src/mldsa87.rs | 3 +- error/src/lib.rs | 56 +- fmc/Makefile | 2 +- image/app/src/create/config.rs | 8 + image/app/src/create/mod.rs | 142 +- image/app/src/main.rs | 4 +- image/crypto/src/openssl.rs | 26 +- image/fake-keys/src/lib.rs | 1234 ++++++++++++++++- image/gen/Cargo.toml | 2 + image/gen/src/generator.rs | 244 +++- image/gen/src/lib.rs | 25 +- image/types/src/lib.rs | 218 ++- image/verify/fuzz/src/fuzz_target_common.rs | 32 +- image/verify/src/lib.rs | 44 +- image/verify/src/verifier.rs | 645 ++++++--- lms-types/src/lib.rs | 41 + rom/dev/Makefile | 4 +- rom/dev/README.md | 2 - rom/dev/doc/test-coverage/test-coverage.md | 2 +- rom/dev/src/crypto.rs | 2 +- rom/dev/src/flow/cold_reset/fmc_alias.rs | 2 +- rom/dev/src/flow/cold_reset/fw_processor.rs | 22 +- rom/dev/src/flow/fake.rs | 51 +- rom/dev/src/flow/update_reset.rs | 2 + rom/dev/src/lock.rs | 2 +- rom/dev/src/pcr.rs | 2 +- rom/dev/src/rom_env.rs | 4 +- .../test_fmcalias_derivation.rs | 18 +- .../test_image_validation.rs | 466 ++++++- .../test_update_reset.rs | 8 +- .../rom_integration_tests/test_warm_reset.rs | 6 +- rom/dev/tools/keys.toml | 9 + rom/dev/tools/test-fmc/src/main.rs | 4 +- runtime/src/authorize_and_stash.rs | 2 +- runtime/src/drivers.rs | 35 +- runtime/src/fips.rs | 1 + runtime/src/set_auth_manifest.rs | 20 +- .../test_pauser_privilege_levels.rs | 28 +- .../test_warm_reset.rs | 12 +- sw-emulator/lib/periph/src/ml_dsa87.rs | 11 +- test/src/lib.rs | 7 +- .../fake_collateral_boot_test.rs | 4 +- .../caliptra_integration_tests/jtag_test.rs | 4 +- .../caliptra_integration_tests/smoke_test.rs | 16 +- .../caliptra_integration_tests/warm_reset.rs | 12 +- test/tests/fips_test_suite/fw_load.rs | 120 +- 54 files changed, 3024 insertions(+), 682 deletions(-) diff --git a/.gitignore b/.gitignore index 24087f3c36..bc2ebd52b1 100644 --- a/.gitignore +++ b/.gitignore @@ -28,3 +28,5 @@ hw/fpga/vivado*.log # libcaliptra build artifacts libcaliptra/libcaliptra.a + +hw-latest/verilated/out/* diff --git a/Cargo.lock b/Cargo.lock index de5a4aade4..589bc2d11e 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -654,7 +654,9 @@ dependencies = [ "bitflags 2.4.0", "caliptra-image-types", "caliptra-lms-types", + "fips204", "memoffset 0.8.0", + "rand", "zerocopy", ] diff --git a/builder/src/lib.rs b/builder/src/lib.rs index 7ffb0c5ff1..0c7bd7df70 100644 --- a/builder/src/lib.rs +++ b/builder/src/lib.rs @@ -20,7 +20,7 @@ use caliptra_image_elf::ElfExecutable; use caliptra_image_gen::{ ImageGenerator, ImageGeneratorConfig, ImageGeneratorOwnerConfig, ImageGeneratorVendorConfig, }; -use caliptra_image_types::{FwImageType, ImageBundle, ImageRevision, RomInfo}; +use caliptra_image_types::{FwVerificationPqcKeyType, ImageBundle, ImageRevision, RomInfo}; use elf::endian::LittleEndian; use nix::fcntl::FlockArg; use zerocopy::AsBytes; @@ -444,7 +444,7 @@ pub struct ImageOptions { pub app_svn: u32, pub vendor_config: ImageGeneratorVendorConfig, pub owner_config: Option, - pub fw_image_type: FwImageType, + pub pqc_key_type: FwVerificationPqcKeyType, } impl Default for ImageOptions { fn default() -> Self { @@ -455,7 +455,7 @@ impl Default for ImageOptions { app_svn: Default::default(), vendor_config: caliptra_image_fake_keys::VENDOR_CONFIG_KEY_0, owner_config: Some(caliptra_image_fake_keys::OWNER_CONFIG), - fw_image_type: FwImageType::EccLms, + pqc_key_type: FwVerificationPqcKeyType::LMS, } } } @@ -478,7 +478,7 @@ pub fn build_and_sign_image( runtime: ElfExecutable::new(&app_elf, opts.app_version, opts.app_svn, image_revision()?)?, vendor_config: opts.vendor_config, owner_config: opts.owner_config, - fw_image_type: opts.fw_image_type, + pqc_key_type: opts.pqc_key_type, })?; Ok(image) } diff --git a/common/src/lib.rs b/common/src/lib.rs index ba4e884d24..71c515490f 100644 --- a/common/src/lib.rs +++ b/common/src/lib.rs @@ -40,7 +40,7 @@ pub use pcr::{PcrLogEntry, PcrLogEntryId, RT_FW_CURRENT_PCR, RT_FW_JOURNEY_PCR}; pub const FMC_ORG: u32 = 0x40000000; pub const FMC_SIZE: u32 = 20 * 1024; pub const RUNTIME_ORG: u32 = FMC_ORG + FMC_SIZE; -pub const RUNTIME_SIZE: u32 = 97 * 1024; +pub const RUNTIME_SIZE: u32 = 98 * 1024; pub use memory_layout::{DATA_ORG, FHT_ORG, FHT_SIZE, MAN1_ORG}; pub use wdt::{restart_wdt, start_wdt, stop_wdt, WdtTimeout}; diff --git a/common/src/verifier.rs b/common/src/verifier.rs index 62d8a47205..17e99ecae6 100644 --- a/common/src/verifier.rs +++ b/common/src/verifier.rs @@ -16,6 +16,7 @@ use caliptra_drivers::*; use caliptra_image_types::*; use caliptra_image_verify::ImageVerificationEnv; use core::ops::Range; +use zerocopy::{AsBytes, FromBytes}; use caliptra_drivers::memory_layout::ICCM_RANGE; @@ -25,14 +26,15 @@ pub struct FirmwareImageVerificationEnv<'a, 'b> { pub sha2_512_384: &'a mut Sha2_512_384, pub soc_ifc: &'a mut SocIfc, pub ecc384: &'a mut Ecc384, + pub mldsa87: &'a mut Mldsa87, pub data_vault: &'a mut DataVault, pub pcr_bank: &'a mut PcrBank, pub image: &'b [u8], } impl<'a, 'b> ImageVerificationEnv for &mut FirmwareImageVerificationEnv<'a, 'b> { - /// Calculate Digest using SHA-384 Accelerator - fn sha384_digest(&mut self, offset: u32, len: u32) -> CaliptraResult { + /// Calculate 384 digest using SHA2 Engine + fn sha384_digest(&mut self, offset: u32, len: u32) -> CaliptraResult { let err = CaliptraError::IMAGE_VERIFIER_ERR_DIGEST_OUT_OF_BOUNDS; let data = self .image @@ -43,10 +45,22 @@ impl<'a, 'b> ImageVerificationEnv for &mut FirmwareImageVerificationEnv<'a, 'b> Ok(self.sha2_512_384.sha384_digest(data)?.0) } + /// Calculate 512 digest using SHA2 Engine + fn sha512_digest(&mut self, offset: u32, len: u32) -> CaliptraResult { + let err = CaliptraError::IMAGE_VERIFIER_ERR_DIGEST_OUT_OF_BOUNDS; + let data = self + .image + .get(offset as usize..) + .ok_or(err)? + .get(..len as usize) + .ok_or(err)?; + Ok(self.sha2_512_384.sha512_digest(data)?.0) + } + /// ECC-384 Verification routine fn ecc384_verify( &mut self, - digest: &ImageDigest, + digest: &ImageDigest384, pub_key: &ImageEccPubKey, sig: &ImageEccSignature, ) -> CaliptraResult> { @@ -67,7 +81,7 @@ impl<'a, 'b> ImageVerificationEnv for &mut FirmwareImageVerificationEnv<'a, 'b> fn lms_verify( &mut self, - digest: &ImageDigest, + digest: &ImageDigest384, pub_key: &ImageLmsPublicKey, sig: &ImageLmsSignature, ) -> CaliptraResult> { @@ -78,8 +92,38 @@ impl<'a, 'b> ImageVerificationEnv for &mut FirmwareImageVerificationEnv<'a, 'b> Lms::default().verify_lms_signature_cfi(self.sha256, &message, pub_key, sig) } + fn mldsa87_verify( + &mut self, + digest: &ImageDigest512, + pub_key: &ImageMldsaPubKey, + sig: &ImageMldsaSignature, + ) -> CaliptraResult { + // Public Key is received in hw format from the image. No conversion needed. + let pub_key_bytes: [u8; MLDSA87_PUB_KEY_BYTE_SIZE] = pub_key + .0 + .as_bytes() + .try_into() + .map_err(|_| CaliptraError::IMAGE_VERIFIER_ERR_MLDSA_TYPE_CONVERSION_FAILED)?; + let pub_key = Mldsa87PubKey::read_from(pub_key_bytes.as_bytes()) + .ok_or(CaliptraError::IMAGE_VERIFIER_ERR_MLDSA_TYPE_CONVERSION_FAILED)?; + + // Signature is received in hw format from the image. No conversion needed. + let sig_bytes: [u8; MLDSA87_SIGNATURE_BYTE_SIZE] = sig + .0 + .as_bytes() + .try_into() + .map_err(|_| CaliptraError::IMAGE_VERIFIER_ERR_MLDSA_TYPE_CONVERSION_FAILED)?; + let sig = Mldsa87Signature::read_from(sig_bytes.as_bytes()) + .ok_or(CaliptraError::IMAGE_VERIFIER_ERR_MLDSA_TYPE_CONVERSION_FAILED)?; + + // digest is received in hw format. No conversion needed. + let msg = digest.into(); + + self.mldsa87.verify(&pub_key, &msg, &sig) + } + /// Retrieve Vendor Public Key Info Digest - fn vendor_pub_key_info_digest_fuses(&self) -> ImageDigest { + fn vendor_pub_key_info_digest_fuses(&self) -> ImageDigest384 { self.soc_ifc.fuse_bank().vendor_pub_key_info_hash().into() } @@ -94,7 +138,7 @@ impl<'a, 'b> ImageVerificationEnv for &mut FirmwareImageVerificationEnv<'a, 'b> } /// Retrieve Owner Public Key Digest from fuses - fn owner_pub_key_digest_fuses(&self) -> ImageDigest { + fn owner_pub_key_digest_fuses(&self) -> ImageDigest384 { self.soc_ifc.fuse_bank().owner_pub_key_hash().into() } @@ -114,17 +158,17 @@ impl<'a, 'b> ImageVerificationEnv for &mut FirmwareImageVerificationEnv<'a, 'b> } /// Get the vendor LMS key index saved in data vault on cold boot - fn vendor_lms_pub_key_idx_dv(&self) -> u32 { - self.data_vault.lms_vendor_pk_index() + fn vendor_pqc_pub_key_idx_dv(&self) -> u32 { + self.data_vault.pqc_vendor_pk_index() } /// Get the owner public key digest saved in the dv on cold boot - fn owner_pub_key_digest_dv(&self) -> ImageDigest { + fn owner_pub_key_digest_dv(&self) -> ImageDigest384 { self.data_vault.owner_pk_hash().into() } // Get the fmc digest from the data vault on cold boot - fn get_fmc_digest_dv(&self) -> ImageDigest { + fn get_fmc_digest_dv(&self) -> ImageDigest384 { self.data_vault.fmc_tci().into() } diff --git a/drivers/src/data_vault.rs b/drivers/src/data_vault.rs index 53fde23469..09827120fb 100644 --- a/drivers/src/data_vault.rs +++ b/drivers/src/data_vault.rs @@ -73,7 +73,7 @@ pub enum ColdResetEntry4 { RomColdBootStatus = 1, FmcEntryPoint = 2, EccVendorPubKeyIndex = 3, - LmsVendorPubKeyIndex = 4, + PqcVendorPubKeyIndex = 4, } impl TryFrom for ColdResetEntry4 { @@ -83,7 +83,7 @@ impl TryFrom for ColdResetEntry4 { 0 => Ok(Self::FmcSvn), 2 => Ok(Self::FmcEntryPoint), 3 => Ok(Self::EccVendorPubKeyIndex), - 4 => Ok(Self::LmsVendorPubKeyIndex), + 4 => Ok(Self::PqcVendorPubKeyIndex), _ => Err(()), } } @@ -325,13 +325,13 @@ impl DataVault { self.read_cold_reset_entry4(ColdResetEntry4::EccVendorPubKeyIndex) } - /// Get the Lms vendor public key index used for image verification. + /// Get the PQC (LMS or MLDSA) vendor public key index used for image verification. /// /// # Returns /// /// * `u32` - Vendor public key index - pub fn lms_vendor_pk_index(&self) -> u32 { - self.read_cold_reset_entry4(ColdResetEntry4::LmsVendorPubKeyIndex) + pub fn pqc_vendor_pk_index(&self) -> u32 { + self.read_cold_reset_entry4(ColdResetEntry4::PqcVendorPubKeyIndex) } /// Get the rom cold boot status. diff --git a/drivers/src/fuse_log.rs b/drivers/src/fuse_log.rs index 3f73a1de2c..4b5f17b4ce 100644 --- a/drivers/src/fuse_log.rs +++ b/drivers/src/fuse_log.rs @@ -28,8 +28,8 @@ pub enum FuseLogEntryId { ManifestRtSvn = 6, // 4 bytes ManifestReserved1 = 7, // 4 bytes FuseRtSvn = 8, // 4 bytes - VendorLmsPubKeyIndex = 9, // 4 bytes (From Manifest) - VendorLmsPubKeyRevocation = 10, // 4 bytes (From Fuse) + VendorPqcPubKeyIndex = 9, // 4 bytes (From Manifest) + VendorPqcPubKeyRevocation = 10, // 4 bytes (From Fuse) } impl From for FuseLogEntryId { @@ -44,8 +44,8 @@ impl From for FuseLogEntryId { 6 => FuseLogEntryId::ManifestRtSvn, 7 => FuseLogEntryId::ManifestReserved1, 8 => FuseLogEntryId::FuseRtSvn, - 9 => FuseLogEntryId::VendorLmsPubKeyIndex, - 10 => FuseLogEntryId::VendorLmsPubKeyRevocation, + 9 => FuseLogEntryId::VendorPqcPubKeyIndex, + 10 => FuseLogEntryId::VendorPqcPubKeyRevocation, _ => FuseLogEntryId::Invalid, } } diff --git a/drivers/src/memory_layout.rs b/drivers/src/memory_layout.rs index d362ca5501..34f810c5af 100644 --- a/drivers/src/memory_layout.rs +++ b/drivers/src/memory_layout.rs @@ -65,8 +65,8 @@ pub const MBOX_SIZE: u32 = 128 * 1024; pub const ICCM_SIZE: u32 = 128 * 1024; pub const DCCM_SIZE: u32 = 256 * 1024; pub const ROM_DATA_SIZE: u32 = 996; -pub const MAN1_SIZE: u32 = 8 * 1024; -pub const MAN2_SIZE: u32 = 8 * 1024; +pub const MAN1_SIZE: u32 = 17 * 1024; +pub const MAN2_SIZE: u32 = 17 * 1024; pub const FHT_SIZE: u32 = 2 * 1024; pub const IDEVID_MLDSA_PUB_KEY_MAX_SIZE: u32 = 3 * 1024; pub const LDEVID_TBS_SIZE: u32 = 1024; @@ -79,7 +79,7 @@ pub const DPE_SIZE: u32 = 5 * 1024; pub const PCR_RESET_COUNTER_SIZE: u32 = 1024; pub const AUTH_MAN_IMAGE_METADATA_MAX_SIZE: u32 = 7 * 1024; pub const IDEVID_CSR_SIZE: u32 = 1024; -pub const DATA_SIZE: u32 = 148 * 1024; +pub const DATA_SIZE: u32 = 130 * 1024; pub const STACK_SIZE: u32 = 64 * 1024; pub const ROM_STACK_SIZE: u32 = 14 * 1024; pub const ESTACK_SIZE: u32 = 1024; diff --git a/drivers/src/mldsa87.rs b/drivers/src/mldsa87.rs index 8f3a684c5c..7309073fc2 100644 --- a/drivers/src/mldsa87.rs +++ b/drivers/src/mldsa87.rs @@ -20,11 +20,12 @@ use crate::{ }; #[cfg(not(feature = "no-cfi"))] use caliptra_cfi_derive::cfi_impl_fn; +use caliptra_cfi_derive::Launder; use caliptra_registers::mldsa::{MldsaReg, RegisterBlock}; #[must_use] #[repr(u32)] -#[derive(Debug, Clone, Copy, PartialEq, Eq)] +#[derive(Debug, Clone, Copy, PartialEq, Eq, Launder)] pub enum Mldsa87Result { Success = 0xAAAAAAAA, SigVerifyFailed = 0x55555555, diff --git a/error/src/lib.rs b/error/src/lib.rs index c580108c2d..ff0e8804ea 100644 --- a/error/src/lib.rs +++ b/error/src/lib.rs @@ -200,7 +200,7 @@ impl CaliptraError { CaliptraError::new_const(0x000b0019); pub const IMAGE_VERIFIER_ERR_OWNER_ECC_SIGNATURE_INVALID_ARG: CaliptraError = CaliptraError::new_const(0x000b001a); - pub const IMAGE_VERIFIER_ERR_VENDOR_PUB_KEY_DIGEST_INVALID_ARG: CaliptraError = + pub const IMAGE_VERIFIER_ERR_VENDOR_ECC_PUB_KEY_INVALID_ARG: CaliptraError = CaliptraError::new_const(0x000b001b); pub const IMAGE_VERIFIER_ERR_VENDOR_ECC_SIGNATURE_INVALID_ARG: CaliptraError = CaliptraError::new_const(0x000b001c); @@ -236,7 +236,7 @@ impl CaliptraError { CaliptraError::new_const(0x000b002e); pub const IMAGE_VERIFIER_ERR_IMAGE_LEN_MORE_THAN_BUNDLE_SIZE: CaliptraError = CaliptraError::new_const(0x000b002f); - pub const IMAGE_VERIFIER_ERR_VENDOR_LMS_PUB_KEY_INDEX_MISMATCH: CaliptraError = + pub const IMAGE_VERIFIER_ERR_VENDOR_PQC_PUB_KEY_INDEX_MISMATCH: CaliptraError = CaliptraError::new_const(0x000b0030); pub const IMAGE_VERIFIER_ERR_VENDOR_LMS_VERIFY_FAILURE: CaliptraError = CaliptraError::new_const(0x000b0031); @@ -256,7 +256,7 @@ impl CaliptraError { CaliptraError::new_const(0x000b003b); pub const IMAGE_VERIFIER_ERR_RUNTIME_SIZE_ZERO: CaliptraError = CaliptraError::new_const(0x000b003c); - pub const IMAGE_VERIFIER_ERR_UPDATE_RESET_VENDOR_LMS_PUB_KEY_IDX_MISMATCH: CaliptraError = + pub const IMAGE_VERIFIER_ERR_UPDATE_RESET_VENDOR_PQC_PUB_KEY_IDX_MISMATCH: CaliptraError = CaliptraError::new_const(0x000b003d); pub const IMAGE_VERIFIER_ERR_FMC_LOAD_ADDRESS_IMAGE_SIZE_ARITHMETIC_OVERFLOW: CaliptraError = CaliptraError::new_const(0x000b003e); @@ -266,28 +266,52 @@ impl CaliptraError { CaliptraError::new_const(0x000b0040); pub const IMAGE_VERIFIER_ERR_DIGEST_OUT_OF_BOUNDS: CaliptraError = CaliptraError::new_const(0x000b0041); - pub const IMAGE_VERIFIER_ERR_ECC_KEY_DESCRIPTOR_MARKER_MISMATCH: CaliptraError = - CaliptraError::new_const(0x000b0042); pub const IMAGE_VERIFIER_ERR_ECC_KEY_DESCRIPTOR_VERSION_MISMATCH: CaliptraError = + CaliptraError::new_const(0x000b0042); + pub const IMAGE_VERIFIER_ERR_ECC_KEY_DESCRIPTOR_HASH_COUNT_GT_MAX: CaliptraError = CaliptraError::new_const(0x000b0043); - pub const IMAGE_VERIFIER_ERR_ECC_KEY_DESCRIPTOR_INTENT_MISMATCH: CaliptraError = + pub const IMAGE_VERIFIER_ERR_PQC_KEY_DESCRIPTOR_VERSION_MISMATCH: CaliptraError = CaliptraError::new_const(0x000b0044); - pub const IMAGE_VERIFIER_ERR_ECC_KEY_DESCRIPTOR_HASH_COUNT_GT_MAX: CaliptraError = + pub const IMAGE_VERIFIER_ERR_PQC_KEY_DESCRIPTOR_TYPE_MISMATCH: CaliptraError = + CaliptraError::new_const(0x000b0045); + pub const IMAGE_VERIFIER_ERR_PQC_KEY_DESCRIPTOR_HASH_COUNT_GT_MAX: CaliptraError = CaliptraError::new_const(0x000b0046); - pub const IMAGE_VERIFIER_ERR_LMS_KEY_DESCRIPTOR_MARKER_MISMATCH: CaliptraError = + pub const IMAGE_VERIFIER_ERR_ECC_KEY_DESCRIPTOR_INVALID_HASH_COUNT: CaliptraError = CaliptraError::new_const(0x000b0047); - pub const IMAGE_VERIFIER_ERR_LMS_KEY_DESCRIPTOR_VERSION_MISMATCH: CaliptraError = + pub const IMAGE_VERIFIER_ERR_PQC_KEY_DESCRIPTOR_INVALID_HASH_COUNT: CaliptraError = CaliptraError::new_const(0x000b0048); - pub const IMAGE_VERIFIER_ERR_LMS_KEY_DESCRIPTOR_INTENT_MISMATCH: CaliptraError = + pub const IMAGE_VERIFIER_ERR_FW_IMAGE_VERIFICATION_KEY_TYPE_INVALID: CaliptraError = CaliptraError::new_const(0x000b0049); - pub const IMAGE_VERIFIER_ERR_LMS_KEY_DESCRIPTOR_TYPE_MISMATCH: CaliptraError = + pub const IMAGE_VERIFIER_ERR_LMS_VENDOR_PUB_KEY_INVALID: CaliptraError = CaliptraError::new_const(0x000b004a); - pub const IMAGE_VERIFIER_ERR_LMS_KEY_DESCRIPTOR_HASH_COUNT_GT_MAX: CaliptraError = + pub const IMAGE_VERIFIER_ERR_LMS_VENDOR_SIG_INVALID: CaliptraError = CaliptraError::new_const(0x000b004b); - pub const IMAGE_VERIFIER_ERR_ECC_KEY_DESCRIPTOR_INVALID_HASH_COUNT: CaliptraError = + pub const IMAGE_VERIFIER_ERR_LMS_OWNER_PUB_KEY_INVALID: CaliptraError = CaliptraError::new_const(0x000b004c); - pub const IMAGE_VERIFIER_ERR_LMS_KEY_DESCRIPTOR_INVALID_HASH_COUNT: CaliptraError = + pub const IMAGE_VERIFIER_ERR_LMS_OWNER_SIG_INVALID: CaliptraError = CaliptraError::new_const(0x000b004d); + pub const IMAGE_VERIFIER_ERR_MLDSA_VENDOR_PUB_KEY_READ_FAILED: CaliptraError = + CaliptraError::new_const(0x000b004e); + pub const IMAGE_VERIFIER_ERR_MLDSA_VENDOR_SIG_READ_FAILED: CaliptraError = + CaliptraError::new_const(0x000b004f); + pub const IMAGE_VERIFIER_ERR_MLDSA_OWNER_PUB_KEY_READ_FAILED: CaliptraError = + CaliptraError::new_const(0x000b0050); + pub const IMAGE_VERIFIER_ERR_MLDSA_OWNER_SIG_READ_FAILED: CaliptraError = + CaliptraError::new_const(0x000b0051); + pub const IMAGE_VERIFIER_ERR_VENDOR_MLDSA_DIGEST_MISSING: CaliptraError = + CaliptraError::new_const(0x000b0052); + pub const IMAGE_VERIFIER_ERR_OWNER_MLDSA_DIGEST_MISSING: CaliptraError = + CaliptraError::new_const(0x000b0053); + pub const IMAGE_VERIFIER_ERR_VENDOR_MLDSA_VERIFY_FAILURE: CaliptraError = + CaliptraError::new_const(0x000b0054); + pub const IMAGE_VERIFIER_ERR_VENDOR_MLDSA_SIGNATURE_INVALID: CaliptraError = + CaliptraError::new_const(0x000b0055); + pub const IMAGE_VERIFIER_ERR_OWNER_MLDSA_VERIFY_FAILURE: CaliptraError = + CaliptraError::new_const(0x000b0056); + pub const IMAGE_VERIFIER_ERR_OWNER_MLDSA_SIGNATURE_INVALID: CaliptraError = + CaliptraError::new_const(0x000b0057); + pub const IMAGE_VERIFIER_ERR_MLDSA_TYPE_CONVERSION_FAILED: CaliptraError = + CaliptraError::new_const(0x000b0058); /// Driver Error: LMS pub const DRIVER_LMS_INVALID_LMS_ALGO_TYPE: CaliptraError = @@ -480,6 +504,10 @@ impl CaliptraError { CaliptraError::new_const(0x000E0051); pub const RUNTIME_GET_IDEV_ID_UNSUPPORTED_ROM: CaliptraError = CaliptraError::new_const(0x000E0052); + pub const RUNTIME_AUTH_MANIFEST_LMS_VENDOR_PUB_KEY_INVALID: CaliptraError = + CaliptraError::new_const(0x000E0053); + pub const RUNTIME_AUTH_MANIFEST_LMS_OWNER_PUB_KEY_INVALID: CaliptraError = + CaliptraError::new_const(0x000E0054); /// FMC Errors pub const FMC_GLOBAL_NMI: CaliptraError = CaliptraError::new_const(0x000F0001); diff --git a/fmc/Makefile b/fmc/Makefile index 04f2e7a761..2b8c27fbee 100644 --- a/fmc/Makefile +++ b/fmc/Makefile @@ -70,7 +70,7 @@ build-fw-image: gen-certs build-emu build-test-rt create \ --key-config $(TARGET_DIR)/keys.toml \ --ecc-pk-idx 3 \ - --lms-pk-idx 3 \ + --pqc-pk-idx 3 \ --fmc $(TARGET_DIR)/caliptra-fmc \ --fmc-version 0 \ --fmc-svn 0 \ diff --git a/image/app/src/create/config.rs b/image/app/src/create/config.rs index 5ee8d94209..8a5e132e4c 100644 --- a/image/app/src/create/config.rs +++ b/image/app/src/create/config.rs @@ -23,9 +23,13 @@ pub(crate) struct VendorKeyConfig { pub lms_pub_keys: Vec, + pub mldsa_pub_keys: Vec, + pub ecc_priv_keys: Option>, pub lms_priv_keys: Option>, + + pub mldsa_priv_keys: Option>, } /// Owner Key Configuration @@ -38,6 +42,10 @@ pub(crate) struct OwnerKeyConfig { pub lms_pub_key: String, pub lms_priv_key: Option, + + pub mldsa_pub_key: String, + + pub mldsa_priv_key: Option, } // Key Configuration diff --git a/image/app/src/create/mod.rs b/image/app/src/create/mod.rs index 6c660a4505..f16947b619 100644 --- a/image/app/src/create/mod.rs +++ b/image/app/src/create/mod.rs @@ -74,9 +74,9 @@ fn check_date(from_date: &str, to_date: &str) -> anyhow::Result { /// Run the command pub(crate) fn run_cmd(args: &ArgMatches) -> anyhow::Result<()> { - let image_type: &u32 = args - .get_one::("image-type") - .with_context(|| "image-type arg not specified")?; + let pqc_key_type: &u32 = args + .get_one::("pqc-key-type") + .with_context(|| "pqc-key-type arg not specified")?; let config_path: &PathBuf = args .get_one::("key-config") @@ -118,9 +118,9 @@ pub(crate) fn run_cmd(args: &ArgMatches) -> anyhow::Result<()> { .get_one::("ecc-pk-idx") .with_context(|| "ecc-pk-idx arg not specified")?; - let lms_key_idx: &u32 = args - .get_one::("lms-pk-idx") - .with_context(|| "lms-pk-idx arg not specified")?; + let pqc_key_idx: &u32 = args + .get_one::("pqc-pk-idx") + .with_context(|| "pqc-pk-idx arg not specified")?; let out_path: &PathBuf = args .get_one::("out") @@ -174,23 +174,32 @@ pub(crate) fn run_cmd(args: &ArgMatches) -> anyhow::Result<()> { .parent() .with_context(|| "Invalid parent path")?; + let pqc_key_type = if *pqc_key_type == 1 { + FwVerificationPqcKeyType::LMS + } else { + FwVerificationPqcKeyType::MLDSA + }; + let gen_config = ImageGeneratorConfig:: { + pqc_key_type, vendor_config: vendor_config( + pqc_key_type, config_dir, &config.vendor, *ecc_key_idx, - *lms_key_idx, + *pqc_key_idx, mfg_from_date, mfg_to_date, )?, - owner_config: owner_config(config_dir, &config.owner, own_from_date, own_to_date)?, + owner_config: owner_config( + pqc_key_type, + config_dir, + &config.owner, + own_from_date, + own_to_date, + )?, fmc, runtime, - fw_image_type: if *image_type == 1 { - FwImageType::EccLms - } else { - FwImageType::EccMldsa - }, }; let gen = ImageGenerator::new(Crypto::default()); @@ -211,10 +220,11 @@ pub(crate) fn run_cmd(args: &ArgMatches) -> anyhow::Result<()> { /// Generate Vendor Config fn vendor_config( + pqc_key_type: FwVerificationPqcKeyType, path: &Path, config: &VendorKeyConfig, ecc_key_idx: u32, - lms_key_idx: u32, + pqc_key_idx: u32, from_date: [u8; 15], to_date: [u8; 15], ) -> anyhow::Result { @@ -222,31 +232,21 @@ fn vendor_config( let ecc_key_count = config.ecc_pub_keys.len() as u32; let lms_key_count = config.lms_pub_keys.len() as u32; + let mldsa_key_count = config.mldsa_pub_keys.len() as u32; if ecc_key_count > VENDOR_ECC_MAX_KEY_COUNT { return Err(anyhow!("Invalid ECC Public Key Count")); } - if lms_key_count > VENDOR_LMS_MAX_KEY_COUNT { - return Err(anyhow!("Invalid LMS Public Key Count")); - } if ecc_key_idx >= ecc_key_count { return Err(anyhow!("Invalid ECC Public Key Index")); } - if lms_key_idx >= lms_key_count { - return Err(anyhow!("Invalid LMS Public Key Index")); - } let ecc_pub_keys = &config.ecc_pub_keys; for (i, pem_file) in ecc_pub_keys.iter().enumerate().take(ecc_key_count as usize) { let pub_key_path = path.join(pem_file); gen_config.pub_keys.ecc_pub_keys[i] = Crypto::ecc_pub_key_from_pem(&pub_key_path)?; } - let lms_pub_keys = &config.lms_pub_keys; - for (i, pem_file) in lms_pub_keys.iter().enumerate().take(lms_key_count as usize) { - let pub_key_path = path.join(pem_file); - gen_config.pub_keys.lms_pub_keys[i] = lms_pub_key_from_pem(&pub_key_path)?; - } let mut priv_keys = ImageVendorPrivKeys::default(); if let Some(ecc_priv_keys) = &config.ecc_priv_keys { @@ -261,30 +261,77 @@ fn vendor_config( gen_config.priv_keys = Some(priv_keys); } - if let Some(lms_priv_keys) = &config.lms_priv_keys { - for (i, pem_file) in lms_priv_keys + if pqc_key_type == FwVerificationPqcKeyType::LMS { + if lms_key_count > VENDOR_LMS_MAX_KEY_COUNT { + return Err(anyhow!("Invalid LMS Public Key Count")); + } + + if pqc_key_idx >= lms_key_count { + return Err(anyhow!("Invalid LMS Public Key Index")); + } + + let lms_pub_keys = &config.lms_pub_keys; + for (i, pem_file) in lms_pub_keys.iter().enumerate().take(lms_key_count as usize) { + let pub_key_path = path.join(pem_file); + gen_config.pub_keys.lms_pub_keys[i] = lms_pub_key_from_pem(&pub_key_path)?; + } + + if let Some(lms_priv_keys) = &config.lms_priv_keys { + for (i, pem_file) in lms_priv_keys + .iter() + .enumerate() + .take(lms_key_count as usize) + { + let priv_key_path = path.join(pem_file); + priv_keys.lms_priv_keys[i] = lms_priv_key_from_pem(&priv_key_path)?; + } + gen_config.priv_keys = Some(priv_keys); + } + } else { + if mldsa_key_count > VENDOR_MLDSA_MAX_KEY_COUNT { + return Err(anyhow!("Invalid MLDSA Public Key Count")); + } + if pqc_key_idx >= mldsa_key_count { + return Err(anyhow!("Invalid MLDSA Public Key Index")); + } + + let mldsa_pub_keys = &config.mldsa_pub_keys; + for (i, file) in mldsa_pub_keys .iter() .enumerate() - .take(lms_key_count as usize) + .take(mldsa_key_count as usize) { - let priv_key_path = path.join(pem_file); - priv_keys.lms_priv_keys[i] = lms_priv_key_from_pem(&priv_key_path)?; + let pub_key_path = path.join(file); + gen_config.pub_keys.mldsa_pub_keys[i] = Crypto::mldsa_pub_key_from_file(&pub_key_path)?; + } + + if let Some(mldsa_priv_keys) = &config.mldsa_priv_keys { + for (i, file) in mldsa_priv_keys + .iter() + .enumerate() + .take(mldsa_key_count as usize) + { + let priv_key_path = path.join(file); + priv_keys.mldsa_priv_keys[i] = Crypto::mldsa_priv_key_from_file(&priv_key_path)?; + } + gen_config.priv_keys = Some(priv_keys); } - gen_config.priv_keys = Some(priv_keys); } gen_config.ecc_key_idx = ecc_key_idx; - gen_config.lms_key_idx = lms_key_idx; + gen_config.pqc_key_idx = pqc_key_idx; gen_config.not_before = from_date; gen_config.not_after = to_date; gen_config.ecc_key_count = ecc_key_count; gen_config.lms_key_count = lms_key_count; + gen_config.mldsa_key_count = mldsa_key_count; Ok(gen_config) } /// Generate owner config fn owner_config( + pqc_key_type: FwVerificationPqcKeyType, path: &Path, config: &Option, from_date: [u8; 15], @@ -292,16 +339,11 @@ fn owner_config( ) -> anyhow::Result> { if let Some(config) = config { let mut gen_config = ImageGeneratorOwnerConfig::default(); - let pem_file = &config.ecc_pub_key; + let pem_file = &config.ecc_pub_key; let pub_key_path = path.join(pem_file); gen_config.pub_keys.ecc_pub_key = Crypto::ecc_pub_key_from_pem(&pub_key_path)?; - let pem_file = &config.lms_pub_key; - - let pub_key_path = path.join(pem_file); - gen_config.pub_keys.lms_pub_key = lms_pub_key_from_pem(&pub_key_path)?; - let mut priv_keys = ImageOwnerPrivKeys::default(); if let Some(pem_file) = &config.ecc_priv_key { let pub_key_path = path.join(pem_file); @@ -309,10 +351,26 @@ fn owner_config( gen_config.priv_keys = Some(priv_keys); } - if let Some(pem_file) = &config.lms_priv_key { - let priv_key_path = path.join(pem_file); - priv_keys.lms_priv_key = lms_priv_key_from_pem(&priv_key_path)?; - gen_config.priv_keys = Some(priv_keys); + if pqc_key_type == FwVerificationPqcKeyType::LMS { + let pem_file = &config.lms_pub_key; + let pub_key_path = path.join(pem_file); + gen_config.pub_keys.lms_pub_key = lms_pub_key_from_pem(&pub_key_path)?; + + if let Some(pem_file) = &config.lms_priv_key { + let priv_key_path = path.join(pem_file); + priv_keys.lms_priv_key = lms_priv_key_from_pem(&priv_key_path)?; + gen_config.priv_keys = Some(priv_keys); + } + } else { + let file = &config.mldsa_pub_key; + let pub_key_path = path.join(file); + gen_config.pub_keys.mldsa_pub_key = Crypto::mldsa_pub_key_from_file(&pub_key_path)?; + + if let Some(file) = &config.mldsa_priv_key { + let priv_key_path = path.join(file); + priv_keys.mldsa_priv_key = Crypto::mldsa_priv_key_from_file(&priv_key_path)?; + gen_config.priv_keys = Some(priv_keys); + } } gen_config.not_before = from_date; gen_config.not_after = to_date; diff --git a/image/app/src/main.rs b/image/app/src/main.rs index 189d4b06b5..768f840205 100644 --- a/image/app/src/main.rs +++ b/image/app/src/main.rs @@ -22,7 +22,7 @@ fn main() { let sub_cmds = vec![Command::new("create") .about("Create a new firmware image bundle") .arg( - arg!(--"image-type" "Type of image keys: 1: ECC + LMS; 2: ECC + MLDSA") + arg!(--"pqc-key-type" "Type of image keys: 1: ECC + LMS; 2: ECC + MLDSA") .required(true) .value_parser(value_parser!(u32)), ) @@ -37,7 +37,7 @@ fn main() { .value_parser(value_parser!(u32)), ) .arg( - arg!(--"lms-pk-idx" "Vendor LMS Public Key Index") + arg!(--"pqc-pk-idx" "Vendor PQC (LMS or MLDSA) Public Key Index") .required(false) .value_parser(value_parser!(u32)), ) diff --git a/image/crypto/src/openssl.rs b/image/crypto/src/openssl.rs index 1ceca85956..9d6f4489f0 100644 --- a/image/crypto/src/openssl.rs +++ b/image/crypto/src/openssl.rs @@ -25,7 +25,7 @@ use openssl::{ ecdsa::EcdsaSig, nid::Nid, rand::rand_bytes, - sha::{Sha256, Sha384}, + sha::{Sha256, Sha384, Sha512}, }; use crate::{from_hw_format, sign_with_lms_key, to_hw_format, Sha256Hasher, SUPPORTED_LMS_Q_VALUE}; @@ -54,15 +54,21 @@ impl ImageGeneratorCrypto for OsslCrypto { OsslSha256Hasher(Sha256::default()) } - fn sha384_digest(&self, data: &[u8]) -> anyhow::Result { + fn sha384_digest(&self, data: &[u8]) -> anyhow::Result { let mut engine = Sha384::new(); engine.update(data); Ok(to_hw_format(&engine.finish())) } + fn sha512_digest(&self, data: &[u8]) -> anyhow::Result { + let mut engine = Sha512::new(); + engine.update(data); + Ok(to_hw_format(&engine.finish())) + } + fn ecdsa384_sign( &self, - digest: &ImageDigest, + digest: &ImageDigest384, priv_key: &ImageEccPrivKey, pub_key: &ImageEccPubKey, ) -> anyhow::Result { @@ -96,7 +102,7 @@ impl ImageGeneratorCrypto for OsslCrypto { fn lms_sign( &self, - digest: &ImageDigest, + digest: &ImageDigest384, priv_key: &ImageLmsPrivKey, ) -> anyhow::Result { let message: [u8; ECC384_SCALAR_BYTE_SIZE] = from_hw_format(digest); @@ -139,6 +145,18 @@ impl ImageGeneratorCrypto for OsslCrypto { Ok(to_hw_format(&priv_key)) } + + fn mldsa_pub_key_from_file(path: &Path) -> anyhow::Result { + let key_bytes = std::fs::read(path) + .with_context(|| format!("Failed to read public key file {}", path.display()))?; + Ok(ImageMldsaPubKey(to_hw_format(&key_bytes))) + } + + fn mldsa_priv_key_from_file(path: &Path) -> anyhow::Result { + let key_bytes = std::fs::read(path) + .with_context(|| format!("Failed to read private key file {}", path.display()))?; + Ok(ImageMldsaPrivKey(to_hw_format(&key_bytes))) + } } pub struct OpensslHasher(Sha256); diff --git a/image/fake-keys/src/lib.rs b/image/fake-keys/src/lib.rs index 733a7eddc4..9d6460e492 100644 --- a/image/fake-keys/src/lib.rs +++ b/image/fake-keys/src/lib.rs @@ -2,9 +2,10 @@ use caliptra_image_gen::{ImageGeneratorOwnerConfig, ImageGeneratorVendorConfig}; use caliptra_image_types::{ - ImageEccPrivKey, ImageEccPubKey, ImageLmsPrivKey, ImageLmsPublicKey, ImageOwnerPrivKeys, - ImageOwnerPubKeys, ImageVendorPrivKeys, ImageVendorPubKeys, IMAGE_LMS_OTS_TYPE, - IMAGE_LMS_TREE_TYPE, VENDOR_ECC_MAX_KEY_COUNT, VENDOR_LMS_MAX_KEY_COUNT, + ImageEccPrivKey, ImageEccPubKey, ImageLmsPrivKey, ImageLmsPublicKey, ImageMldsaPrivKey, + ImageMldsaPubKey, ImageOwnerPrivKeys, ImageVendorPrivKeys, ImageVendorPubKeys, + OwnerPubKeyConfig, IMAGE_LMS_OTS_TYPE, IMAGE_LMS_TREE_TYPE, VENDOR_ECC_MAX_KEY_COUNT, + VENDOR_LMS_MAX_KEY_COUNT, VENDOR_MLDSA_MAX_KEY_COUNT, }; use caliptra_lms_types::bytes_to_words_6; @@ -199,6 +200,964 @@ pub const VENDOR_LMS_KEY_3_PUBLIC: ImageLmsPublicKey = ImageLmsPublicKey { ]), }; +pub const VENDOR_MLDSA_KEY_0_PUBLIC: ImageMldsaPubKey = ImageMldsaPubKey([ + 0xa4c34aad, 0x85990594, 0x3b3099eb, 0x1ecf176c, 0x65de9fd6, 0xd9a79023, 0x8a4aa333, 0xd15a8dd4, + 0x37a0aa4b, 0x0189a817, 0x6fabfe0e, 0xe492fb02, 0xca3b81bd, 0xb50c58ba, 0xfb11dff9, 0x2d477742, + 0xd566336c, 0xd1777f86, 0x0bb73cb4, 0x5ec59477, 0x9b29603f, 0x132b3c75, 0xcecdce3c, 0x6cf949f0, + 0xc4de84ed, 0x070e6a14, 0xc130ede6, 0x9a74116a, 0xdaf1de3e, 0x644faa5c, 0x26cc8d01, 0x60631c69, + 0xce5f9b28, 0x68668dd7, 0xc48858fd, 0x4baaf788, 0xca3433ac, 0x56a9075f, 0x4a1a745d, 0x22aa4649, + 0xa9892830, 0xd849f593, 0x3199e941, 0x844b76be, 0x5bde507d, 0xe356c318, 0xaf6948be, 0xf724d9e2, + 0x0199a2bf, 0xcfccd9eb, 0x533ee9ce, 0x34c404fa, 0x4806443c, 0x6efc17d5, 0x30351c61, 0x42dc875f, + 0x81f53daa, 0x209c95a4, 0x66660dad, 0x3f63c49a, 0x9ae324b1, 0x700520c1, 0x96f1e571, 0xaa5133fc, + 0xb9b80b01, 0x66ec0775, 0xa087606c, 0x678196ed, 0x7e139b1b, 0x544c2fea, 0x3beb95ce, 0xe7c889e9, + 0xd4a78996, 0x1180d253, 0xf0611137, 0xa9065c5b, 0x16ad085e, 0xec4eb2ba, 0x5115d3d0, 0xa5d9ecc6, + 0x48993da9, 0xc9863823, 0x6d696b10, 0xc14bd1aa, 0xd5c7002c, 0x59b76ce5, 0x10d66ed6, 0xd99a3012, + 0x15e32845, 0x64583adb, 0xf131cb8d, 0xa23be8b4, 0x5586c868, 0x0147a4e9, 0x027406d3, 0x38a34707, + 0xbb11d35c, 0x999706cc, 0xd49b4f2f, 0x3a2bffcd, 0xbb8ea26a, 0x6031a38f, 0xb2b81bb0, 0xdd6ae90c, + 0xc52aae9e, 0x40c7118b, 0x4f6f69ab, 0xf1b9fb4e, 0xe17eff23, 0xd4196251, 0xabda30b8, 0xcfe73bdf, + 0x3fd708e8, 0x1dfdc294, 0x91135cf4, 0xce6d3a30, 0xd2d7d0e6, 0xc3bf0052, 0x58489c38, 0x20f2346a, + 0xfd2fcb6d, 0xa1c107ab, 0xa56d7f4d, 0x4af058e5, 0xcee727f4, 0xf90d042e, 0x6e9782dd, 0x3629b653, + 0x714e7dad, 0xe4348b69, 0xaa85996d, 0x8aa5f122, 0xf19ab645, 0x04caa0b3, 0xacdd0b32, 0xad05675c, + 0xffff31eb, 0xa10645f5, 0xa863501a, 0x3911cf31, 0x033bce32, 0xb402a4ba, 0xbbc8e37a, 0x473b2032, + 0xad0a222c, 0xadd5778a, 0xedef07f2, 0x4c704acb, 0x22395a0a, 0x46ed325c, 0x8c241603, 0xc63579f2, + 0x5e171cf0, 0xc703cca8, 0xf0bf7ced, 0x95947386, 0xd118ea9a, 0xcf4061e9, 0x755fb6d7, 0xd34b8467, + 0x4c9e316c, 0x8efbaf5c, 0xaf8b6b3e, 0xf28805b5, 0x2738a2f6, 0xc1cc79fa, 0xc2bd26c5, 0xe26b439c, + 0xed195085, 0xd23091db, 0x9713c325, 0x50f0a173, 0x86a3be0e, 0x4a360d67, 0x934f7b28, 0x926678f0, + 0x62dc04c5, 0xa976ae51, 0x38491c4f, 0xe607a52b, 0xc8704ef4, 0x8dc70877, 0x68acb197, 0xf8893edf, + 0x79b754ab, 0x80e99d9a, 0x663d73e0, 0x49c877b5, 0x1f2a439e, 0x7fd843e6, 0x97e25f70, 0xee6b2ff3, + 0x6b2a5500, 0x4942e97d, 0xc6b07951, 0x669b5e38, 0x5ff06273, 0x60272b43, 0x033fb5c0, 0x27259270, + 0x171aee38, 0xa7484e7b, 0xc10a5c4e, 0xe3b43487, 0x6ddfb66c, 0xc6ef4e62, 0xf9b3589c, 0xc782ae18, + 0xf363227d, 0xaa8ac410, 0xe17eeb1f, 0xeea4133d, 0xa6dfd292, 0x5f08f536, 0x1fcd05e8, 0xe16efe1a, + 0x2e7a455e, 0xc72d6064, 0x5295fdb1, 0xb697a865, 0x8bc53087, 0xc08796f2, 0x2f2f6564, 0xb0a20df5, + 0xdc023426, 0x76987c49, 0x3cce098d, 0x88583c0d, 0x45b0950c, 0x0fe6a2c2, 0x25b2bb09, 0xfaf36bbe, + 0x2435bf9d, 0xb67048a5, 0x702c0f06, 0x2135a52a, 0x26287b18, 0x78cd8d26, 0x6bd42953, 0x726207fa, + 0xd2ebcc0e, 0x0cf25057, 0x06526617, 0xbffc320c, 0xd04bb69c, 0xc727b133, 0x2432b8e5, 0xd254bf04, + 0xb0edaf69, 0x4607caaf, 0xff728989, 0x78b8ce5b, 0xc308efb1, 0x5ed64e1c, 0xeeb02dcc, 0xf9eccf33, + 0xdfe64533, 0xdaf93cc6, 0x78b73c17, 0x9a98cd23, 0x3268ae29, 0x1da48aae, 0xbe5e4261, 0x625797f9, + 0xc16400e7, 0x27fe8157, 0x338cd9f9, 0xb6e767db, 0x82975ba6, 0x01478a92, 0x8c5cdfec, 0xaf7e993b, + 0x7d85b256, 0x9fa753df, 0xe9d265fc, 0xea6425d9, 0x998f95ac, 0x72a0b613, 0x195c598d, 0x2a0c41d8, + 0x5f04c2e9, 0xb46bf7c3, 0x7e6c48e0, 0x0288f1a9, 0xca6cb5f0, 0xe6d7b01d, 0x10c67516, 0xaca376b6, + 0x40ada0f3, 0x419032f3, 0xc48cfd07, 0xb4fdd654, 0xa7e8db89, 0x370a5b78, 0x92787949, 0x63421003, + 0x9ff61dbe, 0x41e91ecd, 0xc855adf9, 0x9debafb1, 0x26636426, 0xfe80dd85, 0xf9c53bb6, 0xae3c4ddb, + 0x188a110c, 0x26cda2b5, 0x9c9917bc, 0x42c0adad, 0x2f089433, 0x67d66b50, 0xa794832c, 0x5af545cc, + 0x2efa85bd, 0x98da9f58, 0x624e5a19, 0xf75ec35b, 0xc676e5a7, 0x2546bf59, 0x4f91107c, 0xb5036c40, + 0x70d7794a, 0xceb719a2, 0xceafdac4, 0x78673f8b, 0x0d9c3355, 0xea376196, 0x2e3c451f, 0x58fc6789, + 0x98843314, 0x10e05005, 0xa3ce45f7, 0xdc885fd2, 0x342e5ac2, 0x74e74b43, 0x6162978f, 0x5089904b, + 0xa4a8f931, 0x35d20a3f, 0x6f20b8be, 0x6d27bf2c, 0xd192dedc, 0x0e9a7c84, 0xbdfcdf99, 0x85d98eef, + 0xe28da928, 0x52bcfee1, 0x9c47918d, 0xc33cc88d, 0x99c8ebda, 0x5350bb28, 0x2fddd04e, 0xc2160cd0, + 0xd9648620, 0x618566d2, 0xf4a0bf7f, 0x5912e3b4, 0xa9c23354, 0x81cc09c1, 0x7b4b41cc, 0x9bdf60e5, + 0xb1adacbe, 0xcdbe6128, 0xa85e60fd, 0x09ec3faf, 0x904d4ca7, 0xb84b8e86, 0x763e058d, 0xca8a6df4, + 0x4f3ef01e, 0x8a982342, 0xb5a59cbc, 0xbc0224f6, 0x3422b3f6, 0xc6ed782b, 0xd74f55c6, 0x38951af4, + 0xb21db0fc, 0x99bc099e, 0xc6744fbc, 0x3cc0bac3, 0x6e6f28b0, 0x2977d2e4, 0x232359d0, 0x60152363, + 0xe75a98f8, 0xaf3ffb97, 0x1c969cde, 0xcbc41a17, 0x6665f99c, 0xb7b7c2db, 0x327317cd, 0x3a163243, + 0x92cfeaa5, 0x042bf3fb, 0x19cec4e4, 0x737a3dec, 0xf22df03f, 0x6c42b10d, 0xf13ebcff, 0x3b0bdf77, + 0x192d2e1c, 0xe8eb3b74, 0x52584a0d, 0xfabea3ea, 0xb8e02671, 0x3d04b140, 0x2b80ee27, 0x734d3032, + 0x4c6455c1, 0xc61e84b5, 0x01ad9944, 0x3ec96119, 0x6e5f95cd, 0x7352aacd, 0x88d2ac4b, 0x5467169e, + 0xd4168a36, 0x1da952aa, 0x2bc0e131, 0x5435ab85, 0xc721938c, 0xb604f118, 0x212cd772, 0x576f6f3c, + 0x69aa0827, 0xb04954e0, 0x1f257a5b, 0x32e882e6, 0xd1b37fcf, 0xde10e082, 0xaa97564f, 0x55210b99, + 0x777dde41, 0x65288b28, 0x5db9c9c8, 0x5252207e, 0xea63af88, 0xca4e4c70, 0x79148f92, 0xb3b3aea5, + 0x1c2a0bd8, 0x45badb6b, 0x020090a6, 0x9fea09ba, 0xae4cd583, 0xe7d105eb, 0x59eccce7, 0xcf6a7c88, + 0x2e5a9b33, 0xdee39d2e, 0xbc686d8c, 0xc7dfdfb7, 0x2462a62a, 0x148ef997, 0x28017beb, 0x9da516bc, + 0x02f99b56, 0xf1a8bdbd, 0x8450e8bc, 0x5a645fc6, 0x9c4d4c2e, 0xf8a77145, 0x80ca80ed, 0x70b7bc63, + 0x121b7a47, 0x606e46e2, 0xea4e0fd2, 0xb981091d, 0xfa705cd5, 0x6a805fb6, 0xf3ba2475, 0x6a22f4d5, + 0xe92c6b32, 0xb27666c1, 0x054b0277, 0x06362955, 0x0c8f72e8, 0x21c9eddd, 0x5e8ddb44, 0xd197a71e, + 0x1162a17a, 0xd5f1421b, 0x91685dd9, 0xe230b73c, 0x9a273985, 0xbec50fb5, 0xb016f4d8, 0x6d5c37fc, + 0x25dc6cac, 0xca3d51ae, 0x97004d3e, 0x5a194f4f, 0x005d47a0, 0xc7a853e4, 0x452ad686, 0x9114c0c3, + 0x65f93218, 0x6c2b60e2, 0xac044aeb, 0x2ddfda20, 0x4dd0276e, 0xc61a870e, 0xc95bfc2c, 0xda195076, + 0x354f97ca, 0x32137480, 0x87fe68b0, 0x6b22b28b, 0x4317ba5c, 0x03ed0d47, 0x97bd480d, 0x619de155, + 0x366693fe, 0xace200ce, 0x6546161d, 0x825a7e75, 0xd640f113, 0x3775386c, 0x6e9c25e5, 0x088a8be4, + 0x94b9b7b3, 0x39f1682d, 0x767efd2a, 0xea687310, 0x10352963, 0xf6ebb8ed, 0x7a05296a, 0xff5487e7, + 0x48509dfc, 0xf39e4cec, 0x8b203189, 0xb0a9570a, 0x1691e8bb, 0x610f37ef, 0xc021e846, 0x56f7c080, + 0xf7755ab4, 0x07864fa8, 0xe625d050, 0x1a81c9fa, 0xd474639e, 0x3f811615, 0x5961f68e, 0xa0f74879, + 0x8ab0aafb, 0x5a76cc37, 0x69adee7c, 0xcb2bd291, 0x98c16b0e, 0x5f4cf758, 0xade63d79, 0xdeeca28b, + 0x0663ae16, 0x31a0874d, 0xb9336dbb, 0x198579e2, 0x06b614c2, 0x5338c7b8, 0xd0ab40cc, 0x3fd1d9ca, + 0x86be3f79, 0xc73ea699, 0x8d76c562, 0x3fb4d865, 0x49fe05d1, 0x19f4d8bf, 0xc37cc553, 0x71354e62, + 0xf5034b0e, 0xd35120f8, 0xcc745c52, 0x2fc5244c, 0x1a88ac22, 0xbcf8175f, 0x36005e32, 0xf9636cdb, + 0xa56e213a, 0xa036b783, 0xda369deb, 0x5994b510, 0x9a0c5c1d, 0x005985ec, 0x30592bdc, 0xbfba60a5, + 0xae4371e8, 0x42d8f5c9, 0x11308268, 0x38ac064a, 0xb775f17a, 0x0068d63f, 0xa78cd9c8, 0xe943c524, + 0x728c9e63, 0x1999dd1b, 0x04bd23f2, 0x2ac632b4, 0x18672908, 0xb7735515, 0x97711e0d, 0xa32a65de, + 0xbdc4910c, 0x75575b2e, 0xfd4bf85d, 0x9c1494d7, 0x335bc800, 0x239953ae, 0x971fedc6, 0x8563f573, + 0xc64adead, 0xe022b3cc, 0xb04890d0, 0xc1ca889e, 0x844e0df5, 0x0059ccd6, 0xfa57851b, 0x0b7e4747, + 0xa0edca48, 0xd24d0309, 0x7bb51774, 0x0c8bb87b, 0xc1c260ce, 0x893359c7, 0xa8afb98c, 0xbca6933d, + 0x5facc0be, 0xd07dd74e, 0xdd2aabe5, 0xd93c1bfd, 0xd6724ba3, 0xea1c92fd, 0x808c0212, 0xc0057e86, + 0x18c116e6, 0x95ea19b6, 0x9971f126, 0xefb4c14c, 0x64087ba5, 0x6dbe8830, 0xa27661b3, 0xa9837201, + 0x4f164171, 0x9108b3d1, 0xf79c865e, 0x541e4696, 0x5c4c4977, 0x25fb4114, 0x7cdae73b, 0xace74be7, +]); + +pub const VENDOR_MLDSA_KEY_0_PRIVATE: ImageMldsaPrivKey = ImageMldsaPrivKey([ + 0xa4c34aad, 0x85990594, 0x3b3099eb, 0x1ecf176c, 0x65de9fd6, 0xd9a79023, 0x8a4aa333, 0xd15a8dd4, + 0xe39406df, 0x780e69d4, 0x58984cde, 0xf56451cf, 0xd7127ef3, 0xddabf144, 0x9b69cfe7, 0x09e93e5e, + 0x9d8af1bc, 0x7db9659f, 0xfae00502, 0xd8ca0ae3, 0x37195014, 0xceafe5a2, 0x8b887a5e, 0x8ecf604d, + 0xcdc9e51d, 0x2a2e0725, 0xf71d9455, 0xa7e9ec84, 0x421b6e1d, 0x4faeb14e, 0x041a3f5c, 0x46ce8a96, + 0x11064c92, 0x002524c7, 0x21894640, 0xa2126ec4, 0x382c1a08, 0x32541044, 0x58b89112, 0xc68cd9c2, + 0x69c8b269, 0xc2287240, 0x2084cb98, 0x2c83428e, 0xc4a66dc3, 0x8280d430, 0x1113c268, 0x54204854, + 0x2490c236, 0x080ba86d, 0x13a908d9, 0x20808836, 0x2820b249, 0xc0088924, 0xc9899902, 0x894c0026, + 0x94228dc2, 0x344813c5, 0x8d013649, 0xe0b42460, 0x28250838, 0x51094246, 0x614029c0, 0xc828c990, + 0x4942904c, 0x90208403, 0xb65103b5, 0x095c2866, 0x44866cc4, 0xa8218812, 0x62d33011, 0xdcc26509, + 0x38484298, 0x7193b490, 0x00150008, 0x0600a136, 0x80db4210, 0x1b188cda, 0x44440a82, 0x31192285, + 0x0b232a14, 0x1421c4c6, 0x31241409, 0x52948910, 0x248e0013, 0x41cb4020, 0x41824900, 0x494c2147, + 0x2c991830, 0x8c366d8b, 0xa28914c0, 0x291cc54d, 0x84a870d8, 0x1861a128, 0x62d3982c, 0xd9840553, + 0x14881228, 0x880a4005, 0x5c084e50, 0x92690815, 0x01189509, 0x09c971cc, 0x888cd8a0, 0x0801b020, + 0x09090449, 0x38646198, 0x2980486e, 0xa4a8601a, 0x346c5418, 0x31002385, 0xa1964850, 0xa84c02c2, + 0x0818342d, 0x93260c22, 0x440a2241, 0x7183b811, 0xa132854b, 0x468951c6, 0x60038769, 0x1a128603, + 0x48055144, 0x0541340d, 0x43382414, 0xb2886220, 0x6a0c4826, 0xcb908d08, 0xb904db88, 0x6d52100d, + 0x99a42088, 0x04008298, 0x280c3441, 0x6484610b, 0x27214b24, 0x4e4a0270, 0x102686cc, 0x121003a0, + 0x6409b344, 0x0ab405d4, 0x0686a1b6, 0x88a2224c, 0x02a46458, 0xc6519212, 0x018b444e, 0x22b80d1a, + 0xa35112b7, 0x88089609, 0x61a8249b, 0x060e8334, 0x31a3486d, 0x8c824d49, 0xb004a042, 0x42902282, + 0x50164a09, 0x012d10a9, 0x20142671, 0x22201153, 0x24481003, 0x2adb2024, 0xdba24900, 0x88251989, + 0x65984004, 0xa4908822, 0x87308c20, 0x8019482c, 0x62162d23, 0x252a1a17, 0x60a1a205, 0xe32861cb, + 0x242d2405, 0x8a1b0291, 0x929291a1, 0x226a4328, 0x2c14204d, 0xe34828dc, 0xa6800a16, 0x66623044, + 0x21a45191, 0x24861248, 0x650c0529, 0xd3347222, 0x166a5296, 0x8109052c, 0x5aa86908, 0x8468a294, + 0x8c84108a, 0x0c37420a, 0x054623b2, 0x25249305, 0xd4b41000, 0x311114b9, 0x9109b888, 0x20840103, + 0x426d42b0, 0x30180929, 0xa4480e10, 0x946c6126, 0x82192510, 0xd20404da, 0xa4115120, 0x66a11084, + 0xc9946412, 0x248e5a04, 0x4ad22804, 0x8a8029e0, 0x4466cc48, 0x82489810, 0xd0000509, 0x0071ca82, + 0x080b8470, 0x24804c18, 0xc281d802, 0x4cd8864d, 0xe3300513, 0xb10d0246, 0x40091289, 0x02b68921, + 0x2326a414, 0x70c3b645, 0x001921d3, 0x88510b23, 0x88e21271, 0x53a628a1, 0x200ed106, 0x8c09c965, + 0x82268cc3, 0xa4514ab0, 0x4918a78c, 0x2444211c, 0x1282d034, 0x92102012, 0xc3464213, 0xa38dca48, + 0x6d5a146a, 0x133648cb, 0x282161b6, 0x6051062c, 0x1c476211, 0x3049dc94, 0x8962402a, 0x08292443, + 0x1262d000, 0x0c19a670, 0x08c66512, 0x81118124, 0x24144240, 0x04a98819, 0x22619038, 0x891a1629, + 0x1a22250b, 0x036c43b4, 0x51d94642, 0x2305611c, 0x372e1a16, 0x06620669, 0x13b00d49, 0x2686e408, + 0x2ddb8480, 0x82160de0, 0x322ec9a8, 0x49124324, 0xc2326504, 0x384902a3, 0x014b1224, 0x04492c81, + 0x36885438, 0x8c9ba425, 0x63966442, 0x0042dc26, 0x12040301, 0x1aa608e2, 0x98091243, 0x084c9689, + 0xc38670da, 0x9440e418, 0x41123969, 0xd1148d9c, 0x12260404, 0x80209864, 0x9c1290d1, 0x36829202, + 0x4a18020e, 0x1a146459, 0x104ea200, 0x28c83680, 0x514268c9, 0x22815838, 0x90009588, 0x0c479282, + 0xb24944a0, 0x20230210, 0xc032929a, 0x3070dab8, 0x0851a048, 0x83006a08, 0xa4894492, 0x090b4901, + 0xa4240ee3, 0x34640910, 0x669c920d, 0x924069d3, 0x34668120, 0x2960a224, 0x8a8280a0, 0xb6492032, + 0x2161006e, 0x913628c3, 0x3805c312, 0x1089c630, 0xa30424dc, 0x06620936, 0x441c4962, 0x1885241c, + 0x93295aa2, 0x01894832, 0x0b804921, 0x80601ac1, 0x08122244, 0xd0b22d13, 0xa0200827, 0x8e0b0964, + 0xc1c8650c, 0x06321895, 0x2454248d, 0xa3b64924, 0x3672e088, 0x2c1b2390, 0x0cb1511b, 0x48504422, + 0x8dc13202, 0xd4c0901b, 0x312a1b21, 0x6513a770, 0x92404814, 0x4591c838, 0x02a3408d, 0x18100a92, + 0x186019b9, 0x4808122e, 0xc1068c89, 0x3469a294, 0x41202166, 0x63062602, 0xa804dbc0, 0x30481681, + 0xe3966018, 0x8085a292, 0x9161228a, 0x0a890411, 0x036ac334, 0x4e0ca629, 0x0ac44081, 0x88012238, + 0x05840085, 0x0a484dcb, 0xa8640821, 0x08024510, 0x19980509, 0x87216020, 0x2d230691, 0x5406265b, + 0x0086c248, 0x4cc84024, 0x193561ca, 0x240962b0, 0x69e3c200, 0x5a40021c, 0x13814c36, 0x2453108e, + 0x4c28659a, 0x22921003, 0x6918c809, 0x9b966451, 0x26061384, 0x44a23225, 0x11a285d1, 0x386c0038, + 0x28213540, 0xc2922108, 0x14690948, 0x29a2088d, 0x4142619b, 0x461222c6, 0x90221942, 0x094766e1, + 0x26418a08, 0x2e58960c, 0x03a73119, 0xc3016232, 0x445a4828, 0x83880461, 0x244a0c12, 0x88133082, + 0x246a5444, 0x03603964, 0x0ae24bfd, 0x674716b8, 0x9ef17d1e, 0x39e92896, 0x9c187a82, 0x16a9483c, + 0x86f6e07d, 0xae2bb46a, 0xf5465e98, 0x1e8217be, 0x77c40eeb, 0xe296856f, 0xbdddaf2d, 0xaf6f9518, + 0xdb70e7a2, 0xcb4424c1, 0x88651530, 0xbad10f64, 0x6b2c85f4, 0xa3d74597, 0x19bb3c58, 0xb9501f09, + 0xd35db9da, 0x8a628612, 0xf81e0b44, 0xb49bea5f, 0xc1a52072, 0xf9a19f48, 0x6081b415, 0x51c9bcfe, + 0x10879a3f, 0x75adfd99, 0x6d89396f, 0xb487ffea, 0xb9ef801a, 0x986d4719, 0xf0e7df16, 0xfbb13811, + 0xe7644277, 0xa2705165, 0x3755eef3, 0x99475d87, 0x78cb4c4a, 0x1e4516ab, 0x977faac5, 0x0ab64740, + 0x35194600, 0x44ccf267, 0xfbe0bd0a, 0x1641e7d4, 0x7bf943c5, 0x8eca0289, 0x04b2dd4f, 0xc12d6ac0, + 0x3f9ee061, 0x99739641, 0x7e0231c6, 0x42730c20, 0x37834a02, 0x94db5a56, 0x549d72c4, 0xccf51e4e, + 0xaefa45fe, 0xd3a01b7a, 0x36dda155, 0xe150d801, 0x20762cec, 0x97175e90, 0x3a1940f3, 0xaf1818d9, + 0x21c2d1ec, 0x41814d1b, 0x024cb245, 0x44f63977, 0xd74c7b34, 0x81050af9, 0x12160508, 0x9434dc34, + 0x65c7b310, 0xb1bf5e02, 0x32884a38, 0xb9c9af69, 0x621d4a24, 0x9f0d6d85, 0xad3a149c, 0x43a90c37, + 0x8eac8e51, 0x7a97b7e3, 0x9b250f00, 0xc73ec9ec, 0x4aa511d0, 0xdeb8b884, 0xc9d1774f, 0x574784e3, + 0xff747168, 0x8221518c, 0x7f244122, 0x9c5233f5, 0xa342667d, 0x6f15731b, 0x9f48584f, 0xe73af6d2, + 0x2d69a9c9, 0xe6d5181c, 0x5c7cdb0b, 0x945c42aa, 0xf8eb85ac, 0xa1707d39, 0x2c507bff, 0x9739973a, + 0x08728ffc, 0x043827b9, 0x04a26f63, 0xb891e952, 0x8bb0b60e, 0xb385e4bf, 0xd92c9b56, 0x6f8e83e8, + 0xdf4524a9, 0x6f983475, 0xaa645c51, 0xcaaa012f, 0x29d73f1e, 0x86462607, 0x66238abf, 0x512f1f78, + 0x579f5f6b, 0xf515c56a, 0x4997bd85, 0xa7eb7d0c, 0x09cc93b5, 0x3875e449, 0x3ffa9d45, 0x1fc20d24, + 0xd83df3bd, 0x554363eb, 0x36384968, 0x51b4eeb6, 0xf4594708, 0xa32e4173, 0x9d30802e, 0x0d475b43, + 0x0fbc0002, 0xd3fcb2ac, 0xb2564eb0, 0x448e84a1, 0xff5a1044, 0x23e05fa1, 0x0940b560, 0x19a6fac2, + 0x2b850781, 0x735f0b46, 0xf6869557, 0x4eb3594f, 0xc2f277f4, 0x71bc6362, 0xed1b5f39, 0x7853ab08, + 0xc5205d29, 0x8fa33728, 0x173960b9, 0x5d3bd6b9, 0xa3123155, 0x6387a4c4, 0x63669054, 0x81162c98, + 0x7c627859, 0x9971be66, 0x2d87fa01, 0xcda7997b, 0xbd32a669, 0x558177a7, 0xa40d3a56, 0x599a43d4, + 0x247c4bf2, 0xcb3b05ef, 0x90f69317, 0xcd49e1c3, 0xd0b33657, 0xc2516898, 0x4872db36, 0x8dc12552, + 0xc1cd1918, 0xf18b71b8, 0xdd75615e, 0xe74e1d02, 0x59a70112, 0x0e675c65, 0x3ce9a63a, 0x263f1662, + 0xe34b7ec4, 0x81b15f6c, 0x78150c6e, 0xb2398603, 0x4b359929, 0x2e027fae, 0x75c0123d, 0xf00ad895, + 0x3cd5c6ff, 0xb7ea913f, 0x2524598e, 0xc059a14a, 0x8675010f, 0x643fcfa6, 0x41da8a16, 0x4a449c39, + 0xf83b1872, 0xad691a95, 0xcc496d2f, 0x39c66e85, 0xc18c6849, 0x55a87a93, 0xb4adef69, 0xeb523759, + 0xbd759393, 0x39657266, 0xc2602d5f, 0xff15def3, 0x944dd782, 0x98db2e1b, 0xa1fc32ff, 0xb20d3147, + 0x597bd8e2, 0xbdd34a1c, 0x71f109dc, 0x30c1a84f, 0x933b6625, 0x78e0a87e, 0xe69bfeb8, 0x880e11bc, + 0xeb802880, 0xece8e4a6, 0xf8d15ed8, 0x4eaf94c5, 0xae6f2cd5, 0x22dc2d99, 0x0aaca9fc, 0x9729ac15, + 0x6792c7aa, 0x1b0d6861, 0x2c3bea50, 0xe37fc9fd, 0xb72d2f35, 0x71f306e7, 0xc14c75bd, 0x846e40ca, + 0x3c5ecec8, 0x93a78213, 0x3503a068, 0xe557ba28, 0x58769d03, 0x404d2e44, 0x543ee72c, 0x06d73f49, + 0xf817d8a0, 0xce902ec8, 0xb2e02c82, 0x8961c205, 0x4e46477e, 0xa8d362a1, 0xedd543b5, 0x5e6e3e3a, + 0x1223f1a3, 0x9f4aef62, 0x620424a9, 0xa1cff3b9, 0x2179f6cd, 0xe2576f43, 0x7ddf3c04, 0x0bf4c303, + 0x4fcab9e7, 0x5ddf5068, 0x7f84d49c, 0x3562b69e, 0xb9bb142f, 0xe9ddbd41, 0x0ecd9888, 0x1274ad3f, + 0x6f5212b5, 0xef3263b3, 0x1d0d3e27, 0xaed295ea, 0xb001a479, 0x46e974b8, 0xeeab5d4d, 0xfaf551ee, + 0x311f8ad7, 0xcf204776, 0xe521035e, 0xc8dd332e, 0x799033d5, 0x4c41d4bf, 0x9cd01048, 0x8a718253, + 0x34adfdab, 0xc903f4a5, 0x879129ac, 0xeb1b05d1, 0xe64015e5, 0x4da0e263, 0x1adafe04, 0x8c6327aa, + 0x8eae637e, 0x2b6381d7, 0x4c7fd789, 0x84f7e664, 0x92ce49ee, 0xc8d3446a, 0x82efcf39, 0x4fc6e4eb, + 0x716e67de, 0xb828932b, 0x7284423b, 0xae750905, 0x0836cabe, 0x1603ca99, 0x3bd7c32c, 0x793af848, + 0x454d6186, 0xd8605012, 0x8c2c5a0c, 0x5919aed4, 0x6934674c, 0x3fc2f330, 0x6cc1acb7, 0xbcd5c4a3, + 0x97c18f30, 0xe706ccc3, 0x19391a57, 0x01318c15, 0xd43005c3, 0x2f474395, 0xc0133d62, 0xa6dfbf19, + 0x95a0b401, 0xba9314d1, 0x7a8baf6a, 0x48d1e504, 0xdbeaf12f, 0x47e160d2, 0x4a7f6db4, 0x8598c2c9, + 0x1a26bc48, 0x9d534d14, 0x6097d0e6, 0x326e5ce1, 0x4b4d6a1b, 0xc819dd5d, 0xa3ae0602, 0xf9bd9328, + 0x24bff80c, 0x5ee94332, 0x1e57779e, 0x09a82af7, 0xe168a242, 0xda810e2d, 0x5d8b8d18, 0xf0f815f0, + 0xff0872dd, 0x5e55bd1e, 0x2f8a07bf, 0x824aeedb, 0x2df3e3f6, 0xb7ab5442, 0x59afdf86, 0x7083b466, + 0x040b6425, 0xc2df2924, 0xefa38568, 0x10826caa, 0x8215e630, 0xc995006d, 0x39a10d8c, 0xfc519807, + 0xb72d708a, 0x783bece7, 0xbb7bea32, 0x6bafdf8c, 0x8ebe01b1, 0x3904dd65, 0x984c9bff, 0x182430be, + 0x4e8769cd, 0xd0d79d95, 0x585398da, 0xf2daf7c9, 0x1dbd1db6, 0x75cfdbaf, 0xa9047673, 0x76d35592, + 0x08b3976c, 0x9ffe9c9e, 0x6d4ce67c, 0x2eced30b, 0x1c3cc39e, 0xfd04ef3e, 0x1cd08f15, 0xa3d08bcb, + 0x1aa2ff00, 0x440d9ab8, 0x00df0d23, 0xc5dd0481, 0x3cc6bad8, 0x532f33c9, 0x5823e489, 0xed5ed1c6, + 0xd4ca0d9c, 0x8fbba119, 0x2e487ddc, 0x9e0cac71, 0x7fc9aed3, 0xe5733e8d, 0x7dd3b22a, 0x8a848ad0, + 0x80bc3aca, 0x555d2d3b, 0xb0ac0940, 0x052dc1f8, 0xb206298c, 0x84aee424, 0xc63a4a14, 0xa4694b28, + 0xd7ed1820, 0x7c762f61, 0x18f7cb23, 0xc7a23bdc, 0x8c4d6c51, 0x6eb3e50b, 0xf3d729d8, 0x5996dd77, + 0x7140054b, 0x140f46ad, 0x5f31c2ac, 0x2439bb34, 0x6b70e26b, 0x3a841b31, 0xb2a6ee25, 0xf7cf672d, + 0x5fa7d039, 0xc8a5faad, 0xd437085c, 0x0c26ffc4, 0x5923ea57, 0x8b3c235c, 0x4feb2f04, 0xb3de8e33, + 0xf57c404c, 0x835e8bf5, 0x2f6efb08, 0x25ba6096, 0xd3ab434c, 0x5da8c7c4, 0x314b6514, 0x9f91c85d, + 0xccd06dd9, 0x5c191048, 0x1aff0916, 0xffb63c01, 0x6d8d4204, 0xabbcf65b, 0x3b1d0dc7, 0xfd5b9fda, + 0x711add54, 0x9a75acea, 0x04a44c75, 0x4ef657f7, 0x6fe3923c, 0x41c0ac70, 0xa02fb297, 0x5ec40380, + 0x002022c3, 0xdb5af233, 0x43932650, 0xb686b0d7, 0x5b255865, 0xa617e3d8, 0x2508492f, 0x4170e5e8, + 0xf8a31f87, 0xd268b645, 0xa75d21f8, 0x0761cd6c, 0x8558b93a, 0xb3688e98, 0xe5c878e3, 0xce624611, + 0x57b4f8fa, 0xd16de94d, 0x3c4fef94, 0xdfebede2, 0x3507204e, 0x6d039441, 0xd0036294, 0xfe94817f, + 0xd73d3618, 0x2a77d537, 0xc947a97c, 0x8d385737, 0xb97297de, 0x59070d2d, 0x51017cfc, 0xb13aace4, + 0xeb508669, 0xb3807d9a, 0x6a6e89b6, 0x9caa16a7, 0x20613013, 0x41967541, 0xd57d07ec, 0x6ea79f15, + 0x86d85c32, 0x89eba5e9, 0x3d7ab102, 0x0cf93887, 0x8a08ec69, 0xc898acd2, 0x0d444d8a, 0x29e14193, + 0xc7d1c700, 0x87329f6a, 0xef534310, 0xfb1fe9ca, 0x65dc33bf, 0xfa072418, 0xae4e7d03, 0xff67fbf3, + 0x8eba4ede, 0xa311daaa, 0xb11008a0, 0x4fb0d4df, 0xcf670f84, 0x39181a64, 0xda650353, 0x6e446b72, + 0x5389fb62, 0xa803c68f, 0xc3e2a7b5, 0xadca5371, 0x31d5a16a, 0x431af45c, 0x9f26f2f1, 0x9a427670, + 0x9f6f5c19, 0xc6e54f17, 0xe2c3410b, 0x776051fc, 0xc28289c2, 0x1e87cb74, 0x714f9ec2, 0xbb30b10d, + 0xcda6e099, 0x5adc8e3c, 0x6229909d, 0x5b20bfda, 0xc559df3c, 0x4b29db85, 0x1db6e921, 0x645ee6eb, + 0x88660511, 0x705d40bc, 0x56051931, 0xc28a68d5, 0xdd27d6c2, 0x0f6d865a, 0x5196d47b, 0xdbf2dd1f, + 0x4b532152, 0x0b63cd0a, 0x6e442b18, 0xf892dae8, 0x76df608f, 0x24e18784, 0xb1434655, 0xfbd40f59, + 0x3bccc9c6, 0x286ce980, 0xb6e71dbe, 0xe0d53f71, 0x340981c3, 0x3446f9d6, 0xd3872da4, 0x523f84ce, + 0x61968878, 0xe609d386, 0x900dfda7, 0x8008a53e, 0xd3685d8f, 0xd0effff5, 0x16b2f869, 0x91ea4b97, + 0xa90ee37e, 0x3d040f9f, 0x86877843, 0xdfa9f1c6, 0xbf9f9525, 0xcf39d88e, 0x34fb0f92, 0xef6758ec, + 0x88f75f3f, 0x78cc77aa, 0xcbd6b047, 0xd4b614dd, 0x8a465738, 0xc504ca4b, 0x30b4a639, 0x1eea1630, + 0x00e62ace, 0x29dddf73, 0x89e0793d, 0x6fca5e10, 0xa7bdb7c4, 0xef701b4d, 0xcc240742, 0xb776c733, + 0x1351b8cf, 0xc92c1705, 0xd6ed9105, 0x51565a45, 0x737ecc0b, 0x11019a66, 0x6476bba5, 0x7c888117, + 0x94efe83f, 0xa331e5f6, 0x6404934a, 0xdc2f4bc8, 0x104e922a, 0xdfda32d0, 0x0f399fa4, 0xd38681b4, + 0x4973cc81, 0xf7c7c7f3, 0x4febf0e5, 0x975cbe6b, 0x622d2457, 0xfa4e5cb5, 0x666900b1, 0xe28817ae, + 0xb17966ae, 0xecb90a44, 0x4571ddef, 0xab6f0c96, 0x57ac307c, 0x4be12bc0, 0x9d13c364, 0x67d4fdbb, + 0x305bd0df, 0xd5b3d8d2, 0xed73d1bd, 0x21dc9a83, 0xcddc04a9, 0xccee56d3, 0x72d80f68, 0x715f9d6c, + 0xb1a58322, 0x02d27a97, 0xfbbc4f20, 0x21352b5e, 0xe95f5aa4, 0xa7407a4d, 0xb150dc56, 0xbae995b0, + 0x11d32f4e, 0xfac468cb, 0xcd514ac4, 0x21e0842d, 0xcbdaa4d6, 0x4d8fd43b, 0xd16ccef5, 0xfe1d5503, + 0x59431404, 0x73c31a99, 0x561d6d15, 0x9c405846, 0xb2f94f0f, 0x7cc03c6e, 0xe12ccf28, 0x1b286166, + 0xe7e2844d, 0x4250e8c0, 0x12c56f7e, 0xb965d6c7, 0x3b8cc885, 0x8a17a1cd, 0x24279007, 0xb950eb2b, + 0x343c1d08, 0x5b5f73d7, 0x1594b149, 0x1fc35cbc, 0x3f353793, 0x0b514167, 0xa622d731, 0x57a8ef7f, + 0x1eba125a, 0x0d6db2f9, 0xe138cde9, 0x57f49546, 0x7c8998d1, 0xa7aef903, 0xa41762a7, 0x0a963d13, + 0xfc212914, 0x93626932, 0x728889c1, 0x48b252ec, 0xfa4d5f50, 0x78cd982c, 0xfec1209a, 0xe09f28b2, + 0xecaba3d9, 0x8a95b1dc, 0xe7e6f5a9, 0x7e489833, 0xb4df3327, 0xb7f00593, 0xba8e1b25, 0x070036fd, + 0xe0e303b4, 0x5f781042, 0x7bbcdb5e, 0x3a322265, 0x46306470, 0x4add49c6, 0xd34291e0, 0xfb4004ad, + 0xdbe02aa3, 0x5e911821, 0x12bb8448, 0xd560a5cf, 0xbb15a9f3, 0x4cbf4498, 0xed6f29b8, 0x32f41e73, + 0xa8988b5c, 0x7264ae33, 0xb3862712, 0x4835e9be, 0x80ebe9d7, 0xc2bfa04c, 0x62fd6ae8, 0x3301e2ca, + 0x763fe004, 0xb6ee1330, 0x35599e9f, 0x2ad82d30, 0x905b4eed, 0x403912f7, 0xf91cbbed, 0xc7c01aaa, + 0x396efd6b, 0x402438d9, 0x36eacc3d, 0xe2bd5d28, 0x8329d07a, 0x6ef2f6d4, 0x48f8c15c, 0x303af1da, + 0x3a9f23e3, 0x104ec5b4, 0x088ea42e, 0xefd76952, 0xdb5992a0, 0x541e3cf8, 0x5eec19b0, 0x697de6ac, + 0xf2d6c752, 0x1aa56e96, 0xaa844601, 0x4fe3c7eb, 0x59d5c213, 0x19d88f7f, 0x0ff53ce1, 0x4c811eb3, + 0x3f511769, 0x54606dd9, 0x61b7e5f3, 0xbdc94c4e, 0x3b0e0f86, 0x7c0df944, 0xa9e28b6a, 0xa293afb8, + 0x898509a6, 0xa1bf57c9, 0xa317a7bd, 0x9b4a6689, 0xb48a2f52, 0x9e0f93c9, 0x9a31e88b, 0x1f469453, + 0x8cb4e0d6, 0xf59fe4bb, 0xce20df9d, 0xa71e67c2, 0x2b29c3aa, 0x9cd28cc2, 0x787deff8, 0xa04fdd08, + 0x48aaa846, 0x3afc3ff0, 0x6ccfd4a8, 0x17d491c8, 0xb0ad68de, 0x32705a39, 0x31e22341, 0x286f1194, + 0xd9615ba8, 0x00a9b087, 0xb33c2ff7, 0x987464dd, 0x22102a61, 0xfeefb16e, 0x12df0ef1, 0x78a719dc, + 0x1379a9e1, 0x7c27bfe9, 0x7f75c0ca, 0xc780f4e4, 0xbe158ff3, 0xd471808f, 0x438b77c4, 0x14b4646b, + 0x96599fa0, 0xb3a518b6, 0xd44b5a60, 0x7678db1d, 0xe70d300b, 0x1981eab1, 0x56575eda, 0xf57e55dc, +]); + +pub const VENDOR_MLDSA_KEY_1_PUBLIC: ImageMldsaPubKey = ImageMldsaPubKey([ + 0x269e8df7, 0x7aba50b4, 0x9007232b, 0x73e1bca6, 0x70f68d4f, 0xb436b149, 0x16fe3d2d, 0x8f27f0e8, + 0xfce83581, 0x89ec288d, 0xd19e37f1, 0x3900682e, 0xb7cbbcf6, 0x9a7e2518, 0x37805f35, 0xae002ed5, + 0x3191b7f3, 0x3bd7b0e7, 0x9736328f, 0x7887391e, 0x0e3bf042, 0xdeee7e91, 0x370cb74f, 0x9769c21a, + 0xa612bd57, 0xe5422736, 0x3fcce779, 0xd0dce5a0, 0x4e0ec58d, 0x791f57d2, 0x629ae147, 0xc6472490, + 0x00fb7455, 0x6bf404f7, 0x9bd537f9, 0xe24a9b5b, 0x89678cf2, 0x69f9da6f, 0x430175b2, 0x081d16d5, + 0x71869292, 0xf8d4d533, 0x4adef988, 0x7e798760, 0x3063e46b, 0x98b3fe05, 0xe0cf9e47, 0x4f78a812, + 0xe9448b9d, 0xf563bd52, 0x52addaa8, 0xe201a87c, 0x79fc0dc6, 0x6ada3a38, 0xa8a709df, 0x431d351e, + 0xf0450fdc, 0xd80e0ffc, 0xaca9e38b, 0xfd7cc8aa, 0xd0a26497, 0x5b1ecb9b, 0xea9ccc1b, 0xf6ef2bfc, + 0xb31adf56, 0xc1e062cc, 0xc4f50cad, 0x867afcca, 0xc94c7859, 0x971460e7, 0x7ffbdcad, 0xdd5c7768, + 0x63a99d79, 0xfef1a17c, 0xc862ffd4, 0x0e4618df, 0x2437d1b5, 0x8a1210bc, 0x01e7431d, 0x16c10546, + 0x10cdadc6, 0xe8429099, 0x10339aff, 0x119b6740, 0x4bf3260b, 0xd33f50e7, 0x33485939, 0xe4af4909, + 0x249ca204, 0xe9f07faf, 0x9f511381, 0xa2483353, 0x6ca2b61c, 0xfc238cfd, 0x3b2ce26d, 0x65d9a13d, + 0x8672aacd, 0xae0a0cf3, 0xf8c204db, 0xda0ab573, 0xcf209214, 0x1cca8ee1, 0xd2c5bc6e, 0x2388d3b3, + 0x84e081fd, 0x1e05a60c, 0x2dce455e, 0xc30a3f7a, 0x261d9e4d, 0x64397fbd, 0x429d238c, 0xdc5e08da, + 0x3942c54b, 0x87bddea6, 0x5fe5bcfb, 0xdcdbabf5, 0xa0da6316, 0xe03e64ff, 0xb90810eb, 0x57c1e369, + 0x23a2f52c, 0x1507e319, 0xe87b6b98, 0xc818eaca, 0xbfd11a02, 0x43309ab4, 0xa3239f63, 0x687dd37a, + 0xf7af3520, 0x2cd8aff5, 0x40f0c5be, 0x6cf0ecb8, 0x3c50947a, 0x98cc7c69, 0x8fc9a5ad, 0xef80b98d, + 0x3e8a8663, 0x7c183b62, 0xdc5d417d, 0x914372e8, 0x48964c21, 0xc57e16cf, 0x59cde911, 0x7f750484, + 0xa683877a, 0xa4cb99dc, 0x45223ff1, 0x82d9fe23, 0xc693b90f, 0xe3c860c3, 0x7f133ba8, 0x9d6d0bc3, + 0xc61ca40c, 0x8d38a15f, 0x6602c6f8, 0x6e68a418, 0x6ce8b011, 0xbc7ff68f, 0x28dd4656, 0xf76e7160, + 0x42c9ef38, 0x11ab134b, 0xe5b2378a, 0x6cf5bacd, 0x08fe8aea, 0x988100d3, 0x8c984926, 0xfc43da9a, + 0x8e656591, 0x8499970c, 0x5498354e, 0xbab3ffaf, 0x2fd985df, 0x4ed9a18f, 0xb74babde, 0x4aa730e7, + 0xc4559cbf, 0xe966495f, 0x45ffb8c1, 0x20039246, 0xc28a0371, 0x5a4975b5, 0xcbbf4770, 0x738293a5, + 0x371b980c, 0xdae5a2b7, 0xf696a2df, 0x018da10e, 0x20c59b82, 0xc953ecd7, 0x1bfe0665, 0xd6e36ed0, + 0x40611d25, 0x96baa66a, 0xd63f9048, 0x7c02cc78, 0x3a34d1a6, 0xd37a03c0, 0xa9669ee6, 0xaec236ce, + 0xc8d3a277, 0x65d764db, 0x86aa4b57, 0xc99d122e, 0x3f9a4c7f, 0x87ea35e8, 0xf13dc78b, 0xf7fefc4d, + 0xc5708d56, 0x5e56a97d, 0xe222a7fb, 0x3107dd1a, 0x949309d0, 0x99a66c70, 0xf6feb74d, 0xc015322b, + 0x4864b948, 0x66751f31, 0xf5290273, 0x6520cfe6, 0xebf1b1ef, 0x8ff857cc, 0x4fab7676, 0x8b268983, + 0xc01da944, 0x8ca94ce4, 0xf0da1bb2, 0xcad4c8cf, 0x90eef0c5, 0x9a98edc1, 0x3d0a19f8, 0x6eb1b26f, + 0x34adc285, 0x43aecdd9, 0x3a66729d, 0x39dbc12e, 0x0dc1cb6a, 0x1e9a47fa, 0xa8ebb7dd, 0x3f780014, + 0x1da3f94d, 0x57bca525, 0xf3b9f5f4, 0x4ba731f5, 0xabd725db, 0x2ff49140, 0x624068f9, 0xd0964434, + 0xa6831859, 0xfd7d50bf, 0x8be4f7f2, 0x1ec1810e, 0x6e089baa, 0x2e393f3c, 0x94a888eb, 0x67aec405, + 0xd5330d47, 0x0f0e0696, 0xcd3a36c0, 0xd266fedb, 0x6cfe6472, 0x7d74918d, 0x4411f51c, 0x4deaa98c, + 0x5e749da7, 0x0bb096ec, 0x12a4b27c, 0x87017c69, 0x4d8f6066, 0x7894cbf7, 0x2b646d29, 0xf43c02b7, + 0x573e92a4, 0x839408b1, 0x9511b635, 0x8be4f237, 0x3cf447e4, 0x6a181e77, 0x2a176ad8, 0x4371928f, + 0xac2c0b65, 0x1bbe1e1d, 0x99692197, 0x568e5bea, 0x61f42a44, 0x016bb400, 0x136411a2, 0xf587dd99, + 0x0dad4313, 0x598ed8b7, 0x80bcd8e8, 0x6ebadd14, 0x2d438fb7, 0x40323de4, 0x681b7d88, 0x4c8b169c, + 0xe673ca13, 0x3f75a06d, 0x8bca016d, 0x8147763e, 0xec9e5d71, 0x62599071, 0x94634e79, 0xed41b8cd, + 0x51ad9ae8, 0x13a7f44d, 0xe55de2ad, 0x25729d36, 0x4e905d82, 0xfe3ca46b, 0xb7d49c70, 0x2072a578, + 0xe1799ddd, 0x26fe8855, 0x4c0d373e, 0x32b0fd39, 0x3d149b10, 0xd6583f84, 0xdea304ab, 0x08c14aaf, + 0xe6964cb1, 0xc0b2896d, 0x124e8f48, 0x4ff31ea2, 0x0adfabbb, 0x3b387701, 0xc7061085, 0xa62fc56b, + 0x53861c5a, 0x809efe5c, 0xd220c5f3, 0x0bebe480, 0x50ed7245, 0x0f58a00a, 0x93dafa94, 0x080bf5b0, + 0xa0a9a89d, 0x88e230fd, 0x1b865f7d, 0xcfd51df2, 0x003bb471, 0xef2705a7, 0x38b459f6, 0x57e77f09, + 0x3afca830, 0x33c0fe67, 0x56e83a0b, 0x05dd714d, 0x4597b9dd, 0x9bd68198, 0x7d031040, 0x1a451fa3, + 0x6b9f4fce, 0xe34e7d42, 0x99420237, 0xf344546c, 0xfbb103e1, 0xd138c2e8, 0x74198441, 0xccff4569, + 0x8f490c3f, 0xecffc0d7, 0x23fd6096, 0x38d68b40, 0x673db57d, 0x27d25604, 0x8e0cf8a3, 0xbde312a6, + 0x73e04bcd, 0x490e5675, 0x2fadd7b8, 0x34c14e0a, 0x7cd4e782, 0x3861a428, 0x2a9bfc0d, 0x9158cde7, + 0xf72faa75, 0xf026f0b2, 0x9a16e688, 0x2534a9e8, 0x9f91f85a, 0x3feacb0a, 0x66fce285, 0xb24c005c, + 0x279a3764, 0x9c0e2e78, 0xb8d500d2, 0x438bed47, 0x8af75942, 0x5eeb0cfa, 0xe23881b4, 0xad155670, + 0x81a4e4a3, 0xe27749e9, 0xebdc3685, 0x6b0ea41a, 0x43b067ad, 0x58fd4c49, 0x58d9a9ac, 0xf1e0ef81, + 0xb77a6751, 0xeb1f1976, 0x3ce9e8ff, 0x139e51d2, 0x2ec05b1f, 0x6d87fec2, 0xeac68b40, 0xc994f951, + 0x6bfe458d, 0xa1e7e474, 0xf76e7c37, 0x01d408dc, 0xb2440437, 0x0a1692b3, 0x239d51e8, 0x313b48a9, + 0x16eaf9ed, 0xf169547a, 0xc91e129c, 0x6171fe40, 0xe25b7a2e, 0xa59f74a2, 0xafcb7f66, 0x62a01360, + 0x8339e232, 0xeae1a3b2, 0x3f073e8d, 0x3273213c, 0x3b6951de, 0x3dcae727, 0x65e22530, 0x69a0f4b7, + 0xde475aea, 0x3fa68d34, 0x2bb88dd7, 0xcf46cb98, 0x3c6dd329, 0x3c60b4eb, 0x81a8ea44, 0x8e0e4a80, + 0xf1879696, 0xd422f84c, 0x39a5a193, 0x7ca3e020, 0xc7f31988, 0x0355fefc, 0xa1c04bdd, 0x8cfd5f29, + 0xe74dca05, 0xb6ff5284, 0x3f48af00, 0xaa530a3d, 0xfed2fab2, 0x4b35e484, 0x7afdd665, 0xcdebb6f9, + 0x45efec13, 0x859d331e, 0xc608b970, 0xeb633597, 0x44c3c26e, 0x9a568a0d, 0xaba71918, 0x02e10f20, + 0x4d4fb2dd, 0xa7401f07, 0x5b551090, 0x12006de6, 0x0d44047f, 0x43b4e3c1, 0xa39d0dbd, 0xd4270e02, + 0x29e09590, 0x234a1d58, 0x682ddd00, 0x47c3e898, 0xcd180ff6, 0x41251bf8, 0xe9a89709, 0x851796db, + 0x52a7e2ed, 0x5d94df2d, 0xb0282744, 0xd00d0ecd, 0x9fba8081, 0x225eb91f, 0x80f66548, 0x915b2ca0, + 0x46f35723, 0x90805f29, 0x364a6603, 0xeed8567f, 0x0fbefbfa, 0x47e679e3, 0x683ef48e, 0xb96ac167, + 0x833264f5, 0x4b1abd51, 0x2ba590db, 0xb8287b19, 0xea9b23e4, 0x58eeab92, 0xd2342cb2, 0x37f1edc1, + 0x2d68a1aa, 0x6f485d66, 0x8ef4e317, 0x248f587a, 0x4de5d1a8, 0x71bdb32c, 0x76322f27, 0xac184d79, + 0xc92968f7, 0xb3913f4a, 0x3759ea28, 0x23261bc8, 0x067a18b7, 0x6690fb36, 0xb6ee367b, 0x42dbffb8, + 0x3a6ddddd, 0xdb7c4453, 0x6c64c0bd, 0x2c6777f8, 0x261c5b27, 0x87433e9e, 0x51c07e9f, 0x4e705df8, + 0x033d2fa7, 0x68bc8112, 0xdb53fc16, 0x03a07bb9, 0xaac31838, 0xf2f68ed9, 0xaeb0be02, 0xe3e2ceb3, + 0x0d2151d2, 0x7b936751, 0xd77e33a6, 0x5e4b1118, 0x1c42fd08, 0x90df3162, 0x069bdacf, 0x6a5c6bee, + 0x98585c05, 0xbd4848c5, 0x7ef13eb3, 0x8f0b07cc, 0x96b13cd8, 0xf1b0f3ec, 0xd6a10833, 0x51f29825, + 0x81870631, 0x68cf7e36, 0x775beabf, 0x162626bc, 0x1471682f, 0xd05b94ac, 0xa320c84c, 0x708e92de, + 0xdf83e5b5, 0x71cbc72e, 0x3b40451b, 0x24c38789, 0xbdd151d6, 0xfd90d366, 0xa5f189c7, 0x592b98aa, + 0x17da52a6, 0x35449ef1, 0xd3d0dc21, 0x18415c6c, 0xa57bb036, 0x3f20c044, 0x84263084, 0xe2dc4151, + 0x21f9187d, 0x41eafbf2, 0x58e9eb85, 0xf34bf785, 0xf40f61c4, 0x74bb4250, 0xfbde9cc6, 0x244cf564, + 0x0114e3f5, 0x5be304c7, 0x6eb6c553, 0x8506d71d, 0x1090a943, 0x2504f406, 0xba1849e8, 0x3b7f5078, + 0x58f64fe4, 0x21c6df4e, 0x468f012f, 0x28112010, 0xff036d9a, 0xe3486e08, 0xe637d14b, 0xbd8efc71, + 0xb31e945b, 0x11ed4143, 0x5e674aa9, 0x730be9ac, 0xe9474691, 0x99abde87, 0x9aa5e920, 0x4d8aee97, + 0x40ebdf73, 0xb298c6f5, 0x6c3aed71, 0xd1196e7e, 0xc99af8ea, 0xfb220a4f, 0x3016f1f4, 0x4bcc3502, + 0x1aa4f8af, 0x79ebe6f3, 0xee8514da, 0x1cac5cb4, 0x3dfa4f4e, 0x5ca2f290, 0x273fbb1b, 0xd6bf3600, + 0x99ce425e, 0x936306c5, 0x92519add, 0x467460df, 0x48ed0bb4, 0x421a94bf, 0xd165e8ac, 0x6e727152, + 0x85cd139e, 0x01ee823a, 0x5ba35985, 0x4bac6f60, 0x33bcba6d, 0x2f2238be, 0x12d15e88, 0x271b99f8, + 0x594ead7d, 0xccea9a68, 0x1826af29, 0xf48ccdaf, 0x8ce423e8, 0x83d76f32, 0x59d57201, 0x82221243, +]); + +pub const VENDOR_MLDSA_KEY_1_PRIVATE: ImageMldsaPrivKey = ImageMldsaPrivKey([ + 0x269e8df7, 0x7aba50b4, 0x9007232b, 0x73e1bca6, 0x70f68d4f, 0xb436b149, 0x16fe3d2d, 0x8f27f0e8, + 0xfa8862b8, 0x40f4e19d, 0x7f348990, 0xb1a6e2c2, 0xf4eed150, 0x599ba9b8, 0xfe694524, 0x6e0f210c, + 0x550a089a, 0x908e85fe, 0xe2fa6b3f, 0xf5a7a85b, 0xb0cac1b9, 0xbdde9243, 0xd4e9d13e, 0x829b7301, + 0x080924a8, 0x0d9ba6d0, 0xeb2b53ec, 0xbe8efd64, 0x4736cd19, 0x51d4875f, 0x34ba4165, 0x78243a67, + 0x41268e53, 0x8488e234, 0x22041609, 0xcb1232cb, 0x126a5c26, 0x08103732, 0x1b319213, 0x9388cab0, + 0x6d903466, 0x838625a4, 0x160014a8, 0x4584a011, 0x01476e98, 0x16061b98, 0x80134430, 0x11050ac0, + 0xb804c3a2, 0x881a4772, 0x40b40402, 0x37529a88, 0x4484c44c, 0xe0324a22, 0x858d0407, 0x1024200d, + 0x8012920b, 0x4728cc02, 0x8103a610, 0x42048a08, 0xc211d328, 0x4ca1c611, 0x08b68000, 0x92912180, + 0x08ccb669, 0x98b4851a, 0xa2681925, 0x32911429, 0x1b422804, 0x10029a80, 0x00cc1880, 0x08985062, + 0x486c0014, 0x40920024, 0x02a07114, 0x91101834, 0x2a218570, 0x8ac82d0c, 0x83882311, 0x05013980, + 0x50b48c54, 0x12908408, 0x2c932440, 0x23a64480, 0x864c4aa4, 0x6089026a, 0x11452a00, 0x98411496, + 0x2c614288, 0x92984949, 0x442d41a4, 0x49a09871, 0x24a30058, 0xb0685204, 0x8460a410, 0x48864424, + 0x92301920, 0x695ac085, 0x54805008, 0x357281b2, 0x09124392, 0x22110013, 0x245194a2, 0x6158400c, + 0x991089e4, 0x9860c200, 0x72021610, 0xa3248c04, 0x020a0a45, 0x2a930211, 0x19266ac0, 0x98848c24, + 0x51214051, 0x002086cb, 0x12041105, 0x1123236e, 0x59a6655c, 0x08442302, 0x70cc8251, 0x2427649c, + 0x06690c35, 0x6502116e, 0x232672d8, 0x120c0217, 0x49c13488, 0xd4984950, 0x302d0429, 0x681b976d, + 0xd2c028d9, 0x1890c128, 0x8ccb8849, 0x83002c04, 0x122a1a14, 0x30211584, 0x48120882, 0x9261caa2, + 0x8124130a, 0x52422da3, 0x02880cb3, 0x10c2a245, 0x9c308420, 0xa70421c5, 0x451a4961, 0x8010641a, + 0x226c9216, 0x4a114846, 0xc2845124, 0xb70c0034, 0x6a4c220a, 0xc0402291, 0x4042e032, 0x0c53b810, + 0x40b48189, 0x3832d1a0, 0x108c306a, 0x58984da2, 0xb00c82a8, 0x61a22270, 0x01194c22, 0x156993c6, + 0x01a39669, 0x99b4104a, 0x420cd480, 0x911b3044, 0x53a20de4, 0xa40451a4, 0x8d0ab985, 0x02256914, + 0xa90dc906, 0x7183b468, 0x603852cc, 0x04050180, 0x4c04a56d, 0x9a289104, 0xc250c1c6, 0x4813178d, + 0x14025294, 0x344d1c07, 0x0d53a88c, 0xd0928161, 0x2085e426, 0x61434048, 0x00360590, 0x98615bb0, + 0x8c923884, 0xca1044d4, 0x96882144, 0x29883605, 0x9c940cca, 0x9288dbc2, 0x8c413090, 0x2032620c, + 0x4332c890, 0x8850940d, 0x04219261, 0x14110a25, 0x409c406c, 0x1837040a, 0x292a13c1, 0x65183948, + 0x24488284, 0x36645214, 0x61023365, 0x22238cd2, 0x046a8232, 0x0a212524, 0x20066c1b, 0xa230e2a0, + 0x8de38288, 0x2480605c, 0x88642024, 0x61808804, 0x0886400b, 0x407013b0, 0x0dc81866, 0x8a160499, + 0x86646432, 0x26984431, 0x8c946918, 0x492d1436, 0x26111924, 0x10296d5c, 0xc4880436, 0x451c3489, + 0xdcc689e0, 0xc60403c7, 0x6dc8b409, 0xa3b6609a, 0xc28024c2, 0x09e3300a, 0x8a988c00, 0x01700136, + 0x82580668, 0x21940c20, 0xb3109cb8, 0x10a1348d, 0x404069e2, 0x8409e036, 0x80511046, 0x032680a0, + 0xa28564b0, 0x24184769, 0x1c352a40, 0x184a0a47, 0x8d919628, 0xe2060ad2, 0x42282444, 0x8859c86c, + 0x89102e24, 0xc8310987, 0x28932060, 0x80208e89, 0xa60d4214, 0x0604148a, 0xe1866ddc, 0xc0011c97, + 0x209c102e, 0x24034518, 0xb42c1a96, 0x2422024d, 0x4ab82009, 0xb24963a4, 0x2c54b450, 0x82a404c1, + 0x22304004, 0x2159c241, 0x18873149, 0x448d9494, 0x6c1b2252, 0xa3a04c4c, 0x268c12a8, 0x0c1b0840, + 0x43440492, 0x286c0346, 0x82411430, 0x8c3232e1, 0xb6702299, 0x89824245, 0x4412811c, 0x01109288, + 0x8493c891, 0xa0482dcc, 0x30401a35, 0x50a00862, 0x09323159, 0x32500c06, 0x6400354d, 0x2112269c, + 0xa46104b4, 0x9002086a, 0xa0328291, 0xc8401931, 0x0e402432, 0xcc424c8a, 0x2400cba0, 0x68512491, + 0x59a67160, 0x822c2493, 0x0ddc204c, 0x0ba06921, 0x292a9b94, 0x908b8409, 0xc386455a, 0x46644882, + 0x51e1a445, 0x58c4089a, 0xb0080b29, 0x0089a089, 0x94064043, 0x14855b10, 0x29d18690, 0xc928529b, + 0xc0681ba6, 0x0863a240, 0xa4162993, 0xa62d1206, 0x81a20852, 0x99120e41, 0xa009e018, 0x61d0b061, + 0x1a368680, 0x24014936, 0x02a22888, 0x08262c10, 0x2260a326, 0x80932888, 0x20902c22, 0x24600414, + 0x4183c085, 0x5482209c, 0x086d1c83, 0x91811001, 0x5a366018, 0x9790dc16, 0x29d33031, 0x1847454b, + 0x8225e332, 0x2ccb3804, 0x08c54510, 0x02450025, 0x0920a328, 0x1b452500, 0x014c2418, 0x080c2265, + 0x51384612, 0x8090c036, 0x8e509885, 0x21a04c12, 0xc4096146, 0x62a21812, 0x0c311098, 0x444050c6, + 0x6903296d, 0x22c86920, 0xb1096180, 0x6880c621, 0x04c92d1b, 0xa70921a4, 0x4523132d, 0x59382c08, + 0x8671d812, 0x714cc88c, 0x14212641, 0xa4911396, 0x7012b581, 0xa3264298, 0x32689b12, 0x919a368d, + 0x62b82192, 0x008624a0, 0x8842b60c, 0x0c300a18, 0xb4450a01, 0x2a632211, 0xa4062518, 0x2001dc12, + 0x8a1a8889, 0x99240501, 0x324ee3c0, 0x89589444, 0x82484019, 0x3284c986, 0x71ca2690, 0x41324a94, + 0xb400e1b4, 0x80a4c06c, 0x02264c5c, 0x22028246, 0x80e1b44d, 0x59c48141, 0x8830c138, 0x70081791, + 0xc612ae0b, 0xb51a1d22, 0x640751f8, 0xf9525ee4, 0x69e86615, 0xe1a705c8, 0x9272010d, 0x4296f12e, + 0xf0f910ab, 0x255272ba, 0x00aedc7e, 0xce02a0d1, 0x6ed3e27f, 0xed9bc0e9, 0x212057f1, 0x77660d97, + 0x0b35d82c, 0x39875173, 0xae5b688a, 0xf9965da4, 0xfb108722, 0xf270627b, 0xace5bf4a, 0xfd649844, + 0xaa1fe1c4, 0xc33667dd, 0x2b7510a2, 0x8542d095, 0x50825e30, 0xaacc72e2, 0x97e916d3, 0xe6261c79, + 0x21cd19ed, 0xcc19f7c0, 0x2e0c00b4, 0x1697f640, 0x9ccab09c, 0x4fd43be6, 0x6844e028, 0x002f1db3, + 0xeae74a26, 0x78cee3c4, 0x2964149a, 0x81115052, 0x055fcad2, 0x3e9cd01c, 0x1f049edc, 0x4fe5b277, + 0x29b2eb67, 0xdb62cef1, 0x880a1372, 0x2a048776, 0x63981a6e, 0x65356732, 0x6345f799, 0xf4234d69, + 0x009ca1b1, 0x700454f4, 0x2f6acd6c, 0xfc461e03, 0xd4e44c51, 0x03471d4b, 0x6705fbae, 0x5d4d14c7, + 0x691f105f, 0x09ea02ba, 0xe173fa35, 0x4f2396d9, 0x1408ceed, 0xc48949fe, 0x9ad5d1c2, 0xc3bc8105, + 0x8f4de3fa, 0x195f3909, 0x885ba6f9, 0x9be8a20a, 0x91e8c891, 0x2681ffc5, 0xd748c84b, 0xdb29ef3d, + 0x535c74ee, 0x9c0a44a9, 0x1a302ac0, 0x14adf27b, 0x6f3e83c4, 0xed9fa325, 0xa3ea5f66, 0x255a01ab, + 0x7b6d4d41, 0x2b42d33a, 0x6da5aaa7, 0x23b8c21c, 0x106e62f6, 0x4163c372, 0x65287cc4, 0xf59f105e, + 0x1c8bb9b2, 0x008eb61c, 0x44b7b254, 0xc4bde2e4, 0x537c39ef, 0x4912b0fe, 0xccaf21be, 0xb128291c, + 0x4c20de6d, 0xb458d648, 0xf5b53504, 0x3889cab1, 0x8d4365fd, 0x68968788, 0x839504a7, 0x8ddbb65e, + 0x74a68fc3, 0x31eba2d1, 0x4f5d2dc5, 0x4eb0236b, 0xd8e1ee00, 0x490fb31b, 0xc6c4379a, 0x66d865a7, + 0x655f4c6a, 0xf09304cd, 0x101a156c, 0xeb9b0231, 0xfb24d143, 0x57629a0a, 0xb0c30ab6, 0xb54274fb, + 0xc03d818e, 0x7ae789d4, 0x156974fc, 0xdcbc657b, 0x54339012, 0x322a8a4f, 0xdd47ae85, 0x8f6a1bda, + 0x145eec07, 0xe5bf58f1, 0x92869b38, 0x2d5df4b4, 0xc90a784a, 0x76ef14eb, 0x92f50830, 0x9689f442, + 0x55425d97, 0x3d5651cc, 0x3d4d1b7a, 0x11070b61, 0xba61429b, 0x725281e3, 0x1629554b, 0xb650f242, + 0x79ad3d08, 0x8e6b9bf9, 0x2d8c7c76, 0x3f05b206, 0x7e732163, 0x3e43d2fc, 0xb26f4268, 0x28609361, + 0xfa201b8a, 0xbf42691a, 0xef8751b0, 0xa2ae8705, 0x6417e136, 0x2f602020, 0x66a42c28, 0x5e4710e8, + 0x1af3822f, 0xce1c6c14, 0x34efc7ae, 0xc0eec05d, 0x8cba6ca6, 0x943624b6, 0x0d06ec26, 0x65c767c5, + 0x72c950ba, 0xc386df4a, 0x6f973653, 0x35044245, 0xfb484510, 0x772941b8, 0xa8213632, 0x59a634b1, + 0x0d816788, 0xd05970e9, 0x769fd7b5, 0x5f25a453, 0x5b0a130e, 0x2753f540, 0xaf4bec80, 0xb7465239, + 0x02ca06bf, 0x8c5bd29d, 0x1eb4c67d, 0x7d64e33f, 0xdfe04ffe, 0xa08a5fcb, 0x40e4434f, 0xcf75f231, + 0x221cefc0, 0xc36cb6d3, 0xd0ea2be9, 0xaac0e9a1, 0x50833d21, 0xcb0cf2d1, 0xf1ff1a9c, 0x0781dd8a, + 0x76b40b56, 0x134b2840, 0xec7ecaee, 0x0cc7f1e8, 0xd3ba8edc, 0x983ba589, 0x6b1aa4b9, 0x3dc3ef50, + 0x04dfbdd5, 0xf87949f8, 0x9822c1ef, 0xff58cfea, 0x59338078, 0x6c496687, 0x9e9188cd, 0xa0e62946, + 0xdc766feb, 0x6e937d53, 0x143464bb, 0x2279c052, 0x80e72cc7, 0x1e461338, 0x64c4f70b, 0xaae9151e, + 0x248df566, 0xf14c9255, 0x36ddb73b, 0xe5333a1e, 0xb8862cb5, 0x1bc32733, 0x8806be2e, 0x91438582, + 0x8b52fec3, 0xb72ae8ee, 0xc760c818, 0xa4dd7e49, 0x68c02692, 0xff376251, 0xa29af0cb, 0xb63ef0ef, + 0x15a8b420, 0x70b81c9d, 0x6996469a, 0x52d738f7, 0x95d60679, 0x600ad5d6, 0xcd4d8f6d, 0xd980168b, + 0x2b7913fd, 0x92a19ed8, 0x91e20cb6, 0xe0470998, 0x61c806ad, 0x2cb4ee4a, 0x7b7ba4ae, 0x0d6f18eb, + 0x2c2a5279, 0x3ea28e15, 0x2fc726a9, 0x161a7bfe, 0xc588cc15, 0xa57f459d, 0x100911a5, 0x52b4d252, + 0xdd48cc91, 0x9899500d, 0x50f1ddd8, 0x4cfaf759, 0x4cb3c17c, 0x3083507e, 0x18881025, 0x5faf45f4, + 0x0f8532dc, 0xc7cb4dfc, 0x5a453f55, 0xd9170056, 0x3e7ba2cf, 0xd0a7f6a1, 0x60827d52, 0x0da8fd6c, + 0x66d0f7ec, 0x092e20aa, 0x44d33fff, 0xc7ca19ac, 0x4a060a68, 0x2b5479e1, 0x018c4e68, 0x724cef06, + 0x519bac9e, 0x737bae95, 0xf8816dff, 0x26c379cd, 0xcfd60ab4, 0x413de7bd, 0x94bd4d0d, 0x855226a1, + 0x75744ef1, 0x939f505f, 0x05e7beee, 0xee74237f, 0x8201ea98, 0xed8d57e3, 0x878a5d47, 0xaedafeef, + 0xba854333, 0x1ef5d85a, 0xf986c474, 0x2582b433, 0xa96aec58, 0x2078c899, 0xf4135e05, 0xb1837f34, + 0x52ed63d1, 0xb0f5cff6, 0x6af64860, 0x4145490d, 0x88ecfa2b, 0x34112084, 0x660734ed, 0x3d11ff6d, + 0x5a7bc1ea, 0xc4d95bee, 0xc4876dba, 0xd7899855, 0x257d1ad8, 0x30003d3b, 0xec592fe1, 0xf3ff23c1, + 0x3ac6326e, 0x413936c5, 0xe7c7ffe0, 0xec3a11e1, 0xc38fbcb5, 0x0f198825, 0xd1bf3d50, 0x0e07706b, + 0x00b0ba06, 0xb0534a40, 0xb5f74f28, 0x34d99a0c, 0xd992a873, 0x796460a0, 0xd24aa8bc, 0xf4c741f4, + 0x41ec8338, 0xb5f6aae0, 0x4e7b02e3, 0x608002a2, 0xa13265aa, 0xda26eac9, 0x0258f1d0, 0xfe218d91, + 0x2a6a0ccb, 0x65b54414, 0x40b1003a, 0x4d2c832d, 0xb4f70f26, 0x84776095, 0x18a13a95, 0x6122dadb, + 0x0f7991da, 0x88ef6759, 0x8d181a52, 0x04c40c61, 0x0e4e534b, 0xc7c8b23e, 0x23b06705, 0x052b9149, + 0xb789ab0b, 0x526f22b8, 0x1547bdc2, 0x959a298f, 0x0523b7a1, 0xbebc341b, 0xe3539293, 0x76abf3e7, + 0x9dc25384, 0x635163d2, 0xf128f16b, 0xa797c121, 0x8974de93, 0x4d600c72, 0xc0f87e6a, 0xa2d1d43a, + 0x9ca5d09e, 0xaea2145d, 0xe49cc0bc, 0x4a1ea5cf, 0x9f2cbbfe, 0xf558af8c, 0x882d1d9d, 0x9b7d9ca4, + 0xc2881033, 0x0e3c2dd8, 0xbf3f824c, 0x6be302e1, 0x008db935, 0x54ef06e4, 0xbba30df4, 0x905d627b, + 0xa977be2a, 0x39b6402a, 0xac281c84, 0x6ce8d78a, 0x25cfcbc0, 0xc0937971, 0x12281306, 0x00c30566, + 0x5b3fea5d, 0x2d94d0f2, 0xc60daa5b, 0x8cea7e05, 0x25f38bca, 0xd3a058b7, 0x286ab55b, 0x465222b9, + 0xe1f6aa9e, 0x24f7b314, 0x76c163d7, 0xe9c98a8f, 0xede3ad22, 0x34b8dc25, 0xdc0fe020, 0x76362263, + 0x748f35e4, 0xdb45f9c8, 0xb6267791, 0x8b8aaada, 0x537059b5, 0xe3ed1488, 0xb9b50869, 0xc0e4b43c, + 0xb69ffa4d, 0xf541703a, 0xe27d90fa, 0x166e1106, 0xc4ef7a55, 0xf30a300d, 0x2b451408, 0x6e7ac2c6, + 0xec0c03c8, 0xfa21968a, 0xdd819299, 0x508084f5, 0x6889b09b, 0xfc96f47f, 0xbaad9de2, 0xb4f787c6, + 0x71e725fc, 0x669393b5, 0x08c96dcc, 0x6251255d, 0xca5c8bb5, 0x227eb4c9, 0xfdd3a8a5, 0x2fb38c99, + 0x283c534b, 0xe87b3b0a, 0x70f7dbc4, 0x13e2719f, 0x4e9b8c2f, 0xaa451b43, 0xd6719115, 0x881cb619, + 0x377f273b, 0x3140d1d6, 0x198ba618, 0x5fe349da, 0x76cc7024, 0x5b2a517f, 0xc19cf9e1, 0x3a12f0e5, + 0x2a27ef32, 0x1f732c1d, 0xee360263, 0xa7a0c9a0, 0xdda3e291, 0xb6a97489, 0x3e2c8f90, 0xb8cfd16c, + 0x46da27b3, 0x9703a9ae, 0x92ea676a, 0x647a07ba, 0x805435ba, 0x6abdedaf, 0xca797035, 0x24406348, + 0x14581130, 0xf2776850, 0x62b1b1dc, 0x691d75ef, 0x804040ca, 0x0c2bc8de, 0x74a829b4, 0xfe55f26c, + 0xf35a1aa2, 0x5356f0ad, 0x6387ae83, 0xd32f3375, 0xb265a299, 0xcd557285, 0xce3a1526, 0x7bb737bc, + 0x16b0e27a, 0x09eb403d, 0x90ccf09a, 0x4407cc1b, 0x7b90d172, 0x8a9e19a3, 0x7741dbbd, 0x25cbb763, + 0x800bfaed, 0x4641a537, 0x7d7c4ac3, 0x10fbb6e0, 0xaa2bdfb2, 0x2c17a5e6, 0x77cb938a, 0xd9d0e07d, + 0x9f125302, 0x3285fec1, 0x655eba71, 0x1593c918, 0xbdda715f, 0x43201244, 0x1bb95399, 0xc2997e81, + 0xf564c224, 0xb3eecac6, 0x646f1dc8, 0x7dda778b, 0x1cc0bfc7, 0xf3176577, 0xd0f42ad2, 0xe5921b63, + 0xef2c335e, 0xa13d31d1, 0xc17ee638, 0x91599137, 0xcd23856f, 0x6e569405, 0x7cc0de77, 0x7f233e70, + 0x29eb7172, 0x51aa9104, 0x37edb985, 0x1d1c176c, 0xfb68c51c, 0x0f3a9c16, 0xd94c0ada, 0x63094959, + 0xd17a290d, 0x0efb2ac1, 0x541c6692, 0xda9dbf15, 0x88f009a0, 0x5b47b440, 0x46ae4239, 0x9ad7c2c8, + 0x01311afa, 0x6823240d, 0x47e5b5b5, 0xb6d38c43, 0xdc88092f, 0x9dc9c999, 0x4e84284c, 0xc9b18d56, + 0x69f37deb, 0x9775b6f2, 0x5a4852ed, 0xdbf21f1a, 0x5ebda774, 0xfad76f85, 0x4280c264, 0xd92adaa8, + 0x8665efcc, 0x5467337d, 0xc786338b, 0x521c0c83, 0xd5f0da58, 0x5dd0157f, 0x520eab0f, 0x79f33224, + 0xa34dc094, 0xd58cabd8, 0xf44f6631, 0x888ce19b, 0xa8b8e96d, 0x24377eee, 0x504bc979, 0xe5c4c9ba, + 0xefd0bcef, 0x745fa328, 0xe53dbf5a, 0x451f97f2, 0x56d66528, 0xf652d256, 0x22917f51, 0xb1f56068, + 0x47285d8b, 0x278384a6, 0x3ff6ec35, 0xe0503bf2, 0xede9d536, 0xb946dad3, 0x73e9e404, 0x796f4c5d, + 0x25084762, 0xc80a08c2, 0xed5f1276, 0x12dfa63d, 0x0ec925ed, 0x696dff9f, 0x23e30e95, 0x7d834063, + 0x76a06406, 0x7c263a71, 0x3e441f60, 0xeb93d99a, 0x902a946d, 0x94e4068d, 0x508fa1ab, 0xc595c80f, + 0xf9132977, 0x33494fab, 0x3123e06a, 0xf4a90d1c, 0x4e2e17a6, 0x26ae68e6, 0x280a5bc2, 0xa641b4c3, + 0x93886e78, 0x3f373dfc, 0x871f386e, 0xdd14815d, 0xe5792ef0, 0x8d256aec, 0x2df7d95f, 0xdbb6b689, + 0xf51074da, 0x20244c43, 0x31ea7959, 0x3a2e2549, 0xfff8f54d, 0x48cef4a6, 0xf1b039a9, 0x7f670499, + 0x565fc4fa, 0x4a07c8aa, 0x3801516c, 0x1bc346b5, 0xc045b6ec, 0xc2455862, 0x1fa99298, 0xd91313d1, + 0xf6940660, 0x8b51aea7, 0xf639701a, 0x87d154ce, 0xe43b321a, 0x3c4f93fd, 0xd7bc740d, 0x211f32b2, + 0x910e7a68, 0xefd7a7dc, 0x105b6ac3, 0xe959309e, 0xa85d0837, 0x59aecfd2, 0x33ce8c25, 0xcf1fdf32, + 0xe65dcbc2, 0x868becc1, 0x1094251e, 0x5120f7fb, 0x7e8ff046, 0x105ebca4, 0x0cd7b0ce, 0x70a1af93, + 0xf3b7da72, 0x51c77daa, 0xb8aa15e9, 0xfaabbdc9, 0x7ce6d67d, 0xb818bc0b, 0xde45f9ea, 0xce04a526, + 0xd05a4e60, 0x71965def, 0x777abd3c, 0xdc21ff19, 0x358fe316, 0x47db5f62, 0xb47a7462, 0x42aedb05, + 0x7777cfc0, 0x258974d8, 0x366ef87f, 0x2b014015, 0xd21bfc3c, 0x41a778c9, 0x24fa6d63, 0xaafcc288, + 0x97038139, 0x46ee7de8, 0xe294227f, 0x9c12cd89, 0x9ee775bf, 0x10db2257, 0x5f9302af, 0x27f31697, + 0x6111c0cf, 0x141ee6dd, 0x22658241, 0x24fbfd4f, 0x11d6ce28, 0x10285f13, 0x2896b443, 0x852ab04d, + 0xc4856c3a, 0x362bbec7, 0x49c25ee1, 0x6990cf39, 0x61a3c85b, 0x98207cdd, 0xbc027307, 0x0f80f6c0, + 0xf7410772, 0x4fee263c, 0x0bab0e97, 0x7a7cad54, 0x82b94496, 0x8d3c1d0c, 0xab45b83e, 0x642487b8, + 0xe1027734, 0x4fb9f81d, 0x0bb748e6, 0xa46a749f, 0xd7fe6250, 0x2801a758, 0x3d089e6e, 0xe82888b6, + 0xec66405d, 0xb28a0a70, 0x878062ec, 0x02766752, 0x8fc182e3, 0x9aabcffe, 0x5b0c0734, 0xded8110c, + 0x1fe632f6, 0xd68aabc1, 0xdc8f6542, 0xedef8757, 0x1227cdae, 0x31cc37a2, 0x1758b71f, 0x9da2eaf8, + 0xe30e5c09, 0xac97c8a2, 0x80eaaba3, 0x86f81900, 0xd3578a77, 0xd60c3d81, 0x7e9af895, 0x00703403, + 0x9771143d, 0xf7dee957, 0x0a973f6d, 0xebe88690, 0x1f049238, 0x2c086b1e, 0x3c93b42f, 0x2e7aec15, + 0x49e73060, 0x094c147e, 0x73999fb5, 0x928195c1, 0xcf4649e4, 0xdbf861de, 0x3d67405f, 0x7c80b528, + 0x7165e82f, 0xb9700458, 0x87970919, 0x5bb493c0, 0x443fd292, 0x8e73a7a2, 0x19891e10, 0xfb0afd40, + 0x85cbae77, 0x7ce68099, 0xebe21a69, 0xb910fa20, 0x70b2ed62, 0x96007d2a, 0x35192dfc, 0x660d1372, + 0x08e13960, 0x91f71fb7, 0x5736d571, 0xa22177c1, 0x9e37f19e, 0x55ca9e18, 0x72d91fb7, 0x506fcae8, + 0xca9b6baa, 0x6bb6241b, 0x0d61cad5, 0x12beb533, 0x29e72209, 0x859cd3fb, 0x5ce26915, 0xce87a861, + 0x8e326ef4, 0x8d4cbae3, 0x6d696056, 0x4f53a4b4, 0x3443375d, 0xa853ef27, 0x3df97b9e, 0x2b40980c, +]); + +pub const VENDOR_MLDSA_KEY_2_PUBLIC: ImageMldsaPubKey = ImageMldsaPubKey([ + 0x07c83c99, 0xdc33f5d9, 0x6e0ecc2f, 0x84af5046, 0x6c03db81, 0x296c5f6e, 0x5c6c880d, 0x75764ada, + 0xa342b4a7, 0x10873e1e, 0x623b91f8, 0x63e130ae, 0xfa6afaa4, 0xb6e10e79, 0xa894c04b, 0x5b830f54, + 0x6e90b4b0, 0xd906727b, 0xe2556487, 0x571042d2, 0xa3ab6f5e, 0x0823d2d1, 0xc6f508a5, 0x546c1f0b, + 0xb52d5af0, 0x10b607fb, 0x24683dc6, 0xfd72006f, 0x583751db, 0x07a3050f, 0x107905f0, 0x1491b1af, + 0x01edc645, 0x3c76205e, 0x7ae33aae, 0xc7dfb3d3, 0xcb11d9a8, 0xcdb40f6d, 0x3c2fa4bc, 0x3585a211, + 0x8cbcee84, 0x07f7b04d, 0x93be263a, 0x93c67ab3, 0xc50131a4, 0x95808ee3, 0xae413692, 0x895f1e23, + 0x4d086c0b, 0xa0c70d4e, 0xf8d6a98c, 0xc8594755, 0xaeda7243, 0x4af3a7b8, 0x4f602e78, 0xb49db365, + 0xe81fef63, 0xb617d6e6, 0x92cb2a57, 0x170b5462, 0xf2748fa6, 0x65e2610f, 0x1b13eeab, 0x9b140955, + 0xd1b22c0c, 0xb494f85c, 0x1ddc3806, 0x694899d3, 0x4675494c, 0xf022233e, 0xf12fffb6, 0x4c15e927, + 0xfba1b9bc, 0xa7d8ea42, 0xff6a4c8a, 0xc67257e0, 0x3c2be8db, 0x9af95974, 0xb9540d69, 0x1576aa2a, + 0x53fab7fd, 0xd05226e6, 0x8ed640b1, 0xe22d142b, 0x396e4351, 0x27509b36, 0x11f38bab, 0x8a7e894a, + 0x142501d2, 0x4377348b, 0x2065aa1e, 0x71020016, 0x5a8cf2cb, 0xd3ca7945, 0x62579051, 0x3c8e3739, + 0x6718f26b, 0x8422e75c, 0xfb7c7c08, 0xfd42c3fb, 0x75cccfbc, 0x08346b17, 0x9973d63d, 0xdb71e209, + 0x07d51bbc, 0x74d2af89, 0x9916b8ec, 0xfdbba63c, 0x8f0baab3, 0xd268fd2f, 0x4651c8e3, 0x1853d56c, + 0xb2da7a1c, 0x1853406d, 0x9083a417, 0x2188e628, 0xd8fa0f9c, 0x691b7039, 0x347b205d, 0x582e7ecc, + 0xba5b85dc, 0xdc758531, 0xa6ea8e06, 0xd94298a7, 0xb3fc738b, 0x586a639f, 0x3c55bf0b, 0x29943634, + 0x734356d4, 0x3c09e30f, 0x6d30d1a5, 0x8114f475, 0x54169efc, 0xce6ac496, 0xf691bcdb, 0x738c17cb, + 0x4c597c3c, 0x435a3496, 0x2655207b, 0xfcab86cf, 0xaf2657d3, 0x876d6512, 0xe0cdc7f8, 0x50730281, + 0xa50542d0, 0x5e68aa5a, 0x3a12a5f9, 0x687ea850, 0x44d99244, 0xc548a11f, 0xd0e3e746, 0x3b10c333, + 0xf7c6ad1e, 0x90239694, 0x4f079565, 0xc40cb2c0, 0x2222fa1e, 0xd41a93c7, 0x62385f59, 0x815f1ee0, + 0x27bd9075, 0x002e3693, 0x76b828b0, 0x84522853, 0x763378cd, 0x9835d9eb, 0x60d4bbb4, 0x49263676, + 0xb2d70385, 0xbb086a8c, 0xa8ff46c1, 0xd3c254a9, 0xef9e4b32, 0x85706406, 0x502cdbf4, 0xa1e7afb7, + 0x4855441c, 0x8525e291, 0x51bccdc7, 0x291b33b8, 0x0ef08169, 0xb9787e66, 0x961e11e2, 0xd343519e, + 0xa9008942, 0xe182c54f, 0x283aba9b, 0x5f96c03d, 0x2cf80e73, 0xa37c354b, 0xfe5eae25, 0x76fc7d52, + 0x47570e5a, 0x8204c2bc, 0x52ef6927, 0xfee4cb01, 0xc715bf31, 0x22015955, 0x854e3a2d, 0xa6eb3115, + 0xd93f4040, 0x38aaffc5, 0x2b6864c2, 0x8122ef23, 0xebce48a3, 0x3d781fe5, 0x1d02320b, 0x88a55239, + 0xc29a4d31, 0x544012e6, 0x416f9a9f, 0xe8a19925, 0xb5b9d9b7, 0xb19002e3, 0xb47014b6, 0x4351216f, + 0x2d83dc39, 0x4bb27c82, 0x251f3714, 0x98fc68f8, 0x4e5d084c, 0x6310c7ba, 0x70451f9b, 0xac51e071, + 0xad61187c, 0x80df8444, 0x4eb3e552, 0x82bcfa26, 0x756d8dfb, 0x08c5d737, 0x328199be, 0x3ffd33e8, + 0xcdcd65e0, 0x6e10aa8c, 0x548ecc82, 0xdc03ccc4, 0x003a59b6, 0x1b060ec2, 0x4d101965, 0x2af1e033, + 0x42ed5022, 0xbbc8bffe, 0xf8b64f79, 0xe30ca87e, 0x1e983561, 0x6ee36285, 0x2dbf21ee, 0x41b1dd1f, + 0x6b0b0d1d, 0xc5a20921, 0xc5c23361, 0x059aa65a, 0x97ddee36, 0xcee71039, 0x2a1301e4, 0x6a2309bd, + 0x0fa45c99, 0xd4f71b08, 0x23d6e258, 0x3e6b214e, 0x829bdd0d, 0x1d72d73b, 0x9ba0e86e, 0xe7f87eb2, + 0x41e87590, 0x8a8eeb39, 0x9ba98860, 0xb0563236, 0xc62d217a, 0x2131e078, 0xdfd324d4, 0xef3de685, + 0x3402f976, 0x98b33b77, 0x57cfa1d3, 0xe6e02c00, 0x74cc8bf1, 0xbde8887c, 0x835093f0, 0x2fcbea05, + 0x4b49817a, 0xb2049ea4, 0x06139c19, 0x8ec9ffc7, 0x9757e7d3, 0xcfc1ac8d, 0x202d054f, 0xaf296f53, + 0x457a8ba2, 0x9765a855, 0xc5bedc88, 0x3145f4ec, 0xf9c54d41, 0x43a5a9d2, 0x5ecb1dd0, 0x3306eda5, + 0x44ca1571, 0x1d930f92, 0xb9a15510, 0x7ce2080c, 0xca9013c7, 0x9d128f82, 0xc5cbefb1, 0xa1bcbb66, + 0x9551b03f, 0x876afefd, 0xaabf86fb, 0x9bf9e449, 0x689b95da, 0x4b7080c3, 0x9d81852e, 0x8b472915, + 0xbed30dce, 0x67e061bb, 0xaa926446, 0xb8c5d982, 0xe4be808a, 0x53a556e8, 0xc8d148c1, 0xd590965a, + 0x35033c0c, 0x29a34821, 0x06bac80d, 0x5e6e54e8, 0x4ef43b51, 0x8902966d, 0x783cf817, 0xdd4ff344, + 0x3094509b, 0xa6f2a6a9, 0x18e3b8d7, 0x78dd43bf, 0xac6e2f4f, 0x13b73976, 0xaea35976, 0x0e1a01de, + 0xd6496329, 0x44efff17, 0x63955a68, 0xa930be45, 0xd5bc6c6b, 0x05164772, 0xb6615b60, 0x717f0970, + 0x9fac9a5b, 0x9c43ab8e, 0x98bcf5f7, 0xf9beacf2, 0x1cc85030, 0xf089dbc9, 0x376de1d6, 0x3d542381, + 0xbb44abc3, 0x0798778f, 0x2369e57d, 0x8648f9e7, 0x1b2f5d3e, 0x54dc0454, 0xe8278f4c, 0xd3c6b14b, + 0x9a57ee57, 0x4c31414d, 0x07f7cb81, 0x6be02a43, 0x8eb4f66a, 0xd3415ed6, 0x6ddf65dd, 0x8fa57974, + 0xf15f516c, 0xb84c3561, 0xdfa9f65a, 0x3b28a135, 0xded84f3b, 0x87dc9d78, 0xc7d9d88a, 0x34c85f50, + 0xecdec48b, 0xc9751ade, 0x2a75ff1e, 0x11a01fc5, 0xc795825c, 0xf3d44262, 0x1ac7ba61, 0xa410f3d0, + 0x3f0909c9, 0x66ea26e4, 0x65e1b3c1, 0xa5a8ab43, 0xf74868bc, 0xeb5818a0, 0x7c4aebc4, 0x5f3d6a51, + 0xfed0b778, 0x2306575c, 0x698916dd, 0xa0a886b6, 0x1f9773ec, 0xcf2d638a, 0xe311e724, 0x402a4f71, + 0xc4d65151, 0xc2aaca41, 0x90466529, 0x48acf35d, 0x6d6e8a4f, 0x07a4af2f, 0x75b7c335, 0x5e653e28, + 0x0a9f08c5, 0xa0303b7d, 0x610c0934, 0x64640614, 0x23b78b99, 0x41e0328f, 0xb90b7393, 0x51086273, + 0x6e58f1b0, 0xfae31fc8, 0x753c4a46, 0x6661472e, 0x71c15ee9, 0xab592f08, 0x4e8051fb, 0xa250eadc, + 0x3779f92b, 0x29d5998f, 0x19a8be11, 0x922feb0c, 0xe848f87a, 0x4b456950, 0x90e50640, 0x3d583a4c, + 0xb8e13ff4, 0xa3ce79a3, 0xbf3062f7, 0xf8dd0b43, 0x4e025260, 0xc0c9294a, 0x7385a6b7, 0x31c63aa6, + 0x73cc66c3, 0xbf525646, 0x7b40151a, 0xdcbab0f5, 0xdb607a7a, 0xa335db6b, 0xf60a95d5, 0xef8608e9, + 0x4a4a89d3, 0x12e221a8, 0x527a922c, 0xdf596f81, 0xacbda3f2, 0x92d4881c, 0x9ef51c38, 0xea6bf0fc, + 0x7b805b28, 0x90f126f0, 0xc6a0e5a2, 0x3c0de948, 0x021d455a, 0x29cd1fb8, 0xae5b65a9, 0xdeca1834, + 0x18394dc7, 0x8b26d7ab, 0x4d084017, 0xa91b097a, 0xdab043e4, 0x73da33c4, 0xa4b2b473, 0x3d5db2b0, + 0x78b2601a, 0xd057e29f, 0x89ec2abe, 0xed72417d, 0xf919eb5c, 0x9d79f235, 0x3e99e875, 0xc8461e70, + 0x4dc7af0a, 0xa6c27bbe, 0xe11ea07d, 0xc8b18eb5, 0x4f7c51cf, 0x014b3504, 0x27b196d1, 0x1c2fb08b, + 0x80153f7c, 0xa8413134, 0xdb0c703c, 0xacac7994, 0x12bd9b9a, 0x7d0df264, 0x6116a62f, 0x4937007e, + 0x33f30ec7, 0x0a364ae5, 0x6a0bf329, 0xb5c34c03, 0xcd44759c, 0x3188a70c, 0xce710f68, 0x9b26bfae, + 0xea2559f8, 0x30a009af, 0x869a60ce, 0xedc6f6a0, 0x603334b4, 0x0f514e42, 0xd94c193c, 0xe80a789b, + 0x84ab1d8c, 0xc120c2c5, 0xc19c20bb, 0xc3c1abfa, 0x671dfebb, 0x01944ca6, 0x3e068203, 0x6442c3d4, + 0xcc1e2e86, 0x7d3e01e7, 0xf06f77c8, 0x1f01f847, 0xca2fa3dc, 0x4d0a2979, 0xeea17d5e, 0x71c4332d, + 0xf2ff51f3, 0x780751af, 0x14b58f54, 0xb65c18d5, 0xbad2f30e, 0x4d58ff6a, 0x9f0f9e09, 0xe3241375, + 0x97e8d691, 0xb95f409e, 0x3ff6f344, 0xfc8b5f22, 0x19b936be, 0x70698921, 0x957ee707, 0xd92ff8e5, + 0x0ec85563, 0x4d3a4002, 0xbd5584e5, 0x8ec3855f, 0x4ae664e0, 0x5eb129a7, 0xc464bc87, 0x831a59a5, + 0xba3e60a2, 0xc9530753, 0x4f38f4cc, 0xcf56f3c5, 0xde62fdbe, 0xe6350081, 0x6348989d, 0x5fa1f603, + 0x3b1bff62, 0x106dc966, 0x58658cb1, 0xeba78ab5, 0x8a33ad01, 0xf34efcda, 0xfcdd8253, 0x8d02b720, + 0xa5bc211d, 0x90edcb91, 0xc9960959, 0x779221e5, 0xc545ec8f, 0x83cf2a86, 0xf955f7b7, 0xa003bb01, + 0x7aef9d77, 0x31528423, 0xb5bb1657, 0x8352fd88, 0x2ae5f46b, 0xc970eb8d, 0x158eb114, 0xf3288b72, + 0x091ef04f, 0x5d72829f, 0xd7c80056, 0x484fab0e, 0x6ca63ee8, 0xceaff55b, 0xf2f8d0e3, 0xacd240c5, + 0x176f9fd6, 0x383ea584, 0x49d65815, 0x3125d989, 0x320fab5d, 0x3ad62092, 0x47c8ff7e, 0x862d8b37, + 0x377f1927, 0x3156943e, 0x86fbaa79, 0x90399328, 0xf426e613, 0xf214b36a, 0xde93f64a, 0xe01947ed, + 0x9d7de613, 0x9d763456, 0xc7684378, 0x0db54db5, 0x466218d7, 0xf2a8b97c, 0x107ae4ff, 0x29f06bd1, + 0xac5a18b8, 0x67013353, 0x11b4ce13, 0x1edee77c, 0x64653649, 0x75e72943, 0x49171f52, 0x2a57bbc3, + 0x942cc8c0, 0xfc53cac3, 0xa2668f20, 0x8ae807fa, 0x6be0d238, 0xebef9583, 0x28db3df9, 0xb7c47d35, + 0xa1a323aa, 0x09138c84, 0x15f56353, 0xe421d405, 0xc6e3239e, 0x960ebf8b, 0x27b97fc2, 0x15d2d2a6, + 0xf930fde9, 0x42411fd0, 0xd448d1d4, 0x7128f482, 0x24b3f60d, 0x413336c0, 0xc423cd73, 0x8dbe6a2b, +]); +pub const VENDOR_MLDSA_KEY_2_PRIVATE: ImageMldsaPrivKey = ImageMldsaPrivKey([ + 0x07c83c99, 0xdc33f5d9, 0x6e0ecc2f, 0x84af5046, 0x6c03db81, 0x296c5f6e, 0x5c6c880d, 0x75764ada, + 0x4a3334a8, 0x726134b0, 0x74a15681, 0x94a42dc7, 0x0d745dbb, 0x93dd300d, 0x600551b5, 0x8fb992a0, + 0x9666a1af, 0x017fc451, 0x7a8f592f, 0xb9837df5, 0xe8ccacb3, 0x4540f3a9, 0xec8080d4, 0xb138a8f6, + 0x549886f2, 0x1daf3cbb, 0x7205d797, 0x5a0958e2, 0xe4f8eca3, 0x1f095c39, 0x0054d33a, 0xa8fc5faf, + 0x4bb2448b, 0xc40440c8, 0x0d812222, 0x0a210a11, 0x37709b32, 0x60dcb248, 0xc0104220, 0x89919a46, + 0x09489480, 0x81208cdc, 0xb44d8282, 0x30239821, 0x5b08325b, 0xc490c8b0, 0x8140c044, 0xd0281052, + 0xb22c9908, 0x81834861, 0xda366640, 0xb6056236, 0x71924081, 0x13b48520, 0xb44dd2b2, 0x809a0892, + 0x0c130d08, 0xb3811234, 0x62013264, 0x238050d3, 0x90841081, 0x64814065, 0xc98260a2, 0x8005da96, + 0x25e4a60d, 0x1216045a, 0x28009438, 0x4e194480, 0x21922c54, 0xa2250492, 0x20849028, 0x0988441a, + 0x316488a2, 0x00c88840, 0xa11029a1, 0x364cc884, 0x44cc2832, 0x9882618a, 0x400c50b0, 0x04a19689, + 0x04874c09, 0x120cdc10, 0x8459c091, 0x24262e09, 0xc711d490, 0x3154b684, 0xc2a48c43, 0xa4705010, + 0x2d5a8869, 0x8aa601c9, 0x028a4c38, 0x5222194c, 0x14c32061, 0x020e88b4, 0x8cc34611, 0x422665e4, + 0x2405dc32, 0x21d9966c, 0x64163089, 0xa0001843, 0x9211184c, 0xa0c651c9, 0x44044396, 0x00092592, + 0x121264a4, 0x24492001, 0x31099370, 0xa31666e4, 0x90702028, 0x8c501824, 0x02456a82, 0x382ad120, + 0x2ea4002d, 0x24400cdb, 0x022a49b6, 0x31810830, 0x00470c08, 0x872d8832, 0x5018a228, 0x094668a0, + 0x0231c4b4, 0x2402b951, 0x531291d9, 0xb40cdb38, 0x218a9605, 0x1aa08401, 0x21611a87, 0x710b1900, + 0xe0b40dcc, 0xa624d908, 0x2d440842, 0xa3144504, 0x14522218, 0x02231150, 0xd4824d13, 0x304dc140, + 0x81649409, 0x9a9840db, 0x2826a018, 0x8611a011, 0x63b2019a, 0x926cd346, 0x06238948, 0x231612c3, + 0x14728804, 0x2e10342e, 0xd944309b, 0x328d2427, 0x30433400, 0x1a324920, 0x439113b7, 0x04a1904d, + 0x09348190, 0xa81050b2, 0x4c4a248a, 0x9b268884, 0x88801381, 0x611a9449, 0x1b958d03, 0x21228ab4, + 0x2504b90d, 0x49822da3, 0xa269d108, 0x82243289, 0xc234291b, 0x31415a22, 0x44591091, 0xe2180024, + 0x845184a2, 0x21d41481, 0xc1346620, 0xb86022b0, 0x884a248d, 0xc1b81123, 0x80218ab0, 0x21e48651, + 0x02c92590, 0x08244806, 0x10204224, 0x5ac68814, 0x044a1821, 0x8e094750, 0x01b68401, 0x37880039, + 0x44624400, 0x99b27112, 0x120c9092, 0x25214920, 0x11367124, 0x3402e412, 0x0e1aa268, 0x1c079108, + 0x047012a4, 0x6099a485, 0x0c334681, 0x96499c42, 0x68403052, 0x09428c5b, 0x2602e004, 0x2e232785, + 0x103468d2, 0x902c5106, 0x12089391, 0x0ab80dd9, 0xc6011c14, 0x05210181, 0x08950d62, 0x06018316, + 0x8d61b20c, 0x5920481a, 0x38419ab8, 0x85449451, 0xc2c48889, 0x0831c012, 0x09912666, 0x52100924, + 0x452181a6, 0x48449411, 0x23002603, 0xb0601098, 0x4c824880, 0xc0a64183, 0x004c9a84, 0x81d24804, + 0xd18825d8, 0x18089118, 0x82e0c201, 0x5222645b, 0xa289cb28, 0x88cac864, 0xe114500c, 0x42861841, + 0x8821278e, 0x909470d8, 0xa22ddbc6, 0x2c88464d, 0xa4166063, 0x28600325, 0x6d9a0609, 0x13484943, + 0x80901409, 0x621b9665, 0xe0c8310c, 0x05404842, 0x001a3792, 0x14454cc0, 0x4032a328, 0x4e1c0904, + 0x5b220c03, 0x076c1a40, 0x0c08b34d, 0x9080110b, 0x9228d342, 0x49e4988d, 0x08c64164, 0x36801b16, + 0x4e249608, 0x14b10c93, 0x109088c6, 0x7011b844, 0xc010401c, 0xc6851112, 0x7262a621, 0x93484604, + 0x2962e146, 0x11112482, 0x24410822, 0x2960e002, 0x26d48491, 0x12042241, 0xa049e380, 0x8d58a629, + 0x10c7654b, 0xa26d1237, 0x10183340, 0x4c988980, 0x12880985, 0x4c011032, 0x5b146d58, 0xa08d8b06, + 0x42444810, 0x41a86d0b, 0x35891029, 0x8921c66d, 0x84c62921, 0x288e94c6, 0x44da004c, 0xa1b428a4, + 0xc4291937, 0x4220b82c, 0x823011c0, 0x0804c4a6, 0x4c002702, 0x1a876d5b, 0x84851c07, 0x06d01241, + 0x9c4484dc, 0x388d04a2, 0x05890661, 0xa300710c, 0x15311a19, 0x868a3230, 0x10060612, 0x91401893, + 0x20440204, 0x21267159, 0x404462b2, 0x91cbc025, 0xc8a24108, 0x26329b06, 0x6c81b865, 0x1002501a, + 0x11821815, 0x61584464, 0xcc926cc8, 0x144cd912, 0x518c260a, 0x531892da, 0x3246c186, 0x44d4b869, + 0x18035181, 0x36844808, 0x0013b288, 0x24a74c82, 0xc4054c12, 0x45a08461, 0x4848910a, 0x036a4832, + 0x6a9c4406, 0x4c906514, 0xc1404006, 0x4d942040, 0x108849dc, 0x228c8a20, 0x7061a425, 0xa216109a, + 0x26642089, 0x21134800, 0x14976402, 0xa3512225, 0x8d04c231, 0x8ba24dc2, 0xa46c4a30, 0x2d020551, + 0x134350d3, 0x128c23a6, 0x61811482, 0x0aa44149, 0xa8514344, 0x45591281, 0x94180619, 0x09119a06, + 0x651a130a, 0xc1320a1a, 0x972d0841, 0x309c366e, 0x40a66553, 0x264211b7, 0x6dca1060, 0x09c17023, + 0x88004800, 0x42021164, 0xe1b8485a, 0x840da410, 0x04c01052, 0x11274d12, 0x1030e340, 0x608b8260, + 0x1a174c50, 0x0665da12, 0x0d1c478d, 0xd4302e1a, 0xc4899418, 0x2e0b9428, 0x0b080a01, 0x982d49b8, + 0x4111a848, 0xd9b43003, 0x02610b27, 0x21c0002e, 0x890202e1, 0x344a50c8, 0x40d99450, 0x13084ddc, + 0x82901494, 0x69a3c664, 0x5b100611, 0xc02d1ca3, 0x099b3626, 0x8a345222, 0x42121124, 0x2ce39645, + 0x1848aa6f, 0xc51522a5, 0x855bd910, 0xed29a31f, 0xa54a35f5, 0x4db1ea53, 0x6b833e96, 0x6cf3317f, + 0xb27ebf05, 0xf07ea92e, 0xfa08fa4f, 0x6ab024bb, 0x1ae3cc38, 0x9538432b, 0x5794dac3, 0xa66ddb8e, + 0x7f637789, 0x75c7d114, 0x903dc4c3, 0x1c69add6, 0x2011624b, 0xb4b939d1, 0x57fa8b0e, 0x128a0bea, + 0x065f58ec, 0xbc9533bf, 0xd2ee18a3, 0x8ae6bd53, 0x4cee9e92, 0x4c1bdfb3, 0x030b14ca, 0xf0f9619f, + 0x06e13e51, 0x4ae5bcc1, 0xf5966181, 0x8c2c6e06, 0x1cf3b730, 0xb200cea6, 0xe9343435, 0x6848db78, + 0xb1483b38, 0xaefc1f60, 0xb7e0744c, 0xd5629c80, 0x2e12f3c8, 0xb66c33b5, 0xd3442580, 0x346dcecc, + 0x35c8a935, 0x3b5069a0, 0x34d040de, 0x1a84a682, 0x0303fb15, 0x6ad9ce58, 0x38d547fb, 0x2300b290, + 0x69f2e206, 0x8a56d258, 0x847f20ce, 0xa137c29d, 0x4e007b5a, 0xc5af7c9c, 0x5f069381, 0x4a8fac21, + 0xe066244a, 0xbb7747a9, 0x5e0be728, 0x9d3c666e, 0xc5e82cda, 0x6ceea613, 0x897895be, 0x458494dd, + 0x6c8f07d3, 0x63e46385, 0xb9125f82, 0x66b0d552, 0x8d7de2b2, 0xb71b3c51, 0x96f5d8fa, 0xf6cc2ac3, + 0x5bb05678, 0xafcdcb72, 0xcdae1866, 0xf63a6f26, 0x2fb21618, 0x54cf1857, 0x66af58f2, 0x9b3d4e52, + 0xe3132124, 0x21ca1a27, 0xdda816cb, 0x55b00a32, 0x13efcba3, 0xe06cc0b9, 0x7c9a784c, 0x5b223afa, + 0x4319900d, 0x6dbe18bf, 0xc30da952, 0xe8339399, 0x8a42c065, 0xda90702e, 0x137d9108, 0xf407f41e, + 0xa6a189b2, 0x51ef442a, 0x2e124abc, 0xd64c9be0, 0x5cd76f16, 0xd4072196, 0xd78a8c10, 0x24c0f83c, + 0x4a06af6f, 0x3fcbc196, 0x214fd45e, 0xca8b6191, 0x8d9b1fc6, 0xa5df161c, 0x50a0ff6a, 0x74d5f336, + 0xe1e784d5, 0xbe6053da, 0x41f695a4, 0xc6a0556d, 0x60233746, 0x5017194b, 0xb22ba1e7, 0xd39efd3a, + 0x6fa4320e, 0x30db2fc7, 0x46f69eee, 0xf730f67b, 0x94a66056, 0x1cdf4a4e, 0x1b68d873, 0x641925be, + 0xbac8cb02, 0x31f8da52, 0xb7d64d5c, 0x456bd81a, 0xf54b028c, 0x8d9fc1e3, 0x91ad8d57, 0x3159cb0b, + 0xd0d8dcc9, 0x208fd09d, 0x82e0c8aa, 0x4e4c93b6, 0xc2bd4d0f, 0xb0cc3381, 0x0938bcb7, 0xe35dbaaf, + 0x1d0668c4, 0x7bdbf29f, 0x81c46de3, 0x5c563804, 0xb8e1f6c5, 0xb03ca0f9, 0x6ccbf6f9, 0x11b6b175, + 0xcd11ca71, 0x75b05c5d, 0x536259a8, 0xfece8491, 0xb9401397, 0x834f27a6, 0x29216a92, 0xe4f9bec2, + 0xb075ebb3, 0xe6e3d33f, 0x1c7d2c5d, 0xb4c65412, 0xd7c85743, 0x7a05e794, 0x59fa1d9c, 0xe3378fcf, + 0x067d2577, 0x5b2cd670, 0x6980f25b, 0xdab1e514, 0x8dd7c978, 0x2db2df84, 0xa2f21b96, 0x4e316ef7, + 0x108be98e, 0x5ce927de, 0xce966b18, 0x4bc5e035, 0x4667517a, 0xc634dd0c, 0xf321f9cf, 0xe319b24e, + 0x9086ae2b, 0x7066e0e0, 0xe0adc482, 0x82458267, 0x66569fb2, 0x52947a7a, 0x89b7d6ee, 0xf8a1574a, + 0x27b09766, 0x8a0f73dd, 0x775a4936, 0x1d129a2b, 0x25c735ca, 0x752d4556, 0x344b0271, 0x110b4aa1, + 0x9e93441c, 0x1429eb43, 0xb61ee5cf, 0x7d2d80a2, 0xabe3c4cf, 0xb89a1e6e, 0x5adced54, 0x6cbc9b5e, + 0x2f823cf6, 0x9948ac6a, 0xdc5e3a3a, 0xf1643943, 0x0e3580db, 0xae4ca5a8, 0x10d966cd, 0xc52a779e, + 0xf2d22641, 0x3abca734, 0xe0fc28ea, 0x78931a6b, 0xab8f43e9, 0xcdf42bd6, 0x2d66e234, 0x2410bf81, + 0x6694c536, 0xda96e414, 0x379f8335, 0x497ecfad, 0x9d7d7c4e, 0x3ff861c9, 0x27ae006c, 0xe80c44b4, + 0xa3af465c, 0x8735a13e, 0x7f229bdb, 0x203060d0, 0x466c602c, 0x234f67b9, 0x52648793, 0x3e75fb48, + 0xdac64551, 0xaae4318b, 0xacf0f7ac, 0xc67afaf8, 0xae4d18a6, 0x15fbb1fe, 0x3163dbed, 0x7385850b, + 0x18150e8f, 0x1cca21c9, 0x2f14b9ec, 0x1bfae1c4, 0x79fd99df, 0x49c37494, 0x3cee27b9, 0x79974709, + 0x9ed1cee5, 0x5ecfc27a, 0x6840b565, 0x4ebf0c28, 0x444a93ac, 0x64bd2ca1, 0x82fbf849, 0x35dc7a6f, + 0x9b883838, 0x9f4059b1, 0x273396fe, 0x6f6cd3b7, 0xae154411, 0xa4bc878b, 0x24440c85, 0x0422c781, + 0x1e104384, 0x6e515c58, 0x47721fc9, 0xd7b220f2, 0x0c7b65fe, 0xc0c82b4a, 0x7a894728, 0xed9f5265, + 0xee30b0db, 0x607b84fe, 0xb9ef583f, 0xd47b603e, 0x24c40ad2, 0x2eedbb0d, 0x2677ace7, 0x17ab02f5, + 0xfdbe6cb5, 0xa5778de1, 0xf1f19036, 0x3817acf6, 0xc1e35f53, 0x7941a72a, 0x1ab88f5e, 0x2958f78d, + 0x4f9ff6ea, 0xc6c5daa3, 0x9561d9f8, 0x3323dce4, 0xf29156ef, 0x3e8f0475, 0x91e6eea3, 0x1114618e, + 0x43dce6ad, 0xc503f007, 0xe3dcb6c4, 0x7f75e7ad, 0x3b29ced0, 0x76db3863, 0xbc925d37, 0xf5419cbf, + 0xee84b497, 0x3f4c04b2, 0xdad07eef, 0x610b45d0, 0x89f2952e, 0x9fc66879, 0x98dd5c01, 0xa1ed4773, + 0x7e4ee1b2, 0x100b3d78, 0x6ecf4b1e, 0xbee09960, 0x0a2f8c83, 0xb164336b, 0x3233b5d7, 0x718ae361, + 0x14d5d174, 0x6fce6611, 0xaa696fc6, 0x0e21b79f, 0x98c6329c, 0xd883c194, 0x96e8cbbc, 0x466a23ce, + 0xaaea7dde, 0x95f7ddc9, 0xfe74a79b, 0x2267fd89, 0xe6f62872, 0x58d7eec7, 0x356f6a28, 0xccbc1a04, + 0x1ebe4000, 0xaa4c157d, 0x594caafd, 0x9d275924, 0xa2285d69, 0x910972b3, 0x1de5e745, 0xcc739ac9, + 0x206b73bd, 0x723a709b, 0x4af8ad91, 0x54181a6f, 0x1d7ea584, 0x07fe9b1e, 0xea42965e, 0x31fcc96f, + 0x37024715, 0xaf2ee1df, 0x321baece, 0xadf02d01, 0xc50a7476, 0xb1c3d059, 0xd27ea029, 0x7baa2177, + 0x0ceff828, 0x7e3a5ed5, 0x91ec941b, 0x9a11f4ed, 0xea75907f, 0xb45af647, 0x2588500f, 0xe1eb5d63, + 0x748f04f6, 0x63fc724b, 0x0190ed10, 0x3c3b634e, 0x4517881a, 0x7d6e0ac8, 0x88ee8db0, 0x5873f7bc, + 0x646f3e03, 0xf6a91867, 0x0a82c9e8, 0x88aba83b, 0xaf27cc7d, 0xb67ac282, 0x810fba97, 0xda710f79, + 0xa364e645, 0xe526d5f4, 0x6808ef7f, 0x4f3fc4c4, 0x2116c103, 0xbfaf564b, 0xae1495e2, 0x99ddf5fc, + 0xa3ff56fb, 0x54d2690a, 0x81ba15c3, 0xafe66511, 0x93a04b6c, 0xafd1640e, 0xf31832e3, 0x47492f56, + 0x20e08354, 0x67b2ab49, 0xe7777662, 0xbcbcb03b, 0x39d9d2af, 0x7ab9c482, 0x9e293e96, 0xe51f50ca, + 0x31f91e39, 0x309cbc7e, 0x8c78d8c7, 0x3732c739, 0x2a8606ab, 0x7a33574e, 0xf2146c2b, 0x497565ac, + 0x620f8709, 0x4c40db47, 0x8fbff110, 0x245dab83, 0xaea342e6, 0xc9404978, 0x884645dc, 0x2e73e3bd, + 0x5c1ad278, 0xdae3cbc3, 0x80c49bc1, 0x5f6f0acd, 0x52b524e2, 0x7c3f15dc, 0xb2e1c2f1, 0x3a1bddfb, + 0x36fd177b, 0xd25c255e, 0x8797d13e, 0x1e9c8314, 0x5e9e19b4, 0xf71284b6, 0xa673f517, 0xbdc9300a, + 0x75870fdf, 0x6fd6ade6, 0x05f8f0c6, 0xfaccab68, 0x1e66c6c8, 0xedd97d8e, 0x0cd3776f, 0xecaffcf0, + 0x16ad731e, 0xf466d545, 0x3f12e197, 0xc567caf5, 0x4b437dc1, 0x8c83b97a, 0x9e8864ec, 0x1ceb3a42, + 0xaaea3b82, 0xabed0058, 0x2f6cfbe9, 0xf58bc8dc, 0xa7fdec1f, 0xc798f8e1, 0x5b56ee9e, 0xaf1f8c48, + 0x727d3758, 0xc0da9db1, 0x8cc65463, 0x5ee3c417, 0xfb8e552c, 0x117b1eb0, 0xc3586e37, 0x9046662a, + 0x6f06351d, 0xb2d95948, 0x14653155, 0xa0f15268, 0x5d234f6d, 0x68cdaf27, 0x55f33222, 0x9776d563, + 0x89e539e8, 0x1e6d3c01, 0x33408ab5, 0x66ae024f, 0x926bd80e, 0xd7fccc67, 0x19f23e28, 0x5900a645, + 0x5c6dc8a0, 0x40333b66, 0x12629445, 0x4cf9a7ee, 0x86b200c1, 0xc29cf5e5, 0xa73edebe, 0x911fffd2, + 0x9edef161, 0x70944744, 0xdb000ace, 0x0c3c2a4d, 0xccb8c63e, 0x4c8ba41e, 0xe72a2921, 0x6aa22167, + 0x3d1999c5, 0x3271f525, 0x2bf66e88, 0x23618f3a, 0xd7397be8, 0x9f6a7e76, 0x045936c8, 0x239dfbb7, + 0xede73a05, 0xe03dcee6, 0xc3c26183, 0x7105bbe4, 0x2a525c32, 0x37d27aad, 0xa1cec018, 0x760fd57c, + 0xebfe4578, 0x141872d0, 0x70f5cf9c, 0x5ec6d918, 0xfa86178f, 0xc9cd175e, 0x773d44ec, 0x08adad16, + 0xc8f8f752, 0x32497d81, 0x7158d5bd, 0xe634e4d4, 0xa3d80564, 0xb079c6b9, 0xafb1ed32, 0x5c3fcb2b, + 0x750d4a36, 0xfb7a8a80, 0x501f6902, 0x6f0a53be, 0xb9ecfbdd, 0xd9016756, 0x257e47b0, 0x2bd5e0b6, + 0x38258e7b, 0x1747bcd4, 0xfda7650c, 0x94384419, 0xfd67dd56, 0x54e17ea3, 0xc89d375a, 0x25c3e110, + 0xb7990183, 0x2f28c5d6, 0xbf2fc23f, 0x9d48a5dc, 0xcf995fca, 0xa26fdfa4, 0x458385cb, 0xc0be5747, + 0xfdb9fbde, 0xc0065588, 0x8d26d901, 0xed3a180c, 0x475fc26f, 0x4719fc45, 0xc415104b, 0xb17fa12f, + 0x62ee2cca, 0xce872915, 0xc6dd7adc, 0x0cd33138, 0xf19875c0, 0x800661e4, 0x4c03b059, 0xfd6e9cae, + 0xb2c1ab3c, 0xc98f7a28, 0xe7706d34, 0xc812aa34, 0x356342c6, 0xc93d0e79, 0xc9df1c3b, 0x34c56e08, + 0x478a62b7, 0x9b519197, 0xd9d52ee8, 0xa5fc3cfe, 0xc21a9052, 0x03c86617, 0x89a194e1, 0x3571eb52, + 0x20318122, 0xcb482ff7, 0x2eb054ab, 0x0ffbbd71, 0x16a6a9f0, 0x76adb997, 0xd4311631, 0xdd16e53c, + 0xd38768cf, 0x1e377d7d, 0xa3c3119f, 0x71df2e38, 0x9f2e92ea, 0x738b73f8, 0xd3e711ec, 0x16e36af0, + 0xc7d04da3, 0x19a2feb6, 0x6e64969a, 0xa8eb57e7, 0xe9a14167, 0x5be590b1, 0xfceaff28, 0xa076b7fb, + 0x20914d47, 0x3af33bc3, 0xb12e34ee, 0xd2d8a515, 0xdda9b0bd, 0x80b50fe6, 0x65080ec2, 0xf49f1fcd, + 0x999cf5ed, 0xa3c152d7, 0x473058e4, 0xe279426c, 0xb7dbc091, 0xc7d23bf9, 0xbbfb5675, 0x86a2c67c, + 0x9be65904, 0x41faf802, 0x7bb4d1e8, 0x06b66e05, 0xe062f362, 0x20325e89, 0x7279b996, 0xb15fb7b6, + 0x67ee6deb, 0xded75d6c, 0x20ccbdfc, 0xee9bef58, 0xaf6f2c1d, 0x99a26857, 0xdcb7d508, 0xaf982de2, + 0x4bb8012c, 0x531bb0b1, 0x2b6f22a9, 0xc566dffd, 0x5e190370, 0x68b37c04, 0x389c6522, 0x0b9c6814, + 0xe451207a, 0xb598e89a, 0xa8166acc, 0x604f51e3, 0x6d5330e5, 0x15df2571, 0xfed0fcc0, 0xcf1f5db6, + 0xb5e329de, 0xc91cc891, 0xd5bf3b75, 0x438d24f9, 0xecdb101e, 0x0c494837, 0x22ea90fd, 0x629c6ca4, + 0x71d72c7f, 0x992680ac, 0xd95a9ed1, 0x691af434, 0x6c5ea1ad, 0x167c0fdd, 0x177c7b44, 0xfc4fae16, + 0xb8ae8259, 0xfbe3cf1c, 0x532565b4, 0x994323f4, 0xd3e963f2, 0x39b4b228, 0xb9e939ad, 0x407015dd, + 0xf2460771, 0x67134f77, 0xc9454b2b, 0x2e0be32d, 0xfff80389, 0x8eb688ff, 0x7f8f2017, 0x8dfaeb1f, + 0xbac55d88, 0x8b4a47f8, 0x8b79eade, 0x0aa8d8e8, 0x4c591d75, 0xc9698a4c, 0x4a31b6cb, 0x90aa6b60, + 0xcf01e8ff, 0xbd214321, 0xf5717938, 0xa1a6fb58, 0x05c008b5, 0x7df76b96, 0xfb1380b5, 0x407adbd3, + 0x40f00e18, 0xfb5c8a75, 0xae957b71, 0x331edc99, 0x5afd917b, 0x0a160906, 0x9ba37131, 0xf607d6c6, + 0xa51e6900, 0xf853b943, 0x9f8d89a6, 0x84d71970, 0xd9fde6ae, 0x94460d5f, 0x2b0c7166, 0x998cb036, + 0xa2b1e57a, 0x59eb1550, 0x0718936e, 0x6ec15c3f, 0x5dc69abf, 0xe5f7dce8, 0x78810b27, 0x691ba904, + 0xe6d64200, 0x0d17ba04, 0x71a70a7d, 0x7162f3c3, 0xdb5236d1, 0x579990cc, 0x1e160658, 0xec10229f, + 0xaafef2c4, 0xa69ba2ae, 0x88fb53f7, 0x25fc6bc9, 0xe076568d, 0x50d64d57, 0x4da0d9b5, 0x6a68f61b, + 0x274092de, 0xcea9fe02, 0xc81db654, 0x5e59488a, 0x25d8c255, 0x9b6e3adb, 0x0086276c, 0xa5eec937, + 0xedaa837a, 0x89a5c86f, 0x943249d8, 0xd3292564, 0x80653bf5, 0x6f919d24, 0x0e7856dd, 0xe0a29451, + 0xa49e3aa9, 0x807257c7, 0x4ade887f, 0x0c10092b, 0x78a58a37, 0xc335a976, 0xb67c1be2, 0x95956db1, + 0xdb643fc0, 0x25fe4523, 0x49e566fd, 0x35154f92, 0x6f6a8310, 0x5329636e, 0xf941f73d, 0x2cdbcc9e, + 0x7a5160d5, 0x318e561c, 0x61f2d775, 0x3eb4a80b, 0x2e7ce89a, 0xc696ed76, 0x78f741bf, 0x6ca26996, + 0x9640df93, 0x600bfdf0, 0x76c61986, 0x410e6679, 0x04ef985a, 0xf59b4bd6, 0x1e8e4487, 0x9cb3a5d2, + 0x4c6848ee, 0xd45640b4, 0xfc9fc145, 0x2fc6d65d, 0x8f74aa32, 0xc0978c0e, 0xc837e9fc, 0x40290723, + 0x1fbdc9b7, 0x494d1e4e, 0x358b8ecd, 0xf7ebe1cc, 0x8af0a069, 0xb83a1082, 0xc8902a46, 0x2e17b8b1, +]); + +pub const VENDOR_MLDSA_KEY_3_PUBLIC: ImageMldsaPubKey = ImageMldsaPubKey([ + 0xfceb4375, 0x1153eb18, 0xfd2daed7, 0x2ade5f69, 0xb0505b3b, 0xe60eda94, 0x0e3b0c70, 0x277cb2f8, + 0x19a84967, 0x927883af, 0xaa992ba0, 0x94f8b139, 0x45389b64, 0x25bd2b22, 0xc98c8759, 0xc2b4c216, + 0xa3f61eed, 0xa44df1bb, 0x8b2770cd, 0x60a61bc9, 0x90d742d2, 0xef6965ae, 0xe856dd93, 0x1244096a, + 0x6d16bd8a, 0xb6e1c81b, 0x996caaa4, 0x00979339, 0xc7aa39ed, 0x5154aaf7, 0x02163144, 0xfeba8609, + 0x393a131e, 0x56276476, 0x18dab3a7, 0x6fb775c0, 0xf253ac8e, 0xfb26c372, 0x191c6429, 0xcd2ef667, + 0x95e45a9e, 0xf7389383, 0x9c95067e, 0x7a7cb329, 0xa7a22deb, 0x63651279, 0x057a38eb, 0x83a5dd93, + 0x54503486, 0x619ea360, 0xc75ec86c, 0x15698af8, 0xb1ae28e9, 0xe2acbd15, 0x5bb38edd, 0x5eb1df77, + 0xe7be4691, 0x2b6dcd22, 0x76494cdd, 0xba6b9d6a, 0x5a95e874, 0x8026183f, 0xe39dc602, 0x647cf332, + 0x0e9092c1, 0xd8554daf, 0xcd80f180, 0x50df41d8, 0x5562073d, 0x00e6344e, 0x8f56d202, 0x0a5fa18a, + 0xd6c4c0fa, 0x1156ada3, 0x037ca837, 0xafce53f0, 0x04ce1ae5, 0x5e43353b, 0x2711ed9a, 0x8162e125, + 0x2eccbcd0, 0xb3c7debb, 0x7c53347c, 0x815a8ef7, 0x2e701e86, 0x668bad23, 0x20ea6a40, 0x8ba2ec7b, + 0xe33e3a04, 0x9bd09128, 0x95a26c3f, 0x61f83c44, 0xd52a747a, 0xee4b6f11, 0xd3ad170c, 0xe46631dd, + 0x8d0b9000, 0x950e1850, 0x522f7e4f, 0x81f2c69c, 0x4b4a364f, 0x1afcf4b5, 0xe2cb277a, 0x8cafc0ec, + 0xd9ebeeb1, 0xd239aa8f, 0x7ad94e67, 0x1897a157, 0x0ef4664b, 0xe3d3da3c, 0x850efa2b, 0x365a89ab, + 0x9ae735cf, 0xcdca2c5e, 0x5308140c, 0x203e1984, 0xba2acd5a, 0x275ee923, 0xe06d2709, 0x7d57de06, + 0x8da31487, 0x4fa04754, 0x0a016283, 0x22b5973d, 0x55083c79, 0x6ed19b27, 0x9b0a312f, 0x49f54460, + 0xe03bde9e, 0x3c9ff046, 0x42ef3b0d, 0xc48c96d6, 0x0765049a, 0xeb972e8d, 0xcf9efb18, 0x4daab18d, + 0xeaf5a673, 0x09f3b0c2, 0xe30dc2ca, 0x19df7d4f, 0xaed52aea, 0x6023cd92, 0x905ea540, 0xe2213cd1, + 0x71d52047, 0xafdf7ef7, 0x66b87433, 0xb40304bd, 0x4f69c350, 0x0000e7e8, 0xad73cfef, 0xcd0de58d, + 0x07874732, 0x4e1cab00, 0x8c69f9f7, 0xa9eb87e6, 0x4316c260, 0x3db44199, 0x47428b69, 0xfda9a081, + 0x9cded9bc, 0x5c8cd026, 0x3a2f08b3, 0x6fd9f77c, 0x6edf96f5, 0x9dadef6a, 0xc4498cba, 0xb367a49c, + 0xbfd2c9e7, 0xabf5cff8, 0x7c33bddc, 0x5959440a, 0x3f18198d, 0x84ac2ffd, 0x744cb3d3, 0x3169796a, + 0x377ba2f4, 0x1380af6e, 0x30b6b8ed, 0xfe4c2c66, 0x88e12181, 0xf93ac11e, 0x89e4c237, 0x497e8610, + 0xa76e60a7, 0x175376eb, 0x27d546bd, 0xafe2969b, 0xd78831e3, 0x367e07e6, 0xea73601a, 0x8c9e4a5f, + 0xd62e1ea1, 0x38cf3ce7, 0xa0abb05c, 0x14fc1c8e, 0x19e98b1d, 0x78b8251f, 0xaf177e88, 0xf5729566, + 0xdd8e9f5f, 0xaf677777, 0xacb22d90, 0x7f574c0a, 0x3806fa99, 0x464b4ce5, 0x03675fea, 0x0c1219e4, + 0x0a92a4b1, 0xd3d9017f, 0x0cfb686f, 0xbd8cd9c5, 0x94c91887, 0x791fb77f, 0x0c476582, 0xe193f539, + 0x78701ee9, 0x9fee31e6, 0x85482553, 0x82e616b6, 0xd0371aff, 0x256a99c7, 0x5e86711c, 0xfde4c05b, + 0x089a2695, 0x63cd6ba2, 0xcfdaa680, 0x08a8028d, 0x829ba2a1, 0x090b119a, 0x39e283ae, 0x68532d26, + 0xb239a1b7, 0x94f6d39b, 0x3cfe2383, 0x0bd567e0, 0x5d898b7a, 0x4d433496, 0x653e3cdd, 0xa7427df1, + 0x9167b661, 0x235f16ab, 0x865b25e6, 0x18cdaba2, 0x0355d6d7, 0x721d7864, 0x4d393d06, 0x2045b5fa, + 0x8479d515, 0xfdcd440a, 0x2b774cc9, 0x29181e4c, 0xb9d00889, 0xfa1384de, 0x532e3c09, 0xc185f156, + 0x0964279b, 0x1ae7da65, 0x2407d8a7, 0xb8a70a4a, 0x0b589a0b, 0xc458f0c8, 0xa880effa, 0xe2e0c4ab, + 0xa3dd8ca3, 0x5e7ee23b, 0x851f781d, 0xec10bfda, 0x582b8438, 0x537643d2, 0x039db953, 0x3f99a2ca, + 0xd627d0a5, 0x7572bfde, 0xae4727a7, 0xc2fbdb20, 0x381baf72, 0x1184baca, 0xab08620a, 0xb92b7ba2, + 0x7f3247ff, 0x578d9bf0, 0xcbb84518, 0xeeeba7b6, 0x932f07ea, 0xf2614c9a, 0xf4f88d8e, 0x03564a8c, + 0x33f65219, 0x76a5d605, 0xd5bbc871, 0xc3df8c37, 0x61d469b5, 0x823b8da6, 0xfdc18c1b, 0x763c4ae8, + 0x7271f17c, 0x29a97ee9, 0x439a2df8, 0x6da9fdce, 0x3ac2b8dc, 0x04975b7b, 0x7f62356e, 0x3846b4af, + 0xdadbc330, 0xc6d64c59, 0x8c1b768d, 0xf5b4e816, 0x634ca004, 0xbce3de2d, 0xd07a5d18, 0x2eeabd82, + 0x37445e16, 0xb8f2fee4, 0x55d3c524, 0x7a5be01b, 0x01834b48, 0xc4b5db09, 0x8341a906, 0xab8630fb, + 0xb18f33e9, 0xe9ae2cf1, 0x3d1fb31a, 0x03f24084, 0xfd595187, 0x71d831ad, 0x32bd33a6, 0xf955038b, + 0x862119ad, 0x243b2fe4, 0x082924a2, 0xbc95a82d, 0x68d04a7d, 0x79fa1cb4, 0x2c5c73e7, 0x09d64cc2, + 0x74f9aebc, 0x782d2ed9, 0xdce7048a, 0x5efaf676, 0x913a0524, 0xbfb1313b, 0x0ed0e55e, 0x2d941c42, + 0x63f4ab9a, 0xca9fd0f5, 0xc03d8c37, 0xa5b742f0, 0xadc73d55, 0x00c31d85, 0xf0fbc254, 0x7717a177, + 0x76c309bb, 0x27b86de6, 0xa93e502f, 0x5ab316c3, 0xe8b9bafa, 0x7f2c168e, 0x6409bb4a, 0x3a319466, + 0xd7c74f52, 0x12d6f58c, 0xb0c07954, 0xaa8bf337, 0xbab78bd3, 0xb723bc30, 0xf6769e2a, 0x0988d61f, + 0x19481432, 0xe652b8c7, 0xb70df987, 0x39103274, 0x1b0a15e9, 0xf8f3fcd1, 0xa65b3ec2, 0x452cf6ff, + 0x7ee45d3b, 0x08335d97, 0x5968894d, 0x38aa52b4, 0x5bc24fd2, 0xf30e4d34, 0xb56c3918, 0xb12aa907, + 0x272c7031, 0x8ce2762f, 0x43b9f286, 0xb39b815e, 0x6b6ba654, 0x527508a9, 0x0a30c49f, 0xe9bc7d21, + 0x5d825468, 0x43a5295e, 0xa8721f3b, 0x73a822d9, 0x46b3c470, 0xa2cc7e04, 0x8243428c, 0x82e80728, + 0xf8145388, 0xddfcf329, 0x8f833b9d, 0x5d1b1cc8, 0xaf67cc6c, 0x7304cba0, 0x4b9b106d, 0x54f6602e, + 0x02e5a692, 0xf98ab789, 0xc65143cc, 0xb2090226, 0xa8cc0fb7, 0xd35cf5f7, 0xe840a731, 0xd1e7248d, + 0xe9fc209c, 0xc86182d9, 0x0151a072, 0xc61360dd, 0x2c517c66, 0x7a38d359, 0x81f940ec, 0x1eb76514, + 0xcfc2b0d6, 0xc3f505ba, 0x546830a6, 0x3a1511b0, 0x962edb2e, 0xd1319a73, 0x4d0044b3, 0x84fb5beb, + 0x2252f57e, 0xcc462c89, 0x230523a0, 0x0d4e3fae, 0xfb8a2963, 0x352b2a03, 0x817aa4d0, 0xa13c10d6, + 0x055e1f0b, 0xb652b7cc, 0x76cb5955, 0xd5f0afe6, 0xea2ae11e, 0x348c0eb0, 0xaf3638f0, 0xdad014a3, + 0xea63a174, 0x19a1dbf4, 0xcec39900, 0x51cf4d9d, 0x582d6842, 0x479610b2, 0x7fca52b4, 0xc409da72, + 0xaab7611c, 0xcf01c246, 0x1f38da2b, 0x9bcb0ddb, 0xe07fec4f, 0xff3baf53, 0x0457faf2, 0x10dbb73b, + 0x8331e0e8, 0xa4165e82, 0xf99c0c6f, 0xde4e2b1b, 0xf11aaa72, 0xfae00e4e, 0x8cb67a51, 0xe8c080d2, + 0xbabeac89, 0x337c1c68, 0x4df593af, 0xd777498e, 0x3b19438c, 0xe338774e, 0x0016d7cb, 0x25910c4c, + 0x8b0c66c0, 0xaeebf324, 0xcbe64bde, 0xcb871804, 0x7cc6b311, 0xe661a250, 0x1027856f, 0xe430d84c, + 0x63446166, 0x684119ca, 0x880c2de0, 0xeab3f0d3, 0xeceddeac, 0x0deec157, 0x4de7f723, 0x60282ba6, + 0xe3d55954, 0x12208717, 0x232ba6f7, 0x9de9a090, 0x1b69d141, 0x24c14913, 0x88a9e9fb, 0x8c90919d, + 0x6ca74c72, 0x99198852, 0x200e197f, 0xb0db60a6, 0xc26a9b61, 0xdc50af7e, 0x77c250df, 0xe59b65b2, + 0xd90cd8bf, 0x320366ed, 0xc1c3b5ed, 0x0d209a81, 0x69ddf69a, 0x735704d4, 0x56cb98ed, 0xe39b32c5, + 0xac7959e8, 0x4f601f83, 0xc582a7e8, 0x8edfcb68, 0x793b2b93, 0x3134ec93, 0xf13e1030, 0x795c95d1, + 0xf958f673, 0x2eff8092, 0x150022f8, 0x3af86f1a, 0x2ee410fd, 0xd69ff635, 0x181dba1f, 0x68edca94, + 0x8f0b627a, 0xad94268d, 0x2225d7da, 0x9ea27b98, 0x7a138b27, 0xa998e806, 0xede17a7f, 0x89979eec, + 0xa67f006e, 0xbb17410b, 0x9c9a8cfa, 0x6b411ed7, 0x2a060a39, 0xd7375043, 0xba1bbbad, 0x1c677e61, + 0x474fa89f, 0x9038fabe, 0x302dd3d8, 0x1658cf9d, 0x75f37450, 0xc9a92802, 0xcd5da6ba, 0xd431d0c2, + 0x4ece6eab, 0x1b017e9e, 0xf21231db, 0x3e1c4107, 0xe8ae64f5, 0x4563a9fb, 0xda5a50d0, 0xaf60c667, + 0x22bdab0a, 0xc7ef8513, 0x872c7ea1, 0x83b323d4, 0xab2f1dd5, 0x4684d4ff, 0x55dba611, 0x352af222, + 0x23326a4c, 0x7a7d87a0, 0x1d6c8105, 0x492d43a9, 0x8adb8630, 0x9707480c, 0xee33a7c1, 0x67ffd19d, + 0x9de6ca16, 0xca0e9e56, 0x33cf7fc6, 0x72cefe76, 0x49b05e3f, 0x93072b63, 0x5b7df0cb, 0xa6b3663c, + 0xe71a0cca, 0x1ad0684c, 0x2eb19d9b, 0xaed7344d, 0x1cdf762e, 0x3b1b5c68, 0x3ffd1301, 0x4bfb61ab, + 0x10eda6a7, 0xdfa42ed5, 0x0d12e0e1, 0xe5020abd, 0x0242bf64, 0x321077e4, 0x65632e92, 0xfb6a7cb0, + 0xac2d93ad, 0x7ec595a9, 0x26cb689e, 0x772e5864, 0xf21207de, 0x50de9b46, 0x8a2bc178, 0x0bb9d913, + 0x1c048a11, 0xabf6b278, 0xd25091cd, 0xe2672f2f, 0xbd7feaba, 0xe5500769, 0xadbb21e1, 0x475c28ca, + 0x3700cddd, 0xd99372f0, 0x323ad3bb, 0xa9c017e2, 0x3b329468, 0xa601748d, 0x15d919f8, 0x633b8773, + 0x5ecfae12, 0x1d45852a, 0x989458a3, 0x42ad267b, 0xbf72060d, 0x85309842, 0x73a2611d, 0x3c4487c4, + 0x5d6a367a, 0x60af3515, 0x71d96903, 0xfe4e497d, 0x3958dfde, 0x9ea35aa6, 0x4fdf86e7, 0x335af720, +]); +pub const VENDOR_MLDSA_KEY_3_PRIVATE: ImageMldsaPrivKey = ImageMldsaPrivKey([ + 0xfceb4375, 0x1153eb18, 0xfd2daed7, 0x2ade5f69, 0xb0505b3b, 0xe60eda94, 0x0e3b0c70, 0x277cb2f8, + 0xf2f5f2b5, 0x3525003d, 0x873067cd, 0xc97bef69, 0xa5f6d16b, 0xd38b0869, 0xef53659c, 0xcaa0d461, + 0xb3549f5d, 0x1eddb554, 0x8f218ac8, 0x018f9f31, 0x970a87e6, 0x9ed47014, 0xeb80cab7, 0xdfc7b26a, + 0xe600b581, 0x5c81fd6c, 0x9c2ae2b4, 0x0e36b26e, 0xf20b4136, 0x6b1e7966, 0xf00dc23d, 0x6ffb2b18, + 0xc9b42c51, 0x988c8828, 0x51088160, 0x09192c01, 0x27842034, 0x66d23880, 0x5b824883, 0x30225006, + 0x81010709, 0xcb840d08, 0x190404b1, 0x11d43208, 0x14157041, 0x82681a90, 0x011b0381, 0x12152e23, + 0x41249136, 0x09539021, 0x21432160, 0x30264c18, 0x6e20c54c, 0xe43470dc, 0x868da004, 0x2e5a8244, + 0x202664a0, 0x48714b04, 0x20d08071, 0x548600c1, 0xb06c60c6, 0x05944870, 0xdac22924, 0x8671dbc8, + 0x29421804, 0x22b68502, 0x31490881, 0x31a33066, 0x54220000, 0xb95180a0, 0x31cba840, 0x1aa88152, + 0x90282230, 0x8692000c, 0x59828988, 0x06251890, 0x80212188, 0x99304458, 0xa2441bc7, 0x915b9064, + 0xdbb00519, 0x182a9118, 0x84c3386d, 0x98389153, 0x44658214, 0x51004312, 0x80a88510, 0x884d0a26, + 0x32e1b46d, 0xc33429d2, 0xa63064c2, 0x60210311, 0x092672a2, 0x18480106, 0x71820420, 0x241661c2, + 0x04824a16, 0x8ec1c289, 0x03890d0c, 0x406e9436, 0x41d82264, 0x1428700c, 0x84688148, 0x6c80106c, + 0x98022d98, 0x28844448, 0x8150068c, 0x5920860b, 0x950c9804, 0x4e644460, 0x01137100, 0x864119c4, + 0x05818645, 0x4c1285db, 0x4848c386, 0x4d00b981, 0xe438664b, 0x168808a2, 0x69599404, 0xc8980ca1, + 0x4020da88, 0x2d919664, 0x4232489b, 0xb04c0225, 0x2d54a844, 0x13012049, 0x04894192, 0x71c40808, + 0x1a83851b, 0x25850cb4, 0x68598824, 0x424466db, 0xb20493c0, 0x440a1872, 0x13229111, 0x936c5206, + 0x6020a429, 0x03b184cb, 0xb40c5332, 0x6e92468d, 0x203884a4, 0xb8259898, 0x84832422, 0x82148c1a, + 0xc521dc90, 0x7059220e, 0x11a06104, 0x15308128, 0x09a10866, 0x41420d41, 0x2082a4a4, 0x2c040205, + 0x0836694c, 0xb488c3a0, 0x401c4050, 0xa0045111, 0xb6019446, 0x02998849, 0xd8247021, 0x07701249, + 0x0e52144d, 0x03430c1a, 0x47460027, 0x4a43a685, 0x12851120, 0x0386c424, 0x4ae4006d, 0x50947122, + 0x88104382, 0x30e3c870, 0x641472a0, 0x2691c400, 0x4ed43231, 0x50b2809a, 0x342d1944, 0x02c80201, + 0x12c40dd0, 0x200c8c12, 0x654b1400, 0x98423114, 0x066ada10, 0x600ac964, 0x843660d2, 0x2032c4b0, + 0x28143409, 0xa0348981, 0xa88c0234, 0x69090541, 0x02a4654c, 0x2091e180, 0x8d931224, 0x19437204, + 0xb8459222, 0x24daa848, 0x0a4021a0, 0xa46d0445, 0x2509320e, 0x9cb4248b, 0x168d09b9, 0x49a3b04c, + 0x42047203, 0x236580c6, 0x4c00084d, 0xc81671e3, 0x00401b87, 0x69990872, 0xd8142810, 0xa6010009, + 0x021c9449, 0x14c03121, 0x4231c236, 0x2a444250, 0xa4268ca4, 0xb8051c96, 0x0de12611, 0x58344eda, + 0xb62c53c8, 0x91cc3684, 0xa180044c, 0x02490319, 0x8c230304, 0x00a94de1, 0x92681118, 0x2c8ac205, + 0x81c46863, 0x846ce284, 0x48dc2840, 0x92a68101, 0x97889102, 0x6884262d, 0x09409224, 0x22664144, + 0x811b1622, 0xd8362460, 0xc464c184, 0x4c108529, 0x899810db, 0x04408296, 0x00443601, 0xdc88680a, + 0x03714aa8, 0x844c840c, 0xe3226d90, 0x40419932, 0x01a3b40d, 0xd3882024, 0x870062a4, 0x7111b500, + 0xc23682db, 0x388054a8, 0x4c643801, 0x00b12d0b, 0x310d99b2, 0x8094a031, 0x4b960422, 0x486c0ab4, + 0x89123792, 0x9b3450c0, 0x286a18a5, 0x65030100, 0x14b665c0, 0x08494308, 0x25201651, 0x19b59100, + 0x229123b0, 0x61108800, 0xdc025223, 0x81041020, 0x86181728, 0xe100621b, 0x938001c6, 0x6808128a, + 0x22186024, 0x816d03a1, 0x80c0c64d, 0xd2066950, 0x22622032, 0x45cb466e, 0xca405119, 0xa365d4a2, + 0x44901605, 0x9ab6009a, 0x1285c888, 0x2109858d, 0xc11462c0, 0x0622e338, 0x4021c324, 0x12326d19, + 0xb6608008, 0x4448b065, 0x54388d80, 0xb2649036, 0x068b3891, 0x0ca00442, 0x26522140, 0x4d0ab58d, + 0x21108edb, 0x30085c80, 0x3010292d, 0x1cb44418, 0x3969d338, 0x2688b471, 0xc4841164, 0x32054a24, + 0x0442408a, 0x5ac0458a, 0xb4486222, 0x90901620, 0xe1b66d61, 0x46918232, 0x690a864c, 0x99446083, + 0xb2616322, 0x69413686, 0x642612c4, 0x300c4042, 0x81511085, 0x19a01120, 0x4830d9c8, 0x0ca20861, + 0x903850d3, 0x142dc998, 0x011a1982, 0x40968164, 0x2666c9c8, 0x851b3245, 0x102726c0, 0xc4810313, + 0x41601682, 0x02212624, 0x85280ab4, 0x880c246d, 0x1b330d02, 0x47421c06, 0x2c81b801, 0x24328922, + 0x88201c32, 0x054a1651, 0x1c3461dc, 0x006c5838, 0x4ee3a444, 0xa11080c4, 0x32465aa4, 0x65244348, + 0x21989141, 0x4089db42, 0x8a232921, 0x84c28598, 0x388e92a4, 0x25d83670, 0x00280198, 0xb0210429, + 0x31a29249, 0x0c312259, 0x466d1208, 0x40d83801, 0xdbc880a3, 0x9821c048, 0x4ee41024, 0x54a68599, + 0x920ce080, 0x09590870, 0x82888512, 0x4881a090, 0x00582630, 0x1b216458, 0x20091313, 0x04a01624, + 0xc8a845c3, 0x06110b42, 0x80140652, 0x9bb43024, 0xb245d224, 0x4a043182, 0x14186d0b, 0x99408b44, + 0x200ab204, 0x0399910a, 0x252dc4a6, 0x4491a489, 0xe3162ec0, 0xb6291b29, 0x28091431, 0x24296423, + 0x46854bb6, 0x50d1382c, 0xa3448202, 0x914d9342, 0x0e233704, 0x24c9688a, 0x462da382, 0x8d080521, + 0xe094325d, 0xe1abf2f0, 0x69e0c43d, 0xda6e3199, 0xc5039fdd, 0x433b075c, 0x9b100565, 0xdd174cfe, + 0xc156cd53, 0xfbd50b8d, 0x36bcf488, 0xf9bda32a, 0xa2e0968e, 0x6f8b36e7, 0x2913e06d, 0xb9ea7a0f, + 0xcb813f3b, 0x5bb9b097, 0xaefea6ee, 0x3285a5f6, 0x7e08fb9c, 0x128b1ba3, 0xd23cd2d0, 0xaf20a673, + 0xebe58877, 0x76120773, 0x42bfb42e, 0x1591ca2e, 0x6f37c36c, 0x57b40826, 0xe55bc320, 0x4551db62, + 0x3a141e8c, 0xf9d67983, 0x56e111bf, 0xdc0b0076, 0x1be48373, 0x5e8d0318, 0x212b96f9, 0x2915dfd3, + 0x3f5f69a2, 0x2087e133, 0x69270897, 0x11b886b7, 0x5b260628, 0x2d0bc1f9, 0x1bdc0b98, 0xa4d80ab8, + 0x340bf79b, 0xbc968221, 0x139c9b86, 0xf664bfc2, 0x7b40c1be, 0xc86d08b0, 0xe8bcdfcd, 0x38205f7e, + 0x4a3c6e2f, 0x4a0a5104, 0x8b2dca54, 0x072dc766, 0xb7a5ad18, 0x0e79ef88, 0x378bd7e7, 0x5a77b4ee, + 0x188814df, 0xec1cf892, 0x6836b50d, 0xb55273a1, 0xfa21aa6e, 0x705cf832, 0x29bbecc5, 0x60a66769, + 0xe1885a44, 0xcde9ae21, 0x478f43e0, 0xcbe014e5, 0xeb702886, 0x27c433eb, 0x4566cffe, 0x7aa5260a, + 0xae88ed87, 0xd6354859, 0x10edf0a2, 0x25b99353, 0xdfa6d361, 0x1c9c9e6e, 0xf7ab4d44, 0xd90d38a8, + 0x1b0b1b53, 0xe787a8a0, 0x2d749096, 0x0fd8c801, 0x613b2727, 0xa72c4e92, 0x5930511c, 0x8f49f8ba, + 0xc66c9bb3, 0x20ff8cfe, 0xc2e37baa, 0xfe5eabeb, 0x5e30fc4a, 0x7ec2f6a9, 0x2006f97b, 0x865d22b2, + 0xa6264de5, 0xf5ddaf0e, 0x76cb2d31, 0xadb8f647, 0x1eb5c13f, 0xa8424218, 0x2f0cd41f, 0x15195cd0, + 0xd63d3eb0, 0xc996a19a, 0x57fd3989, 0x403b459f, 0xea9e49dc, 0xc7463c7f, 0x1cfa645f, 0xaa7704bf, + 0x8fcdf6a8, 0x3f166d7d, 0xcecc956a, 0x9ccd672d, 0xb80b6c59, 0xf28cc52b, 0x99d3b558, 0x53384453, + 0xa97efb17, 0xb36f4752, 0xc0612fa4, 0xe6f6ae92, 0xc6f13e1c, 0x1cab4134, 0xb4a03902, 0x7c1611a6, + 0x1a45f85a, 0x786023b2, 0x515f64d3, 0x59ac0c09, 0xa62a12e6, 0xa96e89fd, 0x263c7c66, 0x82fa0303, + 0x76903879, 0x878e5b0f, 0x12c2866a, 0x2f7564c6, 0xbcaed65e, 0xd4ce929d, 0x2bcd71f3, 0xad4846fa, + 0xb403ab29, 0x823ee6e2, 0xd869cbba, 0x3cbb0da1, 0x53dab20a, 0xdee3213f, 0x72abc57b, 0x3c47b19a, + 0x6c714ed9, 0xf9f6d774, 0x08b2ebe8, 0x8d5adf8c, 0x7d72b052, 0x773420ea, 0xe0bdea5e, 0x547318ba, + 0x29ab438d, 0xb1eb49f5, 0xbfbf67ee, 0x491e939c, 0x7a35acd2, 0xd05b2a89, 0x202b0ec3, 0xd4bbad2a, + 0xbf52b2a1, 0xc2ea2d22, 0xd4787a8a, 0x6a1e84b0, 0x7fbcee55, 0x10bdd515, 0xe870a524, 0x6e11559a, + 0xfff3a2ce, 0x749afd14, 0x99d40585, 0x44023917, 0xdef9cf1b, 0xcd88ef22, 0x38cc09a4, 0x896b47d7, + 0x6e990183, 0xaed7be68, 0x14017ed8, 0x852849e7, 0x1b3f766c, 0x215eef66, 0x7b0bfb1b, 0x21ff50fe, + 0x0481dd6a, 0x9e027f13, 0x6b0b8e7b, 0x172a3b44, 0xe7de5594, 0x82651456, 0xf68c6caf, 0x36316a7d, + 0xa9c874f6, 0xc4539d9c, 0xebd1a40c, 0xec0f78ef, 0xef18fa43, 0xc2b356fe, 0x0cfe9b64, 0xa115b4f2, + 0x7b774d56, 0x61257cc7, 0xba1c4cb3, 0x9fb8dceb, 0xb11f6ade, 0x91848a46, 0x72f2e575, 0xf1c4834f, + 0x0d82fcad, 0x1f3a02fe, 0xe97514f9, 0xa4b4fed9, 0xf0285d90, 0x5119b52a, 0xd25e4d0a, 0x91c06d96, + 0xcd3d9a18, 0x5362504c, 0x3a61785e, 0x91feafdc, 0x41d4026d, 0x763c79f9, 0xa3ead4c5, 0x76b20f47, + 0xb48c5fdb, 0x65b9aff9, 0x571961b5, 0x3a6ef0a3, 0x0fa18ade, 0xf74e9f49, 0x9017b007, 0x44a2099d, + 0xbef35753, 0x607b5f2b, 0xd51d633d, 0x2a432ef0, 0xb653b130, 0xe2074fa4, 0x43d94f7a, 0x32db246e, + 0x5b51610c, 0x47a16119, 0x6e8fc84a, 0xb4c5bbbc, 0xd58df5ca, 0x5dcb2fcf, 0x249cc84b, 0xf07d2e29, + 0x396d3809, 0xe4caebd6, 0xcc97442f, 0x79f944ca, 0x1e679710, 0xcfe25061, 0x74462928, 0x9ec883b2, + 0x15505394, 0xec3a839d, 0x9024df68, 0x27fd802f, 0xba8326f7, 0xbe37b8d3, 0x451a9f3b, 0xdc31cc8b, + 0x65581dbc, 0xbe7c540d, 0x54e9b7fe, 0xfaa462ac, 0x7ebfca4a, 0x1525cc04, 0x6ecad592, 0xad0dee77, + 0x5ec4c9fe, 0xf76da4fc, 0xf660b893, 0x65b3a1be, 0x2ff5ec55, 0x93381c8c, 0x27d9f025, 0x26239e04, + 0x72448ea3, 0x246f19cb, 0xce7815af, 0x06dc4f35, 0xcac65cae, 0x5f5b5adf, 0x39bff140, 0x32c1c51c, + 0xbbea5c12, 0x8a0c1bca, 0x51326752, 0x179c2cfd, 0xdb37f097, 0xbab80a7b, 0xf9e468ba, 0x7af1f31e, + 0xaa80204f, 0xe9a765aa, 0x34e5f0d9, 0xa29ef263, 0x740da94f, 0x31184550, 0x22c24df1, 0x74671460, + 0x22f3eeea, 0x17e9a785, 0xf88c06dd, 0x655f451b, 0xd2333384, 0xa235cb5d, 0x6e692b10, 0x38749a07, + 0x7ead2458, 0x62eee304, 0x8d5aa530, 0xcebabc60, 0x7af5350d, 0x12d4afaa, 0xd455755b, 0xb1d2a449, + 0x2f3868cd, 0x0c5f083b, 0xa73250fa, 0x70dea22f, 0x3c7e63b4, 0xdc9c9c55, 0xd65df8dd, 0x2b9837b8, + 0x82fcf8fc, 0xa3c28171, 0xbebd4ca4, 0x28ac28b6, 0x3a6d1aea, 0xb4bce9ff, 0xf6022189, 0x522f2d17, + 0x4ac239b1, 0xf018ba02, 0x5516011a, 0xc3cf3066, 0x57dd3ef8, 0xbea22c50, 0x3bcb870a, 0x3e9ca12b, + 0xdb7dd198, 0xff0040e9, 0x420c1677, 0x3533a37a, 0xeb56c7a3, 0xeb532225, 0x927fd6dc, 0x0b12025e, + 0x47cc7039, 0xdba89498, 0x65b2bac9, 0x9087c5b5, 0x19730733, 0x4f099638, 0x93959e29, 0xc44c0d39, + 0xa2af6c7c, 0x731a7b8d, 0x1854499b, 0xf0ee0efb, 0xd66db82d, 0x6b6339a5, 0xccffec8e, 0x33c88b5d, + 0xecb30181, 0x274e56ec, 0x86bb6f69, 0x4aa39576, 0xcaec4149, 0xe42512f2, 0xb7ed4778, 0xda494ce0, + 0x5daef573, 0x1310703f, 0x66a6d964, 0x8ea89e1c, 0x16b4c8b1, 0xdbcfdf7d, 0x82ff9445, 0x69c20ae5, + 0xef865591, 0xd1338406, 0x35532ff3, 0x7ac36912, 0x1b3cc422, 0xd7a0e661, 0xccf8f266, 0xfa2d74be, + 0x424366a6, 0x55bf6f78, 0x68d21b42, 0x07bc867a, 0x99b055a9, 0x29a174da, 0x5678e714, 0xe8229321, + 0xbeffc2a9, 0x612e8af8, 0xc0ff73f2, 0x0e94d504, 0x0f3eabda, 0x81e0ac77, 0x031915d9, 0x214745d7, + 0x21dab24a, 0xa37d2549, 0xbcd8fef9, 0x95603559, 0xa06945a9, 0x1300c021, 0x76f635b1, 0xc99b2413, + 0xd3a0a9ac, 0xfb55eb30, 0xb443378e, 0xc2203cbf, 0x4acebce8, 0xc31aff6a, 0x682475d8, 0x147bbb57, + 0x1c3243b8, 0x4bddc5d7, 0x47608a02, 0x6efd3d8a, 0x1d1e3ba9, 0x20698583, 0x9bd659b1, 0xc1729e43, + 0x4318caec, 0xf2dc3cd5, 0x4a89071d, 0x7ca75907, 0xeac9fb4e, 0xb37eee65, 0xbe2624cf, 0xe9b70814, + 0xc38ddb06, 0xfd13b84b, 0x57ccbb92, 0x4dff401d, 0xc7a4658f, 0x0be9667c, 0x0a5f822a, 0x98a01142, + 0x29721c77, 0x179a6a01, 0xc9223def, 0x961ea1b2, 0x52b4be45, 0x34d13de2, 0xcdd0bf3c, 0x9a0affef, + 0x45e69d86, 0x167bb011, 0x72ffe873, 0x0c9bc486, 0x17ae9f25, 0x46c7f1b1, 0x9afd95b8, 0xfdd6168a, + 0xf711baed, 0x9a02b5b4, 0x19b4cf27, 0x3fdc71dd, 0x560774ce, 0xb903f9de, 0xfa56d8ad, 0x6b811135, + 0x28290960, 0x00f974c5, 0x32364342, 0x2e1a8ec1, 0xc7272567, 0x63c15bcc, 0xde5c4f0d, 0x2a134f7e, + 0x3eb9165b, 0x4d5ef602, 0x6770cd1a, 0x84ffd017, 0x4390035e, 0x998f0382, 0xc74ac192, 0xf42a9422, + 0x50afab4b, 0x8994246d, 0xcfa732c1, 0x4a60c019, 0x0b63b2d1, 0x1a6833a8, 0x3903b196, 0xb4e73c8a, + 0x96c098e3, 0x3fed6698, 0xe7c1ae1e, 0x5f121099, 0x11ab5a83, 0xb10a68d8, 0xe8470928, 0x66953229, + 0x5eae475b, 0xce1a6215, 0xd2eb2572, 0x174cd8c5, 0xc1b37abc, 0x67bf18bb, 0x186d6dc3, 0x06d89456, + 0x738a62d6, 0xbf20f90f, 0xb1e0b6be, 0xd7e3e12b, 0x39317145, 0x8be93c24, 0xaef84a3e, 0x41f3df92, + 0x40490af0, 0x69dd041b, 0x2f0bc1b8, 0x3a43583c, 0xc6726ba0, 0x603ac654, 0x1a3b825d, 0x372da930, + 0xb688289f, 0xb008ba4e, 0xa04dfd82, 0x959ad88d, 0xeef18154, 0x2d050581, 0x81a60e7a, 0x1b04f8f8, + 0xecbc2bca, 0xc67f2ce9, 0x623847e1, 0x8a1b2235, 0x4bb1a652, 0xbe5b0d17, 0x6f93151a, 0x34ab610d, + 0xc6ff00b4, 0x16241d84, 0x6e704597, 0x5f52c3ac, 0x0a77eb46, 0xbf9dd22c, 0xcad79394, 0x68a329d8, + 0x85c71552, 0x3ed3d22f, 0xfd6601e2, 0xc0968ca4, 0x3993c1bc, 0xb40b58bf, 0x0b1a61b1, 0x7521c175, + 0x5005f3b5, 0x80ec6156, 0x1e2bea2c, 0xcb550f61, 0x7b35edf8, 0xae7c0388, 0x8b970c14, 0x7f6bcb23, + 0x2693e008, 0x3ddf6bd4, 0xf5881878, 0x5426dc41, 0x7d62942d, 0xb90ca12a, 0x130203a6, 0xe19a59c7, + 0x3471f664, 0x9928692c, 0x180a25d5, 0xf63b679c, 0x3c3fbf3a, 0x315a89a2, 0xdc1c408d, 0x9fdd51bf, + 0xea43978e, 0xb1f3ff68, 0xf29aa2cb, 0x67063220, 0xf2109dc3, 0xe001e8f8, 0x2a621a87, 0x4d2450ec, + 0x61c241fe, 0xf0db2024, 0xeb528d24, 0xdae2f74f, 0xbb46da6b, 0xe3f3235c, 0x49197960, 0x88f8657a, + 0x22430738, 0xb63105b8, 0xad5e807e, 0xf5714249, 0x8eac01e0, 0x6d3b98ff, 0xe5f44225, 0x324aaf2f, + 0x6b866e2b, 0x05970c14, 0xcbfa93f5, 0x70c420b9, 0x8f316e27, 0xc988d0f7, 0x0fe76eab, 0xa9f6bc1e, + 0xa2ca023a, 0x513fe5e9, 0xdce2d4d3, 0x31946be8, 0x48736b49, 0xbd381e4c, 0x279a6441, 0x47723521, + 0xd6682ff3, 0x91d89738, 0x471a20a5, 0x7bd180a2, 0x7b22f2db, 0x9aaf39b8, 0xc23b1e4c, 0xbfe6cec3, + 0x050d9728, 0xe7a15d6a, 0xf7f7f013, 0x7c646b29, 0xbbe83d7c, 0x8741308a, 0x3d6749af, 0x1c6d1af5, + 0xfe3c2192, 0x57e5befc, 0x0e634f34, 0x62e3687b, 0xcaf6b6fe, 0x88c20547, 0x6c4e79e3, 0x396dbcb6, + 0x456c7bd7, 0x96a7eb16, 0xa8665d3a, 0xf1704b85, 0x2f358053, 0xe21b40c2, 0x5db87596, 0x4cf09f46, + 0x9d5e4a3d, 0x32ac4e72, 0x9bdea41e, 0xa5482f4a, 0x6a560d5b, 0x3f534541, 0x329140ee, 0x4db08497, + 0x13d971b3, 0x38fff9cd, 0x1799a92b, 0xf67fbe43, 0x2c0f4d7e, 0x818cf886, 0xea2457d5, 0x74cb7d41, + 0x38089c48, 0x5810daaa, 0xb904e229, 0x5dc8a98f, 0x5cb8b59a, 0xac7f3f01, 0xc970af08, 0x05fa1fb9, + 0x17a2ba3d, 0x292113c2, 0x60d33128, 0x1785d65a, 0xe5982508, 0xd79c3519, 0x6683091b, 0x1080b5f3, + 0xb8184f9c, 0xc99e794a, 0x09ef141d, 0xe0750711, 0x905de708, 0x23618695, 0x50497a87, 0x0235537d, + 0x98e6249d, 0x24528d33, 0x352109f9, 0xfed23f0a, 0xc973fa3b, 0x058b03a9, 0xc0ac8687, 0x3edc9b4e, + 0xbbe925dc, 0x4a92a992, 0xcb9ba5a8, 0x6a39f252, 0x3ea6060f, 0xdcdb0d71, 0xeff93630, 0xe20be088, + 0xd493c639, 0x3c89b1b0, 0xeb5fd043, 0x6172e0c3, 0xa44032b1, 0x99759caf, 0x8e4e1949, 0x4605519a, + 0xc723d5d3, 0x2f9b4e3c, 0xebbe1e2f, 0x1e972541, 0x6afa862f, 0xabece680, 0xc90c0343, 0x6a8b8d5e, + 0x3549314b, 0xb1f360ef, 0x82afb086, 0x417f7f19, 0xc19877c1, 0x73ff652f, 0xed1886b3, 0xdb5451e4, + 0xa96e8ab1, 0x518a3975, 0x5d218afb, 0x7de35abc, 0xaab78394, 0x3cdd1c5b, 0x24898b48, 0xd2c6ce0e, + 0x4fa851aa, 0xa3db9ed5, 0xa8b54d4d, 0xbf7f317b, 0x991a0195, 0x31413319, 0xc782e091, 0x6f5ea41e, + 0xf2df0283, 0x9f353de9, 0x7defccbf, 0xc45858c3, 0x5ec70941, 0x141cb58d, 0x3353e213, 0x16006992, + 0x538f4b70, 0x0a76db78, 0x74b313e5, 0xa77b640a, 0x27678620, 0x0586ef7d, 0xe5191c45, 0x42a47a15, + 0x60966bb0, 0xf5940b86, 0xccd8b42d, 0xbbde4cd9, 0xf48cd269, 0xe8d940ee, 0x61b9561c, 0xc6ee3241, + 0x47fd80d9, 0x09eb276c, 0xd481b58f, 0xed93d636, 0xee10463c, 0x5e59cab6, 0xac754eb7, 0x8af5d3f2, + 0x736da85d, 0x1f2a512c, 0xffaa037f, 0x5f1a1f91, 0xd548bbab, 0x4d6e0529, 0x44d78579, 0x1c8a3655, + 0x700758e7, 0xbd875495, 0x25d758cd, 0x02c1f2a5, 0xcd6f6b3f, 0x76e8f4e3, 0xacd4ab01, 0x0d3a0cb9, + 0x3557e9c4, 0xd5e38dad, 0x95f91a49, 0xf0e5971e, 0x265cd0c6, 0x27b4152d, 0xd57bff92, 0x5b9e4ce8, + 0x2a30f04e, 0x862d4677, 0x0d5d7174, 0xac5fb33a, 0xd6435b70, 0x1da86cc6, 0x4d8804ae, 0x90cf6d4d, +]); + pub const OWNER_LMS_KEY_PRIVATE: ImageLmsPrivKey = ImageLmsPrivKey { tree_type: IMAGE_LMS_TREE_TYPE, otstype: IMAGE_LMS_OTS_TYPE, @@ -237,6 +1196,246 @@ pub const OWNER_ECC_KEY_PRIVATE: ImageEccPrivKey = [ 0x59fdf849, 0xe39f4256, 0x19342ed2, 0x81d28d3d, 0x45ab3219, 0x5174582c, 0xecb4e9df, 0x9cc2e991, 0xb75f88fd, 0xfa4bc6a4, 0x6b88340f, 0x05dd8890, ]; +pub const OWNER_MLDSA_KEY_PUBLIC: ImageMldsaPubKey = ImageMldsaPubKey([ + 0xa9edf181, 0x8ca2903b, 0xd364ae34, 0xd614de58, 0x18e90b12, 0x8760caee, 0x57c06d4c, 0x1c431b7c, + 0x9a7d0f9e, 0xe9cdecea, 0xe6f4d4f2, 0x3fa5fa0e, 0x2161fa18, 0x98fdc152, 0x3bd34aab, 0x955161d2, + 0x44ea42d1, 0x14b25044, 0xcca768fb, 0xc426f8b2, 0x1b1dc6d7, 0x11d3c93e, 0x260b5dda, 0x01add04f, + 0xd43693d7, 0xd1fee110, 0x74c2b640, 0xb01b1e79, 0x6deca0b6, 0x9a0fc5af, 0xda30d600, 0x88d26c7b, + 0xc4c24cd6, 0x057ee05c, 0x23a4cdea, 0x2f5613a2, 0x004ae612, 0x406fbcd7, 0x5ad5fe27, 0x546191b7, + 0x7bbb6bff, 0xbc33fc3b, 0xc731c42e, 0xaee9844a, 0x53ed4a86, 0x80551327, 0xd1de8942, 0xbc6d8aff, + 0x33977eb9, 0x2ef8210f, 0x9d184cad, 0x1f9f8e52, 0xd653f2b3, 0xf07557ad, 0x1f08397f, 0xd67c1e8a, + 0x05dff2bf, 0x26697a4c, 0xa3f9b3c0, 0x35aae338, 0x4bd86680, 0x2ee3bdba, 0xb14dcc6b, 0xdae76a5b, + 0x5a234e5d, 0xeb9d9ee3, 0x763d8f90, 0xbb18e648, 0x8189d961, 0xa408ec7e, 0xee5ba5fd, 0x6e17938a, + 0xe0d1d617, 0x3dadfc75, 0xee2aa095, 0xa41013db, 0xb0e1c446, 0xf753f6bc, 0x57dfb5c4, 0x5a2a1b8d, + 0x20086118, 0x1dadc069, 0x405b37a3, 0x4861260a, 0xce801a93, 0x9a2664c0, 0x835d2b43, 0x27350d29, + 0x23b61b54, 0xa0ed01ba, 0x3b7655c8, 0xcd11b74c, 0x73fa4887, 0x34d4916a, 0x6c4807dd, 0x85924bc6, + 0x9ddc322d, 0x3abe0386, 0x153c9756, 0xd0cae283, 0x985f56f2, 0xc4975ca8, 0x3d931345, 0x292b12a4, + 0xb11335aa, 0x7b51ce33, 0xcc0d9f40, 0x32a36e01, 0xbcde7139, 0xca8ea361, 0x213310e9, 0xeb06c031, + 0xfff30efb, 0x3c8d9334, 0x0abc11ed, 0xd90174cd, 0xbf9a2892, 0x6c7f056e, 0x7bf52027, 0x02c38dbd, + 0x1fc6b7fe, 0x33e0a82a, 0x983e73f9, 0x16eff198, 0x424cc2e4, 0xda99a2a2, 0x7679eb69, 0x38b2e1b2, + 0xf8b7aa69, 0x099d7496, 0xbdca1bc8, 0x3239c2d3, 0xf1ede587, 0xbd259010, 0xf114abc3, 0x135fb877, + 0x5bdafc64, 0xf57ca311, 0x7d55a1ea, 0x6af2cca3, 0x1a5bf6d9, 0x816dcf83, 0x32133dbf, 0xa1c84b99, + 0xae14fb05, 0xdc56492f, 0x66c0c39e, 0xad83710c, 0xce9e6897, 0x8498fe4e, 0x7496ed64, 0x76a8e2e9, + 0x9eedb0bf, 0x37d564ac, 0xccc44941, 0xac25bafc, 0x2b928e78, 0x0153c082, 0x4a7a1d6f, 0xb68a130c, + 0x08108d48, 0xa1687f50, 0x606d1b20, 0x05e2485c, 0x63ce90b9, 0x802e4cd7, 0xc0858c6e, 0x76c5b634, + 0x2e4fe033, 0x7612c7c2, 0x023db18d, 0x63837a2f, 0x935d7d95, 0x4f945b1b, 0xc0daae44, 0x48223d2b, + 0x6a4dd3fc, 0x841888e1, 0xc70e42ed, 0x5f81ae17, 0x8867f430, 0xeac6f08a, 0x420a8cfb, 0xddeb5083, + 0x7873733d, 0x5f475385, 0x294295e2, 0xfb1f2db8, 0x6494d1e5, 0x7957b759, 0x4d028c27, 0xdd478840, + 0xdc68e7df, 0xdf41900b, 0x7cb582a0, 0xe04372f3, 0x3ba64c11, 0x4482541f, 0x5a047003, 0x36932a8f, + 0xbe8ab863, 0xc46cf851, 0x0e57d9fb, 0xb9c7d232, 0x1b9f3561, 0x4b51c902, 0xfbbc3b62, 0xb9434d66, + 0x75c60db3, 0x0fdd59fd, 0xc7cc5cd5, 0x1f86e668, 0x3b9497ef, 0x6476c761, 0x0bc2587f, 0x8f73ae50, + 0xa04c3f67, 0xcf8176c4, 0xc28bd63e, 0xe5232075, 0xdadf6262, 0xe3e9ba2f, 0x429f0860, 0xd7c855b0, + 0x51041db0, 0xb2ca6fe0, 0x396c284a, 0x11cdfe70, 0x3a980044, 0xd29ede2d, 0x80bbdb55, 0x0a6f8ad1, + 0x7f639ede, 0x72a1a813, 0xd81af86c, 0xbf5395fb, 0x7726acc5, 0x3b6fb30d, 0x322861bf, 0xec76a9c2, + 0xdd207eeb, 0x6f3d1ea7, 0x1a8d3f96, 0x930c7201, 0x371b6fa3, 0x4433c032, 0x8a00ea11, 0xf840c9df, + 0x6f5ba9b5, 0x8c38dd6a, 0x0d845211, 0xa15d3490, 0x8039bd57, 0x3b0e5041, 0x6aa08b83, 0x08d412e5, + 0x5474e803, 0x9c015cbd, 0x26a065fd, 0x0bee7534, 0xca1d9aa6, 0xc252daa6, 0x61619a88, 0x9d8850f7, + 0x439fc928, 0x99ca3ca6, 0x8bc9f696, 0xfa9cd591, 0xd458839c, 0x800c3844, 0xeaf3d1ec, 0xb2091964, + 0x29018964, 0x775b34a2, 0xd06de4b4, 0x6a25681b, 0x073fc9f8, 0x9188605f, 0x2c9c8e75, 0x6caf217f, + 0x49ff9c5a, 0x59f182ca, 0x7d4051ff, 0x6c0c83ab, 0xe5374894, 0x76fa7c70, 0x0078a93a, 0x50e7843a, + 0x3dfd2077, 0x7f7bef16, 0x91375673, 0xbdc22b88, 0x3e580c18, 0xaa43eb88, 0x6fec172f, 0x8d0e9256, + 0xece1bc9b, 0xce493fdd, 0x8969d311, 0x27676663, 0xf51e75f5, 0x00cd58bb, 0x01582bed, 0xdd5d5a24, + 0x6dfdec4f, 0x96d83661, 0x52ff4ad6, 0xc5715662, 0xb462bc46, 0x9bb58efe, 0x87f0c2b2, 0x0acc719b, + 0x61173b74, 0xbed67b3d, 0xd755d372, 0x1e811efb, 0x85779a8f, 0x55fbc12b, 0x1f386d46, 0xa5774522, + 0x14385289, 0xee4cd6fc, 0x652d160d, 0xe0788f01, 0x4141e9ef, 0x8160a67b, 0x4980141a, 0x9a3ecebb, + 0xf30614a7, 0x6dcd5387, 0xfa59906e, 0xfd86cca1, 0x6fe27d63, 0x89ae7cbf, 0x537c695e, 0x85915342, + 0x6dcce6e2, 0x345bd54e, 0x2002a238, 0x0509513d, 0x8cbb738b, 0x56419b12, 0xf58986c5, 0xae2e9152, + 0xa58b9904, 0x8d2c3015, 0x0bb68e79, 0x55ddacf1, 0x392223b6, 0x1262d7f3, 0xa17e595a, 0xb07850fb, + 0x05e0618e, 0x11b4a1d3, 0xb874d706, 0x33593c24, 0x00b06880, 0xda2ea3ba, 0x9ee72613, 0x2f30a0ba, + 0x703a5124, 0x43605551, 0xc9b4036c, 0x886edf8c, 0x330cc0f1, 0x622331d7, 0x50c2f160, 0x13045f4a, + 0x6d256f58, 0xee389395, 0x4e5276b9, 0xe07d3cbe, 0xacca856c, 0xf401596e, 0x80ead6c5, 0x24276a01, + 0x8f21b769, 0x6aec714a, 0xd9c82a5f, 0xe1f3d888, 0x39629df0, 0xf5285a0d, 0x6ac3ffd5, 0x9e172d30, + 0x3a224dd6, 0x11581a25, 0xcb029443, 0x71bfe4b4, 0xc43cb7e2, 0x46b4faaa, 0xeee795ff, 0xb3aad498, + 0x29964d98, 0xcdf245a9, 0x04de106f, 0x1042f8f1, 0x417ac1e1, 0x4396fd42, 0xd09ad4f3, 0xdae8eec8, + 0xde14cf86, 0x9c076dae, 0x2991ef52, 0xd38e041c, 0xe8c6b5ca, 0xf0ec147a, 0xd14e40b6, 0x3c3b6c88, + 0x68a02855, 0x80165424, 0xd3b18ce7, 0x13dc003b, 0x77764082, 0x90304a85, 0xe34674c5, 0x33ae75d9, + 0x63bf9638, 0x0f24e8fe, 0x80ce8f7e, 0x9b98a3f9, 0x28206561, 0x7e08dc2b, 0x904cadb0, 0x45a25183, + 0x1ff478dc, 0x83c34ec9, 0xfdb2bcd6, 0x2f2146fb, 0x9139bd89, 0x309bf6e5, 0x5b0fcb30, 0x2826fbbb, + 0x9e079a3e, 0xe5a1e804, 0x5f22236a, 0xef64b60f, 0xa0782191, 0x5c4fc08c, 0x5b1c1565, 0x8d07e923, + 0x12228a9f, 0x110f1a89, 0x778eb329, 0x071eca05, 0xdc5a40f7, 0x48e68677, 0x3affe364, 0x8444431a, + 0xde0de523, 0x2046267a, 0xe9575a36, 0x4ebc7d1b, 0x9c5f4851, 0x716c5f77, 0xb9ab7634, 0x15c7263c, + 0x039509e8, 0x332806ac, 0x03617595, 0x6fd4f350, 0xe856d73e, 0x267715cb, 0x74acc70e, 0x1fd15a90, + 0x51382b6a, 0x7e891b6e, 0x5f4a2522, 0xf96c6ea5, 0x699dcd73, 0xf933f8ff, 0x7f281bad, 0xf5e7b8a8, + 0xf2fd42ad, 0x5eb5b70b, 0xcc0ff682, 0xf104102a, 0x73799523, 0x1a69423b, 0xd01e5cc0, 0xdd68c064, + 0xf29e5036, 0x0376e13c, 0xd3202d76, 0x82167410, 0x9ba53d4e, 0x0d59f401, 0xb4d0162d, 0xfa140b74, + 0x670214d5, 0x3b5e8acb, 0xac1be132, 0x97e52a12, 0x957588dc, 0x9cc12968, 0x0b4d2665, 0x0cd524f1, + 0xb8e46f1d, 0xb41bea5d, 0x991cc28a, 0xa6a3ed19, 0x46fe159c, 0x3eff070e, 0x2740c5d7, 0xe9c38078, + 0x9dc8b6ff, 0xfe141cd9, 0xa4b95b04, 0x3b0f241f, 0xef8d6eaf, 0xe461f23c, 0x69f9200b, 0x4596757e, + 0xb8b11b89, 0x01e0ae5a, 0x38687fd1, 0x99d20225, 0x9a220401, 0xe7055116, 0x64230d61, 0xeb8a55fd, + 0x765f2bb9, 0x5eff9147, 0xa4c86af8, 0x5593e0eb, 0x96b82ca7, 0xc4814f2e, 0xd259e8d3, 0xbb1234ed, + 0xf6f38432, 0x899ba5a4, 0x6ff4225b, 0x9ee7117b, 0x4cad1aa1, 0xcb99a376, 0x3ea69eb9, 0x7c6b971f, + 0x29839dba, 0xc31db6f7, 0x69815b18, 0xb5343677, 0x73f81d85, 0xb277990d, 0x79ee8ad6, 0xbb177961, + 0x6bb475a6, 0x2204b474, 0x8b4aa996, 0x7fe608ea, 0x366aae72, 0x1aa5b878, 0xd529b26a, 0xadab4f38, + 0xf54baa55, 0xb69b0048, 0x55d1a676, 0xd7ab2146, 0x53b4eded, 0x70aab061, 0xa18f2250, 0x45280dc5, + 0x31bc9a28, 0x9b8d3797, 0xe2cb1ded, 0x7c036185, 0x40a096d8, 0x9ea26872, 0xd9afa9d5, 0xe605ec82, + 0x2901edae, 0xd9631cc7, 0x048cdb68, 0x8d3cdf75, 0x0829f08d, 0x593cfb9b, 0xd5bb0bc5, 0xcd320692, + 0xf42353cf, 0x548b8309, 0x84301f99, 0x848c3414, 0xec1b95ef, 0x7633b520, 0x490fb309, 0x4be3337c, + 0x710fba4d, 0x604a628c, 0x86369ca7, 0xf16d4fcc, 0xc0aa76db, 0xcb31420f, 0xed8258bb, 0x1f9475f7, + 0xb40a83e2, 0x81cc090c, 0x0d40bda7, 0x669fc89d, 0xa45a9a13, 0x3c94fc17, 0x2c2a4ad1, 0x073d85fd, + 0xc6770a51, 0xced5344f, 0xdd079bd5, 0x1db63096, 0x4369137d, 0xe3c630b8, 0x8d1dea6c, 0x132db9fa, + 0x17356e05, 0x97b46adf, 0x0f1110d7, 0xd51cc9d9, 0xa6f45ae4, 0x1b80f8a2, 0x48784324, 0xfacfa6de, + 0x872f6713, 0xfd469ddd, 0xce3fed1e, 0x1f563412, 0xbcd00aae, 0x6ebf366a, 0x4127d1d7, 0x67a6ae1b, + 0x0c88b9b2, 0x18067649, 0xb44fede0, 0xbbeed2b4, 0x7dc52499, 0xbd3bbbf4, 0x15b16ea1, 0x7b61ae52, + 0x09c4be4d, 0x421c22d1, 0xda6807cb, 0x91cc1b38, 0xe48b104f, 0x5512727c, 0xa56c9e15, 0xf140dd46, + 0x41df9ac8, 0x652b787c, 0xd5e0d7ca, 0x0cd0273b, 0x4018b74d, 0xdfeaaeb8, 0x27e1cf84, 0x6ccfd694, +]); + +pub const OWNER_MLDSA_KEY_PRIVATE: ImageMldsaPrivKey = ImageMldsaPrivKey([ + 0xa9edf181, 0x8ca2903b, 0xd364ae34, 0xd614de58, 0x18e90b12, 0x8760caee, 0x57c06d4c, 0x1c431b7c, + 0x96e09924, 0x3390088f, 0x4d2050f4, 0xf5b72751, 0x1b02227f, 0x924db512, 0x1e232203, 0x8e4b084e, + 0xe4e40d01, 0xa63ea9d9, 0xfc282aa4, 0xd0029632, 0x07aed24d, 0xdf7f7abc, 0x30dbe1b8, 0x4af84aa4, + 0x0262e156, 0xeef18774, 0xe0a0d2a0, 0xfa132f76, 0x15b720d2, 0x6772af13, 0x89f1e394, 0x22d54bca, + 0x80480581, 0x1601e0a6, 0x2192a881, 0x11a388d1, 0x0292d426, 0x211ba169, 0x0331861a, 0xc7890a01, + 0x8c0ca56d, 0x24466444, 0x40840201, 0x4d102010, 0x18c00c13, 0x430613b6, 0x6480c864, 0x20b86c02, + 0x95290a35, 0x26923484, 0x51408093, 0x38851b15, 0x8adaa06d, 0xe4c02880, 0x02659b22, 0x8ddb3068, + 0x9122625b, 0x30121809, 0x90032052, 0x0c4348d1, 0x208c6294, 0x6d54c884, 0x48465004, 0xa32d0027, + 0x4ccac200, 0x4ac270a2, 0x12690c21, 0x45538468, 0x48062223, 0x16466320, 0x225c1202, 0x4a2225cb, + 0x20258912, 0x10533426, 0x62b44c43, 0x86300887, 0x4cc8a208, 0x24b86188, 0x12690ac8, 0x911a1764, + 0x90b00102, 0x138a0ba6, 0x4122b764, 0x08262a42, 0x842844a6, 0x84111982, 0x80186d00, 0x12062398, + 0x28ca346e, 0xe1a288d1, 0x4441d3c6, 0x9118b809, 0x44924844, 0x220c1047, 0x05091000, 0x5a2821da, + 0x18481b91, 0x41581640, 0xd93001c9, 0xc2000b98, 0x6d8b1022, 0xe2c401d1, 0x9444cc22, 0x49988068, + 0xe138090b, 0x329122a5, 0x29200046, 0x59b80820, 0x112849b4, 0x7189c04d, 0x1cc23023, 0x1221dc16, + 0x31c3a005, 0x0015485b, 0x2406ca00, 0x6ca0a820, 0x50a44ca1, 0x968d5394, 0x81c03671, 0xa2304ad2, + 0x98210091, 0x20134569, 0x90166cdc, 0x3270e290, 0x080a894c, 0x43102892, 0x92504ba6, 0x8c64046c, + 0x4438415c, 0x14711491, 0x8511a144, 0x904405dc, 0x28125904, 0x4220a751, 0xa1a020a3, 0x24219c30, + 0x6080c491, 0x19270d12, 0x42041a33, 0x8a42c620, 0xd2888090, 0xa6901034, 0x00101884, 0x042189da, + 0x424dc4b2, 0x08531020, 0x91949054, 0x38302238, 0x40120210, 0x0b320512, 0xc6451380, 0x8889826d, + 0xa44802dc, 0x84308892, 0x251c3900, 0x19b16993, 0xc2884bb8, 0x001ca568, 0x44400490, 0x32421ac4, + 0x65cb322a, 0x9ac49110, 0x8445c408, 0x894a044a, 0x01c33158, 0x22889884, 0x69a21872, 0xca2826d0, + 0x20291126, 0x50c31011, 0x042101c9, 0x044a6218, 0x8d5b9831, 0x43004ec8, 0x92852281, 0x4c200071, + 0x80a29008, 0xa7400a19, 0x28023869, 0xc34882c2, 0xb4490840, 0x4a644442, 0x4cb8444a, 0x068262c6, + 0x401a1065, 0x0bc320d4, 0x486a00b7, 0x08432865, 0x0a8691a1, 0xa22de4b8, 0x4142c62d, 0x00845019, + 0xb184cca4, 0x09133262, 0x50b28112, 0x25621bb0, 0x4493b681, 0xa4a489c9, 0x12850c47, 0x651b8908, + 0x903491c0, 0x346d6142, 0x0943b025, 0x09914098, 0x24045148, 0x0e0a8421, 0x9ba80ce2, 0x10210829, + 0x64e42230, 0x8b9221d9, 0xc6840017, 0x20021545, 0x11262211, 0x334600c6, 0x4112128e, 0x99a84823, + 0xb20c0c12, 0x0d1b4068, 0x88b28921, 0x276d0384, 0x04049471, 0x91980943, 0xb804c1b6, 0x2c614848, + 0x49200ad3, 0x42451117, 0x1001a405, 0xd9086220, 0x40212384, 0x11024770, 0x200791c8, 0x168a91a8, + 0x48182006, 0x899425e4, 0xc0884226, 0x889a9880, 0x02284802, 0x39325206, 0x8ee24092, 0xc8082ee4, + 0x80218cb6, 0x10128610, 0x48160990, 0x081288a6, 0x0593a220, 0x58282c82, 0x28288908, 0x68214684, + 0x02a0655a, 0x1691d326, 0x8d4bc669, 0x4cb8640c, 0x32845024, 0x31cba085, 0x94948c1c, 0x928cd428, + 0x20230502, 0xc0946d21, 0x29641b88, 0x3022436d, 0x8a4431d2, 0xa044a042, 0x72011341, 0x02372ae0, + 0xb60d1b07, 0x0ee13060, 0x04094a8b, 0x16319bc0, 0x604b862c, 0x8b042219, 0x282899c4, 0x218c1050, + 0x00986511, 0x22900b15, 0x45d42484, 0x9c084043, 0xa6895244, 0x00094240, 0x914805da, 0xc02ca214, + 0x84120469, 0x5c388520, 0x024494a4, 0x70904020, 0x512226a3, 0x408d0b15, 0x2a422262, 0x03898cd2, + 0x4825d8a6, 0x0108478d, 0xa0906c19, 0xc10d8346, 0x6d13386c, 0xa0220259, 0x18666112, 0x6420116a, + 0x1238611b, 0xc00d1381, 0x680c0068, 0x12340c64, 0x329092b0, 0x21c8400a, 0x8014850a, 0x424e2012, + 0x6d9ab86d, 0xd432881a, 0xa8718306, 0x02611009, 0x04252d40, 0xa671e008, 0x6808376c, 0x64106899, + 0x2485e102, 0x641b4064, 0xa0088444, 0x90056342, 0x24c19844, 0x90926190, 0x22210083, 0x21118720, + 0x23b66cd1, 0x28259904, 0x8c00260a, 0x4a2868da, 0x406c4b44, 0x6189b86c, 0xa4088688, 0x342c4c28, + 0x92002232, 0x82a28494, 0x248c1ac8, 0x8062a451, 0x81a088c9, 0x40711405, 0x6e422649, 0x01044920, + 0x30085cc0, 0x2849c810, 0x4b180d9b, 0x84894a34, 0x31d92629, 0x1917011c, 0x007221c7, 0x51244844, + 0x42101114, 0x87516126, 0x06818664, 0x24948d21, 0x06290c08, 0x21432289, 0x218689cb, 0x38015c38, + 0x2dd8466a, 0x8c002018, 0x346553a8, 0x09838071, 0xd01010c8, 0x04081c39, 0x6958b209, 0x64486e18, + 0xb125e410, 0x2c821269, 0x49404822, 0x0082e412, 0x68db3204, 0x01c39053, 0x862c2133, 0x2e5a1490, + 0x1ac22444, 0x10240b26, 0x1008a828, 0x191025c1, 0x20809a82, 0x690c1411, 0x01185202, 0x205044c4, + 0x2cc90064, 0xe3862548, 0xb42d2346, 0x1054b88c, 0xd1025223, 0x3360c294, 0x0510122e, 0xdab849d0, + 0x04910986, 0x8c1c4810, 0x24b37142, 0x12425a92, 0x25242944, 0x54b04110, 0x260ecac0, 0x0d649829, + 0xe8b9c7f9, 0xc23dbc6b, 0x4220609d, 0x1f24e383, 0xe8166c04, 0x1c6acaed, 0x3c793662, 0x5789659c, + 0x2049e56e, 0x28525f79, 0xf5555fc1, 0x0b4e6814, 0x1b6acc83, 0xf0676949, 0x11180962, 0xd9917486, + 0xf8f27850, 0x8cfb76b6, 0xeda5b6b3, 0x3320a838, 0xf881b854, 0x9a8734ac, 0x9961416b, 0x6d599ab6, + 0x200a7153, 0x31a3ae66, 0x949e21f8, 0xfc1baf69, 0x6f842410, 0x6a6a7843, 0x1096b8a7, 0x3d679633, + 0x27816715, 0x022361de, 0x136e3ac3, 0xe9de78e1, 0x759ddb9f, 0x39a47760, 0x31c516a3, 0xebb0d646, + 0x546dee41, 0xd7c63fdb, 0x3ee71e0c, 0x65d95bc0, 0x36485f66, 0x872dacd1, 0x0519a0e9, 0xfc3756c0, + 0x44742f5a, 0xbd08f1af, 0xf8cc5855, 0xc00834e2, 0x867bed1e, 0x20309bd9, 0x9d7799af, 0xd66dc882, + 0x2c513bf3, 0x02c674c2, 0xc63c4fc5, 0x3e1ac8aa, 0xf59f2eab, 0x037058c2, 0x9b009798, 0x1537b864, + 0x9cbb3e73, 0xd960cb98, 0x49a0b1c3, 0x6dc496c2, 0xc259f374, 0xad6d8313, 0x658aafdf, 0xfad50391, + 0x69070ddd, 0xb478112d, 0x219b270c, 0x24d5c164, 0xa790c775, 0x6b06fadb, 0xe99bf637, 0xc78783fe, + 0x6201a263, 0x1aa807fd, 0xc4bcf998, 0x6cb44a4d, 0x73f49f17, 0x8e97e557, 0xa73198b2, 0xdacc791e, + 0x536eab9d, 0x4ace9692, 0x9e0ed687, 0xb53ec019, 0xf2ddd342, 0x338a90ce, 0x2ca620c0, 0xdaa1e1df, + 0xa17eb53d, 0x637a9ef7, 0x8632738d, 0xe9a4be38, 0x7e67a8d1, 0xe53a8876, 0xcdfc829b, 0x02c4b16a, + 0x51782d1a, 0xe5543849, 0x71dcec5d, 0xa4ec3caf, 0x172c6d9e, 0x34f7a8a2, 0x07c6b3c3, 0xcd346c19, + 0x0c585e77, 0x7f8ef441, 0x43f5a58e, 0xdca6b700, 0x30a4ef7d, 0xbee8c7cb, 0xc6dc09d1, 0xffd897e3, + 0x756a95a2, 0xb791dda0, 0x57ea01da, 0xd58e53ba, 0xc37334ad, 0x786addd8, 0x6882c7ad, 0xcb77c4b4, + 0xd497f47b, 0x44305bcd, 0xb85cc8f7, 0x5ecd4efe, 0x76223a43, 0x4474ca8e, 0x1cf467e5, 0xf73dab15, + 0x64fe66f4, 0xfc03b12a, 0xbaafe69a, 0x9f85d30a, 0x30cf54ec, 0x91477b87, 0xf0f86b72, 0xc7ea4b05, + 0xdba9ef2c, 0x0b6de1a6, 0xad135073, 0xc7d6bad3, 0x18ea282e, 0xe5ee87b6, 0x90dd1da2, 0xc209f08e, + 0xaabd400a, 0xe898a156, 0xc41902d5, 0x70f1e261, 0x4affdb75, 0x3d387ecf, 0x269e7e4c, 0x28d6f46e, + 0x4695378c, 0xb15dcb9e, 0xfc8f0e8e, 0xda7baa8e, 0xffe031ad, 0x5f524886, 0x7a9bce75, 0xcc84f37b, + 0xc30b9b00, 0x0a6ab5a4, 0x22ea5fcd, 0x81ff5fbf, 0xeec75195, 0xb3e9a80d, 0xf012a016, 0x3b630fcb, + 0x64c81c97, 0x2d0a94ac, 0x92d16ca1, 0xf43e3b6e, 0xdf411d87, 0xc7eaf235, 0x822d3988, 0xc38e7708, + 0x9a88cecc, 0x0fe8d7a9, 0x09dc4281, 0x74081bbd, 0x2287cd53, 0xf4420b3a, 0x63ac2dd8, 0xccb970cd, + 0x694777ce, 0x93b5d4ea, 0xc1d77e08, 0xd4f3ec57, 0xe3819b61, 0x262495c0, 0xd1ede1b1, 0x6cad8aad, + 0x5af6dbc4, 0xd8e88da1, 0x85105b3e, 0xe6249caa, 0xc4ecb948, 0x9a1f9968, 0xa794346f, 0x554c5f41, + 0x2bead684, 0x3921a44a, 0xd8065e60, 0x0a3a8eca, 0x88b54852, 0x6642a521, 0xe4ab32e3, 0x7672249d, + 0x04cb729c, 0x5dc6d091, 0x433951c2, 0x30e63ce8, 0x0cfdc827, 0x90ea4bb1, 0x22e958d8, 0x03463b16, + 0xc4d531c6, 0x6b84084f, 0xe0dbd384, 0x12191ed3, 0xf663555f, 0x4aa7fde0, 0xafdb367f, 0x54c379a1, + 0xfa6ce9ae, 0xd42da422, 0xe415c0aa, 0xc85bdbad, 0x8629efc4, 0xbd150a35, 0x1d276e43, 0x201b42fa, + 0xb21a7fb1, 0xacc33522, 0x51b22a7a, 0x2dec4eff, 0xa0043754, 0x7f779d8a, 0x8ca10220, 0xda3c472e, + 0xa58c8f3c, 0x96ac701f, 0x58b99778, 0x10285fa8, 0x90861cc0, 0x48cfc58f, 0xfd645307, 0x621297fc, + 0x2ff0584a, 0x68db0197, 0xd97d1704, 0x804e8d4a, 0x02e283fb, 0x27ec1473, 0x72865316, 0xa54c6812, + 0x4806a764, 0x91a75120, 0x6bc17bf0, 0x05810793, 0x0013abb4, 0x4eb1cd77, 0x6a74a433, 0xa7753557, + 0x19d405cc, 0xa7526138, 0x716357c7, 0x03591820, 0x4179a9ca, 0x2567f0db, 0x23839632, 0x34511972, + 0x85a08f21, 0xaf31fda6, 0xbe348234, 0xd3b7a044, 0x6cdb9efa, 0xcb3da517, 0x1b05ee9b, 0xefcf07ca, + 0x4da1cbb1, 0x406508dd, 0x8e2288da, 0x190a8c79, 0x8d4a1146, 0xe3a51f72, 0xb7c4dabd, 0xa432e88c, + 0xd2aad6ca, 0x34c59ba6, 0x1c23f041, 0xd7cc940e, 0xd62a7fba, 0x38157303, 0x17d3cc14, 0xb0cafb46, + 0xcc43536a, 0xd705059e, 0x55ef2e5f, 0x85b495bf, 0x76b8cfc4, 0xb2c0e926, 0x751c50a2, 0x3af6a072, + 0x2bddd143, 0x6f3a8b33, 0x83232fb8, 0x767d34c6, 0x91b36a46, 0xd2c9b1f2, 0x5c727391, 0xdc78b7fc, + 0xcf8a8141, 0xe4ac79cf, 0x49b9c046, 0xe992bf74, 0x62c888e3, 0xed890ef7, 0x4cbbad2c, 0x00c8a3f6, + 0xf7fbd420, 0x70bcfaac, 0x3703db70, 0xe9534913, 0x42922ddc, 0xf435dafa, 0x79e474b8, 0x8f45eca6, + 0xd345b788, 0xd1bb7400, 0x1ba4ef65, 0xec227365, 0xaa61e5c5, 0x885039e9, 0x4d82d065, 0xcfba7fbb, + 0x7e7a70c4, 0x88ec55d5, 0x7f0408c7, 0xc2319441, 0x29559cd1, 0x2b6aa5c3, 0xa1587b2b, 0xe8bdb4c3, + 0x8ca1c0de, 0x2d320459, 0x3d90584e, 0x54524bb3, 0x5022bef2, 0x38d12c32, 0x7f12b4ec, 0xe081434f, + 0x14cc84a2, 0x448e3844, 0x97b3cade, 0x4f05b16f, 0xc1ecccbd, 0xe5d83abd, 0x45789747, 0xee5a0b4f, + 0x03341703, 0x028e4f4c, 0x8df55734, 0x7dca8211, 0x5876ed05, 0x03a32b26, 0xbc158747, 0x0e3f127e, + 0xeb5eaffb, 0x3a084860, 0x3a293513, 0x15ac4a85, 0xad8aafa3, 0xf66177ef, 0x71f4edbe, 0x333871a3, + 0x7cbd5a35, 0x566ccc75, 0x9ceac3d6, 0xc83669b4, 0xf3bcc824, 0x1f3ae324, 0x43b4bc7b, 0x0e89c64b, + 0x64a6d5ae, 0x431dc05f, 0xa3fa240f, 0xb554ad67, 0x79fb1001, 0xc0ebbb03, 0x2e9d8315, 0x8a5d4e41, + 0xb6e14048, 0xf2dddb9b, 0x53e893ac, 0x7bd7d7ce, 0x15f24cd3, 0x387faa8c, 0x0a383d3e, 0x07edc260, + 0x1400221d, 0x5b20954b, 0xff9a5bfa, 0xb4796281, 0x54f864f3, 0x9b44501b, 0xa9f7db70, 0x59a68e41, + 0x032eafd7, 0x6ae3ed54, 0xdab736f9, 0xc89e7293, 0x3a92fabd, 0x3a16232a, 0x50f82e42, 0xa10bee0b, + 0x6fae2e67, 0x80d6833c, 0x304f4952, 0xc5226ca9, 0x1cfc6e6b, 0x6ec7c4f4, 0x777e4e3d, 0xbfd5bafb, + 0x88a75583, 0x6005f437, 0xfd0e4806, 0xb4184a44, 0x3d3bb53a, 0x8586986b, 0xdb1a3460, 0x176036b8, + 0x51804b0f, 0x47aa649f, 0x89c403c6, 0x5eca96b6, 0x83eb71e1, 0x4b9f7092, 0xa69ec4e0, 0xaf1aa1de, + 0xfa91d553, 0xae7a87ae, 0x05aee90e, 0xa5f1d67c, 0x9b5b3a5a, 0x8eb36024, 0xaed5340b, 0x7b849665, + 0x9990b354, 0x0481d276, 0x37719dc4, 0xd6c6b670, 0x489a6191, 0xdf92ebf2, 0x2224e920, 0xf8b600a8, + 0x5908a149, 0x8acdbac1, 0x36122717, 0x5a153f58, 0x79b20e80, 0x5c206841, 0x3c13d457, 0x8326207c, + 0x9b2ccae9, 0x9b3974ef, 0xa13e0448, 0xa08f5e5d, 0x09d9d139, 0xcad491e6, 0x2f61d91e, 0xe732babe, + 0xade3d065, 0x764a37ef, 0xa96632b6, 0x32b025c8, 0xd0b13a16, 0x0ad89f96, 0x645b8557, 0x10b0f790, + 0xe9243d3a, 0xec9b4d3a, 0x75571796, 0xca6b3a50, 0x528ef73e, 0xdd3ebe43, 0x2049810d, 0xab256b64, + 0xe3cdb52d, 0xe6968fca, 0x6bc4b9f8, 0x0e435960, 0x0b162dd3, 0x5c54fc67, 0x8d2b96c7, 0x054ce5da, + 0x9ad99f7f, 0xb37baa12, 0x73ce5bde, 0x98381447, 0xb09792da, 0x892c2a92, 0x719aedca, 0xe203a4df, + 0x8380b847, 0x51a359aa, 0xf38e85b0, 0xe154b115, 0x1fbff8fc, 0x962fb5a0, 0xfdaa97bd, 0xa129620a, + 0x3ae88938, 0x4767bd22, 0x261a5cba, 0x0e8fef67, 0xa8d8ccd7, 0xfa7fd7c1, 0xb39cc047, 0x6bb69a1f, + 0xeb5f6afe, 0x8550dc3f, 0xc1323d50, 0xb0954273, 0xbfec3437, 0xed482668, 0x1b6c4f47, 0x2ce96a82, + 0x6c012381, 0xee4c7745, 0x49257789, 0xf481eb4e, 0x36a48493, 0xb2b90147, 0x9c5ff3cb, 0x6c4782c0, + 0x9e0a0137, 0x9b56445a, 0xdfbb5eec, 0xdf7e8b46, 0xc5bc0237, 0x33983f77, 0x377adb00, 0x9b263594, + 0x5bbfbc58, 0x50d3cac9, 0xfe52f22c, 0x28df0401, 0x55f772aa, 0xafdeb4e6, 0xf7f9c990, 0xdab1df3f, + 0x25c58828, 0x47c572b1, 0x47178007, 0xf26d0ba5, 0xa14498f3, 0xafab85bc, 0xbac276b9, 0x0137fa35, + 0x8a61d4a3, 0x4116049b, 0xe74cbb93, 0x111fceb5, 0xdfd59167, 0x19e99dd3, 0x44dfc252, 0x722b3cde, + 0xf2cd8879, 0xe0008864, 0x0cf9dfb4, 0xa055e582, 0xa35141b7, 0x2b2feff8, 0xc7889c65, 0xcaa20356, + 0xa23bcf57, 0x16f919b3, 0xa98d36b1, 0x1957b858, 0xca5a8b82, 0xbd1256d8, 0x5414753b, 0x877dafc6, + 0x86395346, 0x271913d6, 0x4284ab49, 0x74f00ac3, 0x907e3a19, 0xdc776637, 0x39905d92, 0xdc7e6540, + 0x29fc13ce, 0xf6444416, 0x01db39ad, 0x22c10bf4, 0xa2d95fbc, 0x26aad96d, 0xc83d64c2, 0x68b8d6be, + 0xfa99283e, 0x68f59e81, 0x90002aee, 0xbd364c68, 0xc9aba7d0, 0xba6467d4, 0x0c706523, 0x55f8331a, + 0x39aed764, 0x2469f25b, 0x31e63695, 0xb31f8825, 0x99f6b312, 0x249f0a26, 0xacc53a30, 0xe703773b, + 0x8f422869, 0x2028e3b6, 0x3b01fb82, 0xc640cdac, 0x391e3862, 0x58673342, 0x36aab4ba, 0xe2c6162e, + 0xc775aee7, 0x55f03353, 0x0d788b24, 0x94314ade, 0x97732da1, 0x98633625, 0x7fb5ef7e, 0x9e18a8a9, + 0x9be2ad60, 0x8ce63d60, 0x4f1642eb, 0x4f09b173, 0x02d75da7, 0xadca9607, 0x747cef0f, 0x6af08095, + 0x3a79c9ea, 0x3cf1dd97, 0xef4dde52, 0x4de93246, 0x7cb7f300, 0x4fc84fa3, 0xffb31118, 0xd062c26e, + 0x289f0763, 0x1ada6075, 0x5b4861ab, 0x926479bc, 0x4f7ffde1, 0x61962df3, 0xdbed6bd9, 0x4914b5b9, + 0xf47cee07, 0xefc3314c, 0x6a7a6f67, 0x90dccc5d, 0xb235a956, 0xc9cdd58d, 0x5b72dc1a, 0xbae72880, + 0xba002a6a, 0x1b47ba27, 0x310cda7d, 0xc712f080, 0x5418c6bd, 0xa786e406, 0xe342e51f, 0x7a89dd78, + 0xda3b85c6, 0x130854bc, 0x0c841032, 0xdecf3d38, 0x828280c4, 0xfd793fc5, 0xe42deeb1, 0xc2ca0835, + 0x56c5917e, 0x44dacce4, 0x3470f808, 0xa7069123, 0xefd5dd01, 0x0b891398, 0x16a2d2aa, 0x6fc0b54f, + 0xacaf0721, 0x00f1528d, 0x9d9b94d4, 0x0024ce52, 0x76022521, 0xb5fc9ace, 0xf8a2807f, 0xbaed124c, + 0x3e8f265c, 0x029d32b2, 0x8cd781cf, 0x30dab5c4, 0xe58533e5, 0xe36c473c, 0xe9a4bef9, 0x204dc928, + 0x06c5bb8c, 0x48e66f89, 0x466429ed, 0x8547bd23, 0x6e5429e1, 0x79f892d9, 0x4ae12005, 0xa8bf5d2f, + 0xca081816, 0x5003046d, 0x754f949d, 0xfd3ce99b, 0xe2d5b673, 0xc64dfa92, 0x58e6e616, 0x9d197ff4, + 0xad43a9b2, 0x19b1a2b7, 0x0c6ba056, 0x4ee60270, 0xefc06c28, 0x9ace693c, 0x15e48637, 0xcbf3da6d, + 0x4d3dead8, 0xe2cabbc9, 0x543fc38f, 0x6918599e, 0xb50dc0cf, 0x31623061, 0x9595fe5f, 0x92bcabe3, + 0xb86f2b58, 0x37b3ff6a, 0x0f7d1a97, 0xf8ae3b46, 0x2642c9b0, 0xe88e7c6d, 0xc31d5bf0, 0x3423f888, + 0xa8b94edd, 0x8110815f, 0x01d8bece, 0x22d13954, 0x0b91b4f4, 0x52877919, 0x3341edac, 0x70a08054, + 0x101eae37, 0xb2ee8b41, 0xa0143e10, 0x40945ebd, 0xe4fe71f1, 0xb599ff3c, 0xc923c3cf, 0x889f8708, + 0xa65f1eab, 0xeb4dee86, 0x74ce79f9, 0xc9920734, 0x619de7ef, 0x56c8ced8, 0x459ccd5b, 0x716dec10, + 0x18ef6b23, 0xfd15d916, 0xabd7dd35, 0x524da8d2, 0x4e018f01, 0xe1965985, 0xcad5cf3b, 0x96d9d398, + 0x1678fff8, 0xdf33d2cb, 0xdee41e97, 0xe3afd430, 0x315279d4, 0xd69e68ce, 0x7c08c6fb, 0xe873f1db, + 0xc61bee3b, 0x5b5def66, 0xbbea475b, 0x5d95fdf6, 0x615d22b1, 0x9078ecb8, 0x5b65387a, 0x039b9726, + 0xa5a06912, 0x4d9552b3, 0xde16916f, 0xe3b341bb, 0xef5f1c34, 0x70d5baef, 0x38774f0c, 0x63592edb, + 0xed63bc5d, 0x3284fe16, 0x77b81382, 0xa514d7c5, 0xecc9b4d7, 0xef4caac5, 0x0f2132ec, 0x0f59b2d1, + 0x844953aa, 0x6da7de93, 0x51517608, 0xe4979c9d, 0xae0ada00, 0xa4771757, 0xe04b7f77, 0x25e557e8, + 0x99937648, 0x00639c9f, 0x403ac714, 0x5b1333ba, 0x5f20370b, 0x665c6205, 0x9734759f, 0xedb7b002, +]); + pub const VENDOR_PUBLIC_KEYS: ImageVendorPubKeys = ImageVendorPubKeys { ecc_pub_keys: [ VENDOR_ECC_KEY_0_PUBLIC, @@ -278,11 +1477,18 @@ pub const VENDOR_PUBLIC_KEYS: ImageVendorPubKeys = ImageVendorPubKeys { VENDOR_LMS_KEY_2_PUBLIC, VENDOR_LMS_KEY_3_PUBLIC, ], + mldsa_pub_keys: [ + VENDOR_MLDSA_KEY_0_PUBLIC, + VENDOR_MLDSA_KEY_1_PUBLIC, + VENDOR_MLDSA_KEY_2_PUBLIC, + VENDOR_MLDSA_KEY_3_PUBLIC, + ], }; -pub const OWNER_PUBLIC_KEYS: ImageOwnerPubKeys = ImageOwnerPubKeys { +pub const OWNER_PUBLIC_KEYS: OwnerPubKeyConfig = OwnerPubKeyConfig { ecc_pub_key: OWNER_ECC_KEY_PUBLIC, lms_pub_key: OWNER_LMS_KEY_PUBLIC, + mldsa_pub_key: OWNER_MLDSA_KEY_PUBLIC, }; pub const VENDOR_PRIVATE_KEYS: ImageVendorPrivKeys = ImageVendorPrivKeys { ecc_priv_keys: [ @@ -325,19 +1531,27 @@ pub const VENDOR_PRIVATE_KEYS: ImageVendorPrivKeys = ImageVendorPrivKeys { VENDOR_LMS_KEY_2_PRIVATE, VENDOR_LMS_KEY_3_PRIVATE, ], + mldsa_priv_keys: [ + VENDOR_MLDSA_KEY_0_PRIVATE, + VENDOR_MLDSA_KEY_1_PRIVATE, + VENDOR_MLDSA_KEY_2_PRIVATE, + VENDOR_MLDSA_KEY_3_PRIVATE, + ], }; pub const OWNER_PRIVATE_KEYS: ImageOwnerPrivKeys = ImageOwnerPrivKeys { ecc_priv_key: OWNER_ECC_KEY_PRIVATE, lms_priv_key: OWNER_LMS_KEY_PRIVATE, + mldsa_priv_key: OWNER_MLDSA_KEY_PRIVATE, }; pub const VENDOR_CONFIG_KEY_0: ImageGeneratorVendorConfig = ImageGeneratorVendorConfig { ecc_key_count: VENDOR_ECC_MAX_KEY_COUNT, lms_key_count: VENDOR_LMS_MAX_KEY_COUNT, + mldsa_key_count: VENDOR_MLDSA_MAX_KEY_COUNT, pub_keys: VENDOR_PUBLIC_KEYS, ecc_key_idx: 0, - lms_key_idx: 0, + pqc_key_idx: 0, priv_keys: Some(VENDOR_PRIVATE_KEYS), not_before: [0u8; 15], not_after: [0u8; 15], @@ -346,30 +1560,32 @@ pub const VENDOR_CONFIG_KEY_0: ImageGeneratorVendorConfig = ImageGeneratorVendor pub const VENDOR_CONFIG_KEY_1: ImageGeneratorVendorConfig = ImageGeneratorVendorConfig { ecc_key_idx: 1, - lms_key_idx: 1, + pqc_key_idx: 1, ..VENDOR_CONFIG_KEY_0 }; pub const VENDOR_CONFIG_KEY_2: ImageGeneratorVendorConfig = ImageGeneratorVendorConfig { ecc_key_idx: 2, - lms_key_idx: 2, + pqc_key_idx: 2, ..VENDOR_CONFIG_KEY_0 }; pub const VENDOR_CONFIG_KEY_3: ImageGeneratorVendorConfig = ImageGeneratorVendorConfig { ecc_key_idx: 3, - lms_key_idx: 3, + pqc_key_idx: 3, ..VENDOR_CONFIG_KEY_0 }; pub const OWNER_CONFIG: ImageGeneratorOwnerConfig = ImageGeneratorOwnerConfig { - pub_keys: ImageOwnerPubKeys { + pub_keys: OwnerPubKeyConfig { ecc_pub_key: OWNER_ECC_KEY_PUBLIC, lms_pub_key: OWNER_LMS_KEY_PUBLIC, + mldsa_pub_key: OWNER_MLDSA_KEY_PUBLIC, }, priv_keys: Some(ImageOwnerPrivKeys { ecc_priv_key: OWNER_ECC_KEY_PRIVATE, lms_priv_key: OWNER_LMS_KEY_PRIVATE, + mldsa_priv_key: OWNER_MLDSA_KEY_PRIVATE, }), not_before: [0u8; 15], not_after: [0u8; 15], diff --git a/image/gen/Cargo.toml b/image/gen/Cargo.toml index 16a3aea9cd..eb251f5abc 100644 --- a/image/gen/Cargo.toml +++ b/image/gen/Cargo.toml @@ -15,3 +15,5 @@ caliptra-image-types = { workspace = true, features = ["std"] } caliptra-lms-types.workspace = true memoffset.workspace = true zerocopy.workspace = true +fips204.workspace = true +rand.workspace = true diff --git a/image/gen/src/generator.rs b/image/gen/src/generator.rs index f854bc8748..69115e4aaf 100644 --- a/image/gen/src/generator.rs +++ b/image/gen/src/generator.rs @@ -13,7 +13,11 @@ Abstract: --*/ use anyhow::bail; use caliptra_image_types::*; +use fips204::ml_dsa_87::{PrivateKey, SIG_LEN}; +use fips204::traits::{SerDes, Signer}; use memoffset::offset_of; +use rand::rngs::StdRng; +use rand::SeedableRng; use zerocopy::AsBytes; use crate::*; @@ -76,28 +80,49 @@ impl ImageGenerator { } let ecc_key_idx = config.vendor_config.ecc_key_idx; - let lms_key_idx = config.vendor_config.lms_key_idx; + let pqc_key_idx = config.vendor_config.pqc_key_idx; // Create Header let toc_digest = self.toc_digest(&fmc_toc, &runtime_toc)?; - let header = self.gen_header(config, ecc_key_idx, lms_key_idx, toc_digest)?; + let header = self.gen_header(config, ecc_key_idx, pqc_key_idx, toc_digest)?; // Create Preamble - let header_digest_vendor = self.header_digest_vendor(&header)?; - let header_digest_owner = self.header_digest_owner(&header)?; + let vendor_header_digest_384 = self.vendor_header_digest_384(&header)?; + let mut vendor_header_digest_holder = ImageDigestHolder { + digest_384: &vendor_header_digest_384, + digest_512: None, + }; + + let owner_header_digest_384 = self.owner_header_digest_384(&header)?; + let mut owner_header_digest_holder = ImageDigestHolder { + digest_384: &owner_header_digest_384, + digest_512: None, + }; + + let (vendor_header_digest_512, owner_header_digest_512); + + // Update vendor_digest_holder and owner_digest_holder with SHA512 digests if MLDSA validation is required. + if config.pqc_key_type == FwVerificationPqcKeyType::MLDSA { + vendor_header_digest_512 = self.vendor_header_digest_512(&header)?; + vendor_header_digest_holder.digest_512 = Some(&vendor_header_digest_512); + + owner_header_digest_512 = self.owner_header_digest_512(&header)?; + owner_header_digest_holder.digest_512 = Some(&owner_header_digest_512); + } + let preamble = self.gen_preamble( config, ecc_key_idx, - lms_key_idx, - &header_digest_vendor, - &header_digest_owner, + pqc_key_idx, + &vendor_header_digest_holder, + &owner_header_digest_holder, )?; // Create Manifest let manifest = ImageManifest { marker: MANIFEST_MARKER, size: core::mem::size_of::() as u32, - fw_image_type: config.fw_image_type.into(), + pqc_key_type: config.pqc_key_type.into(), reserved: [0u8; 3], preamble, header, @@ -115,14 +140,60 @@ impl ImageGenerator { Ok(image) } + fn mldsa_sign( + &self, + digest: &ImageDigest512, + priv_key: &ImageMldsaPrivKey, + ) -> anyhow::Result { + pub fn from_hw_format(value: &[u32]) -> [u8; NUM_BYTES] { + let mut result = [0u8; NUM_BYTES]; + for (i, &item) in value.iter().enumerate() { + let bytes = item.to_be_bytes(); + let start = i * 4; + if start + 4 <= NUM_BYTES { + result[start..start + 4].copy_from_slice(&bytes); + } else { + break; // Prevent overflow if the input slice is larger than NUM_BYTES / 4 + } + } + result + } + + let mut rng = StdRng::from_seed([0u8; 32]); + + // Private key is received in hw format. Reverse the DWORD endianess for signing. + let priv_key = { + let key_bytes: [u8; MLDSA87_PRIV_KEY_BYTE_SIZE] = + from_hw_format::(&priv_key.0); + PrivateKey::try_from_bytes(key_bytes).unwrap() + }; + + // Digest is received in hw format. Reverse the DWORD endianess for signing. + let digest: [u8; MLDSA87_MSG_BYTE_SIZE] = from_hw_format::(digest); + + let signature = priv_key.try_sign_with_rng(&mut rng, &digest, &[]).unwrap(); + let signature_extended = { + let mut sig = [0u8; SIG_LEN + 1]; + sig[..SIG_LEN].copy_from_slice(&signature); + sig + }; + + // Return the signature in hw format. + let mut sig: ImageMldsaSignature = ImageMldsaSignature::default(); + for (i, chunk) in signature_extended.chunks(4).enumerate() { + sig.0[i] = u32::from_be_bytes(chunk.try_into().unwrap()); + } + Ok(sig) + } + /// Create preamble pub fn gen_preamble( &self, config: &ImageGeneratorConfig, ecc_vendor_key_idx: u32, - lms_vendor_key_idx: u32, - digest_vendor: &ImageDigest, - digest_owner: &ImageDigest, + pqc_vendor_key_idx: u32, + vendor_digest_holder: &ImageDigestHolder, + owner_digest_holder: &ImageDigestHolder, ) -> anyhow::Result where E: ImageGeneratorExecutable, @@ -130,47 +201,68 @@ impl ImageGenerator { let mut vendor_sigs = ImageSignatures::default(); let mut owner_sigs = ImageSignatures::default(); + // Add Vendor Header Signatures. if let Some(priv_keys) = config.vendor_config.priv_keys { let sig = self.crypto.ecdsa384_sign( - digest_vendor, + vendor_digest_holder.digest_384, &priv_keys.ecc_priv_keys[ecc_vendor_key_idx as usize], &config.vendor_config.pub_keys.ecc_pub_keys[ecc_vendor_key_idx as usize], )?; vendor_sigs.ecc_sig = sig; - let lms_sig = self.crypto.lms_sign( - digest_vendor, - &priv_keys.lms_priv_keys[lms_vendor_key_idx as usize], - )?; - vendor_sigs.lms_sig = lms_sig; + if config.pqc_key_type == FwVerificationPqcKeyType::LMS { + let lms_sig = self.crypto.lms_sign( + vendor_digest_holder.digest_384, + &priv_keys.lms_priv_keys[pqc_vendor_key_idx as usize], + )?; + let sig = lms_sig.as_bytes(); + vendor_sigs.pqc_sig.0[..sig.len()].copy_from_slice(sig); + } else { + let mldsa_sig = self.mldsa_sign( + vendor_digest_holder.digest_512.unwrap(), + &priv_keys.mldsa_priv_keys[pqc_vendor_key_idx as usize], + )?; + + let sig = mldsa_sig.as_bytes(); + vendor_sigs.pqc_sig.0[..sig.len()].copy_from_slice(sig); + }; } + // Add Owner Header Signatures. if let Some(owner_config) = &config.owner_config { if let Some(priv_keys) = &owner_config.priv_keys { let sig = self.crypto.ecdsa384_sign( - digest_owner, + owner_digest_holder.digest_384, &priv_keys.ecc_priv_key, &owner_config.pub_keys.ecc_pub_key, )?; owner_sigs.ecc_sig = sig; - let lms_sig = self - .crypto - .lms_sign(digest_owner, &priv_keys.lms_priv_key)?; - owner_sigs.lms_sig = lms_sig; + if config.pqc_key_type == FwVerificationPqcKeyType::LMS { + let lms_sig = self + .crypto + .lms_sign(owner_digest_holder.digest_384, &priv_keys.lms_priv_key)?; + let sig = lms_sig.as_bytes(); + owner_sigs.pqc_sig.0[..sig.len()].copy_from_slice(sig); + } else { + let mldsa_sig = self.mldsa_sign( + owner_digest_holder.digest_512.unwrap(), + &priv_keys.mldsa_priv_key, + )?; + let sig = mldsa_sig.as_bytes(); + owner_sigs.pqc_sig.0[..sig.len()].copy_from_slice(sig); + }; } } let mut vendor_pub_key_info = ImageVendorPubKeyInfo { ecc_key_descriptor: ImageEccKeyDescriptor { version: KEY_DESCRIPTOR_VERSION, - intent: Intent::Vendor.into(), reserved: 0, key_hash_count: config.vendor_config.ecc_key_count as u8, key_hash: ImageEccKeyHashes::default(), }, pqc_key_descriptor: ImagePqcKeyDescriptor { version: KEY_DESCRIPTOR_VERSION, - intent: Intent::Vendor.into(), - key_type: KeyType::LMS.into(), + key_type: FwVerificationPqcKeyType::default() as u8, key_hash_count: config.vendor_config.lms_key_count as u8, key_hash: ImagePqcKeyHashes::default(), }, @@ -182,10 +274,23 @@ impl ImageGenerator { let ecc_pub_key_digest = self.crypto.sha384_digest(ecc_pub_key.as_bytes())?; vendor_pub_key_info.ecc_key_descriptor.key_hash[i as usize] = ecc_pub_key_digest; } - for i in 0..config.vendor_config.lms_key_count { - let lms_pub_key = config.vendor_config.pub_keys.lms_pub_keys[i as usize]; - let lms_pub_key_digest = self.crypto.sha384_digest(lms_pub_key.as_bytes())?; - vendor_pub_key_info.pqc_key_descriptor.key_hash[i as usize] = lms_pub_key_digest; + if config.pqc_key_type == FwVerificationPqcKeyType::LMS { + for i in 0..config.vendor_config.lms_key_count { + vendor_pub_key_info.pqc_key_descriptor.key_hash[i as usize] = + self.crypto.sha384_digest( + config.vendor_config.pub_keys.lms_pub_keys[i as usize].as_bytes(), + )?; + } + vendor_pub_key_info.pqc_key_descriptor.key_type = FwVerificationPqcKeyType::LMS.into(); + } else { + for i in 0..config.vendor_config.mldsa_key_count { + vendor_pub_key_info.pqc_key_descriptor.key_hash[i as usize] = + self.crypto.sha384_digest( + config.vendor_config.pub_keys.mldsa_pub_keys[i as usize].as_bytes(), + )?; + } + vendor_pub_key_info.pqc_key_descriptor.key_type = + FwVerificationPqcKeyType::MLDSA.into(); } let mut preamble = ImagePreamble { @@ -193,43 +298,34 @@ impl ImageGenerator { vendor_ecc_pub_key_idx: ecc_vendor_key_idx, vendor_ecc_active_pub_key: config.vendor_config.pub_keys.ecc_pub_keys [ecc_vendor_key_idx as usize], - vendor_lms_pub_key_idx: lms_vendor_key_idx, - vendor_lms_active_pub_key: config.vendor_config.pub_keys.lms_pub_keys - [lms_vendor_key_idx as usize], + vendor_pqc_pub_key_idx: pqc_vendor_key_idx, vendor_sigs, owner_sigs, ..Default::default() }; - if let Some(owner_config) = &config.owner_config { - let mut owner_pub_key_info = ImageOwnerPubKeyInfo { - ecc_key_descriptor: ImageEccKeyDescriptor { - version: KEY_DESCRIPTOR_VERSION, - intent: Intent::Owner.into(), - reserved: 0, - key_hash_count: 1, - key_hash: ImageEccKeyHashes::default(), - }, - pqc_key_descriptor: ImagePqcKeyDescriptor { - version: KEY_DESCRIPTOR_VERSION, - intent: Intent::Owner.into(), - key_type: KeyType::LMS.into(), - key_hash_count: 1, - key_hash: ImagePqcKeyHashes::default(), - }, - }; - - // Hash the ECC and LMS owner public keys. - let ecc_pub_key = owner_config.pub_keys.ecc_pub_key; - let ecc_pub_key_digest = self.crypto.sha384_digest(ecc_pub_key.as_bytes())?; - owner_pub_key_info.ecc_key_descriptor.key_hash[0_usize] = ecc_pub_key_digest; + // Store the PQC (LMS or MLDSA) vendor public key in the Preamble. + let pqc_pub_key = match config.pqc_key_type { + FwVerificationPqcKeyType::LMS => { + config.vendor_config.pub_keys.lms_pub_keys[pqc_vendor_key_idx as usize].as_bytes() + } + FwVerificationPqcKeyType::MLDSA => config.vendor_config.pub_keys.mldsa_pub_keys + [pqc_vendor_key_idx as usize] + .0 + .as_bytes(), + }; + preamble.vendor_pqc_active_pub_key.0[..pqc_pub_key.len()].copy_from_slice(pqc_pub_key); - let lms_pub_key = owner_config.pub_keys.lms_pub_key; - let lms_pub_key_digest = self.crypto.sha384_digest(lms_pub_key.as_bytes())?; - owner_pub_key_info.pqc_key_descriptor.key_hash[0_usize] = lms_pub_key_digest; + if let Some(owner_config) = &config.owner_config { + // Store the ECC owner public key in the Preamble. + preamble.owner_pub_keys.ecc_pub_key = owner_config.pub_keys.ecc_pub_key; - preamble.owner_pub_key_info = owner_pub_key_info; - preamble.owner_pub_keys = owner_config.pub_keys; + // Store the PQC (LMS or MLDSA) owner public key in the Preamble. + let pqc_pub_key = match config.pqc_key_type { + FwVerificationPqcKeyType::LMS => owner_config.pub_keys.lms_pub_key.as_bytes(), + FwVerificationPqcKeyType::MLDSA => owner_config.pub_keys.mldsa_pub_key.0.as_bytes(), + }; + preamble.owner_pub_keys.pqc_pub_key.0[..pqc_pub_key.len()].copy_from_slice(pqc_pub_key); } Ok(preamble) @@ -241,14 +337,14 @@ impl ImageGenerator { config: &ImageGeneratorConfig, ecc_key_idx: u32, lms_key_idx: u32, - digest: ImageDigest, + digest: ImageDigest384, ) -> anyhow::Result where E: ImageGeneratorExecutable, { let mut header = ImageHeader { vendor_ecc_pub_key_idx: ecc_key_idx, - vendor_lms_pub_key_idx: lms_key_idx, + vendor_pqc_pub_key_idx: lms_key_idx, flags: Self::DEFAULT_FLAGS, toc_len: MAX_TOC_ENTRY_COUNT, toc_digest: digest, @@ -273,26 +369,38 @@ impl ImageGenerator { } /// Calculate header digest for vendor. - /// Vendor digest is calculated upto the `owner_data` field. - pub fn header_digest_vendor(&self, header: &ImageHeader) -> anyhow::Result { + /// Vendor digest is calculated up to the `owner_data` field. + pub fn vendor_header_digest_384(&self, header: &ImageHeader) -> anyhow::Result { let offset = offset_of!(ImageHeader, owner_data); self.crypto .sha384_digest(header.as_bytes().get(..offset).unwrap()) } /// Calculate header digest for owner. - pub fn header_digest_owner(&self, header: &ImageHeader) -> anyhow::Result { + pub fn owner_header_digest_384(&self, header: &ImageHeader) -> anyhow::Result { self.crypto.sha384_digest(header.as_bytes()) } + /// Vendor digest is calculated up to the `owner_data` field. + pub fn vendor_header_digest_512(&self, header: &ImageHeader) -> anyhow::Result { + let offset = offset_of!(ImageHeader, owner_data); + self.crypto + .sha512_digest(header.as_bytes().get(..offset).unwrap()) + } + + /// Calculate header digest for owner. + pub fn owner_header_digest_512(&self, header: &ImageHeader) -> anyhow::Result { + self.crypto.sha512_digest(header.as_bytes()) + } + /// Calculate owner public key descriptor digest. - pub fn owner_pubkey_digest(&self, preamble: &ImagePreamble) -> anyhow::Result { + pub fn owner_pubkey_digest(&self, preamble: &ImagePreamble) -> anyhow::Result { self.crypto - .sha384_digest(preamble.owner_pub_key_info.as_bytes()) + .sha384_digest(preamble.owner_pub_keys.as_bytes()) } /// Calculate vendor public key descriptor digest. - pub fn vendor_pubkey_digest(&self, preamble: &ImagePreamble) -> anyhow::Result { + pub fn vendor_pubkey_digest(&self, preamble: &ImagePreamble) -> anyhow::Result { self.crypto .sha384_digest(preamble.vendor_pub_key_info.as_bytes()) } @@ -332,7 +440,7 @@ impl ImageGenerator { &self, fmc_toc: &ImageTocEntry, rt_toc: &ImageTocEntry, - ) -> anyhow::Result { + ) -> anyhow::Result { let mut toc_content: Vec = Vec::new(); toc_content.extend_from_slice(fmc_toc.as_bytes()); toc_content.extend_from_slice(rt_toc.as_bytes()); diff --git a/image/gen/src/lib.rs b/image/gen/src/lib.rs index d20a443abc..50c567669d 100644 --- a/image/gen/src/lib.rs +++ b/image/gen/src/lib.rs @@ -64,13 +64,16 @@ pub trait ImageGeneratorCrypto { Ok(hasher.finish()) } - /// Calculate SHA-384 digest - fn sha384_digest(&self, data: &[u8]) -> anyhow::Result; + /// Calculate SHA2-384 digest + fn sha384_digest(&self, data: &[u8]) -> anyhow::Result; + + /// Calculate SHA2-512 digest + fn sha512_digest(&self, data: &[u8]) -> anyhow::Result; /// Calculate ECDSA Signature fn ecdsa384_sign( &self, - digest: &ImageDigest, + digest: &ImageDigest384, priv_key: &ImageEccPrivKey, pub_key: &ImageEccPubKey, ) -> anyhow::Result; @@ -78,7 +81,7 @@ pub trait ImageGeneratorCrypto { /// Calculate LMS Signature fn lms_sign( &self, - digest: &ImageDigest, + digest: &ImageDigest384, priv_key: &ImageLmsPrivKey, ) -> anyhow::Result; @@ -87,6 +90,12 @@ pub trait ImageGeneratorCrypto { /// Read ECC-384 Private Key from PEM file fn ecc_priv_key_from_pem(path: &Path) -> anyhow::Result; + + /// Read MLDSA Public Key from file + fn mldsa_pub_key_from_file(path: &Path) -> anyhow::Result; + + /// Read MLDSA Private Key from file + fn mldsa_priv_key_from_file(path: &Path) -> anyhow::Result; } /// Image Generator Vendor Configuration @@ -96,11 +105,13 @@ pub struct ImageGeneratorVendorConfig { pub lms_key_count: u32, + pub mldsa_key_count: u32, + pub pub_keys: ImageVendorPubKeys, pub ecc_key_idx: u32, - pub lms_key_idx: u32, + pub pqc_key_idx: u32, pub priv_keys: Option, @@ -114,7 +125,7 @@ pub struct ImageGeneratorVendorConfig { /// Image Generator Owner Configuration #[derive(Default, Clone)] pub struct ImageGeneratorOwnerConfig { - pub pub_keys: ImageOwnerPubKeys, + pub pub_keys: OwnerPubKeyConfig, pub priv_keys: Option, @@ -131,7 +142,7 @@ pub struct ImageGeneratorConfig where T: ImageGeneratorExecutable, { - pub fw_image_type: FwImageType, + pub pqc_key_type: FwVerificationPqcKeyType, pub vendor_config: ImageGeneratorVendorConfig, diff --git a/image/types/src/lib.rs b/image/types/src/lib.rs index c645707836..a9f124d5f8 100644 --- a/image/types/src/lib.rs +++ b/image/types/src/lib.rs @@ -26,9 +26,11 @@ use memoffset::{offset_of, span_of}; use zerocopy::{AsBytes, FromBytes}; pub const MANIFEST_MARKER: u32 = 0x4E414D43; -pub const KEY_DESCRIPTOR_VERSION: u8 = 1; +pub const KEY_DESCRIPTOR_VERSION: u16 = 1; pub const VENDOR_ECC_MAX_KEY_COUNT: u32 = 4; pub const VENDOR_LMS_MAX_KEY_COUNT: u32 = 32; +pub const VENDOR_MLDSA_MAX_KEY_COUNT: u32 = 4; +pub const VENDOR_PQC_MAX_KEY_COUNT: u32 = VENDOR_LMS_MAX_KEY_COUNT; pub const MAX_TOC_ENTRY_COUNT: u32 = 2; pub const IMAGE_REVISION_BYTE_SIZE: usize = 20; pub const ECC384_SCALAR_WORD_SIZE: usize = 12; @@ -38,6 +40,7 @@ pub const SHA192_DIGEST_WORD_SIZE: usize = 6; pub const SHA256_DIGEST_WORD_SIZE: usize = 8; pub const SHA384_DIGEST_WORD_SIZE: usize = 12; pub const SHA384_DIGEST_BYTE_SIZE: usize = 48; +pub const SHA512_DIGEST_WORD_SIZE: usize = 16; pub const IMAGE_LMS_OTS_P_PARAM: usize = 51; pub const IMAGE_LMS_KEY_HEIGHT: usize = 15; pub const IMAGE_BYTE_SIZE: usize = 128 * 1024; @@ -46,9 +49,20 @@ pub const IMAGE_LMS_TREE_TYPE: LmsAlgorithmType = LmsAlgorithmType::LmsSha256N24 // LMOTS-SHA192-W4 pub const IMAGE_LMS_OTS_TYPE: LmotsAlgorithmType = LmotsAlgorithmType::LmotsSha256N24W4; pub const IMAGE_MANIFEST_BYTE_SIZE: usize = core::mem::size_of::(); +pub const MLDSA87_PUB_KEY_BYTE_SIZE: usize = 2592; +pub const MLDSA87_PUB_KEY_WORD_SIZE: usize = 648; +pub const MLDSA87_PRIV_KEY_BYTE_SIZE: usize = 4896; +pub const MLDSA87_PRIV_KEY_WORD_SIZE: usize = 1224; +pub const MLDSA87_SIGNATURE_BYTE_SIZE: usize = 4628; +pub const MLDSA87_SIGNATURE_WORD_SIZE: usize = 1157; +pub const MLDSA87_MSG_BYTE_SIZE: usize = 64; + +pub const PQC_PUB_KEY_BYTE_SIZE: usize = MLDSA87_PUB_KEY_BYTE_SIZE; +pub const PQC_SIGNATURE_BYTE_SIZE: usize = MLDSA87_SIGNATURE_BYTE_SIZE; pub type ImageScalar = [u32; ECC384_SCALAR_WORD_SIZE]; -pub type ImageDigest = [u32; SHA384_DIGEST_WORD_SIZE]; +pub type ImageDigest384 = [u32; SHA384_DIGEST_WORD_SIZE]; +pub type ImageDigest512 = [u32; SHA512_DIGEST_WORD_SIZE]; pub type ImageRevision = [u8; IMAGE_REVISION_BYTE_SIZE]; pub type ImageEccPrivKey = ImageScalar; @@ -66,6 +80,58 @@ pub struct ImageEccPubKey { pub type ImageLmsPublicKey = LmsPublicKey; pub type ImageLmsPrivKey = LmsPrivateKey; +#[repr(C)] +#[derive(AsBytes, FromBytes, Debug, Copy, Clone, Eq, PartialEq, Zeroize)] +#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))] +pub struct ImageMldsaPubKey(pub [u32; MLDSA87_PUB_KEY_WORD_SIZE]); + +impl Default for ImageMldsaPubKey { + fn default() -> Self { + ImageMldsaPubKey([0; MLDSA87_PUB_KEY_WORD_SIZE]) + } +} + +// [TODO][CAP2] Remove this once ZeroCopy crate is updated to 0.8.13 +impl ImageMldsaPubKey { + pub fn ref_from_prefix(bytes: &[u8]) -> Option<&Self> { + if bytes.len() >= size_of::() { + Some(unsafe { &*(bytes.as_ptr() as *const Self) }) + } else { + None + } + } + + pub fn mut_ref_from_prefix(bytes: &mut [u8]) -> Option<&mut Self> { + if bytes.len() >= size_of::() { + Some(unsafe { &mut *(bytes.as_mut_ptr() as *mut Self) }) + } else { + None + } + } +} + +#[repr(C)] +#[derive(AsBytes, FromBytes, Debug, Copy, Clone, Eq, PartialEq, Zeroize)] +#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))] +pub struct ImageMldsaPrivKey(pub [u32; MLDSA87_PRIV_KEY_WORD_SIZE]); + +impl Default for ImageMldsaPrivKey { + fn default() -> Self { + ImageMldsaPrivKey([0; MLDSA87_PRIV_KEY_WORD_SIZE]) + } +} + +#[repr(C)] +#[derive(AsBytes, FromBytes, Debug, Copy, Clone, Eq, PartialEq, Zeroize)] +#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))] +pub struct ImagePqcPubKey(pub [u8; PQC_PUB_KEY_BYTE_SIZE]); + +impl Default for ImagePqcPubKey { + fn default() -> Self { + ImagePqcPubKey([0; PQC_PUB_KEY_BYTE_SIZE]) + } +} + #[repr(C)] #[derive(AsBytes, FromBytes, Default, Debug, Copy, Clone, Eq, PartialEq, Zeroize)] #[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))] @@ -81,47 +147,81 @@ pub type ImageLmsSignature = LmsSignature; pub type ImageLmOTSSignature = LmotsSignature; -pub enum Intent { - Vendor = 1, - Owner = 2, -} +#[repr(C)] +#[derive(AsBytes, FromBytes, Debug, Copy, Clone, Eq, PartialEq, Zeroize)] +#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))] +pub struct ImageMldsaSignature(pub [u32; MLDSA87_SIGNATURE_WORD_SIZE]); -impl From for u8 { - fn from(val: Intent) -> Self { - val as u8 +impl Default for ImageMldsaSignature { + fn default() -> Self { + ImageMldsaSignature([0; MLDSA87_SIGNATURE_WORD_SIZE]) } } -pub enum KeyType { - ECC = 1, - LMS = 2, - MLDSA = 3, +// [TODO][CAP2] Remove this once ZeroCopy crate is updated to 0.8.13 +impl ImageMldsaSignature { + pub fn ref_from_prefix(bytes: &[u8]) -> Option<&Self> { + if bytes.len() >= size_of::() { + Some(unsafe { &*(bytes.as_ptr() as *const Self) }) + } else { + None + } + } + + pub fn mut_ref_from_prefix(bytes: &mut [u8]) -> Option<&mut Self> { + if bytes.len() >= size_of::() { + Some(unsafe { &mut *(bytes.as_mut_ptr() as *mut Self) }) + } else { + None + } + } } -impl From for u8 { - fn from(val: KeyType) -> Self { - val as u8 +#[repr(C)] +#[derive(AsBytes, FromBytes, Debug, Copy, Clone, Eq, PartialEq, Zeroize)] +#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))] +pub struct ImagePqcSignature(pub [u8; PQC_SIGNATURE_BYTE_SIZE]); + +impl Default for ImagePqcSignature { + fn default() -> Self { + ImagePqcSignature([0; PQC_SIGNATURE_BYTE_SIZE]) } } -#[derive(Copy, Clone)] -pub enum FwImageType { - EccLms = 1, - EccMldsa = 2, +#[derive(Copy, Clone, PartialEq, Eq)] +pub enum FwVerificationPqcKeyType { + LMS = 1, + MLDSA = 2, } -impl From for u8 { - fn from(val: FwImageType) -> Self { +impl From for u8 { + fn from(val: FwVerificationPqcKeyType) -> Self { val as u8 } } -impl Default for FwImageType { +impl Default for FwVerificationPqcKeyType { fn default() -> Self { - Self::EccLms + Self::LMS } } +impl FwVerificationPqcKeyType { + pub fn from_u8(value: u8) -> Option { + match value { + 1 => Some(FwVerificationPqcKeyType::LMS), + 2 => Some(FwVerificationPqcKeyType::MLDSA), + _ => None, + } + } +} + +#[derive(Debug)] +pub struct ImageDigestHolder<'a> { + pub digest_384: &'a ImageDigest384, + pub digest_512: Option<&'a ImageDigest512>, +} + /// Caliptra Image Bundle #[cfg(feature = "std")] #[derive(Debug, Default)] @@ -183,8 +283,8 @@ pub struct ImageManifest { /// Size of `Manifest` structure pub size: u32, - /// Firmware image type (ECC + LMS keys or ECC + MLDSA keys) - pub fw_image_type: u8, + /// PQC key type for image verification (LMS or MLDSA keys) + pub pqc_key_type: u8, pub reserved: [u8; 3], @@ -206,7 +306,7 @@ impl Default for ImageManifest { Self { marker: Default::default(), size: size_of::() as u32, - fw_image_type: 0, + pqc_key_type: 0, reserved: [0u8; 3], preamble: ImagePreamble::default(), header: ImageHeader::default(), @@ -223,10 +323,10 @@ impl ImageManifest { span.start as u32 + offset..span.end as u32 + offset } - /// Returns the `Range` containing the owner public key descriptors - pub fn owner_pub_key_descriptors_range() -> Range { + /// Returns the `Range` containing the owner public key + pub fn owner_pub_key_range() -> Range { let offset = offset_of!(ImageManifest, preamble) as u32; - let span = span_of!(ImagePreamble, owner_pub_key_info); + let span = span_of!(ImagePreamble, owner_pub_keys); span.start as u32 + offset..span.end as u32 + offset } @@ -250,6 +350,7 @@ pub struct ImageVendorPubKeys { pub ecc_pub_keys: [ImageEccPubKey; VENDOR_ECC_MAX_KEY_COUNT as usize], #[zeroize(skip)] pub lms_pub_keys: [ImageLmsPublicKey; VENDOR_LMS_MAX_KEY_COUNT as usize], + pub mldsa_pub_keys: [ImageMldsaPubKey; VENDOR_MLDSA_MAX_KEY_COUNT as usize], } #[repr(C)] @@ -263,19 +364,20 @@ pub struct ImageVendorPubKeyInfo { #[repr(C)] #[derive(AsBytes, FromBytes, Default, Debug, Clone, Copy, Zeroize)] -#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))] -pub struct ImageOwnerPubKeyInfo { - pub ecc_key_descriptor: ImageEccKeyDescriptor, - - pub pqc_key_descriptor: ImagePqcKeyDescriptor, +pub struct ImageVendorPrivKeys { + pub ecc_priv_keys: [ImageEccPrivKey; VENDOR_ECC_MAX_KEY_COUNT as usize], + #[zeroize(skip)] + pub lms_priv_keys: [ImageLmsPrivKey; VENDOR_LMS_MAX_KEY_COUNT as usize], + pub mldsa_priv_keys: [ImageMldsaPrivKey; VENDOR_MLDSA_MAX_KEY_COUNT as usize], } #[repr(C)] #[derive(AsBytes, FromBytes, Default, Debug, Clone, Copy, Zeroize)] -pub struct ImageVendorPrivKeys { - pub ecc_priv_keys: [ImageEccPrivKey; VENDOR_ECC_MAX_KEY_COUNT as usize], +pub struct OwnerPubKeyConfig { + pub ecc_pub_key: ImageEccPubKey, #[zeroize(skip)] - pub lms_priv_keys: [ImageLmsPrivKey; VENDOR_LMS_MAX_KEY_COUNT as usize], + pub lms_pub_key: ImageLmsPublicKey, + pub mldsa_pub_key: ImageMldsaPubKey, } #[repr(C)] @@ -283,8 +385,7 @@ pub struct ImageVendorPrivKeys { #[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))] pub struct ImageOwnerPubKeys { pub ecc_pub_key: ImageEccPubKey, - #[zeroize(skip)] - pub lms_pub_key: ImageLmsPublicKey, + pub pqc_pub_key: ImagePqcPubKey, } #[repr(C)] @@ -293,6 +394,7 @@ pub struct ImageOwnerPrivKeys { pub ecc_priv_key: ImageEccPrivKey, #[zeroize(skip)] pub lms_priv_key: ImageLmsPrivKey, + pub mldsa_priv_key: ImageMldsaPrivKey, } #[repr(C)] @@ -300,8 +402,7 @@ pub struct ImageOwnerPrivKeys { #[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))] pub struct ImageSignatures { pub ecc_sig: ImageEccSignature, - #[zeroize(skip)] - pub lms_sig: ImageLmsSignature, + pub pqc_sig: ImagePqcSignature, } /// Caliptra Image ECC Key Descriptor @@ -309,8 +410,7 @@ pub struct ImageSignatures { #[derive(AsBytes, Clone, Copy, FromBytes, Default, Debug, Zeroize)] #[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))] pub struct ImageEccKeyDescriptor { - pub version: u8, - pub intent: u8, + pub version: u16, pub reserved: u8, pub key_hash_count: u8, pub key_hash: ImageEccKeyHashes, @@ -321,16 +421,14 @@ pub struct ImageEccKeyDescriptor { #[derive(AsBytes, Clone, Copy, FromBytes, Default, Debug, Zeroize)] #[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))] pub struct ImagePqcKeyDescriptor { - pub version: u8, - pub intent: u8, + pub version: u16, pub key_type: u8, pub key_hash_count: u8, pub key_hash: ImagePqcKeyHashes, } -pub type ImageEccKeyHashes = [ImageDigest; VENDOR_ECC_MAX_KEY_COUNT as usize]; -pub type ImageLmsKeyHashes = [ImageDigest; VENDOR_LMS_MAX_KEY_COUNT as usize]; -pub type ImagePqcKeyHashes = [ImageDigest; VENDOR_LMS_MAX_KEY_COUNT as usize]; +pub type ImageEccKeyHashes = [ImageDigest384; VENDOR_ECC_MAX_KEY_COUNT as usize]; +pub type ImagePqcKeyHashes = [ImageDigest384; VENDOR_PQC_MAX_KEY_COUNT as usize]; /// Caliptra Image Bundle Preamble #[repr(C)] @@ -346,20 +444,16 @@ pub struct ImagePreamble { /// Vendor Active Public Key pub vendor_ecc_active_pub_key: ImageEccPubKey, - /// Vendor LMS Public Key Index - pub vendor_lms_pub_key_idx: u32, + /// Vendor PQC Public Key Index + pub vendor_pqc_pub_key_idx: u32, - /// Vendor Active LMS Public Key - #[zeroize(skip)] - pub vendor_lms_active_pub_key: ImageLmsPublicKey, + /// Vendor Active PQC (LMS or MLDSA) Public Key + pub vendor_pqc_active_pub_key: ImagePqcPubKey, /// Vendor Signatures pub vendor_sigs: ImageSignatures, - /// Owner Public Key Descriptor (no Key Hashes) - pub owner_pub_key_info: ImageOwnerPubKeyInfo, - - /// Owner Public Key + /// Owner Public Keys pub owner_pub_keys: ImageOwnerPubKeys, /// Owner Signatures @@ -408,8 +502,8 @@ pub struct ImageHeader { /// Vendor ECC Public Key Index pub vendor_ecc_pub_key_idx: u32, - /// Vendor LMS Public Key Index - pub vendor_lms_pub_key_idx: u32, + /// Vendor PQC Public Key Index + pub vendor_pqc_pub_key_idx: u32, /// Flags /// Bit 0: Interpret the pl0_pauser field. If not set, all PAUSERs are PL1. @@ -423,7 +517,7 @@ pub struct ImageHeader { pub pl0_pauser: u32, /// TOC Digest - pub toc_digest: ImageDigest, + pub toc_digest: ImageDigest384, /// Vendor Data pub vendor_data: VendorSignedData, @@ -498,7 +592,7 @@ pub struct ImageTocEntry { pub size: u32, /// Digest - pub digest: ImageDigest, + pub digest: ImageDigest384, } impl ImageTocEntry { diff --git a/image/verify/fuzz/src/fuzz_target_common.rs b/image/verify/fuzz/src/fuzz_target_common.rs index 5a39d1b07c..012330d4da 100644 --- a/image/verify/fuzz/src/fuzz_target_common.rs +++ b/image/verify/fuzz/src/fuzz_target_common.rs @@ -21,43 +21,43 @@ const IMAGE_BUNDLE_SIZE: u32 = 131072; * - Ensures bundle is being fuzzed well (by offsets). */ struct TestEnv { - digest: ImageDigest, - fmc_digest: ImageDigest, + digest: ImageDigest384, + fmc_digest: ImageDigest384, verify_result: bool, verify_lms_result: bool, - vendor_pub_key_digest: ImageDigest, + vendor_pub_key_digest: ImageDigest384, vendor_ecc_pub_key_revocation: VendorPubKeyRevocation, vendor_lms_pub_key_revocation: u32, - owner_pub_key_digest: ImageDigest, + owner_pub_key_digest: ImageDigest384, lifecycle: Lifecycle, } impl Default for TestEnv { fn default() -> Self { TestEnv { - digest: ImageDigest::default(), - fmc_digest: ImageDigest::default(), + digest: ImageDigest384::default(), + fmc_digest: ImageDigest384::default(), // PATCHED verify_result: true, // PATCHED verify_lms_result: true, - vendor_pub_key_digest: ImageDigest::default(), + vendor_pub_key_digest: ImageDigest384::default(), vendor_ecc_pub_key_revocation: VendorPubKeyRevocation::default(), vendor_lms_pub_key_revocation: 0, - owner_pub_key_digest: ImageDigest::default(), + owner_pub_key_digest: ImageDigest384::default(), lifecycle: Lifecycle::Unprovisioned, } } } impl ImageVerificationEnv for TestEnv { - fn sha384_digest(&mut self, _offset: u32, _len: u32) -> CaliptraResult { + fn sha384_digest(&mut self, _offset: u32, _len: u32) -> CaliptraResult { Ok(self.digest) } fn ecc384_verify( &mut self, - _digest: &ImageDigest, + _digest: &ImageDigest384, _pub_key: &ImageEccPubKey, sig: &ImageEccSignature, ) -> CaliptraResult> { @@ -70,7 +70,7 @@ impl ImageVerificationEnv for TestEnv { fn lms_verify( &mut self, - _digest: &ImageDigest, + _digest: &ImageDigest384, pub_key: &ImageLmsPublicKey, _sig: &ImageLmsSignature, ) -> CaliptraResult> { @@ -81,7 +81,7 @@ impl ImageVerificationEnv for TestEnv { } } - fn vendor_pub_key_digest(&self) -> ImageDigest { + fn vendor_pub_key_digest(&self) -> ImageDigest384 { self.vendor_pub_key_digest } @@ -93,7 +93,7 @@ impl ImageVerificationEnv for TestEnv { self.vendor_lms_pub_key_revocation } - fn owner_pub_key_digest_fuses(&self) -> ImageDigest { + fn owner_pub_key_digest_fuses(&self) -> ImageDigest384 { self.owner_pub_key_digest } @@ -109,15 +109,15 @@ impl ImageVerificationEnv for TestEnv { 0 } - fn vendor_lms_pub_key_idx_dv(&self) -> u32 { + fn vendor_pqc_pub_key_idx_dv(&self) -> u32 { 0 } - fn owner_pub_key_digest_dv(&self) -> ImageDigest { + fn owner_pub_key_digest_dv(&self) -> ImageDigest384 { self.owner_pub_key_digest } - fn get_fmc_digest_dv(&self) -> ImageDigest { + fn get_fmc_digest_dv(&self) -> ImageDigest384 { self.fmc_digest } diff --git a/image/verify/src/lib.rs b/image/verify/src/lib.rs index a013cc9cc1..15d470a568 100644 --- a/image/verify/src/lib.rs +++ b/image/verify/src/lib.rs @@ -44,7 +44,7 @@ pub struct ImageVerificationExeInfo { pub entry_point: u32, /// Digest of the image - pub digest: ImageDigest, + pub digest: ImageDigest384, } /// Information To Be Logged For The Verified Image @@ -56,11 +56,11 @@ pub struct ImageVerificationLogInfo { /// Vendor ECC Public Key Revocation Fuse pub fuse_vendor_ecc_pub_key_revocation: VendorPubKeyRevocation, - // LMS Vendor Public Key Index - pub vendor_lms_pub_key_idx: u32, + // PQC (LMS or MLDSA) Vendor Public Key Index + pub vendor_pqc_pub_key_idx: u32, - /// Vendor LMS Public Key Revocation Fuse - pub fuse_vendor_lms_pub_key_revocation: u32, + /// Vendor PQC (LMS or MLDSA) Public Key Revocation Fuse + pub fuse_vendor_pqc_pub_key_revocation: u32, /// Firmware's SVN logging information pub fw_log_info: FirmwareSvnLogInfo, @@ -72,14 +72,14 @@ pub struct ImageVerificationInfo { /// Vendor ECC public key index pub vendor_ecc_pub_key_idx: u32, - /// Vendor LMS public key index - pub vendor_lms_pub_key_idx: u32, + /// Vendor PQC (LMS or MLDSA) public key index + pub vendor_pqc_pub_key_idx: u32, /// PQC Verification Configuration pub pqc_verify_config: RomPqcVerifyConfig, /// Digest of owner public keys that verified the image - pub owner_pub_keys_digest: ImageDigest, + pub owner_pub_keys_digest: ImageDigest384, /// Whether `owner_pub_keys_digest` was in fuses pub owner_pub_keys_digest_in_fuses: bool, @@ -103,12 +103,15 @@ pub struct ImageVerificationInfo { /// Image Verification Environment pub trait ImageVerificationEnv { /// Calculate SHA-384 Digest - fn sha384_digest(&mut self, offset: u32, len: u32) -> CaliptraResult; + fn sha384_digest(&mut self, offset: u32, len: u32) -> CaliptraResult; + + /// Calculate SHA-512 Digest + fn sha512_digest(&mut self, offset: u32, len: u32) -> CaliptraResult; /// Perform ECC-384 Verification fn ecc384_verify( &mut self, - digest: &ImageDigest, + digest: &ImageDigest384, pub_key: &ImageEccPubKey, sig: &ImageEccSignature, ) -> CaliptraResult>; @@ -116,13 +119,20 @@ pub trait ImageVerificationEnv { /// Perform LMS Verification fn lms_verify( &mut self, - digest: &ImageDigest, + digest: &ImageDigest384, pub_key: &ImageLmsPublicKey, sig: &ImageLmsSignature, ) -> CaliptraResult>; + fn mldsa87_verify( + &mut self, + digest: &ImageDigest512, + pub_key: &ImageMldsaPubKey, + sig: &ImageMldsaSignature, + ) -> CaliptraResult; + /// Get Vendor Public Key Digest from fuses - fn vendor_pub_key_info_digest_fuses(&self) -> ImageDigest; + fn vendor_pub_key_info_digest_fuses(&self) -> ImageDigest384; /// Get Vendor ECC Public Key Revocation list fn vendor_ecc_pub_key_revocation(&self) -> VendorPubKeyRevocation; @@ -131,7 +141,7 @@ pub trait ImageVerificationEnv { fn vendor_lms_pub_key_revocation(&self) -> u32; /// Get Owner Public Key Digest from fuses - fn owner_pub_key_digest_fuses(&self) -> ImageDigest; + fn owner_pub_key_digest_fuses(&self) -> ImageDigest384; /// Get Anti-Rollback disable setting fn anti_rollback_disable(&self) -> bool; @@ -142,14 +152,14 @@ pub trait ImageVerificationEnv { // Get the vendor ECC key index saved on cold boot in data vault fn vendor_ecc_pub_key_idx_dv(&self) -> u32; - // Get the vendor LMS key index saved on cold boot in data vault - fn vendor_lms_pub_key_idx_dv(&self) -> u32; + // Get the vendor PQC (LMS or MLDSA) key index saved on cold boot in data vault + fn vendor_pqc_pub_key_idx_dv(&self) -> u32; // Get the owner key digest saved on cold boot in data vault - fn owner_pub_key_digest_dv(&self) -> ImageDigest; + fn owner_pub_key_digest_dv(&self) -> ImageDigest384; // Save the fmc digest in the data vault on cold boot - fn get_fmc_digest_dv(&self) -> ImageDigest; + fn get_fmc_digest_dv(&self) -> ImageDigest384; // Get Runtime fuse SVN fn runtime_fuse_svn(&self) -> u32; diff --git a/image/verify/src/verifier.rs b/image/verify/src/verifier.rs index e0228a326a..a992ef0482 100644 --- a/image/verify/src/verifier.rs +++ b/image/verify/src/verifier.rs @@ -23,27 +23,34 @@ use caliptra_cfi_lib::{ use caliptra_drivers::*; use caliptra_image_types::*; use memoffset::offset_of; +use zerocopy::AsBytes; -const ZERO_DIGEST: &ImageDigest = &[0u32; SHA384_DIGEST_WORD_SIZE]; +const ZERO_DIGEST: &ImageDigest384 = &[0u32; SHA384_DIGEST_WORD_SIZE]; + +/// PQC public key and signature +enum PqcKeyInfo<'a> { + Lms(&'a ImageLmsPublicKey, &'a ImageLmsSignature), + Mldsa(&'a ImageMldsaPubKey, &'a ImageMldsaSignature), +} /// Header Info struct HeaderInfo<'a> { vendor_ecc_pub_key_idx: u32, - vendor_lms_pub_key_idx: u32, + vendor_pqc_pub_key_idx: u32, vendor_ecc_pub_key_revocation: VendorPubKeyRevocation, vendor_ecc_info: (&'a ImageEccPubKey, &'a ImageEccSignature), - vendor_lms_info: (&'a ImageLmsPublicKey, &'a ImageLmsSignature), - vendor_lms_pub_key_revocation: u32, + vendor_pqc_info: PqcKeyInfo<'a>, + vendor_pqc_pub_key_revocation: u32, owner_ecc_info: (&'a ImageEccPubKey, &'a ImageEccSignature), - owner_lms_info: (&'a ImageLmsPublicKey, &'a ImageLmsSignature), - owner_pub_keys_digest: ImageDigest, + owner_pqc_info: PqcKeyInfo<'a>, + owner_pub_keys_digest: ImageDigest384, owner_pub_keys_digest_in_fuses: bool, } /// TOC Info struct TocInfo<'a> { len: u32, - digest: &'a ImageDigest, + digest: &'a ImageDigest384, } /// Image Info @@ -97,9 +104,13 @@ impl ImageVerifier { Err(CaliptraError::IMAGE_VERIFIER_ERR_MANIFEST_SIZE_MISMATCH)?; } + // Check the verification pqc key type. + let pqc_key_type = FwVerificationPqcKeyType::from_u8(manifest.pqc_key_type) + .ok_or(CaliptraError::IMAGE_VERIFIER_ERR_FW_IMAGE_VERIFICATION_KEY_TYPE_INVALID)?; + // Verify the preamble let preamble = &manifest.preamble; - let header_info = self.verify_preamble(preamble, reason); + let header_info = self.verify_preamble(preamble, reason, pqc_key_type); let header_info = okref(&header_info)?; // Verify Header @@ -127,7 +138,7 @@ impl ImageVerifier { let info = ImageVerificationInfo { vendor_ecc_pub_key_idx: header_info.vendor_ecc_pub_key_idx, - vendor_lms_pub_key_idx: header_info.vendor_lms_pub_key_idx, + vendor_pqc_pub_key_idx: header_info.vendor_pqc_pub_key_idx, owner_pub_keys_digest: header_info.owner_pub_keys_digest, owner_pub_keys_digest_in_fuses: header_info.owner_pub_keys_digest_in_fuses, fmc: fmc_info, @@ -137,15 +148,15 @@ impl ImageVerifier { log_info: ImageVerificationLogInfo { vendor_ecc_pub_key_idx: header_info.vendor_ecc_pub_key_idx, fuse_vendor_ecc_pub_key_revocation: header_info.vendor_ecc_pub_key_revocation, - fuse_vendor_lms_pub_key_revocation: header_info.vendor_lms_pub_key_revocation, - vendor_lms_pub_key_idx: header_info.vendor_lms_pub_key_idx, + fuse_vendor_pqc_pub_key_revocation: header_info.vendor_pqc_pub_key_revocation, + vendor_pqc_pub_key_idx: header_info.vendor_pqc_pub_key_idx, fw_log_info: FirmwareSvnLogInfo { manifest_svn: fw_svn, reserved: 0, fuse_svn: self.env.runtime_fuse_svn(), }, }, - pqc_verify_config: manifest.fw_image_type.into(), + pqc_verify_config: manifest.pqc_key_type.into(), }; Ok(info) @@ -188,13 +199,14 @@ impl ImageVerifier { &mut self, preamble: &'a ImagePreamble, reason: ResetReason, + pqc_key_type: FwVerificationPqcKeyType, ) -> CaliptraResult> { // Verify Vendor Public Key Info Digest - self.verify_vendor_pub_key_info_digest(&preamble.vendor_pub_key_info)?; + self.verify_vendor_pub_key_info_digest(&preamble.vendor_pub_key_info, pqc_key_type)?; // Verify Owner Public Key Info Digest let (owner_pub_keys_digest, owner_pub_keys_digest_in_fuses) = - self.verify_owner_pub_key_info_digest(reason)?; + self.verify_owner_pk_digest(reason)?; // Verify ECC Vendor Key Index let (vendor_ecc_pub_key_idx, vendor_ecc_pub_key_revocation) = @@ -206,15 +218,58 @@ impl ImageVerifier { &preamble.vendor_sigs.ecc_sig, ); - // Verify LMS Vendor Key Index - let (vendor_lms_pub_key_idx, vendor_lms_pub_key_revocation) = - self.verify_vendor_lms_pk_idx(preamble, reason)?; + struct PubKeyIndexInfo { + key_idx: u32, + key_revocation: u32, + } - // LMS Vendor Information - let vendor_lms_info = ( - &preamble.vendor_lms_active_pub_key, - &preamble.vendor_sigs.lms_sig, - ); + // Verify PQC Vendor Key Index + let vendor_pqc_info: PqcKeyInfo<'a>; + let vendor_pqc_pub_key_idx_info = match pqc_key_type { + FwVerificationPqcKeyType::LMS => { + // Read the LMS public key and signature from the preamble + let lms_pub_key = ImageLmsPublicKey::ref_from_prefix( + preamble.vendor_pqc_active_pub_key.0.as_bytes(), + ) + .ok_or(CaliptraError::IMAGE_VERIFIER_ERR_LMS_VENDOR_PUB_KEY_INVALID)?; + + let lms_sig = + ImageLmsSignature::ref_from_prefix(preamble.vendor_sigs.pqc_sig.0.as_bytes()) + .ok_or(CaliptraError::IMAGE_VERIFIER_ERR_LMS_VENDOR_SIG_INVALID)?; + + vendor_pqc_info = PqcKeyInfo::Lms(lms_pub_key, lms_sig); + + // Verify the vendor LMS public key index and revocation status + let (vendor_pqc_pub_key_idx, vendor_lms_pub_key_revocation) = + self.verify_vendor_lms_pk_idx(preamble, reason)?; + + // Return the public key index information + PubKeyIndexInfo { + key_idx: vendor_pqc_pub_key_idx, + key_revocation: vendor_lms_pub_key_revocation, + } + } + FwVerificationPqcKeyType::MLDSA => { + let mldsa_pub_key = ImageMldsaPubKey::ref_from_prefix( + preamble.vendor_pqc_active_pub_key.0.as_bytes(), + ) + .ok_or(CaliptraError::IMAGE_VERIFIER_ERR_MLDSA_VENDOR_PUB_KEY_READ_FAILED)?; + + let mldsa_sig = + ImageMldsaSignature::ref_from_prefix(preamble.vendor_sigs.pqc_sig.0.as_bytes()) + .ok_or(CaliptraError::IMAGE_VERIFIER_ERR_MLDSA_VENDOR_SIG_READ_FAILED)?; + + vendor_pqc_info = PqcKeyInfo::Mldsa(mldsa_pub_key, mldsa_sig); + + // [TODO][CAP2] Verify the vendor MLDSA public key index and revocation status + + // Return the public key index information + PubKeyIndexInfo { + key_idx: 0, + key_revocation: 0, + } + } + }; // Owner Information let owner_ecc_info = ( @@ -222,22 +277,44 @@ impl ImageVerifier { &preamble.owner_sigs.ecc_sig, ); - let owner_lms_info = ( - &preamble.owner_pub_keys.lms_pub_key, - &preamble.owner_sigs.lms_sig, - ); + let owner_pqc_info: PqcKeyInfo<'a> = match pqc_key_type { + FwVerificationPqcKeyType::LMS => { + let lms_pub_key = ImageLmsPublicKey::ref_from_prefix( + preamble.owner_pub_keys.pqc_pub_key.0.as_bytes(), + ) + .ok_or(CaliptraError::IMAGE_VERIFIER_ERR_LMS_OWNER_PUB_KEY_INVALID)?; + + let lms_sig = + ImageLmsSignature::ref_from_prefix(preamble.owner_sigs.pqc_sig.0.as_bytes()) + .ok_or(CaliptraError::IMAGE_VERIFIER_ERR_LMS_OWNER_SIG_INVALID)?; + + PqcKeyInfo::Lms(lms_pub_key, lms_sig) + } + FwVerificationPqcKeyType::MLDSA => { + let mldsa_pub_key = ImageMldsaPubKey::ref_from_prefix( + preamble.owner_pub_keys.pqc_pub_key.0.as_bytes(), + ) + .ok_or(CaliptraError::IMAGE_VERIFIER_ERR_MLDSA_OWNER_PUB_KEY_READ_FAILED)?; + + let mldsa_sig = + ImageMldsaSignature::ref_from_prefix(preamble.owner_sigs.pqc_sig.0.as_bytes()) + .ok_or(CaliptraError::IMAGE_VERIFIER_ERR_MLDSA_OWNER_SIG_READ_FAILED)?; + + PqcKeyInfo::Mldsa(mldsa_pub_key, mldsa_sig) + } + }; let info = HeaderInfo { vendor_ecc_pub_key_idx, - vendor_lms_pub_key_idx, + vendor_pqc_pub_key_idx: vendor_pqc_pub_key_idx_info.key_idx, vendor_ecc_info, - vendor_lms_info, - owner_lms_info, + vendor_pqc_info, + owner_pqc_info, owner_pub_keys_digest, owner_pub_keys_digest_in_fuses, owner_ecc_info, vendor_ecc_pub_key_revocation, - vendor_lms_pub_key_revocation, + vendor_pqc_pub_key_revocation: vendor_pqc_pub_key_idx_info.key_revocation, }; Ok(info) @@ -296,7 +373,7 @@ impl ImageVerifier { preamble: &ImagePreamble, reason: ResetReason, ) -> CaliptraResult<(u32, u32)> { - let key_idx = preamble.vendor_lms_pub_key_idx; + let key_idx = preamble.vendor_pqc_pub_key_idx; let revocation = self.env.vendor_lms_pub_key_revocation(); let key_hash_count = preamble .vendor_pub_key_info @@ -319,13 +396,13 @@ impl ImageVerifier { } if cfi_launder(reason) == ResetReason::UpdateReset { - let expected = self.env.vendor_lms_pub_key_idx_dv(); + let expected = self.env.vendor_pqc_pub_key_idx_dv(); if cfi_launder(expected) != key_idx { Err( - CaliptraError::IMAGE_VERIFIER_ERR_UPDATE_RESET_VENDOR_LMS_PUB_KEY_IDX_MISMATCH, + CaliptraError::IMAGE_VERIFIER_ERR_UPDATE_RESET_VENDOR_PQC_PUB_KEY_IDX_MISMATCH, )?; } else { - cfi_assert_eq(self.env.vendor_lms_pub_key_idx_dv(), key_idx); + cfi_assert_eq(self.env.vendor_pqc_pub_key_idx_dv(), key_idx); } } else { cfi_assert_ne(reason, ResetReason::UpdateReset); @@ -338,6 +415,7 @@ impl ImageVerifier { fn verify_vendor_pub_key_info_digest( &mut self, pub_key_info: &ImageVendorPubKeyInfo, + pqc_key_type: FwVerificationPqcKeyType, ) -> Result<(), NonZeroU32> { // We skip vendor public key check in unprovisioned state if cfi_launder(self.env.dev_lifecycle() as u32) == Lifecycle::Unprovisioned as u32 { @@ -367,9 +445,6 @@ impl ImageVerifier { if pub_key_info.ecc_key_descriptor.version != KEY_DESCRIPTOR_VERSION { Err(CaliptraError::IMAGE_VERIFIER_ERR_ECC_KEY_DESCRIPTOR_VERSION_MISMATCH)?; } - if pub_key_info.ecc_key_descriptor.intent != Intent::Vendor as u8 { - Err(CaliptraError::IMAGE_VERIFIER_ERR_ECC_KEY_DESCRIPTOR_INTENT_MISMATCH)?; - } if pub_key_info.ecc_key_descriptor.key_hash_count == 0 { Err(CaliptraError::IMAGE_VERIFIER_ERR_ECC_KEY_DESCRIPTOR_INVALID_HASH_COUNT)?; } @@ -377,21 +452,23 @@ impl ImageVerifier { Err(CaliptraError::IMAGE_VERIFIER_ERR_ECC_KEY_DESCRIPTOR_HASH_COUNT_GT_MAX)?; } - // Validate the LMS key descriptor. + // Validate the PQC key descriptor. if pub_key_info.pqc_key_descriptor.version != KEY_DESCRIPTOR_VERSION { - Err(CaliptraError::IMAGE_VERIFIER_ERR_LMS_KEY_DESCRIPTOR_VERSION_MISMATCH)?; - } - if pub_key_info.pqc_key_descriptor.intent != Intent::Vendor as u8 { - Err(CaliptraError::IMAGE_VERIFIER_ERR_LMS_KEY_DESCRIPTOR_INTENT_MISMATCH)?; + Err(CaliptraError::IMAGE_VERIFIER_ERR_PQC_KEY_DESCRIPTOR_VERSION_MISMATCH)?; } - if pub_key_info.pqc_key_descriptor.key_type != KeyType::LMS as u8 { - Err(CaliptraError::IMAGE_VERIFIER_ERR_LMS_KEY_DESCRIPTOR_TYPE_MISMATCH)?; + if pub_key_info.pqc_key_descriptor.key_type != pqc_key_type as u8 { + Err(CaliptraError::IMAGE_VERIFIER_ERR_PQC_KEY_DESCRIPTOR_TYPE_MISMATCH)?; } if pub_key_info.pqc_key_descriptor.key_hash_count == 0 { - Err(CaliptraError::IMAGE_VERIFIER_ERR_LMS_KEY_DESCRIPTOR_INVALID_HASH_COUNT)?; + Err(CaliptraError::IMAGE_VERIFIER_ERR_PQC_KEY_DESCRIPTOR_INVALID_HASH_COUNT)?; } - if pub_key_info.pqc_key_descriptor.key_hash_count > VENDOR_LMS_MAX_KEY_COUNT as u8 { - Err(CaliptraError::IMAGE_VERIFIER_ERR_LMS_KEY_DESCRIPTOR_HASH_COUNT_GT_MAX)?; + if (pqc_key_type == FwVerificationPqcKeyType::LMS + && pub_key_info.pqc_key_descriptor.key_hash_count > VENDOR_LMS_MAX_KEY_COUNT as u8) + || (pqc_key_type == FwVerificationPqcKeyType::MLDSA + && pub_key_info.pqc_key_descriptor.key_hash_count + > VENDOR_MLDSA_MAX_KEY_COUNT as u8) + { + Err(CaliptraError::IMAGE_VERIFIER_ERR_PQC_KEY_DESCRIPTOR_HASH_COUNT_GT_MAX)?; } let range = ImageManifest::vendor_pub_key_descriptors_range(); @@ -425,11 +502,11 @@ impl ImageVerifier { /// Verify owner public key digest. /// Returns a bool indicating whether the digest was in fuses. - fn verify_owner_pub_key_info_digest( + fn verify_owner_pk_digest( &mut self, reason: ResetReason, - ) -> CaliptraResult<(ImageDigest, bool)> { - let range = ImageManifest::owner_pub_key_descriptors_range(); + ) -> CaliptraResult<(ImageDigest384, bool)> { + let range = ImageManifest::owner_pub_key_range(); #[cfg(feature = "fips-test-hooks")] unsafe { @@ -491,7 +568,7 @@ impl ImageVerifier { }; // Vendor header digest is calculated up to the owner_data field. - let digest_vendor = self + let vendor_digest_384 = self .env .sha384_digest(range.start, vendor_header_len as u32) .map_err(|err| { @@ -499,7 +576,12 @@ impl ImageVerifier { CaliptraError::IMAGE_VERIFIER_ERR_HEADER_DIGEST_FAILURE })?; - let digest_owner = self + let mut vendor_digest_holder = ImageDigestHolder { + digest_384: &vendor_digest_384, + digest_512: None, + }; + + let owner_digest_384 = self .env .sha384_digest(range.start, range.len() as u32) .map_err(|err| { @@ -507,8 +589,41 @@ impl ImageVerifier { CaliptraError::IMAGE_VERIFIER_ERR_HEADER_DIGEST_FAILURE })?; - // Verify vendor signature - self.verify_vendor_sig(&digest_vendor, info.vendor_ecc_info, info.vendor_lms_info)?; + let mut owner_digest_holder = ImageDigestHolder { + digest_384: &owner_digest_384, + digest_512: None, + }; + + let vendor_digest_512: [u32; 16]; + let owner_digest_512: [u32; 16]; + + // Update vendor_digest_holder and owner_digest_holder with SHA512 digests if MLDSA validation i required. + if let PqcKeyInfo::Mldsa(_, _) = info.vendor_pqc_info { + vendor_digest_512 = self + .env + .sha512_digest(range.start, vendor_header_len as u32) + .map_err(|err| { + self.env.set_fw_extended_error(err.into()); + CaliptraError::IMAGE_VERIFIER_ERR_HEADER_DIGEST_FAILURE + })?; + vendor_digest_holder.digest_512 = Some(&vendor_digest_512); + + owner_digest_512 = self + .env + .sha512_digest(range.start, range.len() as u32) + .map_err(|err| { + self.env.set_fw_extended_error(err.into()); + CaliptraError::IMAGE_VERIFIER_ERR_HEADER_DIGEST_FAILURE + })?; + owner_digest_holder.digest_512 = Some(&owner_digest_512); + } + + // Verify vendor signatures. + self.verify_vendor_sig( + &vendor_digest_holder, + info.vendor_ecc_info, + &info.vendor_pqc_info, + )?; // Verify the ECC public key index used to verify header signature is encoded // in the header @@ -518,24 +633,19 @@ impl ImageVerifier { cfi_assert_eq(header.vendor_ecc_pub_key_idx, info.vendor_ecc_pub_key_idx); } - // Verify the LMS public key index used to verify header signature is encoded + // Verify the PQC (LMS or MLDSA) public key index used to verify header signature is encoded // in the header - if cfi_launder(header.vendor_lms_pub_key_idx) != info.vendor_lms_pub_key_idx { - return Err(CaliptraError::IMAGE_VERIFIER_ERR_VENDOR_LMS_PUB_KEY_INDEX_MISMATCH); + if cfi_launder(header.vendor_pqc_pub_key_idx) != info.vendor_pqc_pub_key_idx { + return Err(CaliptraError::IMAGE_VERIFIER_ERR_VENDOR_PQC_PUB_KEY_INDEX_MISMATCH); } else { - cfi_assert_eq(header.vendor_lms_pub_key_idx, info.vendor_lms_pub_key_idx); + cfi_assert_eq(header.vendor_pqc_pub_key_idx, info.vendor_pqc_pub_key_idx); } - // Verify owner ECC signature - let (owner_ecc_pub_key, owner_ecc_sig) = info.owner_ecc_info; - self.verify_owner_ecc_sig(&digest_owner, owner_ecc_pub_key, owner_ecc_sig)?; - - // Verify owner LMS signature - let (owner_lms_pub_key, owner_lms_sig) = info.owner_lms_info; - self.verify_owner_lms_sig( - &digest_owner, - cfi_launder(owner_lms_pub_key), - cfi_launder(owner_lms_sig), + // Verify owner signatures. + self.verify_owner_sig( + &owner_digest_holder, + info.owner_ecc_info, + &info.owner_pqc_info, )?; let verif_info = TocInfo { @@ -549,23 +659,43 @@ impl ImageVerifier { /// Verify Owner Signature // Inlined to reduce ROM size #[inline(always)] - fn verify_owner_ecc_sig( + fn verify_ecc_sig( &mut self, - digest: &ImageDigest, + digest: &ImageDigest384, pub_key: &ImageEccPubKey, sig: &ImageEccSignature, + is_owner: bool, ) -> CaliptraResult<()> { + let (signature_invalid, pub_key_invalid_arg, sig_invalid_arg) = if is_owner { + ( + CaliptraError::IMAGE_VERIFIER_ERR_OWNER_ECC_SIGNATURE_INVALID, + CaliptraError::IMAGE_VERIFIER_ERR_OWNER_ECC_PUB_KEY_INVALID_ARG, + CaliptraError::IMAGE_VERIFIER_ERR_OWNER_ECC_SIGNATURE_INVALID_ARG, + ) + } else { + ( + CaliptraError::IMAGE_VERIFIER_ERR_VENDOR_ECC_SIGNATURE_INVALID, + CaliptraError::IMAGE_VERIFIER_ERR_VENDOR_ECC_PUB_KEY_INVALID_ARG, + CaliptraError::IMAGE_VERIFIER_ERR_VENDOR_ECC_SIGNATURE_INVALID_ARG, + ) + }; + if &pub_key.x == ZERO_DIGEST || &pub_key.y == ZERO_DIGEST { - Err(CaliptraError::IMAGE_VERIFIER_ERR_OWNER_ECC_PUB_KEY_INVALID_ARG)?; + return Err(pub_key_invalid_arg); } if &sig.r == ZERO_DIGEST || &sig.s == ZERO_DIGEST { - Err(CaliptraError::IMAGE_VERIFIER_ERR_OWNER_ECC_SIGNATURE_INVALID_ARG)?; + return Err(sig_invalid_arg); } #[cfg(feature = "fips-test-hooks")] unsafe { + let fips_verify_failure = if is_owner { + caliptra_drivers::FipsTestHook::FW_LOAD_OWNER_ECC_VERIFY_FAILURE + } else { + caliptra_drivers::FipsTestHook::FW_LOAD_VENDOR_ECC_VERIFY_FAILURE + }; caliptra_drivers::FipsTestHook::update_hook_cmd_if_hook_set( - caliptra_drivers::FipsTestHook::FW_LOAD_OWNER_ECC_VERIFY_FAILURE, + fips_verify_failure, caliptra_drivers::FipsTestHook::ECC384_VERIFY_FAILURE, ) }; @@ -575,11 +705,15 @@ impl ImageVerifier { .ecc384_verify(digest, pub_key, sig) .map_err(|err| { self.env.set_fw_extended_error(err.into()); - CaliptraError::IMAGE_VERIFIER_ERR_OWNER_ECC_VERIFY_FAILURE + if is_owner { + CaliptraError::IMAGE_VERIFIER_ERR_OWNER_ECC_VERIFY_FAILURE + } else { + CaliptraError::IMAGE_VERIFIER_ERR_VENDOR_ECC_VERIFY_FAILURE + } })?; if cfi_launder(verify_r) != caliptra_drivers::Array4xN(sig.r) { - Err(CaliptraError::IMAGE_VERIFIER_ERR_OWNER_ECC_SIGNATURE_INVALID)?; + return Err(signature_invalid); } else { caliptra_cfi_lib::cfi_assert_eq_12_words(&verify_r.0, &sig.r); } @@ -590,13 +724,13 @@ impl ImageVerifier { /// Verify Vendor Signature fn verify_vendor_sig( &mut self, - digest: &ImageDigest, + digest_holder: &ImageDigestHolder, ecc_info: (&ImageEccPubKey, &ImageEccSignature), - lms_info: (&ImageLmsPublicKey, &ImageLmsSignature), + pqc_info: &PqcKeyInfo, ) -> CaliptraResult<()> { let (ecc_pub_key, ecc_sig) = ecc_info; if &ecc_pub_key.x == ZERO_DIGEST || &ecc_pub_key.y == ZERO_DIGEST { - Err(CaliptraError::IMAGE_VERIFIER_ERR_VENDOR_PUB_KEY_DIGEST_INVALID_ARG)?; + Err(CaliptraError::IMAGE_VERIFIER_ERR_VENDOR_ECC_PUB_KEY_INVALID_ARG)?; } if &ecc_sig.r == ZERO_DIGEST || &ecc_sig.s == ZERO_DIGEST { Err(CaliptraError::IMAGE_VERIFIER_ERR_VENDOR_ECC_SIGNATURE_INVALID_ARG)?; @@ -612,7 +746,7 @@ impl ImageVerifier { let verify_r = self .env - .ecc384_verify(digest, ecc_pub_key, ecc_sig) + .ecc384_verify(digest_holder.digest_384, ecc_pub_key, ecc_sig) .map_err(|err| { self.env.set_fw_extended_error(err.into()); CaliptraError::IMAGE_VERIFIER_ERR_VENDOR_ECC_VERIFY_FAILURE @@ -624,43 +758,99 @@ impl ImageVerifier { caliptra_cfi_lib::cfi_assert_eq_12_words(&verify_r.0, &ecc_sig.r); } - #[cfg(feature = "fips-test-hooks")] - unsafe { - caliptra_drivers::FipsTestHook::update_hook_cmd_if_hook_set( - caliptra_drivers::FipsTestHook::FW_LOAD_VENDOR_LMS_VERIFY_FAILURE, - caliptra_drivers::FipsTestHook::LMS_VERIFY_FAILURE, - ) - }; + // Verify PQC signature. + match pqc_info { + PqcKeyInfo::Lms(lms_pub_key, lms_sig) => { + self.verify_lms_sig(digest_holder.digest_384, lms_pub_key, lms_sig, false)?; + } + PqcKeyInfo::Mldsa(mldsa_pub_key, mldsa_sig) => { + if let Some(digest_512) = digest_holder.digest_512 { + let result = self + .env + .mldsa87_verify(digest_512, mldsa_pub_key, mldsa_sig) + .map_err(|err| { + self.env.set_fw_extended_error(err.into()); + CaliptraError::IMAGE_VERIFIER_ERR_VENDOR_MLDSA_VERIFY_FAILURE + })?; + + if cfi_launder(result) != Mldsa87Result::Success { + Err(CaliptraError::IMAGE_VERIFIER_ERR_VENDOR_MLDSA_SIGNATURE_INVALID)?; + } + } else { + Err(CaliptraError::IMAGE_VERIFIER_ERR_VENDOR_MLDSA_DIGEST_MISSING)?; + } + } + } - let (lms_pub_key, lms_sig) = lms_info; - let candidate_key = self - .env - .lms_verify(digest, lms_pub_key, lms_sig) - .map_err(|err| { - self.env.set_fw_extended_error(err.into()); - CaliptraError::IMAGE_VERIFIER_ERR_VENDOR_LMS_VERIFY_FAILURE - })?; - let pub_key_digest = HashValue::from(lms_pub_key.digest); - if candidate_key != pub_key_digest { - return Err(CaliptraError::IMAGE_VERIFIER_ERR_VENDOR_LMS_SIGNATURE_INVALID); - } else { - caliptra_cfi_lib::cfi_assert_eq_6_words(&candidate_key.0, &pub_key_digest.0); + Ok(()) + } + + fn verify_owner_sig( + &mut self, + digest_holder: &ImageDigestHolder, + ecc_info: (&ImageEccPubKey, &ImageEccSignature), + pqc_info: &PqcKeyInfo, + ) -> CaliptraResult<()> { + // Verify owner ECC signature + let (ecc_pub_key, ecc_sig) = ecc_info; + self.verify_ecc_sig(digest_holder.digest_384, ecc_pub_key, ecc_sig, true)?; + + // Verify owner PQC signature + match pqc_info { + PqcKeyInfo::Lms(lms_pub_key, lms_sig) => { + self.verify_lms_sig(digest_holder.digest_384, lms_pub_key, lms_sig, true)?; + } + PqcKeyInfo::Mldsa(mldsa_pub_key, mldsa_sig) => { + if let Some(digest_512) = digest_holder.digest_512 { + let result = self + .env + .mldsa87_verify(digest_512, mldsa_pub_key, mldsa_sig) + .map_err(|err| { + self.env.set_fw_extended_error(err.into()); + CaliptraError::IMAGE_VERIFIER_ERR_OWNER_MLDSA_VERIFY_FAILURE + })?; + + if cfi_launder(result) != Mldsa87Result::Success { + Err(CaliptraError::IMAGE_VERIFIER_ERR_OWNER_MLDSA_SIGNATURE_INVALID)?; + } + } else { + Err(CaliptraError::IMAGE_VERIFIER_ERR_OWNER_MLDSA_DIGEST_MISSING)?; + } + } } Ok(()) } /// Verify owner LMS Signature - fn verify_owner_lms_sig( + fn verify_lms_sig( &mut self, - digest: &ImageDigest, + digest: &ImageDigest384, lms_pub_key: &ImageLmsPublicKey, lms_sig: &ImageLmsSignature, + is_owner: bool, ) -> CaliptraResult<()> { + let (verify_failure, signature_invalid) = if is_owner { + ( + CaliptraError::IMAGE_VERIFIER_ERR_OWNER_LMS_VERIFY_FAILURE, + CaliptraError::IMAGE_VERIFIER_ERR_OWNER_LMS_SIGNATURE_INVALID, + ) + } else { + ( + CaliptraError::IMAGE_VERIFIER_ERR_VENDOR_LMS_VERIFY_FAILURE, + CaliptraError::IMAGE_VERIFIER_ERR_VENDOR_LMS_SIGNATURE_INVALID, + ) + }; + #[cfg(feature = "fips-test-hooks")] unsafe { + let fips_verify_failure = if is_owner { + caliptra_drivers::FipsTestHook::FW_LOAD_OWNER_LMS_VERIFY_FAILURE + } else { + caliptra_drivers::FipsTestHook::FW_LOAD_VENDOR_LMS_VERIFY_FAILURE + }; caliptra_drivers::FipsTestHook::update_hook_cmd_if_hook_set( - caliptra_drivers::FipsTestHook::FW_LOAD_OWNER_LMS_VERIFY_FAILURE, + fips_verify_failure, caliptra_drivers::FipsTestHook::LMS_VERIFY_FAILURE, ) }; @@ -670,12 +860,12 @@ impl ImageVerifier { .lms_verify(digest, lms_pub_key, lms_sig) .map_err(|err| { self.env.set_fw_extended_error(err.into()); - CaliptraError::IMAGE_VERIFIER_ERR_OWNER_LMS_VERIFY_FAILURE + verify_failure })?; let pub_key_digest = HashValue::from(lms_pub_key.digest); if candidate_key != pub_key_digest { - return Err(CaliptraError::IMAGE_VERIFIER_ERR_OWNER_LMS_SIGNATURE_INVALID); + return Err(signature_invalid); } else { caliptra_cfi_lib::cfi_assert_eq_6_words(&candidate_key.0, &pub_key_digest.0); } @@ -973,15 +1163,13 @@ mod tests { vendor_pub_key_info: ImageVendorPubKeyInfo { ecc_key_descriptor: ImageEccKeyDescriptor { version: KEY_DESCRIPTOR_VERSION, - intent: Intent::Vendor as u8, key_hash_count: 1, reserved: 0, key_hash: ImageEccKeyHashes::default(), }, pqc_key_descriptor: ImagePqcKeyDescriptor { version: KEY_DESCRIPTOR_VERSION, - intent: Intent::Vendor as u8, - key_type: KeyType::LMS as u8, + key_type: FwVerificationPqcKeyType::LMS as u8, key_hash_count: 1, key_hash: ImagePqcKeyHashes::default(), }, @@ -1005,15 +1193,13 @@ mod tests { vendor_pub_key_info: ImageVendorPubKeyInfo { ecc_key_descriptor: ImageEccKeyDescriptor { version: KEY_DESCRIPTOR_VERSION, - intent: Intent::Vendor as u8, key_hash_count: 4, reserved: 0, key_hash: ImageEccKeyHashes::default(), }, pqc_key_descriptor: ImagePqcKeyDescriptor { version: KEY_DESCRIPTOR_VERSION, - intent: Intent::Vendor as u8, - key_type: KeyType::LMS as u8, + key_type: FwVerificationPqcKeyType::LMS as u8, key_hash_count: 1, key_hash: ImagePqcKeyHashes::default(), }, @@ -1035,7 +1221,7 @@ mod tests { lifecycle: Lifecycle::Production, vendor_pub_key_digest: DUMMY_DATA, owner_pub_key_digest: DUMMY_DATA, - digest: DUMMY_DATA, + digest_384: DUMMY_DATA, ..Default::default() }; @@ -1045,15 +1231,15 @@ mod tests { vendor_pub_key_info: ImageVendorPubKeyInfo { ecc_key_descriptor: ImageEccKeyDescriptor { version: KEY_DESCRIPTOR_VERSION, - intent: Intent::Vendor as u8, + key_hash_count: 1, reserved: 0, key_hash: ImageEccKeyHashes::default(), }, pqc_key_descriptor: ImagePqcKeyDescriptor { version: KEY_DESCRIPTOR_VERSION, - intent: Intent::Vendor as u8, - key_type: KeyType::LMS as u8, + + key_type: FwVerificationPqcKeyType::LMS as u8, key_hash_count: 1, key_hash: ImagePqcKeyHashes::default(), }, @@ -1061,7 +1247,11 @@ mod tests { ..Default::default() }; - let result = verifier.verify_preamble(&preamble, ResetReason::UpdateReset); + let result = verifier.verify_preamble( + &preamble, + ResetReason::UpdateReset, + FwVerificationPqcKeyType::LMS, + ); assert!(result.is_ok()); } @@ -1071,7 +1261,7 @@ mod tests { lifecycle: Lifecycle::Production, vendor_pub_key_digest: DUMMY_DATA, owner_pub_key_digest: DUMMY_DATA, - digest: DUMMY_DATA, + digest_384: DUMMY_DATA, fmc_digest: DUMMY_DATA, ..Default::default() }; @@ -1096,7 +1286,7 @@ mod tests { lifecycle: Lifecycle::Production, vendor_pub_key_digest: DUMMY_DATA, owner_pub_key_digest: DUMMY_DATA, - digest: DUMMY_DATA, + digest_384: DUMMY_DATA, ..Default::default() }; @@ -1122,7 +1312,7 @@ mod tests { lifecycle: Lifecycle::Production, vendor_pub_key_digest: DUMMY_DATA, owner_pub_key_digest: DUMMY_DATA, - digest: DUMMY_DATA, + digest_384: DUMMY_DATA, fmc_digest: DUMMY_DATA, ..Default::default() }; @@ -1132,15 +1322,15 @@ mod tests { vendor_pub_key_info: ImageVendorPubKeyInfo { ecc_key_descriptor: ImageEccKeyDescriptor { version: KEY_DESCRIPTOR_VERSION, - intent: Intent::Vendor as u8, + key_hash_count: 1, reserved: 0, key_hash: ImageEccKeyHashes::default(), }, pqc_key_descriptor: ImagePqcKeyDescriptor { version: KEY_DESCRIPTOR_VERSION, - intent: Intent::Vendor as u8, - key_type: KeyType::LMS as u8, + + key_type: FwVerificationPqcKeyType::LMS as u8, key_hash_count: 1, key_hash: ImagePqcKeyHashes::default(), }, @@ -1148,7 +1338,11 @@ mod tests { ..Default::default() }; - let result = verifier.verify_preamble(&preamble, ResetReason::UpdateReset); + let result = verifier.verify_preamble( + &preamble, + ResetReason::UpdateReset, + FwVerificationPqcKeyType::LMS, + ); assert!(result.is_ok()); } @@ -1188,7 +1382,11 @@ mod tests { ..Default::default() }; let mut verifier = ImageVerifier::new(test_env); - let result = verifier.verify_preamble(&preamble, ResetReason::ColdReset); + let result = verifier.verify_preamble( + &preamble, + ResetReason::ColdReset, + FwVerificationPqcKeyType::LMS, + ); assert!(result.is_err()); assert_eq!( result.err(), @@ -1202,7 +1400,7 @@ mod tests { lifecycle: Lifecycle::Production, vendor_pub_key_digest: DUMMY_DATA, owner_pub_key_digest: DUMMY_DATA, - digest: DUMMY_DATA, + digest_384: DUMMY_DATA, ..Default::default() }; let mut verifier = ImageVerifier::new(test_env); @@ -1210,15 +1408,15 @@ mod tests { vendor_pub_key_info: ImageVendorPubKeyInfo { ecc_key_descriptor: ImageEccKeyDescriptor { version: KEY_DESCRIPTOR_VERSION, - intent: Intent::Vendor as u8, + key_hash_count: 1, reserved: 0, key_hash: ImageEccKeyHashes::default(), }, pqc_key_descriptor: ImagePqcKeyDescriptor { version: KEY_DESCRIPTOR_VERSION, - intent: Intent::Vendor as u8, - key_type: KeyType::LMS as u8, + + key_type: FwVerificationPqcKeyType::LMS as u8, key_hash_count: 1, key_hash: ImagePqcKeyHashes::default(), }, @@ -1226,7 +1424,11 @@ mod tests { ..Default::default() }; - let result = verifier.verify_preamble(&preamble, ResetReason::ColdReset); + let result = verifier.verify_preamble( + &preamble, + ResetReason::ColdReset, + FwVerificationPqcKeyType::LMS, + ); assert!(result.is_ok()); } @@ -1243,22 +1445,26 @@ mod tests { vendor_pub_key_info: ImageVendorPubKeyInfo { ecc_key_descriptor: ImageEccKeyDescriptor { version: KEY_DESCRIPTOR_VERSION, - intent: Intent::Vendor as u8, + key_hash_count: 1, reserved: 0, key_hash: ImageEccKeyHashes::default(), }, pqc_key_descriptor: ImagePqcKeyDescriptor { version: KEY_DESCRIPTOR_VERSION, - intent: Intent::Vendor as u8, - key_type: KeyType::LMS as u8, + + key_type: FwVerificationPqcKeyType::LMS as u8, key_hash_count: 1, key_hash: ImagePqcKeyHashes::default(), }, }, ..Default::default() }; - let result = verifier.verify_preamble(&preamble, ResetReason::ColdReset); + let result = verifier.verify_preamble( + &preamble, + ResetReason::ColdReset, + FwVerificationPqcKeyType::LMS, + ); assert_eq!( result.err(), Some(CaliptraError::IMAGE_VERIFIER_ERR_VENDOR_PUB_KEY_DIGEST_MISMATCH) @@ -1278,20 +1484,20 @@ mod tests { let binding_vendor_lms_sig = vendor_lms_sig(); let header_info: HeaderInfo = HeaderInfo { vendor_ecc_pub_key_idx: 0, - vendor_lms_pub_key_idx: 0, + vendor_pqc_pub_key_idx: 0, vendor_ecc_info: (&ImageEccPubKey::default(), &ImageEccSignature::default()), - vendor_lms_info: (&binding_vendor_lms_pubkey, &binding_vendor_lms_sig), + vendor_pqc_info: PqcKeyInfo::Lms(&binding_vendor_lms_pubkey, &binding_vendor_lms_sig), owner_ecc_info: (&ecc_pubkey, &ecc_sig), - owner_lms_info: (&owner_lms_pubkey, &owner_lms_sig), - owner_pub_keys_digest: ImageDigest::default(), + owner_pqc_info: PqcKeyInfo::Lms(&owner_lms_pubkey, &owner_lms_sig), + owner_pub_keys_digest: ImageDigest384::default(), owner_pub_keys_digest_in_fuses: false, vendor_ecc_pub_key_revocation: Default::default(), - vendor_lms_pub_key_revocation: Default::default(), + vendor_pqc_pub_key_revocation: Default::default(), }; let result = verifier.verify_header(&header, &header_info); assert_eq!( result.err(), - Some(CaliptraError::IMAGE_VERIFIER_ERR_VENDOR_PUB_KEY_DIGEST_INVALID_ARG) + Some(CaliptraError::IMAGE_VERIFIER_ERR_VENDOR_ECC_PUB_KEY_INVALID_ARG) ); } @@ -1308,15 +1514,15 @@ mod tests { let binding_vendor_lms_sig = vendor_lms_sig(); let header_info: HeaderInfo = HeaderInfo { vendor_ecc_pub_key_idx: 0, - vendor_lms_pub_key_idx: 0, + vendor_pqc_pub_key_idx: 0, vendor_ecc_info: (&VENDOR_ECC_PUBKEY, &ImageEccSignature::default()), - vendor_lms_info: (&binding_vendor_lms_pubkey, &binding_vendor_lms_sig), + vendor_pqc_info: PqcKeyInfo::Lms(&binding_vendor_lms_pubkey, &binding_vendor_lms_sig), owner_ecc_info: (&owner_ecc_pubkey, &owner_ecc_sig), - owner_lms_info: (&owner_lms_pubkey, &owner_lms_sig), - owner_pub_keys_digest: ImageDigest::default(), + owner_pqc_info: PqcKeyInfo::Lms(&owner_lms_pubkey, &owner_lms_sig), + owner_pub_keys_digest: ImageDigest384::default(), owner_pub_keys_digest_in_fuses: false, vendor_ecc_pub_key_revocation: Default::default(), - vendor_lms_pub_key_revocation: Default::default(), + vendor_pqc_pub_key_revocation: Default::default(), }; let result = verifier.verify_header(&header, &header_info); assert_eq!( @@ -1344,15 +1550,15 @@ mod tests { let binding_vendor_lms_sig = vendor_lms_sig(); let header_info: HeaderInfo = HeaderInfo { vendor_ecc_pub_key_idx: 0, - vendor_lms_pub_key_idx: 0, + vendor_pqc_pub_key_idx: 0, vendor_ecc_info: (&VENDOR_ECC_PUBKEY, &VENDOR_ECC_SIG), - vendor_lms_info: (&binding_vendor_lms_pubkey, &binding_vendor_lms_sig), + vendor_pqc_info: PqcKeyInfo::Lms(&binding_vendor_lms_pubkey, &binding_vendor_lms_sig), owner_ecc_info: (&owner_ecc_pubkey, &owner_ecc_sig), - owner_lms_info: (&owner_lms_pubkey, &owner_lms_sig), - owner_pub_keys_digest: ImageDigest::default(), + owner_pqc_info: PqcKeyInfo::Lms(&owner_lms_pubkey, &owner_lms_sig), + owner_pub_keys_digest: ImageDigest384::default(), owner_pub_keys_digest_in_fuses: false, vendor_ecc_pub_key_revocation: Default::default(), - vendor_lms_pub_key_revocation: Default::default(), + vendor_pqc_pub_key_revocation: Default::default(), }; let result = verifier.verify_header(&header, &header_info); assert_eq!( @@ -1380,15 +1586,15 @@ mod tests { let binding_vendor_lms_sig = vendor_lms_sig(); let header_info: HeaderInfo = HeaderInfo { vendor_ecc_pub_key_idx: 0, - vendor_lms_pub_key_idx: 0, + vendor_pqc_pub_key_idx: 0, vendor_ecc_pub_key_revocation: Default::default(), vendor_ecc_info: (&VENDOR_ECC_PUBKEY, &VENDOR_ECC_SIG), - vendor_lms_info: (&binding_vendor_lms_pubkey, &binding_vendor_lms_sig), + vendor_pqc_info: PqcKeyInfo::Lms(&binding_vendor_lms_pubkey, &binding_vendor_lms_sig), owner_ecc_info: (&owner_ecc_pubkey, &owner_ecc_sig), - owner_lms_info: (&owner_lms_pubkey, &owner_lms_sig), - owner_pub_keys_digest: ImageDigest::default(), + owner_pqc_info: PqcKeyInfo::Lms(&owner_lms_pubkey, &owner_lms_sig), + owner_pub_keys_digest: ImageDigest384::default(), owner_pub_keys_digest_in_fuses: false, - vendor_lms_pub_key_revocation: Default::default(), + vendor_pqc_pub_key_revocation: Default::default(), }; let result = verifier.verify_header(&header, &header_info); assert_eq!( @@ -1401,7 +1607,7 @@ mod tests { fn test_header_incorrect_pubkey_index() { let test_env = TestEnv { verify_result: true, - verify_lms_result: true, + verify_pqc_result: true, ..Default::default() }; let mut verifier = ImageVerifier::new(test_env); @@ -1414,15 +1620,15 @@ mod tests { let binding_vendor_lms_sig = vendor_lms_sig(); let header_info: HeaderInfo = HeaderInfo { vendor_ecc_pub_key_idx: 1, - vendor_lms_pub_key_idx: 0, + vendor_pqc_pub_key_idx: 0, vendor_ecc_info: (&VENDOR_ECC_PUBKEY, &VENDOR_ECC_SIG), - vendor_lms_info: (&binding_vendor_lms_pubkey, &binding_vendor_lms_sig), + vendor_pqc_info: PqcKeyInfo::Lms(&binding_vendor_lms_pubkey, &binding_vendor_lms_sig), owner_ecc_info: (&owner_ecc_pubkey, &owner_ecc_sig), - owner_lms_info: (&owner_lms_pubkey, &owner_lms_sig), - owner_pub_keys_digest: ImageDigest::default(), + owner_pqc_info: PqcKeyInfo::Lms(&owner_lms_pubkey, &owner_lms_sig), + owner_pub_keys_digest: ImageDigest384::default(), owner_pub_keys_digest_in_fuses: false, vendor_ecc_pub_key_revocation: Default::default(), - vendor_lms_pub_key_revocation: Default::default(), + vendor_pqc_pub_key_revocation: Default::default(), }; let result = verifier.verify_header(&header, &header_info); assert_eq!( @@ -1435,7 +1641,7 @@ mod tests { fn test_header_incorrect_lms_pubkey_index() { let test_env = TestEnv { verify_result: true, - verify_lms_result: true, + verify_pqc_result: true, ..Default::default() }; let mut verifier = ImageVerifier::new(test_env); @@ -1448,20 +1654,20 @@ mod tests { let binding_vendor_lms_sig = vendor_lms_sig(); let header_info: HeaderInfo = HeaderInfo { vendor_ecc_pub_key_idx: 0, - vendor_lms_pub_key_idx: 1, + vendor_pqc_pub_key_idx: 1, vendor_ecc_info: (&VENDOR_ECC_PUBKEY, &VENDOR_ECC_SIG), - vendor_lms_info: (&binding_vendor_lms_pubkey, &binding_vendor_lms_sig), + vendor_pqc_info: PqcKeyInfo::Lms(&binding_vendor_lms_pubkey, &binding_vendor_lms_sig), owner_ecc_info: (&owner_ecc_pubkey, &owner_ecc_sig), - owner_lms_info: (&owner_lms_pubkey, &owner_lms_sig), - owner_pub_keys_digest: ImageDigest::default(), + owner_pqc_info: PqcKeyInfo::Lms(&owner_lms_pubkey, &owner_lms_sig), + owner_pub_keys_digest: ImageDigest384::default(), owner_pub_keys_digest_in_fuses: false, vendor_ecc_pub_key_revocation: Default::default(), - vendor_lms_pub_key_revocation: Default::default(), + vendor_pqc_pub_key_revocation: Default::default(), }; let result = verifier.verify_header(&header, &header_info); assert_eq!( result.err(), - Some(CaliptraError::IMAGE_VERIFIER_ERR_VENDOR_LMS_PUB_KEY_INDEX_MISMATCH) + Some(CaliptraError::IMAGE_VERIFIER_ERR_VENDOR_PQC_PUB_KEY_INDEX_MISMATCH) ); } @@ -1469,7 +1675,7 @@ mod tests { fn test_header_owner_pubkey_invalid_arg() { let test_env = TestEnv { verify_result: true, - verify_lms_result: true, + verify_pqc_result: true, ..Default::default() }; let mut verifier = ImageVerifier::new(test_env); @@ -1482,15 +1688,15 @@ mod tests { let binding_vendor_lms_sig = vendor_lms_sig(); let header_info: HeaderInfo = HeaderInfo { vendor_ecc_pub_key_idx: 0, - vendor_lms_pub_key_idx: 0, + vendor_pqc_pub_key_idx: 0, vendor_ecc_info: (&VENDOR_ECC_PUBKEY, &VENDOR_ECC_SIG), - vendor_lms_info: (&binding_vendor_lms_pubkey, &binding_vendor_lms_sig), + vendor_pqc_info: PqcKeyInfo::Lms(&binding_vendor_lms_pubkey, &binding_vendor_lms_sig), owner_ecc_info: (&owner_ecc_pubkey, &owner_ecc_sig), - owner_lms_info: (&owner_lms_pubkey, &owner_lms_sig), - owner_pub_keys_digest: ImageDigest::default(), + owner_pqc_info: PqcKeyInfo::Lms(&owner_lms_pubkey, &owner_lms_sig), + owner_pub_keys_digest: ImageDigest384::default(), owner_pub_keys_digest_in_fuses: false, vendor_ecc_pub_key_revocation: Default::default(), - vendor_lms_pub_key_revocation: Default::default(), + vendor_pqc_pub_key_revocation: Default::default(), }; let result = verifier.verify_header(&header, &header_info); assert_eq!( @@ -1503,7 +1709,7 @@ mod tests { fn test_header_owner_signature_invalid_arg() { let test_env = TestEnv { verify_result: true, - verify_lms_result: true, + verify_pqc_result: true, ..Default::default() }; let mut verifier = ImageVerifier::new(test_env); @@ -1515,15 +1721,15 @@ mod tests { let binding_vendor_lms_sig = vendor_lms_sig(); let header_info: HeaderInfo = HeaderInfo { vendor_ecc_pub_key_idx: 0, - vendor_lms_pub_key_idx: 0, + vendor_pqc_pub_key_idx: 0, vendor_ecc_info: (&VENDOR_ECC_PUBKEY, &VENDOR_ECC_SIG), - vendor_lms_info: (&binding_vendor_lms_pubkey, &binding_vendor_lms_sig), + vendor_pqc_info: PqcKeyInfo::Lms(&binding_vendor_lms_pubkey, &binding_vendor_lms_sig), owner_ecc_info: (&OWNER_ECC_PUBKEY, &owner_ecc_sig), - owner_lms_info: (&owner_lms_pubkey, &owner_lms_sig), - owner_pub_keys_digest: ImageDigest::default(), + owner_pqc_info: PqcKeyInfo::Lms(&owner_lms_pubkey, &owner_lms_sig), + owner_pub_keys_digest: ImageDigest384::default(), owner_pub_keys_digest_in_fuses: false, vendor_ecc_pub_key_revocation: Default::default(), - vendor_lms_pub_key_revocation: Default::default(), + vendor_pqc_pub_key_revocation: Default::default(), }; let result = verifier.verify_header(&header, &header_info); assert_eq!( @@ -1536,7 +1742,7 @@ mod tests { fn test_header_success() { let test_env = TestEnv { verify_result: true, - verify_lms_result: true, + verify_pqc_result: true, ..Default::default() }; let mut verifier = ImageVerifier::new(test_env); @@ -1551,15 +1757,15 @@ mod tests { let binding_vendor_lms_sig = vendor_lms_sig(); let header_info: HeaderInfo = HeaderInfo { vendor_ecc_pub_key_idx: 0, - vendor_lms_pub_key_idx: 0, + vendor_pqc_pub_key_idx: 0, vendor_ecc_info: (&VENDOR_ECC_PUBKEY, &VENDOR_ECC_SIG), - vendor_lms_info: (&binding_vendor_lms_pubkey, &binding_vendor_lms_sig), + vendor_pqc_info: PqcKeyInfo::Lms(&binding_vendor_lms_pubkey, &binding_vendor_lms_sig), owner_ecc_info: (&OWNER_ECC_PUBKEY, &OWNER_ECC_SIG), - owner_lms_info: (&owner_lms_pubkey, &owner_lms_sig), - owner_pub_keys_digest: ImageDigest::default(), + owner_pqc_info: PqcKeyInfo::Lms(&owner_lms_pubkey, &owner_lms_sig), + owner_pub_keys_digest: ImageDigest384::default(), owner_pub_keys_digest_in_fuses: false, vendor_ecc_pub_key_revocation: Default::default(), - vendor_lms_pub_key_revocation: Default::default(), + vendor_pqc_pub_key_revocation: Default::default(), }; let toc_info = verifier.verify_header(&header, &header_info).unwrap(); assert_eq!(toc_info.len, 100); @@ -1573,7 +1779,7 @@ mod tests { let mut verifier = ImageVerifier::new(test_env); let toc_info = TocInfo { len: MAX_TOC_ENTRY_COUNT / 2, - digest: &ImageDigest::default(), + digest: &ImageDigest384::default(), }; let result = verifier.verify_toc(&manifest, &toc_info, manifest.size); assert_eq!( @@ -1605,7 +1811,7 @@ mod tests { let mut verifier = ImageVerifier::new(test_env); let toc_info = TocInfo { len: MAX_TOC_ENTRY_COUNT, - digest: &ImageDigest::default(), + digest: &ImageDigest384::default(), }; // Case 0: @@ -1735,7 +1941,7 @@ mod tests { let mut verifier = ImageVerifier::new(test_env); let toc_info = TocInfo { len: MAX_TOC_ENTRY_COUNT, - digest: &ImageDigest::default(), + digest: &ImageDigest384::default(), }; // FMC size == 0 @@ -1780,7 +1986,7 @@ mod tests { let mut verifier = ImageVerifier::new(test_env); let toc_info = TocInfo { len: MAX_TOC_ENTRY_COUNT, - digest: &ImageDigest::default(), + digest: &ImageDigest384::default(), }; // [-FMC--] @@ -1807,7 +2013,7 @@ mod tests { let mut verifier = ImageVerifier::new(test_env); let toc_info = TocInfo { len: MAX_TOC_ENTRY_COUNT, - digest: &ImageDigest::default(), + digest: &ImageDigest384::default(), }; // [-FMC--] @@ -1834,7 +2040,7 @@ mod tests { let mut verifier = ImageVerifier::new(test_env); let toc_info = TocInfo { len: MAX_TOC_ENTRY_COUNT, - digest: &ImageDigest::default(), + digest: &ImageDigest384::default(), }; manifest.fmc.offset = 0; @@ -2004,41 +2210,47 @@ mod tests { } struct TestEnv { - digest: ImageDigest, - fmc_digest: ImageDigest, + digest_384: ImageDigest384, + digest_512: ImageDigest512, + fmc_digest: ImageDigest384, verify_result: bool, - verify_lms_result: bool, - vendor_pub_key_digest: ImageDigest, + verify_pqc_result: bool, + vendor_pub_key_digest: ImageDigest384, vendor_ecc_pub_key_revocation: VendorPubKeyRevocation, vendor_lms_pub_key_revocation: u32, - owner_pub_key_digest: ImageDigest, + owner_pub_key_digest: ImageDigest384, lifecycle: Lifecycle, } impl Default for TestEnv { fn default() -> Self { TestEnv { - digest: ImageDigest::default(), - fmc_digest: ImageDigest::default(), + digest_384: ImageDigest384::default(), + digest_512: ImageDigest512::default(), + fmc_digest: ImageDigest384::default(), verify_result: false, - verify_lms_result: false, - vendor_pub_key_digest: ImageDigest::default(), + verify_pqc_result: false, + vendor_pub_key_digest: ImageDigest384::default(), vendor_ecc_pub_key_revocation: VendorPubKeyRevocation::default(), vendor_lms_pub_key_revocation: 0, - owner_pub_key_digest: ImageDigest::default(), + owner_pub_key_digest: ImageDigest384::default(), lifecycle: Lifecycle::Unprovisioned, } } } impl ImageVerificationEnv for TestEnv { - fn sha384_digest(&mut self, _offset: u32, _len: u32) -> CaliptraResult { - Ok(self.digest) + fn sha384_digest(&mut self, _offset: u32, _len: u32) -> CaliptraResult { + Ok(self.digest_384) + } + + fn sha512_digest(&mut self, _offset: u32, _len: u32) -> CaliptraResult { + Ok(self.digest_512) } fn ecc384_verify( &mut self, - _digest: &ImageDigest, + _digest: &ImageDigest384, _pub_key: &ImageEccPubKey, sig: &ImageEccSignature, ) -> CaliptraResult> { @@ -2051,18 +2263,31 @@ mod tests { fn lms_verify( &mut self, - _digest: &ImageDigest, + _digest: &ImageDigest384, pub_key: &ImageLmsPublicKey, _sig: &ImageLmsSignature, ) -> CaliptraResult> { - if self.verify_lms_result { + if self.verify_pqc_result { Ok(HashValue::from(pub_key.digest)) } else { Ok(HashValue::from(&[0xDEADBEEF; 6])) } } - fn vendor_pub_key_info_digest_fuses(&self) -> ImageDigest { + fn mldsa87_verify( + &mut self, + _digest: &ImageDigest512, + _pub_key: &ImageMldsaPubKey, + _sig: &ImageMldsaSignature, + ) -> CaliptraResult { + if self.verify_pqc_result { + Ok(Mldsa87Result::Success) + } else { + Ok(Mldsa87Result::SigVerifyFailed) + } + } + + fn vendor_pub_key_info_digest_fuses(&self) -> ImageDigest384 { self.vendor_pub_key_digest } @@ -2074,7 +2299,7 @@ mod tests { self.vendor_lms_pub_key_revocation } - fn owner_pub_key_digest_fuses(&self) -> ImageDigest { + fn owner_pub_key_digest_fuses(&self) -> ImageDigest384 { self.owner_pub_key_digest } @@ -2090,15 +2315,15 @@ mod tests { 0 } - fn vendor_lms_pub_key_idx_dv(&self) -> u32 { + fn vendor_pqc_pub_key_idx_dv(&self) -> u32 { 0 } - fn owner_pub_key_digest_dv(&self) -> ImageDigest { + fn owner_pub_key_digest_dv(&self) -> ImageDigest384 { self.owner_pub_key_digest } - fn get_fmc_digest_dv(&self) -> ImageDigest { + fn get_fmc_digest_dv(&self) -> ImageDigest384 { self.fmc_digest } diff --git a/lms-types/src/lib.rs b/lms-types/src/lib.rs index d5d1423a3e..8bf00f8c37 100644 --- a/lms-types/src/lib.rs +++ b/lms-types/src/lib.rs @@ -97,6 +97,26 @@ unsafe impl FromBytes for LmsPublicKey { fn only_derive_is_allowed_to_implement_this_trait() {} } +impl LmsPublicKey { + pub fn ref_from_prefix(bytes: &[u8]) -> Option<&Self> { + if bytes.len() >= size_of::() { + Some(unsafe { &*(bytes.as_ptr() as *const Self) }) + } else { + None + } + } +} + +impl LmsPublicKey { + pub fn mut_ref_from_prefix(bytes: &mut [u8]) -> Option<&mut Self> { + if bytes.len() >= size_of::() { + Some(unsafe { &mut *(bytes.as_mut_ptr() as *mut Self) }) + } else { + None + } + } +} + #[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))] #[derive(Copy, Clone, Debug, PartialEq, Eq, Zeroize)] #[repr(C)] @@ -171,6 +191,27 @@ unsafe impl AsBytes for LmsSigna unsafe impl FromBytes for LmsSignature { fn only_derive_is_allowed_to_implement_this_trait() {} } +impl LmsSignature { + pub fn ref_from_prefix(bytes: &[u8]) -> Option<&Self> { + if bytes.len() >= size_of::() { + Some(unsafe { &*(bytes.as_ptr() as *const Self) }) + } else { + None + } + } +} + +impl LmsSignature { + pub fn mut_ref_from_prefix(bytes: &mut [u8]) -> Option<&mut Self> { + { + if bytes.len() >= size_of::() { + Some(unsafe { &mut *(bytes.as_mut_ptr() as *mut Self) }) + } else { + None + } + } + } +} #[derive(Debug, Copy, Clone, Eq, PartialEq)] #[repr(C)] diff --git a/rom/dev/Makefile b/rom/dev/Makefile index c46f568124..9294ddfca3 100644 --- a/rom/dev/Makefile +++ b/rom/dev/Makefile @@ -68,10 +68,10 @@ build-fw-image: gen-certs build-test-fmc build-test-rt --manifest-path ../../image/app/Cargo.toml \ -- \ create \ - --image-type 1 \ + --pqc-key-type 1 \ --key-config $(TARGET_DIR)/keys.toml \ --ecc-pk-idx 1 \ - --lms-pk-idx 3 \ + --pqc-pk-idx 3 \ --fmc $(TARGET_DIR)/caliptra-rom-test-fmc \ --fmc-version 0 \ --fmc-svn 0 \ diff --git a/rom/dev/README.md b/rom/dev/README.md index cac3579868..7e5b85de1a 100644 --- a/rom/dev/README.md +++ b/rom/dev/README.md @@ -114,8 +114,6 @@ It is the unsigned portion of the manifest. Preamble contains the signing public | Active LMS or MLDSA Key | 2592 | LMS public key (48 bytes + 2544 unused bytes) used to verify the Firmware Manifest Header Signature.
**tree_type:** LMS Algorithm Type (4 bytes, big endian) Must equal 12.
**otstype:** LM-OTS Algorithm Type (4 bytes, big endian) Must equal 7.
**id:** (16 bytes)
**digest:** (24 bytes)

**OR**

MLDSA-87 public key used to verify the Firmware Manifest Header Signature.
(2592 bytes)| | Manufacturer ECC Signature | 96 | Manufacturer ECC P-384 signature of the Firmware Manifest header hashed using SHA2-384.
**R-Coordinate:** Random Point (48 bytes)
**S-Coordinate:** Proof (48 bytes) | | Manufacturer LMS or MLDSA Signature | 4628 | Manufacturer LMS signature (1620 bytes + 3008 unused bytes) of the Firmware Manifest header hashed using SHA2-384.
**q:** Leaf of the Merkle tree where the OTS public key appears (4 bytes)
**ots:** Lmots Signature (1252 bytes)
**tree_type:** Lms Algorithm Type (4 bytes)
**tree_path:** Path through the tree from the leaf associated with the LM-OTS signature to the root. (360 bytes)

**OR**

Vendor MLDSA-87 signature of the Firmware Manifest header hashed using SHA2-512 (4627 bytes + 1 Reserved byte)| -| Owner ECC Key Descriptor | 52 | Public Key Descriptor for ECC key | -| Owner LMS or MLDSA Key Descriptor | 52 | Public Key Descriptor for LMS or MLDSA key | | Owner ECC Public Key | 96 | ECC P-384 public key used to verify the Firmware Manifest Header Signature.
**X-Coordinate:** Public Key X-Coordinate (48 bytes)
**Y-Coordinate:** Public Key Y-Coordinate (48 bytes)| | Owner LMS or MLDSA Public Key | 2592 | LMS public key (48 bytes + 2544 unused bytes) used to verify the Firmware Manifest Header Signature.
**tree_type:** LMS Algorithm Type (4 bytes)
**otstype:** LMS Ots Algorithm Type (4 bytes)
**id:** (16 bytes)
**digest:** (24 bytes)

**OR**

MLDSA-87 public key used to verify the Firmware Manifest Header Signature.
(2592 bytes)| | Owner ECC Signature | 96 | Manufacturer ECC P-384 signature of the Firmware Manifest header hashed using SHA2-384.
**R-Coordinate:** Random Point (48 bytes)
**S-Coordinate:** Proof (48 bytes) | diff --git a/rom/dev/doc/test-coverage/test-coverage.md b/rom/dev/doc/test-coverage/test-coverage.md index 9477b13a3f..8733faf9fe 100644 --- a/rom/dev/doc/test-coverage/test-coverage.md +++ b/rom/dev/doc/test-coverage/test-coverage.md @@ -100,7 +100,7 @@ Tests update reset flow by providing a non-fw load Mailbox command | **test_upd Tests update reset flow by providing non-compliant fw image | **test_update_reset_verify_image_failure** | IMAGE_VERIFIER_ERR_MANIFEST_MARKER_MISMATCH Check if boot statuses are correctly reported | **test_update_reset_boot_status** | N/A Tests update reset flow by providing a different vendor ECC public key index in the image | **test_update_reset_vendor_ecc_pub_key_idx_dv_mismatch** |IMAGE_VERIFIER_ERR_UPDATE_RESET_VENDOR_ECC_PUB_KEY_IDX_MISMATCH -Tests update reset flow by providing a different vendor LMS public key index in the image | **test_update_reset_vendor_lms_pub_key_idx_dv_mismatch** | IMAGE_VERIFIER_ERR_UPDATE_RESET_VENDOR_LMS_PUB_KEY_IDX_MISMATCH +Tests update reset flow by providing a different vendor LMS public key index in the image | **test_update_reset_vendor_lms_pub_key_idx_dv_mismatch** | IMAGE_VERIFIER_ERR_UPDATE_RESET_VENDOR_PQC_PUB_KEY_IDX_MISMATCH Check value in WarmResetEntry4::RomUpdateResetStatus datavault register | **test_check_rom_update_reset_status_reg** | N/A Ensure that hitless update flow can update an entire 128k bundle with completely different ICCM contents than original boot | **test_update_reset_max_fw_image** | N/A

diff --git a/rom/dev/src/crypto.rs b/rom/dev/src/crypto.rs index 2a48ad0428..666197c936 100644 --- a/rom/dev/src/crypto.rs +++ b/rom/dev/src/crypto.rs @@ -313,7 +313,7 @@ impl Crypto { // Generate the public key. let pub_key = env - .mldsa + .mldsa87 .key_pair(&KeyReadArgs::new(key_pair_seed), &mut env.trng)?; Ok(MlDsaKeyPair { diff --git a/rom/dev/src/flow/cold_reset/fmc_alias.rs b/rom/dev/src/flow/cold_reset/fmc_alias.rs index aa130dc04d..f93fc3c0ce 100644 --- a/rom/dev/src/flow/cold_reset/fmc_alias.rs +++ b/rom/dev/src/flow/cold_reset/fmc_alias.rs @@ -208,7 +208,7 @@ impl FmcAliasLayer { env.soc_ifc.debug_locked() as u8, env.soc_ifc.fuse_bank().anti_rollback_disable() as u8, env.data_vault.ecc_vendor_pk_index() as u8, - env.data_vault.lms_vendor_pk_index() as u8, + env.data_vault.pqc_vendor_pk_index() as u8, fw_proc_info.pqc_verify_config, fw_proc_info.owner_pub_keys_digest_in_fuses as u8, ])?; diff --git a/rom/dev/src/flow/cold_reset/fw_processor.rs b/rom/dev/src/flow/cold_reset/fw_processor.rs index dc290b86a4..ff11224e38 100644 --- a/rom/dev/src/flow/cold_reset/fw_processor.rs +++ b/rom/dev/src/flow/cold_reset/fw_processor.rs @@ -111,6 +111,7 @@ impl FirmwareProcessor { sha2_512_384: &mut env.sha2_512_384, soc_ifc: &mut env.soc_ifc, ecc384: &mut env.ecc384, + mldsa87: &mut env.mldsa87, data_vault: &mut env.data_vault, pcr_bank: &mut env.pcr_bank, image: txn.raw_mailbox_contents(), @@ -382,6 +383,7 @@ impl FirmwareProcessor { soc_ifc: venv.soc_ifc, data_vault: venv.data_vault, ecc384: venv.ecc384, + mldsa87: venv.mldsa87, image: venv.image, }; @@ -395,8 +397,10 @@ impl FirmwareProcessor { let info = verifier.verify(manifest, img_bundle_sz, ResetReason::ColdReset)?; cprintln!( - "[fwproc] Img verified w/ Vendor ECC Key Idx {}, with SVN {} and effective fuse SVN {}", + "[fwproc] Img verified w/ Vendor ECC Key Idx {}, PQC Key Type: {}, PQC Key Idx {}, with SVN {} and effective fuse SVN {}", info.vendor_ecc_pub_key_idx, + manifest.pqc_key_type, + info.vendor_pqc_pub_key_idx, info.fw_svn, info.effective_fuse_svn, ); @@ -476,18 +480,18 @@ impl FirmwareProcessor { log_info.fw_log_info.fuse_svn.as_bytes(), )?; - // Log VendorLmsPubKeyIndex + // Log VendorPqcPubKeyIndex log_fuse_data( log, - FuseLogEntryId::VendorLmsPubKeyIndex, - log_info.vendor_lms_pub_key_idx.as_bytes(), + FuseLogEntryId::VendorPqcPubKeyIndex, + log_info.vendor_pqc_pub_key_idx.as_bytes(), )?; - // Log VendorLmsPubKeyRevocation + // Log VendorPqcPubKeyRevocation log_fuse_data( log, - FuseLogEntryId::VendorLmsPubKeyRevocation, - log_info.fuse_vendor_lms_pub_key_revocation.as_bytes(), + FuseLogEntryId::VendorPqcPubKeyRevocation, + log_info.fuse_vendor_pqc_pub_key_revocation.as_bytes(), )?; Ok(()) @@ -565,8 +569,8 @@ impl FirmwareProcessor { // If LMS is not enabled, write the max value to the data vault // to indicate the index is invalid. data_vault.write_cold_reset_entry4( - ColdResetEntry4::LmsVendorPubKeyIndex, - info.vendor_lms_pub_key_idx, + ColdResetEntry4::PqcVendorPubKeyIndex, + info.vendor_pqc_pub_key_idx, ); data_vault.write_warm_reset_entry48(WarmResetEntry48::RtTci, &info.runtime.digest.into()); diff --git a/rom/dev/src/flow/fake.rs b/rom/dev/src/flow/fake.rs index 6ca822fd9d..e712fd4be2 100644 --- a/rom/dev/src/flow/fake.rs +++ b/rom/dev/src/flow/fake.rs @@ -243,12 +243,13 @@ pub(crate) struct FakeRomImageVerificationEnv<'a, 'b> { pub(crate) soc_ifc: &'a mut SocIfc, pub(crate) data_vault: &'a mut DataVault, pub(crate) ecc384: &'a mut Ecc384, + pub(crate) mldsa87: &'a mut Mldsa87, pub image: &'b [u8], } impl<'a, 'b> ImageVerificationEnv for &mut FakeRomImageVerificationEnv<'a, 'b> { - /// Calculate Digest using SHA-384 Accelerator - fn sha384_digest(&mut self, offset: u32, len: u32) -> CaliptraResult { + /// Calculate 384 digest using SHA2 Engine + fn sha384_digest(&mut self, offset: u32, len: u32) -> CaliptraResult { let err = CaliptraError::IMAGE_VERIFIER_ERR_DIGEST_OUT_OF_BOUNDS; let data = self .image @@ -259,10 +260,22 @@ impl<'a, 'b> ImageVerificationEnv for &mut FakeRomImageVerificationEnv<'a, 'b> { Ok(self.sha2_512_384.sha384_digest(data)?.0) } + /// Calculate 512 digest using SHA2 Engine + fn sha512_digest(&mut self, offset: u32, len: u32) -> CaliptraResult { + let err = CaliptraError::IMAGE_VERIFIER_ERR_DIGEST_OUT_OF_BOUNDS; + let data = self + .image + .get(offset as usize..) + .ok_or(err)? + .get(..len as usize) + .ok_or(err)?; + Ok(self.sha2_512_384.sha512_digest(data)?.0) + } + /// ECC-384 Verification routine fn ecc384_verify( &mut self, - digest: &ImageDigest, + digest: &ImageDigest384, pub_key: &ImageEccPubKey, sig: &ImageEccSignature, ) -> CaliptraResult> { @@ -288,7 +301,7 @@ impl<'a, 'b> ImageVerificationEnv for &mut FakeRomImageVerificationEnv<'a, 'b> { fn lms_verify( &mut self, - digest: &ImageDigest, + digest: &ImageDigest384, pub_key: &ImageLmsPublicKey, sig: &ImageLmsSignature, ) -> CaliptraResult> { @@ -304,8 +317,26 @@ impl<'a, 'b> ImageVerificationEnv for &mut FakeRomImageVerificationEnv<'a, 'b> { } } + fn mldsa87_verify( + &mut self, + digest: &ImageDigest512, + pub_key: &ImageMldsaPubKey, + sig: &ImageMldsaSignature, + ) -> CaliptraResult { + if self.soc_ifc.verify_in_fake_mode() { + let pub_key = Mldsa87PubKey::from(pub_key.0); + let sig = Mldsa87Signature::from(sig.0); + let msg: Mldsa87Msg = Mldsa87Msg::from(digest); + + self.mldsa87.verify(&pub_key, &msg, &sig) + } else { + // Mock verify, just always return success + Ok(Mldsa87Result::Success) + } + } + /// Retrieve Vendor Public Key Digest - fn vendor_pub_key_info_digest_fuses(&self) -> ImageDigest { + fn vendor_pub_key_info_digest_fuses(&self) -> ImageDigest384 { self.soc_ifc.fuse_bank().vendor_pub_key_info_hash().into() } @@ -320,7 +351,7 @@ impl<'a, 'b> ImageVerificationEnv for &mut FakeRomImageVerificationEnv<'a, 'b> { } /// Retrieve Owner Public Key Digest from fuses - fn owner_pub_key_digest_fuses(&self) -> ImageDigest { + fn owner_pub_key_digest_fuses(&self) -> ImageDigest384 { self.soc_ifc.fuse_bank().owner_pub_key_hash().into() } @@ -340,17 +371,17 @@ impl<'a, 'b> ImageVerificationEnv for &mut FakeRomImageVerificationEnv<'a, 'b> { } /// Get the vendor LMS key index saved in data vault on cold boot - fn vendor_lms_pub_key_idx_dv(&self) -> u32 { - self.data_vault.lms_vendor_pk_index() + fn vendor_pqc_pub_key_idx_dv(&self) -> u32 { + self.data_vault.pqc_vendor_pk_index() } /// Get the owner public key digest saved in the dv on cold boot - fn owner_pub_key_digest_dv(&self) -> ImageDigest { + fn owner_pub_key_digest_dv(&self) -> ImageDigest384 { self.data_vault.owner_pk_hash().into() } // Get the fmc digest from the data vault on cold boot - fn get_fmc_digest_dv(&self) -> ImageDigest { + fn get_fmc_digest_dv(&self) -> ImageDigest384 { self.data_vault.fmc_tci().into() } diff --git a/rom/dev/src/flow/update_reset.rs b/rom/dev/src/flow/update_reset.rs index 9f154650fb..b7f8be199b 100644 --- a/rom/dev/src/flow/update_reset.rs +++ b/rom/dev/src/flow/update_reset.rs @@ -70,6 +70,7 @@ impl UpdateResetFlow { sha2_512_384: &mut env.sha2_512_384, soc_ifc: &mut env.soc_ifc, ecc384: &mut env.ecc384, + mldsa87: &mut env.mldsa87, data_vault: &mut env.data_vault, pcr_bank: &mut env.pcr_bank, image: recv_txn.raw_mailbox_contents(), @@ -151,6 +152,7 @@ impl UpdateResetFlow { soc_ifc: env.soc_ifc, data_vault: env.data_vault, ecc384: env.ecc384, + mldsa87: env.mldsa87, image: env.image, }; diff --git a/rom/dev/src/lock.rs b/rom/dev/src/lock.rs index 58f4cd7214..3934e18779 100644 --- a/rom/dev/src/lock.rs +++ b/rom/dev/src/lock.rs @@ -77,7 +77,7 @@ fn lock_cold_reset_reg(env: &mut RomEnv) { // Lock the Lms Vendor Public Key Index in data vault until next cold reset env.data_vault - .lock_cold_reset_entry4(ColdResetEntry4::LmsVendorPubKeyIndex); + .lock_cold_reset_entry4(ColdResetEntry4::PqcVendorPubKeyIndex); // Lock Cold Reset Status register in data vault until next cold reset env.data_vault diff --git a/rom/dev/src/pcr.rs b/rom/dev/src/pcr.rs index 47b2cf81f5..6e680be95a 100644 --- a/rom/dev/src/pcr.rs +++ b/rom/dev/src/pcr.rs @@ -85,7 +85,7 @@ pub(crate) fn extend_pcrs( env.data_vault.ecc_vendor_pk_index() as u8, env.data_vault.fmc_svn() as u8, info.effective_fuse_svn as u8, - env.data_vault.lms_vendor_pk_index() as u8, + env.data_vault.pqc_vendor_pk_index() as u8, info.pqc_verify_config as u8, info.owner_pub_keys_digest_in_fuses as u8, ]; diff --git a/rom/dev/src/rom_env.rs b/rom/dev/src/rom_env.rs index 9ab6e40d52..f2c7bfb74b 100644 --- a/rom/dev/src/rom_env.rs +++ b/rom/dev/src/rom_env.rs @@ -78,7 +78,7 @@ pub struct RomEnv { pub persistent_data: PersistentDataAccessor, /// Mldsa87 Engine - pub mldsa: Mldsa87, + pub mldsa87: Mldsa87, } impl RomEnv { @@ -107,7 +107,7 @@ impl RomEnv { fht_data_store: FhtDataStore::default(), trng, persistent_data: PersistentDataAccessor::new(), - mldsa: Mldsa87::new(MldsaReg::new()), + mldsa87: Mldsa87::new(MldsaReg::new()), }) } } diff --git a/rom/dev/tests/rom_integration_tests/test_fmcalias_derivation.rs b/rom/dev/tests/rom_integration_tests/test_fmcalias_derivation.rs index 72a3079fca..9c1799f44f 100644 --- a/rom/dev/tests/rom_integration_tests/test_fmcalias_derivation.rs +++ b/rom/dev/tests/rom_integration_tests/test_fmcalias_derivation.rs @@ -22,7 +22,7 @@ use caliptra_hw_model::{BootParams, Fuses, HwModel, InitParams, ModelError, Secu use caliptra_image_crypto::OsslCrypto as Crypto; use caliptra_image_fake_keys::{OWNER_CONFIG, VENDOR_CONFIG_KEY_1}; use caliptra_image_gen::ImageGenerator; -use caliptra_image_types::{FwImageType, IMAGE_BYTE_SIZE}; +use caliptra_image_types::{FwVerificationPqcKeyType, IMAGE_BYTE_SIZE}; use caliptra_test::swap_word_bytes; use openssl::hash::{Hasher, MessageDigest}; use zerocopy::{AsBytes, FromBytes}; @@ -202,7 +202,7 @@ fn test_pcr_log() { VENDOR_CONFIG_KEY_1.ecc_key_idx as u8, FMC_SVN as u8, 0_u8, - VENDOR_CONFIG_KEY_1.lms_key_idx as u8, + VENDOR_CONFIG_KEY_1.pqc_key_idx as u8, RomPqcVerifyConfig::EcdsaAndLms as u8, true as u8, ], @@ -304,7 +304,7 @@ fn test_pcr_log_no_owner_key_digest_fuse() { VENDOR_CONFIG_KEY_1.ecc_key_idx as u8, 0_u8, 0_u8, - VENDOR_CONFIG_KEY_1.lms_key_idx as u8, + VENDOR_CONFIG_KEY_1.pqc_key_idx as u8, RomPqcVerifyConfig::EcdsaAndLms as u8, false as u8, ], @@ -399,7 +399,7 @@ fn test_pcr_log_fmc_fuse_svn() { VENDOR_CONFIG_KEY_1.ecc_key_idx as u8, FMC_SVN as u8, FMC_FUSE_SVN as u8, - VENDOR_CONFIG_KEY_1.lms_key_idx as u8, + VENDOR_CONFIG_KEY_1.pqc_key_idx as u8, RomPqcVerifyConfig::EcdsaAndLms as u8, true as u8, ], @@ -610,7 +610,7 @@ fn test_fuse_log() { fmc_version: 0, app_svn: FMC_SVN, app_version: 0, - fw_image_type: FwImageType::EccLms, + pqc_key_type: FwVerificationPqcKeyType::LMS, }; let image_bundle = caliptra_builder::build_and_sign_image(&TEST_FMC_WITH_UART, &APP_WITH_UART, image_options) @@ -703,15 +703,15 @@ fn test_fuse_log() { assert_eq!(fuse_log_entry.entry_id, FuseLogEntryId::FuseRtSvn as u32); assert_eq!(fuse_log_entry.log_data[0], FMC_SVN); - // Validate the VendorLmsPubKeyIndex + // Validate the VendorPqcPubKeyIndex fuse_log_entry_offset += core::mem::size_of::(); let fuse_log_entry = FuseLogEntry::read_from_prefix(fuse_entry_arr[fuse_log_entry_offset..].as_bytes()).unwrap(); assert_eq!( fuse_log_entry.entry_id, - FuseLogEntryId::VendorLmsPubKeyIndex as u32 + FuseLogEntryId::VendorPqcPubKeyIndex as u32 ); - assert_eq!(fuse_log_entry.log_data[0], VENDOR_CONFIG_KEY_1.lms_key_idx); + assert_eq!(fuse_log_entry.log_data[0], VENDOR_CONFIG_KEY_1.pqc_key_idx); // Validate that the ID is VendorPubKeyRevocation fuse_log_entry_offset += core::mem::size_of::(); @@ -719,7 +719,7 @@ fn test_fuse_log() { FuseLogEntry::read_from_prefix(fuse_entry_arr[fuse_log_entry_offset..].as_bytes()).unwrap(); assert_eq!( fuse_log_entry.entry_id, - FuseLogEntryId::VendorLmsPubKeyRevocation as u32 + FuseLogEntryId::VendorPqcPubKeyRevocation as u32 ); assert_eq!(fuse_log_entry.log_data[0], 0,); } diff --git a/rom/dev/tests/rom_integration_tests/test_image_validation.rs b/rom/dev/tests/rom_integration_tests/test_image_validation.rs index 89618df6e8..96fa6dec31 100644 --- a/rom/dev/tests/rom_integration_tests/test_image_validation.rs +++ b/rom/dev/tests/rom_integration_tests/test_image_validation.rs @@ -9,13 +9,15 @@ use caliptra_builder::{ }, ImageOptions, }; -use caliptra_common::memory_layout::{ICCM_ORG, ICCM_SIZE}; -use caliptra_common::RomBootStatus::*; -use caliptra_drivers::MfgFlags; -use caliptra_drivers::{Array4x12, IdevidCertAttr}; +use caliptra_common::{ + memory_layout::{ICCM_ORG, ICCM_SIZE}, + RomBootStatus::*, +}; +use caliptra_drivers::{Array4x12, IdevidCertAttr, MfgFlags}; use caliptra_error::CaliptraError; use caliptra_hw_model::{ - BootParams, DeviceLifecycle, Fuses, HwModel, InitParams, ModelError, SecurityState, U4, + BootParams, DefaultHwModel, DeviceLifecycle, Fuses, HwModel, InitParams, ModelError, + SecurityState, U4, }; use caliptra_image_crypto::OsslCrypto as Crypto; use caliptra_image_elf::ElfExecutable; @@ -24,16 +26,18 @@ use caliptra_image_fake_keys::{ }; use caliptra_image_gen::{ImageGenerator, ImageGeneratorConfig, ImageGeneratorVendorConfig}; use caliptra_image_types::{ - FwImageType, ImageBundle, ImageManifest, VENDOR_ECC_MAX_KEY_COUNT, VENDOR_LMS_MAX_KEY_COUNT, + FwVerificationPqcKeyType, ImageBundle, ImageDigestHolder, ImageLmsPublicKey, ImageLmsSignature, + ImageManifest, ImageMldsaPubKey, ImageMldsaSignature, MLDSA87_SIGNATURE_WORD_SIZE, + VENDOR_ECC_MAX_KEY_COUNT, VENDOR_LMS_MAX_KEY_COUNT, VENDOR_MLDSA_MAX_KEY_COUNT, +}; +use openssl::{ + asn1::{Asn1Integer, Asn1Time}, + bn::BigNum, + hash::MessageDigest, + pkey::{PKey, Private}, + rsa::Rsa, + x509::{X509Req, X509}, }; -use openssl::asn1::Asn1Integer; -use openssl::asn1::Asn1Time; -use openssl::bn::BigNum; -use openssl::hash::MessageDigest; -use openssl::pkey::{PKey, Private}; -use openssl::rsa::Rsa; -use openssl::x509::X509Req; -use openssl::x509::X509; use std::str; use zerocopy::AsBytes; @@ -250,17 +254,17 @@ fn test_preamble_vendor_lms_pubkey_revocation() { for idx in 0..VENDOR_LMS_MAX_KEY_COUNT { let vendor_config = ImageGeneratorVendorConfig { ecc_key_idx: 3, - lms_key_idx: idx, + pqc_key_idx: idx, ..VENDOR_CONFIG_KEY_0 }; let mut image_options = ImageOptions::default(); - let key_idx = vendor_config.lms_key_idx; + let key_idx = vendor_config.pqc_key_idx; image_options.vendor_config = vendor_config; let fuses = caliptra_hw_model::Fuses { lms_verify: true, - fuse_lms_revocation: 1u32 << image_options.vendor_config.lms_key_idx, + fuse_lms_revocation: 1u32 << image_options.vendor_config.pqc_key_idx, ..Default::default() }; @@ -325,7 +329,7 @@ fn test_preamble_vendor_lms_pubkey_out_of_bounds() { }; let (mut hw, mut image_bundle) = helpers::build_hw_model_and_image_bundle(fuses, ImageOptions::default()); - image_bundle.manifest.preamble.vendor_lms_pub_key_idx = VENDOR_LMS_MAX_KEY_COUNT; + image_bundle.manifest.preamble.vendor_pqc_pub_key_idx = VENDOR_LMS_MAX_KEY_COUNT; assert_eq!( ModelError::MailboxCmdFailed( @@ -352,7 +356,7 @@ fn test_header_verify_vendor_sig_zero_ecc_pubkey() { assert_eq!( ModelError::MailboxCmdFailed( - CaliptraError::IMAGE_VERIFIER_ERR_VENDOR_PUB_KEY_DIGEST_INVALID_ARG.into() + CaliptraError::IMAGE_VERIFIER_ERR_VENDOR_ECC_PUB_KEY_INVALID_ARG.into() ), hw.upload_firmware(&image_bundle.to_bytes().unwrap()) .unwrap_err() @@ -378,7 +382,7 @@ fn test_header_verify_vendor_sig_zero_ecc_pubkey() { assert_eq!( ModelError::MailboxCmdFailed( - CaliptraError::IMAGE_VERIFIER_ERR_VENDOR_PUB_KEY_DIGEST_INVALID_ARG.into() + CaliptraError::IMAGE_VERIFIER_ERR_VENDOR_ECC_PUB_KEY_INVALID_ARG.into() ), hw.upload_firmware(&image_bundle.to_bytes().unwrap()) .unwrap_err() @@ -513,13 +517,18 @@ fn test_header_verify_vendor_lms_sig_mismatch() { helpers::build_hw_model_and_image_bundle(fuses, ImageOptions::default()); // Modify the vendor public key. - let lms_pub_key_backup = image_bundle.manifest.preamble.vendor_lms_active_pub_key; + let lms_pub_key_backup = image_bundle.manifest.preamble.vendor_pqc_active_pub_key; - image_bundle - .manifest - .preamble - .vendor_lms_active_pub_key - .digest = [Default::default(); 6]; + let lms_pub_key = ImageLmsPublicKey::mut_ref_from_prefix( + image_bundle + .manifest + .preamble + .vendor_pqc_active_pub_key + .0 + .as_bytes_mut(), + ) + .unwrap(); + lms_pub_key.digest = [Default::default(); 6]; assert_eq!( ModelError::MailboxCmdFailed( CaliptraError::IMAGE_VERIFIER_ERR_VENDOR_LMS_SIGNATURE_INVALID.into() @@ -537,9 +546,18 @@ fn test_header_verify_vendor_lms_sig_mismatch() { helpers::build_hw_model_and_image_bundle(fuses, ImageOptions::default()); // Modify the vendor signature. - image_bundle.manifest.preamble.vendor_lms_active_pub_key = lms_pub_key_backup; - image_bundle.manifest.preamble.vendor_sigs.lms_sig.tree_path[0] = [Default::default(); 6]; - + image_bundle.manifest.preamble.vendor_pqc_active_pub_key = lms_pub_key_backup; + let lms_sig = ImageLmsSignature::mut_ref_from_prefix( + image_bundle + .manifest + .preamble + .vendor_sigs + .pqc_sig + .0 + .as_bytes_mut(), + ) + .unwrap(); + lms_sig.tree_path[0] = [Default::default(); 6]; assert_eq!( ModelError::MailboxCmdFailed( CaliptraError::IMAGE_VERIFIER_ERR_VENDOR_LMS_SIGNATURE_INVALID.into() @@ -564,14 +582,19 @@ fn test_header_verify_owner_lms_sig_mismatch() { helpers::build_hw_model_and_image_bundle(fuses, ImageOptions::default()); // Modify the owner public key. - let lms_pub_key_backup = image_bundle.manifest.preamble.owner_pub_keys.lms_pub_key; + let lms_pub_key_backup = image_bundle.manifest.preamble.owner_pub_keys.pqc_pub_key; - image_bundle - .manifest - .preamble - .owner_pub_keys - .lms_pub_key - .digest = [Default::default(); 6]; + let lms_pub_key = ImageLmsPublicKey::mut_ref_from_prefix( + image_bundle + .manifest + .preamble + .owner_pub_keys + .pqc_pub_key + .0 + .as_bytes_mut(), + ) + .unwrap(); + lms_pub_key.digest = [Default::default(); 6]; assert_eq!( ModelError::MailboxCmdFailed( CaliptraError::IMAGE_VERIFIER_ERR_OWNER_LMS_SIGNATURE_INVALID.into() @@ -589,9 +612,18 @@ fn test_header_verify_owner_lms_sig_mismatch() { helpers::build_hw_model_and_image_bundle(fuses, ImageOptions::default()); // Modify the owner signature. - image_bundle.manifest.preamble.owner_pub_keys.lms_pub_key = lms_pub_key_backup; - image_bundle.manifest.preamble.owner_sigs.lms_sig.tree_path[0] = [Default::default(); 6]; - + image_bundle.manifest.preamble.owner_pub_keys.pqc_pub_key = lms_pub_key_backup; + let lms_sig = ImageLmsSignature::mut_ref_from_prefix( + image_bundle + .manifest + .preamble + .owner_sigs + .pqc_sig + .0 + .as_bytes_mut(), + ) + .unwrap(); + lms_sig.tree_path[0] = [Default::default(); 6]; assert_eq!( ModelError::MailboxCmdFailed( CaliptraError::IMAGE_VERIFIER_ERR_OWNER_LMS_SIGNATURE_INVALID.into() @@ -638,13 +670,13 @@ fn test_header_verify_vendor_lms_pub_key_in_preamble_and_header() { helpers::build_hw_model_and_image_bundle(fuses, ImageOptions::default()); // Change vendor pubkey index. - image_bundle.manifest.header.vendor_lms_pub_key_idx = - image_bundle.manifest.preamble.vendor_lms_pub_key_idx + 1; + image_bundle.manifest.header.vendor_pqc_pub_key_idx = + image_bundle.manifest.preamble.vendor_pqc_pub_key_idx + 1; update_header(&mut image_bundle); assert_eq!( ModelError::MailboxCmdFailed( - CaliptraError::IMAGE_VERIFIER_ERR_VENDOR_LMS_PUB_KEY_INDEX_MISMATCH.into() + CaliptraError::IMAGE_VERIFIER_ERR_VENDOR_PQC_PUB_KEY_INDEX_MISMATCH.into() ), hw.upload_firmware(&image_bundle.to_bytes().unwrap()) .unwrap_err() @@ -1798,24 +1830,33 @@ fn update_header(image_bundle: &mut ImageBundle) { runtime: ElfExecutable::default(), vendor_config: opts.vendor_config, owner_config: opts.owner_config, - fw_image_type: FwImageType::EccLms, + pqc_key_type: FwVerificationPqcKeyType::LMS, }; let gen = ImageGenerator::new(Crypto::default()); - let header_digest_vendor = gen - .header_digest_vendor(&image_bundle.manifest.header) + let vendor_header_digest_384 = gen + .vendor_header_digest_384(&image_bundle.manifest.header) .unwrap(); - let header_digest_owner = gen - .header_digest_owner(&image_bundle.manifest.header) + let vendor_header_digest_holder = ImageDigestHolder { + digest_384: &vendor_header_digest_384, + digest_512: None, + }; + + let owner_header_digest_384 = gen + .owner_header_digest_384(&image_bundle.manifest.header) .unwrap(); + let owner_header_digest_holder = ImageDigestHolder { + digest_384: &owner_header_digest_384, + digest_512: None, + }; image_bundle.manifest.preamble = gen .gen_preamble( &config, image_bundle.manifest.preamble.vendor_ecc_pub_key_idx, - image_bundle.manifest.preamble.vendor_lms_pub_key_idx, - &header_digest_vendor, - &header_digest_owner, + image_bundle.manifest.preamble.vendor_pqc_pub_key_idx, + &vendor_header_digest_holder, + &owner_header_digest_holder, ) .unwrap(); } @@ -2118,3 +2159,328 @@ fn test_max_fw_image() { assert_eq!(iccm_cmp.len(), 1); assert_eq!(iccm_cmp[0], 0); } + +#[test] +fn test_mldsa_verification() { + let rom = caliptra_builder::build_firmware_rom(firmware::rom_from_env()).unwrap(); + let mut hw = caliptra_hw_model::new( + InitParams { + rom: &rom, + ..Default::default() + }, + BootParams::default(), + ) + .unwrap(); + + let image_options = ImageOptions { + pqc_key_type: FwVerificationPqcKeyType::MLDSA, + ..Default::default() + }; + + let image_bundle = caliptra_builder::build_and_sign_image( + &TEST_FMC_INTERACTIVE, + &TEST_RT_WITH_UART, + image_options, + ) + .unwrap(); + + hw.upload_firmware(&image_bundle.to_bytes().unwrap()) + .unwrap(); + + hw.step_until_boot_status(u32::from(ColdResetComplete), true); +} + +fn hw_and_mldsa_image_bundle() -> (DefaultHwModel, ImageBundle) { + let rom = caliptra_builder::build_firmware_rom(firmware::rom_from_env()).unwrap(); + let hw = caliptra_hw_model::new( + InitParams { + rom: &rom, + ..Default::default() + }, + BootParams::default(), + ) + .unwrap(); + + let image_options = ImageOptions { + pqc_key_type: FwVerificationPqcKeyType::MLDSA, + ..Default::default() + }; + + let image_bundle = caliptra_builder::build_and_sign_image( + &TEST_FMC_INTERACTIVE, + &TEST_RT_WITH_UART, + image_options, + ) + .unwrap(); + + (hw, image_bundle) +} + +#[test] +fn test_header_verify_vendor_mldsa_sig_zero() { + let (mut hw, mut image_bundle) = hw_and_mldsa_image_bundle(); + + // Modify the vendor public key. + let mldsa_pub_key_backup = image_bundle.manifest.preamble.vendor_pqc_active_pub_key; + + let mldsa_pub_key = ImageMldsaPubKey::mut_ref_from_prefix( + image_bundle + .manifest + .preamble + .vendor_pqc_active_pub_key + .0 + .as_bytes_mut(), + ) + .unwrap(); + + *mldsa_pub_key = Default::default(); + assert_eq!( + hw.upload_firmware(&image_bundle.to_bytes().unwrap()) + .unwrap_err(), + ModelError::MailboxCmdFailed( + CaliptraError::IMAGE_VERIFIER_ERR_VENDOR_MLDSA_SIGNATURE_INVALID.into() + ) + ); + drop(hw); + + let (mut hw, mut image_bundle) = hw_and_mldsa_image_bundle(); + + // Modify the vendor signature. + image_bundle.manifest.preamble.vendor_pqc_active_pub_key = mldsa_pub_key_backup; + let mldsa_sig = ImageMldsaSignature::mut_ref_from_prefix( + image_bundle + .manifest + .preamble + .vendor_sigs + .pqc_sig + .0 + .as_bytes_mut(), + ) + .unwrap(); + *mldsa_sig = Default::default(); + assert_eq!( + hw.upload_firmware(&image_bundle.to_bytes().unwrap()) + .unwrap_err(), + ModelError::MailboxCmdFailed( + CaliptraError::IMAGE_VERIFIER_ERR_VENDOR_MLDSA_SIGNATURE_INVALID.into() + ) + ); + + assert_eq!( + hw.soc_ifc().cptra_boot_status().read(), + u32::from(FwProcessorManifestLoadComplete) + ); +} + +#[test] +fn test_header_verify_vendor_mldsa_sig_mismatch() { + let (mut hw, mut image_bundle) = hw_and_mldsa_image_bundle(); + + // Modify the vendor public key. + let mldsa_pub_key_backup = image_bundle.manifest.preamble.vendor_pqc_active_pub_key; + + let mldsa_pub_key = ImageMldsaPubKey::mut_ref_from_prefix( + image_bundle + .manifest + .preamble + .vendor_pqc_active_pub_key + .0 + .as_bytes_mut(), + ) + .unwrap(); + + *mldsa_pub_key = Default::default(); + assert_eq!( + hw.upload_firmware(&image_bundle.to_bytes().unwrap()) + .unwrap_err(), + ModelError::MailboxCmdFailed( + CaliptraError::IMAGE_VERIFIER_ERR_VENDOR_MLDSA_SIGNATURE_INVALID.into() + ) + ); + drop(hw); + + let (mut hw, mut image_bundle) = hw_and_mldsa_image_bundle(); + + // Modify the vendor signature. + image_bundle.manifest.preamble.vendor_pqc_active_pub_key = mldsa_pub_key_backup; + let mldsa_sig = ImageMldsaSignature::mut_ref_from_prefix( + image_bundle + .manifest + .preamble + .vendor_sigs + .pqc_sig + .0 + .as_bytes_mut(), + ) + .unwrap(); + + let mut signature = [0u32; MLDSA87_SIGNATURE_WORD_SIZE]; + signature[0..4].copy_from_slice(&[0xDE, 0xAD, 0xBE, 0xEF]); + *mldsa_sig = ImageMldsaSignature(signature); + + assert_eq!( + hw.upload_firmware(&image_bundle.to_bytes().unwrap()) + .unwrap_err(), + ModelError::MailboxCmdFailed( + CaliptraError::IMAGE_VERIFIER_ERR_VENDOR_MLDSA_SIGNATURE_INVALID.into() + ) + ); + + assert_eq!( + hw.soc_ifc().cptra_boot_status().read(), + u32::from(FwProcessorManifestLoadComplete) + ); +} + +#[test] +fn test_header_verify_owner_mldsa_sig_zero() { + let (mut hw, mut image_bundle) = hw_and_mldsa_image_bundle(); + + // Modify the owner public key. + let mldsa_pub_key_backup = image_bundle.manifest.preamble.owner_pub_keys.pqc_pub_key; + + let mldsa_pub_key = ImageMldsaPubKey::mut_ref_from_prefix( + image_bundle + .manifest + .preamble + .owner_pub_keys + .pqc_pub_key + .0 + .as_bytes_mut(), + ) + .unwrap(); + + *mldsa_pub_key = Default::default(); + assert_eq!( + hw.upload_firmware(&image_bundle.to_bytes().unwrap()) + .unwrap_err(), + ModelError::MailboxCmdFailed( + CaliptraError::IMAGE_VERIFIER_ERR_OWNER_MLDSA_SIGNATURE_INVALID.into() + ) + ); + drop(hw); + + let (mut hw, mut image_bundle) = hw_and_mldsa_image_bundle(); + + // Modify the owner signature. + image_bundle.manifest.preamble.owner_pub_keys.pqc_pub_key = mldsa_pub_key_backup; + let mldsa_sig = ImageMldsaSignature::mut_ref_from_prefix( + image_bundle + .manifest + .preamble + .owner_sigs + .pqc_sig + .0 + .as_bytes_mut(), + ) + .unwrap(); + *mldsa_sig = Default::default(); + assert_eq!( + hw.upload_firmware(&image_bundle.to_bytes().unwrap()) + .unwrap_err(), + ModelError::MailboxCmdFailed( + CaliptraError::IMAGE_VERIFIER_ERR_OWNER_MLDSA_SIGNATURE_INVALID.into() + ) + ); + + assert_eq!( + hw.soc_ifc().cptra_boot_status().read(), + u32::from(FwProcessorManifestLoadComplete) + ); +} + +#[test] +fn test_header_verify_owner_mldsa_sig_mismatch() { + let (mut hw, mut image_bundle) = hw_and_mldsa_image_bundle(); + + // Modify the owner public key. + let mldsa_pub_key_backup = image_bundle.manifest.preamble.owner_pub_keys.pqc_pub_key; + + let mldsa_pub_key = ImageMldsaPubKey::mut_ref_from_prefix( + image_bundle + .manifest + .preamble + .owner_pub_keys + .pqc_pub_key + .0 + .as_bytes_mut(), + ) + .unwrap(); + + *mldsa_pub_key = Default::default(); + assert_eq!( + hw.upload_firmware(&image_bundle.to_bytes().unwrap()) + .unwrap_err(), + ModelError::MailboxCmdFailed( + CaliptraError::IMAGE_VERIFIER_ERR_OWNER_MLDSA_SIGNATURE_INVALID.into() + ) + ); + drop(hw); + + let (mut hw, mut image_bundle) = hw_and_mldsa_image_bundle(); + + // Modify the owner signature. + image_bundle.manifest.preamble.owner_pub_keys.pqc_pub_key = mldsa_pub_key_backup; + let mldsa_sig = ImageMldsaSignature::mut_ref_from_prefix( + image_bundle + .manifest + .preamble + .owner_sigs + .pqc_sig + .0 + .as_bytes_mut(), + ) + .unwrap(); + + let mut signature = [0u32; MLDSA87_SIGNATURE_WORD_SIZE]; + signature[0..4].copy_from_slice(&[0xDE, 0xAD, 0xBE, 0xEF]); + *mldsa_sig = ImageMldsaSignature(signature); + + assert_eq!( + hw.upload_firmware(&image_bundle.to_bytes().unwrap()) + .unwrap_err(), + ModelError::MailboxCmdFailed( + CaliptraError::IMAGE_VERIFIER_ERR_OWNER_MLDSA_SIGNATURE_INVALID.into() + ) + ); + + assert_eq!( + hw.soc_ifc().cptra_boot_status().read(), + u32::from(FwProcessorManifestLoadComplete) + ); +} + +#[test] +fn test_header_verify_vendor_mldsa_pub_key_in_preamble_and_header() { + let (mut hw, mut image_bundle) = hw_and_mldsa_image_bundle(); + + // Change vendor pubkey index. + image_bundle.manifest.header.vendor_pqc_pub_key_idx = + image_bundle.manifest.preamble.vendor_pqc_pub_key_idx + 1; + update_header(&mut image_bundle); + + assert_eq!( + hw.upload_firmware(&image_bundle.to_bytes().unwrap()) + .unwrap_err(), + ModelError::MailboxCmdFailed( + CaliptraError::IMAGE_VERIFIER_ERR_VENDOR_MLDSA_SIGNATURE_INVALID.into() + ) + ); +} + +// TODO: Uncomment this test when functionality is implemented. +// #[test] +#[allow(dead_code)] +fn test_preamble_vendor_mldsa_pubkey_out_of_bounds() { + let (mut hw, mut image_bundle) = hw_and_mldsa_image_bundle(); + + image_bundle.manifest.preamble.vendor_pqc_pub_key_idx = VENDOR_MLDSA_MAX_KEY_COUNT; + + assert_eq!( + hw.upload_firmware(&image_bundle.to_bytes().unwrap()) + .unwrap_err(), + ModelError::MailboxCmdFailed( + CaliptraError::IMAGE_VERIFIER_ERR_VENDOR_LMS_PUB_KEY_INDEX_OUT_OF_BOUNDS.into() + ) + ); +} diff --git a/rom/dev/tests/rom_integration_tests/test_update_reset.rs b/rom/dev/tests/rom_integration_tests/test_update_reset.rs index e22e5c12f4..769cab5f3f 100644 --- a/rom/dev/tests/rom_integration_tests/test_update_reset.rs +++ b/rom/dev/tests/rom_integration_tests/test_update_reset.rs @@ -345,7 +345,7 @@ fn test_update_reset_vendor_ecc_pub_key_idx_dv_mismatch() { fn test_update_reset_vendor_lms_pub_key_idx_dv_mismatch() { let rom = caliptra_builder::build_firmware_rom(firmware::rom_from_env()).unwrap(); let vendor_config_cold_boot = ImageGeneratorVendorConfig { - lms_key_idx: 3, + pqc_key_idx: 3, ..VENDOR_CONFIG_KEY_0 }; let image_options = ImageOptions { @@ -361,7 +361,7 @@ fn test_update_reset_vendor_lms_pub_key_idx_dv_mismatch() { // Generate firmware with a different vendor LMS key index. let vendor_config_update_reset = ImageGeneratorVendorConfig { - lms_key_idx: 2, + pqc_key_idx: 2, ..VENDOR_CONFIG_KEY_0 }; let image_options = ImageOptions { @@ -396,7 +396,7 @@ fn test_update_reset_vendor_lms_pub_key_idx_dv_mismatch() { assert_eq!( hw.upload_firmware(&image_bundle2.to_bytes().unwrap()), Err(caliptra_hw_model::ModelError::MailboxCmdFailed( - CaliptraError::IMAGE_VERIFIER_ERR_UPDATE_RESET_VENDOR_LMS_PUB_KEY_IDX_MISMATCH.into() + CaliptraError::IMAGE_VERIFIER_ERR_UPDATE_RESET_VENDOR_PQC_PUB_KEY_IDX_MISMATCH.into() )) ); @@ -407,7 +407,7 @@ fn test_update_reset_vendor_lms_pub_key_idx_dv_mismatch() { assert_eq!( hw.soc_ifc().cptra_fw_error_non_fatal().read(), - u32::from(CaliptraError::IMAGE_VERIFIER_ERR_UPDATE_RESET_VENDOR_LMS_PUB_KEY_IDX_MISMATCH) + u32::from(CaliptraError::IMAGE_VERIFIER_ERR_UPDATE_RESET_VENDOR_PQC_PUB_KEY_IDX_MISMATCH) ); } diff --git a/rom/dev/tests/rom_integration_tests/test_warm_reset.rs b/rom/dev/tests/rom_integration_tests/test_warm_reset.rs index ecce2a6260..4bb3bd715b 100644 --- a/rom/dev/tests/rom_integration_tests/test_warm_reset.rs +++ b/rom/dev/tests/rom_integration_tests/test_warm_reset.rs @@ -31,7 +31,7 @@ fn test_warm_reset_success() { ) .unwrap(); - let (vendor_pk_desc_hash, owner_pk_desc_hash) = image_pk_desc_hash(&image.manifest); + let (vendor_pk_desc_hash, owner_pk_hash) = image_pk_desc_hash(&image.manifest); let mut hw = caliptra_hw_model::new( InitParams { @@ -42,7 +42,7 @@ fn test_warm_reset_success() { BootParams { fuses: Fuses { key_manifest_pk_hash: vendor_pk_desc_hash, - owner_pk_hash: owner_pk_desc_hash, + owner_pk_hash, fmc_key_manifest_svn: 0b1111111, runtime_svn: [0x7F, 0, 0, 0], // Equals 7 ..Default::default() @@ -61,7 +61,7 @@ fn test_warm_reset_success() { // Perform warm reset hw.warm_reset_flow(&Fuses { key_manifest_pk_hash: vendor_pk_desc_hash, - owner_pk_hash: owner_pk_desc_hash, + owner_pk_hash, fmc_key_manifest_svn: 0b1111111, runtime_svn: [0x7F, 0, 0, 0], // Equals 7 ..Default::default() diff --git a/rom/dev/tools/keys.toml b/rom/dev/tools/keys.toml index a2c7942644..b69dbe6274 100644 --- a/rom/dev/tools/keys.toml +++ b/rom/dev/tools/keys.toml @@ -41,6 +41,10 @@ lms_pub_keys = [ "vnd-lms-pub-key-2.pem", "vnd-lms-pub-key-3.pem", ] + +# [TODO][CAP2] Add MLDSA key files. +mldsa_pub_keys = [] + ecc_priv_keys = [ "vnd-priv-key-0.pem", "vnd-priv-key-1.pem", @@ -82,8 +86,13 @@ lms_priv_keys = [ "vnd-lms-priv-key-3.pem", ] +mldsa_priv_keys = [] + [owner] ecc_pub_key = "own-pub-key.pem" ecc_priv_key = "own-priv-key.pem" lms_pub_key = "own-lms-pub-key.pem" lms_priv_key = "own-lms-priv-key.pem" +mldsa_pub_key = "" +mldsa_priv_key = "" + diff --git a/rom/dev/tools/test-fmc/src/main.rs b/rom/dev/tools/test-fmc/src/main.rs index da6a6ca3cf..a478d030dc 100644 --- a/rom/dev/tools/test-fmc/src/main.rs +++ b/rom/dev/tools/test-fmc/src/main.rs @@ -322,8 +322,8 @@ fn read_datavault_coldresetentry4(mbox: &caliptra_registers::mbox::RegisterBlock send_to_mailbox(mbox, (EccVendorPubKeyIndex as u32).as_bytes(), false); send_to_mailbox(mbox, data_vault.ecc_vendor_pk_index().as_bytes(), false); - send_to_mailbox(mbox, (LmsVendorPubKeyIndex as u32).as_bytes(), false); - send_to_mailbox(mbox, data_vault.lms_vendor_pk_index().as_bytes(), false); + send_to_mailbox(mbox, (PqcVendorPubKeyIndex as u32).as_bytes(), false); + send_to_mailbox(mbox, data_vault.pqc_vendor_pk_index().as_bytes(), false); mbox.dlen() .write(|_| (core::mem::size_of::() * 10).try_into().unwrap()); diff --git a/runtime/src/authorize_and_stash.rs b/runtime/src/authorize_and_stash.rs index f3e48521c4..3105c5e063 100644 --- a/runtime/src/authorize_and_stash.rs +++ b/runtime/src/authorize_and_stash.rs @@ -31,7 +31,7 @@ use caliptra_drivers::{ PersistentData, RomPqcVerifyConfig, Sha256, Sha2_512_384, SocIfc, }; use caliptra_image_types::{ - ImageDigest, ImageEccPubKey, ImageEccSignature, ImageLmsPublicKey, ImageLmsSignature, + ImageDigest384, ImageEccPubKey, ImageEccSignature, ImageLmsPublicKey, ImageLmsSignature, ImagePreamble, SHA192_DIGEST_WORD_SIZE, SHA384_DIGEST_BYTE_SIZE, }; use crypto::{AlgLen, Crypto}; diff --git a/runtime/src/drivers.rs b/runtime/src/drivers.rs index 293fa74488..ad77325ab1 100644 --- a/runtime/src/drivers.rs +++ b/runtime/src/drivers.rs @@ -27,22 +27,29 @@ use arrayvec::ArrayVec; use caliptra_cfi_derive_git::{cfi_impl_fn, cfi_mod_fn}; use caliptra_cfi_lib_git::{cfi_assert, cfi_assert_eq, cfi_assert_eq_12_words, cfi_launder}; use caliptra_common::mailbox_api::AddSubjectAltNameReq; -use caliptra_drivers::KeyId; use caliptra_drivers::{ - cprint, cprintln, pcr_log::RT_FW_JOURNEY_PCR, Array4x12, CaliptraError, CaliptraResult, - DataVault, Ecc384, KeyVault, Lms, PersistentDataAccessor, Pic, ResetReason, Sha1, SocIfc, -}; -use caliptra_drivers::{ - hand_off::DataStore, Ecc384PubKey, Hmac, PcrBank, PcrId, Sha256, Sha256Alg, Sha2_512_384, - Sha2_512_384Acc, Trng, + cprint, cprintln, hand_off::DataStore, pcr_log::RT_FW_JOURNEY_PCR, Array4x12, CaliptraError, + CaliptraResult, DataVault, Ecc384, Ecc384PubKey, Hmac, KeyId, KeyVault, Lms, Mldsa87, PcrBank, + PcrId, PersistentDataAccessor, Pic, ResetReason, Sha1, Sha256, Sha256Alg, Sha2_512_384, + Sha2_512_384Acc, SocIfc, Trng, }; use caliptra_image_types::ImageManifest; -use caliptra_registers::el2_pic_ctrl::El2PicCtrl; -use caliptra_registers::mbox::enums::MboxStatusE; use caliptra_registers::{ - csrng::CsrngReg, dv::DvReg, ecc::EccReg, entropy_src::EntropySrcReg, hmac::HmacReg, kv::KvReg, - mbox::MboxCsr, pv::PvReg, sha256::Sha256Reg, sha512::Sha512Reg, sha512_acc::Sha512AccCsr, - soc_ifc::SocIfcReg, soc_ifc_trng::SocIfcTrngReg, + csrng::CsrngReg, + dv::DvReg, + ecc::EccReg, + el2_pic_ctrl::El2PicCtrl, + entropy_src::EntropySrcReg, + hmac::HmacReg, + kv::KvReg, + mbox::{enums::MboxStatusE, MboxCsr}, + mldsa::MldsaReg, + pv::PvReg, + sha256::Sha256Reg, + sha512::Sha512Reg, + sha512_acc::Sha512AccCsr, + soc_ifc::SocIfcReg, + soc_ifc_trng::SocIfcTrngReg, }; use caliptra_x509::{NotAfter, NotBefore}; use dpe::context::{Context, ContextState, ContextType}; @@ -90,6 +97,9 @@ pub struct Drivers { /// Ecc384 Engine pub ecc384: Ecc384, + /// Mldsa87 Engine + pub mldsa87: Mldsa87, + pub persistent_data: PersistentDataAccessor, pub lms: Lms, @@ -135,6 +145,7 @@ impl Drivers { sha2_512_384_acc: Sha2_512_384Acc::new(Sha512AccCsr::new()), hmac: Hmac::new(HmacReg::new()), ecc384: Ecc384::new(EccReg::new()), + mldsa87: Mldsa87::new(MldsaReg::new()), sha1: Sha1::default(), lms: Lms::default(), trng, diff --git a/runtime/src/fips.rs b/runtime/src/fips.rs index 5768c17e25..148e2609e7 100644 --- a/runtime/src/fips.rs +++ b/runtime/src/fips.rs @@ -116,6 +116,7 @@ pub mod fips_self_test_cmd { sha2_512_384: &mut env.sha2_512_384, soc_ifc: &mut env.soc_ifc, ecc384: &mut env.ecc384, + mldsa87: &mut env.mldsa87, data_vault: &mut env.data_vault, pcr_bank: &mut env.pcr_bank, image: env.mbox.raw_mailbox_contents(), diff --git a/runtime/src/set_auth_manifest.rs b/runtime/src/set_auth_manifest.rs index 9c2d84a582..eeca2f9de0 100644 --- a/runtime/src/set_auth_manifest.rs +++ b/runtime/src/set_auth_manifest.rs @@ -32,7 +32,7 @@ use caliptra_drivers::{ PersistentData, RomPqcVerifyConfig, Sha256, Sha2_512_384, SocIfc, }; use caliptra_image_types::{ - ImageDigest, ImageEccPubKey, ImageEccSignature, ImageLmsPublicKey, ImageLmsSignature, + ImageDigest384, ImageEccPubKey, ImageEccSignature, ImageLmsPublicKey, ImageLmsSignature, ImagePreamble, SHA192_DIGEST_WORD_SIZE, SHA384_DIGEST_BYTE_SIZE, }; use crypto::{AlgLen, Crypto}; @@ -52,7 +52,7 @@ impl SetAuthManifestCmd { manifest: &[u8], offset: u32, len: u32, - ) -> CaliptraResult { + ) -> CaliptraResult { let err = CaliptraError::IMAGE_VERIFIER_ERR_DIGEST_OUT_OF_BOUNDS; let data = manifest .get(offset as usize..) @@ -64,7 +64,7 @@ impl SetAuthManifestCmd { fn ecc384_verify( ecc384: &mut Ecc384, - digest: &ImageDigest, + digest: &ImageDigest384, pub_key: &ImageEccPubKey, sig: &ImageEccSignature, ) -> CaliptraResult> { @@ -85,7 +85,7 @@ impl SetAuthManifestCmd { fn lms_verify( sha256: &mut Sha256, - digest: &ImageDigest, + digest: &ImageDigest384, pub_key: &ImageLmsPublicKey, sig: &ImageLmsSignature, ) -> CaliptraResult> { @@ -134,7 +134,9 @@ impl SetAuthManifestCmd { } // Verify vendor LMS signature. - let vendor_fw_lms_key = &fw_preamble.vendor_lms_active_pub_key; + let vendor_fw_lms_key = + ImageLmsPublicKey::ref_from_prefix(fw_preamble.vendor_pqc_active_pub_key.0.as_bytes()) + .ok_or(CaliptraError::RUNTIME_AUTH_MANIFEST_LMS_VENDOR_PUB_KEY_INVALID)?; let candidate_key = Self::lms_verify( sha256, @@ -192,7 +194,9 @@ impl SetAuthManifestCmd { } // Verify owner LMS signature. - let owner_fw_lms_key = &fw_preamble.owner_pub_keys.lms_pub_key; + let owner_fw_lms_key = + ImageLmsPublicKey::ref_from_prefix(fw_preamble.owner_pub_keys.pqc_pub_key.0.as_bytes()) + .ok_or(CaliptraError::RUNTIME_AUTH_MANIFEST_LMS_OWNER_PUB_KEY_INVALID)?; let candidate_key = Self::lms_verify( sha256, @@ -213,7 +217,7 @@ impl SetAuthManifestCmd { fn verify_vendor_image_metadata_col( auth_manifest_preamble: &AuthManifestPreamble, - image_metadata_col_digest: &ImageDigest, + image_metadata_col_digest: &ImageDigest384, sha2: &mut Sha2_512_384, ecc384: &mut Ecc384, sha256: &mut Sha256, @@ -274,7 +278,7 @@ impl SetAuthManifestCmd { fn verify_owner_image_metadata_col( auth_manifest_preamble: &AuthManifestPreamble, - image_metadata_col_digest: &ImageDigest, + image_metadata_col_digest: &ImageDigest384, sha2: &mut Sha2_512_384, ecc384: &mut Ecc384, sha256: &mut Sha256, diff --git a/runtime/tests/runtime_integration_tests/test_pauser_privilege_levels.rs b/runtime/tests/runtime_integration_tests/test_pauser_privilege_levels.rs index b7293d6d9a..07c0772e83 100644 --- a/runtime/tests/runtime_integration_tests/test_pauser_privilege_levels.rs +++ b/runtime/tests/runtime_integration_tests/test_pauser_privilege_levels.rs @@ -15,7 +15,7 @@ use caliptra_hw_model::{BootParams, Fuses, HwModel, InitParams, SecurityState}; use caliptra_image_crypto::OsslCrypto as Crypto; use caliptra_image_elf::ElfExecutable; use caliptra_image_gen::{ImageGenerator, ImageGeneratorConfig}; -use caliptra_image_types::FwImageType; +use caliptra_image_types::{FwVerificationPqcKeyType, ImageDigestHolder}; use caliptra_runtime::{ RtBootStatus, PL0_DPE_ACTIVE_CONTEXT_THRESHOLD, PL1_DPE_ACTIVE_CONTEXT_THRESHOLD, }; @@ -541,14 +541,24 @@ fn test_pl0_unset_in_header() { let opts = ImageOptions::default(); let ecc_index = opts.vendor_config.ecc_key_idx; - let lms_index = opts.vendor_config.lms_key_idx; + let lms_index = opts.vendor_config.pqc_key_idx; let gen = ImageGenerator::new(Crypto::default()); - let header_digest_vendor = gen - .header_digest_vendor(&image_bundle.manifest.header) + let vendor_header_digest_384 = gen + .vendor_header_digest_384(&image_bundle.manifest.header) .unwrap(); - let header_digest_owner = gen - .header_digest_owner(&image_bundle.manifest.header) + let vendor_header_digest_holder = ImageDigestHolder { + digest_384: &vendor_header_digest_384, + digest_512: None, + }; + + let owner_header_digest_384 = gen + .owner_header_digest_384(&image_bundle.manifest.header) .unwrap(); + let owner_header_digest_holder = ImageDigestHolder { + digest_384: &owner_header_digest_384, + digest_512: None, + }; + let fmc_elf = build_firmware_elf(&FMC_WITH_UART).unwrap(); let app_elf = build_firmware_elf(&APP_WITH_UART).unwrap(); let preamble = gen @@ -570,12 +580,12 @@ fn test_pl0_unset_in_header() { .unwrap(), vendor_config: opts.vendor_config, owner_config: opts.owner_config, - fw_image_type: FwImageType::EccLms, + pqc_key_type: FwVerificationPqcKeyType::LMS, }, ecc_index, lms_index, - &header_digest_vendor, - &header_digest_owner, + &vendor_header_digest_holder, + &owner_header_digest_holder, ) .unwrap(); image_bundle.manifest.preamble = preamble; diff --git a/runtime/tests/runtime_integration_tests/test_warm_reset.rs b/runtime/tests/runtime_integration_tests/test_warm_reset.rs index 3652c2e643..5f99c5a813 100644 --- a/runtime/tests/runtime_integration_tests/test_warm_reset.rs +++ b/runtime/tests/runtime_integration_tests/test_warm_reset.rs @@ -28,7 +28,7 @@ fn test_rt_journey_pcr_validation() { ) .unwrap(); - let (vendor_pk_desc_hash, owner_pk_desc_hash) = image_pk_desc_hash(&image.manifest); + let (vendor_pk_desc_hash, owner_pk_hash) = image_pk_desc_hash(&image.manifest); let mut model = caliptra_hw_model::new( InitParams { @@ -39,7 +39,7 @@ fn test_rt_journey_pcr_validation() { BootParams { fuses: Fuses { key_manifest_pk_hash: vendor_pk_desc_hash, - owner_pk_hash: owner_pk_desc_hash, + owner_pk_hash, fmc_key_manifest_svn: 0b1111111, ..Default::default() }, @@ -60,7 +60,7 @@ fn test_rt_journey_pcr_validation() { // Perform warm reset model.warm_reset_flow(&Fuses { key_manifest_pk_hash: vendor_pk_desc_hash, - owner_pk_hash: owner_pk_desc_hash, + owner_pk_hash, fmc_key_manifest_svn: 0b1111111, ..Default::default() }); @@ -91,7 +91,7 @@ fn test_mbox_busy_during_warm_reset() { ) .unwrap(); - let (vendor_pk_desc_hash, owner_pk_desc_hash) = image_pk_desc_hash(&image.manifest); + let (vendor_pk_desc_hash, owner_pk_hash) = image_pk_desc_hash(&image.manifest); let mut model = caliptra_hw_model::new( InitParams { @@ -102,7 +102,7 @@ fn test_mbox_busy_during_warm_reset() { BootParams { fuses: Fuses { key_manifest_pk_hash: vendor_pk_desc_hash, - owner_pk_hash: owner_pk_desc_hash, + owner_pk_hash, fmc_key_manifest_svn: 0b1111111, ..Default::default() }, @@ -123,7 +123,7 @@ fn test_mbox_busy_during_warm_reset() { // Perform warm reset model.warm_reset_flow(&Fuses { key_manifest_pk_hash: vendor_pk_desc_hash, - owner_pk_hash: owner_pk_desc_hash, + owner_pk_hash, fmc_key_manifest_svn: 0b1111111, ..Default::default() }); diff --git a/sw-emulator/lib/periph/src/ml_dsa87.rs b/sw-emulator/lib/periph/src/ml_dsa87.rs index a6627d86a9..41133a0af2 100644 --- a/sw-emulator/lib/periph/src/ml_dsa87.rs +++ b/sw-emulator/lib/periph/src/ml_dsa87.rs @@ -20,6 +20,7 @@ use caliptra_emu_types::{RvData, RvSize}; use fips204::ml_dsa_87::{try_keygen_with_rng, PrivateKey, PublicKey, PK_LEN, SIG_LEN, SK_LEN}; use fips204::traits::{SerDes, Signer, Verifier}; use rand::rngs::StdRng; +use rand::Rng; use rand::SeedableRng; use tock_registers::interfaces::{ReadWriteable, Readable, Writeable}; use tock_registers::register_bitfields; @@ -355,7 +356,7 @@ impl Mldsa87 { self.verify_res .copy_from_slice(&self.signature[..ML_DSA87_VERIFICATION_SIZE / 4]); } else { - self.verify_res.fill(0); + self.verify_res = rand::thread_rng().gen::<[u32; 16]>(); } } @@ -713,7 +714,11 @@ mod tests { assert_eq!(result, &test_signature[..ML_DSA87_VERIFICATION_SIZE]); // Bad signature - let mut signature = [0; SIG_LEN + 1]; + let mut rng = rand::thread_rng(); + let mut signature = [0u8; SIG_LEN + 1]; + + rng.fill(&mut signature[..64]); + signature.to_big_endian(); for i in (0..signature.len()).step_by(4) { @@ -747,7 +752,7 @@ mod tests { } let result = bytes_from_words_be(&ml_dsa87.verify_res); - assert_eq!(&result, &[0; 64]); + assert_ne!(result, &test_signature[..ML_DSA87_VERIFICATION_SIZE]); } #[test] diff --git a/test/src/lib.rs b/test/src/lib.rs index 5d3186a374..ebcd55fa3b 100644 --- a/test/src/lib.rs +++ b/test/src/lib.rs @@ -37,15 +37,14 @@ pub fn bytes_to_be_words_48(buf: &[u8; 48]) -> [u32; 12] { result } -// Returns the vendor and owner public key descriptor hashes from the image. +// Returns the vendor public key descriptor and owner public key hashes from the image. pub fn image_pk_desc_hash(manifest: &ImageManifest) -> ([u32; 12], [u32; 12]) { let vendor_pk_desc_hash = bytes_to_be_words_48(&sha384(manifest.preamble.vendor_pub_key_info.as_bytes())); - let owner_pk_desc_hash = - bytes_to_be_words_48(&sha384(manifest.preamble.owner_pub_key_info.as_bytes())); + let owner_pk_hash = bytes_to_be_words_48(&sha384(manifest.preamble.owner_pub_keys.as_bytes())); - (vendor_pk_desc_hash, owner_pk_desc_hash) + (vendor_pk_desc_hash, owner_pk_hash) } // Run a test which boots ROM -> FMC -> test_bin. If test_bin_name is None, diff --git a/test/tests/caliptra_integration_tests/fake_collateral_boot_test.rs b/test/tests/caliptra_integration_tests/fake_collateral_boot_test.rs index e6a4f32ef2..9215367530 100755 --- a/test/tests/caliptra_integration_tests/fake_collateral_boot_test.rs +++ b/test/tests/caliptra_integration_tests/fake_collateral_boot_test.rs @@ -59,7 +59,7 @@ fn fake_boot_test() { ) .unwrap(); - let (vendor_pk_desc_hash, owner_pk_desc_hash) = image_pk_desc_hash(&image.manifest); + let (vendor_pk_desc_hash, owner_pk_hash) = image_pk_desc_hash(&image.manifest); let mut hw = caliptra_hw_model::new( InitParams { @@ -69,7 +69,7 @@ fn fake_boot_test() { BootParams { fuses: Fuses { key_manifest_pk_hash: vendor_pk_desc_hash, - owner_pk_hash: owner_pk_desc_hash, + owner_pk_hash, fmc_key_manifest_svn: 0b1111111, runtime_svn: [0x7F, 0, 0, 0], // Equals 7 ..Default::default() diff --git a/test/tests/caliptra_integration_tests/jtag_test.rs b/test/tests/caliptra_integration_tests/jtag_test.rs index 34739103fc..b64bdeb0d8 100644 --- a/test/tests/caliptra_integration_tests/jtag_test.rs +++ b/test/tests/caliptra_integration_tests/jtag_test.rs @@ -88,11 +88,11 @@ fn gdb_test() { ) .unwrap(); - let (vendor_pk_desc_hash, owner_pk_desc_hash) = image_pk_desc_hash(&image.manifest); + let (vendor_pk_desc_hash, owner_pk_hash) = image_pk_desc_hash(&image.manifest); let fuses = Fuses { key_manifest_pk_hash: vendor_pk_desc_hash, - owner_pk_hash: owner_pk_desc_hash, + owner_pk_hash, fmc_key_manifest_svn: 0b1111111, lms_verify: true, ..Default::default() diff --git a/test/tests/caliptra_integration_tests/smoke_test.rs b/test/tests/caliptra_integration_tests/smoke_test.rs index b8422efd5f..252c3192b0 100644 --- a/test/tests/caliptra_integration_tests/smoke_test.rs +++ b/test/tests/caliptra_integration_tests/smoke_test.rs @@ -154,13 +154,13 @@ fn smoke_test() { ) .unwrap(); let vendor_pk_desc_hash = sha384(image.manifest.preamble.vendor_pub_key_info.as_bytes()); - let owner_pk_desc_hash = sha384(image.manifest.preamble.owner_pub_key_info.as_bytes()); + let owner_pk_hash = sha384(image.manifest.preamble.owner_pub_keys.as_bytes()); let vendor_pk_desc_hash_words = bytes_to_be_words_48(&vendor_pk_desc_hash); - let owner_pk_desc_hash_words = bytes_to_be_words_48(&owner_pk_desc_hash); + let owner_pk_hash_words = bytes_to_be_words_48(&owner_pk_hash); let fuses = Fuses { key_manifest_pk_hash: vendor_pk_desc_hash_words, - owner_pk_hash: owner_pk_desc_hash_words, + owner_pk_hash: owner_pk_hash_words, fmc_key_manifest_svn: 0b1111111, runtime_svn: [0x7F, 0, 0, 0], // Equals 7 lms_verify: true, @@ -265,11 +265,11 @@ fn smoke_test() { hasher.update(&[security_state.debug_locked() as u8]); hasher.update(&[fuses.anti_rollback_disable as u8]); hasher.update(/*ecc_vendor_pk_index=*/ &[0u8]); // No keys are revoked - hasher.update(&[image.manifest.header.vendor_lms_pub_key_idx as u8]); - hasher.update(&[image.manifest.fw_image_type]); + hasher.update(&[image.manifest.header.vendor_pqc_pub_key_idx as u8]); + hasher.update(&[image.manifest.pqc_key_type]); hasher.update(&[true as u8]); hasher.update(vendor_pk_desc_hash.as_bytes()); - hasher.update(&owner_pk_desc_hash); + hasher.update(&owner_pk_hash); let device_info_hash = hasher.finish(); let dice_tcb_info = DiceTcbInfo::find_multiple_in_cert(fmc_alias_cert_der).unwrap(); @@ -313,14 +313,14 @@ fn smoke_test() { security_state, fuse_anti_rollback_disable: false, vendor_pub_key_hash: vendor_pk_desc_hash_words, - owner_pub_key_hash: owner_pk_desc_hash_words, + owner_pub_key_hash: owner_pk_hash_words, owner_pub_key_hash_from_fuses: true, ecc_vendor_pub_key_index: image.manifest.preamble.vendor_ecc_pub_key_idx, fmc_digest: image.manifest.fmc.digest, fmc_svn: image.manifest.fmc.svn, // This is from the SVN in the fuses (7 bits set) fmc_fuse_svn: 7, - lms_vendor_pub_key_index: image.manifest.header.vendor_lms_pub_key_idx, + lms_vendor_pub_key_index: image.manifest.header.vendor_pqc_pub_key_idx, rom_verify_config: 1, // RomVerifyConfig::EcdsaAndLms }), &expected_ldevid_key, diff --git a/test/tests/caliptra_integration_tests/warm_reset.rs b/test/tests/caliptra_integration_tests/warm_reset.rs index 49699f4b15..a5135005d8 100644 --- a/test/tests/caliptra_integration_tests/warm_reset.rs +++ b/test/tests/caliptra_integration_tests/warm_reset.rs @@ -28,7 +28,7 @@ fn warm_reset_basic() { ) .unwrap(); - let (vendor_pk_desc_hash, owner_pk_desc_hash) = image_pk_desc_hash(&image.manifest); + let (vendor_pk_desc_hash, owner_pk_hash) = image_pk_desc_hash(&image.manifest); let mut hw = caliptra_hw_model::new( InitParams { @@ -39,7 +39,7 @@ fn warm_reset_basic() { BootParams { fuses: Fuses { key_manifest_pk_hash: vendor_pk_desc_hash, - owner_pk_hash: owner_pk_desc_hash, + owner_pk_hash, fmc_key_manifest_svn: 0b1111111, runtime_svn: [0x7F, 0, 0, 0], // Equals 7 ..Default::default() @@ -58,7 +58,7 @@ fn warm_reset_basic() { // Perform warm reset hw.warm_reset_flow(&Fuses { key_manifest_pk_hash: vendor_pk_desc_hash, - owner_pk_hash: owner_pk_desc_hash, + owner_pk_hash, fmc_key_manifest_svn: 0b1111111, runtime_svn: [0x7F, 0, 0, 0], // Equals 7 ..Default::default() @@ -88,7 +88,7 @@ fn warm_reset_during_fw_load() { ) .unwrap(); - let (vendor_pk_desc_hash, owner_pk_desc_hash) = image_pk_desc_hash(&image.manifest); + let (vendor_pk_desc_hash, owner_pk_hash) = image_pk_desc_hash(&image.manifest); let mut hw = caliptra_hw_model::new( InitParams { @@ -99,7 +99,7 @@ fn warm_reset_during_fw_load() { BootParams { fuses: Fuses { key_manifest_pk_hash: vendor_pk_desc_hash, - owner_pk_hash: owner_pk_desc_hash, + owner_pk_hash, fmc_key_manifest_svn: 0b1111111, runtime_svn: [0x7F, 0, 0, 0], // Equals 7 ..Default::default() @@ -129,7 +129,7 @@ fn warm_reset_during_fw_load() { // Perform warm reset while ROM is executing the firmware load hw.warm_reset_flow(&Fuses { key_manifest_pk_hash: vendor_pk_desc_hash, - owner_pk_hash: owner_pk_desc_hash, + owner_pk_hash, fmc_key_manifest_svn: 0b1111111, runtime_svn: [0x7F, 0, 0, 0], // Equals 7 ..Default::default() diff --git a/test/tests/fips_test_suite/fw_load.rs b/test/tests/fips_test_suite/fw_load.rs index efd441995d..2efafb0061 100755 --- a/test/tests/fips_test_suite/fw_load.rs +++ b/test/tests/fips_test_suite/fw_load.rs @@ -15,9 +15,9 @@ use caliptra_hw_model::{ use caliptra_image_crypto::OsslCrypto as Crypto; use caliptra_image_fake_keys::{VENDOR_CONFIG_KEY_0, VENDOR_CONFIG_KEY_1}; use caliptra_image_gen::{ImageGenerator, ImageGeneratorConfig, ImageGeneratorVendorConfig}; -use caliptra_image_types::SHA384_DIGEST_WORD_SIZE; use caliptra_image_types::{ - FwImageType, ImageBundle, VENDOR_ECC_MAX_KEY_COUNT, VENDOR_LMS_MAX_KEY_COUNT, + FwVerificationPqcKeyType, ImageBundle, ImageDigestHolder, ImageLmsPublicKey, + SHA384_DIGEST_WORD_SIZE, VENDOR_ECC_MAX_KEY_COUNT, VENDOR_LMS_MAX_KEY_COUNT, }; use caliptra_test::image_pk_desc_hash; @@ -48,7 +48,7 @@ fn update_manifest(image_bundle: &mut ImageBundle, hdr_digest: HdrDigest, toc_di runtime: caliptra_image_elf::ElfExecutable::default(), vendor_config: opts.vendor_config, owner_config: opts.owner_config, - fw_image_type: FwImageType::EccLms, + pqc_key_type: FwVerificationPqcKeyType::LMS, }; let gen = ImageGenerator::new(Crypto::default()); @@ -61,21 +61,30 @@ fn update_manifest(image_bundle: &mut ImageBundle, hdr_digest: HdrDigest, toc_di } if hdr_digest == HdrDigest::Update { - let header_digest_vendor = gen - .header_digest_vendor(&image_bundle.manifest.header) + let vendor_header_digest_384 = gen + .vendor_header_digest_384(&image_bundle.manifest.header) .unwrap(); - let header_digest_owner = gen - .header_digest_owner(&image_bundle.manifest.header) + let vendor_header_digest_holder = ImageDigestHolder { + digest_384: &vendor_header_digest_384, + digest_512: None, + }; + + let owner_header_digest_384 = gen + .owner_header_digest_384(&image_bundle.manifest.header) .unwrap(); + let owner_header_digest_holder = ImageDigestHolder { + digest_384: &owner_header_digest_384, + digest_512: None, + }; // Update preamble image_bundle.manifest.preamble = gen .gen_preamble( &config, image_bundle.manifest.preamble.vendor_ecc_pub_key_idx, - image_bundle.manifest.preamble.vendor_lms_pub_key_idx, - &header_digest_vendor, - &header_digest_owner, + image_bundle.manifest.preamble.vendor_pqc_pub_key_idx, + &vendor_header_digest_holder, + &owner_header_digest_holder, ) .unwrap(); } @@ -628,7 +637,7 @@ fn fw_load_error_owner_ecc_signature_invalid_arg() { } #[test] -fn fw_load_error_vendor_pub_key_digest_invalid_arg() { +fn fw_load_error_vendor_pub_key_invalid_arg() { // Generate image let mut fw_image = build_fw_image(ImageOptions::default()); // Set ecc_pub_key.x to zero. @@ -642,7 +651,7 @@ fn fw_load_error_vendor_pub_key_digest_invalid_arg() { fw_load_error_flow( Some(fw_image), None, - CaliptraError::IMAGE_VERIFIER_ERR_VENDOR_PUB_KEY_DIGEST_INVALID_ARG.into(), + CaliptraError::IMAGE_VERIFIER_ERR_VENDOR_ECC_PUB_KEY_INVALID_ARG.into(), ); } @@ -665,13 +674,13 @@ fn fw_load_error_update_reset_owner_digest_failure() { // Generate image let mut update_image = build_fw_image(ImageOptions::default()); - // Set ecc pub key hash to some corrupted, non-zero value + // Set ecc_pub_key.y to some corrupted, non-zero value update_image .manifest .preamble - .owner_pub_key_info - .ecc_key_descriptor - .key_hash[0] + .owner_pub_keys + .ecc_pub_key + .y .fill(0x1234abcd); update_fw_error_flow( @@ -931,8 +940,8 @@ fn fw_load_error_vendor_lms_pub_key_index_mismatch() { // Generate image let mut fw_image = build_fw_image(ImageOptions::default()); // Change vendor pubkey index. - fw_image.manifest.header.vendor_lms_pub_key_idx = - fw_image.manifest.preamble.vendor_lms_pub_key_idx + 1; + fw_image.manifest.header.vendor_pqc_pub_key_idx = + fw_image.manifest.preamble.vendor_pqc_pub_key_idx + 1; update_manifest(&mut fw_image, HdrDigest::Update, TocDigest::Update); // Turn LMS verify on @@ -944,7 +953,7 @@ fn fw_load_error_vendor_lms_pub_key_index_mismatch() { fw_load_error_flow( Some(fw_image), Some(fuses), - CaliptraError::IMAGE_VERIFIER_ERR_VENDOR_LMS_PUB_KEY_INDEX_MISMATCH.into(), + CaliptraError::IMAGE_VERIFIER_ERR_VENDOR_PQC_PUB_KEY_INDEX_MISMATCH.into(), ); } @@ -970,7 +979,7 @@ fn fw_load_error_vendor_lms_pub_key_index_out_of_bounds() { // Generate image let mut fw_image = build_fw_image(ImageOptions::default()); // Set LMS pub key index to MAX + 1 - fw_image.manifest.preamble.vendor_lms_pub_key_idx = VENDOR_LMS_MAX_KEY_COUNT; + fw_image.manifest.preamble.vendor_pqc_pub_key_idx = VENDOR_LMS_MAX_KEY_COUNT; // Turn LMS verify on let fuses = caliptra_hw_model::Fuses { @@ -989,8 +998,20 @@ fn fw_load_error_vendor_lms_pub_key_index_out_of_bounds() { fn fw_load_error_vendor_lms_signature_invalid() { // Generate image let mut fw_image = build_fw_image(ImageOptions::default()); + + // Get a mutable reference to the LMS public key. + let lms_pub_key = ImageLmsPublicKey::mut_ref_from_prefix( + fw_image + .manifest + .preamble + .vendor_pqc_active_pub_key + .0 + .as_bytes_mut(), + ) + .unwrap(); + // Modify the vendor public key. - fw_image.manifest.preamble.vendor_lms_active_pub_key.digest = [Default::default(); 6]; + lms_pub_key.digest = [Default::default(); 6]; // Turn LMS verify on let fuses = caliptra_hw_model::Fuses { @@ -1041,8 +1062,21 @@ fn fw_load_error_owner_lms_verify_failure() { fn fw_load_error_owner_lms_signature_invalid() { // Generate image let mut fw_image = build_fw_image(ImageOptions::default()); + + // Get a mutable reference to the LMS public key. + let lms_pub_key = ImageLmsPublicKey::mut_ref_from_prefix( + fw_image + .manifest + .preamble + .owner_pub_keys + .pqc_pub_key + .0 + .as_bytes_mut(), + ) + .unwrap(); + // Modify the owner public key - fw_image.manifest.preamble.owner_pub_keys.lms_pub_key.digest = [Default::default(); 6]; + lms_pub_key.digest = [Default::default(); 6]; // Turn LMS verify on let fuses = caliptra_hw_model::Fuses { @@ -1060,7 +1094,7 @@ fn fw_load_error_owner_lms_signature_invalid() { #[test] fn fw_load_error_vendor_lms_pub_key_revoked() { let vendor_config = ImageGeneratorVendorConfig { - lms_key_idx: 5, + pqc_key_idx: 5, ..VENDOR_CONFIG_KEY_0 }; let image_options = ImageOptions { @@ -1071,7 +1105,7 @@ fn fw_load_error_vendor_lms_pub_key_revoked() { // Set fuses let fuses = caliptra_hw_model::Fuses { lms_verify: true, - fuse_lms_revocation: 1u32 << image_options.vendor_config.lms_key_idx, + fuse_lms_revocation: 1u32 << image_options.vendor_config.pqc_key_idx, ..Default::default() }; @@ -1116,9 +1150,9 @@ fn fw_load_error_runtime_size_zero() { } #[test] -fn fw_load_error_update_reset_vendor_lms_pub_key_idx_mismatch() { +fn fw_load_error_update_reset_vendor_pqc_pub_key_idx_mismatch() { let vendor_config_update_reset = ImageGeneratorVendorConfig { - lms_key_idx: 2, + pqc_key_idx: 2, ..VENDOR_CONFIG_KEY_0 }; let image_options_update_reset = ImageOptions { @@ -1138,7 +1172,7 @@ fn fw_load_error_update_reset_vendor_lms_pub_key_idx_mismatch() { None, Some(fuses), Some(update_image), - CaliptraError::IMAGE_VERIFIER_ERR_UPDATE_RESET_VENDOR_LMS_PUB_KEY_IDX_MISMATCH.into(), + CaliptraError::IMAGE_VERIFIER_ERR_UPDATE_RESET_VENDOR_PQC_PUB_KEY_IDX_MISMATCH.into(), ); } @@ -1195,12 +1229,12 @@ fn fw_load_bad_pub_key_flow(fw_image: ImageBundle, exp_error_code: u32) { // Generate pub key hashes and set fuses // Use a fresh image (will NOT be loaded) let pk_hash_src_image = build_fw_image(ImageOptions::default()); - let (vendor_pk_desc_hash, owner_pk_desc_hash) = image_pk_desc_hash(&pk_hash_src_image.manifest); + let (vendor_pk_desc_hash, owner_pk_hash) = image_pk_desc_hash(&pk_hash_src_image.manifest); let fuses = Fuses { life_cycle: DeviceLifecycle::Production, key_manifest_pk_hash: vendor_pk_desc_hash, - owner_pk_hash: owner_pk_desc_hash, + owner_pk_hash, lms_verify: true, ..Default::default() }; @@ -1249,13 +1283,8 @@ fn fw_load_bad_owner_ecc_pub_key() { // Generate image let mut fw_image = build_fw_image(ImageOptions::default()); - // Modify the pub key hash - fw_image - .manifest - .preamble - .owner_pub_key_info - .ecc_key_descriptor - .key_hash[0][0] ^= 0x1; + // Modify the pub key + fw_image.manifest.preamble.owner_pub_keys.ecc_pub_key.x[0] ^= 0x1; fw_load_bad_pub_key_flow( fw_image, @@ -1287,13 +1316,18 @@ fn fw_load_bad_owner_lms_pub_key() { // Generate image let mut fw_image = build_fw_image(ImageOptions::default()); - // Modify the pub key hash - fw_image - .manifest - .preamble - .owner_pub_key_info - .pqc_key_descriptor - .key_hash[0][0] ^= 0x1; + // Modify the pub key + let lms_pub_key = ImageLmsPublicKey::mut_ref_from_prefix( + fw_image + .manifest + .preamble + .owner_pub_keys + .pqc_pub_key + .0 + .as_bytes_mut(), + ) + .unwrap(); + lms_pub_key.digest[0] = 0xDEADBEEF.into(); fw_load_bad_pub_key_flow( fw_image, From 0001d500a44ce8c84941717ed49c9da15422ca17 Mon Sep 17 00:00:00 2001 From: Arthur Heymans Date: Sat, 14 Dec 2024 03:31:12 +0100 Subject: [PATCH 44/51] Upate RTL (#1847) The adams-bridge is now a submodule of the rtl. Adapt software and emulator to new RTL - Longer UDS -> 48 bytes to 64 - Longer keys in KV but less keys - MLDSA bit in KV - ready_for_fw -> ready_for_mb_processing - SOC_IFC renaming - AXI_ID -> AXI_USER --- .gitmodules | 3 - api/src/soc_mgr.rs | 33 +- api/types/src/lib.rs | 10 +- drivers/src/fuse_bank.rs | 17 +- drivers/src/key_vault.rs | 34 +- drivers/src/kv_access.rs | 2 +- drivers/src/mailbox.rs | 2 +- drivers/src/soc_ifc.rs | 16 +- drivers/test-fw/src/bin/keyvault_tests.rs | 10 +- drivers/test-fw/src/bin/mldsa87_tests.rs | 10 +- .../test-fw/src/bin/status_reporter_tests.rs | 8 +- .../tests/drivers_integration_tests/main.rs | 12 +- .../c-binding/examples/api/caliptra_api.c | 5 +- hw-model/src/lib.rs | 52 +- hw-model/src/model_emulated.rs | 2 +- hw-model/src/model_fpga_realtime.rs | 4 +- hw-model/src/model_verilated.rs | 6 +- hw-model/test-fw/mailbox_responder.rs | 2 +- hw-model/test-fw/mailbox_sender.rs | 4 +- hw-model/types/src/lib.rs | 5 +- hw/latest/adams-bridge | 1 - hw/latest/registers/src/axi_dma.rs | 19 +- hw/latest/registers/src/csrng.rs | 2 +- hw/latest/registers/src/doe.rs | 2 +- hw/latest/registers/src/dv.rs | 2 +- hw/latest/registers/src/ecc.rs | 2 +- hw/latest/registers/src/el2_pic_ctrl.rs | 2 +- hw/latest/registers/src/entropy_src.rs | 2 +- hw/latest/registers/src/hmac.rs | 9 +- hw/latest/registers/src/i3ccsr.rs | 2 +- hw/latest/registers/src/kv.rs | 8 +- hw/latest/registers/src/lib.rs | 10 +- hw/latest/registers/src/mbox.rs | 77 +- hw/latest/registers/src/mbox_sram.rs | 2 +- hw/latest/registers/src/mldsa.rs | 2 +- hw/latest/registers/src/pv.rs | 2 +- hw/latest/registers/src/sha256.rs | 2 +- hw/latest/registers/src/sha512.rs | 2 +- hw/latest/registers/src/sha512_acc.rs | 8 +- hw/latest/registers/src/soc_ifc.rs | 1064 +++++++++++++---- hw/latest/registers/src/soc_ifc_trng.rs | 2 +- hw/latest/rtl | 2 +- libcaliptra/inc/caliptra_types.h | 1 - libcaliptra/src/caliptra_api.c | 8 +- libcaliptra/src/caliptra_fuses.h | 16 +- registers/bin/generator/src/main.rs | 6 +- registers/update.sh | 2 +- rom/dev/src/crypto.rs | 3 +- rom/dev/src/flow/cold_reset/idev_id.rs | 6 +- rom/dev/src/flow/fake.rs | 2 +- .../test_dice_derivations.rs | 7 +- .../rom_integration_tests/test_fake_rom.rs | 28 +- .../test_fmcalias_derivation.rs | 4 - .../test_idevid_derivation.rs | 13 +- .../test_image_validation.rs | 28 +- .../test_mailbox_errors.rs | 2 +- .../test_update_reset.rs | 1 - .../test_wdt_activation_and_stoppage.rs | 7 +- .../tests_get_idev_csr.rs | 14 +- runtime/src/mailbox.rs | 2 +- .../tests/runtime_integration_tests/common.rs | 12 +- .../runtime_integration_tests/test_mailbox.rs | 2 +- .../test_set_auth_manifest.rs | 6 +- sw-emulator/app/src/main.rs | 2 +- sw-emulator/lib/periph/src/doe.rs | 4 +- sw-emulator/lib/periph/src/hash_sha512.rs | 93 +- sw-emulator/lib/periph/src/hmac.rs | 6 +- sw-emulator/lib/periph/src/key_vault.rs | 6 +- sw-emulator/lib/periph/src/mailbox.rs | 11 +- sw-emulator/lib/periph/src/ml_dsa87.rs | 5 +- sw-emulator/lib/periph/src/soc_reg.rs | 138 ++- test/src/derive.rs | 38 +- test/src/lib.rs | 7 +- .../caliptra_integration_tests/jtag_test.rs | 1 - .../caliptra_integration_tests/smoke_test.rs | 13 +- .../fmc_alias_cert_redacted.der | Bin 874 -> 874 bytes .../fmc_alias_cert_redacted.txt | 4 +- .../smoke_testdata/idevid_csr.der | Bin 443 -> 445 bytes .../smoke_testdata/idevid_csr.txt | 28 +- .../smoke_testdata/ldevid_cert.der | Bin 673 -> 674 bytes .../smoke_testdata/ldevid_cert.txt | 36 +- .../test_code_coverage.rs | 7 +- test/tests/fips_test_suite/common.rs | 7 +- test/tests/fips_test_suite/fw_load.rs | 21 +- test/tests/fips_test_suite/self_tests.rs | 14 +- 85 files changed, 1377 insertions(+), 695 deletions(-) delete mode 160000 hw/latest/adams-bridge diff --git a/.gitmodules b/.gitmodules index 55c387cb7b..3f0bd70983 100644 --- a/.gitmodules +++ b/.gitmodules @@ -12,6 +12,3 @@ [submodule "hw/latest/i3c-core-rtl"] path = hw/latest/i3c-core-rtl url = https://github.com/chipsalliance/i3c-core.git -[submodule "hw/latest/adams-bridge"] - path = hw/latest/adams-bridge - url = https://github.com/chipsalliance/adams-bridge.git diff --git a/api/src/soc_mgr.rs b/api/src/soc_mgr.rs index 2693aab6ac..29cf550bba 100644 --- a/api/src/soc_mgr.rs +++ b/api/src/soc_mgr.rs @@ -33,13 +33,13 @@ pub const NUM_PAUSERS: usize = 5; /// impl SocManager for RealSocManager { /// /// Address of the mailbox, remapped for the SoC. /// const SOC_MBOX_ADDR: u32 = caliptra_address_remap(CPTRA_SOC_MBOX_ADDR); -/// +/// /// /// Address of the SoC interface, remapped for the SoC. /// const SOC_IFC_ADDR: u32 = caliptra_address_remap(CPTRA_SOC_IFC_ADDR); -/// +/// /// /// Address of the SoC TRNG interface, remapped for the SoC. /// const SOC_IFC_TRNG_ADDR: u32 = caliptra_address_remap(CPTRA_SOC_IFC_TRNG_ADDR); -/// +/// /// /// Address of the SHA-512 accelerator, remapped for the SoC. /// const SOC_SHA512_ACC_ADDR: u32 = caliptra_address_remap(CPTRA_SOC_SHA512_ACC_ADDR); /// @@ -86,7 +86,7 @@ pub trait SocManager { for (idx, apb_pauser) in apb_pausers.iter().enumerate() { if self .soc_ifc() - .cptra_mbox_axi_id_lock() + .cptra_mbox_axi_user_lock() .at(idx) .read() .lock() @@ -95,11 +95,11 @@ pub trait SocManager { } self.soc_ifc() - .cptra_mbox_valid_axi_id() + .cptra_mbox_valid_axi_user() .at(idx) .write(|_| *apb_pauser); self.soc_ifc() - .cptra_mbox_axi_id_lock() + .cptra_mbox_axi_user_lock() .at(idx) .write(|w| w.lock(true)); } @@ -126,11 +126,18 @@ pub trait SocManager { self.soc_ifc() .fuse_key_manifest_pk_hash() .write(&fuses.key_manifest_pk_hash); + self.soc_ifc().fuse_key_manifest_pk_hash_mask().write(&[ + fuses.key_manifest_pk_hash_mask.into(), + 0, + 0, + 0, + 0, + 0, + 0, + 0, + ]); self.soc_ifc() - .fuse_key_manifest_pk_hash_mask() - .write(|w| w.mask(fuses.key_manifest_pk_hash_mask.into())); - self.soc_ifc() - .fuse_owner_pk_hash() + .cptra_owner_pk_hash() .write(&fuses.owner_pk_hash); self.soc_ifc() .fuse_fmc_key_manifest_svn() @@ -145,12 +152,6 @@ pub trait SocManager { self.soc_ifc() .fuse_idevid_manuf_hsm_id() .write(&fuses.idevid_manuf_hsm_id); - self.soc_ifc() - .fuse_life_cycle() - .write(|w| w.life_cycle(fuses.life_cycle.into())); - self.soc_ifc() - .fuse_lms_verify() - .write(|w| w.lms_verify(fuses.lms_verify)); self.soc_ifc() .fuse_lms_revocation() .write(|_| fuses.fuse_lms_revocation); diff --git a/api/types/src/lib.rs b/api/types/src/lib.rs index 37f4f05d71..7d6fb712df 100644 --- a/api/types/src/lib.rs +++ b/api/types/src/lib.rs @@ -6,9 +6,9 @@ // * The constant should be easily recognizable in waveforms and debug logs // * Every word must be different to ensure that a "stuck word" bug is noticed. // * Each byte in a word must be unique to ensure an endianness bug is noticed. -pub const DEFAULT_UDS_SEED: [u32; 12] = [ +pub const DEFAULT_UDS_SEED: [u32; 16] = [ 0x00010203, 0x04050607, 0x08090a0b, 0x0c0d0e0f, 0x10111213, 0x14151617, 0x18191a1b, 0x1c1d1e1f, - 0x20212223, 0x24252627, 0x28292a2b, 0x2c2d2e2f, + 0x20212223, 0x24252627, 0x28292a2b, 0x2c2d2e2f, 0x30313233, 0x34353637, 0x38393a3b, 0x3c3d3e3f, ]; pub const DEFAULT_FIELD_ENTROPY: [u32; 8] = [ @@ -154,7 +154,7 @@ impl TryFrom for U4 { #[derive(Clone, Debug)] pub struct Fuses { - pub uds_seed: [u32; 12], + pub uds_seed: [u32; 16], pub field_entropy: [u32; 8], pub key_manifest_pk_hash: [u32; 12], pub key_manifest_pk_hash_mask: U4, @@ -165,8 +165,8 @@ pub struct Fuses { pub idevid_cert_attr: [u32; 24], pub idevid_manuf_hsm_id: [u32; 4], pub life_cycle: DeviceLifecycle, - pub lms_verify: bool, pub fuse_lms_revocation: u32, + pub fuse_mldsa_revocation: u32, pub soc_stepping_id: u16, } impl Default for Fuses { @@ -183,8 +183,8 @@ impl Default for Fuses { idevid_cert_attr: Default::default(), idevid_manuf_hsm_id: Default::default(), life_cycle: Default::default(), - lms_verify: Default::default(), fuse_lms_revocation: Default::default(), + fuse_mldsa_revocation: Default::default(), soc_stepping_id: Default::default(), } } diff --git a/drivers/src/fuse_bank.rs b/drivers/src/fuse_bank.rs index f12455319d..44f7ae8642 100644 --- a/drivers/src/fuse_bank.rs +++ b/drivers/src/fuse_bank.rs @@ -215,7 +215,7 @@ impl FuseBank<'_> { pub fn vendor_ecc_pub_key_revocation(&self) -> VendorPubKeyRevocation { let soc_ifc_regs = self.soc_ifc.regs(); VendorPubKeyRevocation::from_bits_truncate( - soc_ifc_regs.fuse_key_manifest_pk_hash_mask().read().mask(), + soc_ifc_regs.fuse_key_manifest_pk_hash_mask().read()[0], ) } @@ -232,6 +232,19 @@ impl FuseBank<'_> { soc_ifc_regs.fuse_lms_revocation().read() } + /// Get the mldsa vendor public key revocation mask. + /// + /// # Arguments + /// * None + /// + /// # Returns + /// mldsa vendor public key revocation mask + /// + pub fn vendor_mldsa_pub_key_revocation(&self) -> u32 { + let soc_ifc_regs = self.soc_ifc.regs(); + soc_ifc_regs.fuse_mldsa_revocation().read().into() + } + /// Get the owner public key hash. /// /// # Arguments @@ -242,7 +255,7 @@ impl FuseBank<'_> { /// pub fn owner_pub_key_hash(&self) -> Array4x12 { let soc_ifc_regs = self.soc_ifc.regs(); - Array4x12::read_from_reg(soc_ifc_regs.fuse_owner_pk_hash()) + Array4x12::read_from_reg(soc_ifc_regs.cptra_owner_pk_hash()) } /// Get the rollback disability setting. diff --git a/drivers/src/key_vault.rs b/drivers/src/key_vault.rs index b3b9b2d883..72b7db7635 100644 --- a/drivers/src/key_vault.rs +++ b/drivers/src/key_vault.rs @@ -44,14 +44,6 @@ pub enum KeyId { KeyId21 = 21, KeyId22 = 22, KeyId23 = 23, - KeyId24 = 24, - KeyId25 = 25, - KeyId26 = 26, - KeyId27 = 27, - KeyId28 = 28, - KeyId29 = 29, - KeyId30 = 30, - KeyId31 = 31, } impl TryFrom for KeyId { @@ -82,14 +74,6 @@ impl TryFrom for KeyId { 21 => Ok(Self::KeyId21), 22 => Ok(Self::KeyId22), 23 => Ok(Self::KeyId23), - 24 => Ok(Self::KeyId24), - 25 => Ok(Self::KeyId25), - 26 => Ok(Self::KeyId26), - 27 => Ok(Self::KeyId27), - 28 => Ok(Self::KeyId28), - 29 => Ok(Self::KeyId29), - 30 => Ok(Self::KeyId30), - 31 => Ok(Self::KeyId31), _ => Err(()), } } @@ -127,8 +111,8 @@ bitfield! { /// Flag indicating if the key can be used as HMAC data pub hmac_data, set_hmac_data: 1; - /// Flag indicating if the key can be used as SHA data - pub sha_data, set_sha_data: 2; + /// Flag indicating if the key can be used as MLDSA seed + pub mldsa_seed, set_mldsa_seed: 2; /// Flag indicating if the key can be used aas ECC Private Key pub ecc_private_key, set_ecc_private_key: 3; @@ -150,8 +134,8 @@ impl KeyUsage { self.set_hmac_data(true); *self } - pub fn set_sha_data_en(&mut self) -> KeyUsage { - self.set_sha_data(true); + pub fn set_mldsa_seed_en(&mut self) -> KeyUsage { + self.set_mldsa_seed(true); *self } pub fn set_ecc_private_key_en(&mut self) -> KeyUsage { @@ -181,7 +165,7 @@ impl KeyVault { /// /// Note: The keys that have "use" or "write" lock set will not be erased pub fn erase_all_keys(&mut self) { - const KEY_IDS: [KeyId; 32] = [ + const KEY_IDS: [KeyId; 24] = [ KeyId::KeyId0, KeyId::KeyId1, KeyId::KeyId2, @@ -206,14 +190,6 @@ impl KeyVault { KeyId::KeyId21, KeyId::KeyId22, KeyId::KeyId23, - KeyId::KeyId24, - KeyId::KeyId25, - KeyId::KeyId26, - KeyId::KeyId27, - KeyId::KeyId28, - KeyId::KeyId29, - KeyId::KeyId30, - KeyId::KeyId31, ]; for id in KEY_IDS { diff --git a/drivers/src/kv_access.rs b/drivers/src/kv_access.rs index 66ae4a3ca8..bfd649353a 100644 --- a/drivers/src/kv_access.rs +++ b/drivers/src/kv_access.rs @@ -138,7 +138,7 @@ impl KvAccess { .write_entry(key.id.into()) .hmac_key_dest_valid(key.usage.hmac_key()) .hmac_block_dest_valid(key.usage.hmac_data()) - .sha_block_dest_valid(key.usage.sha_data()) + .mldsa_seed_dest_valid(key.usage.mldsa_seed()) .ecc_pkey_dest_valid(key.usage.ecc_private_key()) .ecc_seed_dest_valid(key.usage.ecc_key_gen_seed()) }); diff --git a/drivers/src/mailbox.rs b/drivers/src/mailbox.rs index 53a6df2e54..d1a4224cf2 100644 --- a/drivers/src/mailbox.rs +++ b/drivers/src/mailbox.rs @@ -270,7 +270,7 @@ impl<'a> MailboxRecvPeek<'a> { /// Returns the value stored in the user register pub fn id(&self) -> u32 { let mbox = self.mbox.regs(); - mbox.id().read() + mbox.user().read() } /// Returns the value stored in the data length register. This is the total diff --git a/drivers/src/soc_ifc.rs b/drivers/src/soc_ifc.rs index 872a1722a4..a6a022b402 100644 --- a/drivers/src/soc_ifc.rs +++ b/drivers/src/soc_ifc.rs @@ -77,12 +77,12 @@ impl SocIfc { pub fn mbox_valid_pauser(&self) -> [u32; 5] { let soc_ifc_regs = self.soc_ifc.regs(); - soc_ifc_regs.cptra_mbox_valid_axi_id().read() + soc_ifc_regs.cptra_mbox_valid_axi_user().read() } pub fn mbox_pauser_lock(&self) -> [bool; 5] { let soc_ifc_regs = self.soc_ifc.regs(); - let pauser_lock = soc_ifc_regs.cptra_mbox_axi_id_lock(); + let pauser_lock = soc_ifc_regs.cptra_mbox_axi_user_lock(); [ pauser_lock.at(0).read().lock(), pauser_lock.at(1).read().lock(), @@ -119,14 +119,16 @@ impl SocIfc { .write(|w| w.idevid_csr_ready(true)); } - /// Set ready for firmware + /// Set ready for Mailbox operations /// /// # Arguments /// /// * None - pub fn flow_status_set_ready_for_firmware(&mut self) { + pub fn flow_status_set_ready_for_mb_processing(&mut self) { let soc_ifc = self.soc_ifc.regs_mut(); - soc_ifc.cptra_flow_status().write(|w| w.ready_for_fw(true)); + soc_ifc + .cptra_flow_status() + .write(|w| w.ready_for_mb_processing(true)); } /// Get 'ready for firmware' status @@ -134,9 +136,9 @@ impl SocIfc { /// # Arguments /// /// * None - pub fn flow_status_ready_for_firmware(&mut self) -> bool { + pub fn flow_status_ready_for_mb_processing(&mut self) -> bool { let soc_ifc = self.soc_ifc.regs_mut(); - soc_ifc.cptra_flow_status().read().ready_for_fw() + soc_ifc.cptra_flow_status().read().ready_for_mb_processing() } pub fn fuse_bank(&self) -> FuseBank { diff --git a/drivers/test-fw/src/bin/keyvault_tests.rs b/drivers/test-fw/src/bin/keyvault_tests.rs index 21ed5a2ec3..d63c4f257d 100644 --- a/drivers/test-fw/src/bin/keyvault_tests.rs +++ b/drivers/test-fw/src/bin/keyvault_tests.rs @@ -20,7 +20,7 @@ use caliptra_registers::kv::KvReg; use caliptra_test_harness::test_suite; #[cfg(not(feature = "fpga_realtime"))] -const KEY_IDS: [KeyId; 32] = [ +const KEY_IDS: [KeyId; 24] = [ KeyId::KeyId0, KeyId::KeyId1, KeyId::KeyId2, @@ -45,14 +45,6 @@ const KEY_IDS: [KeyId; 32] = [ KeyId::KeyId21, KeyId::KeyId22, KeyId::KeyId23, - KeyId::KeyId24, - KeyId::KeyId25, - KeyId::KeyId26, - KeyId::KeyId27, - KeyId::KeyId28, - KeyId::KeyId29, - KeyId::KeyId30, - KeyId::KeyId31, ]; #[cfg(feature = "fpga_realtime")] diff --git a/drivers/test-fw/src/bin/mldsa87_tests.rs b/drivers/test-fw/src/bin/mldsa87_tests.rs index b11711983e..68d9756970 100644 --- a/drivers/test-fw/src/bin/mldsa87_tests.rs +++ b/drivers/test-fw/src/bin/mldsa87_tests.rs @@ -392,6 +392,8 @@ const MESSAGE: [u8; 64] = [ 186, ]; +const KEY_ID: KeyId = KeyId::KeyId1; + fn test_gen_key_pair() { let mut trng = unsafe { Trng::new( @@ -411,8 +413,8 @@ fn test_gen_key_pair() { let mut hmac = unsafe { Hmac::new(HmacReg::new()) }; let key_out_1 = KeyWriteArgs { - id: KeyId::KeyId0, - usage: KeyUsage::default().set_ecc_key_gen_seed_en(), + id: KEY_ID, + usage: KeyUsage::default().set_mldsa_seed_en(), }; hmac.hmac( @@ -424,7 +426,7 @@ fn test_gen_key_pair() { ) .unwrap(); - let seed = KeyReadArgs::new(KeyId::KeyId0); + let seed = KeyReadArgs::new(KEY_ID); let public_key = ml_dsa87.key_pair(&seed, &mut trng).unwrap(); assert_eq!(public_key, Mldsa87PubKey::from(PUBKEY)); } @@ -443,7 +445,7 @@ fn test_sign() { }; let sign_rnd = Mldsa87SignRnd::default(); // Deterministic signing - let seed = KeyReadArgs::new(KeyId::KeyId0); // Reuse SEED + let seed = KeyReadArgs::new(KEY_ID); // Reuse SEED let signature = ml_dsa87 .sign( diff --git a/drivers/test-fw/src/bin/status_reporter_tests.rs b/drivers/test-fw/src/bin/status_reporter_tests.rs index e18a8a45c1..ee8d297649 100644 --- a/drivers/test-fw/src/bin/status_reporter_tests.rs +++ b/drivers/test-fw/src/bin/status_reporter_tests.rs @@ -40,9 +40,13 @@ fn test_report_idevid_csr_ready() { fn test_report_ready_for_firmware() { let soc_ifc = unsafe { SocIfcReg::new() }; - SocIfc::new(soc_ifc).flow_status_set_ready_for_firmware(); + SocIfc::new(soc_ifc).flow_status_set_ready_for_mb_processing(); let soc_ifc = unsafe { SocIfcReg::new() }; - assert!(soc_ifc.regs().cptra_flow_status().read().ready_for_fw()); + assert!(soc_ifc + .regs() + .cptra_flow_status() + .read() + .ready_for_mb_processing()); } test_suite! { diff --git a/drivers/tests/drivers_integration_tests/main.rs b/drivers/tests/drivers_integration_tests/main.rs index 4ce11e5d20..25b1c21680 100644 --- a/drivers/tests/drivers_integration_tests/main.rs +++ b/drivers/tests/drivers_integration_tests/main.rs @@ -91,13 +91,13 @@ impl DoeTestVectors { }; result.expected_test_results.hmac_uds_as_key_out_pub = ecdsa_keygen(&hmac384( - swap_word_bytes(&result.doe_output.uds).as_bytes(), + swap_word_bytes(&result.doe_output.uds[..12]).as_bytes(), "Hello world!".as_bytes(), )); result.expected_test_results.hmac_uds_as_data_out_pub = ecdsa_keygen(&hmac384( swap_word_bytes(&caliptra_drivers_test_bin::DOE_TEST_HMAC_KEY).as_bytes(), - swap_word_bytes(&result.doe_output.uds).as_bytes(), + swap_word_bytes(&result.doe_output.uds[..12]).as_bytes(), )); result @@ -122,7 +122,8 @@ const DOE_TEST_VECTORS_DEBUG_MODE: DoeTestVectors = DoeTestVectors { // The decrypted UDS as stored in the key vault uds: [ 0x34aa667c, 0x0a52c71f, 0x977a1de2, 0x701ef611, 0x0de19e21, 0x24b49b9d, 0xdf205ff6, - 0xa9c04303, 0x0de19e21, 0x24b49b9d, 0xdf205ff6, 0xa9c04303, + 0xa9c04303, 0x0de19e21, 0x24b49b9d, 0xdf205ff6, 0xa9c04303, 0xde19e21, 0x24b49b9d, + 0xdf205ff6, 0xa9c04303, ], // The decrypted field entropy as stored in the key vault (with padding) @@ -196,7 +197,7 @@ fn test_generate_doe_vectors_when_debug_not_locked() { doe_iv: caliptra_drivers_test_bin::DOE_TEST_IV, - uds_seed: [0xffff_ffff_u32; 12], + uds_seed: [0xffff_ffff_u32; 16], field_entropy_seed: [0xffff_ffff_u32; 8], // In debug mode, this defaults to 0xaaaa_aaaa @@ -232,7 +233,8 @@ const DOE_TEST_VECTORS: DoeTestVectors = DoeTestVectors { doe_output: DoeOutput { uds: [ 0x0b21f10f, 0x6963005e, 0x4884d93f, 0x1f91037a, 0x2d37ffe0, 0x3727b5e8, 0xb78b9608, - 0x7e0e58d2, 0x420ce5ae, 0x4b1f04f8, 0x33b7af81, 0x72156bd8, + 0x7e0e58d2, 0x420ce5ae, 0x4b1f04f8, 0x33b7af81, 0x72156bd8, 0xf55d652c, 0xfbdb1831, + 0x58517e56, 0xfe1eab2f, ], field_entropy: [ 0x3d75d35e, 0xbc44a31e, 0xad27aee5, 0x75cdd170, 0xe51dcaf4, 0x09c096ae, 0xa70ff448, diff --git a/hw-model/c-binding/examples/api/caliptra_api.c b/hw-model/c-binding/examples/api/caliptra_api.c index 45d9c02189..a0eaafdd56 100644 --- a/hw-model/c-binding/examples/api/caliptra_api.c +++ b/hw-model/c-binding/examples/api/caliptra_api.c @@ -22,14 +22,13 @@ int caliptra_init_fuses(struct caliptra_model *model, struct caliptra_fuses *fus caliptra_fuse_array_write(model, GENERIC_AND_FUSE_REG_FUSE_UDS_SEED_0, fuses->uds_seed, CALIPTRA_ARRAY_SIZE(fuses->uds_seed)); caliptra_fuse_array_write(model, GENERIC_AND_FUSE_REG_FUSE_FIELD_ENTROPY_0, fuses->field_entropy, CALIPTRA_ARRAY_SIZE(fuses->field_entropy)); caliptra_fuse_array_write(model, GENERIC_AND_FUSE_REG_FUSE_KEY_MANIFEST_PK_HASH_0, fuses->key_manifest_pk_hash, CALIPTRA_ARRAY_SIZE(fuses->key_manifest_pk_hash)); - caliptra_fuse_write(model, GENERIC_AND_FUSE_REG_FUSE_KEY_MANIFEST_PK_HASH_MASK, fuses->key_manifest_pk_hash_mask); - caliptra_fuse_array_write(model, GENERIC_AND_FUSE_REG_FUSE_OWNER_PK_HASH_0, fuses->owner_pk_hash, CALIPTRA_ARRAY_SIZE(fuses->owner_pk_hash)); + caliptra_fuse_write(model, GENERIC_AND_FUSE_REG_FUSE_KEY_MANIFEST_PK_HASH_MASK_0, fuses->key_manifest_pk_hash_mask); + caliptra_fuse_array_write(model, GENERIC_AND_FUSE_REG_CPTRA_OWNER_PK_HASH_0, fuses->owner_pk_hash, CALIPTRA_ARRAY_SIZE(fuses->owner_pk_hash)); caliptra_fuse_write(model, GENERIC_AND_FUSE_REG_FUSE_FMC_KEY_MANIFEST_SVN, fuses->fmc_key_manifest_svn); caliptra_fuse_array_write(model, GENERIC_AND_FUSE_REG_FUSE_FMC_KEY_MANIFEST_SVN, fuses->runtime_svn, CALIPTRA_ARRAY_SIZE(fuses->runtime_svn)); caliptra_fuse_write(model, GENERIC_AND_FUSE_REG_FUSE_ANTI_ROLLBACK_DISABLE, (uint32_t)fuses->anti_rollback_disable); caliptra_fuse_array_write(model, GENERIC_AND_FUSE_REG_FUSE_IDEVID_CERT_ATTR_0, fuses->idevid_cert_attr, CALIPTRA_ARRAY_SIZE(fuses->idevid_cert_attr)); caliptra_fuse_array_write(model, GENERIC_AND_FUSE_REG_FUSE_IDEVID_MANUF_HSM_ID_0, fuses->idevid_manuf_hsm_id, CALIPTRA_ARRAY_SIZE(fuses->idevid_manuf_hsm_id)); - caliptra_fuse_write(model, GENERIC_AND_FUSE_REG_FUSE_LIFE_CYCLE, (uint32_t)fuses->life_cycle); // Write to Caliptra Fuse Done caliptra_model_axi_write_u32(model, CALIPTRA_TOP_REG_GENERIC_AND_FUSE_REG_CPTRA_FUSE_WR_DONE, 1); diff --git a/hw-model/src/lib.rs b/hw-model/src/lib.rs index 8552a83301..ee642945d0 100644 --- a/hw-model/src/lib.rs +++ b/hw-model/src/lib.rs @@ -253,7 +253,7 @@ pub struct BootParams<'a> { pub initial_dbg_manuf_service_reg: u32, pub initial_repcnt_thresh_reg: Option, pub initial_adaptp_thresh_reg: Option, - pub valid_axi_id: Vec, + pub valid_axi_user: Vec, pub wdt_timeout_cycles: u64, } @@ -266,7 +266,7 @@ impl<'a> Default for BootParams<'a> { initial_dbg_manuf_service_reg: Default::default(), initial_repcnt_thresh_reg: Default::default(), initial_adaptp_thresh_reg: Default::default(), - valid_axi_id: vec![0, 1, 2, 3, 4], + valid_axi_user: vec![0, 1, 2, 3, 4], wdt_timeout_cycles: EXPECTED_CALIPTRA_BOOT_TIME_IN_CYCLES, } } @@ -575,7 +575,7 @@ pub trait HwModel: SocManager { } // Set up the PAUSER as valid for the mailbox (using index 0) - self.setup_mailbox_users(boot_params.valid_axi_id.as_slice()) + self.setup_mailbox_users(boot_params.valid_axi_user.as_slice()) .map_err(ModelError::from)?; writeln!(self.output().logger(), "writing to cptra_bootfsm_go")?; @@ -826,7 +826,7 @@ pub trait HwModel: SocManager { fn ecc_error_injection(&mut self, _mode: ErrorInjectionMode) {} - fn set_axi_id(&mut self, axi_id: u32); + fn set_axi_user(&mut self, axi_user: u32); /// Executes a typed request and (if success), returns the typed response. /// The checksum field of the request is calculated, and the checksum of the @@ -867,7 +867,7 @@ pub trait HwModel: SocManager { } // Mailbox lock value should read 1 now - // If not, the reads are likely being blocked by the AXI_ID check or some other issue + // If not, the reads are likely being blocked by the AXI_USER check or some other issue if !(self.soc_mbox().lock().read().lock()) { return Err(ModelError::UnableToReadMailbox); } @@ -1134,15 +1134,15 @@ mod tests { model.soc_ifc().cptra_fuse_wr_done().write(|w| w.done(true)); model.soc_ifc().cptra_bootfsm_go().write(|w| w.go(true)); - // Set up the AXI_ID as valid for the mailbox (using index 0) + // Set up the AXI_USER as valid for the mailbox (using index 0) model .soc_ifc() - .cptra_mbox_valid_axi_id() + .cptra_mbox_valid_axi_user() .at(0) .write(|_| 0x1); model .soc_ifc() - .cptra_mbox_axi_id_lock() + .cptra_mbox_axi_user_lock() .at(0) .write(|w| w.lock(true)); @@ -1178,15 +1178,15 @@ mod tests { model.soc_ifc().cptra_fuse_wr_done().write(|w| w.done(true)); model.soc_ifc().cptra_bootfsm_go().write(|w| w.go(true)); - // Set up the AXI_ID as valid for the mailbox (using index 0) + // Set up the AXI_USER as valid for the mailbox (using index 0) model .soc_ifc() - .cptra_mbox_valid_axi_id() + .cptra_mbox_valid_axi_user() .at(0) .write(|_| 0x1); model .soc_ifc() - .cptra_mbox_axi_id_lock() + .cptra_mbox_axi_user_lock() .at(0) .write(|w| w.lock(true)); @@ -1209,15 +1209,15 @@ mod tests { model.soc_ifc().cptra_fuse_wr_done().write(|w| w.done(true)); model.soc_ifc().cptra_bootfsm_go().write(|w| w.go(true)); - // Set up the AXI_ID as valid for the mailbox (using index 0) + // Set up the AXI_USER as valid for the mailbox (using index 0) model .soc_ifc() - .cptra_mbox_valid_axi_id() + .cptra_mbox_valid_axi_user() .at(0) .write(|_| 0x1); model .soc_ifc() - .cptra_mbox_axi_id_lock() + .cptra_mbox_axi_user_lock() .at(0) .write(|w| w.lock(true)); @@ -1237,10 +1237,10 @@ mod tests { #[test] // Currently only possible on verilator - // SW emulator does not support axi_id + // SW emulator does not support axi_user // For FPGA, test case needs to be reworked to capture SIGBUS from linux environment #[cfg(feature = "verilator")] - fn test_mbox_axi_id() { + fn test_mbox_axi_user() { let mut model = caliptra_hw_model::new_unbooted(InitParams { rom: &gen_image_hi(), ..Default::default() @@ -1250,27 +1250,27 @@ mod tests { model.soc_ifc().cptra_fuse_wr_done().write(|w| w.done(true)); model.soc_ifc().cptra_bootfsm_go().write(|w| w.go(true)); - // Set up the AXI_ID as valid for the mailbox (using index 0) + // Set up the AXI_USER as valid for the mailbox (using index 0) model .soc_ifc() - .cptra_mbox_valid_axi_id() + .cptra_mbox_valid_axi_user() .at(0) .write(|_| 0x1); model .soc_ifc() - .cptra_mbox_axi_id_lock() + .cptra_mbox_axi_user_lock() .at(0) .write(|w| w.lock(true)); - // Set the AXI_ID to something invalid - model.set_axi_id(0x2); + // Set the AXI_USER to something invalid + model.set_axi_user(0x2); assert!(!model.soc_mbox().lock().read().lock()); - // Should continue to read 0 because the reads are being blocked by valid AXI_ID + // Should continue to read 0 because the reads are being blocked by valid AXI_USER assert!(!model.soc_mbox().lock().read().lock()); - // Set the AXI_ID back to valid - model.set_axi_id(0x1); + // Set the AXI_USER back to valid + model.set_axi_user(0x1); // Should read 0 the first time still for lock available assert!(!model.soc_mbox().lock().read().lock()); @@ -1393,12 +1393,12 @@ mod tests { // Set up the PAUSER as valid for the mailbox (using index 0) model .soc_ifc() - .cptra_mbox_valid_axi_id() + .cptra_mbox_valid_axi_user() .at(0) .write(|_| 0x1); model .soc_ifc() - .cptra_mbox_axi_id_lock() + .cptra_mbox_axi_user_lock() .at(0) .write(|w| w.lock(true)); diff --git a/hw-model/src/model_emulated.rs b/hw-model/src/model_emulated.rs index 9b0c32d970..c2515ee735 100644 --- a/hw-model/src/model_emulated.rs +++ b/hw-model/src/model_emulated.rs @@ -282,7 +282,7 @@ impl HwModel for ModelEmulated { } } - fn set_axi_id(&mut self, _axi_id: u32) { + fn set_axi_user(&mut self, _axi_user: u32) { unimplemented!(); } diff --git a/hw-model/src/model_fpga_realtime.rs b/hw-model/src/model_fpga_realtime.rs index 177c95931d..54e3b02df0 100644 --- a/hw-model/src/model_fpga_realtime.rs +++ b/hw-model/src/model_fpga_realtime.rs @@ -421,7 +421,7 @@ impl HwModel for ModelFpgaRealtime { m.set_security_state(params.security_state); // Set initial PAUSER - m.set_axi_id(DEFAULT_AXI_PAUSER); + m.set_axi_user(DEFAULT_AXI_PAUSER); // Set divisor for ITRNG throttling m.set_itrng_divider(ITRNG_DIVISOR); @@ -522,7 +522,7 @@ impl HwModel for ModelFpgaRealtime { // Do nothing; we don't support tracing yet } - fn set_axi_id(&mut self, pauser: u32) { + fn set_axi_user(&mut self, pauser: u32) { unsafe { self.wrapper .offset(FPGA_WRAPPER_PAUSER_OFFSET) diff --git a/hw-model/src/model_verilated.rs b/hw-model/src/model_verilated.rs index 8886bf0168..e09e7c4ec5 100644 --- a/hw-model/src/model_verilated.rs +++ b/hw-model/src/model_verilated.rs @@ -321,8 +321,8 @@ impl HwModel for ModelVerilated { } } - fn ready_for_fw(&self) -> bool { - self.v.output.ready_for_fw_push + fn ready_for_mb_processing(&self) -> bool { + self.v.output.ready_for_mb_processing_push } fn tracing_hint(&mut self, enable: bool) { @@ -364,7 +364,7 @@ impl HwModel for ModelVerilated { } } - fn set_axi_id(&mut self, pauser: u32) { + fn set_axi_user(&mut self, pauser: u32) { self.soc_axi_pauser = pauser; } } diff --git a/hw-model/test-fw/mailbox_responder.rs b/hw-model/test-fw/mailbox_responder.rs index 5a26921fe7..d4ca7122fd 100644 --- a/hw-model/test-fw/mailbox_responder.rs +++ b/hw-model/test-fw/mailbox_responder.rs @@ -29,7 +29,7 @@ extern "C" fn main() { soc_ifc .regs_mut() .cptra_flow_status() - .write(|w| w.ready_for_fw(true)); + .write(|w| w.ready_for_mb_processing(true)); let mut replay_buf_len = 0; let mut replay_buf = [0u32; 2048]; diff --git a/hw-model/test-fw/mailbox_sender.rs b/hw-model/test-fw/mailbox_sender.rs index cee321f6c2..ba264a71ca 100644 --- a/hw-model/test-fw/mailbox_sender.rs +++ b/hw-model/test-fw/mailbox_sender.rs @@ -50,7 +50,9 @@ extern "C" fn main() { let mut mbox = unsafe { MboxCsr::new() }; let mbox = mbox.regs_mut(); - soc_ifc.cptra_flow_status().write(|w| w.ready_for_fw(true)); + soc_ifc + .cptra_flow_status() + .write(|w| w.ready_for_mb_processing(true)); let mut response_iter = RESPONSES.iter().cycle(); loop { diff --git a/hw-model/types/src/lib.rs b/hw-model/types/src/lib.rs index 244aff9be3..b290bb6af0 100644 --- a/hw-model/types/src/lib.rs +++ b/hw-model/types/src/lib.rs @@ -14,9 +14,9 @@ use rand::{ // * The constant should be easily recognizable in waveforms and debug logs // * Every word must be different to ensure that a "stuck word" bug is noticed. // * Each byte in a word must be unique to ensure an endianness bug is noticed. -pub const DEFAULT_UDS_SEED: [u32; 12] = [ +pub const DEFAULT_UDS_SEED: [u32; 16] = [ 0x00010203, 0x04050607, 0x08090a0b, 0x0c0d0e0f, 0x10111213, 0x14151617, 0x18191a1b, 0x1c1d1e1f, - 0x20212223, 0x24252627, 0x28292a2b, 0x2c2d2e2f, + 0x20212223, 0x24252627, 0x28292a2b, 0x2c2d2e2f, 0x30313233, 0x34353637, 0x38393a3b, 0x3c3d3e3f, ]; pub const DEFAULT_FIELD_ENTROPY: [u32; 8] = [ @@ -130,7 +130,6 @@ impl std::fmt::Debug for FusesWrapper { &HexSlice(&self.0.idevid_manuf_hsm_id), ) .field("life_cycle", &self.0.life_cycle) - .field("lms_verify", &self.0.lms_verify) .field("fuse_lms_revocation", &self.0.fuse_lms_revocation) .field("soc_stepping_id", &self.0.soc_stepping_id) .finish() diff --git a/hw/latest/adams-bridge b/hw/latest/adams-bridge deleted file mode 160000 index 861a9b9eb3..0000000000 --- a/hw/latest/adams-bridge +++ /dev/null @@ -1 +0,0 @@ -Subproject commit 861a9b9eb3cf1c52094b1b1f4244173eb2b64e40 diff --git a/hw/latest/registers/src/axi_dma.rs b/hw/latest/registers/src/axi_dma.rs index a2ddda3645..e480946a79 100644 --- a/hw/latest/registers/src/axi_dma.rs +++ b/hw/latest/registers/src/axi_dma.rs @@ -1,6 +1,6 @@ // Licensed under the Apache-2.0 license. // -// generated by caliptra_registers_generator with caliptra-rtl repo at ac8e5592b1a6d53f92809c98f8f0144c5a5bf0eb +// generated by caliptra_registers_generator with caliptra-rtl repo at 00730026cdf11841d20a6085ea3909ea3bd4a21b // #![allow(clippy::erasing_op)] #![allow(clippy::identity_op)] @@ -1719,10 +1719,25 @@ pub mod regs { pub fn axi_dma_fsm_ps(&self) -> super::enums::AxiDmaFsmE { super::enums::AxiDmaFsmE::try_from((self.0 >> 16) & 3).unwrap() } + /// Payload Available. Signal indicates data is available. + /// When the DMA is active and was armed with nonzero block + /// size, this is used by the hardware to automatically + /// trigger AXI transactions of the specified block + /// size, until the total byte count is transferred. + #[inline(always)] + pub fn payload_available(&self) -> bool { + ((self.0 >> 18) & 1) != 0 + } + /// Image Activated. Signal indicates image activation status + /// reported by Recovery Interface (from Caliptra Subsystem). + #[inline(always)] + pub fn image_activated(&self) -> bool { + ((self.0 >> 19) & 1) != 0 + } /// RESERVED. #[inline(always)] pub fn rsvd1(&self) -> u32 { - (self.0 >> 18) & 0x3fff + (self.0 >> 20) & 0xfff } } impl From for Status0ReadVal { diff --git a/hw/latest/registers/src/csrng.rs b/hw/latest/registers/src/csrng.rs index 7342ca5f88..b6f5a5f05a 100644 --- a/hw/latest/registers/src/csrng.rs +++ b/hw/latest/registers/src/csrng.rs @@ -1,6 +1,6 @@ // Licensed under the Apache-2.0 license. // -// generated by caliptra_registers_generator with caliptra-rtl repo at ac8e5592b1a6d53f92809c98f8f0144c5a5bf0eb +// generated by caliptra_registers_generator with caliptra-rtl repo at 00730026cdf11841d20a6085ea3909ea3bd4a21b // #![allow(clippy::erasing_op)] #![allow(clippy::identity_op)] diff --git a/hw/latest/registers/src/doe.rs b/hw/latest/registers/src/doe.rs index 9843f8eaa2..887d9966f1 100644 --- a/hw/latest/registers/src/doe.rs +++ b/hw/latest/registers/src/doe.rs @@ -1,6 +1,6 @@ // Licensed under the Apache-2.0 license. // -// generated by caliptra_registers_generator with caliptra-rtl repo at ac8e5592b1a6d53f92809c98f8f0144c5a5bf0eb +// generated by caliptra_registers_generator with caliptra-rtl repo at 00730026cdf11841d20a6085ea3909ea3bd4a21b // #![allow(clippy::erasing_op)] #![allow(clippy::identity_op)] diff --git a/hw/latest/registers/src/dv.rs b/hw/latest/registers/src/dv.rs index a567bcdd40..e1999ce222 100644 --- a/hw/latest/registers/src/dv.rs +++ b/hw/latest/registers/src/dv.rs @@ -1,6 +1,6 @@ // Licensed under the Apache-2.0 license. // -// generated by caliptra_registers_generator with caliptra-rtl repo at ac8e5592b1a6d53f92809c98f8f0144c5a5bf0eb +// generated by caliptra_registers_generator with caliptra-rtl repo at 00730026cdf11841d20a6085ea3909ea3bd4a21b // #![allow(clippy::erasing_op)] #![allow(clippy::identity_op)] diff --git a/hw/latest/registers/src/ecc.rs b/hw/latest/registers/src/ecc.rs index c3f13f1333..65805bf7ba 100644 --- a/hw/latest/registers/src/ecc.rs +++ b/hw/latest/registers/src/ecc.rs @@ -1,6 +1,6 @@ // Licensed under the Apache-2.0 license. // -// generated by caliptra_registers_generator with caliptra-rtl repo at ac8e5592b1a6d53f92809c98f8f0144c5a5bf0eb +// generated by caliptra_registers_generator with caliptra-rtl repo at 00730026cdf11841d20a6085ea3909ea3bd4a21b // #![allow(clippy::erasing_op)] #![allow(clippy::identity_op)] diff --git a/hw/latest/registers/src/el2_pic_ctrl.rs b/hw/latest/registers/src/el2_pic_ctrl.rs index ad65753e54..0d93abe5d5 100644 --- a/hw/latest/registers/src/el2_pic_ctrl.rs +++ b/hw/latest/registers/src/el2_pic_ctrl.rs @@ -1,6 +1,6 @@ // Licensed under the Apache-2.0 license. // -// generated by caliptra_registers_generator with caliptra-rtl repo at ac8e5592b1a6d53f92809c98f8f0144c5a5bf0eb +// generated by caliptra_registers_generator with caliptra-rtl repo at 00730026cdf11841d20a6085ea3909ea3bd4a21b // #![allow(clippy::erasing_op)] #![allow(clippy::identity_op)] diff --git a/hw/latest/registers/src/entropy_src.rs b/hw/latest/registers/src/entropy_src.rs index cf5944d0fd..669e0289cc 100644 --- a/hw/latest/registers/src/entropy_src.rs +++ b/hw/latest/registers/src/entropy_src.rs @@ -1,6 +1,6 @@ // Licensed under the Apache-2.0 license. // -// generated by caliptra_registers_generator with caliptra-rtl repo at ac8e5592b1a6d53f92809c98f8f0144c5a5bf0eb +// generated by caliptra_registers_generator with caliptra-rtl repo at 00730026cdf11841d20a6085ea3909ea3bd4a21b // #![allow(clippy::erasing_op)] #![allow(clippy::identity_op)] diff --git a/hw/latest/registers/src/hmac.rs b/hw/latest/registers/src/hmac.rs index 6b10f2e931..f54e403d70 100644 --- a/hw/latest/registers/src/hmac.rs +++ b/hw/latest/registers/src/hmac.rs @@ -1,6 +1,6 @@ // Licensed under the Apache-2.0 license. // -// generated by caliptra_registers_generator with caliptra-rtl repo at ac8e5592b1a6d53f92809c98f8f0144c5a5bf0eb +// generated by caliptra_registers_generator with caliptra-rtl repo at 00730026cdf11841d20a6085ea3909ea3bd4a21b // #![allow(clippy::erasing_op)] #![allow(clippy::identity_op)] @@ -697,10 +697,15 @@ pub mod regs { pub fn mode(self, val: bool) -> Self { Self((self.0 & !(1 << 3)) | (u32::from(val) << 3)) } + /// CSR Mode: Indicates to the HMAC512 core to use the CSR HMAC key + #[inline(always)] + pub fn csr_mode(self, val: bool) -> Self { + Self((self.0 & !(1 << 4)) | (u32::from(val) << 4)) + } /// Reserved #[inline(always)] pub fn reserved(self, val: bool) -> Self { - Self((self.0 & !(1 << 4)) | (u32::from(val) << 4)) + Self((self.0 & !(1 << 5)) | (u32::from(val) << 5)) } } impl From for Hmac512CtrlWriteVal { diff --git a/hw/latest/registers/src/i3ccsr.rs b/hw/latest/registers/src/i3ccsr.rs index 9c643394e6..d70156820c 100644 --- a/hw/latest/registers/src/i3ccsr.rs +++ b/hw/latest/registers/src/i3ccsr.rs @@ -1,6 +1,6 @@ // Licensed under the Apache-2.0 license. // -// generated by caliptra_registers_generator with caliptra-rtl repo at ac8e5592b1a6d53f92809c98f8f0144c5a5bf0eb +// generated by caliptra_registers_generator with caliptra-rtl repo at 00730026cdf11841d20a6085ea3909ea3bd4a21b // #![allow(clippy::erasing_op)] #![allow(clippy::identity_op)] diff --git a/hw/latest/registers/src/kv.rs b/hw/latest/registers/src/kv.rs index fbbd58614b..2aacc599ad 100644 --- a/hw/latest/registers/src/kv.rs +++ b/hw/latest/registers/src/kv.rs @@ -1,6 +1,6 @@ // Licensed under the Apache-2.0 license. // -// generated by caliptra_registers_generator with caliptra-rtl repo at ac8e5592b1a6d53f92809c98f8f0144c5a5bf0eb +// generated by caliptra_registers_generator with caliptra-rtl repo at 00730026cdf11841d20a6085ea3909ea3bd4a21b // #![allow(clippy::erasing_op)] #![allow(clippy::identity_op)] @@ -77,7 +77,7 @@ impl RegisterBlock { /// /// Read value: [`kv::regs::KvctrlReadVal`]; Write value: [`kv::regs::KvctrlWriteVal`] #[inline(always)] - pub fn key_ctrl(&self) -> ureg::Array<32, ureg::RegRef> { + pub fn key_ctrl(&self) -> ureg::Array<24, ureg::RegRef> { unsafe { ureg::Array::new_with_mmio( self.ptr.wrapping_add(0 / core::mem::size_of::()), @@ -91,7 +91,7 @@ impl RegisterBlock { #[inline(always)] pub fn key_entry( &self, - ) -> ureg::Array<32, ureg::Array<12, ureg::RegRef>> { + ) -> ureg::Array<24, ureg::Array<16, ureg::RegRef>> { unsafe { ureg::Array::new_with_mmio( self.ptr.wrapping_add(0x600 / core::mem::size_of::()), @@ -200,7 +200,7 @@ pub mod regs { /// Destination valid bits stored as an array for ease of use in RTL. /// [br]dest_valid[0] = hmac_key_dest_valid /// [br]dest_valid[1] = hmac_block_dest_valid - /// [br]dest_valid[2] = sha_block_dest_valid + /// [br]dest_valid[2] = mldsa_seed_dest_valid /// [br]dest_valid[3] = ecc_pkey_dest_valid /// [br]dest_valid[4] = ecc_seed_dest_valid /// [br]dest_valid[5] = rsvd diff --git a/hw/latest/registers/src/lib.rs b/hw/latest/registers/src/lib.rs index f8866a2830..2f86558b38 100644 --- a/hw/latest/registers/src/lib.rs +++ b/hw/latest/registers/src/lib.rs @@ -1,6 +1,6 @@ // Licensed under the Apache-2.0 license. // -// generated by caliptra_registers_generator with caliptra-rtl repo at ac8e5592b1a6d53f92809c98f8f0144c5a5bf0eb +// generated by caliptra_registers_generator with caliptra-rtl repo at 00730026cdf11841d20a6085ea3909ea3bd4a21b // #![no_std] #![allow(clippy::erasing_op)] @@ -141,9 +141,9 @@ pub mod regs { pub fn hmac_block_dest_valid(&self) -> bool { ((self.0 >> 7) & 1) != 0 } - /// Reserved field. No SHA key vault interface + /// MLDSA_SEED is a valid destination #[inline(always)] - pub fn sha_block_dest_valid(&self) -> bool { + pub fn mldsa_seed_dest_valid(&self) -> bool { ((self.0 >> 8) & 1) != 0 } /// ECC PKEY is a valid destination @@ -203,9 +203,9 @@ pub mod regs { pub fn hmac_block_dest_valid(self, val: bool) -> Self { Self((self.0 & !(1 << 7)) | (u32::from(val) << 7)) } - /// Reserved field. No SHA key vault interface + /// MLDSA_SEED is a valid destination #[inline(always)] - pub fn sha_block_dest_valid(self, val: bool) -> Self { + pub fn mldsa_seed_dest_valid(self, val: bool) -> Self { Self((self.0 & !(1 << 8)) | (u32::from(val) << 8)) } /// ECC PKEY is a valid destination diff --git a/hw/latest/registers/src/mbox.rs b/hw/latest/registers/src/mbox.rs index 0a670c3dc5..ac76836ef7 100644 --- a/hw/latest/registers/src/mbox.rs +++ b/hw/latest/registers/src/mbox.rs @@ -1,6 +1,6 @@ // Licensed under the Apache-2.0 license. // -// generated by caliptra_registers_generator with caliptra-rtl repo at ac8e5592b1a6d53f92809c98f8f0144c5a5bf0eb +// generated by caliptra_registers_generator with caliptra-rtl repo at 00730026cdf11841d20a6085ea3909ea3bd4a21b // #![allow(clippy::erasing_op)] #![allow(clippy::identity_op)] @@ -87,13 +87,13 @@ impl RegisterBlock { ) } } - /// Stores the AXI ID that locked the mailbox + /// Stores the AXI USER that locked the mailbox /// [br]Caliptra Access: RO /// [br]SOC Access: RO /// /// Read value: [`u32`]; Write value: [`u32`] #[inline(always)] - pub fn id(&self) -> ureg::RegRef { + pub fn user(&self) -> ureg::RegRef { unsafe { ureg::RegRef::new_with_mmio( self.ptr.wrapping_add(4 / core::mem::size_of::()), @@ -118,7 +118,7 @@ impl RegisterBlock { /// Data length for mailbox access in bytes /// [br]Caliptra Access: RW /// [br]SOC Access: RW - /// [br]TAP Access [in debug/manuf mode]: RO + /// [br]TAP Access [in debug/manuf mode]: RW /// /// Read value: [`u32`]; Write value: [`u32`] #[inline(always)] @@ -133,6 +133,7 @@ impl RegisterBlock { /// Data in register, write the next data to mailbox /// [br]Caliptra Access: RW /// [br]SOC Access: RW + /// [br]TAP Access [in debug/manuf mode]: WO /// /// Read value: [`u32`]; Write value: [`u32`] #[inline(always)] @@ -199,6 +200,20 @@ impl RegisterBlock { ) } } + /// Capability for uC to enable TAP logic to respond to mailbox commands. + /// [br]Caliptra Access: RW + /// [br]SOC Access: RO + /// + /// Read value: [`mbox::regs::TapModeReadVal`]; Write value: [`mbox::regs::TapModeWriteVal`] + #[inline(always)] + pub fn tap_mode(&self) -> ureg::RegRef { + unsafe { + ureg::RegRef::new_with_mmio( + self.ptr.wrapping_add(0x24 / core::mem::size_of::()), + core::borrow::Borrow::borrow(&self.mmio), + ) + } + } } pub mod regs { //! Types that represent the values held by registers. @@ -376,6 +391,53 @@ pub mod regs { } } #[derive(Clone, Copy)] + pub struct TapModeReadVal(u32); + impl TapModeReadVal { + /// + #[inline(always)] + pub fn enabled(&self) -> bool { + ((self.0 >> 0) & 1) != 0 + } + /// Construct a WriteVal that can be used to modify the contents of this register value. + #[inline(always)] + pub fn modify(self) -> TapModeWriteVal { + TapModeWriteVal(self.0) + } + } + impl From for TapModeReadVal { + #[inline(always)] + fn from(val: u32) -> Self { + Self(val) + } + } + impl From for u32 { + #[inline(always)] + fn from(val: TapModeReadVal) -> u32 { + val.0 + } + } + #[derive(Clone, Copy)] + pub struct TapModeWriteVal(u32); + impl TapModeWriteVal { + /// + #[inline(always)] + pub fn enabled(self, val: bool) -> Self { + Self((self.0 & !(1 << 0)) | (u32::from(val) << 0)) + } + } + impl From for TapModeWriteVal { + #[inline(always)] + fn from(val: u32) -> Self { + Self(val) + } + } + impl From for u32 { + #[inline(always)] + fn from(val: TapModeWriteVal) -> u32 { + val.0 + } + } + #[derive(Clone, Copy)] pub struct UnlockReadVal(u32); impl UnlockReadVal { /// @@ -593,7 +655,7 @@ pub mod enums { pub mod meta { //! Additional metadata needed by ureg. pub type Lock = ureg::ReadOnlyReg32; - pub type Id = ureg::ReadOnlyReg32; + pub type User = ureg::ReadOnlyReg32; pub type Cmd = ureg::ReadWriteReg32<0, u32, u32>; pub type Dlen = ureg::ReadWriteReg32<0, u32, u32>; pub type Datain = ureg::ReadWriteReg32<0, u32, u32>; @@ -613,4 +675,9 @@ pub mod meta { crate::mbox::regs::UnlockReadVal, crate::mbox::regs::UnlockWriteVal, >; + pub type TapMode = ureg::ReadWriteReg32< + 0, + crate::mbox::regs::TapModeReadVal, + crate::mbox::regs::TapModeWriteVal, + >; } diff --git a/hw/latest/registers/src/mbox_sram.rs b/hw/latest/registers/src/mbox_sram.rs index 71571c0ea1..70de58b297 100644 --- a/hw/latest/registers/src/mbox_sram.rs +++ b/hw/latest/registers/src/mbox_sram.rs @@ -1,6 +1,6 @@ // Licensed under the Apache-2.0 license. // -// generated by caliptra_registers_generator with caliptra-rtl repo at ac8e5592b1a6d53f92809c98f8f0144c5a5bf0eb +// generated by caliptra_registers_generator with caliptra-rtl repo at 00730026cdf11841d20a6085ea3909ea3bd4a21b // #![allow(clippy::erasing_op)] #![allow(clippy::identity_op)] diff --git a/hw/latest/registers/src/mldsa.rs b/hw/latest/registers/src/mldsa.rs index 32d0f3ae71..cf14306c9d 100644 --- a/hw/latest/registers/src/mldsa.rs +++ b/hw/latest/registers/src/mldsa.rs @@ -1,6 +1,6 @@ // Licensed under the Apache-2.0 license. // -// generated by caliptra_registers_generator with caliptra-rtl repo at ac8e5592b1a6d53f92809c98f8f0144c5a5bf0eb +// generated by caliptra_registers_generator with caliptra-rtl repo at 00730026cdf11841d20a6085ea3909ea3bd4a21b // #![allow(clippy::erasing_op)] #![allow(clippy::identity_op)] diff --git a/hw/latest/registers/src/pv.rs b/hw/latest/registers/src/pv.rs index 8e72013e4a..03e4b30a13 100644 --- a/hw/latest/registers/src/pv.rs +++ b/hw/latest/registers/src/pv.rs @@ -1,6 +1,6 @@ // Licensed under the Apache-2.0 license. // -// generated by caliptra_registers_generator with caliptra-rtl repo at ac8e5592b1a6d53f92809c98f8f0144c5a5bf0eb +// generated by caliptra_registers_generator with caliptra-rtl repo at 00730026cdf11841d20a6085ea3909ea3bd4a21b // #![allow(clippy::erasing_op)] #![allow(clippy::identity_op)] diff --git a/hw/latest/registers/src/sha256.rs b/hw/latest/registers/src/sha256.rs index c08b9efb19..1b66d53315 100644 --- a/hw/latest/registers/src/sha256.rs +++ b/hw/latest/registers/src/sha256.rs @@ -1,6 +1,6 @@ // Licensed under the Apache-2.0 license. // -// generated by caliptra_registers_generator with caliptra-rtl repo at ac8e5592b1a6d53f92809c98f8f0144c5a5bf0eb +// generated by caliptra_registers_generator with caliptra-rtl repo at 00730026cdf11841d20a6085ea3909ea3bd4a21b // #![allow(clippy::erasing_op)] #![allow(clippy::identity_op)] diff --git a/hw/latest/registers/src/sha512.rs b/hw/latest/registers/src/sha512.rs index 5cb33d0989..3e5dbeeb30 100644 --- a/hw/latest/registers/src/sha512.rs +++ b/hw/latest/registers/src/sha512.rs @@ -1,6 +1,6 @@ // Licensed under the Apache-2.0 license. // -// generated by caliptra_registers_generator with caliptra-rtl repo at ac8e5592b1a6d53f92809c98f8f0144c5a5bf0eb +// generated by caliptra_registers_generator with caliptra-rtl repo at 00730026cdf11841d20a6085ea3909ea3bd4a21b // #![allow(clippy::erasing_op)] #![allow(clippy::identity_op)] diff --git a/hw/latest/registers/src/sha512_acc.rs b/hw/latest/registers/src/sha512_acc.rs index f281b172fb..c63838684c 100644 --- a/hw/latest/registers/src/sha512_acc.rs +++ b/hw/latest/registers/src/sha512_acc.rs @@ -1,6 +1,6 @@ // Licensed under the Apache-2.0 license. // -// generated by caliptra_registers_generator with caliptra-rtl repo at ac8e5592b1a6d53f92809c98f8f0144c5a5bf0eb +// generated by caliptra_registers_generator with caliptra-rtl repo at 00730026cdf11841d20a6085ea3909ea3bd4a21b // #![allow(clippy::erasing_op)] #![allow(clippy::identity_op)] @@ -87,13 +87,13 @@ impl RegisterBlock { ) } } - /// Stores the AXI ID that locked the SHA + /// Stores the AXI USER that locked the SHA /// [br]Caliptra Access: RO /// [br]SOC Access: RO /// /// Read value: [`u32`]; Write value: [`u32`] #[inline(always)] - pub fn id(&self) -> ureg::RegRef { + pub fn user(&self) -> ureg::RegRef { unsafe { ureg::RegRef::new_with_mmio( self.ptr.wrapping_add(4 / core::mem::size_of::()), @@ -1398,7 +1398,7 @@ pub mod meta { crate::sha512_acc::regs::LockReadVal, crate::sha512_acc::regs::LockWriteVal, >; - pub type Id = ureg::ReadOnlyReg32; + pub type User = ureg::ReadOnlyReg32; pub type Mode = ureg::ReadWriteReg32< 0, crate::sha512_acc::regs::ModeReadVal, diff --git a/hw/latest/registers/src/soc_ifc.rs b/hw/latest/registers/src/soc_ifc.rs index 4fc16d4cc8..9bec9d1320 100644 --- a/hw/latest/registers/src/soc_ifc.rs +++ b/hw/latest/registers/src/soc_ifc.rs @@ -1,6 +1,6 @@ // Licensed under the Apache-2.0 license. // -// generated by caliptra_registers_generator with caliptra-rtl repo at ac8e5592b1a6d53f92809c98f8f0144c5a5bf0eb +// generated by caliptra_registers_generator with caliptra-rtl repo at 00730026cdf11841d20a6085ea3909ea3bd4a21b // #![allow(clippy::erasing_op)] #![allow(clippy::identity_op)] @@ -287,16 +287,16 @@ impl RegisterBlock { ) } } - /// Valid AXI ID attributes for requests from SoC AXI Interface. Only valid once LOCK is set. + /// Valid AXI USER attributes for requests from SoC AXI Interface. Only valid once LOCK is set. /// [br]Caliptra Access: RW /// [br]SOC Access: RW - /// Read-Only once locked by AXI_ID_LOCK. + /// Read-Only once locked by AXI_USER_LOCK. /// /// Read value: [`u32`]; Write value: [`u32`] #[inline(always)] - pub fn cptra_mbox_valid_axi_id( + pub fn cptra_mbox_valid_axi_user( &self, - ) -> ureg::Array<5, ureg::RegRef> { + ) -> ureg::Array<5, ureg::RegRef> { unsafe { ureg::Array::new_with_mmio( self.ptr.wrapping_add(0x48 / core::mem::size_of::()), @@ -304,18 +304,18 @@ impl RegisterBlock { ) } } - /// Valid AXI_ID attributes for requests from SoC AXI Interface. - /// [br]Each bit corresponds to locking the associated MBOX_VALID_AXI_ID register. - /// [br]Associated MBOX_VALID_AXI_ID register is only valid once locked by this bit. + /// Valid AXI_USER attributes for requests from SoC AXI Interface. + /// [br]Each bit corresponds to locking the associated MBOX_VALID_AXI_USER register. + /// [br]Associated MBOX_VALID_AXI_USER register is only valid once locked by this bit. /// [br]Caliptra Access: RW /// [br]SOC Access: RW /// [br]Read-Only once locked. /// - /// Read value: [`soc_ifc::regs::CptraXxxxAxiIdLockReadVal`]; Write value: [`soc_ifc::regs::CptraXxxxAxiIdLockWriteVal`] + /// Read value: [`soc_ifc::regs::CptraXxxxAxiUserLockReadVal`]; Write value: [`soc_ifc::regs::CptraXxxxAxiUserLockWriteVal`] #[inline(always)] - pub fn cptra_mbox_axi_id_lock( + pub fn cptra_mbox_axi_user_lock( &self, - ) -> ureg::Array<5, ureg::RegRef> { + ) -> ureg::Array<5, ureg::RegRef> { unsafe { ureg::Array::new_with_mmio( self.ptr.wrapping_add(0x5c / core::mem::size_of::()), @@ -323,16 +323,16 @@ impl RegisterBlock { ) } } - /// Valid AXI ID attributes for TRNG on SoC AXI Interface. Only valid once LOCK is set. + /// Valid AXI USER attributes for TRNG on SoC AXI Interface. Only valid once LOCK is set. /// [br]Caliptra Access: RW /// [br]SOC Access: RW - /// [br]Read-Only once locked by TRNG_AXI_ID_LOCK. + /// [br]Read-Only once locked by TRNG_AXI_USER_LOCK. /// /// Read value: [`u32`]; Write value: [`u32`] #[inline(always)] - pub fn cptra_trng_valid_axi_id( + pub fn cptra_trng_valid_axi_user( &self, - ) -> ureg::RegRef { + ) -> ureg::RegRef { unsafe { ureg::RegRef::new_with_mmio( self.ptr.wrapping_add(0x70 / core::mem::size_of::()), @@ -340,19 +340,19 @@ impl RegisterBlock { ) } } - /// Valid AXI ID attributes for requests from SoC AXI Interface. - /// [br]Each bit corresponds to locking the associated TRNG_VALID_AXI_ID register. - /// [br]Associated TRNG_VALID_AXI_ID register is only valid once locked by this bit. + /// Valid AXI USER attributes for requests from SoC AXI Interface. + /// [br]Each bit corresponds to locking the associated TRNG_VALID_AXI_USER register. + /// [br]Associated TRNG_VALID_AXI_USER register is only valid once locked by this bit. /// [br]Caliptra FW RW access for survivability but cannot unlock once locked /// [br]Caliptra Access: RW /// [br]SOC Access: RW /// [br]Read-Only once locked. /// - /// Read value: [`soc_ifc::regs::CptraXxxxAxiIdLockReadVal`]; Write value: [`soc_ifc::regs::CptraXxxxAxiIdLockWriteVal`] + /// Read value: [`soc_ifc::regs::CptraXxxxAxiUserLockReadVal`]; Write value: [`soc_ifc::regs::CptraXxxxAxiUserLockWriteVal`] #[inline(always)] - pub fn cptra_trng_axi_id_lock( + pub fn cptra_trng_axi_user_lock( &self, - ) -> ureg::RegRef { + ) -> ureg::RegRef { unsafe { ureg::RegRef::new_with_mmio( self.ptr.wrapping_add(0x74 / core::mem::size_of::()), @@ -652,16 +652,16 @@ impl RegisterBlock { ) } } - /// Valid AXI ID attributes for FUSE on SoC AXI Interface. Only valid once LOCK is set. + /// Valid AXI USER attributes for FUSE on SoC AXI Interface. Only valid once LOCK is set. /// [br]Caliptra Access: RW /// [br]SOC Access: RW - /// [br]Read-Only once locked by FUSE_AXI_ID_LOCK. + /// [br]Read-Only once locked by FUSE_AXI_USER_LOCK. /// /// Read value: [`u32`]; Write value: [`u32`] #[inline(always)] - pub fn cptra_fuse_valid_axi_id( + pub fn cptra_fuse_valid_axi_user( &self, - ) -> ureg::RegRef { + ) -> ureg::RegRef { unsafe { ureg::RegRef::new_with_mmio( self.ptr.wrapping_add(0x108 / core::mem::size_of::()), @@ -669,19 +669,19 @@ impl RegisterBlock { ) } } - /// Valid AXI_ID attributes for requests from SoC AXI Interface. - /// [br]Each bit corresponds to locking the associated FUSE_VALID_AXI_ID register. - /// [br]Associated FUSE_VALID_AXI_ID register is only valid once locked by this bit. + /// Valid AXI_USER attributes for requests from SoC AXI Interface. + /// [br]Each bit corresponds to locking the associated FUSE_VALID_AXI_USER register. + /// [br]Associated FUSE_VALID_AXI_USER register is only valid once locked by this bit. /// [br]Caliptra FW RW access for survivability but cannot unlock once locked /// [br]Caliptra Access: RW /// [br]SOC Access: RW /// [br]Read-Only once locked. /// - /// Read value: [`soc_ifc::regs::CptraXxxxAxiIdLockReadVal`]; Write value: [`soc_ifc::regs::CptraXxxxAxiIdLockWriteVal`] + /// Read value: [`soc_ifc::regs::CptraXxxxAxiUserLockReadVal`]; Write value: [`soc_ifc::regs::CptraXxxxAxiUserLockWriteVal`] #[inline(always)] - pub fn cptra_fuse_axi_id_lock( + pub fn cptra_fuse_axi_user_lock( &self, - ) -> ureg::RegRef { + ) -> ureg::RegRef { unsafe { ureg::RegRef::new_with_mmio( self.ptr.wrapping_add(0x10c / core::mem::size_of::()), @@ -753,6 +753,88 @@ impl RegisterBlock { ) } } + /// Caliptra HW Capabilities. Initialized with reset values, rewritable by Caliptra firmware. + /// [br]Caliptra Access: RW + /// [br]SOC Access: RO + /// [br]Read-only once locked. + /// + /// Read value: [`u32`]; Write value: [`u32`] + #[inline(always)] + pub fn cptra_hw_capabilities( + &self, + ) -> ureg::RegRef { + unsafe { + ureg::RegRef::new_with_mmio( + self.ptr.wrapping_add(0x128 / core::mem::size_of::()), + core::borrow::Borrow::borrow(&self.mmio), + ) + } + } + /// Caliptra FW Capabilities. Initialized with reset values, rewritable by Caliptra firmware. + /// [br]Caliptra Access: RW + /// [br]SOC Access: RO + /// [br]Read-only once locked. + /// + /// Read value: [`u32`]; Write value: [`u32`] + #[inline(always)] + pub fn cptra_fw_capabilities( + &self, + ) -> ureg::RegRef { + unsafe { + ureg::RegRef::new_with_mmio( + self.ptr.wrapping_add(0x12c / core::mem::size_of::()), + core::borrow::Borrow::borrow(&self.mmio), + ) + } + } + /// Lock register to disable further firmware modifications to capabilities registers. + /// [br]Once set, this register may not be cleared until a warm reset. If set, the values in CPTRA_HW_CAPABILITIES and CPTRA_FW_CAPABILITIES may not be modified. + /// [br]Caliptra Access: RW + /// [br]SOC Access: RO + /// [br]Read-only once locked. + /// + /// Read value: [`soc_ifc::regs::CptraXxxxxxxkReadVal`]; Write value: [`soc_ifc::regs::CptraXxxxxxxkWriteVal`] + #[inline(always)] + pub fn cptra_cap_lock(&self) -> ureg::RegRef { + unsafe { + ureg::RegRef::new_with_mmio( + self.ptr.wrapping_add(0x130 / core::mem::size_of::()), + core::borrow::Borrow::borrow(&self.mmio), + ) + } + } + /// Owner PK hash lockable register. + /// [br]Caliptra Access: RO + /// [br]SOC Access: RWL-S + /// + /// Read value: [`u32`]; Write value: [`u32`] + #[inline(always)] + pub fn cptra_owner_pk_hash( + &self, + ) -> ureg::Array<12, ureg::RegRef> { + unsafe { + ureg::Array::new_with_mmio( + self.ptr.wrapping_add(0x140 / core::mem::size_of::()), + core::borrow::Borrow::borrow(&self.mmio), + ) + } + } + /// Owner PK hash register lock. Locks further writes to Owner PK hash register. Reset only by power cycle. + /// [br]Caliptra Access: RO + /// [br]SOC Access: RW1-S + /// + /// Read value: [`soc_ifc::regs::CptraXxxxxxxkReadVal`]; Write value: [`soc_ifc::regs::CptraXxxxxxxkWriteVal`] + #[inline(always)] + pub fn cptra_owner_pk_hash_lock( + &self, + ) -> ureg::RegRef { + unsafe { + ureg::RegRef::new_with_mmio( + self.ptr.wrapping_add(0x170 / core::mem::size_of::()), + core::borrow::Borrow::borrow(&self.mmio), + ) + } + } /// Obfuscated UDS. /// [br]Caliptra Access: - /// [br]SOC Access: WL-S @@ -761,7 +843,7 @@ impl RegisterBlock { #[inline(always)] pub fn fuse_uds_seed( &self, - ) -> ureg::Array<12, ureg::RegRef> { + ) -> ureg::Array<16, ureg::RegRef> { unsafe { ureg::Array::new_with_mmio( self.ptr.wrapping_add(0x200 / core::mem::size_of::()), @@ -780,7 +862,7 @@ impl RegisterBlock { ) -> ureg::Array<8, ureg::RegRef> { unsafe { ureg::Array::new_with_mmio( - self.ptr.wrapping_add(0x230 / core::mem::size_of::()), + self.ptr.wrapping_add(0x240 / core::mem::size_of::()), core::borrow::Borrow::borrow(&self.mmio), ) } @@ -796,39 +878,23 @@ impl RegisterBlock { ) -> ureg::Array<12, ureg::RegRef> { unsafe { ureg::Array::new_with_mmio( - self.ptr.wrapping_add(0x250 / core::mem::size_of::()), + self.ptr.wrapping_add(0x260 / core::mem::size_of::()), core::borrow::Borrow::borrow(&self.mmio), ) } } - /// Key Manifest Mask Fuse. - /// [br]Caliptra Access: RO - /// [br]SOC Access: RWL-S - /// - /// Read value: [`soc_ifc::regs::FuseKeyManifestPkHashMaskReadVal`]; Write value: [`soc_ifc::regs::FuseKeyManifestPkHashMaskWriteVal`] - #[inline(always)] - pub fn fuse_key_manifest_pk_hash_mask( - &self, - ) -> ureg::RegRef { - unsafe { - ureg::RegRef::new_with_mmio( - self.ptr.wrapping_add(0x280 / core::mem::size_of::()), - core::borrow::Borrow::borrow(&self.mmio), - ) - } - } - /// Owner PK hash Fuse. + /// Key Manifest Mask Fuse (ECC Revocation). /// [br]Caliptra Access: RO /// [br]SOC Access: RWL-S /// /// Read value: [`u32`]; Write value: [`u32`] #[inline(always)] - pub fn fuse_owner_pk_hash( + pub fn fuse_key_manifest_pk_hash_mask( &self, - ) -> ureg::Array<12, ureg::RegRef> { + ) -> ureg::Array<8, ureg::RegRef> { unsafe { ureg::Array::new_with_mmio( - self.ptr.wrapping_add(0x284 / core::mem::size_of::()), + self.ptr.wrapping_add(0x290 / core::mem::size_of::()), core::borrow::Borrow::borrow(&self.mmio), ) } @@ -913,62 +979,381 @@ impl RegisterBlock { ) } } - /// Caliptra Boot Media Integrated mode usage only. SOCs that build with a Boot Media Independent profile don’t have to account for these fuses. + /// One-hot encoded list of revoked Vendor LMS Public Keys (up to 32 keys) /// [br]Caliptra Access: RO /// [br]SOC Access: RWL-S /// - /// Read value: [`soc_ifc::regs::FuseLifeCycleReadVal`]; Write value: [`soc_ifc::regs::FuseLifeCycleWriteVal`] + /// Read value: [`u32`]; Write value: [`u32`] #[inline(always)] - pub fn fuse_life_cycle(&self) -> ureg::RegRef { + pub fn fuse_lms_revocation( + &self, + ) -> ureg::RegRef { unsafe { ureg::RegRef::new_with_mmio( - self.ptr.wrapping_add(0x33c / core::mem::size_of::()), + self.ptr.wrapping_add(0x340 / core::mem::size_of::()), core::borrow::Borrow::borrow(&self.mmio), ) } } - /// 0 - Verify Caliptra firmware images with ECDSA-only; 1 - Verify Caliptra firmware images with both ECDSA and LMS + /// One-hot encoded list of revoked Vendor MLDSA Public Keys (up to 4 keys) /// [br]Caliptra Access: RO /// [br]SOC Access: RWL-S /// - /// Read value: [`soc_ifc::regs::FuseLmsVerifyReadVal`]; Write value: [`soc_ifc::regs::FuseLmsVerifyWriteVal`] + /// Read value: [`soc_ifc::regs::FuseMldsaRevocationReadVal`]; Write value: [`soc_ifc::regs::FuseMldsaRevocationWriteVal`] #[inline(always)] - pub fn fuse_lms_verify(&self) -> ureg::RegRef { + pub fn fuse_mldsa_revocation( + &self, + ) -> ureg::RegRef { unsafe { ureg::RegRef::new_with_mmio( - self.ptr.wrapping_add(0x340 / core::mem::size_of::()), + self.ptr.wrapping_add(0x344 / core::mem::size_of::()), core::borrow::Borrow::borrow(&self.mmio), ) } } - /// Bits for revoking LMS public keys in the key manifest + /// SOC stepping ID + /// [br]Caliptra Access: RO + /// [br]SOC Access: RWL-S + /// + /// Read value: [`soc_ifc::regs::FuseSocSteppingIdReadVal`]; Write value: [`soc_ifc::regs::FuseSocSteppingIdWriteVal`] + #[inline(always)] + pub fn fuse_soc_stepping_id( + &self, + ) -> ureg::RegRef { + unsafe { + ureg::RegRef::new_with_mmio( + self.ptr.wrapping_add(0x348 / core::mem::size_of::()), + core::borrow::Borrow::borrow(&self.mmio), + ) + } + } + /// Manufacturing debug unlock token /// [br]Caliptra Access: RO /// [br]SOC Access: RWL-S /// /// Read value: [`u32`]; Write value: [`u32`] #[inline(always)] - pub fn fuse_lms_revocation( + pub fn fuse_manuf_dbg_unlock_token( &self, - ) -> ureg::RegRef { + ) -> ureg::Array<4, ureg::RegRef> { + unsafe { + ureg::Array::new_with_mmio( + self.ptr.wrapping_add(0x34c / core::mem::size_of::()), + core::borrow::Borrow::borrow(&self.mmio), + ) + } + } + /// Subsystem Caliptra Base Address Lower 32 bits (from AXI). + /// [br]Indicates base address of Caliptra register set from AXI fabric. + /// [br]Strap that is initialized from Caliptra input port at cptra_pwrgood deassertion. May be overwritten by SoC prior to CPTRA_FUSE_WR_DONE. Locked by CPTRA_FUSE_WR_DONE. + /// [br]Caliptra Access: RO + /// [br]SOC Access: RWL-S + /// + /// Read value: [`u32`]; Write value: [`u32`] + #[inline(always)] + pub fn ss_caliptra_base_addr_l( + &self, + ) -> ureg::RegRef { unsafe { ureg::RegRef::new_with_mmio( - self.ptr.wrapping_add(0x344 / core::mem::size_of::()), + self.ptr.wrapping_add(0x500 / core::mem::size_of::()), core::borrow::Borrow::borrow(&self.mmio), ) } } - /// SOC stepping ID + /// Subsystem Caliptra Base Address Upper 32 bits (from AXI). + /// [br]Indicates base address of Caliptra register set from AXI fabric. + /// [br]Strap that is initialized from Caliptra input port at cptra_pwrgood deassertion. May be overwritten by SoC prior to CPTRA_FUSE_WR_DONE. Locked by CPTRA_FUSE_WR_DONE. /// [br]Caliptra Access: RO /// [br]SOC Access: RWL-S /// - /// Read value: [`soc_ifc::regs::FuseSocSteppingIdReadVal`]; Write value: [`soc_ifc::regs::FuseSocSteppingIdWriteVal`] + /// Read value: [`u32`]; Write value: [`u32`] #[inline(always)] - pub fn fuse_soc_stepping_id( + pub fn ss_caliptra_base_addr_h( &self, - ) -> ureg::RegRef { + ) -> ureg::RegRef { unsafe { ureg::RegRef::new_with_mmio( - self.ptr.wrapping_add(0x348 / core::mem::size_of::()), + self.ptr.wrapping_add(0x504 / core::mem::size_of::()), + core::borrow::Borrow::borrow(&self.mmio), + ) + } + } + /// Subsystem MCI Base Address Lower 32 bits (from AXI). + /// [br]Indicates base address of MCI register set from AXI fabric. + /// [br]Strap that is initialized from Caliptra input port at cptra_pwrgood deassertion. May be overwritten by SoC prior to CPTRA_FUSE_WR_DONE. Locked by CPTRA_FUSE_WR_DONE. + /// [br]Caliptra Access: RO + /// [br]SOC Access: RWL-S + /// + /// Read value: [`u32`]; Write value: [`u32`] + #[inline(always)] + pub fn ss_mci_base_addr_l(&self) -> ureg::RegRef { + unsafe { + ureg::RegRef::new_with_mmio( + self.ptr.wrapping_add(0x508 / core::mem::size_of::()), + core::borrow::Borrow::borrow(&self.mmio), + ) + } + } + /// Subsystem MCI Base Address Upper 32 bits (from AXI). + /// [br]Indicates base address of MCI register set from AXI fabric. + /// [br]Strap that is initialized from Caliptra input port at cptra_pwrgood deassertion. May be overwritten by SoC prior to CPTRA_FUSE_WR_DONE. Locked by CPTRA_FUSE_WR_DONE. + /// [br]Caliptra Access: RO + /// [br]SOC Access: RWL-S + /// + /// Read value: [`u32`]; Write value: [`u32`] + #[inline(always)] + pub fn ss_mci_base_addr_h(&self) -> ureg::RegRef { + unsafe { + ureg::RegRef::new_with_mmio( + self.ptr.wrapping_add(0x50c / core::mem::size_of::()), + core::borrow::Borrow::borrow(&self.mmio), + ) + } + } + /// Subsystem Recovery Interface Base Address Lower 32 bits (from AXI). + /// [br]Indicates base address of OCP Recovery Interface register set from AXI fabric. + /// [br]Strap that is initialized from Caliptra input port at cptra_pwrgood deassertion. May be overwritten by SoC prior to CPTRA_FUSE_WR_DONE. Locked by CPTRA_FUSE_WR_DONE. + /// [br]Caliptra Access: RO + /// [br]SOC Access: RWL-S + /// + /// Read value: [`u32`]; Write value: [`u32`] + #[inline(always)] + pub fn ss_recovery_ifc_base_addr_l( + &self, + ) -> ureg::RegRef { + unsafe { + ureg::RegRef::new_with_mmio( + self.ptr.wrapping_add(0x510 / core::mem::size_of::()), + core::borrow::Borrow::borrow(&self.mmio), + ) + } + } + /// Subsystem Recovery Interface Base Address Upper 32 bits (from AXI). + /// [br]Indicates base address of OCP Recovery Interface register set from AXI fabric. + /// [br]Strap that is initialized from Caliptra input port at cptra_pwrgood deassertion. May be overwritten by SoC prior to CPTRA_FUSE_WR_DONE. Locked by CPTRA_FUSE_WR_DONE. + /// [br]Caliptra Access: RO + /// [br]SOC Access: RWL-S + /// + /// Read value: [`u32`]; Write value: [`u32`] + #[inline(always)] + pub fn ss_recovery_ifc_base_addr_h( + &self, + ) -> ureg::RegRef { + unsafe { + ureg::RegRef::new_with_mmio( + self.ptr.wrapping_add(0x514 / core::mem::size_of::()), + core::borrow::Borrow::borrow(&self.mmio), + ) + } + } + /// Subsystem Fuse Controller Base Address Lower 32 bits (from AXI). + /// [br]Indicates base address of OTP Fuse Controller from AXI fabric. + /// [br]Strap that is initialized from Caliptra input port at cptra_pwrgood deassertion. May be overwritten by SoC prior to CPTRA_FUSE_WR_DONE. Locked by CPTRA_FUSE_WR_DONE. + /// [br]Caliptra Access: RO + /// [br]SOC Access: RWL-S + /// + /// Read value: [`u32`]; Write value: [`u32`] + #[inline(always)] + pub fn ss_otp_fc_base_addr_l( + &self, + ) -> ureg::RegRef { + unsafe { + ureg::RegRef::new_with_mmio( + self.ptr.wrapping_add(0x518 / core::mem::size_of::()), + core::borrow::Borrow::borrow(&self.mmio), + ) + } + } + /// Subsystem Fuse Controller Base Address Upper 32 bits (from AXI). + /// [br]Indicates base address of OTP Fuse Controller from AXI fabric. + /// [br]Strap that is initialized from Caliptra input port at cptra_pwrgood deassertion. May be overwritten by SoC prior to CPTRA_FUSE_WR_DONE. Locked by CPTRA_FUSE_WR_DONE. + /// [br]Caliptra Access: RO + /// [br]SOC Access: RWL-S + /// + /// Read value: [`u32`]; Write value: [`u32`] + #[inline(always)] + pub fn ss_otp_fc_base_addr_h( + &self, + ) -> ureg::RegRef { + unsafe { + ureg::RegRef::new_with_mmio( + self.ptr.wrapping_add(0x51c / core::mem::size_of::()), + core::borrow::Borrow::borrow(&self.mmio), + ) + } + } + /// Subsystem UDS Seed Destination Base Address Lower 32 bits (from AXI). Used as the write address when programming the UDS seed during manufacturing. + /// [br]Strap that is initialized from Caliptra input port at cptra_pwrgood deassertion. May be overwritten by SoC prior to CPTRA_FUSE_WR_DONE. Locked by CPTRA_FUSE_WR_DONE. + /// [br]Caliptra Access: RO + /// [br]SOC Access: RWL-S + /// + /// Read value: [`u32`]; Write value: [`u32`] + #[inline(always)] + pub fn ss_uds_seed_base_addr_l( + &self, + ) -> ureg::RegRef { + unsafe { + ureg::RegRef::new_with_mmio( + self.ptr.wrapping_add(0x520 / core::mem::size_of::()), + core::borrow::Borrow::borrow(&self.mmio), + ) + } + } + /// Subsystem UDS Seed Destination Base Address Upper 32 bits (from AXI). Used as the write address when programming the UDS seed during manufacturing. + /// [br]Strap that is initialized from Caliptra input port at cptra_pwrgood deassertion. May be overwritten by SoC prior to CPTRA_FUSE_WR_DONE. Locked by CPTRA_FUSE_WR_DONE. + /// [br]Caliptra Access: RO + /// [br]SOC Access: RWL-S + /// + /// Read value: [`u32`]; Write value: [`u32`] + #[inline(always)] + pub fn ss_uds_seed_base_addr_h( + &self, + ) -> ureg::RegRef { + unsafe { + ureg::RegRef::new_with_mmio( + self.ptr.wrapping_add(0x524 / core::mem::size_of::()), + core::borrow::Borrow::borrow(&self.mmio), + ) + } + } + /// Provides an offset in the destination register bank at which a set of Public Key Hashes may be found. The number of hashes available at this offset is indicated by + /// SS_NUM_OF_PROD_DEBUG_UNLOCK_AUTH_PK_HASHES. + /// [br]Strap that is initialized from Caliptra input port at cptra_pwrgood deassertion. May be overwritten by SoC prior to CPTRA_FUSE_WR_DONE. Locked by CPTRA_FUSE_WR_DONE. + /// [br]Caliptra Access: RO + /// [br]SOC Access: RWL-S + /// + /// Read value: [`u32`]; Write value: [`u32`] + #[inline(always)] + pub fn ss_prod_debug_unlock_auth_pk_hash_reg_bank_offset( + &self, + ) -> ureg::RegRef { + unsafe { + ureg::RegRef::new_with_mmio( + self.ptr.wrapping_add(0x528 / core::mem::size_of::()), + core::borrow::Borrow::borrow(&self.mmio), + ) + } + } + /// Provides the number of Public Key Hashes that may be found at the offset in the destination register bank, specified in SS_PROD_DEBUG_UNLOCK_AUTH_PK_HASH_REG_BANK_OFFSET. + /// [br]Strap that is initialized from Caliptra input port at cptra_pwrgood deassertion. May be overwritten by SoC prior to CPTRA_FUSE_WR_DONE. Locked by CPTRA_FUSE_WR_DONE. + /// [br]Caliptra Access: RO + /// [br]SOC Access: RWL-S + /// + /// Read value: [`u32`]; Write value: [`u32`] + #[inline(always)] + pub fn ss_num_of_prod_debug_unlock_auth_pk_hashes( + &self, + ) -> ureg::RegRef { + unsafe { + ureg::RegRef::new_with_mmio( + self.ptr.wrapping_add(0x52c / core::mem::size_of::()), + core::borrow::Borrow::borrow(&self.mmio), + ) + } + } + /// Strap from SoC in Subsystem configuration that indicates if this boot cycle will be used for debug. In passive mode this register always reflects a value of 0. + /// [br]Caliptra Access: RO + /// [br]SOC Access: RO + /// [br]TAP Access [in debug/manuf mode]: RW + /// + /// Read value: [`soc_ifc::regs::SsDebugIntentReadVal`]; Write value: [`soc_ifc::regs::SsDebugIntentWriteVal`] + #[inline(always)] + pub fn ss_debug_intent(&self) -> ureg::RegRef { + unsafe { + ureg::RegRef::new_with_mmio( + self.ptr.wrapping_add(0x530 / core::mem::size_of::()), + core::borrow::Borrow::borrow(&self.mmio), + ) + } + } + /// Straps reserved for late-binding features for survivability. + /// [br]Strap that is initialized from Caliptra input port at cptra_pwrgood deassertion. May be overwritten by SoC prior to CPTRA_FUSE_WR_DONE. Locked by CPTRA_FUSE_WR_DONE. + /// [br]Caliptra Access: RO + /// [br]SOC Access: RWL-S + /// + /// Read value: [`u32`]; Write value: [`u32`] + #[inline(always)] + pub fn ss_strap_generic( + &self, + ) -> ureg::Array<4, ureg::RegRef> { + unsafe { + ureg::Array::new_with_mmio( + self.ptr.wrapping_add(0x5a0 / core::mem::size_of::()), + core::borrow::Borrow::borrow(&self.mmio), + ) + } + } + /// JTAG in debug/manuf mode or SOC can write to this register for ROM/FW defined skips or services. + /// [br]This register is used to support Subsystem flows, and is disabled in Caliptra passive mode. + /// [br]Caliptra Access: RW + /// [br]SOC Access: RW + /// [br]TAP Access [in debug/manuf mode]: RW + /// + /// Read value: [`soc_ifc::regs::SsDbgManufServiceRegReqReadVal`]; Write value: [`soc_ifc::regs::SsDbgManufServiceRegReqWriteVal`] + #[inline(always)] + pub fn ss_dbg_manuf_service_reg_req( + &self, + ) -> ureg::RegRef { + unsafe { + ureg::RegRef::new_with_mmio( + self.ptr.wrapping_add(0x5c0 / core::mem::size_of::()), + core::borrow::Borrow::borrow(&self.mmio), + ) + } + } + /// JTAG in debug/manuf mode or SOC can read from this register for ROM/FW defined skips or services. + /// [br]This register is used to support Subsystem flows, and is disabled in Caliptra passive mode. + /// [br]Caliptra Access: RW + /// [br]SOC Access: RO + /// [br]TAP Access [in debug/manuf mode]: RO + /// + /// Read value: [`soc_ifc::regs::SsDbgManufServiceRegRspReadVal`]; Write value: [`soc_ifc::regs::SsDbgManufServiceRegRspWriteVal`] + #[inline(always)] + pub fn ss_dbg_manuf_service_reg_rsp( + &self, + ) -> ureg::RegRef { + unsafe { + ureg::RegRef::new_with_mmio( + self.ptr.wrapping_add(0x5c4 / core::mem::size_of::()), + core::borrow::Borrow::borrow(&self.mmio), + ) + } + } + /// Individual bits indicating debug unlock level to multiple SoC endpoints. Writable only for Caliptra, and only when DEBUG_INTENT is set to 1. + /// [br]This register is used to support Subsystem flows, and is disabled in Caliptra passive mode. + /// [br]Caliptra Access: RW + /// [br]SOC Access: RO + /// [br]TAP Access [in debug/manuf mode]: RO + /// + /// Read value: [`u32`]; Write value: [`u32`] + #[inline(always)] + pub fn ss_soc_dbg_unlock_level( + &self, + ) -> ureg::Array<2, ureg::RegRef> { + unsafe { + ureg::Array::new_with_mmio( + self.ptr.wrapping_add(0x5c8 / core::mem::size_of::()), + core::borrow::Borrow::borrow(&self.mmio), + ) + } + } + /// Each bit may be optionally routed to a unique SoC core that requires a hardware enforced execution enablement. + /// For example, this bit may be used to block execution access to an instruction memory containing firmware updates. + /// Bits 0/1 are reserved. Bit 2 controls the MCU from the Caliptra Subsystem. All other bits are integrator-defined. + /// [br]These bits are only writable for Caliptra firmware. + /// [br]Caliptra Access: RW + /// [br]SOC Access: RO + /// [br]TAP Access [in debug/manuf mode]: RO + /// + /// Read value: [`u32`]; Write value: [`u32`] + #[inline(always)] + pub fn ss_generic_fw_exec_ctrl( + &self, + ) -> ureg::Array<4, ureg::RegRef> { + unsafe { + ureg::Array::new_with_mmio( + self.ptr.wrapping_add(0x5d0 / core::mem::size_of::()), core::borrow::Borrow::borrow(&self.mmio), ) } @@ -2095,9 +2480,9 @@ pub mod regs { pub fn boot_fsm_ps(&self) -> u32 { (self.0 >> 25) & 7 } - /// Indicates Caliptra is ready for Firmware Download + /// Indicates Caliptra is ready for Mailbox operations #[inline(always)] - pub fn ready_for_fw(&self) -> bool { + pub fn ready_for_mb_processing(&self) -> bool { ((self.0 >> 28) & 1) != 0 } /// Indicates Caliptra is ready for RT flows @@ -2147,9 +2532,9 @@ pub mod regs { pub fn idevid_csr_ready(self, val: bool) -> Self { Self((self.0 & !(1 << 24)) | (u32::from(val) << 24)) } - /// Indicates Caliptra is ready for Firmware Download + /// Indicates Caliptra is ready for Mailbox operations #[inline(always)] - pub fn ready_for_fw(self, val: bool) -> Self { + pub fn ready_for_mb_processing(self, val: bool) -> Self { Self((self.0 & !(1 << 28)) | (u32::from(val) << 28)) } /// Indicates Caliptra is ready for RT flows @@ -2232,23 +2617,18 @@ pub mod regs { } /// #[inline(always)] - pub fn qspi_en(&self) -> bool { - ((self.0 >> 1) & 1) != 0 - } - /// - #[inline(always)] - pub fn i3c_en(&self) -> bool { - ((self.0 >> 2) & 1) != 0 + pub fn rsvd_en(&self) -> u32 { + (self.0 >> 1) & 7 } /// #[inline(always)] - pub fn uart_en(&self) -> bool { - ((self.0 >> 3) & 1) != 0 + pub fn lms_acc_en(&self) -> bool { + ((self.0 >> 4) & 1) != 0 } /// #[inline(always)] - pub fn lms_acc_en(&self) -> bool { - ((self.0 >> 4) & 1) != 0 + pub fn active_mode_en(&self) -> bool { + ((self.0 >> 5) & 1) != 0 } } impl From for CptraHwConfigReadVal { @@ -2286,6 +2666,11 @@ pub mod regs { pub fn crypto_err(&self) -> bool { ((self.0 >> 3) & 1) != 0 } + /// + #[inline(always)] + pub fn rsvd(&self) -> u32 { + (self.0 >> 4) & 0xfffffff + } /// Construct a WriteVal that can be used to modify the contents of this register value. #[inline(always)] pub fn modify(self) -> CptraHwErrorFatalWriteVal { @@ -2358,6 +2743,11 @@ pub mod regs { pub fn mbox_ecc_unc(&self) -> bool { ((self.0 >> 2) & 1) != 0 } + /// + #[inline(always)] + pub fn rsvd(&self) -> u32 { + (self.0 >> 3) & 0x1fffffff + } /// Construct a WriteVal that can be used to modify the contents of this register value. #[inline(always)] pub fn modify(self) -> CptraHwErrorNonFatalWriteVal { @@ -2796,8 +3186,55 @@ pub mod regs { } } #[derive(Clone, Copy)] - pub struct CptraXxxxAxiIdLockReadVal(u32); - impl CptraXxxxAxiIdLockReadVal { + pub struct CptraXxxxxxxkReadVal(u32); + impl CptraXxxxxxxkReadVal { + /// + #[inline(always)] + pub fn lock(&self) -> bool { + ((self.0 >> 0) & 1) != 0 + } + /// Construct a WriteVal that can be used to modify the contents of this register value. + #[inline(always)] + pub fn modify(self) -> CptraXxxxxxxkWriteVal { + CptraXxxxxxxkWriteVal(self.0) + } + } + impl From for CptraXxxxxxxkReadVal { + #[inline(always)] + fn from(val: u32) -> Self { + Self(val) + } + } + impl From for u32 { + #[inline(always)] + fn from(val: CptraXxxxxxxkReadVal) -> u32 { + val.0 + } + } + #[derive(Clone, Copy)] + pub struct CptraXxxxxxxkWriteVal(u32); + impl CptraXxxxxxxkWriteVal { + /// + #[inline(always)] + pub fn lock(self, val: bool) -> Self { + Self((self.0 & !(1 << 0)) | (u32::from(val) << 0)) + } + } + impl From for CptraXxxxxxxkWriteVal { + #[inline(always)] + fn from(val: u32) -> Self { + Self(val) + } + } + impl From for u32 { + #[inline(always)] + fn from(val: CptraXxxxxxxkWriteVal) -> u32 { + val.0 + } + } + #[derive(Clone, Copy)] + pub struct CptraXxxxAxiUserLockReadVal(u32); + impl CptraXxxxAxiUserLockReadVal { /// #[inline(always)] pub fn lock(&self) -> bool { @@ -2805,40 +3242,40 @@ pub mod regs { } /// Construct a WriteVal that can be used to modify the contents of this register value. #[inline(always)] - pub fn modify(self) -> CptraXxxxAxiIdLockWriteVal { - CptraXxxxAxiIdLockWriteVal(self.0) + pub fn modify(self) -> CptraXxxxAxiUserLockWriteVal { + CptraXxxxAxiUserLockWriteVal(self.0) } } - impl From for CptraXxxxAxiIdLockReadVal { + impl From for CptraXxxxAxiUserLockReadVal { #[inline(always)] fn from(val: u32) -> Self { Self(val) } } - impl From for u32 { + impl From for u32 { #[inline(always)] - fn from(val: CptraXxxxAxiIdLockReadVal) -> u32 { + fn from(val: CptraXxxxAxiUserLockReadVal) -> u32 { val.0 } } #[derive(Clone, Copy)] - pub struct CptraXxxxAxiIdLockWriteVal(u32); - impl CptraXxxxAxiIdLockWriteVal { + pub struct CptraXxxxAxiUserLockWriteVal(u32); + impl CptraXxxxAxiUserLockWriteVal { /// #[inline(always)] pub fn lock(self, val: bool) -> Self { Self((self.0 & !(1 << 0)) | (u32::from(val) << 0)) } } - impl From for CptraXxxxAxiIdLockWriteVal { + impl From for CptraXxxxAxiUserLockWriteVal { #[inline(always)] fn from(val: u32) -> Self { Self(val) } } - impl From for u32 { + impl From for u32 { #[inline(always)] - fn from(val: CptraXxxxAxiIdLockWriteVal) -> u32 { + fn from(val: CptraXxxxAxiUserLockWriteVal) -> u32 { val.0 } } @@ -2957,6 +3394,231 @@ pub mod regs { } } #[derive(Clone, Copy)] + pub struct SsDbgManufServiceRegReqReadVal(u32); + impl SsDbgManufServiceRegReqReadVal { + /// Manufacturing debug unlock request. Only writable when lifecycle state is MANUFACTURING and DEBUG_INTENT strap is set to 1. + #[inline(always)] + pub fn manuf_dbg_unlock_req(&self) -> bool { + ((self.0 >> 0) & 1) != 0 + } + /// Production debug unlock request. Only writable when lifecycle state is PRODUCTION and DEBUG_INTENT strap is set to 1. + #[inline(always)] + pub fn prod_dbg_unlock_req(&self) -> bool { + ((self.0 >> 1) & 1) != 0 + } + /// UDS programming request. + #[inline(always)] + pub fn uds_program_req(&self) -> bool { + ((self.0 >> 2) & 1) != 0 + } + /// RSVD + #[inline(always)] + pub fn rsvd(&self) -> u32 { + (self.0 >> 3) & 0x1fffffff + } + /// Construct a WriteVal that can be used to modify the contents of this register value. + #[inline(always)] + pub fn modify(self) -> SsDbgManufServiceRegReqWriteVal { + SsDbgManufServiceRegReqWriteVal(self.0) + } + } + impl From for SsDbgManufServiceRegReqReadVal { + #[inline(always)] + fn from(val: u32) -> Self { + Self(val) + } + } + impl From for u32 { + #[inline(always)] + fn from(val: SsDbgManufServiceRegReqReadVal) -> u32 { + val.0 + } + } + #[derive(Clone, Copy)] + pub struct SsDbgManufServiceRegReqWriteVal(u32); + impl SsDbgManufServiceRegReqWriteVal { + /// Manufacturing debug unlock request. Only writable when lifecycle state is MANUFACTURING and DEBUG_INTENT strap is set to 1. + #[inline(always)] + pub fn manuf_dbg_unlock_req(self, val: bool) -> Self { + Self((self.0 & !(1 << 0)) | (u32::from(val) << 0)) + } + /// Production debug unlock request. Only writable when lifecycle state is PRODUCTION and DEBUG_INTENT strap is set to 1. + #[inline(always)] + pub fn prod_dbg_unlock_req(self, val: bool) -> Self { + Self((self.0 & !(1 << 1)) | (u32::from(val) << 1)) + } + /// UDS programming request. + #[inline(always)] + pub fn uds_program_req(self, val: bool) -> Self { + Self((self.0 & !(1 << 2)) | (u32::from(val) << 2)) + } + } + impl From for SsDbgManufServiceRegReqWriteVal { + #[inline(always)] + fn from(val: u32) -> Self { + Self(val) + } + } + impl From for u32 { + #[inline(always)] + fn from(val: SsDbgManufServiceRegReqWriteVal) -> u32 { + val.0 + } + } + #[derive(Clone, Copy)] + pub struct SsDbgManufServiceRegRspReadVal(u32); + impl SsDbgManufServiceRegRspReadVal { + /// Manufacturing debug unlock was successful. Only writable by Caliptra, and only when lifecycle state is MANUFACTURING and DEBUG_INTENT strap is set to 1. Sticky once set, until warm reset. + #[inline(always)] + pub fn manuf_dbg_unlock_success(&self) -> bool { + ((self.0 >> 0) & 1) != 0 + } + /// Manufacturing debug unlock failed. Only writable by Caliptra, and only when lifecycle state is MANUFACTURING and DEBUG_INTENT strap is set to 1. + #[inline(always)] + pub fn manuf_dbg_unlock_fail(&self) -> bool { + ((self.0 >> 1) & 1) != 0 + } + /// Manufacturing debug unlock is in progress. Only writable by Caliptra, and only when lifecycle state is MANUFACTURING and DEBUG_INTENT strap is set to 1. + #[inline(always)] + pub fn manuf_dbg_unlock_in_progress(&self) -> bool { + ((self.0 >> 2) & 1) != 0 + } + /// Production debug unlock was successful. Only writable by Caliptra, and only when lifecycle state is PRODUCTION and DEBUG_INTENT strap is set to 1. Sticky once set, until warm reset. + #[inline(always)] + pub fn prod_dbg_unlock_success(&self) -> bool { + ((self.0 >> 3) & 1) != 0 + } + /// Production debug unlock failed. Only writable by Caliptra, and only when lifecycle state is PRODUCTION and DEBUG_INTENT strap is set to 1. + #[inline(always)] + pub fn prod_dbg_unlock_fail(&self) -> bool { + ((self.0 >> 4) & 1) != 0 + } + /// Production debug unlock is in progress. Only writable by Caliptra, and only when lifecycle state is PRODUCTION and DEBUG_INTENT strap is set to 1. + #[inline(always)] + pub fn prod_dbg_unlock_in_progress(&self) -> bool { + ((self.0 >> 5) & 1) != 0 + } + /// UDS Programming was successful. Only writable by Caliptra. Sticky once set, until warm reset. + #[inline(always)] + pub fn uds_program_success(&self) -> bool { + ((self.0 >> 6) & 1) != 0 + } + /// UDS Programming failed. Only writable by Caliptra. + #[inline(always)] + pub fn uds_program_fail(&self) -> bool { + ((self.0 >> 7) & 1) != 0 + } + /// UDS Programming is in progress. Only writable by Caliptra. + #[inline(always)] + pub fn uds_program_in_progress(&self) -> bool { + ((self.0 >> 8) & 1) != 0 + } + /// RSVD + #[inline(always)] + pub fn rsvd(&self) -> u32 { + (self.0 >> 9) & 0x7fffff + } + /// Construct a WriteVal that can be used to modify the contents of this register value. + #[inline(always)] + pub fn modify(self) -> SsDbgManufServiceRegRspWriteVal { + SsDbgManufServiceRegRspWriteVal(self.0) + } + } + impl From for SsDbgManufServiceRegRspReadVal { + #[inline(always)] + fn from(val: u32) -> Self { + Self(val) + } + } + impl From for u32 { + #[inline(always)] + fn from(val: SsDbgManufServiceRegRspReadVal) -> u32 { + val.0 + } + } + #[derive(Clone, Copy)] + pub struct SsDbgManufServiceRegRspWriteVal(u32); + impl SsDbgManufServiceRegRspWriteVal { + /// Manufacturing debug unlock was successful. Only writable by Caliptra, and only when lifecycle state is MANUFACTURING and DEBUG_INTENT strap is set to 1. Sticky once set, until warm reset. + #[inline(always)] + pub fn manuf_dbg_unlock_success(self, val: bool) -> Self { + Self((self.0 & !(1 << 0)) | (u32::from(val) << 0)) + } + /// Manufacturing debug unlock failed. Only writable by Caliptra, and only when lifecycle state is MANUFACTURING and DEBUG_INTENT strap is set to 1. + #[inline(always)] + pub fn manuf_dbg_unlock_fail(self, val: bool) -> Self { + Self((self.0 & !(1 << 1)) | (u32::from(val) << 1)) + } + /// Manufacturing debug unlock is in progress. Only writable by Caliptra, and only when lifecycle state is MANUFACTURING and DEBUG_INTENT strap is set to 1. + #[inline(always)] + pub fn manuf_dbg_unlock_in_progress(self, val: bool) -> Self { + Self((self.0 & !(1 << 2)) | (u32::from(val) << 2)) + } + /// Production debug unlock was successful. Only writable by Caliptra, and only when lifecycle state is PRODUCTION and DEBUG_INTENT strap is set to 1. Sticky once set, until warm reset. + #[inline(always)] + pub fn prod_dbg_unlock_success(self, val: bool) -> Self { + Self((self.0 & !(1 << 3)) | (u32::from(val) << 3)) + } + /// Production debug unlock failed. Only writable by Caliptra, and only when lifecycle state is PRODUCTION and DEBUG_INTENT strap is set to 1. + #[inline(always)] + pub fn prod_dbg_unlock_fail(self, val: bool) -> Self { + Self((self.0 & !(1 << 4)) | (u32::from(val) << 4)) + } + /// Production debug unlock is in progress. Only writable by Caliptra, and only when lifecycle state is PRODUCTION and DEBUG_INTENT strap is set to 1. + #[inline(always)] + pub fn prod_dbg_unlock_in_progress(self, val: bool) -> Self { + Self((self.0 & !(1 << 5)) | (u32::from(val) << 5)) + } + /// UDS Programming was successful. Only writable by Caliptra. Sticky once set, until warm reset. + #[inline(always)] + pub fn uds_program_success(self, val: bool) -> Self { + Self((self.0 & !(1 << 6)) | (u32::from(val) << 6)) + } + /// UDS Programming failed. Only writable by Caliptra. + #[inline(always)] + pub fn uds_program_fail(self, val: bool) -> Self { + Self((self.0 & !(1 << 7)) | (u32::from(val) << 7)) + } + /// UDS Programming is in progress. Only writable by Caliptra. + #[inline(always)] + pub fn uds_program_in_progress(self, val: bool) -> Self { + Self((self.0 & !(1 << 8)) | (u32::from(val) << 8)) + } + } + impl From for SsDbgManufServiceRegRspWriteVal { + #[inline(always)] + fn from(val: u32) -> Self { + Self(val) + } + } + impl From for u32 { + #[inline(always)] + fn from(val: SsDbgManufServiceRegRspWriteVal) -> u32 { + val.0 + } + } + #[derive(Clone, Copy)] + pub struct SsDebugIntentReadVal(u32); + impl SsDebugIntentReadVal { + /// + #[inline(always)] + pub fn debug_intent(&self) -> bool { + ((self.0 >> 0) & 1) != 0 + } + } + impl From for SsDebugIntentReadVal { + #[inline(always)] + fn from(val: u32) -> Self { + Self(val) + } + } + impl From for u32 { + #[inline(always)] + fn from(val: SsDebugIntentReadVal) -> u32 { + val.0 + } + } + #[derive(Clone, Copy)] pub struct ErrorIntrEnTReadVal(u32); impl ErrorIntrEnTReadVal { /// Enable bit for Internal Errors @@ -3355,143 +4017,49 @@ pub mod regs { } } #[derive(Clone, Copy)] - pub struct FuseKeyManifestPkHashMaskReadVal(u32); - impl FuseKeyManifestPkHashMaskReadVal { + pub struct FuseMldsaRevocationReadVal(u32); + impl FuseMldsaRevocationReadVal { /// #[inline(always)] - pub fn mask(&self) -> u32 { + pub fn mldsa_revocation(&self) -> u32 { (self.0 >> 0) & 0xf } /// Construct a WriteVal that can be used to modify the contents of this register value. #[inline(always)] - pub fn modify(self) -> FuseKeyManifestPkHashMaskWriteVal { - FuseKeyManifestPkHashMaskWriteVal(self.0) + pub fn modify(self) -> FuseMldsaRevocationWriteVal { + FuseMldsaRevocationWriteVal(self.0) } } - impl From for FuseKeyManifestPkHashMaskReadVal { + impl From for FuseMldsaRevocationReadVal { #[inline(always)] fn from(val: u32) -> Self { Self(val) } } - impl From for u32 { + impl From for u32 { #[inline(always)] - fn from(val: FuseKeyManifestPkHashMaskReadVal) -> u32 { + fn from(val: FuseMldsaRevocationReadVal) -> u32 { val.0 } } #[derive(Clone, Copy)] - pub struct FuseKeyManifestPkHashMaskWriteVal(u32); - impl FuseKeyManifestPkHashMaskWriteVal { + pub struct FuseMldsaRevocationWriteVal(u32); + impl FuseMldsaRevocationWriteVal { /// #[inline(always)] - pub fn mask(self, val: u32) -> Self { + pub fn mldsa_revocation(self, val: u32) -> Self { Self((self.0 & !(0xf << 0)) | ((val & 0xf) << 0)) } } - impl From for FuseKeyManifestPkHashMaskWriteVal { - #[inline(always)] - fn from(val: u32) -> Self { - Self(val) - } - } - impl From for u32 { - #[inline(always)] - fn from(val: FuseKeyManifestPkHashMaskWriteVal) -> u32 { - val.0 - } - } - #[derive(Clone, Copy)] - pub struct FuseLifeCycleReadVal(u32); - impl FuseLifeCycleReadVal { - /// - #[inline(always)] - pub fn life_cycle(&self) -> u32 { - (self.0 >> 0) & 3 - } - /// Construct a WriteVal that can be used to modify the contents of this register value. - #[inline(always)] - pub fn modify(self) -> FuseLifeCycleWriteVal { - FuseLifeCycleWriteVal(self.0) - } - } - impl From for FuseLifeCycleReadVal { - #[inline(always)] - fn from(val: u32) -> Self { - Self(val) - } - } - impl From for u32 { - #[inline(always)] - fn from(val: FuseLifeCycleReadVal) -> u32 { - val.0 - } - } - #[derive(Clone, Copy)] - pub struct FuseLifeCycleWriteVal(u32); - impl FuseLifeCycleWriteVal { - /// - #[inline(always)] - pub fn life_cycle(self, val: u32) -> Self { - Self((self.0 & !(3 << 0)) | ((val & 3) << 0)) - } - } - impl From for FuseLifeCycleWriteVal { - #[inline(always)] - fn from(val: u32) -> Self { - Self(val) - } - } - impl From for u32 { - #[inline(always)] - fn from(val: FuseLifeCycleWriteVal) -> u32 { - val.0 - } - } - #[derive(Clone, Copy)] - pub struct FuseLmsVerifyReadVal(u32); - impl FuseLmsVerifyReadVal { - /// - #[inline(always)] - pub fn lms_verify(&self) -> bool { - ((self.0 >> 0) & 1) != 0 - } - /// Construct a WriteVal that can be used to modify the contents of this register value. - #[inline(always)] - pub fn modify(self) -> FuseLmsVerifyWriteVal { - FuseLmsVerifyWriteVal(self.0) - } - } - impl From for FuseLmsVerifyReadVal { - #[inline(always)] - fn from(val: u32) -> Self { - Self(val) - } - } - impl From for u32 { - #[inline(always)] - fn from(val: FuseLmsVerifyReadVal) -> u32 { - val.0 - } - } - #[derive(Clone, Copy)] - pub struct FuseLmsVerifyWriteVal(u32); - impl FuseLmsVerifyWriteVal { - /// - #[inline(always)] - pub fn lms_verify(self, val: bool) -> Self { - Self((self.0 & !(1 << 0)) | (u32::from(val) << 0)) - } - } - impl From for FuseLmsVerifyWriteVal { + impl From for FuseMldsaRevocationWriteVal { #[inline(always)] fn from(val: u32) -> Self { Self(val) } } - impl From for u32 { + impl From for u32 { #[inline(always)] - fn from(val: FuseLmsVerifyWriteVal) -> u32 { + fn from(val: FuseMldsaRevocationWriteVal) -> u32 { val.0 } } @@ -4198,17 +4766,17 @@ pub mod meta { pub type CptraResetReason = ureg::ReadOnlyReg32; pub type CptraSecurityState = ureg::ReadOnlyReg32; - pub type CptraMboxValidAxiId = ureg::ReadWriteReg32<0xffffffff, u32, u32>; - pub type CptraMboxAxiIdLock = ureg::ReadWriteReg32< + pub type CptraMboxValidAxiUser = ureg::ReadWriteReg32<0xffffffff, u32, u32>; + pub type CptraMboxAxiUserLock = ureg::ReadWriteReg32< 0, - crate::soc_ifc::regs::CptraXxxxAxiIdLockReadVal, - crate::soc_ifc::regs::CptraXxxxAxiIdLockWriteVal, + crate::soc_ifc::regs::CptraXxxxAxiUserLockReadVal, + crate::soc_ifc::regs::CptraXxxxAxiUserLockWriteVal, >; - pub type CptraTrngValidAxiId = ureg::ReadWriteReg32<0xffffffff, u32, u32>; - pub type CptraTrngAxiIdLock = ureg::ReadWriteReg32< + pub type CptraTrngValidAxiUser = ureg::ReadWriteReg32<0xffffffff, u32, u32>; + pub type CptraTrngAxiUserLock = ureg::ReadWriteReg32< 0, - crate::soc_ifc::regs::CptraXxxxAxiIdLockReadVal, - crate::soc_ifc::regs::CptraXxxxAxiIdLockWriteVal, + crate::soc_ifc::regs::CptraXxxxAxiUserLockReadVal, + crate::soc_ifc::regs::CptraXxxxAxiUserLockWriteVal, >; pub type CptraTrngCtrl = ureg::ReadWriteReg32< 0, @@ -4264,11 +4832,11 @@ pub mod meta { crate::soc_ifc::regs::CptraWdtStatusReadVal, crate::soc_ifc::regs::CptraWdtStatusWriteVal, >; - pub type CptraFuseValidAxiId = ureg::ReadWriteReg32<0xffffffff, u32, u32>; - pub type CptraFuseAxiIdLock = ureg::ReadWriteReg32< + pub type CptraFuseValidAxiUser = ureg::ReadWriteReg32<0xffffffff, u32, u32>; + pub type CptraFuseAxiUserLock = ureg::ReadWriteReg32< 0, - crate::soc_ifc::regs::CptraXxxxAxiIdLockReadVal, - crate::soc_ifc::regs::CptraXxxxAxiIdLockWriteVal, + crate::soc_ifc::regs::CptraXxxxAxiUserLockReadVal, + crate::soc_ifc::regs::CptraXxxxAxiUserLockWriteVal, >; pub type CptraWdtCfg = ureg::ReadWriteReg32<0, u32, u32>; pub type CptraItrngEntropyConfig0 = ureg::ReadWriteReg32< @@ -4282,15 +4850,23 @@ pub mod meta { crate::soc_ifc::regs::CptraItrngEntropyConfig1WriteVal, >; pub type CptraRsvdReg = ureg::ReadWriteReg32<0, u32, u32>; + pub type CptraHwCapabilities = ureg::ReadWriteReg32<0, u32, u32>; + pub type CptraFwCapabilities = ureg::ReadWriteReg32<0, u32, u32>; + pub type CptraCapLock = ureg::ReadWriteReg32< + 0, + crate::soc_ifc::regs::CptraXxxxxxxkReadVal, + crate::soc_ifc::regs::CptraXxxxxxxkWriteVal, + >; + pub type CptraOwnerPkHash = ureg::ReadWriteReg32<0, u32, u32>; + pub type CptraOwnerPkHashLock = ureg::ReadWriteReg32< + 0, + crate::soc_ifc::regs::CptraXxxxxxxkReadVal, + crate::soc_ifc::regs::CptraXxxxxxxkWriteVal, + >; pub type FuseUdsSeed = ureg::WriteOnlyReg32<0, u32>; pub type FuseFieldEntropy = ureg::WriteOnlyReg32<0, u32>; pub type FuseKeyManifestPkHash = ureg::ReadWriteReg32<0, u32, u32>; - pub type FuseKeyManifestPkHashMask = ureg::ReadWriteReg32< - 0, - crate::soc_ifc::regs::FuseKeyManifestPkHashMaskReadVal, - crate::soc_ifc::regs::FuseKeyManifestPkHashMaskWriteVal, - >; - pub type FuseOwnerPkHash = ureg::ReadWriteReg32<0, u32, u32>; + pub type FuseKeyManifestPkHashMask = ureg::ReadWriteReg32<0, u32, u32>; pub type FuseFmcKeyManifestSvn = ureg::ReadWriteReg32<0, u32, u32>; pub type FuseRuntimeSvn = ureg::ReadWriteReg32<0, u32, u32>; pub type FuseAntiRollbackDisable = ureg::ReadWriteReg32< @@ -4300,22 +4876,44 @@ pub mod meta { >; pub type FuseIdevidCertAttr = ureg::ReadWriteReg32<0, u32, u32>; pub type FuseIdevidManufHsmId = ureg::ReadWriteReg32<0, u32, u32>; - pub type FuseLifeCycle = ureg::ReadWriteReg32< - 0, - crate::soc_ifc::regs::FuseLifeCycleReadVal, - crate::soc_ifc::regs::FuseLifeCycleWriteVal, - >; - pub type FuseLmsVerify = ureg::ReadWriteReg32< + pub type FuseLmsRevocation = ureg::ReadWriteReg32<0, u32, u32>; + pub type FuseMldsaRevocation = ureg::ReadWriteReg32< 0, - crate::soc_ifc::regs::FuseLmsVerifyReadVal, - crate::soc_ifc::regs::FuseLmsVerifyWriteVal, + crate::soc_ifc::regs::FuseMldsaRevocationReadVal, + crate::soc_ifc::regs::FuseMldsaRevocationWriteVal, >; - pub type FuseLmsRevocation = ureg::ReadWriteReg32<0, u32, u32>; pub type FuseSocSteppingId = ureg::ReadWriteReg32< 0, crate::soc_ifc::regs::FuseSocSteppingIdReadVal, crate::soc_ifc::regs::FuseSocSteppingIdWriteVal, >; + pub type FuseManufDbgUnlockToken = ureg::ReadWriteReg32<0, u32, u32>; + pub type SsCaliptraBaseAddrL = ureg::ReadWriteReg32<0, u32, u32>; + pub type SsCaliptraBaseAddrH = ureg::ReadWriteReg32<0, u32, u32>; + pub type SsMciBaseAddrL = ureg::ReadWriteReg32<0, u32, u32>; + pub type SsMciBaseAddrH = ureg::ReadWriteReg32<0, u32, u32>; + pub type SsRecoveryIfcBaseAddrL = ureg::ReadWriteReg32<0, u32, u32>; + pub type SsRecoveryIfcBaseAddrH = ureg::ReadWriteReg32<0, u32, u32>; + pub type SsOtpFcBaseAddrL = ureg::ReadWriteReg32<0, u32, u32>; + pub type SsOtpFcBaseAddrH = ureg::ReadWriteReg32<0, u32, u32>; + pub type SsUdsSeedBaseAddrL = ureg::ReadWriteReg32<0, u32, u32>; + pub type SsUdsSeedBaseAddrH = ureg::ReadWriteReg32<0, u32, u32>; + pub type SsProdDebugUnlockAuthPkHashRegBankOffset = ureg::ReadWriteReg32<0, u32, u32>; + pub type SsNumOfProdDebugUnlockAuthPkHashes = ureg::ReadWriteReg32<8, u32, u32>; + pub type SsDebugIntent = ureg::ReadOnlyReg32; + pub type SsStrapGeneric = ureg::ReadWriteReg32<0, u32, u32>; + pub type SsDbgManufServiceRegReq = ureg::ReadWriteReg32< + 0, + crate::soc_ifc::regs::SsDbgManufServiceRegReqReadVal, + crate::soc_ifc::regs::SsDbgManufServiceRegReqWriteVal, + >; + pub type SsDbgManufServiceRegRsp = ureg::ReadWriteReg32< + 0, + crate::soc_ifc::regs::SsDbgManufServiceRegRspReadVal, + crate::soc_ifc::regs::SsDbgManufServiceRegRspWriteVal, + >; + pub type SsSocDbgUnlockLevel = ureg::ReadWriteReg32<0, u32, u32>; + pub type SsGenericFwExecCtrl = ureg::ReadWriteReg32<0, u32, u32>; pub type InternalObfKey = ureg::WriteOnlyReg32<0, u32>; pub type InternalIccmLock = ureg::ReadWriteReg32< 0, diff --git a/hw/latest/registers/src/soc_ifc_trng.rs b/hw/latest/registers/src/soc_ifc_trng.rs index e1e836643d..84be130cb1 100644 --- a/hw/latest/registers/src/soc_ifc_trng.rs +++ b/hw/latest/registers/src/soc_ifc_trng.rs @@ -1,6 +1,6 @@ // Licensed under the Apache-2.0 license. // -// generated by caliptra_registers_generator with caliptra-rtl repo at ac8e5592b1a6d53f92809c98f8f0144c5a5bf0eb +// generated by caliptra_registers_generator with caliptra-rtl repo at 00730026cdf11841d20a6085ea3909ea3bd4a21b // #![allow(clippy::erasing_op)] #![allow(clippy::identity_op)] diff --git a/hw/latest/rtl b/hw/latest/rtl index ac8e5592b1..00730026cd 160000 --- a/hw/latest/rtl +++ b/hw/latest/rtl @@ -1 +1 @@ -Subproject commit ac8e5592b1a6d53f92809c98f8f0144c5a5bf0eb +Subproject commit 00730026cdf11841d20a6085ea3909ea3bd4a21b diff --git a/libcaliptra/inc/caliptra_types.h b/libcaliptra/inc/caliptra_types.h index 9058f50bd7..3e6d33470e 100644 --- a/libcaliptra/inc/caliptra_types.h +++ b/libcaliptra/inc/caliptra_types.h @@ -38,7 +38,6 @@ struct caliptra_fuses { uint32_t idevid_cert_attr[24]; uint32_t idevid_manuf_hsm_id[4]; enum device_lifecycle life_cycle; - bool lms_verify; uint32_t lms_revocation; uint16_t soc_stepping_id; }; diff --git a/libcaliptra/src/caliptra_api.c b/libcaliptra/src/caliptra_api.c index 2417891888..04a292c3e2 100644 --- a/libcaliptra/src/caliptra_api.c +++ b/libcaliptra/src/caliptra_api.c @@ -278,15 +278,13 @@ int caliptra_init_fuses(const struct caliptra_fuses *fuses) caliptra_fuse_array_write(GENERIC_AND_FUSE_REG_FUSE_UDS_SEED_0, fuses->uds_seed, CALIPTRA_ARRAY_SIZE(fuses->uds_seed)); caliptra_fuse_array_write(GENERIC_AND_FUSE_REG_FUSE_FIELD_ENTROPY_0, fuses->field_entropy, CALIPTRA_ARRAY_SIZE(fuses->field_entropy)); caliptra_fuse_array_write(GENERIC_AND_FUSE_REG_FUSE_KEY_MANIFEST_PK_HASH_0, fuses->key_manifest_pk_hash, CALIPTRA_ARRAY_SIZE(fuses->key_manifest_pk_hash)); - caliptra_generic_and_fuse_write(GENERIC_AND_FUSE_REG_FUSE_KEY_MANIFEST_PK_HASH_MASK, fuses->key_manifest_pk_hash_mask); - caliptra_fuse_array_write(GENERIC_AND_FUSE_REG_FUSE_OWNER_PK_HASH_0, fuses->owner_pk_hash, CALIPTRA_ARRAY_SIZE(fuses->owner_pk_hash)); + caliptra_generic_and_fuse_write(GENERIC_AND_FUSE_REG_FUSE_KEY_MANIFEST_PK_HASH_MASK_0, fuses->key_manifest_pk_hash_mask); + caliptra_fuse_array_write(GENERIC_AND_FUSE_REG_CPTRA_OWNER_PK_HASH_0, fuses->owner_pk_hash, CALIPTRA_ARRAY_SIZE(fuses->owner_pk_hash)); caliptra_generic_and_fuse_write(GENERIC_AND_FUSE_REG_FUSE_FMC_KEY_MANIFEST_SVN, fuses->fmc_key_manifest_svn); caliptra_fuse_array_write(GENERIC_AND_FUSE_REG_FUSE_RUNTIME_SVN_0, fuses->runtime_svn, CALIPTRA_ARRAY_SIZE(fuses->runtime_svn)); caliptra_generic_and_fuse_write(GENERIC_AND_FUSE_REG_FUSE_ANTI_ROLLBACK_DISABLE, (uint32_t)fuses->anti_rollback_disable); caliptra_fuse_array_write(GENERIC_AND_FUSE_REG_FUSE_IDEVID_CERT_ATTR_0, fuses->idevid_cert_attr, CALIPTRA_ARRAY_SIZE(fuses->idevid_cert_attr)); caliptra_fuse_array_write(GENERIC_AND_FUSE_REG_FUSE_IDEVID_MANUF_HSM_ID_0, fuses->idevid_manuf_hsm_id, CALIPTRA_ARRAY_SIZE(fuses->idevid_manuf_hsm_id)); - caliptra_generic_and_fuse_write(GENERIC_AND_FUSE_REG_FUSE_LIFE_CYCLE, (uint32_t)fuses->life_cycle); - caliptra_generic_and_fuse_write(GENERIC_AND_FUSE_REG_FUSE_LMS_VERIFY, (uint32_t)fuses->lms_verify); caliptra_generic_and_fuse_write(GENERIC_AND_FUSE_REG_FUSE_LMS_REVOCATION, fuses->lms_revocation); caliptra_generic_and_fuse_write(GENERIC_AND_FUSE_REG_FUSE_SOC_STEPPING_ID, fuses->soc_stepping_id); @@ -340,7 +338,7 @@ bool caliptra_ready_for_firmware(void) { status = caliptra_read_status(); - if ((status & GENERIC_AND_FUSE_REG_CPTRA_FLOW_STATUS_READY_FOR_FW_MASK) == GENERIC_AND_FUSE_REG_CPTRA_FLOW_STATUS_READY_FOR_FW_MASK) + if ((status & GENERIC_AND_FUSE_REG_CPTRA_FLOW_STATUS_READY_FOR_MB_PROCESSING_MASK) == GENERIC_AND_FUSE_REG_CPTRA_FLOW_STATUS_READY_FOR_MB_PROCESSING_MASK) { ready = true; } diff --git a/libcaliptra/src/caliptra_fuses.h b/libcaliptra/src/caliptra_fuses.h index 16100bc730..7e345ce9db 100644 --- a/libcaliptra/src/caliptra_fuses.h +++ b/libcaliptra/src/caliptra_fuses.h @@ -89,34 +89,34 @@ static inline void caliptra_write_itrng_entropy_repetition_count(uint16_t data) // NOTE: Is the responsibility of the caller to ensure the index does not exceed MBOX_AXI_ID_SLOTS static inline bool caliptra_read_mbox_pauser_lock(uint8_t idx) { - return caliptra_generic_and_fuse_read(GENERIC_AND_FUSE_REG_CPTRA_MBOX_AXI_ID_LOCK_0 + (sizeof(uint32_t) * idx)) != 0; + return caliptra_generic_and_fuse_read(GENERIC_AND_FUSE_REG_CPTRA_MBOX_AXI_USER_LOCK_0 + (sizeof(uint32_t) * idx)) != 0; } -// NOTE: Is the responsibility of the caller to ensure the index does not exceed MBOX_AXI_ID_SLOTS +// NOTE: Is the responsibility of the caller to ensure the index does not exceed MBOX_AXI_USER_SLOTS static inline void caliptra_set_mbox_pauser_lock(uint8_t idx) { - caliptra_generic_and_fuse_write(GENERIC_AND_FUSE_REG_CPTRA_MBOX_AXI_ID_LOCK_0 + (sizeof(uint32_t) * idx), 0x1); + caliptra_generic_and_fuse_write(GENERIC_AND_FUSE_REG_CPTRA_MBOX_AXI_USER_LOCK_0 + (sizeof(uint32_t) * idx), 0x1); } -// NOTE: Is the responsibility of the caller to ensure the index does not exceed MBOX_AXI_ID_SLOTS +// NOTE: Is the responsibility of the caller to ensure the index does not exceed MBOX_AXI_USER_SLOTS static inline void caliptra_write_mbox_valid_pauser(uint8_t idx, uint32_t data) { - caliptra_generic_and_fuse_write(GENERIC_AND_FUSE_REG_CPTRA_MBOX_VALID_AXI_ID_0 + (sizeof(uint32_t) * idx), data); + caliptra_generic_and_fuse_write(GENERIC_AND_FUSE_REG_CPTRA_MBOX_VALID_AXI_USER_0 + (sizeof(uint32_t) * idx), data); } static inline bool caliptra_read_fuse_pauser_lock() { - return caliptra_generic_and_fuse_read(GENERIC_AND_FUSE_REG_CPTRA_FUSE_AXI_ID_LOCK) != 0; + return caliptra_generic_and_fuse_read(GENERIC_AND_FUSE_REG_CPTRA_FUSE_AXI_USER_LOCK) != 0; } static inline void caliptra_set_fuse_pauser_lock() { - caliptra_generic_and_fuse_write(GENERIC_AND_FUSE_REG_CPTRA_FUSE_AXI_ID_LOCK, 0x1); + caliptra_generic_and_fuse_write(GENERIC_AND_FUSE_REG_CPTRA_FUSE_AXI_USER_LOCK, 0x1); } static inline void caliptra_write_fuse_valid_pauser(uint32_t data) { - caliptra_generic_and_fuse_write(GENERIC_AND_FUSE_REG_CPTRA_FUSE_VALID_AXI_ID, data); + caliptra_generic_and_fuse_write(GENERIC_AND_FUSE_REG_CPTRA_FUSE_VALID_AXI_USER, data); } static inline void caliptra_write_dbg_manuf_serv(uint32_t data) diff --git a/registers/bin/generator/src/main.rs b/registers/bin/generator/src/main.rs index 0c020e81d9..7acfdd5cc8 100644 --- a/registers/bin/generator/src/main.rs +++ b/registers/bin/generator/src/main.rs @@ -120,9 +120,9 @@ fn real_main() -> Result<(), Box> { write_file }; - if args.len() < 6 { + if args.len() < 5 { Err( - "Usage: codegen [--check] ", + "Usage: codegen [--check] ", )?; } @@ -134,7 +134,7 @@ fn real_main() -> Result<(), Box> { .filter(|p| p.exists()) .collect(); - let adamsbridge_rdl_dir = Path::new(&args[4]); + let adamsbridge_rdl_dir = rtl_dir.join("submodules").join("adams-bridge"); let mut adamsbridge_rdl_files: Vec = ADAMSBRIDGE_RDL_FILES .iter() .map(|p| adamsbridge_rdl_dir.join(p)) diff --git a/registers/update.sh b/registers/update.sh index 21af8eb529..ef31983728 100755 --- a/registers/update.sh +++ b/registers/update.sh @@ -9,4 +9,4 @@ if [[ ! -f "../hw/latest/rtl/.git" ]]; then exit 1 fi -cargo run --manifest-path bin/generator/Cargo.toml -- ../hw/latest/rtl bin/extra-rdl/ ../hw/latest/i3c-core-rtl ../hw/latest/adams-bridge ../hw/latest/registers/src/ +cargo run --manifest-path bin/generator/Cargo.toml -- ../hw/latest/rtl bin/extra-rdl/ ../hw/latest/i3c-core-rtl ../hw/latest/registers/src/ diff --git a/rom/dev/src/crypto.rs b/rom/dev/src/crypto.rs index 666197c936..cd7f0141f4 100644 --- a/rom/dev/src/crypto.rs +++ b/rom/dev/src/crypto.rs @@ -191,7 +191,8 @@ impl Crypto { output, KeyUsage::default() .set_hmac_key_en() - .set_ecc_key_gen_seed_en(), + .set_ecc_key_gen_seed_en() + .set_mldsa_seed_en(), ) .into(), mode, diff --git a/rom/dev/src/flow/cold_reset/idev_id.rs b/rom/dev/src/flow/cold_reset/idev_id.rs index aa7f5afb18..ca40af2520 100644 --- a/rom/dev/src/flow/cold_reset/idev_id.rs +++ b/rom/dev/src/flow/cold_reset/idev_id.rs @@ -62,7 +62,7 @@ impl InitDevIdLayer { // If CSR is not requested, indicate to the SOC that it can start // uploading the firmware image to the mailbox. if !env.soc_ifc.mfg_flag_gen_idev_id_csr() { - env.soc_ifc.flow_status_set_ready_for_firmware(); + env.soc_ifc.flow_status_set_ready_for_mb_processing(); } // Decrypt the UDS @@ -111,8 +111,8 @@ impl InitDevIdLayer { Self::generate_csr(env, &output)?; // Indicate (if not already done) to SOC that it can start uploading the firmware image to the mailbox. - if !env.soc_ifc.flow_status_ready_for_firmware() { - env.soc_ifc.flow_status_set_ready_for_firmware(); + if !env.soc_ifc.flow_status_ready_for_mb_processing() { + env.soc_ifc.flow_status_set_ready_for_mb_processing(); } // Write IDevID public key to FHT diff --git a/rom/dev/src/flow/fake.rs b/rom/dev/src/flow/fake.rs index e712fd4be2..c9bdf6e1d6 100644 --- a/rom/dev/src/flow/fake.rs +++ b/rom/dev/src/flow/fake.rs @@ -148,7 +148,7 @@ impl FakeRomFlow { // Zeroize the key vault in the fake ROM flow unsafe { KeyVault::zeroize() }; - env.soc_ifc.flow_status_set_ready_for_firmware(); + env.soc_ifc.flow_status_set_ready_for_mb_processing(); fht::initialize_fht(env); diff --git a/rom/dev/tests/rom_integration_tests/test_dice_derivations.rs b/rom/dev/tests/rom_integration_tests/test_dice_derivations.rs index 9d898b8af6..b6f2f2ca84 100644 --- a/rom/dev/tests/rom_integration_tests/test_dice_derivations.rs +++ b/rom/dev/tests/rom_integration_tests/test_dice_derivations.rs @@ -46,7 +46,12 @@ fn test_cold_reset_status_reporting() { } // Wait for uploading firmware. - hw.step_until(|m| m.soc_ifc().cptra_flow_status().read().ready_for_fw()); + hw.step_until(|m| { + m.soc_ifc() + .cptra_flow_status() + .read() + .ready_for_mb_processing() + }); // Manually put the firmware in the mailbox because // HwModel::upload_firmware returns only when the transaction is complete. diff --git a/rom/dev/tests/rom_integration_tests/test_fake_rom.rs b/rom/dev/tests/rom_integration_tests/test_fake_rom.rs index 1a7bab391a..a7e98c9e85 100644 --- a/rom/dev/tests/rom_integration_tests/test_fake_rom.rs +++ b/rom/dev/tests/rom_integration_tests/test_fake_rom.rs @@ -93,7 +93,12 @@ fn test_fake_rom_production_enabled() { .unwrap(); // Wait for ready for FW - hw.step_until(|m| m.soc_ifc().cptra_flow_status().read().ready_for_fw()); + hw.step_until(|m| { + m.soc_ifc() + .cptra_flow_status() + .read() + .ready_for_mb_processing() + }); } #[test] @@ -122,7 +127,12 @@ fn test_fake_rom_fw_load() { .unwrap(); // Upload the FW once ROM is at the right point - hw.step_until(|m| m.soc_ifc().cptra_flow_status().read().ready_for_fw()); + hw.step_until(|m| { + m.soc_ifc() + .cptra_flow_status() + .read() + .ready_for_mb_processing() + }); hw.upload_firmware(&image_bundle.to_bytes().unwrap()) .unwrap(); @@ -160,7 +170,12 @@ fn test_fake_rom_update_reset() { .unwrap(); // Upload FW - hw.step_until(|m| m.soc_ifc().cptra_flow_status().read().ready_for_fw()); + hw.step_until(|m| { + m.soc_ifc() + .cptra_flow_status() + .read() + .ready_for_mb_processing() + }); hw.upload_firmware(&image_bundle.to_bytes().unwrap()) .unwrap(); @@ -256,7 +271,12 @@ fn test_fake_rom_version() { .unwrap(); // Wait for ready for FW - hw.step_until(|m| m.soc_ifc().cptra_flow_status().read().ready_for_fw()); + hw.step_until(|m| { + m.soc_ifc() + .cptra_flow_status() + .read() + .ready_for_mb_processing() + }); assert_eq!( hw.soc_ifc().cptra_fw_rev_id().at(0).read() as u16, diff --git a/rom/dev/tests/rom_integration_tests/test_fmcalias_derivation.rs b/rom/dev/tests/rom_integration_tests/test_fmcalias_derivation.rs index 9c1799f44f..ebbfffd631 100644 --- a/rom/dev/tests/rom_integration_tests/test_fmcalias_derivation.rs +++ b/rom/dev/tests/rom_integration_tests/test_fmcalias_derivation.rs @@ -140,7 +140,6 @@ fn test_pcr_log() { let fuses = Fuses { anti_rollback_disable: true, - lms_verify: true, key_manifest_pk_hash: vendor_pubkey_digest, owner_pk_hash: owner_pubkey_digest, ..Default::default() @@ -244,7 +243,6 @@ fn test_pcr_log_no_owner_key_digest_fuse() { let fuses = Fuses { anti_rollback_disable: true, - lms_verify: true, key_manifest_pk_hash: gen .vendor_pubkey_digest(&image_bundle.manifest.preamble) .unwrap(), @@ -585,7 +583,6 @@ fn test_fuse_log() { anti_rollback_disable: true, fmc_key_manifest_svn: 0x0F, // Value of FMC_SVN runtime_svn: [0xF, 0, 0, 0], // Value of RT_SVN - lms_verify: true, ..Default::default() }; @@ -764,7 +761,6 @@ fn test_fht_info() { #[test] fn test_check_rom_cold_boot_status_reg() { let fuses = Fuses { - lms_verify: false, ..Default::default() }; let rom = caliptra_builder::build_firmware_rom(firmware::rom_from_env()).unwrap(); diff --git a/rom/dev/tests/rom_integration_tests/test_idevid_derivation.rs b/rom/dev/tests/rom_integration_tests/test_idevid_derivation.rs index cb77cceca2..4430ba8b1f 100644 --- a/rom/dev/tests/rom_integration_tests/test_idevid_derivation.rs +++ b/rom/dev/tests/rom_integration_tests/test_idevid_derivation.rs @@ -26,7 +26,12 @@ fn generate_csr(hw: &mut DefaultHwModel, image_bundle: &ImageBundle) -> Vec let downloaded = helpers::get_csr(hw).unwrap(); // Wait for uploading firmware. - hw.step_until(|m| m.soc_ifc().cptra_flow_status().read().ready_for_fw()); + hw.step_until(|m| { + m.soc_ifc() + .cptra_flow_status() + .read() + .ready_for_mb_processing() + }); hw.upload_firmware(&image_bundle.to_bytes().unwrap()) .unwrap(); @@ -64,10 +69,10 @@ fn test_idev_subj_key_id_algo() { } fn fuses_with_random_uds() -> Fuses { - const UDS_LEN: usize = core::mem::size_of::() * 12; + const UDS_LEN: usize = core::mem::size_of::() * 16; let mut uds_bytes = [0; UDS_LEN]; rand_bytes(&mut uds_bytes).unwrap(); - let mut uds_seed = [0u32; 12]; + let mut uds_seed = [0u32; 16]; for (word, bytes) in uds_seed.iter_mut().zip(uds_bytes.chunks_exact(4)) { *word = u32::from_be_bytes(bytes.try_into().unwrap()); @@ -132,7 +137,7 @@ fn verify_key( hw: &mut DefaultHwModel, cmd_id: u32, pubkey: &PKey, - test_uds: &[u32; 12], + test_uds: &[u32; 16], ) -> X509 { let payload = MailboxReqHeader { chksum: caliptra_common::checksum::calc_checksum(cmd_id, &[]), diff --git a/rom/dev/tests/rom_integration_tests/test_image_validation.rs b/rom/dev/tests/rom_integration_tests/test_image_validation.rs index 96fa6dec31..93e581c0ee 100644 --- a/rom/dev/tests/rom_integration_tests/test_image_validation.rs +++ b/rom/dev/tests/rom_integration_tests/test_image_validation.rs @@ -263,7 +263,6 @@ fn test_preamble_vendor_lms_pubkey_revocation() { image_options.vendor_config = vendor_config; let fuses = caliptra_hw_model::Fuses { - lms_verify: true, fuse_lms_revocation: 1u32 << image_options.vendor_config.pqc_key_idx, ..Default::default() }; @@ -324,7 +323,6 @@ fn test_preamble_vendor_ecc_pubkey_out_of_bounds() { #[test] fn test_preamble_vendor_lms_pubkey_out_of_bounds() { let fuses = caliptra_hw_model::Fuses { - lms_verify: true, ..Default::default() }; let (mut hw, mut image_bundle) = @@ -510,7 +508,6 @@ fn test_header_verify_vendor_ecc_sig_mismatch() { #[test] fn test_header_verify_vendor_lms_sig_mismatch() { let fuses = caliptra_hw_model::Fuses { - lms_verify: true, ..Default::default() }; let (mut hw, mut image_bundle) = @@ -539,7 +536,6 @@ fn test_header_verify_vendor_lms_sig_mismatch() { drop(hw); let fuses = caliptra_hw_model::Fuses { - lms_verify: true, ..Default::default() }; let (mut hw, mut image_bundle) = @@ -575,7 +571,6 @@ fn test_header_verify_vendor_lms_sig_mismatch() { #[test] fn test_header_verify_owner_lms_sig_mismatch() { let fuses = caliptra_hw_model::Fuses { - lms_verify: true, ..Default::default() }; let (mut hw, mut image_bundle) = @@ -605,7 +600,6 @@ fn test_header_verify_owner_lms_sig_mismatch() { drop(hw); let fuses = caliptra_hw_model::Fuses { - lms_verify: true, ..Default::default() }; let (mut hw, mut image_bundle) = @@ -663,7 +657,6 @@ fn test_header_verify_vendor_ecc_pub_key_in_preamble_and_header() { #[test] fn test_header_verify_vendor_lms_pub_key_in_preamble_and_header() { let fuses = caliptra_hw_model::Fuses { - lms_verify: true, ..Default::default() }; let (mut hw, mut image_bundle) = @@ -1684,7 +1677,12 @@ fn cert_test_with_custom_dates() { // Download the CSR from the mailbox. let idevid_cert_bytes = helpers::get_csr(&mut hw).unwrap(); - hw.step_until(|m| m.soc_ifc().cptra_flow_status().read().ready_for_fw()); + hw.step_until(|m| { + m.soc_ifc() + .cptra_flow_status() + .read() + .ready_for_mb_processing() + }); hw.upload_firmware(&image_bundle.to_bytes().unwrap()) .unwrap(); @@ -1744,7 +1742,12 @@ fn cert_test() { // Download the CSR from the mailbox. let csr_bytes = helpers::get_csr(&mut hw).unwrap(); - hw.step_until(|m| m.soc_ifc().cptra_flow_status().read().ready_for_fw()); + hw.step_until(|m| { + m.soc_ifc() + .cptra_flow_status() + .read() + .ready_for_mb_processing() + }); hw.upload_firmware(&image_bundle.to_bytes().unwrap()) .unwrap(); @@ -1804,7 +1807,12 @@ fn cert_test_with_ueid() { // Download the CSR from the mailbox. let csr_bytes = helpers::get_csr(&mut hw).unwrap(); - hw.step_until(|m| m.soc_ifc().cptra_flow_status().read().ready_for_fw()); + hw.step_until(|m| { + m.soc_ifc() + .cptra_flow_status() + .read() + .ready_for_mb_processing() + }); hw.upload_firmware(&image_bundle.to_bytes().unwrap()) .unwrap(); diff --git a/rom/dev/tests/rom_integration_tests/test_mailbox_errors.rs b/rom/dev/tests/rom_integration_tests/test_mailbox_errors.rs index 6ff11b3153..1fd0078749 100644 --- a/rom/dev/tests/rom_integration_tests/test_mailbox_errors.rs +++ b/rom/dev/tests/rom_integration_tests/test_mailbox_errors.rs @@ -160,7 +160,7 @@ fn test_mailbox_reserved_pauser() { helpers::build_hw_model_and_image_bundle(Fuses::default(), ImageOptions::default()); // Set pauser to the reserved value - hw.set_axi_id(0xffffffff); + hw.set_axi_user(0xffffffff); // Send anything assert_eq!( diff --git a/rom/dev/tests/rom_integration_tests/test_update_reset.rs b/rom/dev/tests/rom_integration_tests/test_update_reset.rs index 769cab5f3f..67321bbe96 100644 --- a/rom/dev/tests/rom_integration_tests/test_update_reset.rs +++ b/rom/dev/tests/rom_integration_tests/test_update_reset.rs @@ -382,7 +382,6 @@ fn test_update_reset_vendor_lms_pub_key_idx_dv_mismatch() { }, BootParams { fuses: caliptra_hw_model::Fuses { - lms_verify: true, ..Default::default() }, fw_image: Some(&image_bundle.to_bytes().unwrap()), diff --git a/rom/dev/tests/rom_integration_tests/test_wdt_activation_and_stoppage.rs b/rom/dev/tests/rom_integration_tests/test_wdt_activation_and_stoppage.rs index e120c6cc13..8a7a867aa7 100644 --- a/rom/dev/tests/rom_integration_tests/test_wdt_activation_and_stoppage.rs +++ b/rom/dev/tests/rom_integration_tests/test_wdt_activation_and_stoppage.rs @@ -48,7 +48,12 @@ fn test_wdt_activation_and_stoppage() { assert!(hw.soc_ifc().cptra_wdt_timer1_en().read().timer1_en()); // Upload the FW once ROM is at the right point - hw.step_until(|m| m.soc_ifc().cptra_flow_status().read().ready_for_fw()); + hw.step_until(|m| { + m.soc_ifc() + .cptra_flow_status() + .read() + .ready_for_mb_processing() + }); hw.upload_firmware(&image_bundle.to_bytes().unwrap()) .unwrap(); diff --git a/rom/dev/tests/rom_integration_tests/tests_get_idev_csr.rs b/rom/dev/tests/rom_integration_tests/tests_get_idev_csr.rs index 2327d013ad..cfa7838fba 100644 --- a/rom/dev/tests/rom_integration_tests/tests_get_idev_csr.rs +++ b/rom/dev/tests/rom_integration_tests/tests_get_idev_csr.rs @@ -23,7 +23,12 @@ fn test_get_csr() { let downloaded = helpers::get_csr(&mut hw).unwrap(); - hw.step_until(|m| m.soc_ifc().cptra_flow_status().read().ready_for_fw()); + hw.step_until(|m| { + m.soc_ifc() + .cptra_flow_status() + .read() + .ready_for_mb_processing() + }); downloaded }; @@ -55,7 +60,12 @@ fn test_get_csr() { fn test_get_csr_generate_csr_flag_not_set() { let (mut hw, _) = helpers::build_hw_model_and_image_bundle(Fuses::default(), ImageOptions::default()); - hw.step_until(|m| m.soc_ifc().cptra_flow_status().read().ready_for_fw()); + hw.step_until(|m| { + m.soc_ifc() + .cptra_flow_status() + .read() + .ready_for_mb_processing() + }); let payload = MailboxReqHeader { chksum: caliptra_common::checksum::calc_checksum(u32::from(CommandId::GET_IDEV_CSR), &[]), diff --git a/runtime/src/mailbox.rs b/runtime/src/mailbox.rs index 3e0bc291c3..362069e9d7 100644 --- a/runtime/src/mailbox.rs +++ b/runtime/src/mailbox.rs @@ -103,7 +103,7 @@ impl Mailbox { /// Gets the id of the mailbox pub fn id(&self) -> u32 { let mbox = self.mbox.regs(); - mbox.id().read() + mbox.user().read() } /// Copies data in mailbox to `buf` diff --git a/runtime/tests/runtime_integration_tests/common.rs b/runtime/tests/runtime_integration_tests/common.rs index eb7fce430a..2f10a2c900 100644 --- a/runtime/tests/runtime_integration_tests/common.rs +++ b/runtime/tests/runtime_integration_tests/common.rs @@ -49,7 +49,7 @@ pub struct RuntimeTestArgs<'a> { pub test_mfg_flags: Option, } -pub fn run_rt_test_lms(args: RuntimeTestArgs, lms_verify: bool) -> DefaultHwModel { +pub fn run_rt_test_lms(args: RuntimeTestArgs) -> DefaultHwModel { let default_rt_fwid = if cfg!(feature = "fpga_realtime") { &APP_WITH_UART_FPGA } else { @@ -88,7 +88,6 @@ pub fn run_rt_test_lms(args: RuntimeTestArgs, lms_verify: bool) -> DefaultHwMode BootParams { fw_image: Some(&image.to_bytes().unwrap()), fuses: Fuses { - lms_verify, ..Default::default() }, initial_dbg_manuf_service_reg: boot_flags, @@ -97,7 +96,12 @@ pub fn run_rt_test_lms(args: RuntimeTestArgs, lms_verify: bool) -> DefaultHwMode ) .unwrap(); - model.step_until(|m| m.soc_ifc().cptra_flow_status().read().ready_for_fw()); + model.step_until(|m| { + m.soc_ifc() + .cptra_flow_status() + .read() + .ready_for_mb_processing() + }); model } @@ -105,7 +109,7 @@ pub fn run_rt_test_lms(args: RuntimeTestArgs, lms_verify: bool) -> DefaultHwMode // Run a test which boots ROM -> FMC -> test_bin. If test_bin_name is None, // run the production runtime image. pub fn run_rt_test(args: RuntimeTestArgs) -> DefaultHwModel { - run_rt_test_lms(args, false) + run_rt_test_lms(args) } pub fn generate_test_x509_cert(ec_key: PKey) -> X509 { diff --git a/runtime/tests/runtime_integration_tests/test_mailbox.rs b/runtime/tests/runtime_integration_tests/test_mailbox.rs index 7670e97850..9f014d803a 100644 --- a/runtime/tests/runtime_integration_tests/test_mailbox.rs +++ b/runtime/tests/runtime_integration_tests/test_mailbox.rs @@ -66,7 +66,7 @@ fn test_reserved_pauser() { model.step_until(|m| m.soc_mbox().status().read().mbox_fsm_ps().mbox_idle()); // Set pauser to the reserved value - model.set_axi_id(0xffffffff); + model.set_axi_user(0xffffffff); // Send anything let payload = MailboxReqHeader { diff --git a/runtime/tests/runtime_integration_tests/test_set_auth_manifest.rs b/runtime/tests/runtime_integration_tests/test_set_auth_manifest.rs index e4db31a51b..d88ad95415 100644 --- a/runtime/tests/runtime_integration_tests/test_set_auth_manifest.rs +++ b/runtime/tests/runtime_integration_tests/test_set_auth_manifest.rs @@ -102,7 +102,7 @@ pub fn test_auth_manifest() -> AuthorizationManifest { #[test] fn test_set_auth_manifest_cmd() { - let mut model = run_rt_test_lms(RuntimeTestArgs::default(), true); + let mut model = run_rt_test_lms(RuntimeTestArgs::default()); model.step_until(|m| { m.soc_ifc().cptra_boot_status().read() == u32::from(RtBootStatus::RtReadyForCommands) @@ -131,7 +131,7 @@ fn test_set_auth_manifest_cmd() { #[test] fn test_set_auth_manifest_cmd_invalid_len() { - let mut model = run_rt_test_lms(RuntimeTestArgs::default(), true); + let mut model = run_rt_test_lms(RuntimeTestArgs::default()); model.step_until(|m| { m.soc_ifc().cptra_boot_status().read() == u32::from(RtBootStatus::RtReadyForCommands) @@ -179,7 +179,7 @@ fn test_set_auth_manifest_cmd_invalid_len() { } fn test_manifest_expect_err(manifest: AuthorizationManifest, expected_err: CaliptraError) { - let mut model = run_rt_test_lms(RuntimeTestArgs::default(), true); + let mut model = run_rt_test_lms(RuntimeTestArgs::default()); model.step_until(|m| { m.soc_ifc().cptra_boot_status().read() == u32::from(RtBootStatus::RtReadyForCommands) diff --git a/sw-emulator/app/src/main.rs b/sw-emulator/app/src/main.rs index 2cae70601c..8c2a0aa23d 100644 --- a/sw-emulator/app/src/main.rs +++ b/sw-emulator/app/src/main.rs @@ -320,7 +320,7 @@ fn main() -> io::Result<()> { .try_into() .expect("owner_pk_hash must be 48 bytes"), ); - soc_ifc.fuse_owner_pk_hash().write(&owner_pk_hash); + soc_ifc.cptra_owner_pk_hash().write(&owner_pk_hash); } // Populate DBG_MANUF_SERVICE_REG diff --git a/sw-emulator/lib/periph/src/doe.rs b/sw-emulator/lib/periph/src/doe.rs index 47a48dfd13..ffb314bebe 100644 --- a/sw-emulator/lib/periph/src/doe.rs +++ b/sw-emulator/lib/periph/src/doe.rs @@ -172,7 +172,7 @@ impl Doe { /// * `key_id` - Key index to store the UDS fn unscramble_uds(&mut self, key_id: u32) { let cipher_uds = self.soc_reg.uds(); - let mut plain_uds = [0u8; 48]; + let mut plain_uds = [0u8; 64]; Aes256Cbc::decrypt( &self.soc_reg.doe_key(), self.iv.data(), @@ -382,7 +382,7 @@ mod tests { #[test] fn test_clear_secrets() { - let expected_uds = [0u8; 48]; + let expected_uds = [0u8; 64]; let expected_doe_key = [0u8; 32]; let expected_fe = [0u8; 32]; let pic = Pic::new(); diff --git a/sw-emulator/lib/periph/src/hash_sha512.rs b/sw-emulator/lib/periph/src/hash_sha512.rs index 59718f88d6..e6aaa007ea 100644 --- a/sw-emulator/lib/periph/src/hash_sha512.rs +++ b/sw-emulator/lib/periph/src/hash_sha512.rs @@ -561,8 +561,7 @@ impl HashSha512Regs { self.block.fill(0); let result: Result<[u8; KeyVault::PCR_SIZE], BusError> = if pcr_hash_extend == 0 { - let mut key_usage = KeyUsage::default(); - key_usage.set_sha_data(true); + let key_usage = KeyUsage::default(); match self.key_vault.read_key(key_id, key_usage) { Err(x) => Err(x), Ok(x) => Ok(x[..KeyVault::PCR_SIZE].try_into().unwrap()), @@ -892,8 +891,7 @@ mod tests { let mut block: [u8; KeyVault::KEY_SIZE] = [0; KeyVault::KEY_SIZE]; block[..data.len()].copy_from_slice(data); block.to_big_endian(); // Keys are stored in big-endian format. - let mut key_usage = KeyUsage::default(); - key_usage.set_sha_data(true); + let key_usage = KeyUsage::default(); key_vault .write_key(block_id, &block, u32::from(key_usage)) @@ -952,8 +950,7 @@ mod tests { if hash_to_kv { // Instruct hash to be written to the key-vault. - let mut key_usage = KeyUsage::default(); - key_usage.set_sha_data(true); + let key_usage = KeyUsage::default(); let hash_ctrl = InMemoryRegister::::new(0); hash_ctrl.modify( HashWriteControl::KEY_ID.val(hash_id) @@ -1080,8 +1077,7 @@ mod tests { let mut hash_le: [u8; SHA512_HASH_SIZE] = [0; SHA512_HASH_SIZE]; if hash_to_kv { - let mut key_usage = KeyUsage::default(); - key_usage.set_sha_data(true); + let key_usage = KeyUsage::default(); hash_le[..KeyVault::KEY_SIZE] .copy_from_slice(&sha512.key_vault.read_key(hash_id, key_usage).unwrap()[..]); } else { @@ -1170,32 +1166,6 @@ mod tests { test_sha(&SHA_512_TEST_BLOCK, &expected, Sha512Mode::Sha256, &[]); } - #[test] - fn test_sha384_kv_block_read() { - let test_block: [u8; SHA384_HASH_SIZE] = [ - 0x9c, 0x2f, 0x48, 0x76, 0x0d, 0x13, 0xac, 0x42, 0xea, 0xd1, 0x96, 0xe5, 0x4d, 0xcb, - 0xaa, 0x5e, 0x58, 0x72, 0x06, 0x62, 0xa9, 0x6b, 0x91, 0x94, 0xe9, 0x81, 0x33, 0x29, - 0xbd, 0xb6, 0x27, 0xc7, 0xc1, 0xca, 0x77, 0x15, 0x31, 0x16, 0x32, 0xc1, 0x39, 0xe7, - 0xa3, 0x59, 0x14, 0xfc, 0x1e, 0xcd, - ]; - - let expected: [u8; SHA384_HASH_SIZE] = [ - 0x4a, 0x8a, 0x78, 0xb1, 0xa0, 0xa, 0x13, 0x33, 0xfc, 0x92, 0x32, 0x2f, 0xad, 0xd2, - 0x47, 0x47, 0xf2, 0xcd, 0x2f, 0x1, 0x8e, 0xff, 0xa3, 0x61, 0xff, 0x13, 0x33, 0x10, - 0x5b, 0x86, 0x6a, 0xc9, 0x39, 0xea, 0xd2, 0x67, 0x2b, 0xdb, 0xba, 0x4e, 0x18, 0x1c, - 0xb3, 0x4f, 0xb7, 0xeb, 0xa4, 0xf6, - ]; - - for key_id in 0..KeyVault::KEY_COUNT { - test_sha( - &test_block, - &expected, - Sha512Mode::Sha384, - &[KeyVaultAction::BlockFromVault(key_id)], - ); - } - } - #[test] fn test_sha384_kv_block_read_fail() { let test_block: [u8; SHA384_HASH_SIZE] = [ @@ -1239,32 +1209,6 @@ mod tests { } } - #[test] - fn test_sha384_kv_hash_write() { - let test_block: [u8; SHA384_HASH_SIZE] = [ - 0x9c, 0x2f, 0x48, 0x76, 0x0d, 0x13, 0xac, 0x42, 0xea, 0xd1, 0x96, 0xe5, 0x4d, 0xcb, - 0xaa, 0x5e, 0x58, 0x72, 0x06, 0x62, 0xa9, 0x6b, 0x91, 0x94, 0xe9, 0x81, 0x33, 0x29, - 0xbd, 0xb6, 0x27, 0xc7, 0xc1, 0xca, 0x77, 0x15, 0x31, 0x16, 0x32, 0xc1, 0x39, 0xe7, - 0xa3, 0x59, 0x14, 0xfc, 0x1e, 0xcd, - ]; - - let expected: [u8; SHA384_HASH_SIZE] = [ - 0x4a, 0x8a, 0x78, 0xb1, 0xa0, 0xa, 0x13, 0x33, 0xfc, 0x92, 0x32, 0x2f, 0xad, 0xd2, - 0x47, 0x47, 0xf2, 0xcd, 0x2f, 0x1, 0x8e, 0xff, 0xa3, 0x61, 0xff, 0x13, 0x33, 0x10, - 0x5b, 0x86, 0x6a, 0xc9, 0x39, 0xea, 0xd2, 0x67, 0x2b, 0xdb, 0xba, 0x4e, 0x18, 0x1c, - 0xb3, 0x4f, 0xb7, 0xeb, 0xa4, 0xf6, - ]; - - for key_id in 0..8 { - test_sha( - &test_block, - &expected, - Sha512Mode::Sha384, - &[KeyVaultAction::HashToVault(key_id)], - ); - } - } - #[test] fn test_sha384_kv_hash_write_fail() { let test_block: [u8; SHA384_HASH_SIZE] = [ @@ -1294,35 +1238,6 @@ mod tests { } } - #[test] - fn test_sha384_kv_block_read_hash_write() { - let test_block: [u8; SHA384_HASH_SIZE] = [ - 0x9c, 0x2f, 0x48, 0x76, 0x0d, 0x13, 0xac, 0x42, 0xea, 0xd1, 0x96, 0xe5, 0x4d, 0xcb, - 0xaa, 0x5e, 0x58, 0x72, 0x06, 0x62, 0xa9, 0x6b, 0x91, 0x94, 0xe9, 0x81, 0x33, 0x29, - 0xbd, 0xb6, 0x27, 0xc7, 0xc1, 0xca, 0x77, 0x15, 0x31, 0x16, 0x32, 0xc1, 0x39, 0xe7, - 0xa3, 0x59, 0x14, 0xfc, 0x1e, 0xcd, - ]; - - let expected: [u8; SHA384_HASH_SIZE] = [ - 0x4a, 0x8a, 0x78, 0xb1, 0xa0, 0xa, 0x13, 0x33, 0xfc, 0x92, 0x32, 0x2f, 0xad, 0xd2, - 0x47, 0x47, 0xf2, 0xcd, 0x2f, 0x1, 0x8e, 0xff, 0xa3, 0x61, 0xff, 0x13, 0x33, 0x10, - 0x5b, 0x86, 0x6a, 0xc9, 0x39, 0xea, 0xd2, 0x67, 0x2b, 0xdb, 0xba, 0x4e, 0x18, 0x1c, - 0xb3, 0x4f, 0xb7, 0xeb, 0xa4, 0xf6, - ]; - - for key_id in 0..KeyVault::KEY_COUNT { - test_sha( - &test_block, - &expected, - Sha512Mode::Sha384, - &[ - KeyVaultAction::BlockFromVault(key_id), - KeyVaultAction::HashToVault((key_id + 1) % KeyVault::KEY_COUNT), - ], - ); - } - } - fn test_pcr_hash_extend(data: &[u8], pcr_data: &mut [u8; SHA384_HASH_SIZE], expected: &[u8]) { // Prime the PCR vault. let clock = Clock::new(); diff --git a/sw-emulator/lib/periph/src/hmac.rs b/sw-emulator/lib/periph/src/hmac.rs index f7b54d5a95..1d29d2168a 100644 --- a/sw-emulator/lib/periph/src/hmac.rs +++ b/sw-emulator/lib/periph/src/hmac.rs @@ -36,6 +36,7 @@ register_bitfields! [ HMAC384 = 0, HMAC512 = 1, ], + CSR_MODE OFFSET(4) NUMBITS(1) [], RSVD OFFSET(4) NUMBITS(28) [], ], @@ -379,6 +380,8 @@ impl HmacSha { self.zeroize(); } + // [TODO][CAP2] if CSR Mode is set, use a pre-defined key. + Ok(()) } @@ -598,7 +601,8 @@ impl HmacSha { KeyReadStatus::ERROR::KV_WRITE_FAIL.value } Ok(data) => { - self.format_block(&data); + let key_size = self.key_len() * 4; + self.format_block(&data[..key_size.min(data.len())]); self.block_from_kv = true; KeyReadStatus::ERROR::KV_SUCCESS.value } diff --git a/sw-emulator/lib/periph/src/key_vault.rs b/sw-emulator/lib/periph/src/key_vault.rs index 57532129ff..2ac77073fe 100644 --- a/sw-emulator/lib/periph/src/key_vault.rs +++ b/sw-emulator/lib/periph/src/key_vault.rs @@ -146,7 +146,7 @@ pub struct KeyVault { impl KeyVault { pub const PCR_SIZE: usize = 48; - pub const KEY_COUNT: u32 = 32; + pub const KEY_COUNT: u32 = 24; pub const KEY_SIZE: usize = 64; pub const KEY_CONTROL_REG_OFFSET: u32 = 0; pub const KEY_CONTROL_REG_WIDTH: u32 = 0x4; @@ -246,8 +246,8 @@ bitfield! { /// Flag indicating if the key can be used as HMAC data pub hmac_data, set_hmac_data: 1; - /// Flag indicating if the key can be used as SHA data - pub sha_data, set_sha_data: 2; + /// Flag indicating if the key can be used as MLDSA seed + pub mldsa_seed, set_mldsa_seed: 2; /// Flag indicating if the key can be used aas ECC Private Key pub ecc_private_key, set_ecc_private_key: 3; diff --git a/sw-emulator/lib/periph/src/mailbox.rs b/sw-emulator/lib/periph/src/mailbox.rs index a3790229f5..59383d8a2d 100644 --- a/sw-emulator/lib/periph/src/mailbox.rs +++ b/sw-emulator/lib/periph/src/mailbox.rs @@ -238,6 +238,10 @@ pub struct MailboxRegs { #[register(offset = 0x0000_0020, write_fn = write_unlock, read_fn = read_unlock)] _unlock: ReadWriteRegister, + /// MBOX_TAP_MODE register + #[register(offset = 0x0000_0024)] + _tap_mode: ReadWriteRegister, + /// State Machine state_machine: StateMachine, @@ -274,6 +278,7 @@ impl MailboxRegs { execute: ReadWriteRegister::new(Self::EXEC_VAL), _status: ReadWriteRegister::new(Self::STATUS_VAL), _unlock: ReadWriteRegister::new(Self::UNLOCK_VAL), + _tap_mode: ReadWriteRegister::new(0), state_machine: StateMachine::new(Context::new(ram)), requester: MailboxRequester::Caliptra, irq: false, @@ -654,7 +659,7 @@ mod tests { // Confirm it is locked assert!(uc_regs.lock().read().lock()); - assert_eq!(uc_regs.id().read(), 0); + assert_eq!(uc_regs.user().read(), 0); // Write command uc_regs.cmd().write(|_| 0x55); @@ -735,7 +740,7 @@ mod tests { // Confirm it is locked assert!(soc_regs.lock().read().lock()); - assert_eq!(soc_regs.id().read(), MailboxRequester::Soc as u32); + assert_eq!(soc_regs.user().read(), MailboxRequester::Soc as u32); // Write command soc_regs.cmd().write(|_| 0x55); @@ -876,7 +881,7 @@ mod tests { // Confirm it is locked assert!(uc_regs.lock().read().lock()); - let user = uc_regs.id().read(); + let user = uc_regs.user().read(); assert_eq!(user, MailboxRequester::Caliptra as u32); // Write command diff --git a/sw-emulator/lib/periph/src/ml_dsa87.rs b/sw-emulator/lib/periph/src/ml_dsa87.rs index 41133a0af2..74f09843a1 100644 --- a/sw-emulator/lib/periph/src/ml_dsa87.rs +++ b/sw-emulator/lib/periph/src/ml_dsa87.rs @@ -383,9 +383,8 @@ impl Mldsa87 { fn seed_read_complete(&mut self) { let key_id = self.kv_rd_seed_ctrl.reg.read(KvRdSeedCtrl::READ_ENTRY); - // TODO will keyvault feature a special ID for ML-DSA usage? let mut key_usage = KeyUsage::default(); - key_usage.set_ecc_key_gen_seed(true); + key_usage.set_mldsa_seed(true); let result = self.key_vault.read_key(key_id, key_usage); let (seed_read_result, seed) = match result.err() { @@ -767,7 +766,7 @@ mod tests { let mut key_vault = KeyVault::new(); let mut key_usage = KeyUsage::default(); - key_usage.set_ecc_key_gen_seed(true); + key_usage.set_mldsa_seed(true); key_vault .write_key(key_id, &seed, u32::from(key_usage)) diff --git a/sw-emulator/lib/periph/src/soc_reg.rs b/sw-emulator/lib/periph/src/soc_reg.rs index 0b54cb1666..7b0bfed20c 100644 --- a/sw-emulator/lib/periph/src/soc_reg.rs +++ b/sw-emulator/lib/periph/src/soc_reg.rs @@ -74,7 +74,7 @@ mod constants { pub const CPTRA_GENERIC_INPUT_WIRES_SIZE: usize = 8; pub const CPTRA_GENERIC_OUTPUT_WIRES_START: u32 = 0xcc; pub const CPTRA_GENERIC_OUTPUT_WIRES_SIZE: usize = 8; - pub const FUSE_UDS_SEED_SIZE: usize = 48; + pub const FUSE_UDS_SEED_SIZE: usize = 64; pub const FUSE_FIELD_ENTROPY_SIZE: usize = 32; pub const CPTRA_WDT_TIMER1_EN_START: u32 = 0xe4; pub const CPTRA_WDT_TIMER1_CTRL_START: u32 = 0xe8; @@ -84,12 +84,13 @@ mod constants { pub const CPTRA_WDT_TIMER2_TIMEOUT_PERIOD_START: u32 = 0xfc; pub const CPTRA_WDT_STATUS_START: u32 = 0x104; pub const CPTRA_FUSE_VALID_PAUSER_START: u32 = 0x108; + pub const CPTRA_OWNER_PK_HASH_START: u32 = 0x140; + pub const CPTRA_OWNER_PK_HASH_SIZE: usize = 48; pub const CPTRA_FUSE_PAUSER_LOCK_START: u32 = 0x10c; - pub const FUSE_VENDOR_PK_HASH_START: u32 = 0x250; - pub const FUSE_VENDOR_PK_HASH_SIZE: usize = 48; - pub const FUSE_VENDOR_PK_MASK_START: u32 = 0x280; - pub const FUSE_OWNER_PK_HASH_START: u32 = 0x284; - pub const FUSE_OWNER_PK_HASH_SIZE: usize = 48; + pub const FUSE_KEY_MANIFEST_PK_HASH_START: u32 = 0x260; + pub const FUSE_KEY_MANIFEST_PK_HASH_SIZE: usize = 48; + pub const FUSE_KEY_MANIFEST_PK_HASH_MASK_START: u32 = 0x290; + pub const FUSE_KEY_MANIFEST_PK_HASH_MASK_SIZE: usize = 32; pub const FUSE_FMC_SVN_START: u32 = 0x2b4; pub const FUSE_RUNTIME_SVN_START: u32 = 0x2b8; pub const FUSE_RUNTIME_SVN_SIZE: usize = 16; @@ -98,7 +99,8 @@ mod constants { pub const FUSE_IDEVID_CERT_ATTR_SIZE: usize = 96; pub const FUSE_IDEVID_MANUF_HSM_ID_START: u32 = 0x32c; pub const FUSE_IDEVID_MANUF_HSM_ID_SIZE: usize = 16; - pub const FUSE_LIFE_CYCLE_START: u32 = 0x33c; + pub const FUSE_MANUF_DBG_UNLOCK_TOKEN_START: u32 = 0x34c; + pub const FUSE_MANUF_DBG_UNLOCK_TOKEN_SIZE: usize = 16; pub const INTERNAL_OBF_KEY_SIZE: usize = 32; pub const INTERNAL_ICCM_LOCK_START: u32 = 0x620; pub const INTERNAL_FW_UPDATE_RESET_START: u32 = 0x624; @@ -197,10 +199,9 @@ register_bitfields! [ RSVD OFFSET(2) NUMBITS(30) [], ], - /// LMS Verify - LmsVerify [ - LMS_VERIFY OFFSET(0) NUMBITS(1) [], - RSVD OFFSET(1) NUMBITS(31) [], + /// Cap Lock + CapLock [ + LOCK OFFSET(0) NUMBITS(1) [], ], /// SoC Stepping ID @@ -523,16 +524,16 @@ struct SocRegistersImpl { // TODO: Functionality for mbox pauser regs needs to be implemented #[register_array(offset = 0x0048)] - cptra_mbox_valid_pauser: [u32; CPTRA_MBOX_VALID_PAUSER_SIZE / 4], + cptra_mbox_valid_axi_user: [u32; CPTRA_MBOX_VALID_PAUSER_SIZE / 4], #[register_array(offset = 0x005c)] - cptra_mbox_pauser_lock: [u32; CPTRA_MBOX_PAUSER_LOCK_SIZE / 4], + cptra_mbox_axi_user_lock: [u32; CPTRA_MBOX_PAUSER_LOCK_SIZE / 4], #[register(offset = 0x0070)] - cptra_trng_valid_pauser: ReadWriteRegister, + cptra_trng_valid_axi_user: ReadWriteRegister, #[register(offset = 0x0074)] - cptra_trng_pauser_lock: ReadWriteRegister, + cptra_trng_axi_user_lock: ReadWriteRegister, #[register_array(offset = 0x0078)] cptra_trng_data: [u32; CPTRA_TRNG_DATA_SIZE / 4], @@ -596,10 +597,13 @@ struct SocRegistersImpl { // TODO: Functionality for fuse pauser regs needs to be implemented #[register(offset = 0x0108)] - cptra_fuse_valid_pauser: ReadWriteRegister, + cptra_fuse_valid_axi_user: ReadWriteRegister, #[register(offset = 0x010c)] - cptra_fuse_pauser_lock: ReadWriteRegister, + cptra_fuse_axi_user_lock: ReadWriteRegister, + + #[register_array(offset = 0x110)] + cptra_wdt_cfg: [u32; 2], #[register(offset = 0x0118)] cptra_i_trng_entropy_config_0: u32, @@ -610,23 +614,33 @@ struct SocRegistersImpl { #[register_array(offset = 0x0120)] cptra_rsvd_reg: [u32; 2], + #[register(offset = 0x128)] + cptra_hw_capabilities: u32, + + #[register(offset = 0x12c)] + cptra_fw_capabilities: u32, + + #[register(offset = 0x130)] + cptra_cap_lock: ReadWriteRegister, + + // TODO implement lock + #[register_array(offset = 0x140)] + cptra_owner_pk_hash: [u32; CPTRA_OWNER_PK_HASH_SIZE / 4], + + #[register(offset = 0x170)] + cptra_owner_pk_hash_lock: u32, + #[register_array(offset = 0x0200)] fuse_uds_seed: [u32; FUSE_UDS_SEED_SIZE / 4], - #[register_array(offset = 0x110)] - cptra_wdt_cfg: [u32; 2], - - #[register_array(offset = 0x0230)] + #[register_array(offset = 0x0240)] fuse_field_entropy: [u32; FUSE_FIELD_ENTROPY_SIZE / 4], - #[register_array(offset = 0x0250)] - fuse_vendor_pk_hash: [u32; FUSE_VENDOR_PK_HASH_SIZE / 4], - - #[register(offset = 0x0280)] - fuse_vendor_pk_hash_mask: ReadWriteRegister, + #[register_array(offset = 0x0260)] + fuse_key_manifest_pk_hash: [u32; FUSE_KEY_MANIFEST_PK_HASH_SIZE / 4], - #[register_array(offset = 0x0284)] - fuse_owner_pk_hash: [u32; FUSE_OWNER_PK_HASH_SIZE / 4], + #[register_array(offset = 0x0290)] + fuse_key_manifest_pk_hash_mask: [u32; FUSE_KEY_MANIFEST_PK_HASH_MASK_SIZE / 4], #[register(offset = 0x02b4)] fuse_fmc_svn: u32, @@ -643,18 +657,18 @@ struct SocRegistersImpl { #[register_array(offset = 0x032c)] fuse_idevid_manuf_hsm_id: [u32; FUSE_IDEVID_MANUF_HSM_ID_SIZE / 4], - #[register(offset = 0x033c)] - fuse_life_cycle: u32, - #[register(offset = 0x340)] - fuse_lms_verify: ReadWriteRegister, + fuse_lms_revocation: u32, #[register(offset = 0x344)] - fuse_lms_revocation: u32, + fuse_mldsa_revocation: u32, #[register(offset = 0x348)] fuse_soc_stepping_id: ReadWriteRegister, + #[register_array(offset = 0x34c)] + fuse_manuf_dbg_unlock_token: [u32; FUSE_MANUF_DBG_UNLOCK_TOKEN_SIZE / 4], + /// INTERNAL_OBF_KEY Register internal_obf_key: [u32; 8], @@ -767,7 +781,8 @@ impl SocRegistersImpl { 0xF5, 0x8C, 0x4C, 0x4, 0xD6, 0xE5, 0xF1, 0xBA, 0x77, 0x9E, 0xAB, 0xFB, 0x5F, 0x7B, 0xFB, 0xD6, 0x9C, 0xFC, 0x4E, 0x96, 0x7E, 0xDB, 0x80, 0x8D, 0x67, 0x9F, 0x77, 0x7B, 0xC6, 0x70, 0x2C, 0x7D, 0x39, 0xF2, 0x33, 0x69, 0xA9, 0xD9, 0xBA, 0xCF, 0xA5, 0x30, 0xE2, 0x63, 0x4, - 0x23, 0x14, 0x61, + 0x23, 0x14, 0x61, 0x3B, 0x4, 0x38, 0x96, 0xCF, 0xE1, 0x95, 0x74, 0xFC, 0xA0, 0xA, 0xCC, + 0x2A, 0x5C, 0x31, 0xCD, ]; /// The number of CPU clock cycles it takes to read the firmware from the mailbox. @@ -798,10 +813,10 @@ impl SocRegistersImpl { cptra_flow_status: ReadWriteRegister::new(flow_status.get()), cptra_reset_reason: ReadOnlyRegister::new(0), cptra_security_state: ReadOnlyRegister::new(args.security_state.into()), - cptra_mbox_valid_pauser: Default::default(), - cptra_mbox_pauser_lock: Default::default(), - cptra_trng_valid_pauser: ReadWriteRegister::new(0), - cptra_trng_pauser_lock: ReadWriteRegister::new(0), + cptra_mbox_valid_axi_user: Default::default(), + cptra_mbox_axi_user_lock: Default::default(), + cptra_trng_valid_axi_user: ReadWriteRegister::new(0), + cptra_trng_axi_user_lock: ReadWriteRegister::new(0), cptra_trng_data: Default::default(), cptra_trng_ctrl: 0, cptra_trng_status: 0, @@ -815,20 +830,37 @@ impl SocRegistersImpl { cptra_hw_rev_id: ReadOnlyRegister::new(0x11), // TODO 2.0 cptra_fw_rev_id: Default::default(), cptra_hw_config: 0, + cptra_wdt_timer1_en: ReadWriteRegister::new(0), + cptra_wdt_timer1_ctrl: ReadWriteRegister::new(0), + cptra_wdt_timer1_timeout_period: [0xffff_ffff; 2], + cptra_wdt_timer2_en: ReadWriteRegister::new(0), + cptra_wdt_timer2_ctrl: ReadWriteRegister::new(0), + cptra_wdt_timer2_timeout_period: [0xffff_ffff; 2], + cptra_wdt_status: ReadOnlyRegister::new(0), + cptra_fuse_valid_axi_user: ReadWriteRegister::new(0xffff_ffff), + cptra_fuse_axi_user_lock: ReadWriteRegister::new(0), + cptra_wdt_cfg: [0x0; 2], + cptra_i_trng_entropy_config_0: 0, + cptra_i_trng_entropy_config_1: 0, + cptra_rsvd_reg: Default::default(), + cptra_hw_capabilities: 0, + cptra_fw_capabilities: 0, + cptra_cap_lock: ReadWriteRegister::new(0), + cptra_owner_pk_hash: Default::default(), + cptra_owner_pk_hash_lock: 0, fuse_uds_seed: words_from_bytes_be(&Self::UDS), fuse_field_entropy: [0xffff_ffff; 8], - fuse_vendor_pk_hash: Default::default(), - fuse_vendor_pk_hash_mask: ReadWriteRegister::new(0), - fuse_owner_pk_hash: Default::default(), + fuse_key_manifest_pk_hash: [0; 12], + fuse_key_manifest_pk_hash_mask: [0; 8], fuse_fmc_svn: Default::default(), fuse_runtime_svn: Default::default(), fuse_anti_rollback_disable: Default::default(), fuse_idevid_cert_attr: Default::default(), fuse_idevid_manuf_hsm_id: Default::default(), - fuse_life_cycle: Default::default(), - fuse_lms_verify: ReadWriteRegister::new(0), fuse_lms_revocation: Default::default(), + fuse_mldsa_revocation: Default::default(), fuse_soc_stepping_id: ReadWriteRegister::new(0), + fuse_manuf_dbg_unlock_token: [0; 4], internal_obf_key: args.cptra_obf_key, internal_iccm_lock: ReadWriteRegister::new(0), internal_fw_update_reset: ReadWriteRegister::new(0), @@ -856,35 +888,21 @@ impl SocRegistersImpl { tb_services_cb: args.tb_services_cb.take(), ready_for_fw_cb: args.ready_for_fw_cb.take(), upload_update_fw: args.upload_update_fw.take(), - fuses_can_be_written: true, bootfsm_go_cb: args.bootfsm_go_cb.take(), + fuses_can_be_written: true, download_idevid_csr_cb: args.download_idevid_csr_cb.take(), - cptra_wdt_timer1_en: ReadWriteRegister::new(0), - cptra_wdt_timer1_ctrl: ReadWriteRegister::new(0), - cptra_wdt_timer1_timeout_period: [0xffff_ffff; 2], - cptra_wdt_timer2_en: ReadWriteRegister::new(0), - cptra_wdt_timer2_ctrl: ReadWriteRegister::new(0), - cptra_wdt_timer2_timeout_period: [0xffff_ffff; 2], - cptra_wdt_status: ReadOnlyRegister::new(0), - cptra_i_trng_entropy_config_0: 0, - cptra_i_trng_entropy_config_1: 0, - cptra_rsvd_reg: Default::default(), op_wdt_timer1_expired_action: None, op_wdt_timer2_expired_action: None, etrng_responses: args.etrng_responses, pending_etrng_response: None, op_pending_etrng_response_action: None, - cptra_wdt_cfg: [0x0; 2], - cptra_fuse_valid_pauser: ReadWriteRegister::new(0xffff_ffff), - cptra_fuse_pauser_lock: ReadWriteRegister::new(0), }; - regs } /// Clear secrets fn clear_secrets(&mut self) { - self.fuse_uds_seed = [0u32; 12]; + self.fuse_uds_seed = [0u32; 16]; self.fuse_field_entropy = [0u32; 8]; self.internal_obf_key = [0u32; 8]; } @@ -1552,7 +1570,7 @@ mod tests { }, ); soc.external_regs().regs.borrow_mut().fuse_field_entropy = [0x33333333; 8]; - assert_eq!(soc.uds(), [0xff_u8; 48]); + assert_eq!(soc.uds(), [0xff_u8; 64]); assert_eq!(soc.field_entropy(), [0xff_u8; 32]); assert_eq!(soc.doe_key(), [0xff_u8; 32]); } diff --git a/test/src/derive.rs b/test/src/derive.rs index 8f85415351..2722133d5a 100644 --- a/test/src/derive.rs +++ b/test/src/derive.rs @@ -35,7 +35,7 @@ pub struct DoeInput { pub doe_iv: [u32; 4], // The UDS seed, as stored in the fuses - pub uds_seed: [u32; 12], + pub uds_seed: [u32; 16], // The field entropy, as stored in the fuses pub field_entropy_seed: [u32; 8], @@ -62,7 +62,7 @@ impl Default for DoeInput { #[derive(Clone, Copy, Debug, Eq, PartialEq)] pub struct DoeOutput { // The decrypted UDS as stored in the key vault - pub uds: [u32; 12], + pub uds: [u32; 16], // The decrypted field entropy as stored in the key vault (with padding) pub field_entropy: [u32; 12], @@ -85,7 +85,7 @@ impl DoeOutput { } let mut result = Self { - uds: [0_u32; 12], + uds: [0_u32; 16], // After reset, the key-vault registers are filled with a particular // word, depending on the debug-locked mode. The field entropy only @@ -129,7 +129,8 @@ fn test_doe_output() { doe_iv: [0x455ba825, 0x45e16ca6, 0xf97d1f86, 0xb3718021], uds_seed: [ 0x86c65f40, 0x04d45413, 0x5041da9a, 0x8580ec9a, 0xc7007ee6, 0xceb4a4b8, 0xce485f47, - 0xbf6976b8, 0xc906de7b, 0xb0cd2dce, 0x8d2b8eed, 0xa537255f, + 0xbf6976b8, 0xc906de7b, 0xb0cd2dce, 0x8d2b8eed, 0xa537255f, 0x2fd70f7c, 0xda37caeb, + 0xa748021, 0x34d2fd94, ], field_entropy_seed: [ 0x8531a3db, 0xc1725f07, 0x05f5a301, 0x047c1e27, 0xd0f18efa, 0x6a33e9d2, 0x3827ead4, @@ -142,7 +143,8 @@ fn test_doe_output() { DoeOutput { uds: [ 2450659586, 3204072599, 1027011035, 1213873878, 763047603, 1402117172, 2275304687, - 1797647086, 2750999, 2465724634, 992659675, 557913425 + 1797647086, 2750999, 2465724634, 992659675, 557913425, 1982584393, 56096072, + 3122931436, 3177452069 ], field_entropy: [ 437386532, 405572964, 972652519, 2702758929, 92052297, 1822317414, 295423989, @@ -197,7 +199,8 @@ fn test_idevid() { let idevid = IDevId::derive(&DoeOutput { uds: [ 0x92121902, 0xbefa4497, 0x3d36f1db, 0x485a3ed6, 0x2d7b2eb3, 0x53929c34, 0x879e64ef, - 0x6b25eaee, 0x0029fa17, 0x92f7f8da, 0x3b2ac8db, 0x21411551, + 0x6b25eaee, 0x0029fa17, 0x92f7f8da, 0x3b2ac8db, 0x21411551, 0xed0e3d62, 0x5e51aed, + 0x14199450, 0x45b540a1, ], field_entropy: [ 0xdbca1cfa, 0x149c0355, 0x7ee48ddb, 0xb022238b, 0x057c9b49, 0x6c9e5b66, 0x119bcff5, @@ -208,13 +211,13 @@ fn test_idevid() { idevid, IDevId { cdi: [ - 0x0ae8ec4b, 0x25da6d36, 0x6469502c, 0x94c7b654, 0xf78a5b9e, 0x1cef338f, 0xee5b5ecb, - 0x9b533c4e, 0xc11af69e, 0xe23d2612, 0x6b37a1fb, 0xd36e0914, 0x1f5d9fdc, 0x2927753a, - 0x4523e552, 0x5216eaf3, + 0xe047693d, 0x5038cf58, 0xbafff529, 0x4308aced, 0xd356fd37, 0x620386b3, 0xb2cfdd97, + 0x602e5b26, 0x29ff1601, 0xe3196949, 0xe04109ab, 0x9b6bcab1, 0xef5dc70d, 0xbd2d0875, + 0xf17a7559, 0x2328baa2, ], ecc_priv_key: [ - 0xaf16a87e, 0x14729bb6, 0xa9912ded, 0xe8331772, 0x288451ff, 0x4a304f24, 0xe02438c3, - 0xf3413e68, 0x4862cca1, 0xfe65126b, 0x1f3d8677, 0x36424b27, + 0x34d9279, 0x2e58660b, 0xcfa3e026, 0x90ac31dc, 0xb97a6b6c, 0xf259f7d4, 0xaa3b7a0d, + 0x565232ff, 0x38560790, 0x73ff1c04, 0x34501150, 0x48641108, ], } ); @@ -271,7 +274,8 @@ fn test_ldevid() { let ldevid = LDevId::derive(&DoeOutput { uds: [ 0x92121902, 0xbefa4497, 0x3d36f1db, 0x485a3ed6, 0x2d7b2eb3, 0x53929c34, 0x879e64ef, - 0x6b25eaee, 0x0029fa17, 0x92f7f8da, 0x3b2ac8db, 0x21411551, + 0x6b25eaee, 0x0029fa17, 0x92f7f8da, 0x3b2ac8db, 0x21411551, 0x57d115c, 0xfade7a, + 0xb8cca563, 0xe1f504a2, ], field_entropy: [ 0xdbca1cfa, 0x149c0355, 0x7ee48ddb, 0xb022238b, 0x057c9b49, 0x6c9e5b66, 0x119bcff5, @@ -282,13 +286,13 @@ fn test_ldevid() { ldevid, LDevId { cdi: [ - 0x179d3c40, 0xddca767f, 0x47cd8c43, 0x4dfe5832, 0x9e8f8119, 0xec29ffeb, 0x21fb3af5, - 0xd50a5ab4, 0x2d7b7d1d, 0x61e96220, 0xbc161735, 0xc66dce6f, 0x6dd8e4ec, 0xa28b66d7, - 0x28788a5f, 0x6f845a7c, + 0x5c705f09, 0x63f7edfb, 0x9cf0cb89, 0x7306da3f, 0xff1acde2, 0xf1f0b333, 0xafb85fa3, + 0x8783a424, 0x6c6aa9db, 0x43ce3297, 0x2568332, 0x53670f99, 0x9e4fff07, 0xdc1911f7, + 0xd7af58ed, 0xab20aff0, ], ecc_priv_key: [ - 0xec4cfba4, 0x28d8344c, 0xbb443f0d, 0xcca57231, 0x1b28d1df, 0x202aaff3, 0xc2f37cd3, - 0x7e1de81d, 0xfc624db2, 0x835f1a4, 0x37b02dbc, 0xd39e5a09, + 0x15e65daa, 0x3e7dedbb, 0x60eb7ea6, 0xd7e9e441, 0xf2adaa7a, 0x35ca904c, 0x9076d1a1, + 0x69972589, 0x274a2869, 0x48eb0fb4, 0xee749db1, 0x15cbe26e, ], } ); diff --git a/test/src/lib.rs b/test/src/lib.rs index ebcd55fa3b..44dba1f839 100644 --- a/test/src/lib.rs +++ b/test/src/lib.rs @@ -92,7 +92,12 @@ pub fn run_test( let mut model = caliptra_hw_model::new(init_params, boot_params).unwrap(); - model.step_until(|m| m.soc_ifc().cptra_flow_status().read().ready_for_fw()); + model.step_until(|m| { + m.soc_ifc() + .cptra_flow_status() + .read() + .ready_for_mb_processing() + }); model } diff --git a/test/tests/caliptra_integration_tests/jtag_test.rs b/test/tests/caliptra_integration_tests/jtag_test.rs index b64bdeb0d8..5b40aa04d4 100644 --- a/test/tests/caliptra_integration_tests/jtag_test.rs +++ b/test/tests/caliptra_integration_tests/jtag_test.rs @@ -94,7 +94,6 @@ fn gdb_test() { key_manifest_pk_hash: vendor_pk_desc_hash, owner_pk_hash, fmc_key_manifest_svn: 0b1111111, - lms_verify: true, ..Default::default() }; let mut hw = caliptra_hw_model::new( diff --git a/test/tests/caliptra_integration_tests/smoke_test.rs b/test/tests/caliptra_integration_tests/smoke_test.rs index 252c3192b0..770a9051fb 100644 --- a/test/tests/caliptra_integration_tests/smoke_test.rs +++ b/test/tests/caliptra_integration_tests/smoke_test.rs @@ -106,9 +106,9 @@ fn test_golden_idevid_pubkey_matches_generated() { assert_eq!( generated_idevid.cdi, [ - 3736836117, 951734631, 1062246775, 1343680552, 3737486010, 473346827, 2246415195, - 914173071, 357859522, 506223632, 1064260590, 4040292325, 1807964448, 3683558581, - 3839832324, 1615123947, + 1595302429, 2693222204, 2700750034, 2341068947, 1086336218, 1015077934, 3439704633, + 2756110496, 670106478, 1965056064, 3175014961, 1018544412, 1086626027, 1869434586, + 2638089882, 3209973098 ] ); assert!(generated_idevid @@ -125,9 +125,9 @@ fn test_golden_ldevid_pubkey_matches_generated() { assert_eq!( generated_ldevid.cdi, [ - 0x34caaef4, 0x5b1cf2cc, 0x80034cc7, 0xda97ab04, 0xfcf1df75, 0x48896447, 0x81e51dd4, - 0x80638cbe, 0xe349cfad, 0x4d70b120, 0xcbf5cc76, 0x8c00bb5c, 0x10179e15, 0xfdd9244b, - 0x6226db25, 0xd4f08f3d, + 2646856615, 2999180291, 4071428836, 3246385254, 3302857457, 919578714, 2458268004, + 291060689, 3979116117, 4017638804, 3557014009, 2639554114, 2914235687, 3521247795, + 1993163061, 3092908117 ] ); assert!(generated_ldevid @@ -163,7 +163,6 @@ fn smoke_test() { owner_pk_hash: owner_pk_hash_words, fmc_key_manifest_svn: 0b1111111, runtime_svn: [0x7F, 0, 0, 0], // Equals 7 - lms_verify: true, ..Default::default() }; let mut hw = caliptra_hw_model::new( diff --git a/test/tests/caliptra_integration_tests/smoke_testdata/fmc_alias_cert_redacted.der b/test/tests/caliptra_integration_tests/smoke_testdata/fmc_alias_cert_redacted.der index 2cbe7ddd85bbe584457f1a882e2dfcea28552997..80846c57157e984426207112695765b105c7e6e0 100644 GIT binary patch delta 99 zcmV-p0G$8o2I>ZoTR%lPHbFEsFh(*nK{!P;K{YcoGcYhUMK&-(Mngt4L^DJ|I7UG+ zHZU_rK}JG0Ff~LnLNYQ#G&DvuLozZsGO?OR0u>?i6a+UF*JWhw;# DZs{Mq diff --git a/test/tests/caliptra_integration_tests/smoke_testdata/fmc_alias_cert_redacted.txt b/test/tests/caliptra_integration_tests/smoke_testdata/fmc_alias_cert_redacted.txt index 901b1b28c7..fb78315d10 100644 --- a/test/tests/caliptra_integration_tests/smoke_testdata/fmc_alias_cert_redacted.txt +++ b/test/tests/caliptra_integration_tests/smoke_testdata/fmc_alias_cert_redacted.txt @@ -4,7 +4,7 @@ Certificate: Serial Number: 44:44:44:44:44:44:44:44:44:44:44:44:44:44:44:44:44:44:44:44 Signature Algorithm: ecdsa-with-SHA384 - Issuer: CN=Caliptra 1.0 LDevID/serialNumber=DFC3F8F71FC244C9A62F5151EB0C6BE427742BCEC40C43151A9B85895955666A + Issuer: CN=Caliptra 1.0 LDevID/serialNumber=DE96A450F23A8E4A5333005E60BFCF4D3DA8FA1603FAFB605D2B22C44F4C2292 Validity Not Before: Jan 1 00:00:00 2023 GMT Not After : Dec 31 23:59:59 9999 GMT @@ -34,7 +34,7 @@ Certificate: X509v3 Subject Key Identifier: 44:44:44:44:44:44:44:44:44:44:44:44:44:44:44:44:44:44:44:44 X509v3 Authority Key Identifier: - DF:C3:F8:F7:1F:C2:44:C9:A6:2F:51:51:EB:0C:6B:E4:27:74:2B:CE + DE:96:A4:50:F2:3A:8E:4A:53:33:00:5E:60:BF:CF:4D:3D:A8:FA:16 Signature Algorithm: ecdsa-with-SHA384 Signature Value: 30:64:02:30:44:44:44:44:44:44:44:44:44:44:44:44:44:44: diff --git a/test/tests/caliptra_integration_tests/smoke_testdata/idevid_csr.der b/test/tests/caliptra_integration_tests/smoke_testdata/idevid_csr.der index 604f12d2e7d5d7d6e3eb8d74d03648982ceb9242..3df680220eed97bb92118464053bb012c708206f 100644 GIT binary patch delta 308 zcmV-40n7fo1HA(TFoFTOkpwb-H%3N9L`6n6L_%BoLS7Q7_#g+Kw>W#gzXd~ z%ZdaAYaWboU5uDx^7i|2+TJrpI%3irudXg_*giayQQZ0p58gIUx?L2x&TZNjoRRKj zYH0v4W&$w)q%bRzowd_$tdMh$-!9tiWv)O6r)Bye`~N2RbgejsEn4Gq=Gf(iJ27!z z_}hZ30xF`gbpOrZ%46N>wxGeV_mUk5pP7+&fJ6-Qx G+V{d><$DnT delta 306 zcmV-20nPrs1G@tRFoFTMkpwb-K{Q1)FgQ0wGea>(FgQdsLpC%wL^3i)F)~6lIYUD< zH#tHwF+?yqGBZRlMKwe?F)=qXLODS}F)%YkL_iGrUw&l>`@uLscXG9X8UNwh}1UXaWJRT!i4oPX@@~MRIJ&Kkkt5c z^DB=d5)|7^hwN;ir4tX;$7S%Ww(%U4)I*KD2r$re3)SiFpV8FOE465fss5933z6<+ zXlDR0WCAcEltGo4hl#WMb!T$tas19$nv5WvU z1=^MZFjRj-T$@4gJKcRivKghw7KOLSg&m$I8@g}RYe*oC>ajuB_|&D>R%cO#NRSG# E${|I57ytkO diff --git a/test/tests/caliptra_integration_tests/smoke_testdata/idevid_csr.txt b/test/tests/caliptra_integration_tests/smoke_testdata/idevid_csr.txt index 61b0b36de3..03be72f9ac 100644 --- a/test/tests/caliptra_integration_tests/smoke_testdata/idevid_csr.txt +++ b/test/tests/caliptra_integration_tests/smoke_testdata/idevid_csr.txt @@ -1,18 +1,18 @@ Certificate Request: Data: Version: 1 (0x0) - Subject: CN=Caliptra 1.0 IDevID/serialNumber=A4E4087E3C1F08D4C647D22F12B49CC479B21D0923D0E5D81172B9AA103DDCCA + Subject: CN=Caliptra 1.0 IDevID/serialNumber=7FFEDEF6DCD6697BD0F381AA37B58112F24BDDB5550D2C791B5798AD202A0351 Subject Public Key Info: Public Key Algorithm: id-ecPublicKey Public-Key: (384 bit) pub: - 04:06:3d:ee:99:b8:27:78:0d:a6:07:13:6e:ec:51: - 19:bd:a9:6b:bd:36:66:fb:68:c4:88:d4:36:e2:71: - 30:a7:d3:c2:84:f5:31:69:87:41:54:ac:d9:8e:90: - d4:f8:72:f3:2b:8f:23:12:14:db:4c:87:ec:6c:a0: - a5:13:0f:d5:c7:65:f0:ac:b6:f1:1c:94:d4:43:8d: - bc:08:30:d0:74:0b:d5:e9:ee:9f:d1:d4:d1:2b:b5: - 68:8a:a9:fe:93:71:0b + 04:31:8c:e7:cc:f1:0d:d3:2f:48:1c:3d:76:fc:64: + ba:21:5b:54:d5:c8:60:ad:c7:46:2f:22:32:1c:af: + 26:47:43:9c:59:cc:ac:18:b2:ec:40:62:2f:18:84: + ed:14:23:cb:8a:04:05:6b:1e:8c:71:5d:8c:98:63: + f2:f6:fb:71:da:de:33:46:3a:62:d2:1b:af:ae:2e: + 6d:d8:3e:3c:93:51:dc:fa:0a:0f:de:36:4f:ba:5d: + 14:b9:ce:6d:da:16:9c ASN1 OID: secp384r1 NIST CURVE: P-384 Attributes: @@ -25,9 +25,9 @@ Certificate Request: 0.................... Signature Algorithm: ecdsa-with-SHA384 Signature Value: - 30:64:02:30:22:94:41:95:98:87:89:b3:fb:75:67:72:e7:e3: - f2:b0:3f:12:5d:4d:92:e5:8b:d8:c2:a0:44:4a:0c:bc:94:77: - c2:3d:62:0d:cc:a8:0e:6f:b5:b1:8c:00:35:05:da:96:02:30: - 54:7f:43:5c:9b:41:f0:3b:dd:7d:40:b2:19:a5:c8:16:85:b7: - c8:85:1d:9e:26:1b:ba:6f:d5:6b:48:20:8d:ea:b1:41:d7:f8: - d4:a5:d7:56:67:51:85:48:90:0a:b1:ca + 30:66:02:31:00:a4:30:2b:92:9d:b5:d3:6e:ac:90:73:8f:df: + 2e:da:ed:65:ae:40:07:a7:65:fa:20:fb:ff:26:f8:74:ad:38: + 86:2d:5a:e3:73:e6:d8:e5:86:3b:31:71:5f:f8:db:82:ab:02: + 31:00:ae:da:6c:36:13:2f:9d:17:de:c2:e2:a4:8f:82:fd:5a: + 38:e9:f0:4f:a5:9f:95:39:28:0c:ac:ee:92:b8:2c:f7:1d:96: + 77:15:10:4e:12:5b:6d:3b:5d:ef:5d:da:f7:c2 diff --git a/test/tests/caliptra_integration_tests/smoke_testdata/ldevid_cert.der b/test/tests/caliptra_integration_tests/smoke_testdata/ldevid_cert.der index 4114083c4e5d38b4fa721baba12ca4fb4dd90245..c9b81aa89e8baa41761263d33dd1683df5d0ad94 100644 GIT binary patch delta 473 zcmZ3;x`zkK)1&g#l-`?GiFC@c(~6)%Hn%!&G+x3x?&TiEK`F1wHHROPN}g zy!@7Jb1rUjVm;>M|Mu{S%Pz~prZBQNKMu^EIPdX}h{Awro09(XHy%r!ypS=h{vMWq zF_33t4wY4AkuVTz5HV>y?zLL5FouKqM#ZGnUD|bz$($Ue- zz}Usb+1YX8tblqqXJa=DH*-TbXCo66XG=#jBR5k+Q$trL17|ZQR}&+1a}y&cXIEzv z17{OspoF8PlZB~;rKzQvt^WJdA$qO07>hEI- z7z24W=1^H>76}8f29Yz~bKJ^4u}Czpd9>O8O=Q-~u&`VME;bIZgISoFnbR2zQkV>K zTMA;ey4(KvU7B-9@Nw_%*N2=xc1|%}&SaRq(#-N#cmI~U&B<}^EUe?aAFq>EVqr2c zxyE$ohIYr39Sj@FqQWy*V!XZDE! E09QS;pa1{> diff --git a/test/tests/caliptra_integration_tests/smoke_testdata/ldevid_cert.txt b/test/tests/caliptra_integration_tests/smoke_testdata/ldevid_cert.txt index 4c22e355cf..f3071fd64c 100644 --- a/test/tests/caliptra_integration_tests/smoke_testdata/ldevid_cert.txt +++ b/test/tests/caliptra_integration_tests/smoke_testdata/ldevid_cert.txt @@ -2,24 +2,24 @@ Certificate: Data: Version: 3 (0x2) Serial Number: - 5f:c3:f8:f7:1f:c2:44:c9:a6:2f:51:51:eb:0c:6b:e4:27:74:2b:ce + 5e:96:a4:50:f2:3a:8e:4a:53:33:00:5e:60:bf:cf:4d:3d:a8:fa:16 Signature Algorithm: ecdsa-with-SHA384 - Issuer: CN=Caliptra 1.0 IDevID/serialNumber=A4E4087E3C1F08D4C647D22F12B49CC479B21D0923D0E5D81172B9AA103DDCCA + Issuer: CN=Caliptra 1.0 IDevID/serialNumber=7FFEDEF6DCD6697BD0F381AA37B58112F24BDDB5550D2C791B5798AD202A0351 Validity Not Before: Jan 1 00:00:00 2023 GMT Not After : Dec 31 23:59:59 9999 GMT - Subject: CN=Caliptra 1.0 LDevID/serialNumber=DFC3F8F71FC244C9A62F5151EB0C6BE427742BCEC40C43151A9B85895955666A + Subject: CN=Caliptra 1.0 LDevID/serialNumber=DE96A450F23A8E4A5333005E60BFCF4D3DA8FA1603FAFB605D2B22C44F4C2292 Subject Public Key Info: Public Key Algorithm: id-ecPublicKey Public-Key: (384 bit) pub: - 04:09:c7:e7:63:d1:07:f9:38:73:0e:e9:7b:0e:f0: - 13:f3:af:a1:96:9e:ab:15:d8:67:06:4b:ea:87:fc: - 3c:3c:d7:c4:73:a3:a3:1f:6d:50:df:51:ad:25:77: - 27:db:d9:2f:9a:02:8f:2f:da:ac:02:1e:b7:86:f3: - 15:fb:41:da:60:f7:a4:bc:39:3d:84:ce:d8:f4:4f: - c0:a4:09:37:c2:8c:f5:b9:be:a7:7a:b0:dc:c4:41: - 68:c1:70:e7:8d:57:01 + 04:e0:1c:57:6c:ae:bb:0f:d1:ae:e1:08:d1:83:6f: + 5b:9a:a0:48:73:71:b0:71:50:cd:b6:ba:12:37:70: + 4f:ff:c0:25:3d:e4:50:40:95:47:10:00:a7:75:61: + 06:42:7e:70:8c:ae:3f:75:02:85:22:4a:4e:a6:b6: + 43:73:82:42:05:c6:42:4f:ed:c3:c8:d3:44:a6:56: + 94:01:04:43:e3:51:6b:91:9e:e3:b8:58:71:50:96: + b2:62:ff:0f:81:c6:65 ASN1 OID: secp384r1 NIST CURVE: P-384 X509v3 extensions: @@ -30,14 +30,14 @@ Certificate: 2.23.133.5.4.4: 0.................... X509v3 Subject Key Identifier: - DF:C3:F8:F7:1F:C2:44:C9:A6:2F:51:51:EB:0C:6B:E4:27:74:2B:CE + DE:96:A4:50:F2:3A:8E:4A:53:33:00:5E:60:BF:CF:4D:3D:A8:FA:16 X509v3 Authority Key Identifier: - CC:4B:9C:46:76:F2:04:18:83:AC:E2:B3:4F:EC:59:6A:E9:56:56:6D + 34:81:C7:4A:AB:11:71:5C:08:03:D8:78:92:AB:8A:2B:7E:B2:2A:90 Signature Algorithm: ecdsa-with-SHA384 Signature Value: - 30:64:02:30:6d:84:70:5d:2a:8b:86:fc:4e:d2:9c:c2:11:e3: - 8d:bb:eb:c2:43:f1:89:94:35:a7:02:31:6b:a9:36:39:fa:8b: - 8f:b4:7e:b3:63:5e:ee:38:3b:5e:4b:e3:ae:1b:22:04:02:30: - 34:d6:02:dc:d8:88:e4:63:af:0e:60:2a:7d:ea:5b:fc:94:d2: - 02:5b:03:ee:67:8e:ce:e0:aa:a7:14:a0:e8:80:42:28:5a:9f: - b8:dc:2a:cc:d8:76:23:bc:63:99:8e:16 + 30:65:02:30:3b:2b:4e:7e:2d:38:57:1d:90:63:df:ae:62:8d: + 02:18:d6:d1:7f:17:56:a1:39:83:83:21:99:22:da:4e:b1:5a: + 82:41:26:a1:1c:f4:cf:bc:11:5b:f6:c0:88:3f:e7:49:02:31: + 00:97:52:49:d6:b9:70:d1:72:1e:75:df:71:90:55:d1:19:31: + d3:9a:81:01:2d:8d:8d:20:33:2b:87:0c:7e:53:8c:d5:55:24: + 16:e4:eb:24:de:37:4d:68:94:e1:a8:96:e0 diff --git a/test/tests/caliptra_integration_tests/test_code_coverage.rs b/test/tests/caliptra_integration_tests/test_code_coverage.rs index da1a551b95..a428590446 100644 --- a/test/tests/caliptra_integration_tests/test_code_coverage.rs +++ b/test/tests/caliptra_integration_tests/test_code_coverage.rs @@ -29,7 +29,12 @@ fn test_emu_coverage() { ) .unwrap(); // Upload FW - hw.step_until(|m| m.soc_ifc().cptra_flow_status().read().ready_for_fw()); + hw.step_until(|m| { + m.soc_ifc() + .cptra_flow_status() + .read() + .ready_for_mb_processing() + }); let CoverageBitmaps { rom, iccm: _iccm } = hw.code_coverage_bitmap(); calculator::coverage_from_bitmap(0, rom, &instr_pcs) }; diff --git a/test/tests/fips_test_suite/common.rs b/test/tests/fips_test_suite/common.rs index e96fa409a5..392da7acf9 100755 --- a/test/tests/fips_test_suite/common.rs +++ b/test/tests/fips_test_suite/common.rs @@ -210,7 +210,12 @@ pub fn fips_test_init_to_rom( let mut model = fips_test_init_base(init_params, boot_params); // Step to ready for FW in ROM - model.step_until(|m| m.soc_ifc().cptra_flow_status().read().ready_for_fw()); + model.step_until(|m| { + m.soc_ifc() + .cptra_flow_status() + .read() + .ready_for_mb_processing() + }); model } diff --git a/test/tests/fips_test_suite/fw_load.rs b/test/tests/fips_test_suite/fw_load.rs index 2efafb0061..6de7a4b63c 100755 --- a/test/tests/fips_test_suite/fw_load.rs +++ b/test/tests/fips_test_suite/fw_load.rs @@ -227,7 +227,12 @@ fn fw_load_error_flow_base( }) .unwrap(); - hw.step_until(|m| m.soc_ifc().cptra_flow_status().read().ready_for_fw()); + hw.step_until(|m| { + m.soc_ifc() + .cptra_flow_status() + .read() + .ready_for_mb_processing() + }); // Verify we can load FW (use clean FW) hw.upload_firmware(&clean_fw_image.to_bytes().unwrap()) @@ -946,7 +951,6 @@ fn fw_load_error_vendor_lms_pub_key_index_mismatch() { // Turn LMS verify on let fuses = caliptra_hw_model::Fuses { - lms_verify: true, ..Default::default() }; @@ -960,9 +964,7 @@ fn fw_load_error_vendor_lms_pub_key_index_mismatch() { #[test] #[cfg(not(feature = "test_env_immutable_rom"))] fn fw_load_error_vendor_lms_verify_failure() { - // Turn LMS verify on let fuses = caliptra_hw_model::Fuses { - lms_verify: true, ..Default::default() }; @@ -981,9 +983,7 @@ fn fw_load_error_vendor_lms_pub_key_index_out_of_bounds() { // Set LMS pub key index to MAX + 1 fw_image.manifest.preamble.vendor_pqc_pub_key_idx = VENDOR_LMS_MAX_KEY_COUNT; - // Turn LMS verify on let fuses = caliptra_hw_model::Fuses { - lms_verify: true, ..Default::default() }; @@ -1013,9 +1013,7 @@ fn fw_load_error_vendor_lms_signature_invalid() { // Modify the vendor public key. lms_pub_key.digest = [Default::default(); 6]; - // Turn LMS verify on let fuses = caliptra_hw_model::Fuses { - lms_verify: true, ..Default::default() }; @@ -1044,9 +1042,7 @@ fn fw_load_error_fmc_runtime_load_addr_overlap() { #[test] #[cfg(not(feature = "test_env_immutable_rom"))] fn fw_load_error_owner_lms_verify_failure() { - // Turn LMS verify on let fuses = caliptra_hw_model::Fuses { - lms_verify: true, ..Default::default() }; @@ -1080,7 +1076,6 @@ fn fw_load_error_owner_lms_signature_invalid() { // Turn LMS verify on let fuses = caliptra_hw_model::Fuses { - lms_verify: true, ..Default::default() }; @@ -1104,7 +1099,6 @@ fn fw_load_error_vendor_lms_pub_key_revoked() { // Set fuses let fuses = caliptra_hw_model::Fuses { - lms_verify: true, fuse_lms_revocation: 1u32 << image_options.vendor_config.pqc_key_idx, ..Default::default() }; @@ -1162,9 +1156,7 @@ fn fw_load_error_update_reset_vendor_pqc_pub_key_idx_mismatch() { // Generate image let update_image = build_fw_image(image_options_update_reset); - // Turn LMS verify on let fuses = caliptra_hw_model::Fuses { - lms_verify: true, ..Default::default() }; @@ -1235,7 +1227,6 @@ fn fw_load_bad_pub_key_flow(fw_image: ImageBundle, exp_error_code: u32) { life_cycle: DeviceLifecycle::Production, key_manifest_pk_hash: vendor_pk_desc_hash, owner_pk_hash, - lms_verify: true, ..Default::default() }; diff --git a/test/tests/fips_test_suite/self_tests.rs b/test/tests/fips_test_suite/self_tests.rs index 1168527ec2..be9fba237f 100755 --- a/test/tests/fips_test_suite/self_tests.rs +++ b/test/tests/fips_test_suite/self_tests.rs @@ -130,7 +130,12 @@ fn self_test_failure_flow_rom(hook_code: u8, exp_error_code: u32) { })) } hw.boot(BootParams::default()).unwrap(); - hw.step_until(|m| m.soc_ifc().cptra_flow_status().read().ready_for_fw()); + hw.step_until(|m| { + m.soc_ifc() + .cptra_flow_status() + .read() + .ready_for_mb_processing() + }); // Verify crypto operations can be performed // Verify the SHA engine is usable @@ -226,7 +231,12 @@ fn self_test_failure_flow_rt(hook_code: u8, exp_error_code: u32) { hw = fips_test_init_model(None) } hw.boot(BootParams::default()).unwrap(); - hw.step_until(|m| m.soc_ifc().cptra_flow_status().read().ready_for_fw()); + hw.step_until(|m| { + m.soc_ifc() + .cptra_flow_status() + .read() + .ready_for_mb_processing() + }); // Verify crypto operations can be performed // Verify the SHA engine is usable From 3e13d2ea087cbf8d873ce53811c2739afff91712 Mon Sep 17 00:00:00 2001 From: Nick Quarton <139178705+nquarton@users.noreply.github.com> Date: Mon, 25 Nov 2024 13:42:03 -0800 Subject: [PATCH 45/51] Fixing release CI failures and adding frozen 1.1 ROM (#1809) * Fixing release CI failures and adding frozen 1.1 ROM * Changing CI ROM version from rust feature to environment variable * Removing reference to main branch in release flow Prevents a release being made from main when tests were actuall run on a different branch/commit (cherry picked from commit 5daf1b42842d7344bbc032f1700f56355d981624) --- .github/workflows/fpga.yml | 13 ++++- .github/workflows/fw-test-emu.yml | 6 +++ .github/workflows/nightly-release.yml | 3 +- builder/src/lib.rs | 18 ++++++- runtime/Cargo.toml | 2 +- .../test_get_idev_csr.rs | 35 +++++++----- .../caliptra_integration_tests/smoke_test.rs | 50 ++++++++++++++---- .../fmc_alias_cert_redacted.der | Bin .../fmc_alias_cert_redacted.txt | 0 test/tests/fips_test_suite/common.rs | 8 ++- 10 files changed, 106 insertions(+), 29 deletions(-) rename test/tests/caliptra_integration_tests/smoke_testdata/{ => rom-latest}/fmc_alias_cert_redacted.der (100%) rename test/tests/caliptra_integration_tests/smoke_testdata/{ => rom-latest}/fmc_alias_cert_redacted.txt (100%) diff --git a/.github/workflows/fpga.yml b/.github/workflows/fpga.yml index b43eecdc04..979faedeae 100644 --- a/.github/workflows/fpga.yml +++ b/.github/workflows/fpga.yml @@ -23,6 +23,9 @@ on: hw-version: default: "latest" type: string + rom-version: + default: "latest" + type: string workflow_call: description: 'Set true for workflow_call' default: true @@ -162,6 +165,9 @@ jobs: run: | export CARGO_TARGET_AARCH64_UNKNOWN_LINUX_GNU_LINKER="aarch64-linux-gnu-gcc" export CARGO_TARGET_AARCH64_UNKNOWN_LINUX_GNU_RUSTFLAGS="-C link-arg=--sysroot=$FARGO_SYSROOT" + if [ "${{ inputs.rom-version }}" != "latest" ]; then + export CPTRA_CI_ROM_VERSION="${{ inputs.rom-version }}" + fi if [ "${{ inputs.workflow_call }}" ]; then FEATURES=fpga_realtime,${{ inputs.extra-features }} @@ -429,7 +435,12 @@ jobs: # echo "Unexpected inputs.rom-logging: ${{ inputs.rom-logging }}" # exit 1 # fi - # echo CPTRA_ROM_TYPE=${CPTRA_ROM_TYPE} + +# if [[ "${{ inputs.workflow_call }}" && "${{ inputs.rom-version }}" != "latest" ]]; then +# VARS+=" CPTRA_CI_ROM_VERSION="${{ inputs.rom-version }}"" +# fi + + # echo VARS=${VARS} # COMMON_ARGS=( # --cargo-metadata="${TEST_BIN}/target/nextest/cargo-metadata.json" diff --git a/.github/workflows/fw-test-emu.yml b/.github/workflows/fw-test-emu.yml index b600ba6231..33d270edb7 100644 --- a/.github/workflows/fw-test-emu.yml +++ b/.github/workflows/fw-test-emu.yml @@ -13,6 +13,9 @@ on: rom-logging: default: true type: boolean + rom-version: + default: "latest" + type: string jobs: build_and_test: @@ -57,6 +60,9 @@ jobs: - name: Run tests run: | export CALIPTRA_PREBUILT_FW_DIR=/tmp/caliptra-test-firmware + if [ "${{ inputs.rom-version }}" != "latest" ]; then + export CPTRA_CI_ROM_VERSION="${{ inputs.rom-version }}" + fi if [ "${{ inputs.rom-logging }}" == "true" ] || [ -z "${{ inputs.rom-logging }}" ]; then export CPTRA_ROM_TYPE=ROM_WITH_UART diff --git a/.github/workflows/nightly-release.yml b/.github/workflows/nightly-release.yml index 49c6bf4d89..06b207144a 100644 --- a/.github/workflows/nightly-release.yml +++ b/.github/workflows/nightly-release.yml @@ -23,7 +23,6 @@ jobs: - uses: actions/checkout@v3 with: submodules: 'true' - ref: 'main' fetch-depth: 0 - name: Find latest release @@ -100,7 +99,7 @@ jobs: with: artifact-suffix: -fpga-realtime-latest-itrng-nolog extra-features: slow_tests,itrng - hw-version: latest + hw-version: "latest" rom-logging: false fpga-itrng: true diff --git a/builder/src/lib.rs b/builder/src/lib.rs index 0c7bd7df70..cd3f1d4ef1 100644 --- a/builder/src/lib.rs +++ b/builder/src/lib.rs @@ -35,6 +35,11 @@ use once_cell::sync::Lazy; pub const THIS_WORKSPACE_DIR: &str = concat!(env!("CARGO_MANIFEST_DIR"), "/.."); +#[derive(Debug, PartialEq)] +pub enum CiRomVersion { + Latest, +} + fn other_err(e: impl Into>) -> io::Error { io::Error::new(ErrorKind::Other, e) } @@ -355,11 +360,22 @@ pub fn build_firmware_elf(id: &FwId<'static>) -> io::Result>> { Ok(result) } +// Returns the ROM version to be used for CI testing specified in the environment variable "CPTRA_CI_ROM_VERSION" +// Default is Latest +pub fn get_ci_rom_version() -> CiRomVersion { + match std::env::var("CPTRA_CI_ROM_VERSION").as_deref() { + Ok(version) => panic!("Unknown CI ROM version \'{}\'", version), + Err(_) => CiRomVersion::Latest, + } +} + /// Returns the most appropriate ROM for use when testing non-ROM code against /// a particular hardware version. DO NOT USE this for ROM-only tests. pub fn rom_for_fw_integration_tests() -> io::Result> { let rom_from_env = firmware::rom_from_env(); - Ok(build_firmware_rom(rom_from_env)?.into()) + match get_ci_rom_version() { + CiRomVersion::Latest => Ok(build_firmware_rom(rom_from_env)?.into()), + } } pub fn build_firmware_rom(id: &FwId<'static>) -> io::Result> { diff --git a/runtime/Cargo.toml b/runtime/Cargo.toml index 74eb20feba..0323f58eb4 100644 --- a/runtime/Cargo.toml +++ b/runtime/Cargo.toml @@ -64,4 +64,4 @@ verilator = ["caliptra-hw-model/verilator"] fips_self_test=[] no-cfi = ["caliptra-image-verify/no-cfi", "caliptra-drivers/no-cfi"] fpga_realtime = ["caliptra-drivers/fpga_realtime"] -fips-test-hooks = ["caliptra-drivers/fips-test-hooks"] +fips-test-hooks = ["caliptra-drivers/fips-test-hooks"] \ No newline at end of file diff --git a/runtime/tests/runtime_integration_tests/test_get_idev_csr.rs b/runtime/tests/runtime_integration_tests/test_get_idev_csr.rs index 13078f7e60..b986816962 100644 --- a/runtime/tests/runtime_integration_tests/test_get_idev_csr.rs +++ b/runtime/tests/runtime_integration_tests/test_get_idev_csr.rs @@ -1,6 +1,7 @@ // Licensed under the Apache-2.0 license use caliptra_api::SocManager; +use caliptra_builder::{get_ci_rom_version, CiRomVersion}; use caliptra_common::mailbox_api::{CommandId, GetIdevCsrResp, MailboxReqHeader}; use caliptra_drivers::{IdevIdCsr, MfgFlags}; use caliptra_error::CaliptraError; @@ -25,20 +26,23 @@ fn test_get_csr() { chksum: caliptra_common::checksum::calc_checksum(u32::from(CommandId::GET_IDEV_CSR), &[]), }; - let response = model - .mailbox_execute(CommandId::GET_IDEV_CSR.into(), payload.as_bytes()) - .unwrap() - .unwrap(); + let result = model.mailbox_execute(CommandId::GET_IDEV_CSR.into(), payload.as_bytes()); + + match get_ci_rom_version() { + CiRomVersion::Latest => { + let response = result.unwrap().unwrap(); - let get_idv_csr_resp = GetIdevCsrResp::read_from(response.as_bytes()).unwrap(); + let get_idv_csr_resp = GetIdevCsrResp::read_from(response.as_bytes()).unwrap(); - assert_ne!(IdevIdCsr::UNPROVISIONED_CSR, get_idv_csr_resp.data_size); - assert_ne!(0, get_idv_csr_resp.data_size); + assert_ne!(IdevIdCsr::UNPROVISIONED_CSR, get_idv_csr_resp.data_size); + assert_ne!(0, get_idv_csr_resp.data_size); - let csr_bytes = &get_idv_csr_resp.data[..get_idv_csr_resp.data_size as usize]; - assert_ne!([0; 512], csr_bytes); + let csr_bytes = &get_idv_csr_resp.data[..get_idv_csr_resp.data_size as usize]; + assert_ne!([0; 512], csr_bytes); - assert!(X509Req::from_der(csr_bytes).is_ok()); + assert!(X509Req::from_der(csr_bytes).is_ok()); + } + }; } #[test] @@ -56,8 +60,11 @@ fn test_missing_csr() { let response = model .mailbox_execute(CommandId::GET_IDEV_CSR.into(), payload.as_bytes()) .unwrap_err(); - assert_eq!( - response, - ModelError::MailboxCmdFailed(CaliptraError::RUNTIME_GET_IDEV_ID_UNPROVISIONED.into()) - ); + + match get_ci_rom_version() { + CiRomVersion::Latest => assert_eq!( + response, + ModelError::MailboxCmdFailed(CaliptraError::RUNTIME_GET_IDEV_ID_UNPROVISIONED.into()) + ), + }; } diff --git a/test/tests/caliptra_integration_tests/smoke_test.rs b/test/tests/caliptra_integration_tests/smoke_test.rs index 770a9051fb..e2223fbd89 100644 --- a/test/tests/caliptra_integration_tests/smoke_test.rs +++ b/test/tests/caliptra_integration_tests/smoke_test.rs @@ -26,6 +26,36 @@ use regex::Regex; use std::mem; use zerocopy::AsBytes; +// Support testing against older versions of ROM in CI +// More constants may need to be added here as the ROMs further diverge +struct RomTestParams<'a> { + #[allow(dead_code)] + testdata_path: &'a str, + fmc_alias_cert_redacted_txt: &'a str, + fmc_alias_cert_redacted_der: &'a [u8], + tcb_info_vendor: Option<&'a str>, + tcb_device_info_model: Option<&'a str>, + tcb_fmc_info_model: Option<&'a str>, + tcb_info_flags: Option, +} +const ROM_LATEST_TEST_PARAMS: RomTestParams = RomTestParams { + testdata_path: "tests/caliptra_integration_tests/smoke_testdata/rom-latest", + fmc_alias_cert_redacted_txt: include_str!( + "smoke_testdata/rom-latest/fmc_alias_cert_redacted.txt" + ), + fmc_alias_cert_redacted_der: include_bytes!( + "smoke_testdata/rom-latest/fmc_alias_cert_redacted.der" + ), + tcb_info_vendor: None, + tcb_device_info_model: None, + tcb_fmc_info_model: None, + tcb_info_flags: Some(0x00000001), +}; + +fn get_rom_test_params() -> RomTestParams<'static> { + ROM_LATEST_TEST_PARAMS +} + #[track_caller] fn assert_output_contains(haystack: &str, needle: &str) { assert!( @@ -276,8 +306,10 @@ fn smoke_test() { dice_tcb_info, [ DiceTcbInfo { - vendor: None, - model: None, + vendor: get_rom_test_params().tcb_info_vendor.map(String::from), + model: get_rom_test_params() + .tcb_device_info_model + .map(String::from), // This is from the SVN in the fuses (7 bits set) svn: Some(0x107), fwids: vec![DiceFwid { @@ -285,13 +317,13 @@ fn smoke_test() { digest: device_info_hash.to_vec(), },], - flags: Some(0x00000001), + flags: get_rom_test_params().tcb_info_flags, ty: Some(b"DEVICE_INFO".to_vec()), ..Default::default() }, DiceTcbInfo { - vendor: None, - model: None, + vendor: get_rom_test_params().tcb_info_vendor.map(String::from), + model: get_rom_test_params().tcb_fmc_info_model.map(String::from), // This is from the SVN in the image (9) svn: Some(0x109), fwids: vec![DiceFwid { @@ -402,16 +434,16 @@ fn smoke_test() { String::from_utf8(fmc_alias_cert_redacted.to_text().unwrap()).unwrap(); // To update the alias-cert golden-data: - // std::fs::write("tests/caliptra_integration_tests/smoke_testdata/fmc_alias_cert_redacted.txt", &fmc_alias_cert_redacted_txt).unwrap(); - // std::fs::write("tests/caliptra_integration_tests/smoke_testdata/fmc_alias_cert_redacted.der", &fmc_alias_cert_redacted_der).unwrap(); + // std::fs::write(format!("{}/fmc_alias_cert_redacted.txt", get_rom_test_params().testdata_path), &fmc_alias_cert_redacted_txt).unwrap(); + // std::fs::write(format!("{}/fmc_alias_cert_redacted.der", get_rom_test_params().testdata_path), &fmc_alias_cert_redacted_der).unwrap(); assert_eq!( fmc_alias_cert_redacted_txt.as_str(), - include_str!("smoke_testdata/fmc_alias_cert_redacted.txt") + get_rom_test_params().fmc_alias_cert_redacted_txt ); assert_eq!( fmc_alias_cert_redacted_der, - include_bytes!("smoke_testdata/fmc_alias_cert_redacted.der") + get_rom_test_params().fmc_alias_cert_redacted_der ); } diff --git a/test/tests/caliptra_integration_tests/smoke_testdata/fmc_alias_cert_redacted.der b/test/tests/caliptra_integration_tests/smoke_testdata/rom-latest/fmc_alias_cert_redacted.der similarity index 100% rename from test/tests/caliptra_integration_tests/smoke_testdata/fmc_alias_cert_redacted.der rename to test/tests/caliptra_integration_tests/smoke_testdata/rom-latest/fmc_alias_cert_redacted.der diff --git a/test/tests/caliptra_integration_tests/smoke_testdata/fmc_alias_cert_redacted.txt b/test/tests/caliptra_integration_tests/smoke_testdata/rom-latest/fmc_alias_cert_redacted.txt similarity index 100% rename from test/tests/caliptra_integration_tests/smoke_testdata/fmc_alias_cert_redacted.txt rename to test/tests/caliptra_integration_tests/smoke_testdata/rom-latest/fmc_alias_cert_redacted.txt diff --git a/test/tests/fips_test_suite/common.rs b/test/tests/fips_test_suite/common.rs index 392da7acf9..8efb047533 100755 --- a/test/tests/fips_test_suite/common.rs +++ b/test/tests/fips_test_suite/common.rs @@ -50,9 +50,14 @@ const ROM_EXP_1_0_1: RomExpVals = RomExpVals { ], }; +const ROM_EXP_1_0_3: RomExpVals = RomExpVals { + rom_version: 0x803, // 1.0.3 + ..ROM_EXP_1_0_1 +}; + const ROM_EXP_1_1_0: RomExpVals = RomExpVals { rom_version: 0x840, // 1.1.0 - ..ROM_EXP_1_0_1 + ..ROM_EXP_1_0_3 }; const ROM_EXP_CURRENT: RomExpVals = RomExpVals { ..ROM_EXP_1_1_0 }; @@ -101,6 +106,7 @@ impl RomExpVals { match version.as_str() { // Add more versions here "1_0_1" => ROM_EXP_1_0_1, + "1_0_3" => ROM_EXP_1_0_3, _ => panic!( "FIPS Test: Unknown version for expected ROM values ({})", version From c334dc614f8de9ea95a80a97a2706327623e2d7d Mon Sep 17 00:00:00 2001 From: Nick Quarton <139178705+nquarton@users.noreply.github.com> Date: Mon, 2 Dec 2024 09:05:14 -0800 Subject: [PATCH 46/51] Updating ROM version to 1.2.0 (#1818) (cherry picked from commit 3b50c6ab227bba973da2e6ca33a0a5012fde7146) --- FROZEN_IMAGES.sha384sum | 4 ++-- builder/src/version.rs | 2 +- test/tests/fips_test_suite/common.rs | 7 ++++++- 3 files changed, 9 insertions(+), 4 deletions(-) diff --git a/FROZEN_IMAGES.sha384sum b/FROZEN_IMAGES.sha384sum index 8138d5d756..149f78dccc 100644 --- a/FROZEN_IMAGES.sha384sum +++ b/FROZEN_IMAGES.sha384sum @@ -1,3 +1,3 @@ # WARNING: Do not update this file without the approval of the Caliptra TAC -129ee84ecdc1f80a9aab51883589b4eb80191bc726277fb31fab2bb2e99f54b3ad7dc80459914c9cd9749e5994614ccd caliptra-rom-no-log.bin -162eb324937462a1534406d43b9ba74b229d9347541f148eebc435f901e839e4c95af308f91b873f0bc67124cf35ecc1 caliptra-rom-with-log.bin +df4a72ee4a88d12d7216f8d23c6567b479694dec959e7332d69094098d312ea2dbf35de1117db156635ad41a78bf3c14 caliptra-rom-no-log.bin +02db1204eea812bee28904ce877ec7604746169fa7bfa82471cf10af239852466c1a16b2d5b3b9ad26b4ccfe2ca0a1b5 caliptra-rom-with-log.bin diff --git a/builder/src/version.rs b/builder/src/version.rs index 36d57e2d12..bb881ab230 100755 --- a/builder/src/version.rs +++ b/builder/src/version.rs @@ -1,7 +1,7 @@ // Licensed under the Apache-2.0 license pub const ROM_VERSION_MAJOR: u16 = 1; -pub const ROM_VERSION_MINOR: u16 = 1; +pub const ROM_VERSION_MINOR: u16 = 2; pub const ROM_VERSION_PATCH: u16 = 0; pub const FMC_VERSION_MAJOR: u16 = 1; diff --git a/test/tests/fips_test_suite/common.rs b/test/tests/fips_test_suite/common.rs index 8efb047533..d387c3b823 100755 --- a/test/tests/fips_test_suite/common.rs +++ b/test/tests/fips_test_suite/common.rs @@ -60,7 +60,12 @@ const ROM_EXP_1_1_0: RomExpVals = RomExpVals { ..ROM_EXP_1_0_3 }; -const ROM_EXP_CURRENT: RomExpVals = RomExpVals { ..ROM_EXP_1_1_0 }; +const ROM_EXP_1_2_0: RomExpVals = RomExpVals { + rom_version: 0x880, // 1.2.0 + ..ROM_EXP_1_1_0 +}; + +const ROM_EXP_CURRENT: RomExpVals = RomExpVals { ..ROM_EXP_1_2_0 }; // === RUNTIME === pub struct RtExpVals { From 639941fa2ac077472184f21b975f166d98f6190c Mon Sep 17 00:00:00 2001 From: Carl Lundin Date: Fri, 1 Nov 2024 11:16:41 -0700 Subject: [PATCH 47/51] Added stack monitoring and overflow detection to the SW emulator (cherry picked from commit 2f8f19be70f2971af818b8d35b74c878212aff72) --- drivers/src/memory_layout.rs | 2 +- hw-model/src/lib.rs | 6 + hw-model/src/model_emulated.rs | 8 +- rom/dev/src/rom.ld | 4 +- .../tests/rom_integration_tests/helpers.rs | 24 ++- .../tests/runtime_integration_tests/common.rs | 30 +++- sw-emulator/lib/cpu/src/cpu.rs | 158 +++++++++++++++++- sw-emulator/lib/cpu/src/lib.rs | 2 +- 8 files changed, 223 insertions(+), 11 deletions(-) diff --git a/drivers/src/memory_layout.rs b/drivers/src/memory_layout.rs index 34f810c5af..70b9b9774a 100644 --- a/drivers/src/memory_layout.rs +++ b/drivers/src/memory_layout.rs @@ -81,7 +81,7 @@ pub const AUTH_MAN_IMAGE_METADATA_MAX_SIZE: u32 = 7 * 1024; pub const IDEVID_CSR_SIZE: u32 = 1024; pub const DATA_SIZE: u32 = 130 * 1024; pub const STACK_SIZE: u32 = 64 * 1024; -pub const ROM_STACK_SIZE: u32 = 14 * 1024; +pub const ROM_STACK_SIZE: u32 = 40 * 1024; pub const ESTACK_SIZE: u32 = 1024; pub const ROM_ESTACK_SIZE: u32 = 1024; pub const NSTACK_SIZE: u32 = 1024; diff --git a/hw-model/src/lib.rs b/hw-model/src/lib.rs index ee642945d0..7467662b42 100644 --- a/hw-model/src/lib.rs +++ b/hw-model/src/lib.rs @@ -45,6 +45,7 @@ mod rv32_builder; pub use api::mailbox::mbox_write_fifo; pub use api_types::{DeviceLifecycle, Fuses, SecurityState, U4}; pub use caliptra_emu_bus::BusMmio; +pub use caliptra_emu_cpu::{CodeRange, ImageInfo, StackInfo, StackRange}; use output::ExitStatus; pub use output::Output; @@ -176,6 +177,10 @@ pub struct InitParams<'a> { // A trace path to use. If None, the CPTRA_TRACE_PATH environment variable // will be used pub trace_path: Option, + + // Information about the stack Caliptra is using. When set the emulator will check if the stack + // overflows. + pub stack_info: Option, } impl<'a> Default for InitParams<'a> { fn default() -> Self { @@ -210,6 +215,7 @@ impl<'a> Default for InitParams<'a> { }), random_sram_puf: true, trace_path: None, + stack_info: None, } } } diff --git a/hw-model/src/model_emulated.rs b/hw-model/src/model_emulated.rs index c2515ee735..f94c22e4f4 100644 --- a/hw-model/src/model_emulated.rs +++ b/hw-model/src/model_emulated.rs @@ -187,7 +187,13 @@ impl HwModel for ModelEmulated { dccm_dest.copy_from_slice(params.dccm); } let soc_to_caliptra_bus = root_bus.soc_to_caliptra_bus(); - let cpu = Cpu::new(BusLogger::new(root_bus), clock); + let cpu = { + let mut cpu = Cpu::new(BusLogger::new(root_bus), clock); + if let Some(stack_info) = params.stack_info { + cpu.with_stack_info(stack_info); + } + cpu + }; let mut hasher = DefaultHasher::new(); std::hash::Hash::hash_slice(params.rom, &mut hasher); diff --git a/rom/dev/src/rom.ld b/rom/dev/src/rom.ld index 1e7fc8d241..ddda7b425e 100644 --- a/rom/dev/src/rom.ld +++ b/rom/dev/src/rom.ld @@ -20,7 +20,7 @@ ROM_ORG = 0x00000000; ICCM_ORG = 0x40000000; DCCM_ORG = 0x50000000; DATA_ORG = 0x50000000; -STACK_ORG = 0x5003C000; +STACK_ORG = 0x50035800; ESTACK_ORG = 0x5003F800; NSTACK_ORG = 0x5003FC00; @@ -36,7 +36,7 @@ ROM_SIZE = 96K; ICCM_SIZE = 128K; DCCM_SIZE = 256K; DATA_SIZE = 996; -STACK_SIZE = 14K; +STACK_SIZE = 40K; ESTACK_SIZE = 1K; NSTACK_SIZE = 1K; diff --git a/rom/dev/tests/rom_integration_tests/helpers.rs b/rom/dev/tests/rom_integration_tests/helpers.rs index f960726370..998dca3853 100644 --- a/rom/dev/tests/rom_integration_tests/helpers.rs +++ b/rom/dev/tests/rom_integration_tests/helpers.rs @@ -4,7 +4,14 @@ use std::mem; use caliptra_api::SocManager; use caliptra_builder::{firmware, ImageOptions}; -use caliptra_hw_model::{BootParams, Fuses, HwModel, InitParams, SecurityState}; +use caliptra_common::{ + memory_layout::{ROM_ORG, ROM_SIZE, ROM_STACK_ORG, ROM_STACK_SIZE, STACK_ORG, STACK_SIZE}, + FMC_ORG, FMC_SIZE, RUNTIME_ORG, RUNTIME_SIZE, +}; +use caliptra_hw_model::{ + BootParams, CodeRange, Fuses, HwModel, ImageInfo, InitParams, SecurityState, StackInfo, + StackRange, +}; use caliptra_hw_model::{DefaultHwModel, ModelError}; use caliptra_image_types::ImageBundle; @@ -18,10 +25,25 @@ pub fn build_hw_model_and_image_bundle( pub fn build_hw_model(fuses: Fuses) -> DefaultHwModel { let rom = caliptra_builder::build_firmware_rom(firmware::rom_from_env()).unwrap(); + let image_info = vec![ + ImageInfo::new( + StackRange::new(ROM_STACK_ORG + ROM_STACK_SIZE, ROM_STACK_ORG), + CodeRange::new(ROM_ORG, ROM_ORG + ROM_SIZE), + ), + ImageInfo::new( + StackRange::new(STACK_ORG + STACK_SIZE, STACK_ORG), + CodeRange::new(FMC_ORG, FMC_ORG + FMC_SIZE), + ), + ImageInfo::new( + StackRange::new(STACK_ORG + STACK_SIZE, STACK_ORG), + CodeRange::new(RUNTIME_ORG, RUNTIME_ORG + RUNTIME_SIZE), + ), + ]; caliptra_hw_model::new( InitParams { rom: &rom, security_state: SecurityState::from(fuses.life_cycle as u32), + stack_info: Some(StackInfo::new(image_info)), ..Default::default() }, BootParams { diff --git a/runtime/tests/runtime_integration_tests/common.rs b/runtime/tests/runtime_integration_tests/common.rs index 2f10a2c900..399542e723 100644 --- a/runtime/tests/runtime_integration_tests/common.rs +++ b/runtime/tests/runtime_integration_tests/common.rs @@ -5,13 +5,20 @@ use caliptra_builder::{ firmware::{APP_WITH_UART, APP_WITH_UART_FPGA, FMC_WITH_UART}, FwId, ImageOptions, }; -use caliptra_common::mailbox_api::{ - CommandId, GetFmcAliasCertResp, GetRtAliasCertResp, InvokeDpeReq, InvokeDpeResp, MailboxReq, - MailboxReqHeader, +use caliptra_common::{ + mailbox_api::{ + CommandId, GetFmcAliasCertResp, GetRtAliasCertResp, InvokeDpeReq, InvokeDpeResp, + MailboxReq, MailboxReqHeader, + }, + memory_layout::{ROM_ORG, ROM_SIZE, ROM_STACK_ORG, ROM_STACK_SIZE, STACK_ORG, STACK_SIZE}, + FMC_ORG, FMC_SIZE, RUNTIME_ORG, RUNTIME_SIZE, }; use caliptra_drivers::MfgFlags; use caliptra_error::CaliptraError; -use caliptra_hw_model::{BootParams, DefaultHwModel, Fuses, HwModel, InitParams, ModelError}; +use caliptra_hw_model::{ + BootParams, CodeRange, DefaultHwModel, Fuses, HwModel, ImageInfo, InitParams, ModelError, + StackInfo, StackRange, +}; use dpe::{ commands::{Command, CommandHdr}, response::{ @@ -65,11 +72,26 @@ pub fn run_rt_test_lms(args: RuntimeTestArgs) -> DefaultHwModel { opts }); + let image_info = vec![ + ImageInfo::new( + StackRange::new(ROM_STACK_ORG + ROM_STACK_SIZE, ROM_STACK_ORG), + CodeRange::new(ROM_ORG, ROM_ORG + ROM_SIZE), + ), + ImageInfo::new( + StackRange::new(STACK_ORG + STACK_SIZE, STACK_ORG), + CodeRange::new(FMC_ORG, FMC_ORG + FMC_SIZE), + ), + ImageInfo::new( + StackRange::new(STACK_ORG + STACK_SIZE, STACK_ORG), + CodeRange::new(RUNTIME_ORG, RUNTIME_ORG + RUNTIME_SIZE), + ), + ]; let rom = caliptra_builder::rom_for_fw_integration_tests().unwrap(); let init_params = match args.init_params { Some(init_params) => init_params, None => InitParams { rom: &rom, + stack_info: Some(StackInfo::new(image_info)), ..Default::default() }, }; diff --git a/sw-emulator/lib/cpu/src/cpu.rs b/sw-emulator/lib/cpu/src/cpu.rs index 78c1680f99..9e032e7595 100644 --- a/sw-emulator/lib/cpu/src/cpu.rs +++ b/sw-emulator/lib/cpu/src/cpu.rs @@ -22,6 +22,126 @@ use caliptra_emu_types::{RvAddr, RvData, RvException, RvSize}; pub type InstrTracer<'a> = dyn FnMut(u32, RvInstr) + 'a; +/// Describes a Caliptra stack memory region +pub struct StackRange(u32, u32); +impl StackRange { + /// **Note:** `stack_start` MUST be greater than `stack_end`. Caliptra's stack grows + /// to a lower address. + pub fn new(stack_start: u32, stack_end: u32) -> Self { + if stack_start < stack_end { + panic!("Caliptra's stack grows to a lower address"); + } + Self(stack_start, stack_end) + } +} + +/// Describes a Caliptra code region +pub struct CodeRange(u32, u32); +impl CodeRange { + pub fn new(code_start: u32, code_end: u32) -> Self { + if code_start > code_end { + panic!("code grows to a higher address"); + } + Self(code_start, code_end) + } +} + +/// Contains metadata describing a Caliptra image +pub struct ImageInfo { + stack_range: StackRange, + code_range: CodeRange, +} + +impl ImageInfo { + pub fn new(stack_range: StackRange, code_range: CodeRange) -> Self { + Self { + stack_range, + code_range, + } + } + + /// Checks if the program counter is contained in `self` + /// + /// returns `true` if the pc is in the image. `false` otherwise. + fn contains_pc(&self, pc: u32) -> bool { + self.code_range.0 <= pc && pc <= self.code_range.1 + } + + /// Checks if the stack pointer has overflowed. + /// + /// Returns `Some(u32)` if an overflow has occurred. The `u32` is set + /// to the overflow amount. + /// + /// Returns `None` if no overflow has occurred. + fn check_overflow(&self, sp: u32) -> Option { + let stack_end = self.stack_range.1; + + // Stack grows to a lower address + if sp < stack_end { + let current_overflow = stack_end - sp; + Some(current_overflow) + } else { + None + } + } +} + +/// Describes the shape of Caliptra's stacks. +/// +/// Used to monitor stack usage and check for overflows. +pub struct StackInfo { + images: Vec, + max_stack_overflow: u32, + has_overflowed: bool, +} + +impl StackInfo { + /// Create a new `StackInfo` by describing the start and end of the stack and code segment for each + /// Caliptra image. + pub fn new(images: Vec) -> Self { + Self { + images, + max_stack_overflow: 0, + has_overflowed: false, + } + } +} + +impl StackInfo { + /// Fetch the largest stack overflow. + /// + /// If the stack never overflowed, returns `None`. + fn max_stack_overflow(&self) -> Option { + if self.has_overflowed { + Some(self.max_stack_overflow) + } else { + None + } + } + + /// Checks if the stack will overflow when pushed to `stack_address`. + /// + /// Returns `Some(u32)` if the stack will overflow and by how much, `None` if it will not overflow. + fn check_overflow(&mut self, pc: u32, stack_address: u32) -> Option { + if stack_address == 0 { + // sp is initialized to 0. + return None; + } + + for image in self.images.iter() { + if image.contains_pc(pc) { + if let Some(overflow_amount) = image.check_overflow(stack_address) { + self.max_stack_overflow = self.max_stack_overflow.max(overflow_amount); + self.has_overflowed = true; + return Some(overflow_amount); + } + } + } + + None + } +} + #[derive(Clone)] pub struct CodeCoverage { rom_bit_vec: BitVec, @@ -162,6 +282,20 @@ pub struct Cpu { pub(crate) watch_ptr_cfg: WatchPtrCfg, pub code_coverage: CodeCoverage, + stack_info: Option, +} + +impl Drop for Cpu { + fn drop(&mut self) { + if let Some(stack_info) = &self.stack_info { + if stack_info.has_overflowed { + panic!( + "[EMU] Fatal: Caliptra's stack overflowed by {} bytes!", + stack_info.max_stack_overflow().unwrap() + ) + } + } + } } /// Cpu instruction step action @@ -201,9 +335,14 @@ impl Cpu { // TODO: Pass in code_coverage from the outside (as caliptra-emu-cpu // isn't supposed to know anything about the caliptra memory map) code_coverage: CodeCoverage::new(ROM_SIZE, ICCM_SIZE), + stack_info: None, } } + pub fn with_stack_info(&mut self, stack_info: StackInfo) { + self.stack_info = Some(stack_info); + } + /// Read the RISCV CPU Program counter /// /// # Return @@ -266,7 +405,24 @@ impl Cpu { /// /// * `RvException` - Exception with cause `RvExceptionCause::IllegalRegister` pub fn write_xreg(&mut self, reg: XReg, val: RvData) -> Result<(), RvException> { - self.xregs.write(reg, val) + // XReg::X2 is the sp register. + if reg == XReg::X2 { + self.check_stack(val); + } + self.xregs.write(reg, val)?; + Ok(()) + } + + // Check if the stack overflows at the requested address. + fn check_stack(&mut self, val: RvData) { + if let Some(stack_info) = &mut self.stack_info { + if let Some(overflow_amount) = stack_info.check_overflow(self.pc, val) { + eprintln!( + "[EMU] Caliptra's stack overflowed by {} bytes at pc 0x{:x}.", + overflow_amount, self.pc + ); + } + } } /// Read the specified configuration status register with the current privilege mode diff --git a/sw-emulator/lib/cpu/src/lib.rs b/sw-emulator/lib/cpu/src/lib.rs index 5d0a73f57e..87c88d75f2 100644 --- a/sw-emulator/lib/cpu/src/lib.rs +++ b/sw-emulator/lib/cpu/src/lib.rs @@ -22,7 +22,7 @@ pub mod xreg_file; pub use cpu::StepAction; pub use cpu::WatchPtrHit; pub use cpu::WatchPtrKind; -pub use cpu::{CoverageBitmaps, Cpu, InstrTracer}; +pub use cpu::{CodeRange, CoverageBitmaps, Cpu, ImageInfo, InstrTracer, StackInfo, StackRange}; pub use csr_file::CsrFile; pub use pic::{IntSource, Irq, Pic, PicMmioRegisters}; pub use types::RvInstr; From 4e0dd15dd9d0845d7b96aeae9294b16bcec71595 Mon Sep 17 00:00:00 2001 From: Vishal Mhatre Date: Mon, 2 Dec 2024 12:03:38 -0800 Subject: [PATCH 48/51] [update] Manifest Based Authorization feature update. This PR makes the following changes to the feature: 1. Adds a 'firmware id' to the image metadata entry (IME) structure. 2. Reduces max IME limit from 128 to 127 to account for size increase due to the firmware id addition. 3. SET_AUTH_MANIFEST command validates that the IME collection does not contain duplicate firmware ids. 4. SET_AUTH_MANIFEST command sorts the IME on the firmware ids. 5. Adds a new bit to the IME flags named 'SKIP AUTHORIZATION'. If set, AUTHORIZE_AND_STASH command authorizes an IME with a matching firmware id ignoring the image hash. 6. If a firmware id is not found, AUTHORIZE_AND_STASH command returns IMAGE_NOT_AUTHORIZED status code in the command output. 7. If a firmware id is found but the image hash does not match, AUTHORIZE_AND_STASH returns IMAGE_HASH_MISMATCH status code in the command output. 8. If a firmware id is found and the image hash matches or if the 'SKIP AUTHORIZATION' flag is set for the the firmware id, AUTHORIZE_AND_STASH command returns IMAGE_AUTHORIZED status code in the command output. 9. AUTHORIZE_AND_STASH command uses binary search on the firmware id to lookup an IME. (cherry picked from commit cbd59bfabb9c9e1a4e8ea1dbc859741fec05965b) --- Cargo.lock | 1 + api/src/mailbox.rs | 6 +- auth-manifest/app/src/auth-man.toml | 6 + auth-manifest/app/src/config.rs | 21 +- auth-manifest/types/Cargo.toml | 1 + auth-manifest/types/src/lib.rs | 24 +- error/src/lib.rs | 6 +- runtime/README.md | 106 +++--- runtime/src/authorize_and_stash.rs | 67 +++- runtime/src/lib.rs | 2 +- runtime/src/set_auth_manifest.rs | 146 +++++++- .../test_authorize_and_stash.rs | 342 ++++++++++++++++-- .../test_set_auth_manifest.rs | 325 ++++++++++++++++- 13 files changed, 903 insertions(+), 150 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 589bc2d11e..88d6869a1b 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -244,6 +244,7 @@ name = "caliptra-auth-man-types" version = "0.1.0" dependencies = [ "arbitrary", + "bitfield", "bitflags 2.4.0", "caliptra-error", "caliptra-image-types", diff --git a/api/src/mailbox.rs b/api/src/mailbox.rs index 9db5ff59f0..6800c630eb 100644 --- a/api/src/mailbox.rs +++ b/api/src/mailbox.rs @@ -1059,8 +1059,8 @@ impl AuthAndStashFlags { #[derive(Debug, AsBytes, FromBytes, PartialEq, Eq)] pub struct AuthorizeAndStashReq { pub hdr: MailboxReqHeader, - pub metadata: [u8; 4], - pub measurement: [u8; 48], + pub fw_id: [u8; 4], + pub measurement: [u8; 48], // Image digest. pub context: [u8; 48], pub svn: u32, pub flags: u32, @@ -1070,7 +1070,7 @@ impl Default for AuthorizeAndStashReq { fn default() -> Self { Self { hdr: Default::default(), - metadata: Default::default(), + fw_id: Default::default(), measurement: [0u8; 48], context: [0u8; 48], svn: Default::default(), diff --git a/auth-manifest/app/src/auth-man.toml b/auth-manifest/app/src/auth-man.toml index e141a7446b..f0d5047f19 100644 --- a/auth-manifest/app/src/auth-man.toml +++ b/auth-manifest/app/src/auth-man.toml @@ -27,11 +27,17 @@ lms_priv_key = "own-lms-priv-key.pem" [[image_metadata_list]] digest = "C120EED0004B4CF6C344B00F5F501E7B7167C7010B6EA1D36AEE20CC90F1AE373DF1EC91C9AD9E0A5A969326A54E2517" source = 1 +fw_id = 1 +ignore_auth_check = false [[image_metadata_list]] digest = "99514329186b2f6ae4a1329e7ee6c610a729636335174ac6b740f9028396fcc803d0e93863a7c3d90f86beee782f4f3f" source = 2 +fw_id = 2 +ignore_auth_check = true [[image_metadata_list]] digest = "9B514329186b2f6ae4a1329e7ee6c610a729636335174ac6b740f9028396fcc803d0e93863a7c3d90f86beee782f4f3f" source = 2 +fw_id = 3 +ignore_auth_check = false diff --git a/auth-manifest/app/src/config.rs b/auth-manifest/app/src/config.rs index a94f966b00..8e9a207b5a 100644 --- a/auth-manifest/app/src/config.rs +++ b/auth-manifest/app/src/config.rs @@ -14,8 +14,8 @@ Abstract: use anyhow::Context; use caliptra_auth_man_gen::AuthManifestGeneratorKeyConfig; -use caliptra_auth_man_types::AuthManifestPubKeys; use caliptra_auth_man_types::{AuthManifestImageMetadata, AuthManifestPrivKeys}; +use caliptra_auth_man_types::{AuthManifestPubKeys, ImageMetadataFlags}; #[cfg(feature = "openssl")] use caliptra_image_crypto::OsslCrypto as Crypto; #[cfg(feature = "rustcrypto")] @@ -41,6 +41,8 @@ pub(crate) struct AuthManifestKeyConfigFromFile { pub struct ImageMetadataConfigFromFile { digest: String, source: u32, + fw_id: u32, + ignore_auth_check: bool, } // Authorization Manifest configuration from TOML file @@ -119,14 +121,27 @@ pub(crate) fn image_metadata_config_from_file( config: &Vec, ) -> anyhow::Result> { let mut image_metadata_list = Vec::new(); + let mut fw_ids: Vec = Vec::new(); for image in config { + // Check if the firmware ID is already present in the list. + if fw_ids.contains(&image.fw_id) { + return Err(anyhow::anyhow!( + "Duplicate firmware ID found in the image metadata list" + )); + } else { + fw_ids.push(image.fw_id); + } + let digest_vec = hex::decode(&image.digest)?; - let image_source = image.source; + let mut flags = ImageMetadataFlags(0); + flags.set_ignore_auth_check(image.ignore_auth_check); + flags.set_image_source(image.source); let image_metadata = AuthManifestImageMetadata { + fw_id: image.fw_id, + flags: flags.0, digest: digest_vec.try_into().unwrap(), - image_source, }; image_metadata_list.push(image_metadata); diff --git a/auth-manifest/types/Cargo.toml b/auth-manifest/types/Cargo.toml index 0f43ee3672..33d9dfcd55 100644 --- a/auth-manifest/types/Cargo.toml +++ b/auth-manifest/types/Cargo.toml @@ -17,6 +17,7 @@ caliptra-error = { workspace = true, default-features = false } zeroize.workspace = true caliptra-image-types = { workspace = true, default-features = false } bitflags.workspace = true +bitfield.workspace = true [features] default = ["std"] diff --git a/auth-manifest/types/src/lib.rs b/auth-manifest/types/src/lib.rs index a6aa13e67b..5b4818cc91 100644 --- a/auth-manifest/types/src/lib.rs +++ b/auth-manifest/types/src/lib.rs @@ -14,16 +14,16 @@ Abstract: #![no_std] -use core::ops::Range; - +use bitfield::bitfield; use caliptra_image_types::*; use core::default::Default; +use core::ops::Range; use memoffset::span_of; use zerocopy::{AsBytes, FromBytes}; use zeroize::Zeroize; pub const AUTH_MANIFEST_MARKER: u32 = 0x4154_4D4E; -pub const AUTH_MANIFEST_IMAGE_METADATA_MAX_COUNT: usize = 128; +pub const AUTH_MANIFEST_IMAGE_METADATA_MAX_COUNT: usize = 127; bitflags::bitflags! { #[derive(Default, Copy, Clone, Debug)] @@ -76,7 +76,7 @@ pub struct AuthManifestPreamble { pub version: u32, - pub flags: u32, + pub flags: u32, // AuthManifestFlags(VENDOR_SIGNATURE_REQUIRED) pub vendor_pub_keys: AuthManifestPubKeys, @@ -129,21 +129,31 @@ impl AuthManifestPreamble { } } +bitfield! { + #[derive(Debug, PartialEq, Eq, Clone, Copy)] + pub struct ImageMetadataFlags(u32); + pub image_source, set_image_source: 1, 0; + pub ignore_auth_check, set_ignore_auth_check: 2; +} + /// Caliptra Authorization Manifest Image Metadata #[repr(C)] #[derive(AsBytes, FromBytes, Clone, Copy, Debug, Zeroize)] #[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))] pub struct AuthManifestImageMetadata { - pub digest: [u8; 48], + pub fw_id: u32, - pub image_source: u32, + pub flags: u32, // ImageMetadataFlags(image_source, ignore_auth_check) + + pub digest: [u8; 48], } impl Default for AuthManifestImageMetadata { fn default() -> Self { AuthManifestImageMetadata { + fw_id: u32::MAX, + flags: 0, digest: [0; 48], - image_source: 0, } } } diff --git a/error/src/lib.rs b/error/src/lib.rs index ff0e8804ea..0f73e1851f 100644 --- a/error/src/lib.rs +++ b/error/src/lib.rs @@ -504,10 +504,12 @@ impl CaliptraError { CaliptraError::new_const(0x000E0051); pub const RUNTIME_GET_IDEV_ID_UNSUPPORTED_ROM: CaliptraError = CaliptraError::new_const(0x000E0052); - pub const RUNTIME_AUTH_MANIFEST_LMS_VENDOR_PUB_KEY_INVALID: CaliptraError = + pub const RUNTIME_AUTH_MANIFEST_IMAGE_METADATA_LIST_DUPLICATE_FIRMWARE_ID: CaliptraError = CaliptraError::new_const(0x000E0053); - pub const RUNTIME_AUTH_MANIFEST_LMS_OWNER_PUB_KEY_INVALID: CaliptraError = + pub const RUNTIME_AUTH_MANIFEST_LMS_VENDOR_PUB_KEY_INVALID: CaliptraError = CaliptraError::new_const(0x000E0054); + pub const RUNTIME_AUTH_MANIFEST_LMS_OWNER_PUB_KEY_INVALID: CaliptraError = + CaliptraError::new_const(0x000E0055); /// FMC Errors pub const FMC_GLOBAL_NMI: CaliptraError = CaliptraError::new_const(0x000F0001); diff --git a/runtime/README.md b/runtime/README.md index d1b970062d..2b3dd9c944 100644 --- a/runtime/README.md +++ b/runtime/README.md @@ -918,65 +918,51 @@ The SoC uses this command and `SET_IMAGE_METADTA` to program an image manifest f Command Code: `0x4154_4D4E` ("ATMN") *Table: `SET_AUTH_MANIFEST` input arguments* -| **Name** | **Type** | **Description** | -| -------------------------- | --------- | --------------------------------------------------------------------------- | -| chksum | u32 | Checksum over other input arguments, computed by the caller. Little endian. | -| manifest size | u32 | The size of the full Authentication Manifest | -| preamble_marker | u32 | Marker needs to be 0x4154_4D4E for the preamble to be valid | -| preamble_size | u32 | Size of the preamble | -| preamble_version | u32 | Version of the preamble | -| preamble_flags | u32 | Preamble flags | -| preamble_vendor_ecc384_key | u32[24] | Vendor ECC384 public key with X and Y coordinates in that order | -| preamble_vendor_lms_key | u32[6] | Vendor LMS-SHA192-H15 public key | -| preamble_vendor_ecc384_sig | u32[24] | Vendor ECC384 signature | -| preamble_vendor_LMS_sig | u32[1344] | Vendor LMOTS-SHA192-W4 signature | -| preamble_owner_ecc384_key | u32[24] | Owner ECC384 key with X and Y coordinates in that order | -| preamble_owner_lms_key | u32[6] | Owner LMS-SHA192-H15 key | -| preamble_owner_ecc384_sig | u32[24] | Owner ECC384 signature | -| preamble_owner_LMS_sig | u32[1344] | Owner LMOTS-SHA192-W4 signature | + +| **Name** | **Type** | **Description** +| -------- | -------- | --------------- +| chksum | u32 | Checksum over other input arguments, computed by the caller. Little endian. | +| manifest size | u32 | The size of the full Authentication Manifest | +| preamble\_marker | u32 | Marker needs to be 0x4154_4D4E for the preamble to be valid | +| preamble\_size | u32 | Size of the preamble | +| preamble\_version | u32 | Version of the preamble | +| preamble\_flags | u32 | Manifest flags. See AUTH_MANIFEST_FLAGS below | +| preamble\_vendor\_ecc384\_key | u32[24] | Vendor ECC384 key with X and Y coordinates in that order | +| preamble\_vendor\_lms\_key | u32[6] | Vendor LMS-SHA192-H15 key | +| preamble\_vendor\_ecc384\_sig | u32[24] | Vendor ECC384 signature | +| preamble\_vendor\_LMS\_sig | u32[1344] | Vendor LMOTS-SHA192-W4 signature | +| preamble\_owner\_ecc384\_key | u32[24] | Owner ECC384 key with X and Y coordinates in that order | +| preamble\_owner\_lms\_key | u32[6] | Owner LMS-SHA192-H15 key | +| preamble\_owner\_ecc384\_sig | u32[24] | Owner ECC384 signature | +| preamble\_owner\_LMS\_sig | u32[1344] | Owner LMOTS-SHA192-W4 signature | +| metadata\_vendor\_ecc384\_sig | u32[24] | Metadata Vendor ECC384 signature | +| metadata\_vendor\_LMS\_sig | u32[1344] | Metadata Vendor LMOTS-SHA192-W4 signature | +| metadata\_owner\_ecc384\_sig | u32[24] | Metadata Owner ECC384 signature | +| metadata\_owner\_LMS\_sig | u32[1344] | Metadata Owner LMOTS-SHA192-W4 signature | +| metadata\_entry\_entry\_count | u32 | number of metadata entries | +| metadata\_entries | Metadata[127] | The max number of metadata entries is 127 but less can be used | + *Table: `AUTH_MANIFEST_FLAGS` input flags* | **Name** | **Value** | | ------------------------- | --------- | | VENDOR_SIGNATURE_REQUIRED | 1 << 0 | -*Table: `SET_AUTH_MANIFEST` output arguments* - -| **Name** | **Type** | **Description** | -| ------------ | -------- | -------------------------------------------------------------------------- | -| chksum | u32 | Checksum over other output arguments, computed by Caliptra. Little endian. | -| fips\_status | u32 | Indicates if the command is FIPS approved or an error. | - -### SET_IMAGE_METADATA +*Table: `AUTH_MANIFEST_METADATA_ENTRY` digest entries* -This command is used alonside `SET_AUTH_MANIFEST` to provide image metadata signatures for manifest-based image authorization. +| **Name** | **Type** | **Description** | +|---------------|----------|--------------------------------| +| fw\_id | u32 | Id of the image | +| flags | u32 | See METADATA_ENTRY_FLAGS below | +| digest | u32[48] | Digest of the image | -Command Code: `0x5349_4D44` ("SIMD") -*Table: `SET_IMAGE_METADATA` input arguments* -| **Name** | **Type** | **Description** | -| -------------------------- | ------------ | --------------------------------------------------------------------------- | -| chksum | u32 | Checksum over other input arguments, computed by the caller. Little endian. | -| metadata_vendor_ecc384_sig | u32[24] | Metadata Vendor ECC384 signature | -| metadata_vendor_LMS_sig | u32[1344] | Metadata Vendor LMOTS-SHA192-W4 signature | -| metadata_owner_ecc384_sig | u32[24] | Metadata Owner ECC384 signature | -| metadata_owner_LMS_sig | u32[1344] | Metadata Owner LMOTS-SHA192-W4 signature | -| metadata_header_revision | u32 | Revision of the metadata header | -| metadata_header_reserved | u32[3] | Reserved | -| metadata_entry_entry_count | u32 | number of metadata entries | -| metadata_entries | MetaData[16] | The max number of metadata is 16 but less can be used | +*Table: `METADATA_ENTRY_FLAGS` input flags* -*Table: `SET_IMAGE_METADATA_ENTRY` digest entries* -| **Name** | **Type** | **Description** | -| ------------ | -------- | ---------------------- | -| digest | u32[48] | Digest of the metadata | -| image_source | u32 | Image source | - -*Table: `SET_IMAGE_METADATA` output arguments* -| **Name** | **Type** | **Description** | -| ----------- | -------- | -------------------------------------------------------------------------- | -| chksum | u32 | Checksum over other output arguments, computed by Caliptra. Little endian. | -| fips_status | u32 | Indicates if the command is FIPS approved or an error. | +| **Name** | **Size (Bits)** | **Description** | +|---------------------|-----------------|-----------------| +| image\_source | 2 | 1: InRequest | +| ignore\_auth\_check | 1 | If set, the image digest is not compared for the firmware id | ### AUTHORIZE_AND_STASH @@ -988,30 +974,28 @@ The SoC uses this command repeatedly to ask for authorization to run its differe Command Code: `0x4154_5348` ("ATSH") *Table: `AUTHORIZE_AND_STASH` input arguments* -| **Name** | **Type** | **Description** | -| ----------- | -------- | ----------------------------------------------------------------------------------- | -| chksum | u32 | Checksum over other input arguments, computed by the caller. Little endian. | -| metadata | u8[4] | 4-byte measurement identifier. | -| measurement | u8[48] | Digest of measured | + +| **Name** | **Type** | **Description** +| ------------| -------- | --------------- +| chksum | u32 | Checksum over other input arguments, computed by the caller. Little endian. | +| fw_id | u8[4] | Firmware id of the image, in little-endian format | +| measurement | u8[48] | Digest of the image requested for authorization | | context | u8[48] | Context field for `svn`; e.g., a hash of the public key that authenticated the SVN. | | svn | u32 | SVN | -| flags | u32 | Flags | -| source | u32 | Enumeration values: | -| | | 1 = InRequest | -| | | 2 = ShaAcc | +| flags | u32 | See AUTHORIZE_AND_STASH_FLAGS below | +| source | u32 | Enumeration values: { InRequest(1), ShaAcc (2) } | *Table: `AUTHORIZE_AND_STASH_FLAGS` input flags* | **Name** | **Value** | | ----------- | --------- | -| SKIP_STASH | 1 << 0 | +| SKIP\_STASH | 1 << 0 | *Table: `AUTHORIZE_AND_STASH` output arguments* | **Name** | **Type** | **Description** | | --------------- | -------- | -------------------------------------------------------------------------- | | chksum | u32 | Checksum over other output arguments, computed by Caliptra. Little endian. | | fips_status | u32 | Indicates if the command is FIPS approved or an error. | -| auth_req_result | u32 | Authorized: `0xDEADC0DE` | -| | | Denied: `0x21523F21` | +| auth_req_result | u32 |AUTHORIZE_IMAGE (0xDEADC0DE), IMAGE_NOT_AUTHORIZED (0x21523F21) or IMAGE_HASH_MISMATCH (0x8BFB95CB) ## Mailbox commands: Cryptographic Mailbox (2.0) diff --git a/runtime/src/authorize_and_stash.rs b/runtime/src/authorize_and_stash.rs index 3105c5e063..326840e490 100644 --- a/runtime/src/authorize_and_stash.rs +++ b/runtime/src/authorize_and_stash.rs @@ -12,15 +12,16 @@ Abstract: --*/ -use core::cmp::min; +use core::cmp::{self, min}; use core::mem::size_of; use crate::{dpe_crypto::DpeCrypto, CptraDpeTypes, DpePlatform, Drivers, StashMeasurementCmd}; use caliptra_auth_man_types::{ - AuthManifestImageMetadataCollection, AuthManifestPreamble, AUTH_MANIFEST_MARKER, + AuthManifestImageMetadata, AuthManifestImageMetadataCollection, AuthManifestPreamble, + ImageMetadataFlags, AUTH_MANIFEST_MARKER, }; use caliptra_cfi_derive_git::cfi_impl_fn; -use caliptra_cfi_lib_git::cfi_launder; +use caliptra_cfi_lib_git::{cfi_assert, cfi_assert_eq, cfi_launder}; use caliptra_common::mailbox_api::{ AuthAndStashFlags, AuthorizeAndStashReq, AuthorizeAndStashResp, ImageHashSource, MailboxResp, MailboxRespHeader, SetAuthManifestReq, @@ -44,8 +45,9 @@ use dpe::{ use memoffset::offset_of; use zerocopy::{AsBytes, FromBytes}; -pub const AUTHORIZE_IMAGE: u32 = 0xDEADC0DE; -pub const DENY_IMAGE_AUTHORIZATION: u32 = 0x21523F21; +pub const IMAGE_AUTHORIZED: u32 = 0xDEADC0DE; // Either FW ID and image digest matched or 'ignore_auth_check' is set for the FW ID. +pub const IMAGE_NOT_AUTHORIZED: u32 = 0x21523F21; // FW ID not found in the image metadata entry collection. +pub const IMAGE_HASH_MISMATCH: u32 = 0x8BFB95CB; // FW ID matched, but image digest mismatched. pub struct AuthorizeAndStashCmd; impl AuthorizeAndStashCmd { @@ -57,30 +59,40 @@ impl AuthorizeAndStashCmd { Err(CaliptraError::RUNTIME_AUTH_AND_STASH_UNSUPPORTED_IMAGE_SOURCE)?; } - // Check if image hash is present in the image metadata entry collection. + // Check if firmware id is present in the image metadata entry collection. let persistent_data = drivers.persistent_data.get(); let auth_manifest_image_metadata_col = &persistent_data.auth_manifest_image_metadata_col; - let mut auth_result = DENY_IMAGE_AUTHORIZATION; - for metadata_entry in auth_manifest_image_metadata_col.image_metadata_list.iter() { - if cfi_launder(metadata_entry.digest) == cmd.measurement { + let cmd_fw_id = u32::from_le_bytes(cmd.fw_id); + let auth_result = if let Some(metadata_entry) = + Self::find_metadata_entry(auth_manifest_image_metadata_col, cmd_fw_id) + { + // If 'ignore_auth_check' is set, then skip the image digest comparison and authorize the image. + let flags = ImageMetadataFlags(metadata_entry.flags); + if flags.ignore_auth_check() { + cfi_assert!(cfi_launder(flags.ignore_auth_check())); + IMAGE_AUTHORIZED + } else if cfi_launder(metadata_entry.digest) == cmd.measurement { caliptra_cfi_lib_git::cfi_assert_eq_12_words( &Array4x12::from(metadata_entry.digest).0, &Array4x12::from(cmd.measurement).0, ); - auth_result = AUTHORIZE_IMAGE; - break; + IMAGE_AUTHORIZED + } else { + IMAGE_HASH_MISMATCH } - } + } else { + IMAGE_NOT_AUTHORIZED + }; // Stash the measurement if the image is authorized. - if auth_result == AUTHORIZE_IMAGE { + if auth_result == IMAGE_AUTHORIZED { let flags: AuthAndStashFlags = cmd.flags.into(); if !flags.contains(AuthAndStashFlags::SKIP_STASH) { let dpe_result = StashMeasurementCmd::stash_measurement( drivers, - &cmd.metadata, + &cmd.fw_id, &cmd.measurement, )?; if dpe_result != DpeErrorCode::NoError { @@ -100,4 +112,31 @@ impl AuthorizeAndStashCmd { Err(CaliptraError::RUNTIME_INSUFFICIENT_MEMORY) } } + + /// Search for a metadata entry in the sorted `AuthManifestImageMetadataCollection` that matches the firmware ID. + /// + /// This function performs a binary search on the `image_metadata_list` of the provided `AuthManifestImageMetadataCollection`. + /// It compares the firmware ID (`fw_id`) of each metadata entry with the provided `cmd_fw_id`. + /// + /// # Arguments + /// + /// * `auth_manifest_image_metadata_col` - A reference to the `AuthManifestImageMetadataCollection` containing the metadata entries. + /// * `cmd_fw_id` - The firmware ID from the command to search for. + /// + /// # Returns + /// + /// * `Option<&AuthManifestImageMetadata>` - Returns `Some(&AuthManifestImageMetadata)` if a matching entry is found, + /// otherwise returns `None`. + /// + #[inline(never)] + fn find_metadata_entry( + auth_manifest_image_metadata_col: &AuthManifestImageMetadataCollection, + cmd_fw_id: u32, + ) -> Option<&AuthManifestImageMetadata> { + auth_manifest_image_metadata_col + .image_metadata_list + .binary_search_by(|metadata| metadata.fw_id.cmp(&cmd_fw_id)) + .ok() + .map(|index| &auth_manifest_image_metadata_col.image_metadata_list[index]) + } } diff --git a/runtime/src/lib.rs b/runtime/src/lib.rs index fd8480f23c..c8057bff47 100644 --- a/runtime/src/lib.rs +++ b/runtime/src/lib.rs @@ -47,7 +47,7 @@ use crate::capabilities::CapabilitiesCmd; pub use crate::certify_key_extended::CertifyKeyExtendedCmd; pub use crate::hmac::Hmac; pub use crate::subject_alt_name::AddSubjectAltNameCmd; -pub use authorize_and_stash::{AUTHORIZE_IMAGE, DENY_IMAGE_AUTHORIZATION}; +pub use authorize_and_stash::{IMAGE_AUTHORIZED, IMAGE_HASH_MISMATCH, IMAGE_NOT_AUTHORIZED}; pub use caliptra_common::fips::FipsVersionCmd; pub use dice::{GetFmcAliasCertCmd, GetLdevCertCmd, IDevIdCertCmd}; pub use disable::DisableAttestationCmd; diff --git a/runtime/src/set_auth_manifest.rs b/runtime/src/set_auth_manifest.rs index eeca2f9de0..770e9093a6 100644 --- a/runtime/src/set_auth_manifest.rs +++ b/runtime/src/set_auth_manifest.rs @@ -18,8 +18,8 @@ use core::mem::size_of; use crate::verify; use crate::{dpe_crypto::DpeCrypto, CptraDpeTypes, DpePlatform, Drivers}; use caliptra_auth_man_types::{ - AuthManifestFlags, AuthManifestImageMetadataCollection, AuthManifestPreamble, - AUTH_MANIFEST_IMAGE_METADATA_MAX_COUNT, AUTH_MANIFEST_MARKER, + AuthManifestFlags, AuthManifestImageMetadata, AuthManifestImageMetadataCollection, + AuthManifestPreamble, AUTH_MANIFEST_IMAGE_METADATA_MAX_COUNT, AUTH_MANIFEST_MARKER, }; use caliptra_cfi_derive_git::cfi_impl_fn; use caliptra_cfi_lib_git::cfi_launder; @@ -44,17 +44,18 @@ use dpe::{ }; use memoffset::offset_of; use zerocopy::{AsBytes, FromBytes}; +use zeroize::Zeroize; pub struct SetAuthManifestCmd; impl SetAuthManifestCmd { fn sha384_digest( sha2: &mut Sha2_512_384, - manifest: &[u8], + buf: &[u8], offset: u32, len: u32, ) -> CaliptraResult { let err = CaliptraError::IMAGE_VERIFIER_ERR_DIGEST_OUT_OF_BOUNDS; - let data = manifest + let data = buf .get(offset as usize..) .ok_or(err)? .get(..len as usize) @@ -337,7 +338,7 @@ impl SetAuthManifestCmd { fn process_image_metadata_col( cmd_buf: &[u8], auth_manifest_preamble: &AuthManifestPreamble, - image_metadata_col: &mut AuthManifestImageMetadataCollection, + metadata_persistent: &mut AuthManifestImageMetadataCollection, sha2: &mut Sha2_512_384, ecc384: &mut Ecc384, sha256: &mut Sha256, @@ -347,23 +348,36 @@ impl SetAuthManifestCmd { Err(CaliptraError::RUNTIME_AUTH_MANIFEST_IMAGE_METADATA_LIST_INVALID_SIZE)?; } - let col_size = min( + let metadata_size = min( cmd_buf.len(), size_of::(), ); + + // Resize the buffer to the metadata size. let buf = cmd_buf - .get(..col_size) + .get(..metadata_size) .ok_or(CaliptraError::RUNTIME_AUTH_MANIFEST_IMAGE_METADATA_LIST_INVALID_SIZE)?; - image_metadata_col.as_bytes_mut()[..col_size].copy_from_slice(buf); + // Typecast the mailbox buffer to the image metadata collection. + let metadata_mailbox = + unsafe { &mut *(buf.as_ptr() as *mut AuthManifestImageMetadataCollection) }; - if image_metadata_col.entry_count == 0 - || image_metadata_col.entry_count > AUTH_MANIFEST_IMAGE_METADATA_MAX_COUNT as u32 + if metadata_mailbox.entry_count == 0 + || metadata_mailbox.entry_count > AUTH_MANIFEST_IMAGE_METADATA_MAX_COUNT as u32 { Err(CaliptraError::RUNTIME_AUTH_MANIFEST_IMAGE_METADATA_LIST_INVALID_ENTRY_COUNT)?; } - let digest_metadata_col = Self::sha384_digest(sha2, buf, 0, col_size as u32)?; + // Check if the buffer contains the entry count and all the image metadata entries specified by the entry count. + if buf.len() + < (size_of::() + + metadata_mailbox.entry_count as usize * size_of::()) + { + Err(CaliptraError::RUNTIME_AUTH_MANIFEST_IMAGE_METADATA_LIST_INVALID_SIZE)?; + } + + // Calculate the digest of the image metadata collection. + let digest_metadata_col = Self::sha384_digest(sha2, buf, 0, metadata_size as u32)?; Self::verify_vendor_image_metadata_col( auth_manifest_preamble, @@ -383,6 +397,45 @@ impl SetAuthManifestCmd { soc_ifc, )?; + // Sort the image metadata list by firmware ID in place. Also check for duplicate firmware IDs. let slice = + let slice = + &mut metadata_mailbox.image_metadata_list[..metadata_mailbox.entry_count as usize]; + + Self::sort_and_check_duplicate_fwid(slice)?; + + // Clear the previous image metadata collection. + metadata_persistent.zeroize(); + + // Copy the image metadata collection to the persistent data. + metadata_persistent.as_bytes_mut()[..buf.len()].copy_from_slice(buf); + + Ok(()) + } + + fn sort_and_check_duplicate_fwid( + slice: &mut [AuthManifestImageMetadata], + ) -> CaliptraResult<()> { + for i in 1..slice.len() { + let mut j = i; + while j > 0 { + if j >= slice.len() { + break; + } + + match slice[j - 1].fw_id.cmp(&slice[j].fw_id) { + core::cmp::Ordering::Greater => { + slice.swap(j - 1, j); + j -= 1; + } + core::cmp::Ordering::Equal => { + Err(CaliptraError::RUNTIME_AUTH_MANIFEST_IMAGE_METADATA_LIST_DUPLICATE_FIRMWARE_ID)?; + } + _ => { + break; + } + } + } + } Ok(()) } @@ -468,3 +521,74 @@ impl SetAuthManifestCmd { Ok(MailboxResp::default()) } } + +#[cfg(all(test))] +mod tests { + use super::*; + + fn is_sorted(slice: &[AuthManifestImageMetadata]) -> bool { + for i in 0..slice.len() - 1 { + if slice[i].fw_id > slice[i + 1].fw_id { + return false; + } + } + + true + } + + #[test] + fn test_sort_and_duplicate_empty() { + let resp = SetAuthManifestCmd::sort_and_check_duplicate_fwid(&mut []); + assert!(resp.is_ok()); + } + + #[test] + fn test_sort_and_duplicate_sort() { + let mut list = [ + AuthManifestImageMetadata { + fw_id: 5, + flags: 0, + digest: [0u8; 48], + }, + AuthManifestImageMetadata { + fw_id: 127, + flags: 0, + digest: [0u8; 48], + }, + AuthManifestImageMetadata { + fw_id: 48, + flags: 0, + digest: [0u8; 48], + }, + ]; + let resp = SetAuthManifestCmd::sort_and_check_duplicate_fwid(&mut list); + assert!(resp.is_ok()); + assert!(is_sorted(&list)); + } + + #[test] + fn test_sort_and_duplicate_dupe() { + let mut list = [ + AuthManifestImageMetadata { + fw_id: 127, + flags: 0, + digest: [0u8; 48], + }, + AuthManifestImageMetadata { + fw_id: 5, + flags: 0, + digest: [0u8; 48], + }, + AuthManifestImageMetadata { + fw_id: 127, + flags: 0, + digest: [0u8; 48], + }, + ]; + let resp = SetAuthManifestCmd::sort_and_check_duplicate_fwid(&mut list); + assert_eq!( + resp.unwrap_err(), + CaliptraError::RUNTIME_AUTH_MANIFEST_IMAGE_METADATA_LIST_DUPLICATE_FIRMWARE_ID + ); + } +} diff --git a/runtime/tests/runtime_integration_tests/test_authorize_and_stash.rs b/runtime/tests/runtime_integration_tests/test_authorize_and_stash.rs index 588c440656..cbe9fbc3cd 100644 --- a/runtime/tests/runtime_integration_tests/test_authorize_and_stash.rs +++ b/runtime/tests/runtime_integration_tests/test_authorize_and_stash.rs @@ -1,8 +1,11 @@ // Licensed under the Apache-2.0 license use crate::common::{run_rt_test, RuntimeTestArgs}; -use crate::test_set_auth_manifest::test_auth_manifest; +use crate::test_set_auth_manifest::{create_auth_manifest, create_auth_manifest_with_metadata}; use caliptra_api::SocManager; +use caliptra_auth_man_types::{ + AuthManifestFlags, AuthManifestImageMetadata, AuthorizationManifest, ImageMetadataFlags, +}; use caliptra_builder::{ firmware::{self, FMC_WITH_UART}, ImageOptions, @@ -11,19 +14,66 @@ use caliptra_common::mailbox_api::{ AuthorizeAndStashReq, AuthorizeAndStashResp, CommandId, ImageHashSource, MailboxReq, MailboxReqHeader, SetAuthManifestReq, }; -use caliptra_hw_model::HwModel; +use caliptra_hw_model::{DefaultHwModel, HwModel}; use caliptra_runtime::RtBootStatus; -use caliptra_runtime::{AUTHORIZE_IMAGE, DENY_IMAGE_AUTHORIZATION}; +use caliptra_runtime::{IMAGE_AUTHORIZED, IMAGE_NOT_AUTHORIZED}; use sha2::{Digest, Sha384}; use zerocopy::AsBytes; use zerocopy::FromBytes; +const IMAGE_HASH_MISMATCH: u32 = 0x8BFB95CB; // FW ID matched, but image digest mismatched. + pub const IMAGE_DIGEST1: [u8; 48] = [ 0x38, 0xB0, 0x60, 0xA7, 0x51, 0xAC, 0x96, 0x38, 0x4C, 0xD9, 0x32, 0x7E, 0xB1, 0xB1, 0xE3, 0x6A, 0x21, 0xFD, 0xB7, 0x11, 0x14, 0xBE, 0x07, 0x43, 0x4C, 0x0C, 0xC7, 0xBF, 0x63, 0xF6, 0xE1, 0xDA, 0x27, 0x4E, 0xDE, 0xBF, 0xE7, 0x6F, 0x65, 0xFB, 0xD5, 0x1A, 0xD2, 0xF1, 0x48, 0x98, 0xB9, 0x5B, ]; +pub const IMAGE_DIGEST_BAD: [u8; 48] = [ + 0x39, 0xB0, 0x60, 0xA7, 0x51, 0xAC, 0x96, 0x38, 0x4C, 0xD9, 0x32, 0x7E, 0xB1, 0xB1, 0xE3, 0x6A, + 0x21, 0xFD, 0xB7, 0x11, 0x14, 0xBE, 0x07, 0x43, 0x4C, 0x0C, 0xC7, 0xBF, 0x63, 0xF6, 0xE1, 0xDA, + 0x27, 0x4E, 0xDE, 0xBF, 0xE7, 0x6F, 0x65, 0xFB, 0xD5, 0x1A, 0xD2, 0xF1, 0x48, 0x98, 0xB9, 0x5B, +]; + +pub const FW_ID_1: [u8; 4] = [0x01, 0x00, 0x00, 0x00]; +pub const FW_ID_2: [u8; 4] = [0x02, 0x00, 0x00, 0x00]; +pub const FW_ID_BAD: [u8; 4] = [0xDE, 0xED, 0xBE, 0xEF]; + +fn set_auth_manifest(auth_manifest: Option) -> DefaultHwModel { + let mut model = run_rt_test(RuntimeTestArgs::default()); + + model.step_until(|m| { + m.soc_ifc().cptra_boot_status().read() == u32::from(RtBootStatus::RtReadyForCommands) + }); + + let auth_manifest = if let Some(auth_manifest) = auth_manifest { + auth_manifest + } else { + create_auth_manifest(AuthManifestFlags::VENDOR_SIGNATURE_REQUIRED) + }; + + let buf = auth_manifest.as_bytes(); + let mut auth_manifest_slice = [0u8; SetAuthManifestReq::MAX_MAN_SIZE]; + auth_manifest_slice[..buf.len()].copy_from_slice(buf); + + let mut set_auth_manifest_cmd = MailboxReq::SetAuthManifest(SetAuthManifestReq { + hdr: MailboxReqHeader { chksum: 0 }, + manifest_size: buf.len() as u32, + manifest: auth_manifest_slice, + }); + set_auth_manifest_cmd.populate_chksum().unwrap(); + + model + .mailbox_execute( + u32::from(CommandId::SET_AUTH_MANIFEST), + set_auth_manifest_cmd.as_bytes().unwrap(), + ) + .unwrap() + .expect("We should have received a response"); + + model +} + #[test] fn test_authorize_and_stash_cmd_deny_authorization() { let mut model = run_rt_test(RuntimeTestArgs::default()); @@ -37,6 +87,7 @@ fn test_authorize_and_stash_cmd_deny_authorization() { measurement: IMAGE_DIGEST1, source: ImageHashSource::InRequest as u32, flags: 0, // Don't skip stash + fw_id: FW_ID_BAD, ..Default::default() }); authorize_and_stash_cmd.populate_chksum().unwrap(); @@ -52,7 +103,7 @@ fn test_authorize_and_stash_cmd_deny_authorization() { let authorize_and_stash_resp = AuthorizeAndStashResp::read_from(resp.as_slice()).unwrap(); assert_eq!( authorize_and_stash_resp.auth_req_result, - DENY_IMAGE_AUTHORIZATION + IMAGE_NOT_AUTHORIZED ); // create a new fw image with the runtime replaced by the mbox responder @@ -87,35 +138,12 @@ fn test_authorize_and_stash_cmd_deny_authorization() { } #[test] -fn test_authorize_and_stash_cmd_succes() { - let mut model = run_rt_test(RuntimeTestArgs::default()); - - model.step_until(|m| { - m.soc_ifc().cptra_boot_status().read() == u32::from(RtBootStatus::RtReadyForCommands) - }); - - let auth_manifest = test_auth_manifest(); - let buf = auth_manifest.as_bytes(); - let mut auth_manifest_slice = [0u8; SetAuthManifestReq::MAX_MAN_SIZE]; - auth_manifest_slice[..buf.len()].copy_from_slice(buf); - - let mut set_auth_manifest_cmd = MailboxReq::SetAuthManifest(SetAuthManifestReq { - hdr: MailboxReqHeader { chksum: 0 }, - manifest_size: buf.len() as u32, - manifest: auth_manifest_slice, - }); - set_auth_manifest_cmd.populate_chksum().unwrap(); - - model - .mailbox_execute( - u32::from(CommandId::SET_AUTH_MANIFEST), - set_auth_manifest_cmd.as_bytes().unwrap(), - ) - .unwrap() - .expect("We should have received a response"); +fn test_authorize_and_stash_cmd_success() { + let mut model = set_auth_manifest(None); let mut authorize_and_stash_cmd = MailboxReq::AuthorizeAndStash(AuthorizeAndStashReq { hdr: MailboxReqHeader { chksum: 0 }, + fw_id: FW_ID_1, measurement: IMAGE_DIGEST1, source: ImageHashSource::InRequest as u32, flags: 0, // Don't skip stash @@ -132,7 +160,7 @@ fn test_authorize_and_stash_cmd_succes() { .expect("We should have received a response"); let authorize_and_stash_resp = AuthorizeAndStashResp::read_from(resp.as_slice()).unwrap(); - assert_eq!(authorize_and_stash_resp.auth_req_result, AUTHORIZE_IMAGE); + assert_eq!(authorize_and_stash_resp.auth_req_result, IMAGE_AUTHORIZED); // create a new fw image with the runtime replaced by the mbox responder let updated_fw_image = caliptra_builder::build_and_sign_image( @@ -165,3 +193,255 @@ fn test_authorize_and_stash_cmd_succes() { let dpe_measurement_hash = model.mailbox_execute(0x3000_0000, &[]).unwrap().unwrap(); assert_eq!(expected_measurement_hash.as_bytes(), dpe_measurement_hash); } + +#[test] +fn test_authorize_and_stash_cmd_deny_authorization_no_hash_or_id() { + let mut model = set_auth_manifest(None); + + let mut authorize_and_stash_cmd = MailboxReq::AuthorizeAndStash(AuthorizeAndStashReq { + hdr: MailboxReqHeader { chksum: 0 }, + source: ImageHashSource::InRequest as u32, + flags: 0, // Don't skip stash + ..Default::default() + }); + authorize_and_stash_cmd.populate_chksum().unwrap(); + + let resp = model + .mailbox_execute( + u32::from(CommandId::AUTHORIZE_AND_STASH), + authorize_and_stash_cmd.as_bytes().unwrap(), + ) + .unwrap() + .expect("We should have received a response"); + + let authorize_and_stash_resp = AuthorizeAndStashResp::read_from(resp.as_slice()).unwrap(); + assert_eq!( + authorize_and_stash_resp.auth_req_result, + IMAGE_NOT_AUTHORIZED + ); +} + +#[test] +fn test_authorize_and_stash_cmd_deny_authorization_wrong_id_no_hash() { + let mut model = set_auth_manifest(None); + + let mut authorize_and_stash_cmd = MailboxReq::AuthorizeAndStash(AuthorizeAndStashReq { + hdr: MailboxReqHeader { chksum: 0 }, + fw_id: FW_ID_BAD, + source: ImageHashSource::InRequest as u32, + flags: 0, // Don't skip stash + ..Default::default() + }); + authorize_and_stash_cmd.populate_chksum().unwrap(); + + let resp = model + .mailbox_execute( + u32::from(CommandId::AUTHORIZE_AND_STASH), + authorize_and_stash_cmd.as_bytes().unwrap(), + ) + .unwrap() + .expect("We should have received a response"); + + let authorize_and_stash_resp = AuthorizeAndStashResp::read_from(resp.as_slice()).unwrap(); + assert_eq!( + authorize_and_stash_resp.auth_req_result, + IMAGE_NOT_AUTHORIZED + ); +} + +#[test] +fn test_authorize_and_stash_cmd_deny_authorization_wrong_hash() { + let mut model = set_auth_manifest(None); + + let mut authorize_and_stash_cmd = MailboxReq::AuthorizeAndStash(AuthorizeAndStashReq { + hdr: MailboxReqHeader { chksum: 0 }, + fw_id: FW_ID_1, + measurement: IMAGE_DIGEST_BAD, + source: ImageHashSource::InRequest as u32, + flags: 0, // Don't skip stash + ..Default::default() + }); + authorize_and_stash_cmd.populate_chksum().unwrap(); + + let resp = model + .mailbox_execute( + u32::from(CommandId::AUTHORIZE_AND_STASH), + authorize_and_stash_cmd.as_bytes().unwrap(), + ) + .unwrap() + .expect("We should have received a response"); + + let authorize_and_stash_resp = AuthorizeAndStashResp::read_from(resp.as_slice()).unwrap(); + assert_eq!( + authorize_and_stash_resp.auth_req_result, + IMAGE_HASH_MISMATCH + ); +} + +#[test] +fn test_authorize_and_stash_cmd_success_skip_auth() { + let mut model = set_auth_manifest(None); + + let mut authorize_and_stash_cmd = MailboxReq::AuthorizeAndStash(AuthorizeAndStashReq { + hdr: MailboxReqHeader { chksum: 0 }, + fw_id: FW_ID_2, + measurement: IMAGE_DIGEST_BAD, + source: ImageHashSource::InRequest as u32, + flags: 0, // Don't skip stash + ..Default::default() + }); + authorize_and_stash_cmd.populate_chksum().unwrap(); + + let resp = model + .mailbox_execute( + u32::from(CommandId::AUTHORIZE_AND_STASH), + authorize_and_stash_cmd.as_bytes().unwrap(), + ) + .unwrap() + .expect("We should have received a response"); + + let authorize_and_stash_resp = AuthorizeAndStashResp::read_from(resp.as_slice()).unwrap(); + assert_eq!(authorize_and_stash_resp.auth_req_result, IMAGE_AUTHORIZED); +} + +#[test] +fn test_authorize_and_stash_fwid_0() { + let mut flags = ImageMetadataFlags(0); + flags.set_ignore_auth_check(false); + flags.set_image_source(ImageHashSource::InRequest as u32); + + const FW_ID_0: [u8; 4] = [0x00, 0x00, 0x00, 0x00]; + + let image_metadata = vec![AuthManifestImageMetadata { + fw_id: 0, + flags: flags.0, + digest: IMAGE_DIGEST1, + }]; + let auth_manifest = create_auth_manifest_with_metadata(image_metadata); + let mut model = set_auth_manifest(Some(auth_manifest)); + + let mut authorize_and_stash_cmd = MailboxReq::AuthorizeAndStash(AuthorizeAndStashReq { + hdr: MailboxReqHeader { chksum: 0 }, + fw_id: FW_ID_0, + measurement: IMAGE_DIGEST1, + source: ImageHashSource::InRequest as u32, + flags: 0, // Don't skip stash + ..Default::default() + }); + authorize_and_stash_cmd.populate_chksum().unwrap(); + + let resp = model + .mailbox_execute( + u32::from(CommandId::AUTHORIZE_AND_STASH), + authorize_and_stash_cmd.as_bytes().unwrap(), + ) + .unwrap() + .expect("We should have received a response"); + + let authorize_and_stash_resp = AuthorizeAndStashResp::read_from(resp.as_slice()).unwrap(); + assert_eq!(authorize_and_stash_resp.auth_req_result, IMAGE_AUTHORIZED); +} + +#[test] +fn test_authorize_and_stash_fwid_127() { + let mut flags = ImageMetadataFlags(0); + flags.set_ignore_auth_check(false); + flags.set_image_source(ImageHashSource::InRequest as u32); + + const FW_ID_127: [u8; 4] = [0x7F, 0x00, 0x00, 0x00]; + + let image_metadata = vec![AuthManifestImageMetadata { + fw_id: 127, + flags: flags.0, + digest: IMAGE_DIGEST1, + }]; + let auth_manifest = create_auth_manifest_with_metadata(image_metadata); + let mut model = set_auth_manifest(Some(auth_manifest)); + + let mut authorize_and_stash_cmd = MailboxReq::AuthorizeAndStash(AuthorizeAndStashReq { + hdr: MailboxReqHeader { chksum: 0 }, + fw_id: FW_ID_127, + measurement: IMAGE_DIGEST1, + source: ImageHashSource::InRequest as u32, + flags: 0, // Don't skip stash + ..Default::default() + }); + authorize_and_stash_cmd.populate_chksum().unwrap(); + + let resp = model + .mailbox_execute( + u32::from(CommandId::AUTHORIZE_AND_STASH), + authorize_and_stash_cmd.as_bytes().unwrap(), + ) + .unwrap() + .expect("We should have received a response"); + + let authorize_and_stash_resp = AuthorizeAndStashResp::read_from(resp.as_slice()).unwrap(); + assert_eq!(authorize_and_stash_resp.auth_req_result, IMAGE_AUTHORIZED); +} + +#[test] +fn test_authorize_and_stash_cmd_deny_second_bad_hash() { + { + let mut model = set_auth_manifest(None); + + let mut authorize_and_stash_cmd = MailboxReq::AuthorizeAndStash(AuthorizeAndStashReq { + hdr: MailboxReqHeader { chksum: 0 }, + fw_id: FW_ID_1, + measurement: IMAGE_DIGEST1, + source: ImageHashSource::InRequest as u32, + flags: 0, // Don't skip stash + ..Default::default() + }); + authorize_and_stash_cmd.populate_chksum().unwrap(); + + let resp = model + .mailbox_execute( + u32::from(CommandId::AUTHORIZE_AND_STASH), + authorize_and_stash_cmd.as_bytes().unwrap(), + ) + .unwrap() + .expect("We should have received a response"); + + let authorize_and_stash_resp = AuthorizeAndStashResp::read_from(resp.as_slice()).unwrap(); + assert_eq!(authorize_and_stash_resp.auth_req_result, IMAGE_AUTHORIZED); + } + + { + let mut flags = ImageMetadataFlags(0); + flags.set_ignore_auth_check(false); + flags.set_image_source(ImageHashSource::InRequest as u32); + + let image_metadata = vec![AuthManifestImageMetadata { + fw_id: 1, + flags: flags.0, + digest: IMAGE_DIGEST_BAD, + }]; + let auth_manifest = create_auth_manifest_with_metadata(image_metadata); + let mut model = set_auth_manifest(Some(auth_manifest)); + + let mut authorize_and_stash_cmd = MailboxReq::AuthorizeAndStash(AuthorizeAndStashReq { + hdr: MailboxReqHeader { chksum: 0 }, + fw_id: FW_ID_1, + measurement: IMAGE_DIGEST1, + source: ImageHashSource::InRequest as u32, + flags: 0, // Don't skip stash + ..Default::default() + }); + authorize_and_stash_cmd.populate_chksum().unwrap(); + + let resp = model + .mailbox_execute( + u32::from(CommandId::AUTHORIZE_AND_STASH), + authorize_and_stash_cmd.as_bytes().unwrap(), + ) + .unwrap() + .expect("We should have received a response"); + + let authorize_and_stash_resp = AuthorizeAndStashResp::read_from(resp.as_slice()).unwrap(); + assert_eq!( + authorize_and_stash_resp.auth_req_result, + IMAGE_HASH_MISMATCH + ); + } +} diff --git a/runtime/tests/runtime_integration_tests/test_set_auth_manifest.rs b/runtime/tests/runtime_integration_tests/test_set_auth_manifest.rs index d88ad95415..9b936ce845 100644 --- a/runtime/tests/runtime_integration_tests/test_set_auth_manifest.rs +++ b/runtime/tests/runtime_integration_tests/test_set_auth_manifest.rs @@ -4,13 +4,13 @@ use crate::{ common::{assert_error, run_rt_test_lms, RuntimeTestArgs}, test_authorize_and_stash::IMAGE_DIGEST1, }; -use caliptra_api::SocManager; +use caliptra_api::{mailbox::ImageHashSource, SocManager}; use caliptra_auth_man_gen::{ AuthManifestGenerator, AuthManifestGeneratorConfig, AuthManifestGeneratorKeyConfig, }; use caliptra_auth_man_types::{ AuthManifestFlags, AuthManifestImageMetadata, AuthManifestPrivKeys, AuthManifestPubKeys, - AuthorizationManifest, + AuthorizationManifest, ImageMetadataFlags, AUTH_MANIFEST_IMAGE_METADATA_MAX_COUNT, }; use caliptra_common::mailbox_api::{CommandId, MailboxReq, MailboxReqHeader, SetAuthManifestReq}; use caliptra_error::CaliptraError; @@ -20,7 +20,7 @@ use caliptra_image_fake_keys::*; use caliptra_runtime::RtBootStatus; use zerocopy::AsBytes; -pub fn test_auth_manifest() -> AuthorizationManifest { +pub fn create_auth_manifest(manifest_flags: AuthManifestFlags) -> AuthorizationManifest { let vendor_fw_key_info: AuthManifestGeneratorKeyConfig = AuthManifestGeneratorKeyConfig { pub_keys: AuthManifestPubKeys { ecc_pub_key: VENDOR_ECC_KEY_0_PUBLIC, @@ -74,18 +74,168 @@ pub fn test_auth_manifest() -> AuthorizationManifest { 0xC8, 0x25, 0xA7, ]; + let mut flags1 = ImageMetadataFlags(0); + flags1.set_ignore_auth_check(false); + flags1.set_image_source(ImageHashSource::InRequest as u32); + + let mut flags2 = ImageMetadataFlags(0); + flags2.set_ignore_auth_check(true); + flags2.set_image_source(ImageHashSource::ShaAcc as u32); + // Generate authorization manifest. let image_metadata_list: Vec = vec![ AuthManifestImageMetadata { - image_source: 0, + fw_id: 1, + flags: flags1.0, digest: IMAGE_DIGEST1, }, AuthManifestImageMetadata { - image_source: 1, + fw_id: 2, + flags: flags2.0, digest: image_digest2, }, ]; + let gen_config: AuthManifestGeneratorConfig = AuthManifestGeneratorConfig { + vendor_fw_key_info, + vendor_man_key_info, + owner_fw_key_info, + owner_man_key_info, + image_metadata_list, + version: 1, + flags: manifest_flags, + }; + + let gen = AuthManifestGenerator::new(Crypto::default()); + gen.generate(&gen_config).unwrap() +} + +pub fn create_auth_manifest_with_metadata( + image_metadata_list: Vec, +) -> AuthorizationManifest { + let vendor_fw_key_info: AuthManifestGeneratorKeyConfig = AuthManifestGeneratorKeyConfig { + pub_keys: AuthManifestPubKeys { + ecc_pub_key: VENDOR_ECC_KEY_0_PUBLIC, + lms_pub_key: VENDOR_LMS_KEY_0_PUBLIC, + }, + priv_keys: Some(AuthManifestPrivKeys { + ecc_priv_key: VENDOR_ECC_KEY_0_PRIVATE, + lms_priv_key: VENDOR_LMS_KEY_0_PRIVATE, + }), + }; + + let vendor_man_key_info: AuthManifestGeneratorKeyConfig = AuthManifestGeneratorKeyConfig { + pub_keys: AuthManifestPubKeys { + ecc_pub_key: VENDOR_ECC_KEY_1_PUBLIC, + lms_pub_key: VENDOR_LMS_KEY_1_PUBLIC, + }, + priv_keys: Some(AuthManifestPrivKeys { + ecc_priv_key: VENDOR_ECC_KEY_1_PRIVATE, + lms_priv_key: VENDOR_LMS_KEY_1_PRIVATE, + }), + }; + + let owner_fw_key_info: Option = + Some(AuthManifestGeneratorKeyConfig { + pub_keys: AuthManifestPubKeys { + ecc_pub_key: OWNER_ECC_KEY_PUBLIC, + lms_pub_key: OWNER_LMS_KEY_PUBLIC, + }, + priv_keys: Some(AuthManifestPrivKeys { + ecc_priv_key: OWNER_ECC_KEY_PRIVATE, + lms_priv_key: OWNER_LMS_KEY_PRIVATE, + }), + }); + + let owner_man_key_info: Option = + Some(AuthManifestGeneratorKeyConfig { + pub_keys: AuthManifestPubKeys { + ecc_pub_key: OWNER_ECC_KEY_PUBLIC, + lms_pub_key: OWNER_LMS_KEY_PUBLIC, + }, + priv_keys: Some(AuthManifestPrivKeys { + ecc_priv_key: OWNER_ECC_KEY_PRIVATE, + lms_priv_key: OWNER_LMS_KEY_PRIVATE, + }), + }); + + let gen_config: AuthManifestGeneratorConfig = AuthManifestGeneratorConfig { + vendor_fw_key_info, + vendor_man_key_info, + owner_fw_key_info, + owner_man_key_info, + image_metadata_list, + version: 1, + flags: AuthManifestFlags::VENDOR_SIGNATURE_REQUIRED, + }; + + let gen = AuthManifestGenerator::new(Crypto::default()); + gen.generate(&gen_config).unwrap() +} + +fn create_auth_manifest_of_metadata_size(metadata_size: usize) -> AuthorizationManifest { + let vendor_fw_key_info: AuthManifestGeneratorKeyConfig = AuthManifestGeneratorKeyConfig { + pub_keys: AuthManifestPubKeys { + ecc_pub_key: VENDOR_ECC_KEY_0_PUBLIC, + lms_pub_key: VENDOR_LMS_KEY_0_PUBLIC, + }, + priv_keys: Some(AuthManifestPrivKeys { + ecc_priv_key: VENDOR_ECC_KEY_0_PRIVATE, + lms_priv_key: VENDOR_LMS_KEY_0_PRIVATE, + }), + }; + + let vendor_man_key_info: AuthManifestGeneratorKeyConfig = AuthManifestGeneratorKeyConfig { + pub_keys: AuthManifestPubKeys { + ecc_pub_key: VENDOR_ECC_KEY_1_PUBLIC, + lms_pub_key: VENDOR_LMS_KEY_1_PUBLIC, + }, + priv_keys: Some(AuthManifestPrivKeys { + ecc_priv_key: VENDOR_ECC_KEY_1_PRIVATE, + lms_priv_key: VENDOR_LMS_KEY_1_PRIVATE, + }), + }; + + let owner_fw_key_info: Option = + Some(AuthManifestGeneratorKeyConfig { + pub_keys: AuthManifestPubKeys { + ecc_pub_key: OWNER_ECC_KEY_PUBLIC, + lms_pub_key: OWNER_LMS_KEY_PUBLIC, + }, + priv_keys: Some(AuthManifestPrivKeys { + ecc_priv_key: OWNER_ECC_KEY_PRIVATE, + lms_priv_key: OWNER_LMS_KEY_PRIVATE, + }), + }); + + let owner_man_key_info: Option = + Some(AuthManifestGeneratorKeyConfig { + pub_keys: AuthManifestPubKeys { + ecc_pub_key: OWNER_ECC_KEY_PUBLIC, + lms_pub_key: OWNER_LMS_KEY_PUBLIC, + }, + priv_keys: Some(AuthManifestPrivKeys { + ecc_priv_key: OWNER_ECC_KEY_PRIVATE, + lms_priv_key: OWNER_LMS_KEY_PRIVATE, + }), + }); + + let mut flags = ImageMetadataFlags(0); + flags.set_ignore_auth_check(true); + flags.set_image_source(ImageHashSource::ShaAcc as u32); + let mut digest = crate::test_authorize_and_stash::IMAGE_DIGEST1; + + // Generate authorization manifest with a specific amount of elements. + let mut image_metadata_list = Vec::new(); + for id in 0..metadata_size { + digest[0] = id as u8; + image_metadata_list.push(AuthManifestImageMetadata { + fw_id: id as u32, + flags: flags.0, + digest, + }) + } + let gen_config: AuthManifestGeneratorConfig = AuthManifestGeneratorConfig { vendor_fw_key_info, vendor_man_key_info, @@ -108,7 +258,7 @@ fn test_set_auth_manifest_cmd() { m.soc_ifc().cptra_boot_status().read() == u32::from(RtBootStatus::RtReadyForCommands) }); - let auth_manifest = test_auth_manifest(); + let auth_manifest = create_auth_manifest(AuthManifestFlags::VENDOR_SIGNATURE_REQUIRED); let buf = auth_manifest.as_bytes(); let mut auth_manifest_slice = [0u8; SetAuthManifestReq::MAX_MAN_SIZE]; auth_manifest_slice[..buf.len()].copy_from_slice(buf); @@ -206,9 +356,78 @@ fn test_manifest_expect_err(manifest: AuthorizationManifest, expected_err: Calip assert_error(&mut model, expected_err, resp); } +#[test] +fn test_set_auth_manifest_cmd_zero_metadata_entry() { + let auth_manifest = create_auth_manifest_of_metadata_size(0); + test_manifest_expect_err( + auth_manifest, + CaliptraError::RUNTIME_AUTH_MANIFEST_IMAGE_METADATA_LIST_INVALID_ENTRY_COUNT, + ); +} + +#[test] +fn test_set_auth_manifest_cmd_max_metadata_entry_limit() { + let auth_manifest = + create_auth_manifest_of_metadata_size(AUTH_MANIFEST_IMAGE_METADATA_MAX_COUNT); + + let mut model = run_rt_test_lms(RuntimeTestArgs::default()); + + model.step_until(|m| { + m.soc_ifc().cptra_boot_status().read() == u32::from(RtBootStatus::RtReadyForCommands) + }); + + let buf = auth_manifest.as_bytes(); + let mut auth_manifest_slice = [0u8; SetAuthManifestReq::MAX_MAN_SIZE]; + auth_manifest_slice[..buf.len()].copy_from_slice(buf); + + let mut set_auth_manifest_cmd = MailboxReq::SetAuthManifest(SetAuthManifestReq { + hdr: MailboxReqHeader { chksum: 0 }, + manifest_size: buf.len() as u32, + manifest: auth_manifest_slice, + }); + set_auth_manifest_cmd.populate_chksum().unwrap(); + + model + .mailbox_execute( + u32::from(CommandId::SET_AUTH_MANIFEST), + set_auth_manifest_cmd.as_bytes().unwrap(), + ) + .unwrap() + .expect("We should have received a response"); +} + +#[test] +fn test_set_auth_manifest_cmd_max_plus_one_metadata_entry_limit() { + let mut auth_manifest = + create_auth_manifest_of_metadata_size(AUTH_MANIFEST_IMAGE_METADATA_MAX_COUNT); + auth_manifest.image_metadata_col.entry_count += 1; + + let mut flags = ImageMetadataFlags(0); + flags.set_ignore_auth_check(true); + flags.set_image_source(ImageHashSource::ShaAcc as u32); + + let ptr = auth_manifest + .image_metadata_col + .image_metadata_list + .as_mut_ptr(); + + unsafe { + *ptr.add(AUTH_MANIFEST_IMAGE_METADATA_MAX_COUNT) = AuthManifestImageMetadata { + fw_id: 127, + flags: flags.0, + digest: IMAGE_DIGEST1, + }; + } + + test_manifest_expect_err( + auth_manifest, + CaliptraError::RUNTIME_AUTH_MANIFEST_IMAGE_METADATA_LIST_INVALID_ENTRY_COUNT, + ); +} + #[test] fn test_set_auth_manifest_invalid_preamble_marker() { - let mut auth_manifest = test_auth_manifest(); + let mut auth_manifest = create_auth_manifest(AuthManifestFlags::VENDOR_SIGNATURE_REQUIRED); auth_manifest.preamble.marker = Default::default(); test_manifest_expect_err( auth_manifest, @@ -218,7 +437,7 @@ fn test_set_auth_manifest_invalid_preamble_marker() { #[test] fn test_set_auth_manifest_invalid_preamble_size() { - let mut auth_manifest = test_auth_manifest(); + let mut auth_manifest = create_auth_manifest(AuthManifestFlags::VENDOR_SIGNATURE_REQUIRED); auth_manifest.preamble.size -= 1; test_manifest_expect_err( auth_manifest, @@ -228,7 +447,7 @@ fn test_set_auth_manifest_invalid_preamble_size() { #[test] fn test_set_auth_manifest_invalid_vendor_ecc_sig() { - let mut auth_manifest = test_auth_manifest(); + let mut auth_manifest = create_auth_manifest(AuthManifestFlags::VENDOR_SIGNATURE_REQUIRED); auth_manifest.preamble.vendor_pub_keys_signatures.ecc_sig = Default::default(); test_manifest_expect_err( auth_manifest, @@ -238,7 +457,7 @@ fn test_set_auth_manifest_invalid_vendor_ecc_sig() { #[test] fn test_set_auth_manifest_invalid_vendor_lms_sig() { - let mut auth_manifest = test_auth_manifest(); + let mut auth_manifest = create_auth_manifest(AuthManifestFlags::VENDOR_SIGNATURE_REQUIRED); auth_manifest.preamble.vendor_pub_keys_signatures.lms_sig = Default::default(); test_manifest_expect_err( auth_manifest, @@ -248,7 +467,7 @@ fn test_set_auth_manifest_invalid_vendor_lms_sig() { #[test] fn test_set_auth_manifest_invalid_owner_ecc_sig() { - let mut auth_manifest = test_auth_manifest(); + let mut auth_manifest = create_auth_manifest(AuthManifestFlags::VENDOR_SIGNATURE_REQUIRED); auth_manifest.preamble.owner_pub_keys_signatures.ecc_sig = Default::default(); test_manifest_expect_err( auth_manifest, @@ -258,7 +477,7 @@ fn test_set_auth_manifest_invalid_owner_ecc_sig() { #[test] fn test_set_auth_manifest_invalid_owner_lms_sig() { - let mut auth_manifest = test_auth_manifest(); + let mut auth_manifest = create_auth_manifest(AuthManifestFlags::VENDOR_SIGNATURE_REQUIRED); auth_manifest.preamble.owner_pub_keys_signatures.lms_sig = Default::default(); test_manifest_expect_err( auth_manifest, @@ -268,7 +487,7 @@ fn test_set_auth_manifest_invalid_owner_lms_sig() { #[test] fn test_set_auth_manifest_invalid_metadata_list_count() { - let mut auth_manifest = test_auth_manifest(); + let mut auth_manifest = create_auth_manifest(AuthManifestFlags::VENDOR_SIGNATURE_REQUIRED); auth_manifest.image_metadata_col.entry_count = 0; test_manifest_expect_err( auth_manifest, @@ -278,7 +497,7 @@ fn test_set_auth_manifest_invalid_metadata_list_count() { #[test] fn test_set_auth_manifest_invalid_vendor_metadata_ecc_sig() { - let mut auth_manifest = test_auth_manifest(); + let mut auth_manifest = create_auth_manifest(AuthManifestFlags::VENDOR_SIGNATURE_REQUIRED); auth_manifest .preamble .vendor_image_metdata_signatures @@ -291,7 +510,7 @@ fn test_set_auth_manifest_invalid_vendor_metadata_ecc_sig() { #[test] fn test_set_auth_manifest_invalid_vendor_metadata_lms_sig() { - let mut auth_manifest = test_auth_manifest(); + let mut auth_manifest = create_auth_manifest(AuthManifestFlags::VENDOR_SIGNATURE_REQUIRED); auth_manifest .preamble .vendor_image_metdata_signatures @@ -304,7 +523,7 @@ fn test_set_auth_manifest_invalid_vendor_metadata_lms_sig() { #[test] fn test_set_auth_manifest_invalid_owner_metadata_ecc_sig() { - let mut auth_manifest = test_auth_manifest(); + let mut auth_manifest = create_auth_manifest(AuthManifestFlags::VENDOR_SIGNATURE_REQUIRED); auth_manifest .preamble .owner_image_metdata_signatures @@ -317,7 +536,7 @@ fn test_set_auth_manifest_invalid_owner_metadata_ecc_sig() { #[test] fn test_set_auth_manifest_invalid_owner_metadata_lms_sig() { - let mut auth_manifest = test_auth_manifest(); + let mut auth_manifest = create_auth_manifest(AuthManifestFlags::VENDOR_SIGNATURE_REQUIRED); auth_manifest .preamble .owner_image_metdata_signatures @@ -327,3 +546,75 @@ fn test_set_auth_manifest_invalid_owner_metadata_lms_sig() { CaliptraError::RUNTIME_AUTH_MANIFEST_OWNER_LMS_SIGNATURE_INVALID, ); } + +#[test] +fn test_set_auth_manifest_cmd_ignore_vendor_ecc_sig() { + let mut auth_manifest = create_auth_manifest(0.into()); + + // Erase the vendor manifest ECC signature. + auth_manifest + .preamble + .vendor_image_metdata_signatures + .ecc_sig = Default::default(); + + let buf = auth_manifest.as_bytes(); + let mut auth_manifest_slice = [0u8; SetAuthManifestReq::MAX_MAN_SIZE]; + auth_manifest_slice[..buf.len()].copy_from_slice(buf); + + let mut model = run_rt_test_lms(RuntimeTestArgs::default()); + + model.step_until(|m| { + m.soc_ifc().cptra_boot_status().read() == u32::from(RtBootStatus::RtReadyForCommands) + }); + + let mut set_auth_manifest_cmd = MailboxReq::SetAuthManifest(SetAuthManifestReq { + hdr: MailboxReqHeader { chksum: 0 }, + manifest_size: buf.len() as u32, + manifest: auth_manifest_slice, + }); + set_auth_manifest_cmd.populate_chksum().unwrap(); + + model + .mailbox_execute( + u32::from(CommandId::SET_AUTH_MANIFEST), + set_auth_manifest_cmd.as_bytes().unwrap(), + ) + .unwrap() + .expect("We should have received a response"); +} + +#[test] +fn test_set_auth_manifest_cmd_ignore_vendor_lms_sig() { + let mut auth_manifest = create_auth_manifest(0.into()); + + // Erase the vendor manifest LMS signature. + auth_manifest + .preamble + .vendor_image_metdata_signatures + .lms_sig = Default::default(); + + let buf = auth_manifest.as_bytes(); + let mut auth_manifest_slice = [0u8; SetAuthManifestReq::MAX_MAN_SIZE]; + auth_manifest_slice[..buf.len()].copy_from_slice(buf); + + let mut model = run_rt_test_lms(RuntimeTestArgs::default()); + + model.step_until(|m| { + m.soc_ifc().cptra_boot_status().read() == u32::from(RtBootStatus::RtReadyForCommands) + }); + + let mut set_auth_manifest_cmd = MailboxReq::SetAuthManifest(SetAuthManifestReq { + hdr: MailboxReqHeader { chksum: 0 }, + manifest_size: buf.len() as u32, + manifest: auth_manifest_slice, + }); + set_auth_manifest_cmd.populate_chksum().unwrap(); + + model + .mailbox_execute( + u32::from(CommandId::SET_AUTH_MANIFEST), + set_auth_manifest_cmd.as_bytes().unwrap(), + ) + .unwrap() + .expect("We should have received a response"); +} From 824a384b958f8dc6ffac91d597882daf58bfba40 Mon Sep 17 00:00:00 2001 From: Vishal Mhatre <38512878+mhatrevi@users.noreply.github.com> Date: Tue, 17 Dec 2024 19:40:56 -0800 Subject: [PATCH 49/51] [feat] Data Vault in DCCM (#1844) This change moves the information stored in the hardware datavault into a DCCM-backed datavault. Memory protections on the DCCM datavault will be added as a separate change later. --- common/src/verifier.rs | 10 +- drivers/src/data_vault.rs | 575 ++++++------------ drivers/src/hand_off.rs | 180 +----- drivers/src/lib.rs | 4 +- drivers/src/memory_layout.rs | 14 +- drivers/src/persistent.rs | 6 +- fmc/README.md | 32 +- fmc/src/fmc_env.rs | 10 +- fmc/src/hand_off.rs | 97 +-- rom/dev/README.md | 4 +- rom/dev/src/crypto.rs | 8 +- rom/dev/src/fht.rs | 130 +--- rom/dev/src/flow/cold_reset/fmc_alias.rs | 33 +- rom/dev/src/flow/cold_reset/fw_processor.rs | 64 +- rom/dev/src/flow/cold_reset/idev_id.rs | 2 +- rom/dev/src/flow/cold_reset/ldev_id.rs | 16 +- rom/dev/src/flow/cold_reset/mod.rs | 18 +- rom/dev/src/flow/cold_reset/x509.rs | 16 +- rom/dev/src/flow/fake.rs | 18 +- rom/dev/src/flow/update_reset.rs | 41 +- rom/dev/src/flow/warm_reset.rs | 13 +- rom/dev/src/lock.rs | 60 +- rom/dev/src/main.rs | 2 +- rom/dev/src/pcr.rs | 64 +- rom/dev/src/rom_env.rs | 12 +- .../test_fmcalias_derivation.rs | 19 +- .../test_update_reset.rs | 18 +- rom/dev/tools/test-fmc/src/main.rs | 72 +-- runtime/src/dice.rs | 156 +---- runtime/src/drivers.rs | 13 +- runtime/src/fips.rs | 2 +- runtime/src/handoff.rs | 34 +- runtime/src/info.rs | 8 +- .../caliptra_integration_tests/smoke_test.rs | 2 +- 34 files changed, 437 insertions(+), 1316 deletions(-) diff --git a/common/src/verifier.rs b/common/src/verifier.rs index 17e99ecae6..108060fc1b 100644 --- a/common/src/verifier.rs +++ b/common/src/verifier.rs @@ -27,7 +27,7 @@ pub struct FirmwareImageVerificationEnv<'a, 'b> { pub soc_ifc: &'a mut SocIfc, pub ecc384: &'a mut Ecc384, pub mldsa87: &'a mut Mldsa87, - pub data_vault: &'a mut DataVault, + pub data_vault: &'a DataVault, pub pcr_bank: &'a mut PcrBank, pub image: &'b [u8], } @@ -154,15 +154,15 @@ impl<'a, 'b> ImageVerificationEnv for &mut FirmwareImageVerificationEnv<'a, 'b> /// Get the vendor ECC key index saved in data vault on cold boot fn vendor_ecc_pub_key_idx_dv(&self) -> u32 { - self.data_vault.ecc_vendor_pk_index() + self.data_vault.vendor_ecc_pk_index() } - /// Get the vendor LMS key index saved in data vault on cold boot + /// Get the vendor PQC key index saved in data vault on cold boot fn vendor_pqc_pub_key_idx_dv(&self) -> u32 { - self.data_vault.pqc_vendor_pk_index() + self.data_vault.vendor_pqc_pk_index() } - /// Get the owner public key digest saved in the dv on cold boot + /// Get the owner public keys digest saved in the dv on cold boot fn owner_pub_key_digest_dv(&self) -> ImageDigest384 { self.data_vault.owner_pk_hash().into() } diff --git a/drivers/src/data_vault.rs b/drivers/src/data_vault.rs index 09827120fb..613bca4245 100644 --- a/drivers/src/data_vault.rs +++ b/drivers/src/data_vault.rs @@ -8,275 +8,135 @@ File Name: Abstract: - File contains API for the Data Vault registers. + File contains API for the Data Vault. --*/ -use caliptra_registers::dv::DvReg; - -use crate::{Array4x12, Ecc384PubKey, Ecc384Signature}; - -#[derive(Debug, Clone, Copy, PartialEq, Eq)] -pub enum ColdResetEntry48 { - LDevDiceSigR = 0, - LDevDiceSigS = 1, - LDevDicePubKeyX = 2, - LDevDicePubKeyY = 3, - FmcDiceSigR = 4, - FmcDiceSigS = 5, - FmcPubKeyX = 6, - FmcPubKeyY = 7, - FmcTci = 8, - OwnerPubKeyHash = 9, +use crate::{Array4x12, Ecc384PubKey, Ecc384Signature, Mldsa87PubKey, Mldsa87Signature}; +use zerocopy::{AsBytes, FromBytes}; +use zeroize::Zeroize; + +#[repr(C)] +#[derive(FromBytes, AsBytes, Zeroize, Default)] +pub struct ColdResetEntries { + ldev_dice_ecc_sig: Ecc384Signature, + ldev_dice_ecc_pk: Ecc384PubKey, + ldev_dice_mldsa_sig: Mldsa87Signature, + ldev_dice_mldsa_pk: Mldsa87PubKey, + fmc_dice_ecc_sig: Ecc384Signature, + fmc_ecc_pk: Ecc384PubKey, + fmc_dice_mldsa_sig: Mldsa87Signature, + fmc_mldsa_pk: Mldsa87PubKey, + fmc_tci: Array4x12, + owner_pk_hash: Array4x12, + fmc_svn: u32, + rom_cold_boot_status: u32, + fmc_entry_point: u32, + vendor_ecc_pk_index: u32, + vendor_pqc_pk_index: u32, } -impl TryFrom for ColdResetEntry48 { - type Error = (); - fn try_from(value: u8) -> Result { - match value { - 0 => Ok(ColdResetEntry48::LDevDiceSigR), - 1 => Ok(ColdResetEntry48::LDevDiceSigS), - 2 => Ok(ColdResetEntry48::LDevDicePubKeyX), - 3 => Ok(ColdResetEntry48::LDevDicePubKeyY), - 4 => Ok(ColdResetEntry48::FmcDiceSigR), - 5 => Ok(ColdResetEntry48::FmcDiceSigS), - 6 => Ok(ColdResetEntry48::FmcPubKeyX), - 7 => Ok(ColdResetEntry48::FmcPubKeyY), - 8 => Ok(ColdResetEntry48::FmcTci), - 9 => Ok(ColdResetEntry48::OwnerPubKeyHash), - _ => Err(()), - } - } -} - -impl From for u8 { - fn from(value: ColdResetEntry48) -> Self { - value as Self - } -} - -impl From for u32 { - fn from(value: ColdResetEntry48) -> Self { - value as Self - } -} - -impl From for usize { - fn from(value: ColdResetEntry48) -> Self { - value as Self - } -} - -#[derive(Debug, Clone, Copy, PartialEq, Eq)] -pub enum ColdResetEntry4 { - FmcSvn = 0, - RomColdBootStatus = 1, - FmcEntryPoint = 2, - EccVendorPubKeyIndex = 3, - PqcVendorPubKeyIndex = 4, -} - -impl TryFrom for ColdResetEntry4 { - type Error = (); - fn try_from(value: u8) -> Result { - match value { - 0 => Ok(Self::FmcSvn), - 2 => Ok(Self::FmcEntryPoint), - 3 => Ok(Self::EccVendorPubKeyIndex), - 4 => Ok(Self::PqcVendorPubKeyIndex), - _ => Err(()), - } - } -} - -impl From for u8 { - fn from(value: ColdResetEntry4) -> Self { - value as Self - } -} - -impl From for u32 { - fn from(value: ColdResetEntry4) -> Self { - value as Self - } -} - -impl From for usize { - fn from(value: ColdResetEntry4) -> Self { - value as Self - } -} - -#[derive(Debug, Clone, Copy, PartialEq, Eq)] -pub enum WarmResetEntry48 { - RtTci = 0, -} - -impl From for u8 { - fn from(value: WarmResetEntry48) -> Self { - value as Self - } -} - -impl From for u32 { - fn from(value: WarmResetEntry48) -> Self { - value as Self - } -} - -impl From for usize { - fn from(value: WarmResetEntry48) -> Self { - value as Self - } -} - -#[derive(Debug, Clone, Copy, PartialEq, Eq)] -pub enum WarmResetEntry4 { - RtSvn = 0, - RtEntryPoint = 1, - ManifestAddr = 2, - RtMinSvn = 3, - RomUpdateResetStatus = 4, -} - -impl From for u8 { - fn from(value: WarmResetEntry4) -> Self { - value as Self - } -} - -impl From for u32 { - fn from(value: WarmResetEntry4) -> Self { - value as Self - } -} - -impl From for usize { - fn from(value: WarmResetEntry4) -> Self { - value as Self - } -} - -impl TryFrom for WarmResetEntry4 { - type Error = (); - fn try_from(original: u8) -> Result { - match original { - 0 => Ok(Self::RtSvn), - 1 => Ok(Self::RtEntryPoint), - 2 => Ok(Self::ManifestAddr), - 3 => Ok(Self::RtMinSvn), - _ => Err(()), - } - } -} - -impl TryFrom for WarmResetEntry48 { - type Error = (); - fn try_from(value: u8) -> Result { - match value { - 0 => Ok(Self::RtTci), - _ => Err(()), - } - } +#[repr(C)] +#[derive(FromBytes, AsBytes, Zeroize, Default)] +pub struct WarmResetEntries { + rt_tci: Array4x12, + rt_svn: u32, + rt_entry_point: u32, + manifest_addr: u32, + rt_min_svn: u32, + rom_update_reset_status: u32, } +#[repr(C)] +#[derive(FromBytes, AsBytes, Zeroize, Default)] pub struct DataVault { - dv: DvReg, + cold_reset_entries: ColdResetEntries, + warm_reset_entries: WarmResetEntries, } impl DataVault { - pub fn new(dv: DvReg) -> Self { - Self { dv } - } - /// Set the ldev dice signature. + /// Set the ldev dice ECC signature. /// /// # Arguments - /// * `sig` - ldev dice signature + /// * `sig` - ldev dice ECC signature /// - pub fn set_ldev_dice_signature(&mut self, sig: &Ecc384Signature) { - self.write_lock_cold_reset_entry48(ColdResetEntry48::LDevDiceSigR, &sig.r); - self.write_lock_cold_reset_entry48(ColdResetEntry48::LDevDiceSigS, &sig.s); + pub fn set_ldev_dice_ecc_signature(&mut self, sig: &Ecc384Signature) { + self.cold_reset_entries.ldev_dice_ecc_sig = *sig; } - /// Get the ldev dice signature. + /// Get the ldev dice ECC signature. /// /// # Arguments /// * None /// /// # Returns - /// ldev dice signature + /// ldev dice ECC signature /// - pub fn ldev_dice_signature(&self) -> Ecc384Signature { - Ecc384Signature { - r: self.read_cold_reset_entry48(ColdResetEntry48::LDevDiceSigR), - s: self.read_cold_reset_entry48(ColdResetEntry48::LDevDiceSigS), - } + pub fn ldev_dice_ecc_signature(&self) -> Ecc384Signature { + self.cold_reset_entries.ldev_dice_ecc_sig } - /// Set the ldev dice public key. + /// Set the ldev dice ECC public key. /// /// # Arguments - /// * `pub_key` - ldev dice public key + /// * `pub_key` - ldev dice ECC public key /// - pub fn set_ldev_dice_pub_key(&mut self, pub_key: &Ecc384PubKey) { - self.write_lock_cold_reset_entry48(ColdResetEntry48::LDevDicePubKeyX, &pub_key.x); - self.write_lock_cold_reset_entry48(ColdResetEntry48::LDevDicePubKeyY, &pub_key.y); + pub fn set_ldev_dice_ecc_pub_key(&mut self, pub_key: &Ecc384PubKey) { + self.cold_reset_entries.ldev_dice_ecc_pk = *pub_key; } - /// Get the ldev dice public key. + /// Get the ldev dice ECC public key. /// /// # Returns - /// * ldev dice public key + /// * ldev dice ECC public key /// - pub fn ldev_dice_pub_key(&self) -> Ecc384PubKey { - Ecc384PubKey { - x: self.read_cold_reset_entry48(ColdResetEntry48::LDevDicePubKeyX), - y: self.read_cold_reset_entry48(ColdResetEntry48::LDevDicePubKeyY), - } + pub fn ldev_dice_ecc_pub_key(&self) -> Ecc384PubKey { + self.cold_reset_entries.ldev_dice_ecc_pk } - /// Set the fmc dice signature. + /// Set the fmc dice ECC signature. /// /// # Arguments - /// * `sig` - fmc dice signature + /// * `sig` - fmc dice ECC signature /// - pub fn set_fmc_dice_signature(&mut self, sig: &Ecc384Signature) { - self.write_lock_cold_reset_entry48(ColdResetEntry48::FmcDiceSigR, &sig.r); - self.write_lock_cold_reset_entry48(ColdResetEntry48::FmcDiceSigS, &sig.s); + pub fn set_fmc_dice_ecc_signature(&mut self, sig: &Ecc384Signature) { + self.cold_reset_entries.fmc_dice_ecc_sig = *sig; } - /// Get the fmc dice signature. + /// Get the fmc dice ECC signature. /// /// # Returns - /// * fmc dice signature + /// * fmc dice ECC signature /// - pub fn fmc_dice_signature(&self) -> Ecc384Signature { - Ecc384Signature { - r: self.read_cold_reset_entry48(ColdResetEntry48::FmcDiceSigR), - s: self.read_cold_reset_entry48(ColdResetEntry48::FmcDiceSigS), - } + pub fn fmc_dice_ecc_signature(&self) -> Ecc384Signature { + self.cold_reset_entries.fmc_dice_ecc_sig } - /// Set the fmc public key. + /// Set the fmc ECC public key. /// /// # Arguments - /// * `pub_key` - fmc public key + /// * `pub_key` - fmc ECC public key /// - pub fn set_fmc_pub_key(&mut self, pub_key: &Ecc384PubKey) { - self.write_lock_cold_reset_entry48(ColdResetEntry48::FmcPubKeyX, &pub_key.x); - self.write_lock_cold_reset_entry48(ColdResetEntry48::FmcPubKeyY, &pub_key.y); + pub fn set_fmc_ecc_pub_key(&mut self, pub_key: &Ecc384PubKey) { + self.cold_reset_entries.fmc_ecc_pk = *pub_key; } - /// Get the fmc public key. + /// Get the fmc ECC public key. /// /// # Returns - /// * fmc public key + /// * fmc ECC public key + /// + pub fn fmc_ecc_pub_key(&self) -> Ecc384PubKey { + self.cold_reset_entries.fmc_ecc_pk + } + + /// Set the fmc tcb component identifier. /// - pub fn fmc_pub_key(&self) -> Ecc384PubKey { - Ecc384PubKey { - x: self.read_cold_reset_entry48(ColdResetEntry48::FmcPubKeyX), - y: self.read_cold_reset_entry48(ColdResetEntry48::FmcPubKeyY), - } + /// # Arguments + /// * `tci` - fmc tcb component identifier + /// + pub fn set_fmc_tci(&mut self, tci: &Array4x12) { + self.cold_reset_entries.fmc_tci = *tci; } /// Get the fmc tcb component identifier. @@ -285,291 +145,222 @@ impl DataVault { /// * fmc tcb component identifier /// pub fn fmc_tci(&self) -> Array4x12 { - self.read_cold_reset_entry48(ColdResetEntry48::FmcTci) + self.cold_reset_entries.fmc_tci } - /// Get the owner public key hash + /// Set the owner public keys hash /// - /// # Returns + /// # Arguments /// - /// * `Array4x12` - Owner public key hash + /// * `hash` - Owner public keys hash /// - pub fn owner_pk_hash(&self) -> Array4x12 { - self.read_cold_reset_entry48(ColdResetEntry48::OwnerPubKeyHash) + pub fn set_owner_pk_hash(&mut self, hash: &Array4x12) { + self.cold_reset_entries.owner_pk_hash = *hash; } - /// Get the fmc security version number. + /// Get the owner public keys hash /// /// # Returns - /// * fmc security version number - /// - pub fn fmc_svn(&self) -> u32 { - self.read_cold_reset_entry4(ColdResetEntry4::FmcSvn) - } - - /// Get the fmc entry. /// - /// # Returns + /// * `Array4x12` - Owner public keys hash /// - /// * fmc entry point - pub fn fmc_entry_point(&self) -> u32 { - self.read_cold_reset_entry4(ColdResetEntry4::FmcEntryPoint) + pub fn owner_pk_hash(&self) -> Array4x12 { + self.cold_reset_entries.owner_pk_hash } - /// Get the Ecc vendor public key index used for image verification. + /// Set the fmc security version number. /// - /// # Returns + /// # Arguments + /// * `svn` - fmc security version number /// - /// * `u32` - Vendor public key index - pub fn ecc_vendor_pk_index(&self) -> u32 { - self.read_cold_reset_entry4(ColdResetEntry4::EccVendorPubKeyIndex) + pub fn set_fmc_svn(&mut self, svn: u32) { + self.cold_reset_entries.fmc_svn = svn; } - /// Get the PQC (LMS or MLDSA) vendor public key index used for image verification. + /// Get the fmc security version number. /// /// # Returns + /// * fmc security version number /// - /// * `u32` - Vendor public key index - pub fn pqc_vendor_pk_index(&self) -> u32 { - self.read_cold_reset_entry4(ColdResetEntry4::PqcVendorPubKeyIndex) + pub fn fmc_svn(&self) -> u32 { + self.cold_reset_entries.fmc_svn } - /// Get the rom cold boot status. + /// Set the fmc entry point. /// - /// # Returns + /// # Arguments /// - /// * `u32` - Rom Cold Boot Status - pub fn rom_cold_boot_status(&self) -> u32 { - self.read_cold_reset_entry4(ColdResetEntry4::RomColdBootStatus) + /// * `entry_point` - fmc entry point + pub fn set_fmc_entry_point(&mut self, entry_point: u32) { + self.cold_reset_entries.fmc_entry_point = entry_point; } - /// Get the rom update reset status. + /// Get the fmc entry point. /// /// # Returns /// - /// * `u32` - Rom Update Reset Status - pub fn rom_update_reset_status(&self) -> u32 { - self.read_warm_reset_entry4(WarmResetEntry4::RomUpdateResetStatus) + /// * fmc entry point + pub fn fmc_entry_point(&self) -> u32 { + self.cold_reset_entries.fmc_entry_point } - /// Get the rt tcb component identifier. + /// Set the vendor ECC public key index used for image verification. /// - /// # Returns - /// * rt tcb component identifier + /// # Arguments /// - pub fn rt_tci(&self) -> Array4x12 { - self.read_warm_reset_entry48(WarmResetEntry48::RtTci) + /// * `index` - Vendor ECC public key index + pub fn set_vendor_ecc_pk_index(&mut self, index: u32) { + self.cold_reset_entries.vendor_ecc_pk_index = index; } - /// Get the rt security version number. + /// Get the vendor ECC public key index used for image verification. /// /// # Returns - /// * rt security version number /// - pub fn rt_svn(&self) -> u32 { - self.read_warm_reset_entry4(WarmResetEntry4::RtSvn) + /// * `u32` - Vendor ECC public key index + pub fn vendor_ecc_pk_index(&self) -> u32 { + self.cold_reset_entries.vendor_ecc_pk_index } - /// Get the rt minimum security version number. + /// Set the vendor LMS public key index used for image verification. /// - /// # Returns - /// * rt minimum security version number + /// # Arguments /// - pub fn rt_min_svn(&self) -> u32 { - self.read_warm_reset_entry4(WarmResetEntry4::RtMinSvn) + /// * `index` - Vendor LMS public key index + pub fn set_vendor_pqc_pk_index(&mut self, index: u32) { + self.cold_reset_entries.vendor_pqc_pk_index = index; } - /// Get the rt entry. + /// Get the PQC (LMS or MLDSA) vendor public key index used for image verification. /// /// # Returns /// - /// * rt entry point - pub fn rt_entry_point(&self) -> u32 { - self.read_warm_reset_entry4(WarmResetEntry4::RtEntryPoint) + /// * `u32` - Vendor public key index + pub fn vendor_pqc_pk_index(&self) -> u32 { + self.cold_reset_entries.vendor_pqc_pk_index } - /// Get the manifest address. + /// Set the rom cold boot status. /// - /// # Returns + /// # Arguments /// - /// * manifest address - pub fn manifest_addr(&self) -> u32 { - self.read_warm_reset_entry4(WarmResetEntry4::ManifestAddr) + /// * `status` - Rom Cold Boot Status + pub fn set_rom_cold_boot_status(&mut self, status: u32) { + self.cold_reset_entries.rom_cold_boot_status = status; } - /// Read the cold reset entry. - /// - /// # Arguments - /// * `entry` - cold reset entry + /// Get the rom cold boot status. /// /// # Returns - /// cold reset entry value /// - pub fn read_cold_reset_entry48(&self, entry: ColdResetEntry48) -> Array4x12 { - let dv = self.dv.regs(); - Array4x12::read_from_reg(dv.sticky_data_vault_entry().at(entry.into())) + /// * `u32` - Rom Cold Boot Status + pub fn rom_cold_boot_status(&self) -> u32 { + self.cold_reset_entries.rom_cold_boot_status } - /// Write and lock the cold reset entry. + /// Set the rom update reset status. /// /// # Arguments - /// * `entry` - cold reset entry - /// * `value` - cold reset entry value /// - fn write_lock_cold_reset_entry48(&mut self, entry: ColdResetEntry48, value: &Array4x12) { - self.write_cold_reset_entry48(entry, value); - self.lock_cold_reset_entry48(entry); + /// * `status` - Rom Update Reset Status + pub fn set_rom_update_reset_status(&mut self, status: u32) { + self.warm_reset_entries.rom_update_reset_status = status; } - /// Write the cold reset entry. + /// Get the rom update reset status. /// - /// # Arguments - /// * `entry` - cold reset entry - /// * `value` - cold reset entry value + /// # Returns /// - pub fn write_cold_reset_entry48(&mut self, entry: ColdResetEntry48, value: &Array4x12) { - let dv = self.dv.regs_mut(); - value.write_to_reg(dv.sticky_data_vault_entry().at(entry.into())); + /// * `u32` - Rom Update Reset Status + pub fn rom_update_reset_status(&self) -> u32 { + self.warm_reset_entries.rom_update_reset_status } - /// Lock the cold reset entry. + /// Set the rt tcb component identifier. /// /// # Arguments - /// * `entry` - cold reset entry + /// * `tci` - rt tcb component identifier /// - pub fn lock_cold_reset_entry48(&mut self, entry: ColdResetEntry48) { - let dv = self.dv.regs_mut(); - dv.sticky_data_vault_ctrl() - .at(entry.into()) - .write(|w| w.lock_entry(true)); + pub fn set_rt_tci(&mut self, tci: &Array4x12) { + self.warm_reset_entries.rt_tci = *tci; } - /// Read the warm reset entry. - /// - /// # Arguments - /// * `entry` - warm reset entry + /// Get the rt tcb component identifier. /// /// # Returns - /// warm reset entry value - /// - pub fn read_warm_reset_entry48(&self, entry: WarmResetEntry48) -> Array4x12 { - let dv = self.dv.regs(); - Array4x12::read_from_reg(dv.data_vault_entry().at(entry.into())) - } - - /// Write the warm reset entry. - /// - /// # Arguments - /// * `entry` - warm reset entry - /// * `value` - warm reset entry value + /// * rt tcb component identifier /// - pub fn write_warm_reset_entry48(&mut self, entry: WarmResetEntry48, value: &Array4x12) { - let dv = self.dv.regs_mut(); - value.write_to_reg(dv.data_vault_entry().at(entry.into())); + pub fn rt_tci(&self) -> Array4x12 { + self.warm_reset_entries.rt_tci } - /// Lock the warm reset entry. + /// Set the rt security version number. /// /// # Arguments - /// * `entry` - warm reset entry + /// * `svn` - rt security version number /// - pub fn lock_warm_reset_entry48(&mut self, entry: WarmResetEntry48) { - let dv = self.dv.regs_mut(); - dv.data_vault_ctrl() - .at(entry.into()) - .write(|w| w.lock_entry(true)); + pub fn set_rt_svn(&mut self, svn: u32) { + self.warm_reset_entries.rt_svn = svn; } - /// Read the cold reset entry. - /// - /// # Arguments - /// * `entry` - cold reset entry + /// Get the rt security version number. /// /// # Returns - /// cold reset entry value + /// * rt security version number /// - pub fn read_cold_reset_entry4(&self, entry: ColdResetEntry4) -> u32 { - let dv = self.dv.regs(); - dv.sticky_lockable_scratch_reg().at(entry.into()).read() + pub fn rt_svn(&self) -> u32 { + self.warm_reset_entries.rt_svn } - /// Write and lock the cold reset entry. + /// Set the rt minimum security version number. /// /// # Arguments - /// * `entry` - cold reset entry - /// * `value` - cold reset entry value + /// * `svn` - rt minimum security version number /// - pub fn write_lock_cold_reset_entry4(&mut self, entry: ColdResetEntry4, value: u32) { - self.write_cold_reset_entry4(entry, value); - self.lock_cold_reset_entry4(entry); + pub fn set_rt_min_svn(&mut self, svn: u32) { + self.warm_reset_entries.rt_min_svn = svn; } - /// Write the cold reset entry. + /// Get the rt minimum security version number. /// - /// # Arguments - /// * `entry` - cold reset entry - /// * `value` - cold reset entry value + /// # Returns + /// * rt minimum security version number /// - pub fn write_cold_reset_entry4(&mut self, entry: ColdResetEntry4, value: u32) { - let dv = self.dv.regs_mut(); - dv.sticky_lockable_scratch_reg() - .at(entry.into()) - .write(|_| value); + pub fn rt_min_svn(&self) -> u32 { + self.warm_reset_entries.rt_min_svn } - /// Lock the cold reset entry. + /// Set the rt entry. /// /// # Arguments - /// * `entry` - cold reset entry - /// - pub fn lock_cold_reset_entry4(&mut self, entry: ColdResetEntry4) { - let dv = self.dv.regs_mut(); - dv.sticky_lockable_scratch_reg_ctrl() - .at(entry.into()) - .write(|w| w.lock_entry(true)); + /// * `entry_point` - rt entry point + pub fn set_rt_entry_point(&mut self, entry_point: u32) { + self.warm_reset_entries.rt_entry_point = entry_point; } - /// Read the warm reset entry. - /// - /// # Arguments - /// * `entry` - warm reset entry + /// Get the rt entry. /// /// # Returns - /// warm reset entry value /// - pub fn read_warm_reset_entry4(&self, entry: WarmResetEntry4) -> u32 { - let dv = self.dv.regs(); - dv.lockable_scratch_reg().at(entry.into()).read() + /// * rt entry point + pub fn rt_entry_point(&self) -> u32 { + self.warm_reset_entries.rt_entry_point } - /// Write and lock the warm reset entry. + /// Set the manifest address. /// /// # Arguments - /// * `entry` - warm reset entry - /// * `value` - warm reset entry value - pub fn write_lock_warm_reset_entry4(&mut self, entry: WarmResetEntry4, value: u32) { - self.write_warm_reset_entry4(entry, value); - self.lock_warm_reset_entry4(entry); + /// * `addr` - manifest address + pub fn set_manifest_addr(&mut self, addr: u32) { + self.warm_reset_entries.manifest_addr = addr; } - /// Write the warm reset entry. + /// Get the manifest address. /// - /// # Arguments - /// * `entry` - warm reset entry - /// * `value` - warm reset entry value - pub fn write_warm_reset_entry4(&mut self, entry: WarmResetEntry4, value: u32) { - let dv = self.dv.regs_mut(); - dv.lockable_scratch_reg().at(entry.into()).write(|_| value); - } - - /// Lock the warm reset entry. + /// # Returns /// - /// # Arguments - /// * `entry` - warm reset entry - pub fn lock_warm_reset_entry4(&mut self, entry: WarmResetEntry4) { - let dv = self.dv.regs_mut(); - dv.lockable_scratch_reg_ctrl() - .at(entry.into()) - .write(|w| w.lock_entry(true)); + /// * manifest address + pub fn manifest_addr(&self) -> u32 { + self.warm_reset_entries.manifest_addr } } diff --git a/drivers/src/hand_off.rs b/drivers/src/hand_off.rs index eb59f6a39c..7be38b65ac 100644 --- a/drivers/src/hand_off.rs +++ b/drivers/src/hand_off.rs @@ -2,10 +2,7 @@ use crate::bounded_address::RomAddr; use crate::soc_ifc; -use crate::{ - memory_layout, ColdResetEntry4, ColdResetEntry48, Ecc384PubKey, Ecc384Signature, KeyId, - ResetReason, WarmResetEntry4, WarmResetEntry48, -}; +use crate::{memory_layout, Ecc384PubKey, Ecc384Signature, KeyId, ResetReason}; use bitfield::{bitfield_bitrange, bitfield_fields}; use caliptra_error::CaliptraError; use caliptra_image_types::RomInfo; @@ -67,10 +64,6 @@ impl TryFrom for Vault { pub enum DataStore { KeyVaultSlot(KeyId), //PlatformConfigRegister(PcrId), - DataVaultSticky4(ColdResetEntry4), - DataVaultSticky48(ColdResetEntry48), - DataVaultNonSticky4(WarmResetEntry4), - DataVaultNonSticky48(WarmResetEntry48), Invalid, } @@ -97,29 +90,6 @@ impl TryInto for HandOffDataHandle { KeyId::try_from(self.reg_num() as u8) .map_err(|_| CaliptraError::DRIVER_HANDOFF_INVALID_KEY_ID)?, )), - Vault::DataVault => match self.reg_type() { - 1 => Ok(DataStore::DataVaultSticky4( - ColdResetEntry4::try_from(self.reg_num() as u8) - .map_err(|_| CaliptraError::DRIVER_HANDOFF_INVALID_COLD_RESET_ENTRY4)?, - )), - - 2 => Ok(DataStore::DataVaultSticky48( - ColdResetEntry48::try_from(self.reg_num() as u8) - .map_err(|_| CaliptraError::DRIVER_HANDOFF_INVALID_COLD_RESET_ENTRY48)?, - )), - - 3 => Ok(DataStore::DataVaultNonSticky4( - WarmResetEntry4::try_from(self.reg_num() as u8) - .map_err(|_| CaliptraError::DRIVER_HANDOFF_INVALID_WARM_RESET_ENTRY4)?, - )), - - 4 => Ok(DataStore::DataVaultNonSticky48( - WarmResetEntry48::try_from(self.reg_num() as u8) - .map_err(|_| CaliptraError::DRIVER_HANDOFF_INVALID_WARM_RESET_ENTRY48)?, - )), - - _ => Err(CaliptraError::DRIVER_BAD_DATASTORE_REG_TYPE), - }, _ => Err(CaliptraError::DRIVER_BAD_DATASTORE_VAULT_TYPE), } } @@ -134,34 +104,6 @@ impl From for HandOffDataHandle { me.set_reg_num(key_id.into()); me } - DataStore::DataVaultSticky4(entry_id) => { - let mut me = Self(0); - me.set_vault(u32::from(Vault::DataVault)); - me.set_reg_type(DataVaultRegister::Sticky32BitReg as u32); - me.set_reg_num(entry_id.into()); - me - } - DataStore::DataVaultSticky48(entry_id) => { - let mut me = Self(0); - me.set_vault(Vault::DataVault as u32); - me.set_reg_type(DataVaultRegister::Sticky384BitReg as u32); - me.set_reg_num(entry_id.into()); - me - } - DataStore::DataVaultNonSticky4(entry_id) => { - let mut me = Self(0); - me.set_vault(Vault::DataVault as u32); - me.set_reg_type(DataVaultRegister::NonSticky32BitReg as u32); - me.set_reg_num(entry_id.into()); - me - } - DataStore::DataVaultNonSticky48(entry_id) => { - let mut me = Self(0); - me.set_vault(u32::from(Vault::DataVault)); - me.set_reg_type(DataVaultRegister::NonSticky384BitReg as u32); - me.set_reg_num(entry_id.into()); - me - } _ => { let mut me = Self(0); me.set_vault(0); @@ -173,6 +115,8 @@ impl From for HandOffDataHandle { } } +const FHT_RESERVED_SIZE: usize = 1680; + /// The Firmware Handoff Table is a data structure that is resident at a well-known /// location in DCCM. It is initially populated by ROM and modified by FMC as a way /// to pass parameters and configuration information from one firmware layer to the next. @@ -199,48 +143,18 @@ pub struct FirmwareHandoffTable { /// May be NULL if there is no discrete module. pub fips_fw_load_addr_hdl: HandOffDataHandle, - /// Entry point of Runtime FW Module in ICCM SRAM. - pub rt_fw_entry_point_hdl: HandOffDataHandle, - - /// Index of FMC TCI value in the Data Vault. - pub fmc_tci_dv_hdl: HandOffDataHandle, - /// Index of FMC CDI value in the Key Vault. Value of 0xFF indicates not present. pub fmc_cdi_kv_hdl: HandOffDataHandle, /// Index of FMC Private Alias Key in the Key Vault. pub fmc_priv_key_kv_hdl: HandOffDataHandle, - /// Index of FMC Public Alias Key X Coordinate in the Data Vault. - pub fmc_pub_key_x_dv_hdl: HandOffDataHandle, - - /// Index of FMC Public Alias Key Y Coordinate in the Data Vault. - pub fmc_pub_key_y_dv_hdl: HandOffDataHandle, - - /// Index of FMC Certificate Signature R Component in the Data Vault. - pub fmc_cert_sig_r_dv_hdl: HandOffDataHandle, - - /// Index of FMC Certificate Signature S Component in the Data Vault. - pub fmc_cert_sig_s_dv_hdl: HandOffDataHandle, - - /// Index of FMC SVN value in the Data Vault - pub fmc_svn_dv_hdl: HandOffDataHandle, - - /// Index of RT TCI value in the Data Vault. - pub rt_tci_dv_hdl: HandOffDataHandle, - /// Index of RT CDI value in the Key Vault. pub rt_cdi_kv_hdl: HandOffDataHandle, /// Index of RT Private Alias Key in the Key Vault. pub rt_priv_key_kv_hdl: HandOffDataHandle, - /// Index of RT SVN value in the Data Vault - pub rt_svn_dv_hdl: HandOffDataHandle, - - /// Index of RT Min SVN value in the Data Vault - pub rt_min_svn_dv_hdl: HandOffDataHandle, - /// LdevId TBS Address pub ldevid_tbs_addr: u32, @@ -274,12 +188,6 @@ pub struct FirmwareHandoffTable { /// RtAlias certificate signature. pub rt_dice_sign: Ecc384Signature, - /// Index of LdevId Certificate Signature R Component in the Data Vault. - pub ldevid_cert_sig_r_dv_hdl: HandOffDataHandle, - - /// Index of LdevId Certificate Signature S Component in the Data Vault. - pub ldevid_cert_sig_s_dv_hdl: HandOffDataHandle, - /// IDevID ECDSA public key pub idev_dice_ecdsa_pub_key: Ecc384PubKey, @@ -299,7 +207,7 @@ pub struct FirmwareHandoffTable { pub rt_hash_chain_kv_hdl: HandOffDataHandle, /// Reserved for future use. - pub reserved: [u8; 1632], + pub reserved: [u8; FHT_RESERVED_SIZE], } impl Default for FirmwareHandoffTable { @@ -310,20 +218,10 @@ impl Default for FirmwareHandoffTable { fht_minor_ver: 0, manifest_load_addr: FHT_INVALID_ADDRESS, fips_fw_load_addr_hdl: FHT_INVALID_HANDLE, - rt_fw_entry_point_hdl: FHT_INVALID_HANDLE, - fmc_tci_dv_hdl: FHT_INVALID_HANDLE, fmc_cdi_kv_hdl: FHT_INVALID_HANDLE, fmc_priv_key_kv_hdl: FHT_INVALID_HANDLE, - fmc_pub_key_x_dv_hdl: FHT_INVALID_HANDLE, - fmc_pub_key_y_dv_hdl: FHT_INVALID_HANDLE, - fmc_cert_sig_r_dv_hdl: FHT_INVALID_HANDLE, - fmc_cert_sig_s_dv_hdl: FHT_INVALID_HANDLE, - fmc_svn_dv_hdl: FHT_INVALID_HANDLE, - rt_tci_dv_hdl: FHT_INVALID_HANDLE, rt_cdi_kv_hdl: FHT_INVALID_HANDLE, rt_priv_key_kv_hdl: FHT_INVALID_HANDLE, - rt_svn_dv_hdl: FHT_INVALID_HANDLE, - rt_min_svn_dv_hdl: FHT_INVALID_HANDLE, ldevid_tbs_addr: 0, fmcalias_tbs_addr: 0, ldevid_tbs_size: 0, @@ -335,15 +233,13 @@ impl Default for FirmwareHandoffTable { fuse_log_addr: 0, rt_dice_pub_key: Ecc384PubKey::default(), rt_dice_sign: Ecc384Signature::default(), - ldevid_cert_sig_r_dv_hdl: FHT_INVALID_HANDLE, - ldevid_cert_sig_s_dv_hdl: FHT_INVALID_HANDLE, idev_dice_ecdsa_pub_key: Ecc384PubKey::default(), idev_dice_mldsa_pub_key_load_addr: 0, rom_info_addr: RomAddr::new(FHT_INVALID_ADDRESS), rtalias_tbs_size: 0, rt_hash_chain_max_svn: 0, rt_hash_chain_kv_hdl: HandOffDataHandle(0), - reserved: [0u8; 1632], + reserved: [0u8; FHT_RESERVED_SIZE], } } } @@ -360,41 +256,16 @@ pub fn print_fht(fht: &FirmwareHandoffTable) { "FIPS FW Load Address: 0x{:08x}", fht.fips_fw_load_addr_hdl.0 ); - crate::cprintln!( - "Runtime FW Entry Point: 0x{:08x}", - fht.rt_fw_entry_point_hdl.0 - ); - crate::cprintln!("FMC TCI DV Handle: 0x{:08x}", fht.fmc_tci_dv_hdl.0); crate::cprintln!("FMC CDI KV Handle: 0x{:08x}", fht.fmc_cdi_kv_hdl.0); crate::cprintln!( "FMC Private Key KV Handle: 0x{:08x}", fht.fmc_priv_key_kv_hdl.0 ); - crate::cprintln!( - "FMC Public Key X DV Handle: 0x{:08x}", - fht.fmc_pub_key_x_dv_hdl.0 - ); - crate::cprintln!( - "FMC Public Key Y DV Handle: 0x{:08x}", - fht.fmc_pub_key_y_dv_hdl.0 - ); - crate::cprintln!( - "FMC Certificate Signature R DV Handle: 0x{:08x}", - fht.fmc_cert_sig_r_dv_hdl.0 - ); - crate::cprintln!( - "FMC Certificate Signature S DV Handle: 0x{:08x}", - fht.fmc_cert_sig_s_dv_hdl.0 - ); - crate::cprintln!("FMC SVN DV Handle: 0x{:08x}", fht.fmc_svn_dv_hdl.0); - crate::cprintln!("RT TCI DV Handle: 0x{:08x}", fht.rt_tci_dv_hdl.0); crate::cprintln!("RT CDI KV Handle: 0x{:08x}", fht.rt_cdi_kv_hdl.0); crate::cprintln!( "RT Private Key KV Handle: 0x{:08x}", fht.rt_priv_key_kv_hdl.0 ); - crate::cprintln!("RT SVN DV Handle: 0x{:08x}", fht.rt_svn_dv_hdl.0); - crate::cprintln!("RT Min SVN DV Handle: 0x{:08x}", fht.rt_min_svn_dv_hdl.0); crate::cprintln!( "IdevId MLDSA Public Key Address: 0x{:08x}", @@ -402,14 +273,6 @@ pub fn print_fht(fht: &FirmwareHandoffTable) { ); crate::cprintln!("LdevId TBS Address: 0x{:08x}", fht.ldevid_tbs_addr); crate::cprintln!("LdevId TBS Size: {} bytes", fht.ldevid_tbs_size); - crate::cprintln!( - "LDevId Certificate Signature R DV Handle: 0x{:08x}", - fht.ldevid_cert_sig_r_dv_hdl.0 - ); - crate::cprintln!( - "LDevId Certificate Signature S DV Handle: 0x{:08x}", - fht.ldevid_cert_sig_s_dv_hdl.0 - ); crate::cprintln!("FmcAlias TBS Address: 0x{:08x}", fht.fmcalias_tbs_addr); crate::cprintln!("FmcAlias TBS Size: {} bytes", fht.fmcalias_tbs_size); crate::cprintln!("RtAlias TBS Size: {} bytes", fht.rtalias_tbs_size); @@ -432,12 +295,6 @@ impl FirmwareHandoffTable { let mut valid = self.fht_marker == FHT_MARKER && self.fmc_cdi_kv_hdl != FHT_INVALID_HANDLE && self.manifest_load_addr != FHT_INVALID_ADDRESS - && self.fmc_pub_key_x_dv_hdl != FHT_INVALID_HANDLE - && self.fmc_pub_key_y_dv_hdl != FHT_INVALID_HANDLE - && self.fmc_cert_sig_r_dv_hdl != FHT_INVALID_HANDLE - && self.fmc_cert_sig_s_dv_hdl != FHT_INVALID_HANDLE - && self.rt_tci_dv_hdl != FHT_INVALID_HANDLE - && self.rt_fw_entry_point_hdl != FHT_INVALID_HANDLE // This is for Gen1 POR. && self.fips_fw_load_addr_hdl == FHT_INVALID_HANDLE && self.ldevid_tbs_addr != 0 @@ -445,9 +302,7 @@ impl FirmwareHandoffTable { && self.pcr_log_addr != 0 && self.meas_log_addr != 0 && self.fuse_log_addr != 0 - && self.rom_info_addr.is_valid() - && self.ldevid_cert_sig_r_dv_hdl != FHT_INVALID_HANDLE - && self.ldevid_cert_sig_s_dv_hdl != FHT_INVALID_HANDLE; + && self.rom_info_addr.is_valid(); if valid && reset_reason == ResetReason::ColdReset @@ -467,10 +322,6 @@ mod tests { const FHT_SIZE: usize = 2048; const KEY_ID_FMC_ECDSA_PRIV_KEY: KeyId = KeyId::KeyId7; - fn rt_tci_store() -> HandOffDataHandle { - HandOffDataHandle::from(DataStore::DataVaultNonSticky48(WarmResetEntry48::RtTci)) - } - fn fmc_priv_key_store() -> HandOffDataHandle { HandOffDataHandle(((Vault::KeyVault as u32) << 12) | KEY_ID_FMC_ECDSA_PRIV_KEY as u32) } @@ -491,12 +342,6 @@ mod tests { let valid = fht.fht_marker == FHT_MARKER && fht.fmc_cdi_kv_hdl != FHT_INVALID_HANDLE && fht.manifest_load_addr != FHT_INVALID_ADDRESS - && fht.fmc_pub_key_x_dv_hdl != FHT_INVALID_HANDLE - && fht.fmc_pub_key_y_dv_hdl != FHT_INVALID_HANDLE - && fht.fmc_cert_sig_r_dv_hdl != FHT_INVALID_HANDLE - && fht.fmc_cert_sig_s_dv_hdl != FHT_INVALID_HANDLE - && fht.rt_tci_dv_hdl != FHT_INVALID_HANDLE - && fht.rt_fw_entry_point_hdl != FHT_INVALID_HANDLE // This is for Gen1 POR. && fht.fips_fw_load_addr_hdl == FHT_INVALID_HANDLE && fht.ldevid_tbs_size == 0 @@ -512,19 +357,6 @@ mod tests { assert_eq!(FHT_SIZE, mem::size_of::()); } - #[test] - fn test_dv_nonsticky_384bit_set() { - let fht = crate::hand_off::FirmwareHandoffTable { - rt_tci_dv_hdl: rt_tci_store(), - ..Default::default() - }; - assert_eq!(fht.rt_tci_dv_hdl.vault(), Vault::DataVault as u32); - assert_eq!( - fht.rt_tci_dv_hdl.reg_type(), - DataVaultRegister::NonSticky384BitReg as u32 - ); - } - #[test] fn test_fmc_priv_key_store() { let fht = crate::hand_off::FirmwareHandoffTable { diff --git a/drivers/src/lib.rs b/drivers/src/lib.rs index f83ca623ab..b3c6d8b6c9 100644 --- a/drivers/src/lib.rs +++ b/drivers/src/lib.rs @@ -59,9 +59,7 @@ pub use array_concat::array_concat3; pub use bounded_address::{BoundedAddr, MemBounds, RomAddr}; pub use caliptra_error::{CaliptraError, CaliptraResult}; pub use csrng::{Csrng, HealthFailCounts as CsrngHealthFailCounts, Seed as CsrngSeed}; -pub use data_vault::{ - ColdResetEntry4, ColdResetEntry48, DataVault, WarmResetEntry4, WarmResetEntry48, -}; +pub use data_vault::{ColdResetEntries, DataVault, WarmResetEntries}; pub use dma::{Dma, DmaReadTarget, DmaReadTransaction, DmaWriteOrigin, DmaWriteTransaction}; pub use doe::DeobfuscationEngine; pub use ecc384::{ diff --git a/drivers/src/memory_layout.rs b/drivers/src/memory_layout.rs index 70b9b9774a..d951d48cd2 100644 --- a/drivers/src/memory_layout.rs +++ b/drivers/src/memory_layout.rs @@ -33,7 +33,8 @@ pub const CFI_STATE_ORG: u32 = 0x500003E4; // size = 6 words pub const BOOT_STATUS_ORG: u32 = 0x500003FC; pub const MAN1_ORG: u32 = 0x50000400; pub const MAN2_ORG: u32 = MAN1_ORG + MAN1_SIZE; -pub const FHT_ORG: u32 = MAN2_ORG + MAN2_SIZE; +pub const DATAVAULT_ORG: u32 = MAN2_ORG + MAN2_SIZE; +pub const FHT_ORG: u32 = DATAVAULT_ORG + DATAVAULT_MAX_SIZE; pub const IDEVID_MLDSA_PUB_KEY_ORG: u32 = FHT_ORG + FHT_SIZE; pub const LDEVID_TBS_ORG: u32 = IDEVID_MLDSA_PUB_KEY_ORG + IDEVID_MLDSA_PUB_KEY_MAX_SIZE; pub const FMCALIAS_TBS_ORG: u32 = LDEVID_TBS_ORG + LDEVID_TBS_SIZE; @@ -67,6 +68,7 @@ pub const DCCM_SIZE: u32 = 256 * 1024; pub const ROM_DATA_SIZE: u32 = 996; pub const MAN1_SIZE: u32 = 17 * 1024; pub const MAN2_SIZE: u32 = 17 * 1024; +pub const DATAVAULT_MAX_SIZE: u32 = 15 * 1024; pub const FHT_SIZE: u32 = 2 * 1024; pub const IDEVID_MLDSA_PUB_KEY_MAX_SIZE: u32 = 3 * 1024; pub const LDEVID_TBS_SIZE: u32 = 1024; @@ -79,7 +81,7 @@ pub const DPE_SIZE: u32 = 5 * 1024; pub const PCR_RESET_COUNTER_SIZE: u32 = 1024; pub const AUTH_MAN_IMAGE_METADATA_MAX_SIZE: u32 = 7 * 1024; pub const IDEVID_CSR_SIZE: u32 = 1024; -pub const DATA_SIZE: u32 = 130 * 1024; +pub const DATA_SIZE: u32 = 115 * 1024; pub const STACK_SIZE: u32 = 64 * 1024; pub const ROM_STACK_SIZE: u32 = 40 * 1024; pub const ESTACK_SIZE: u32 = 1024; @@ -99,7 +101,13 @@ fn mem_layout_test_manifest() { assert!(MAN2_SIZE as usize >= core::mem::size_of::()); assert_eq!(MAN1_SIZE, MAN2_SIZE); assert_eq!((MAN2_ORG - MAN1_ORG), MAN1_SIZE); - assert_eq!((FHT_ORG - MAN2_ORG), MAN2_SIZE); + assert_eq!((DATAVAULT_ORG - MAN2_ORG), MAN2_SIZE); +} + +#[test] +#[allow(clippy::assertions_on_constants)] +fn mem_layout_test_datavault() { + assert_eq!((FHT_ORG - DATAVAULT_ORG), DATAVAULT_MAX_SIZE); } #[test] diff --git a/drivers/src/persistent.rs b/drivers/src/persistent.rs index 5824b56154..2d0328c677 100644 --- a/drivers/src/persistent.rs +++ b/drivers/src/persistent.rs @@ -18,7 +18,7 @@ use crate::{ fuse_log::FuseLogEntry, memory_layout, pcr_log::{MeasurementLogEntry, PcrLogEntry}, - FirmwareHandoffTable, Mldsa87PubKey, + DataVault, FirmwareHandoffTable, Mldsa87PubKey, }; #[cfg(feature = "runtime")] @@ -113,6 +113,9 @@ pub struct PersistentData { pub manifest2: ImageManifest, reserved1: [u8; memory_layout::MAN2_SIZE as usize - size_of::()], + pub data_vault: DataVault, + reserved1_1: [u8; memory_layout::DATAVAULT_MAX_SIZE as usize - size_of::()], + pub fht: FirmwareHandoffTable, reserved2: [u8; memory_layout::FHT_SIZE as usize - size_of::()], @@ -177,6 +180,7 @@ impl PersistentData { unsafe { assert_eq!(addr_of!((*P).manifest1) as u32, layout::MAN1_ORG); assert_eq!(addr_of!((*P).manifest2) as u32, layout::MAN2_ORG); + assert_eq!(addr_of!((*P).data_vault) as u32, layout::DATAVAULT_ORG); assert_eq!(addr_of!((*P).fht) as u32, layout::FHT_ORG); assert_eq!( addr_of!((*P).idevid_mldsa_pub_key) as u32, diff --git a/fmc/README.md b/fmc/README.md index ece00369f9..1b98c1fd17 100644 --- a/fmc/README.md +++ b/fmc/README.md @@ -103,8 +103,6 @@ fields may not be changed or removed). Table revisions with different Major Vers | fht_minor_ver | 2 | ROM, FMC | Minor version of FHT. Initially written by ROM but may be changed to a higher version by FMC. | | manifest_load_addr | 4 | ROM | Physical base address of Manifest in DCCM SRAM. | | fips_fw_load_addr_hdl | 4 | ROM | Handle of base address of FIPS Module in ROM or ICCM SRAM. May be 0xFF if there is no discrete module. | -| rt_fw_entry_point_hdl | 4 | ROM | Handle of entry point of Runtime FW Module value in DCCM datavault. SRAM. | -| fmc_tci_dv_hdl | 4 | ROM | Handle of FMC TCI value in the DCCM datavault. | | fmc_cdi_kv_hdl | 4 | ROM | Handle of FMC CDI value in the Key Vault. Value of 0xFF indicates not present. | | fmc_priv_key_ecdsa_kv_hdl | 4 | ROM | Handle of FMC Alias ECDSA Private Key in the Key Vault. | | fmc_keypair_seed_mldsa_kv_hdl | 4 | ROM | Handle of FMC Alias MLDSA Key Pair Generation Seed in the Key Vault. | @@ -114,13 +112,9 @@ fields may not be changed or removed). Table revisions with different Major Vers | fmc_cert_sig_ecdsa_r_dv_hdl | 4 | ROM | Handle of FMC Certificate ECDSA Signature R Component in the DCCM datavault. | | fmc_cert_sig_ecdsa_s_dv_hdl | 4 | ROM | Handle of FMC Certificate ECDSA Signature S Component in the DCCM datavault. | | fmc_cert_sig_mldsa_dv_hdl | 4 | ROM | Handle of FMC Certificate MLDSA Signature in the DCCM datavault. | -| fmc_svn_dv_hdl | 4 | ROM | Handle of FMC SVN value in the DCCM datavault. | -| rt_tci_dv_hdl | 4 | ROM | Handle of RT TCI value in the DCCM datavault. | | rt_cdi_kv_hdl | 4 | FMC | Handle of RT CDI value in the Key Vault. | | rt_priv_key_ecdsa_kv_hdl | 4 | FMC | Handle of RT Alias ECDSA Private Key in the Key Vault. | | rt_keygen_seed_mldsa_kv_hdl | 4 | FMC | Handle of RT Alias MLDSA Key Generation Seed in the Key Vault. | -| rt_svn_dv_hdl | 4 | FMC | Handle of RT SVN value in the DCCM datavault. | -| rt_min_svn_dv_hdl | 4 | FMC | Handle of Min RT SVN value in the DCCM datavault. | | ldevid_tbs_ecdsa_addr | 4 | ROM | Local Device ID ECDSA TBS Address. | | fmcalias_tbs_ecdsa_addr | 4 | ROM | FMC Alias TBS ECDSA Address. | | ldevid_tbs_mldsa_addr | 4 | ROM | Local Device ID MLDSA TBS Address. | @@ -176,14 +170,6 @@ is able to re-run firmware integrity checks on-demand (required by FIPS 140-3). discrete FIPS module does not exist, then this field shall be 0xFF and ROM, FMC, and RT FW must all carry their own code for accessing crypto resources and keys. -### rt_fw_entry_point_hdl - -This field provides the Handle of the DV entry that stores the physical address of the Entry Point of Runtime FW Module in ICCM SRAM. - -### fmc_tci_dv_hdl - -This field provides the Handle into the DCCM datavault where the TCIFMC is stored. TCIFMC is a SHA-384 Hash of the FMC Module. - ### fmc_cdi_kv_hdl This field provides the Handle into the Key Vault where the CDIFMC is stored. @@ -212,14 +198,6 @@ These fields provide the Handle into the DCCM datavault where the ECDSA Signatur This field provides the Handle into the DCCM datavault where the MLDSA SignatureFMC is stored. -### fmc_svn_dv_hdl - -This field provides the Handle into the DCCM datavault where the SVNFMC is stored. - -### rt_tci_dv_hdl - -This field provides the Handle into the DCCM datavault where the TCIRT is stored. TCIRT is a SHA-384 Hash of the RT FW Module. - ### rt_cdi_kv_hdl This field provides the Handle into the Key Vault where the CDIRT is stored. @@ -232,14 +210,6 @@ This field provides the Handle into the Key Vault where the ECDSA PrivateKeyRT is stored. -### rt_svn_dv_hdl - -This field provides the Handle into the DCCM datavault where the SVNRT is stored. - -### rt_min_svn_dv_hdl - -This field provides the Handle into the DCCM datavault where the Min-SVNRT is stored. Upon cold-boot this is set to SVNRT. On subsequent boots this is set to MIN(SVNRT, Min-SVNRT). - ### ldevid_tbs_ecdsa_addr This field provides the address of the *To Be Signed* portion of the LDevID ECDSA certificate. @@ -436,7 +406,7 @@ sequenceDiagram FMC->>+FIPS: InitFipsFw() (if needed) FIPS-->>-FMC: return() FMC->>FMC: LocateManifest(fht) - FMC->>FMC: GetRtMeasurement(fht.rt_tci_dv_hdl) + FMC->>FMC: GetRtMeasurement(data_vault.rt_tci) rect rgba(0, 100, 200, .2) diff --git a/fmc/src/fmc_env.rs b/fmc/src/fmc_env.rs index 4dae5e97fc..8f94f5cd06 100644 --- a/fmc/src/fmc_env.rs +++ b/fmc/src/fmc_env.rs @@ -16,11 +16,11 @@ Abstract: --*/ use caliptra_drivers::{ - CaliptraResult, DataVault, Ecc384, Hmac, KeyVault, Mailbox, PcrBank, PersistentDataAccessor, - Sha1, Sha256, Sha2_512_384, Sha2_512_384Acc, SocIfc, Trng, + CaliptraResult, Ecc384, Hmac, KeyVault, Mailbox, PcrBank, PersistentDataAccessor, Sha1, Sha256, + Sha2_512_384, Sha2_512_384Acc, SocIfc, Trng, }; use caliptra_registers::{ - csrng::CsrngReg, dv::DvReg, ecc::EccReg, entropy_src::EntropySrcReg, hmac::HmacReg, kv::KvReg, + csrng::CsrngReg, ecc::EccReg, entropy_src::EntropySrcReg, hmac::HmacReg, kv::KvReg, mbox::MboxCsr, pv::PvReg, sha256::Sha256Reg, sha512::Sha512Reg, sha512_acc::Sha512AccCsr, soc_ifc::SocIfcReg, soc_ifc_trng::SocIfcTrngReg, }; @@ -48,9 +48,6 @@ pub struct FmcEnv { /// Key Vault pub key_vault: KeyVault, - /// Data Vault - pub data_vault: DataVault, - /// Device state pub soc_ifc: SocIfc, @@ -91,7 +88,6 @@ impl FmcEnv { hmac384: Hmac::new(HmacReg::new()), ecc384: Ecc384::new(EccReg::new()), key_vault: KeyVault::new(KvReg::new()), - data_vault: DataVault::new(DvReg::new()), soc_ifc: SocIfc::new(SocIfcReg::new()), mbox: Mailbox::new(MboxCsr::new()), pcr_bank: PcrBank::new(PvReg::new()), diff --git a/fmc/src/hand_off.rs b/fmc/src/hand_off.rs index 5e1e77e6ca..8e56298805 100644 --- a/fmc/src/hand_off.rs +++ b/fmc/src/hand_off.rs @@ -16,8 +16,8 @@ use crate::fmc_env::FmcEnv; use caliptra_cfi_derive::cfi_impl_fn; use caliptra_common::{handle_fatal_error, DataStore::*}; use caliptra_common::{DataStore, FirmwareHandoffTable, HandOffDataHandle, Vault}; +use caliptra_drivers::Ecc384PubKey; use caliptra_drivers::{cprintln, memory_layout, Array4x12, Ecc384Signature, KeyId}; -use caliptra_drivers::{Ecc384PubKey, Ecc384Scalar}; use caliptra_error::{CaliptraError, CaliptraResult}; #[cfg(feature = "riscv")] @@ -66,52 +66,13 @@ impl HandOff { } } - fn fmc_pub_key_x(env: &FmcEnv) -> Ecc384Scalar { - let ds: DataStore = Self::fht(env) - .fmc_pub_key_x_dv_hdl - .try_into() - .unwrap_or_else(|e: CaliptraError| { - cprintln!("[fht] Invalid FMC ALias Public Key X DV handle"); - handle_fatal_error(e.into()); - }); - - // The data store is either a warm reset entry or a cold reset entry. - match ds { - DataVaultNonSticky48(dv_entry) => env.data_vault.read_warm_reset_entry48(dv_entry), - DataVaultSticky48(dv_entry) => env.data_vault.read_cold_reset_entry48(dv_entry), - _ => handle_fatal_error(CaliptraError::FMC_HANDOFF_INVALID_PARAM.into()), - } - } - - fn fmc_pub_key_y(env: &FmcEnv) -> Ecc384Scalar { - let ds: DataStore = Self::fht(env) - .fmc_pub_key_y_dv_hdl - .try_into() - .unwrap_or_else(|e: CaliptraError| { - cprintln!("[fht] Invalid FMC ALias Public Key Y DV handle"); - handle_fatal_error(e.into()); - }); - - // The data store is either a warm reset entry or a cold reset entry. - match ds { - DataVaultNonSticky48(dv_entry) => env.data_vault.read_warm_reset_entry48(dv_entry), - DataVaultSticky48(dv_entry) => env.data_vault.read_cold_reset_entry48(dv_entry), - _ => { - handle_fatal_error(CaliptraError::FMC_HANDOFF_INVALID_PARAM.into()); - } - } - } - - /// Get the fmc public key. + /// Get the fmc ECC public key. /// /// # Returns /// * fmc public key /// pub fn fmc_pub_key(env: &FmcEnv) -> Ecc384PubKey { - Ecc384PubKey { - x: Self::fmc_pub_key_x(env), - y: Self::fmc_pub_key_y(env), - } + env.persistent_data.get().data_vault.fmc_ecc_pub_key() } /// Retrieve FMC Alias Private Key @@ -156,44 +117,12 @@ impl HandOff { /// Retrieve runtime TCI (digest) pub fn rt_tci(env: &FmcEnv) -> Array4x12 { - let ds: DataStore = - Self::fht(env) - .rt_tci_dv_hdl - .try_into() - .unwrap_or_else(|e: CaliptraError| { - cprintln!("[fht] Invalid TCI DV handle"); - handle_fatal_error(e.into()) - }); - - // The data store is either a warm reset entry or a cold reset entry. - match ds { - DataVaultNonSticky48(dv_entry) => env.data_vault.read_warm_reset_entry48(dv_entry), - DataVaultSticky48(dv_entry) => env.data_vault.read_cold_reset_entry48(dv_entry), - _ => { - handle_fatal_error(CaliptraError::FMC_HANDOFF_INVALID_PARAM.into()); - } - } + env.persistent_data.get().data_vault.rt_tci() } /// Retrieve runtime SVN. pub fn rt_svn(env: &FmcEnv) -> u32 { - let ds: DataStore = - Self::fht(env) - .rt_svn_dv_hdl - .try_into() - .unwrap_or_else(|e: CaliptraError| { - cprintln!("[fht] Invalid RT SVN handle"); - handle_fatal_error(e.into()) - }); - - // The data store is either a warm reset entry or a cold reset entry. - match ds { - DataVaultNonSticky4(dv_entry) => env.data_vault.read_warm_reset_entry4(dv_entry), - DataVaultSticky4(dv_entry) => env.data_vault.read_cold_reset_entry4(dv_entry), - _ => { - handle_fatal_error(CaliptraError::FMC_HANDOFF_INVALID_PARAM.into()); - } - } + env.persistent_data.get().data_vault.rt_svn() } /// Store runtime Dice Signature @@ -209,21 +138,7 @@ impl HandOff { /// Retrieve the entry point of the runtime firmware. fn rt_entry_point(env: &FmcEnv) -> u32 { - let ds: DataStore = Self::fht(env) - .rt_fw_entry_point_hdl - .try_into() - .unwrap_or_else(|e: CaliptraError| { - cprintln!("[fht] Invalid runtime entry point DV handle"); - handle_fatal_error(e.into()); - }); - // The data store is either a warm reset entry or a cold reset entry. - match ds { - DataVaultNonSticky4(dv_entry) => env.data_vault.read_warm_reset_entry4(dv_entry), - DataVaultSticky4(dv_entry) => env.data_vault.read_cold_reset_entry4(dv_entry), - _ => { - handle_fatal_error(CaliptraError::FMC_HANDOFF_INVALID_PARAM.into()); - } - } + env.persistent_data.get().data_vault.rt_entry_point() } /// The FMC CDI is stored in a 32-bit DataVault sticky register. diff --git a/rom/dev/README.md b/rom/dev/README.md index 7e5b85de1a..c201a77218 100644 --- a/rom/dev/README.md +++ b/rom/dev/README.md @@ -694,10 +694,10 @@ Alias FMC Layer includes the measurement of the FMC and other security states. T CPTRA_SECURITY_STATE.LIFECYCLE_STATE, CPTRA_SECURITY_STATE.DEBUG_ENABLED, FUSE_ANTI_ROLLBACK_DISABLE, - ECC_VENDOR_PK_INDEX, + VENDOR_ECC_PK_INDEX, FW_SVN, FW_FUSE_SVN (or 0 if `FUSE_ANTI_ROLLBACK_DISABLE`), - PQC_VENDOR_PK_INDEX, + VENDOR_PQC_PK_INDEX, ROM_VERIFY_CONFIG, OWNER_PK_HASH_FROM_FUSES (0 or 1), ]) diff --git a/rom/dev/src/crypto.rs b/rom/dev/src/crypto.rs index cd7f0141f4..13a721e037 100644 --- a/rom/dev/src/crypto.rs +++ b/rom/dev/src/crypto.rs @@ -87,15 +87,15 @@ impl Crypto { /// /// # Arguments /// - /// * `env` - ROM Environment - /// * `data` - Input data to hash + /// * `sha256` - SHA256 driver + /// * `data` - Input data to hash /// /// # Returns /// /// * `Array4x8` - Digest #[cfg_attr(not(feature = "no-cfi"), cfi_impl_fn)] - pub fn sha256_digest(env: &mut RomEnv, data: &[u8]) -> CaliptraResult { - env.sha256.digest(data) + pub fn sha256_digest(sha256: &mut Sha256, data: &[u8]) -> CaliptraResult { + sha256.digest(data) } /// Calculate SHA2-384 Digest diff --git a/rom/dev/src/fht.rs b/rom/dev/src/fht.rs index 6ee377e3d1..4d396ebb65 100644 --- a/rom/dev/src/fht.rs +++ b/rom/dev/src/fht.rs @@ -17,12 +17,9 @@ use crate::{rom_env::RomEnv, CALIPTRA_ROM_INFO}; use caliptra_cfi_derive::cfi_mod_fn; use caliptra_common::{ keyids::{KEY_ID_FMC_ECDSA_PRIV_KEY, KEY_ID_ROM_FMC_CDI}, - DataVaultRegister, FirmwareHandoffTable, HandOffDataHandle, Vault, FHT_INVALID_HANDLE, - FHT_MARKER, -}; -use caliptra_drivers::{ - cprintln, ColdResetEntry4, ColdResetEntry48, RomAddr, WarmResetEntry4, WarmResetEntry48, + FirmwareHandoffTable, HandOffDataHandle, Vault, FHT_INVALID_HANDLE, FHT_MARKER, }; +use caliptra_drivers::{cprintln, RomAddr}; const FHT_MAJOR_VERSION: u16 = 1; const FHT_MINOR_VERSION: u16 = 0; @@ -31,121 +28,14 @@ const FHT_MINOR_VERSION: u16 = 0; pub struct FhtDataStore {} impl FhtDataStore { - /// The FMC CDI is stored in a 32-bit DataVault sticky register. + /// The FMC CDI is stored in a Key Vault slot. pub const fn fmc_cdi_store() -> HandOffDataHandle { HandOffDataHandle(((Vault::KeyVault as u32) << 12) | KEY_ID_ROM_FMC_CDI as u32) } - /// The FMC private key is stored in a 32-bit DataVault sticky register. + /// The FMC private key is stored in a Key Vault slot. pub const fn fmc_priv_key_store() -> HandOffDataHandle { HandOffDataHandle(((Vault::KeyVault as u32) << 12) | KEY_ID_FMC_ECDSA_PRIV_KEY as u32) } - /// The FMC SVN is stored in a 32-bit DataVault sticky register. - pub const fn fmc_svn_store() -> HandOffDataHandle { - HandOffDataHandle( - ((Vault::DataVault as u32) << 12) - | (DataVaultRegister::Sticky32BitReg as u32) << 8 - | ColdResetEntry4::FmcSvn as u32, - ) - } - /// The FMC TCI is stored in a 384-bit DataVault sticky register. - pub const fn fmc_tci_store() -> HandOffDataHandle { - HandOffDataHandle( - ((Vault::DataVault as u32) << 12) - | (DataVaultRegister::Sticky384BitReg as u32) << 8 - | ColdResetEntry48::FmcTci as u32, - ) - } - - /// The FMC certificate signature R value is stored in a 384-bit DataVault - /// sticky register. - pub const fn fmc_cert_sig_r_store() -> HandOffDataHandle { - HandOffDataHandle( - ((Vault::DataVault as u32) << 12) - | (DataVaultRegister::Sticky384BitReg as u32) << 8 - | ColdResetEntry48::FmcDiceSigR as u32, - ) - } - - /// The FMC certificate signature S value is stored in a 384-bit DataVault - /// sticky register. - pub const fn fmc_cert_sig_s_store() -> HandOffDataHandle { - HandOffDataHandle( - ((Vault::DataVault as u32) << 12) - | (DataVaultRegister::Sticky384BitReg as u32) << 8 - | ColdResetEntry48::FmcDiceSigS as u32, - ) - } - /// The FMC public key X coordinate is stored in a 384-bit DataVault - /// sticky register. - pub const fn fmc_pub_key_x_store() -> HandOffDataHandle { - HandOffDataHandle( - (Vault::DataVault as u32) << 12 - | (DataVaultRegister::Sticky384BitReg as u32) << 8 - | ColdResetEntry48::FmcPubKeyX as u32, - ) - } - /// FMC public key Y coordinate is stored in a 384-bit DataVault - /// sticky register. - pub const fn fmc_pub_key_y_store() -> HandOffDataHandle { - HandOffDataHandle( - (Vault::DataVault as u32) << 12 - | (DataVaultRegister::Sticky384BitReg as u32) << 8 - | ColdResetEntry48::FmcPubKeyY as u32, - ) - } - /// The RT SVN is stored in a 32-bit DataVault non-sticky register. - pub const fn rt_svn_data_store() -> HandOffDataHandle { - HandOffDataHandle( - ((Vault::DataVault as u32) << 12) - | (DataVaultRegister::NonSticky32BitReg as u32) << 8 - | WarmResetEntry4::RtSvn as u32, - ) - } - /// The RT Min SVN is stored in a 32-bit DataVault non-sticky register. - pub const fn rt_min_svn_data_store() -> HandOffDataHandle { - HandOffDataHandle( - ((Vault::DataVault as u32) << 12) - | (DataVaultRegister::NonSticky32BitReg as u32) << 8 - | WarmResetEntry4::RtMinSvn as u32, - ) - } - /// The RT TCI is stored in a 384-bit DataVault non-sticky register. - pub const fn rt_tci_data_store() -> HandOffDataHandle { - HandOffDataHandle( - ((Vault::DataVault as u32) << 12) - | (DataVaultRegister::NonSticky384BitReg as u32) << 8 - | WarmResetEntry48::RtTci as u32, - ) - } - /// The runtime firmware entry point is stored in a 32-bit DataVault - /// non-sticky register. - pub const fn rt_fw_entry_point() -> HandOffDataHandle { - HandOffDataHandle( - ((Vault::DataVault as u32) << 12) - | (DataVaultRegister::NonSticky32BitReg as u32) << 8 - | WarmResetEntry4::RtEntryPoint as u32, - ) - } - - /// The LDevId certificate signature R value is stored in a 384-bit DataVault - /// sticky register. - pub const fn ldevid_cert_sig_r_store() -> HandOffDataHandle { - HandOffDataHandle( - ((Vault::DataVault as u32) << 12) - | (DataVaultRegister::Sticky384BitReg as u32) << 8 - | ColdResetEntry48::LDevDiceSigR as u32, - ) - } - - /// The LDevId certificate signature S value is stored in a 384-bit DataVault - /// sticky register. - pub const fn ldevid_cert_sig_s_store() -> HandOffDataHandle { - HandOffDataHandle( - ((Vault::DataVault as u32) << 12) - | (DataVaultRegister::Sticky384BitReg as u32) << 8 - | ColdResetEntry48::LDevDiceSigS as u32, - ) - } } #[cfg_attr(not(feature = "no-cfi"), cfi_mod_fn)] @@ -159,22 +49,10 @@ pub fn initialize_fht(env: &mut RomEnv) { fht_major_ver: FHT_MAJOR_VERSION, fht_minor_ver: FHT_MINOR_VERSION, fips_fw_load_addr_hdl: FHT_INVALID_HANDLE, - rt_fw_entry_point_hdl: FhtDataStore::rt_fw_entry_point(), fmc_cdi_kv_hdl: FhtDataStore::fmc_cdi_store(), fmc_priv_key_kv_hdl: FhtDataStore::fmc_priv_key_store(), - fmc_pub_key_x_dv_hdl: FhtDataStore::fmc_pub_key_x_store(), - fmc_pub_key_y_dv_hdl: FhtDataStore::fmc_pub_key_y_store(), - fmc_cert_sig_r_dv_hdl: FhtDataStore::fmc_cert_sig_r_store(), - fmc_cert_sig_s_dv_hdl: FhtDataStore::fmc_cert_sig_s_store(), - fmc_tci_dv_hdl: FhtDataStore::fmc_tci_store(), - fmc_svn_dv_hdl: FhtDataStore::fmc_svn_store(), rt_cdi_kv_hdl: FHT_INVALID_HANDLE, rt_priv_key_kv_hdl: FHT_INVALID_HANDLE, - rt_tci_dv_hdl: FhtDataStore::rt_tci_data_store(), - rt_svn_dv_hdl: FhtDataStore::rt_svn_data_store(), - rt_min_svn_dv_hdl: FhtDataStore::rt_min_svn_data_store(), - ldevid_cert_sig_r_dv_hdl: FhtDataStore::ldevid_cert_sig_r_store(), - ldevid_cert_sig_s_dv_hdl: FhtDataStore::ldevid_cert_sig_s_store(), rom_info_addr: RomAddr::from(unsafe { &CALIPTRA_ROM_INFO }), manifest_load_addr: &pdata.manifest1 as *const _ as u32, ldevid_tbs_addr: &pdata.ldevid_tbs as *const _ as u32, diff --git a/rom/dev/src/flow/cold_reset/fmc_alias.rs b/rom/dev/src/flow/cold_reset/fmc_alias.rs index f93fc3c0ce..a076e0c211 100644 --- a/rom/dev/src/flow/cold_reset/fmc_alias.rs +++ b/rom/dev/src/flow/cold_reset/fmc_alias.rs @@ -195,39 +195,41 @@ impl FmcAliasLayer { let auth_priv_key = input.ecc_auth_key_pair.priv_key; let auth_pub_key = &input.ecc_auth_key_pair.pub_key; let pub_key = &output.ecc_subj_key_pair.pub_key; + let data_vault = &env.persistent_data.get().data_vault; + let soc_ifc = &env.soc_ifc; let flags = Self::make_flags(env.soc_ifc.lifecycle(), env.soc_ifc.debug_locked()); - let svn = env.data_vault.fmc_svn() as u8; + let svn = data_vault.fmc_svn() as u8; let fuse_svn = fw_proc_info.effective_fuse_svn as u8; let mut fuse_info_digest = Array4x12::default(); let mut hasher = env.sha2_512_384.sha384_digest_init()?; hasher.update(&[ - env.soc_ifc.lifecycle() as u8, - env.soc_ifc.debug_locked() as u8, - env.soc_ifc.fuse_bank().anti_rollback_disable() as u8, - env.data_vault.ecc_vendor_pk_index() as u8, - env.data_vault.pqc_vendor_pk_index() as u8, + soc_ifc.lifecycle() as u8, + soc_ifc.debug_locked() as u8, + soc_ifc.fuse_bank().anti_rollback_disable() as u8, + data_vault.vendor_ecc_pk_index() as u8, + data_vault.vendor_pqc_pk_index() as u8, fw_proc_info.pqc_verify_config, fw_proc_info.owner_pub_keys_digest_in_fuses as u8, ])?; hasher.update(&<[u8; 48]>::from( - env.soc_ifc.fuse_bank().vendor_pub_key_info_hash(), + soc_ifc.fuse_bank().vendor_pub_key_info_hash(), ))?; - hasher.update(&<[u8; 48]>::from(env.data_vault.owner_pk_hash()))?; + hasher.update(&<[u8; 48]>::from(data_vault.owner_pk_hash()))?; hasher.finalize(&mut fuse_info_digest)?; // Certificate `To Be Signed` Parameters let params = FmcAliasCertTbsParams { - ueid: &X509::ueid(env)?, + ueid: &X509::ueid(soc_ifc)?, subject_sn: &output.ecc_subj_sn, subject_key_id: &output.ecc_subj_key_id, issuer_sn: input.ecc_auth_sn, authority_key_id: input.ecc_auth_key_id, - serial_number: &X509::ecc_cert_sn(env, pub_key)?, + serial_number: &X509::ecc_cert_sn(&mut env.sha256, pub_key)?, public_key: &pub_key.to_der(), - tcb_info_fmc_tci: &(&env.data_vault.fmc_tci()).into(), + tcb_info_fmc_tci: &(&data_vault.fmc_tci()).into(), tcb_info_device_info_hash: &fuse_info_digest.into(), tcb_info_flags: &flags, tcb_info_fmc_svn: &svn.to_be_bytes(), @@ -264,12 +266,13 @@ impl FmcAliasLayer { cprintln!("[afmc] SIG.R = {}", HexBytes(&_sig_r)); cprintln!("[afmc] SIG.S = {}", HexBytes(&_sig_s)); - // Lock the FMC Certificate Signature in data vault until next boot - env.data_vault.set_fmc_dice_signature(sig); + // Set the FMC Certificate Signature in data vault. + let data_vault = &mut env.persistent_data.get_mut().data_vault; + data_vault.set_fmc_dice_ecc_signature(sig); sig.zeroize(); - // Lock the FMC Public key in the data vault until next boot - env.data_vault.set_fmc_pub_key(pub_key); + // Set the FMC Public key in the data vault. + data_vault.set_fmc_ecc_pub_key(pub_key); // Copy TBS to DCCM. copy_tbs(tbs.tbs(), TbsType::FmcaliasTbs, env)?; diff --git a/rom/dev/src/flow/cold_reset/fw_processor.rs b/rom/dev/src/flow/cold_reset/fw_processor.rs index ff11224e38..d7490927dc 100644 --- a/rom/dev/src/flow/cold_reset/fw_processor.rs +++ b/rom/dev/src/flow/cold_reset/fw_processor.rs @@ -112,7 +112,7 @@ impl FirmwareProcessor { soc_ifc: &mut env.soc_ifc, ecc384: &mut env.ecc384, mldsa87: &mut env.mldsa87, - data_vault: &mut env.data_vault, + data_vault: &env.persistent_data.get().data_vault, pcr_bank: &mut env.pcr_bank, image: txn.raw_mailbox_contents(), }; @@ -124,10 +124,16 @@ impl FirmwareProcessor { Self::update_fuse_log(&mut env.persistent_data.get_mut().fuse_log, &info.log_info)?; // Populate data vault - Self::populate_data_vault(venv.data_vault, info, &env.persistent_data); + Self::populate_data_vault(info, &mut env.persistent_data); // Extend PCR0 and PCR1 - pcr::extend_pcrs(&mut venv, info, &mut env.persistent_data)?; + pcr::extend_pcrs( + env.persistent_data.get_mut(), + &env.soc_ifc, + &mut env.pcr_bank, + &mut env.sha2_512_384, + info, + )?; report_boot_status(FwProcessorExtendPcrComplete.into()); // Load the image @@ -542,48 +548,28 @@ impl FirmwareProcessor { /// /// # Arguments /// - /// * `env` - ROM Environment /// * `info` - Image Verification Info + /// * `persistent_data` - Persistent data accessor + /// #[cfg_attr(not(feature = "no-cfi"), cfi_impl_fn)] fn populate_data_vault( - data_vault: &mut DataVault, info: &ImageVerificationInfo, - persistent_data: &PersistentDataAccessor, + persistent_data: &mut PersistentDataAccessor, ) { - data_vault.write_cold_reset_entry48(ColdResetEntry48::FmcTci, &info.fmc.digest.into()); + let manifest_address = &persistent_data.get().manifest1 as *const _ as u32; + let data_vault = &mut persistent_data.get_mut().data_vault; + data_vault.set_fmc_tci(&info.fmc.digest.into()); + data_vault.set_fmc_svn(info.fw_svn); + data_vault.set_fmc_entry_point(info.fmc.entry_point); + data_vault.set_owner_pk_hash(&info.owner_pub_keys_digest.into()); + data_vault.set_vendor_ecc_pk_index(info.vendor_ecc_pub_key_idx); + data_vault.set_vendor_pqc_pk_index(info.vendor_pqc_pub_key_idx); + data_vault.set_rt_tci(&info.runtime.digest.into()); + data_vault.set_rt_svn(info.fw_svn); + data_vault.set_rt_min_svn(info.fw_svn); + data_vault.set_rt_entry_point(info.runtime.entry_point); + data_vault.set_manifest_addr(manifest_address); - data_vault.write_cold_reset_entry4(ColdResetEntry4::FmcSvn, info.fw_svn); - - data_vault.write_cold_reset_entry4(ColdResetEntry4::FmcEntryPoint, info.fmc.entry_point); - - data_vault.write_cold_reset_entry48( - ColdResetEntry48::OwnerPubKeyHash, - &info.owner_pub_keys_digest.into(), - ); - - data_vault.write_cold_reset_entry4( - ColdResetEntry4::EccVendorPubKeyIndex, - info.vendor_ecc_pub_key_idx, - ); - - // If LMS is not enabled, write the max value to the data vault - // to indicate the index is invalid. - data_vault.write_cold_reset_entry4( - ColdResetEntry4::PqcVendorPubKeyIndex, - info.vendor_pqc_pub_key_idx, - ); - - data_vault.write_warm_reset_entry48(WarmResetEntry48::RtTci, &info.runtime.digest.into()); - - data_vault.write_warm_reset_entry4(WarmResetEntry4::RtSvn, info.fw_svn); - data_vault.write_warm_reset_entry4(WarmResetEntry4::RtMinSvn, info.fw_svn); // At cold-boot, min_svn == curr_svn - - data_vault.write_warm_reset_entry4(WarmResetEntry4::RtEntryPoint, info.runtime.entry_point); - - data_vault.write_warm_reset_entry4( - WarmResetEntry4::ManifestAddr, - &persistent_data.get().manifest1 as *const _ as u32, - ); report_boot_status(FwProcessorPopulateDataVaultComplete.into()); } diff --git a/rom/dev/src/flow/cold_reset/idev_id.rs b/rom/dev/src/flow/cold_reset/idev_id.rs index ca40af2520..7142868e47 100644 --- a/rom/dev/src/flow/cold_reset/idev_id.rs +++ b/rom/dev/src/flow/cold_reset/idev_id.rs @@ -265,7 +265,7 @@ impl InitDevIdLayer { // CSR `To Be Signed` Parameters let params = InitDevIdCsrTbsParams { // Unique Endpoint Identifier - ueid: &X509::ueid(env)?, + ueid: &X509::ueid(&env.soc_ifc)?, // Subject Name subject_sn: &output.ecc_subj_sn, diff --git a/rom/dev/src/flow/cold_reset/ldev_id.rs b/rom/dev/src/flow/cold_reset/ldev_id.rs index 898ce72c80..5ce5291b9c 100644 --- a/rom/dev/src/flow/cold_reset/ldev_id.rs +++ b/rom/dev/src/flow/cold_reset/ldev_id.rs @@ -186,12 +186,12 @@ impl LocalDevIdLayer { let ecc_auth_pub_key = &input.ecc_auth_key_pair.pub_key; let ecc_pub_key = &output.ecc_subj_key_pair.pub_key; - let ecc_serial_number = X509::ecc_cert_sn(env, ecc_pub_key); + let ecc_serial_number = X509::ecc_cert_sn(&mut env.sha256, ecc_pub_key); let ecc_serial_number = okref(&ecc_serial_number)?; // CSR `To Be Signed` Parameters let ecc_tbs_params = LocalDevIdCertTbsParams { - ueid: &X509::ueid(env)?, + ueid: &X509::ueid(&env.soc_ifc)?, subject_sn: &output.ecc_subj_sn, subject_key_id: &output.ecc_subj_key_id, issuer_sn: input.ecc_auth_sn, @@ -234,14 +234,14 @@ impl LocalDevIdLayer { cprintln!("[ldev] SIG.R = {}", HexBytes(&_sig_r)); cprintln!("[ldev] SIG.S = {}", HexBytes(&_sig_s)); - // Lock the Local Device ID cert signature in data vault until - // cold reset - env.data_vault.set_ldev_dice_signature(sig); + let data_vault = &mut env.persistent_data.get_mut().data_vault; + + // Save the Local Device ID cert signature in data vault. + data_vault.set_ldev_dice_ecc_signature(sig); sig.zeroize(); - // Lock the Local Device ID public key in data vault until - // cold reset - env.data_vault.set_ldev_dice_pub_key(ecc_pub_key); + // Save the Local Device ID public key in data vault. + data_vault.set_ldev_dice_ecc_pub_key(ecc_pub_key); // Copy TBS to DCCM. copy_tbs(ecc_tbs.tbs(), TbsType::LdevidTbs, env)?; diff --git a/rom/dev/src/flow/cold_reset/mod.rs b/rom/dev/src/flow/cold_reset/mod.rs index 54cbf908dd..9713fcdac4 100644 --- a/rom/dev/src/flow/cold_reset/mod.rs +++ b/rom/dev/src/flow/cold_reset/mod.rs @@ -50,12 +50,14 @@ impl ColdResetFlow { pub fn run(env: &mut RomEnv) -> CaliptraResult<()> { cprintln!("[cold-reset] ++"); report_boot_status(ColdResetStarted.into()); + { + let data_vault = &mut env.persistent_data.get_mut().data_vault; - // Indicate that Cold-Reset flow has started. - // This is used by the next Warm-Reset flow to confirm that the Cold-Reset was successful. - // Success status is set at the end of the flow. - env.data_vault - .write_cold_reset_entry4(ColdResetEntry4::RomColdBootStatus, ColdResetStarted.into()); + // Indicate that Cold-Reset flow has started. + // This is used by the next Warm-Reset flow to confirm that the Cold-Reset was successful. + // Success status is set at the end of the flow. + data_vault.set_rom_cold_boot_status(ColdResetStarted.into()); + } // Initialize FHT fht::initialize_fht(env); @@ -81,10 +83,8 @@ impl ColdResetFlow { // Indicate Cold-Reset successful completion. // This is used by the Warm-Reset flow to confirm that the Cold-Reset was successful. - env.data_vault.write_lock_cold_reset_entry4( - ColdResetEntry4::RomColdBootStatus, - ColdResetComplete.into(), - ); + let data_vault = &mut env.persistent_data.get_mut().data_vault; + data_vault.set_rom_cold_boot_status(ColdResetComplete.into()); report_boot_status(ColdResetComplete.into()); diff --git a/rom/dev/src/flow/cold_reset/x509.rs b/rom/dev/src/flow/cold_reset/x509.rs index 6ff1dc68aa..93ec773b5b 100644 --- a/rom/dev/src/flow/cold_reset/x509.rs +++ b/rom/dev/src/flow/cold_reset/x509.rs @@ -27,13 +27,13 @@ impl X509 { /// /// # Arguments /// - /// * `env` - ROM Environment + /// * `soc_ifc` - SOC Interface object /// /// # Returns /// /// `[u8; 17]` - Byte 0 - Ueid Type, Bytes 1-16 Unique Endpoint Identifier - pub fn ueid(env: &RomEnv) -> CaliptraResult<[u8; 17]> { - let ueid = env.soc_ifc.fuse_bank().ueid(); + pub fn ueid(soc_ifc: &SocIfc) -> CaliptraResult<[u8; 17]> { + let ueid = soc_ifc.fuse_bank().ueid(); Ok(ueid) } @@ -67,7 +67,7 @@ impl X509 { // Define an array large enough to hold the largest public key. let mut pub_key_bytes: [u8; size_of::()] = [0; size_of::()]; let pub_key_size = Self::get_pubkey_bytes(pub_key, &mut pub_key_bytes); - Crypto::sha256_digest(env, &pub_key_bytes[..pub_key_size]) + Crypto::sha256_digest(&mut env.sha256, &pub_key_bytes[..pub_key_size]) } /// Get X509 Subject Serial Number from public key @@ -111,7 +111,7 @@ impl X509 { } X509KeyIdAlgo::Sha256 => { cprintln!("[idev] Sha256 KeyId Algorithm"); - let digest = Crypto::sha256_digest(env, data); + let digest = Crypto::sha256_digest(&mut env.sha256, data); let digest: [u8; 32] = okref(&digest)?.into(); digest[..20].try_into().unwrap() } @@ -150,15 +150,15 @@ impl X509 { /// /// # Arguments /// - /// * `env` - ROM Environment + /// * `sha256` - SHA256 Driver /// * `pub_key` - ECC Public Key /// /// # Returns /// /// `[u8; 20]` - X509 Serial Number - pub fn ecc_cert_sn(env: &mut RomEnv, pub_key: &Ecc384PubKey) -> CaliptraResult<[u8; 20]> { + pub fn ecc_cert_sn(sha256: &mut Sha256, pub_key: &Ecc384PubKey) -> CaliptraResult<[u8; 20]> { let data = pub_key.to_der(); - let digest = Crypto::sha256_digest(env, &data); + let digest = Crypto::sha256_digest(sha256, &data); let mut digest: [u8; 32] = okref(&digest)?.into(); // Ensure the encoded integer is positive, and that the first octet diff --git a/rom/dev/src/flow/fake.rs b/rom/dev/src/flow/fake.rs index c9bdf6e1d6..55da4c4a01 100644 --- a/rom/dev/src/flow/fake.rs +++ b/rom/dev/src/flow/fake.rs @@ -202,11 +202,13 @@ fn initialize_fake_ldevid_cdi(env: &mut RomEnv) -> CaliptraResult<()> { } pub fn copy_canned_ldev_cert(env: &mut RomEnv) -> CaliptraResult<()> { + let data_vault = &mut env.persistent_data.get_mut().data_vault; + // Store signature - env.data_vault.set_ldev_dice_signature(&FAKE_LDEV_SIG); + data_vault.set_ldev_dice_ecc_signature(&FAKE_LDEV_SIG); // Store pub key - env.data_vault.set_ldev_dice_pub_key(&FAKE_LDEV_PUB_KEY); + data_vault.set_ldev_dice_ecc_pub_key(&FAKE_LDEV_PUB_KEY); // Copy TBS to DCCM let tbs = &FAKE_LDEV_TBS; @@ -220,11 +222,13 @@ pub fn copy_canned_ldev_cert(env: &mut RomEnv) -> CaliptraResult<()> { } pub fn copy_canned_fmc_alias_cert(env: &mut RomEnv) -> CaliptraResult<()> { + let data_vault = &mut env.persistent_data.get_mut().data_vault; + // Store signature - env.data_vault.set_fmc_dice_signature(&FAKE_FMC_ALIAS_SIG); + data_vault.set_fmc_dice_ecc_signature(&FAKE_FMC_ALIAS_SIG); // Store pub key - env.data_vault.set_fmc_pub_key(&FAKE_FMC_ALIAS_PUB_KEY); + data_vault.set_fmc_ecc_pub_key(&FAKE_FMC_ALIAS_PUB_KEY); // Copy TBS to DCCM let tbs = &FAKE_FMC_ALIAS_TBS; @@ -241,7 +245,7 @@ pub(crate) struct FakeRomImageVerificationEnv<'a, 'b> { pub(crate) sha256: &'a mut Sha256, pub(crate) sha2_512_384: &'a mut Sha2_512_384, pub(crate) soc_ifc: &'a mut SocIfc, - pub(crate) data_vault: &'a mut DataVault, + pub(crate) data_vault: &'a DataVault, pub(crate) ecc384: &'a mut Ecc384, pub(crate) mldsa87: &'a mut Mldsa87, pub image: &'b [u8], @@ -367,12 +371,12 @@ impl<'a, 'b> ImageVerificationEnv for &mut FakeRomImageVerificationEnv<'a, 'b> { /// Get the vendor ECC key index saved in data vault on cold boot fn vendor_ecc_pub_key_idx_dv(&self) -> u32 { - self.data_vault.ecc_vendor_pk_index() + self.data_vault.vendor_ecc_pk_index() } /// Get the vendor LMS key index saved in data vault on cold boot fn vendor_pqc_pub_key_idx_dv(&self) -> u32 { - self.data_vault.pqc_vendor_pk_index() + self.data_vault.vendor_pqc_pk_index() } /// Get the owner public key digest saved in the dv on cold boot diff --git a/rom/dev/src/flow/update_reset.rs b/rom/dev/src/flow/update_reset.rs index b7f8be199b..d819f62163 100644 --- a/rom/dev/src/flow/update_reset.rs +++ b/rom/dev/src/flow/update_reset.rs @@ -20,9 +20,7 @@ use caliptra_common::mailbox_api::CommandId; use caliptra_common::verifier::FirmwareImageVerificationEnv; use caliptra_common::RomBootStatus::*; use caliptra_drivers::report_fw_error_non_fatal; -use caliptra_drivers::{ - okref, report_boot_status, MailboxRecvTxn, ResetReason, WarmResetEntry4, WarmResetEntry48, -}; +use caliptra_drivers::{okref, report_boot_status, MailboxRecvTxn, ResetReason}; use caliptra_drivers::{DataVault, PersistentData}; use caliptra_error::{CaliptraError, CaliptraResult}; use caliptra_image_types::ImageManifest; @@ -43,13 +41,12 @@ impl UpdateResetFlow { cprintln!("[update-reset] ++"); report_boot_status(UpdateResetStarted.into()); + let data_vault = &mut env.persistent_data.get_mut().data_vault; + // Indicate that Update-Reset flow has started. // This is used by the next Warm-Reset flow to confirm that the Update-Reset was successful. // Success status is set at the end of the flow. - env.data_vault.write_warm_reset_entry4( - WarmResetEntry4::RomUpdateResetStatus, - UpdateResetStarted.into(), - ); + data_vault.set_rom_update_reset_status(UpdateResetStarted.into()); let Some(mut recv_txn) = env.mbox.try_start_recv_txn() else { cprintln!("Failed To Get Mailbox Txn"); @@ -71,7 +68,7 @@ impl UpdateResetFlow { soc_ifc: &mut env.soc_ifc, ecc384: &mut env.ecc384, mldsa87: &mut env.mldsa87, - data_vault: &mut env.data_vault, + data_vault: &env.persistent_data.get().data_vault, pcr_bank: &mut env.pcr_bank, image: recv_txn.raw_mailbox_contents(), }; @@ -84,10 +81,17 @@ impl UpdateResetFlow { report_boot_status(UpdateResetImageVerificationComplete.into()); // Populate data vault - Self::populate_data_vault(venv.data_vault, info); + let data_vault = &mut env.persistent_data.get_mut().data_vault; + Self::populate_data_vault(data_vault, info); // Extend PCR0 and PCR1 - pcr::extend_pcrs(&mut venv, info, &mut env.persistent_data)?; + pcr::extend_pcrs( + env.persistent_data.get_mut(), + &env.soc_ifc, + &mut env.pcr_bank, + &mut env.sha2_512_384, + info, + )?; report_boot_status(UpdateResetExtendPcrComplete.into()); cprintln!( @@ -121,10 +125,8 @@ impl UpdateResetFlow { env.soc_ifc .set_rt_fw_rev_id(persistent_data.manifest1.runtime.version); - env.data_vault.write_lock_warm_reset_entry4( - WarmResetEntry4::RomUpdateResetStatus, - UpdateResetComplete.into(), - ); + let data_vault = &mut env.persistent_data.get_mut().data_vault; + data_vault.set_rom_update_reset_status(UpdateResetComplete.into()); cprintln!("[update-reset Success] --"); report_boot_status(UpdateResetComplete.into()); @@ -215,15 +217,14 @@ impl UpdateResetFlow { /// * `env` - ROM Environment /// * `info` - Image Verification Info fn populate_data_vault(data_vault: &mut DataVault, info: &ImageVerificationInfo) { - data_vault.write_warm_reset_entry48(WarmResetEntry48::RtTci, &info.runtime.digest.into()); + data_vault.set_rt_tci(&info.runtime.digest.into()); - let cur_min_svn = data_vault.read_warm_reset_entry4(WarmResetEntry4::RtMinSvn); + let cur_min_svn = data_vault.rt_min_svn(); let new_min_svn = core::cmp::min(cur_min_svn, info.fw_svn); - data_vault.write_warm_reset_entry4(WarmResetEntry4::RtSvn, info.fw_svn); - data_vault.write_warm_reset_entry4(WarmResetEntry4::RtMinSvn, new_min_svn); - - data_vault.write_warm_reset_entry4(WarmResetEntry4::RtEntryPoint, info.runtime.entry_point); + data_vault.set_rt_svn(info.fw_svn); + data_vault.set_rt_min_svn(new_min_svn); + data_vault.set_rt_entry_point(info.runtime.entry_point); report_boot_status(UpdateResetPopulateDataVaultComplete.into()); } diff --git a/rom/dev/src/flow/warm_reset.rs b/rom/dev/src/flow/warm_reset.rs index 07e5ae799a..8a9b67c592 100644 --- a/rom/dev/src/flow/warm_reset.rs +++ b/rom/dev/src/flow/warm_reset.rs @@ -32,24 +32,23 @@ impl WarmResetFlow { pub fn run(env: &mut RomEnv) -> CaliptraResult<()> { cprintln!("[warm-reset] ++"); + let data_vault = &env.persistent_data.get().data_vault; + // Check if previous Cold-Reset was successful. - if cfi_launder(env.data_vault.rom_cold_boot_status()) != ColdResetComplete.into() { + if cfi_launder(data_vault.rom_cold_boot_status()) != ColdResetComplete.into() { cprintln!("[warm-reset] Prev Cold-Reset failed"); return Err(CaliptraError::ROM_WARM_RESET_UNSUCCESSFUL_PREVIOUS_COLD_RESET); } else { - cfi_assert_eq( - env.data_vault.rom_cold_boot_status(), - ColdResetComplete.into(), - ); + cfi_assert_eq(data_vault.rom_cold_boot_status(), ColdResetComplete.into()); } // Check if previous Update-Reset, if any, was successful. - if cfi_launder(env.data_vault.rom_update_reset_status()) == UpdateResetStarted.into() { + if cfi_launder(data_vault.rom_update_reset_status()) == UpdateResetStarted.into() { cprintln!("[warm-reset] Prev Update Reset failed"); return Err(CaliptraError::ROM_WARM_RESET_UNSUCCESSFUL_PREVIOUS_UPDATE_RESET); } else { cfi_assert_ne( - env.data_vault.rom_update_reset_status(), + data_vault.rom_update_reset_status(), UpdateResetStarted.into(), ); } diff --git a/rom/dev/src/lock.rs b/rom/dev/src/lock.rs index 3934e18779..81baeb3f0d 100644 --- a/rom/dev/src/lock.rs +++ b/rom/dev/src/lock.rs @@ -15,9 +15,7 @@ Abstract: #[cfg(not(feature = "no-cfi"))] use caliptra_cfi_derive::cfi_mod_fn; use caliptra_common::pcr::{PCR_ID_FMC_CURRENT, PCR_ID_FMC_JOURNEY, PCR_ID_STASH_MEASUREMENT}; -use caliptra_drivers::{ - ColdResetEntry4, ColdResetEntry48, ResetReason, WarmResetEntry4, WarmResetEntry48, -}; +use caliptra_drivers::ResetReason; use crate::{cprintln, rom_env::RomEnv}; @@ -54,34 +52,8 @@ pub fn lock_registers(env: &mut RomEnv, reset_reason: ResetReason) { /// /// * `env` - ROM Environment #[cfg_attr(not(feature = "no-cfi"), cfi_mod_fn)] -fn lock_cold_reset_reg(env: &mut RomEnv) { - // Lock the FMC TCI in data vault until next cold reset - env.data_vault - .lock_cold_reset_entry48(ColdResetEntry48::FmcTci); - - // Lock the FMC SVN in data vault until next cold reset - env.data_vault - .lock_cold_reset_entry4(ColdResetEntry4::FmcSvn); - - // Lock the FMC entry point in data vault until next cold reset - env.data_vault - .lock_cold_reset_entry4(ColdResetEntry4::FmcEntryPoint); - - // Lock the Owner Public Key Hash in data vault until next cold reset - env.data_vault - .lock_cold_reset_entry48(ColdResetEntry48::OwnerPubKeyHash); - - // Lock the Ecc Vendor Public Key Index in data vault until next cold reset - env.data_vault - .lock_cold_reset_entry4(ColdResetEntry4::EccVendorPubKeyIndex); - - // Lock the Lms Vendor Public Key Index in data vault until next cold reset - env.data_vault - .lock_cold_reset_entry4(ColdResetEntry4::PqcVendorPubKeyIndex); - - // Lock Cold Reset Status register in data vault until next cold reset - env.data_vault - .lock_cold_reset_entry4(ColdResetEntry4::RomColdBootStatus); +fn lock_cold_reset_reg(_env: &mut RomEnv) { + // [TODO][CAP2] Lock the cold reset entries via PMP. } /// Lock all common registers across all reset types @@ -90,28 +62,6 @@ fn lock_cold_reset_reg(env: &mut RomEnv) { /// /// * `env` - ROM Environment #[cfg_attr(not(feature = "no-cfi"), cfi_mod_fn)] -fn lock_common_reg_set(env: &mut RomEnv) { - // Lock the Runtime TCI in data vault until next reset - env.data_vault - .lock_warm_reset_entry48(WarmResetEntry48::RtTci); - - // Lock the Runtime SVN in data vault until next reset - env.data_vault - .lock_warm_reset_entry4(WarmResetEntry4::RtSvn); - - // Lock the Firmware Min-SVN in data vault until next reset - env.data_vault - .lock_warm_reset_entry4(WarmResetEntry4::RtMinSvn); - - // Lock the Runtime entry point in data vault until next reset - env.data_vault - .lock_warm_reset_entry4(WarmResetEntry4::RtEntryPoint); - - // Lock the Manifest addr in data vault until next reset - env.data_vault - .lock_warm_reset_entry4(WarmResetEntry4::ManifestAddr); - - // Lock the Update Reset status in data vault until next reset - env.data_vault - .lock_warm_reset_entry4(WarmResetEntry4::RomUpdateResetStatus); +fn lock_common_reg_set(_env: &mut RomEnv) { + // [TODO][CAP2] Lock the warm reset entries via PMP. } diff --git a/rom/dev/src/main.rs b/rom/dev/src/main.rs index 48853aa3d2..9b7ee46e29 100644 --- a/rom/dev/src/main.rs +++ b/rom/dev/src/main.rs @@ -251,7 +251,7 @@ fn launch_fmc(env: &mut RomEnv) -> ! { } // Get the fmc entry point from data vault - let entry = env.data_vault.fmc_entry_point(); + let entry = env.persistent_data.get().data_vault.fmc_entry_point(); cprintln!("[exit] Launching FMC @ 0x{:08X}", entry); diff --git a/rom/dev/src/pcr.rs b/rom/dev/src/pcr.rs index 6e680be95a..e7a63fecc8 100644 --- a/rom/dev/src/pcr.rs +++ b/rom/dev/src/pcr.rs @@ -23,16 +23,14 @@ Note: #[cfg(not(feature = "no-cfi"))] use caliptra_cfi_derive::{cfi_impl_fn, cfi_mod_fn}; -use caliptra_common::verifier::FirmwareImageVerificationEnv; use caliptra_common::{ pcr::{PCR_ID_FMC_CURRENT, PCR_ID_FMC_JOURNEY}, PcrLogEntry, PcrLogEntryId, }; use caliptra_drivers::{ - CaliptraError, CaliptraResult, PcrBank, PersistentData, PersistentDataAccessor, Sha2_512_384, + CaliptraError, CaliptraResult, PcrBank, PersistentData, Sha2_512_384, SocIfc, }; use caliptra_image_verify::ImageVerificationInfo; - use zerocopy::AsBytes; struct PcrExtender<'a> { @@ -58,52 +56,60 @@ impl PcrExtender<'_> { /// /// # Arguments /// -/// * `env` - ROM Environment +/// * `persistent_data` - Persistent data +/// * `soc_ifc` - SOC Interface +/// * `pcr_bank` - PCR Bank +/// * `sha2_512_384` - SHA-512/384 Accelerator +/// * `info` - Image Verification Info +/// +/// # Return Value +/// * `Ok(())` on success, error code on failure +/// #[cfg_attr(not(feature = "no-cfi"), cfi_mod_fn)] #[inline(never)] pub(crate) fn extend_pcrs( - env: &mut FirmwareImageVerificationEnv, + persistent_data: &mut PersistentData, + soc_ifc: &SocIfc, + pcr_bank: &mut PcrBank, + sha2_512_384: &mut Sha2_512_384, info: &ImageVerificationInfo, - persistent_data: &mut PersistentDataAccessor, ) -> CaliptraResult<()> { + let data_vault = &persistent_data.data_vault; + let owner_pk_hash = <[u8; 48]>::from(&data_vault.owner_pk_hash()); + let fmc_tci = <[u8; 48]>::from(&data_vault.fmc_tci()); + // Reset the PCR log size to zero. - persistent_data.get_mut().fht.pcr_log_index = 0; + persistent_data.fht.pcr_log_index = 0; // Clear the Current PCR, but do not clear the Journey PCR - env.pcr_bank.erase_pcr(PCR_ID_FMC_CURRENT)?; - - let mut pcr = PcrExtender { - persistent_data: persistent_data.get_mut(), - pcr_bank: env.pcr_bank, - sha2_512_384: env.sha2_512_384, - }; + pcr_bank.erase_pcr(PCR_ID_FMC_CURRENT)?; let device_status: [u8; 9] = [ - env.soc_ifc.lifecycle() as u8, - env.soc_ifc.debug_locked() as u8, - env.soc_ifc.fuse_bank().anti_rollback_disable() as u8, - env.data_vault.ecc_vendor_pk_index() as u8, - env.data_vault.fmc_svn() as u8, + soc_ifc.lifecycle() as u8, + soc_ifc.debug_locked() as u8, + soc_ifc.fuse_bank().anti_rollback_disable() as u8, + data_vault.vendor_ecc_pk_index() as u8, + data_vault.fmc_svn() as u8, info.effective_fuse_svn as u8, - env.data_vault.pqc_vendor_pk_index() as u8, + data_vault.vendor_pqc_pk_index() as u8, info.pqc_verify_config as u8, info.owner_pub_keys_digest_in_fuses as u8, ]; + let mut pcr = PcrExtender { + persistent_data, + pcr_bank, + sha2_512_384, + }; + pcr.extend(&device_status, PcrLogEntryId::DeviceStatus)?; pcr.extend( - &<[u8; 48]>::from(&env.soc_ifc.fuse_bank().vendor_pub_key_info_hash()), + &<[u8; 48]>::from(&soc_ifc.fuse_bank().vendor_pub_key_info_hash()), PcrLogEntryId::VendorPubKeyInfoHash, )?; - pcr.extend( - &<[u8; 48]>::from(&env.data_vault.owner_pk_hash()), - PcrLogEntryId::OwnerPubKeyHash, - )?; - pcr.extend( - &<[u8; 48]>::from(&env.data_vault.fmc_tci()), - PcrLogEntryId::FmcTci, - )?; + pcr.extend(&owner_pk_hash, PcrLogEntryId::OwnerPubKeyHash)?; + pcr.extend(&fmc_tci, PcrLogEntryId::FmcTci)?; Ok(()) } diff --git a/rom/dev/src/rom_env.rs b/rom/dev/src/rom_env.rs index f2c7bfb74b..8750ede1a5 100644 --- a/rom/dev/src/rom_env.rs +++ b/rom/dev/src/rom_env.rs @@ -17,14 +17,14 @@ Abstract: use crate::fht::FhtDataStore; use caliptra_drivers::{ - DataVault, DeobfuscationEngine, Ecc384, Hmac, KeyVault, Lms, Mailbox, Mldsa87, PcrBank, + DeobfuscationEngine, Ecc384, Hmac, KeyVault, Lms, Mailbox, Mldsa87, PcrBank, PersistentDataAccessor, Sha1, Sha256, Sha2_512_384, Sha2_512_384Acc, SocIfc, Trng, }; use caliptra_error::CaliptraResult; use caliptra_registers::{ - csrng::CsrngReg, doe::DoeReg, dv::DvReg, ecc::EccReg, entropy_src::EntropySrcReg, - hmac::HmacReg, kv::KvReg, mbox::MboxCsr, mldsa::MldsaReg, pv::PvReg, sha256::Sha256Reg, - sha512::Sha512Reg, sha512_acc::Sha512AccCsr, soc_ifc::SocIfcReg, soc_ifc_trng::SocIfcTrngReg, + csrng::CsrngReg, doe::DoeReg, ecc::EccReg, entropy_src::EntropySrcReg, hmac::HmacReg, + kv::KvReg, mbox::MboxCsr, mldsa::MldsaReg, pv::PvReg, sha256::Sha256Reg, sha512::Sha512Reg, + sha512_acc::Sha512AccCsr, soc_ifc::SocIfcReg, soc_ifc_trng::SocIfcTrngReg, }; /// Rom Context @@ -56,9 +56,6 @@ pub struct RomEnv { /// Key Vault pub key_vault: KeyVault, - /// Data Vault - pub data_vault: DataVault, - /// SoC interface pub soc_ifc: SocIfc, @@ -100,7 +97,6 @@ impl RomEnv { ecc384: Ecc384::new(EccReg::new()), lms: Lms::default(), key_vault: KeyVault::new(KvReg::new()), - data_vault: DataVault::new(DvReg::new()), soc_ifc: SocIfc::new(SocIfcReg::new()), mbox: Mailbox::new(MboxCsr::new()), pcr_bank: PcrBank::new(PvReg::new()), diff --git a/rom/dev/tests/rom_integration_tests/test_fmcalias_derivation.rs b/rom/dev/tests/rom_integration_tests/test_fmcalias_derivation.rs index ebbfffd631..fe7293460b 100644 --- a/rom/dev/tests/rom_integration_tests/test_fmcalias_derivation.rs +++ b/rom/dev/tests/rom_integration_tests/test_fmcalias_derivation.rs @@ -15,8 +15,8 @@ use caliptra_common::RomBootStatus::*; use caliptra_common::{FirmwareHandoffTable, FuseLogEntry, FuseLogEntryId}; use caliptra_common::{PcrLogEntry, PcrLogEntryId}; use caliptra_drivers::memory_layout::*; -use caliptra_drivers::pcr_log::MeasurementLogEntry; -use caliptra_drivers::{ColdResetEntry4, PcrId, RomPqcVerifyConfig}; +use caliptra_drivers::{pcr_log::MeasurementLogEntry, DataVault}; +use caliptra_drivers::{PcrId, RomPqcVerifyConfig}; use caliptra_error::CaliptraError; use caliptra_hw_model::{BootParams, Fuses, HwModel, InitParams, ModelError, SecurityState}; use caliptra_image_crypto::OsslCrypto as Crypto; @@ -789,20 +789,13 @@ fn test_check_rom_cold_boot_status_reg() { hw.step_until_boot_status(u32::from(ColdResetComplete), true); - let coldresetentry4_array = hw.mailbox_execute(0x1000_0005, &[]).unwrap().unwrap(); - let mut coldresetentry4_offset = core::mem::size_of::() * 2; // Skip first entry + let data_vault = hw.mailbox_execute(0x1000_0005, &[]).unwrap().unwrap(); + let data_vault = DataVault::read_from_prefix(data_vault.as_bytes()).unwrap(); - // Check RomColdBootStatus datavault value. - let coldresetentry4_id = - u32::read_from_prefix(coldresetentry4_array[coldresetentry4_offset..].as_bytes()).unwrap(); assert_eq!( - coldresetentry4_id, - ColdResetEntry4::RomColdBootStatus as u32 + data_vault.rom_cold_boot_status(), + u32::from(ColdResetComplete) ); - coldresetentry4_offset += core::mem::size_of::(); - let coldresetentry4_value = - u32::read_from_prefix(coldresetentry4_array[coldresetentry4_offset..].as_bytes()).unwrap(); - assert_eq!(coldresetentry4_value, u32::from(ColdResetComplete)); } #[test] diff --git a/rom/dev/tests/rom_integration_tests/test_update_reset.rs b/rom/dev/tests/rom_integration_tests/test_update_reset.rs index 67321bbe96..b3175d0df0 100644 --- a/rom/dev/tests/rom_integration_tests/test_update_reset.rs +++ b/rom/dev/tests/rom_integration_tests/test_update_reset.rs @@ -14,7 +14,7 @@ use caliptra_builder::{ }; use caliptra_common::mailbox_api::CommandId; use caliptra_common::RomBootStatus::*; -use caliptra_drivers::WarmResetEntry4; +use caliptra_drivers::DataVault; use caliptra_error::CaliptraError; use caliptra_hw_model::{BootParams, HwModel, InitParams}; use caliptra_image_fake_keys::VENDOR_CONFIG_KEY_0; @@ -451,20 +451,12 @@ fn test_check_rom_update_reset_status_reg() { hw.step_until_boot_status(UpdateResetComplete.into(), true); - let warmresetentry4_array = hw.mailbox_execute(0x1000_000D, &[]).unwrap().unwrap(); - let mut warmresetentry4_offset = core::mem::size_of::() * 8; // Skip first four entries - - // Check RomUpdateResetStatus datavault value. - let warmresetentry4_id = - u32::read_from_prefix(warmresetentry4_array[warmresetentry4_offset..].as_bytes()).unwrap(); + let data_vault = hw.mailbox_execute(0x1000_0005, &[]).unwrap().unwrap(); + let data_vault = DataVault::read_from_prefix(data_vault.as_bytes()).unwrap(); assert_eq!( - warmresetentry4_id, - WarmResetEntry4::RomUpdateResetStatus as u32 + data_vault.rom_update_reset_status(), + u32::from(UpdateResetComplete) ); - warmresetentry4_offset += core::mem::size_of::(); - let warmresetentry4_value = - u32::read_from_prefix(warmresetentry4_array[warmresetentry4_offset..].as_bytes()).unwrap(); - assert_eq!(warmresetentry4_value, u32::from(UpdateResetComplete)); } #[test] diff --git a/rom/dev/tools/test-fmc/src/main.rs b/rom/dev/tools/test-fmc/src/main.rs index a478d030dc..d45be970bb 100644 --- a/rom/dev/tools/test-fmc/src/main.rs +++ b/rom/dev/tools/test-fmc/src/main.rs @@ -18,11 +18,7 @@ use caliptra_common::pcr::PCR_ID_STASH_MEASUREMENT; use caliptra_common::PcrLogEntry; use caliptra_common::{mailbox_api, FuseLogEntry, FuseLogEntryId}; use caliptra_drivers::pcr_log::MeasurementLogEntry; -use caliptra_drivers::{ - ColdResetEntry4::*, DataVault, Mailbox, PcrBank, PcrId, PersistentDataAccessor, - WarmResetEntry4::*, -}; -use caliptra_registers::dv::DvReg; +use caliptra_drivers::{DataVault, Mailbox, PcrBank, PcrId, PersistentDataAccessor}; use caliptra_registers::pv::PvReg; use caliptra_registers::soc_ifc::SocIfcReg; use caliptra_x509::{Ecdsa384CertBuilder, Ecdsa384Signature, FmcAliasCertTbs, LocalDevIdCertTbs}; @@ -104,13 +100,15 @@ fn create_certs(mbox: &caliptra_registers::mbox::RegisterBlock) { // Create LDEVID cert. // - // Retrieve the public key and signature from the data vault. - let data_vault = unsafe { DataVault::new(DvReg::new()) }; - let ldevid_pub_key = data_vault.ldev_dice_pub_key(); + // Retrieve the ECC public key and signature from the data vault. + let persistent_data = unsafe { PersistentDataAccessor::new() }; + let data_vault = &persistent_data.get().data_vault; + + let ldevid_pub_key = data_vault.ldev_dice_ecc_pub_key(); let mut _pub_der: [u8; 97] = ldevid_pub_key.to_der(); cprint_slice!("[fmc] LDEVID PUBLIC KEY DER", _pub_der); - let sig = data_vault.ldev_dice_signature(); + let sig = data_vault.ldev_dice_ecc_signature(); let ecdsa_sig = Ecdsa384Signature { r: sig.r.into(), @@ -134,11 +132,11 @@ fn create_certs(mbox: &caliptra_registers::mbox::RegisterBlock) { // // Retrieve the public key and signature from the data vault. - let fmcalias_pub_key = data_vault.fmc_pub_key(); + let fmcalias_pub_key = data_vault.fmc_ecc_pub_key(); let _pub_der: [u8; 97] = fmcalias_pub_key.to_der(); cprint_slice!("[fmc] FMCALIAS PUBLIC KEY DER", _pub_der); - let sig = data_vault.fmc_dice_signature(); + let sig = data_vault.fmc_dice_ecc_signature(); let ecdsa_sig = Ecdsa384Signature { r: sig.r.into(), s: sig.s.into(), @@ -195,7 +193,7 @@ fn process_mailbox_command(mbox: &caliptra_registers::mbox::RegisterBlock { - read_datavault_coldresetentry4(mbox); + read_datavault(mbox); } 0x1000_0006 => { read_pcrs(mbox); @@ -225,9 +223,6 @@ fn process_mailbox_command(mbox: &caliptra_registers::mbox::RegisterBlock { - read_datavault_warmresetentry4(mbox); - } 0x1000_000E => { validate_fmc_rt_load_in_iccm(mbox); } @@ -251,7 +246,9 @@ fn process_mailbox_commands() { } fn validate_fmc_rt_load_in_iccm(mbox: &caliptra_registers::mbox::RegisterBlock) { - let data_vault = unsafe { DataVault::new(DvReg::new()) }; + let persistent_data = unsafe { PersistentDataAccessor::new() }; + let data_vault = &persistent_data.get().data_vault; + let fmc_load_addr = data_vault.fmc_entry_point(); let rt_load_addr = data_vault.rt_entry_point(); let fmc_size = mbox.dataout().read() as usize; @@ -308,47 +305,14 @@ fn read_pcr31(mbox: &caliptra_registers::mbox::RegisterBlock) { send_to_mailbox(mbox, &pcr31, true); } -fn read_datavault_coldresetentry4(mbox: &caliptra_registers::mbox::RegisterBlock) { - let data_vault = unsafe { DataVault::new(DvReg::new()) }; - send_to_mailbox(mbox, (FmcSvn as u32).as_bytes(), false); - send_to_mailbox(mbox, data_vault.fmc_svn().as_bytes(), false); - - send_to_mailbox(mbox, (RomColdBootStatus as u32).as_bytes(), false); - send_to_mailbox(mbox, data_vault.rom_cold_boot_status().as_bytes(), false); - - send_to_mailbox(mbox, (FmcEntryPoint as u32).as_bytes(), false); - send_to_mailbox(mbox, data_vault.fmc_entry_point().as_bytes(), false); - - send_to_mailbox(mbox, (EccVendorPubKeyIndex as u32).as_bytes(), false); - send_to_mailbox(mbox, data_vault.ecc_vendor_pk_index().as_bytes(), false); - - send_to_mailbox(mbox, (PqcVendorPubKeyIndex as u32).as_bytes(), false); - send_to_mailbox(mbox, data_vault.pqc_vendor_pk_index().as_bytes(), false); - - mbox.dlen() - .write(|_| (core::mem::size_of::() * 10).try_into().unwrap()); - mbox.status().write(|w| w.status(|w| w.data_ready())); -} - -fn read_datavault_warmresetentry4(mbox: &caliptra_registers::mbox::RegisterBlock) { - let data_vault = unsafe { DataVault::new(DvReg::new()) }; - send_to_mailbox(mbox, (RtSvn as u32).as_bytes(), false); - send_to_mailbox(mbox, data_vault.rt_svn().as_bytes(), false); - - send_to_mailbox(mbox, (RtEntryPoint as u32).as_bytes(), false); - send_to_mailbox(mbox, data_vault.rt_entry_point().as_bytes(), false); - - send_to_mailbox(mbox, (ManifestAddr as u32).as_bytes(), false); - send_to_mailbox(mbox, data_vault.manifest_addr().as_bytes(), false); - - send_to_mailbox(mbox, (RtMinSvn as u32).as_bytes(), false); - send_to_mailbox(mbox, data_vault.rt_min_svn().as_bytes(), false); +fn read_datavault(mbox: &caliptra_registers::mbox::RegisterBlock) { + let persistent_data = unsafe { PersistentDataAccessor::new() }; + let data_vault = &persistent_data.get().data_vault; - send_to_mailbox(mbox, (RomUpdateResetStatus as u32).as_bytes(), false); - send_to_mailbox(mbox, data_vault.rom_update_reset_status().as_bytes(), false); + send_to_mailbox(mbox, data_vault.as_bytes(), false); mbox.dlen() - .write(|_| (core::mem::size_of::() * 10).try_into().unwrap()); + .write(|_| (core::mem::size_of::()).try_into().unwrap()); mbox.status().write(|w| w.status(|w| w.data_ready())); } diff --git a/runtime/src/dice.rs b/runtime/src/dice.rs index cca1659125..642ec651ad 100644 --- a/runtime/src/dice.rs +++ b/runtime/src/dice.rs @@ -70,11 +70,7 @@ impl GetLdevCertCmd { pub(crate) fn execute(drivers: &mut Drivers) -> CaliptraResult { let mut resp = GetLdevCertResp::default(); - resp.data_size = copy_ldevid_cert( - &drivers.data_vault, - drivers.persistent_data.get(), - &mut resp.data, - )? as u32; + resp.data_size = copy_ldevid_cert(drivers.persistent_data.get(), &mut resp.data)? as u32; Ok(MailboxResp::GetLdevCert(resp)) } @@ -86,11 +82,7 @@ impl GetFmcAliasCertCmd { pub(crate) fn execute(drivers: &mut Drivers) -> CaliptraResult { let mut resp = GetFmcAliasCertResp::default(); - resp.data_size = copy_fmc_alias_cert( - &drivers.data_vault, - drivers.persistent_data.get(), - &mut resp.data, - )? as u32; + resp.data_size = copy_fmc_alias_cert(drivers.persistent_data.get(), &mut resp.data)? as u32; Ok(MailboxResp::GetFmcAliasCert(resp)) } @@ -108,87 +100,23 @@ impl GetRtAliasCertCmd { } } -/// Retrieve the r portion of the LDevId cert signature +/// Return the LDevId ECC cert signature /// /// # Arguments /// /// * `persistent_data` - PersistentData -/// * `dv` - DataVault -/// -/// # Returns -/// -/// * `Ecc384Scalar` - The r portion of the LDevId cert signature -fn ldevid_dice_sign_r( - persistent_data: &PersistentData, - dv: &DataVault, -) -> CaliptraResult { - let ds: DataStore = persistent_data - .fht - .ldevid_cert_sig_r_dv_hdl - .try_into() - .map_err(|_| CaliptraError::RUNTIME_LDEVID_CERT_HANDOFF_FAILED)?; - - // The data store is either a warm reset entry or a cold reset entry. - match ds { - DataStore::DataVaultNonSticky48(dv_entry) => Ok(dv.read_warm_reset_entry48(dv_entry)), - DataStore::DataVaultSticky48(dv_entry) => Ok(dv.read_cold_reset_entry48(dv_entry)), - _ => Err(CaliptraError::RUNTIME_LDEVID_CERT_HANDOFF_FAILED), - } -} - -/// Retrieve the s portion of the LDevId cert signature -/// -/// # Arguments -/// -/// * `persistent_data` - PersistentData -/// * `dv` - DataVault -/// -/// # Returns -/// -/// * `Ecc384Scalar` - The s portion of the LDevId cert signature -fn ldevid_dice_sign_s( - persistent_data: &PersistentData, - dv: &DataVault, -) -> CaliptraResult { - let ds: DataStore = persistent_data - .fht - .ldevid_cert_sig_s_dv_hdl - .try_into() - .map_err(|_| CaliptraError::RUNTIME_LDEVID_CERT_HANDOFF_FAILED)?; - - // The data store is either a warm reset entry or a cold reset entry. - match ds { - DataStore::DataVaultNonSticky48(dv_entry) => Ok(dv.read_warm_reset_entry48(dv_entry)), - DataStore::DataVaultSticky48(dv_entry) => Ok(dv.read_cold_reset_entry48(dv_entry)), - _ => Err(CaliptraError::RUNTIME_LDEVID_CERT_HANDOFF_FAILED), - } -} - -/// Piece together the r and s portions of the LDevId cert signature -/// -/// # Arguments -/// -/// * `persistent_data` - PersistentData -/// * `dv` - DataVault /// /// # Returns /// /// * `Ecc384Signature` - The formed signature -pub fn ldevid_dice_sign( - persistent_data: &PersistentData, - dv: &DataVault, -) -> CaliptraResult { - Ok(Ecc384Signature { - r: ldevid_dice_sign_r(persistent_data, dv)?, - s: ldevid_dice_sign_s(persistent_data, dv)?, - }) +pub fn ldevid_dice_sign(persistent_data: &PersistentData) -> Ecc384Signature { + persistent_data.data_vault.ldev_dice_ecc_signature() } /// Copy LDevID certificate produced by ROM to `cert` buffer /// /// # Arguments /// -/// * `dv` - DataVault /// * `persistent_data` - PersistentData /// * `cert` - Buffer to copy LDevID certificate to /// @@ -197,99 +125,34 @@ pub fn ldevid_dice_sign( /// * `usize` - The number of bytes written to `cert` #[inline(never)] pub fn copy_ldevid_cert( - dv: &DataVault, persistent_data: &PersistentData, cert: &mut [u8], ) -> CaliptraResult { let tbs = persistent_data .ldevid_tbs .get(..persistent_data.fht.ldevid_tbs_size.into()); - let sig = ldevid_dice_sign(persistent_data, dv)?; + let sig = ldevid_dice_sign(persistent_data); cert_from_tbs_and_sig(tbs, &sig, cert) .map_err(|_| CaliptraError::RUNTIME_GET_LDEVID_CERT_FAILED) } -/// Retrieve the r portion of the FMC alias cert signature -/// -/// # Arguments -/// -/// * `persistent_data` - PersistentData -/// * `dv` - DataVault -/// -/// # Returns -/// -/// * `Ecc384Scalar` - The r portion of the FMC alias cert signature -fn fmc_dice_sign_r( - persistent_data: &PersistentData, - dv: &DataVault, -) -> CaliptraResult { - let ds: DataStore = persistent_data - .fht - .fmc_cert_sig_r_dv_hdl - .try_into() - .map_err(|_| CaliptraError::RUNTIME_FMC_CERT_HANDOFF_FAILED)?; - - // The data store is either a warm reset entry or a cold reset entry. - match ds { - DataStore::DataVaultNonSticky48(dv_entry) => Ok(dv.read_warm_reset_entry48(dv_entry)), - DataStore::DataVaultSticky48(dv_entry) => Ok(dv.read_cold_reset_entry48(dv_entry)), - _ => Err(CaliptraError::RUNTIME_FMC_CERT_HANDOFF_FAILED), - } -} - -/// Retrieve the s portion of the FMC alias cert signature -/// -/// # Arguments -/// -/// * `persistent_data` - PersistentData -/// * `dv` - DataVault -/// -/// # Returns -/// -/// * `Ecc384Scalar` - The s portion of the FMC alias cert signature -fn fmc_dice_sign_s( - persistent_data: &PersistentData, - dv: &DataVault, -) -> CaliptraResult { - let ds: DataStore = persistent_data - .fht - .fmc_cert_sig_s_dv_hdl - .try_into() - .map_err(|_| CaliptraError::RUNTIME_FMC_CERT_HANDOFF_FAILED)?; - - // The data store is either a warm reset entry or a cold reset entry. - match ds { - DataStore::DataVaultNonSticky48(dv_entry) => Ok(dv.read_warm_reset_entry48(dv_entry)), - DataStore::DataVaultSticky48(dv_entry) => Ok(dv.read_cold_reset_entry48(dv_entry)), - _ => Err(CaliptraError::RUNTIME_FMC_CERT_HANDOFF_FAILED), - } -} - /// Piece together the r and s portions of the FMC alias cert signature /// /// # Arguments /// /// * `persistent_data` - PersistentData -/// * `dv` - DataVault /// /// # Returns /// /// * `Ecc384Signature` - The formed signature -pub fn fmc_dice_sign( - persistent_data: &PersistentData, - dv: &DataVault, -) -> CaliptraResult { - Ok(Ecc384Signature { - r: fmc_dice_sign_r(persistent_data, dv)?, - s: fmc_dice_sign_s(persistent_data, dv)?, - }) +pub fn fmc_dice_sign(persistent_data: &PersistentData) -> Ecc384Signature { + persistent_data.data_vault.fmc_dice_ecc_signature() } /// Copy FMC alias certificate produced by ROM to `cert` buffer /// /// # Arguments /// -/// * `dv` - DataVault /// * `persistent_data` - PersistentData /// * `cert` - Buffer to copy LDevID certificate to /// @@ -298,14 +161,13 @@ pub fn fmc_dice_sign( /// * `usize` - The number of bytes written to `cert` #[inline(never)] pub fn copy_fmc_alias_cert( - dv: &DataVault, persistent_data: &PersistentData, cert: &mut [u8], ) -> CaliptraResult { let tbs = persistent_data .fmcalias_tbs .get(..persistent_data.fht.fmcalias_tbs_size.into()); - let sig = fmc_dice_sign(persistent_data, dv)?; + let sig = fmc_dice_sign(persistent_data); cert_from_tbs_and_sig(tbs, &sig, cert) .map_err(|_| CaliptraError::RUNTIME_GET_FMC_ALIAS_CERT_FAILED) } diff --git a/runtime/src/drivers.rs b/runtime/src/drivers.rs index ad77325ab1..2c018319a6 100644 --- a/runtime/src/drivers.rs +++ b/runtime/src/drivers.rs @@ -77,7 +77,6 @@ pub enum PauserPrivileges { pub struct Drivers { pub mbox: Mailbox, pub sha_acc: Sha512AccCsr, - pub data_vault: DataVault, pub key_vault: KeyVault, pub soc_ifc: SocIfc, pub sha256: Sha256, @@ -137,7 +136,6 @@ impl Drivers { Ok(Self { mbox: Mailbox::new(MboxCsr::new()), sha_acc: Sha512AccCsr::new(), - data_vault: DataVault::new(DvReg::new()), key_vault: KeyVault::new(KvReg::new()), soc_ifc: SocIfc::new(SocIfcReg::new()), sha256: Sha256::new(Sha256Reg::new()), @@ -496,23 +494,18 @@ impl Drivers { /// Create certificate chain and store in Drivers #[cfg_attr(not(feature = "no-cfi"), cfi_impl_fn)] fn create_cert_chain(drivers: &mut Drivers) -> CaliptraResult<()> { - let data_vault = &drivers.data_vault; let persistent_data = &drivers.persistent_data; let mut cert = [0u8; MAX_CERT_CHAIN_SIZE]; // Write ldev_id cert to cert chain. - let ldevid_cert_size = - dice::copy_ldevid_cert(data_vault, persistent_data.get(), &mut cert)?; + let ldevid_cert_size = dice::copy_ldevid_cert(persistent_data.get(), &mut cert)?; if ldevid_cert_size > cert.len() { return Err(CaliptraError::RUNTIME_LDEV_ID_CERT_TOO_BIG); } // Write fmc alias cert to cert chain. - let fmcalias_cert_size = dice::copy_fmc_alias_cert( - data_vault, - persistent_data.get(), - &mut cert[ldevid_cert_size..], - )?; + let fmcalias_cert_size = + dice::copy_fmc_alias_cert(persistent_data.get(), &mut cert[ldevid_cert_size..])?; if ldevid_cert_size + fmcalias_cert_size > cert.len() { return Err(CaliptraError::RUNTIME_FMC_ALIAS_CERT_TOO_BIG); } diff --git a/runtime/src/fips.rs b/runtime/src/fips.rs index 148e2609e7..796ee40201 100644 --- a/runtime/src/fips.rs +++ b/runtime/src/fips.rs @@ -117,7 +117,7 @@ pub mod fips_self_test_cmd { soc_ifc: &mut env.soc_ifc, ecc384: &mut env.ecc384, mldsa87: &mut env.mldsa87, - data_vault: &mut env.data_vault, + data_vault: &env.persistent_data.get().data_vault, pcr_bank: &mut env.pcr_bank, image: env.mbox.raw_mailbox_contents(), }; diff --git a/runtime/src/handoff.rs b/runtime/src/handoff.rs index 7e763f2f9b..465b7fc92c 100644 --- a/runtime/src/handoff.rs +++ b/runtime/src/handoff.rs @@ -12,7 +12,7 @@ Abstract: --*/ -use caliptra_common::DataStore::{DataVaultNonSticky4, DataVaultSticky4, KeyVaultSlot}; +use caliptra_common::DataStore::KeyVaultSlot; use caliptra_drivers::{hand_off::DataStore, DataVault, FirmwareHandoffTable, KeyId}; use caliptra_error::{CaliptraError, CaliptraResult}; @@ -22,23 +22,6 @@ pub struct RtHandoff<'a> { } impl RtHandoff<'_> { - /// Retrieve the value from a DataStore - /// - /// # Arguments - /// - /// * `ds` - DataStore - /// - /// # Returns - /// - /// * `u32` - The value in `ds` - fn read_from_ds(&self, ds: DataStore) -> CaliptraResult { - match ds { - DataVaultNonSticky4(dv_entry) => Ok(self.data_vault.read_warm_reset_entry4(dv_entry)), - DataVaultSticky4(dv_entry) => Ok(self.data_vault.read_cold_reset_entry4(dv_entry)), - _ => Err(CaliptraError::RUNTIME_INTERNAL), - } - } - fn read_as_kv(&self, ds: DataStore) -> CaliptraResult { match ds { KeyVaultSlot(key_id) => Ok(key_id), @@ -47,21 +30,18 @@ impl RtHandoff<'_> { } /// Retrieve runtime SVN. - pub fn rt_svn(&self) -> CaliptraResult { - self.read_from_ds(self.fht.rt_svn_dv_hdl.try_into()?) - .map_err(|_| CaliptraError::RUNTIME_RT_SVN_HANDOFF_FAILED) + pub fn rt_svn(&self) -> u32 { + self.data_vault.rt_svn() } /// Retrieve runtime minimum SVN. - pub fn rt_min_svn(&self) -> CaliptraResult { - self.read_from_ds(self.fht.rt_min_svn_dv_hdl.try_into()?) - .map_err(|_| CaliptraError::RUNTIME_RT_MIN_SVN_HANDOFF_FAILED) + pub fn rt_min_svn(&self) -> u32 { + self.data_vault.rt_min_svn() } /// Retrieve FMC SVN. - pub fn fmc_svn(&self) -> CaliptraResult { - self.read_from_ds(self.fht.fmc_svn_dv_hdl.try_into()?) - .map_err(|_| CaliptraError::RUNTIME_FMC_SVN_HANDOFF_FAILED) + pub fn fmc_svn(&self) -> u32 { + self.data_vault.fmc_svn() } /// Retrieve the RT FW hash chain. diff --git a/runtime/src/info.rs b/runtime/src/info.rs index 4bcf205bb2..029447a6ec 100644 --- a/runtime/src/info.rs +++ b/runtime/src/info.rs @@ -24,13 +24,13 @@ impl FwInfoCmd { let pdata = drivers.persistent_data.get(); let handoff = RtHandoff { - data_vault: &drivers.data_vault, + data_vault: &pdata.data_vault, fht: &pdata.fht, }; - let runtime_svn = handoff.rt_svn()?; - let min_runtime_svn = handoff.rt_min_svn()?; - let fmc_manifest_svn = handoff.fmc_svn()?; + let runtime_svn = handoff.rt_svn(); + let min_runtime_svn = handoff.rt_min_svn(); + let fmc_manifest_svn = handoff.fmc_svn(); let rom_info = handoff.fht.rom_info_addr.get()?; Ok(MailboxResp::FwInfo(FwInfoResp { diff --git a/test/tests/caliptra_integration_tests/smoke_test.rs b/test/tests/caliptra_integration_tests/smoke_test.rs index e2223fbd89..643042fb49 100644 --- a/test/tests/caliptra_integration_tests/smoke_test.rs +++ b/test/tests/caliptra_integration_tests/smoke_test.rs @@ -293,7 +293,7 @@ fn smoke_test() { hasher.update(&[security_state.device_lifecycle() as u8]); hasher.update(&[security_state.debug_locked() as u8]); hasher.update(&[fuses.anti_rollback_disable as u8]); - hasher.update(/*ecc_vendor_pk_index=*/ &[0u8]); // No keys are revoked + hasher.update(/*vendor_ecc_pk_index=*/ &[0u8]); // No keys are revoked hasher.update(&[image.manifest.header.vendor_pqc_pub_key_idx as u8]); hasher.update(&[image.manifest.pqc_key_type]); hasher.update(&[true as u8]); From 5f88202d1c176f91c1c15a68952faab977aa5400 Mon Sep 17 00:00:00 2001 From: Christopher Swenson Date: Tue, 17 Dec 2024 22:39:13 -0800 Subject: [PATCH 50/51] emulator: Decode PMP NAPOT addresses correctly (#1858) Decoding NAPOT (natural power of 2) PMP regions involves some bit twiddly math, and the current code did it incorrectly, which I discovered when testing against a Tock library. I added some tests for the function as well. --- sw-emulator/lib/cpu/src/csr_file.rs | 52 ++++++++++++++++++++++++----- 1 file changed, 43 insertions(+), 9 deletions(-) diff --git a/sw-emulator/lib/cpu/src/csr_file.rs b/sw-emulator/lib/cpu/src/csr_file.rs index 858d2f95ab..bc4ee59c8f 100644 --- a/sw-emulator/lib/cpu/src/csr_file.rs +++ b/sw-emulator/lib/cpu/src/csr_file.rs @@ -73,13 +73,13 @@ impl Csr { /// PMP configuration register range start, inclusive pub const PMPCFG_START: RvAddr = 0x3A0; /// PMP configuration register range end, inclusive - pub const PMPCFG_END: RvAddr = 0x3A3; + pub const PMPCFG_END: RvAddr = 0x3AF; /// PMP address register range start, inclusive pub const PMPADDR_START: RvAddr = 0x3B0; /// PMP address register range end, inclusive - pub const PMPADDR_END: RvAddr = 0x3C0; + pub const PMPADDR_END: RvAddr = 0x3EF; /// Number of PMP address/cfg registers - pub const PMPCOUNT: usize = 16; + pub const PMPCOUNT: usize = 64; /// Create a new Configurations and Status register /// @@ -669,8 +669,9 @@ impl CsrFile { return Ok(false); } + let addr = addr as u64; let pmpaddr = self.any_read(RvPrivMode::M, Csr::PMPADDR_START + index as RvAddr)?; - let pmpaddr_shift = pmpaddr << 2; + let pmpaddr_shift = (pmpaddr as u64) << 2; let addr_top; let addr_bottom; @@ -680,7 +681,9 @@ impl CsrFile { // otherwise it's the previous one addr_top = pmpaddr_shift; addr_bottom = if index > 0 { - self.any_read(RvPrivMode::M, Csr::PMPADDR_START + (index - 1) as RvAddr)? << 2 + (self.any_read(RvPrivMode::M, Csr::PMPADDR_START + (index - 1) as RvAddr)? + as u64) + << 2 } else { 0 }; @@ -691,13 +694,12 @@ impl CsrFile { addr_bottom = pmpaddr_shift; } RvPmpAddrMode::Napot => { - // Range from 8..32 - addr_top = pmpaddr_shift + (1 << (pmpaddr.trailing_ones() + 3)); - addr_bottom = pmpaddr_shift; + let (bot, top) = decode_napot_pmpaddr(pmpaddr); + addr_bottom = bot; + addr_top = top; } _ => unreachable!(), } - Ok(addr >= addr_bottom && addr < addr_top) } @@ -748,11 +750,43 @@ impl CsrFile { } } +// Returns the base address (inclusive) and end address (exclusive) of a NAPOT PMP address +fn decode_napot_pmpaddr(addr: u32) -> (u64, u64) { + let bits = addr.trailing_ones(); + let addr = addr as u64; + let base = (addr & !((1 << bits) - 1)) << 2; + (base, base + (1 << (bits + 3))) +} + #[cfg(test)] mod tests { use super::*; + #[test] + fn test_decode_napot_pmpaddr() { + assert_eq!((0x0000_0000, 0x0000_0008), decode_napot_pmpaddr(0x00000000)); + assert_eq!((0x0000_0000, 0x0000_0010), decode_napot_pmpaddr(0x00000001)); + assert_eq!((0x0040_0000, 0x0040_8000), decode_napot_pmpaddr(0x00100fff)); + assert_eq!((0x1000_0000, 0x2000_0000), decode_napot_pmpaddr(0x05ffffff)); + assert_eq!( + (0x0000_0000, 0x1_0000_0000), + decode_napot_pmpaddr(0x1fffffff) + ); + assert_eq!( + (0x0000_0000, 0x2_0000_0000), + decode_napot_pmpaddr(0x3fffffff) + ); + assert_eq!( + (0x0000_0000, 0x4_0000_0000), + decode_napot_pmpaddr(0x7fffffff) + ); + assert_eq!( + (0x0000_0000, 0x8_0000_0000), + decode_napot_pmpaddr(0xffffffff) + ); + } + #[test] fn test_u_mode_read_m_mode_csr() { let clock = Clock::new(); From 1186ca861270169dbbdb249845eaa1108be85190 Mon Sep 17 00:00:00 2001 From: Arthur Heymans Date: Thu, 19 Dec 2024 03:25:34 +0100 Subject: [PATCH 51/51] Fix driver/dma: Operate on 64bit addresses (#1861) This fixes the driver side to operate on 64bit AXI addresses. --- drivers/src/dma.rs | 60 ++++++++++++++++------------ drivers/src/lib.rs | 4 +- drivers/test-fw/src/bin/dma_tests.rs | 17 +++++--- 3 files changed, 48 insertions(+), 33 deletions(-) diff --git a/drivers/src/dma.rs b/drivers/src/dma.rs index a2b8262757..6c15e8ef28 100644 --- a/drivers/src/dma.rs +++ b/drivers/src/dma.rs @@ -22,11 +22,26 @@ use zerocopy::AsBytes; pub enum DmaReadTarget { Mbox, AhbFifo, - AxiWr(usize), + AxiWr(AxiAddr), +} + +#[derive(Debug, Clone, Copy)] +pub struct AxiAddr { + pub lo: u32, + pub hi: u32, +} + +impl From for AxiAddr { + fn from(addr: u64) -> Self { + Self { + lo: addr as u32, + hi: (addr >> 32) as u32, + } + } } pub struct DmaReadTransaction { - pub read_addr: usize, + pub read_addr: AxiAddr, pub fixed_addr: bool, pub length: u32, pub target: DmaReadTarget, @@ -35,11 +50,11 @@ pub struct DmaReadTransaction { pub enum DmaWriteOrigin { Mbox, AhbFifo, - AxiRd(usize), + AxiRd(AxiAddr), } pub struct DmaWriteTransaction { - pub write_addr: usize, + pub write_addr: AxiAddr, pub fixed_addr: bool, pub length: u32, pub origin: DmaWriteOrigin, @@ -78,16 +93,13 @@ impl Dma { fn setup_dma_read(&mut self, read_transaction: DmaReadTransaction) { let dma = self.dma.regs_mut(); - let read_addr: usize = read_transaction.read_addr; - #[cfg(target_pointer_width = "64")] - dma.src_addr_h().write(|_| (read_addr >> 32) as u32); - dma.src_addr_l().write(|_| (read_addr & 0xffff_ffff) as u32); + let read_addr = read_transaction.read_addr; + dma.src_addr_l().write(|_| read_addr.lo); + dma.src_addr_h().write(|_| read_addr.hi); if let DmaReadTarget::AxiWr(target_addr) = read_transaction.target { - #[cfg(target_pointer_width = "64")] - dma.dst_addr_h().write(|_| (target_addr >> 32) as u32); - dma.dst_addr_l() - .write(|_| (target_addr & 0xffff_ffff) as u32); + dma.dst_addr_l().write(|_| target_addr.lo); + dma.dst_addr_h().write(|_| target_addr.hi); } dma.ctrl().modify(|c| { @@ -110,16 +122,12 @@ impl Dma { let dma = self.dma.regs_mut(); let write_addr = write_transaction.write_addr; - #[cfg(target_pointer_width = "64")] - dma.dst_addr_h().write(|_| (write_addr >> 32) as u32); - dma.dst_addr_l() - .write(|_| (write_addr & 0xffff_ffff) as u32); + dma.dst_addr_l().write(|_| write_addr.lo); + dma.dst_addr_h().write(|_| write_addr.hi); if let DmaWriteOrigin::AxiRd(origin_addr) = write_transaction.origin { - #[cfg(target_pointer_width = "64")] - dma.dst_addr_h().write(|_| (origin_addr >> 32) as u32); - dma.dst_addr_l() - .write(|_| (origin_addr & 0xffff_ffff) as u32); + dma.dst_addr_l().write(|_| origin_addr.lo); + dma.dst_addr_h().write(|_| origin_addr.hi); } dma.ctrl().modify(|c| { @@ -193,18 +201,18 @@ impl Dma { let status0 = dma.status0().read(); if status0.busy() { - return Err(CaliptraError::DRIVER_DMA_TRANSACTION_ALREADY_BUSY); + Err(CaliptraError::DRIVER_DMA_TRANSACTION_ALREADY_BUSY)?; } if status0.error() { - return Err(CaliptraError::DRIVER_DMA_TRANSACTION_ERROR); + Err(CaliptraError::DRIVER_DMA_TRANSACTION_ERROR)?; } dma.ctrl().modify(|c| c.go(true)); while dma.status0().read().busy() { if dma.status0().read().error() { - return Err(CaliptraError::DRIVER_DMA_TRANSACTION_ERROR); + Err(CaliptraError::DRIVER_DMA_TRANSACTION_ERROR)?; } } @@ -220,7 +228,7 @@ impl Dma { /// # Returns /// /// * `CaliptraResult` - Read value or error code - pub fn read_dword(&mut self, read_addr: usize) -> CaliptraResult { + pub fn read_dword(&mut self, read_addr: AxiAddr) -> CaliptraResult { let mut read_val: u32 = 0; self.flush(); @@ -248,7 +256,7 @@ impl Dma { /// # Returns /// /// * `CaliptraResult<()>` - Success or error code - pub fn write_dword(&mut self, write_addr: usize, write_val: u32) -> CaliptraResult<()> { + pub fn write_dword(&mut self, write_addr: AxiAddr, write_val: u32) -> CaliptraResult<()> { self.flush(); let write_transaction = DmaWriteTransaction { @@ -279,7 +287,7 @@ impl Dma { /// * `CaliptraResult<()>` - Success or error code pub fn transfer_payload_to_mbox( &mut self, - read_addr: usize, + read_addr: AxiAddr, payload_len_bytes: u32, fixed_addr: bool, block_size: u32, diff --git a/drivers/src/lib.rs b/drivers/src/lib.rs index b3c6d8b6c9..6632a03268 100644 --- a/drivers/src/lib.rs +++ b/drivers/src/lib.rs @@ -60,7 +60,9 @@ pub use bounded_address::{BoundedAddr, MemBounds, RomAddr}; pub use caliptra_error::{CaliptraError, CaliptraResult}; pub use csrng::{Csrng, HealthFailCounts as CsrngHealthFailCounts, Seed as CsrngSeed}; pub use data_vault::{ColdResetEntries, DataVault, WarmResetEntries}; -pub use dma::{Dma, DmaReadTarget, DmaReadTransaction, DmaWriteOrigin, DmaWriteTransaction}; +pub use dma::{ + AxiAddr, Dma, DmaReadTarget, DmaReadTransaction, DmaWriteOrigin, DmaWriteTransaction, +}; pub use doe::DeobfuscationEngine; pub use ecc384::{ Ecc384, Ecc384PrivKeyIn, Ecc384PrivKeyOut, Ecc384PubKey, Ecc384Result, Ecc384Scalar, diff --git a/drivers/test-fw/src/bin/dma_tests.rs b/drivers/test-fw/src/bin/dma_tests.rs index d87cc78b50..912d3e173e 100644 --- a/drivers/test-fw/src/bin/dma_tests.rs +++ b/drivers/test-fw/src/bin/dma_tests.rs @@ -15,7 +15,7 @@ Abstract: #![no_std] #![no_main] -use caliptra_drivers::{memory_layout, Dma, Mailbox}; +use caliptra_drivers::{memory_layout, AxiAddr, Dma, Mailbox}; use caliptra_registers::{axi_dma::AxiDmaReg, ecc::EccReg, mbox::MboxCsr}; use caliptra_test_harness::test_suite; use core::slice; @@ -27,7 +27,7 @@ fn test_dma_read_from_periph() { let ecc_regs = unsafe { EccReg::new() }; let ecc_name = ecc_regs.regs().name().ptr(); - let dword = dma.read_dword(ecc_name as usize).unwrap(); + let dword = dma.read_dword(AxiAddr::from(ecc_name as u64)).unwrap(); assert_eq!(dword.to_ne_bytes(), [0x70, 0x63, 0x65, 0x73]); // secp } @@ -40,8 +40,8 @@ fn test_dma_write_to_periph() { let data: u32 = 0xdead_beef; - dma.write_dword(ecc_iv as usize, data).unwrap(); - let dword = dma.read_dword(ecc_iv as usize).unwrap(); + dma.write_dword(AxiAddr::from(ecc_iv as u64), data).unwrap(); + let dword = dma.read_dword(AxiAddr::from(ecc_iv as u64)).unwrap(); assert_eq!(dword, data); } @@ -59,8 +59,13 @@ fn test_read_rri_to_mailbox() { let mut txn = mbox_driver.try_start_send_txn().unwrap(); txn.send_request(0xdead_beef, b"").unwrap(); - dma.transfer_payload_to_mbox(rri_regs, test_image.len() as u32, true, block_size) - .unwrap(); + dma.transfer_payload_to_mbox( + AxiAddr::from(rri_regs as u64), + test_image.len() as u32, + true, + block_size, + ) + .unwrap(); let mbox_fifo = unsafe { slice::from_raw_parts(