From a9ad8a6edbeb25643d88f25f24e35270296470fd Mon Sep 17 00:00:00 2001 From: Nick Quarton <139178705+nquarton@users.noreply.github.com> Date: Tue, 15 Oct 2024 13:28:15 -0400 Subject: [PATCH] Reject mbx commands from 0xFFFFFFFF pauser in both ROM and runtime --- FROZEN_IMAGES.sha384sum | 4 +-- drivers/src/mailbox.rs | 6 +++++ error/src/lib.rs | 2 ++ rom/dev/src/flow/cold_reset/fw_processor.rs | 8 ++++++ .../test_mailbox_errors.rs | 24 ++++++++++++++++++ runtime/src/lib.rs | 7 ++++++ .../runtime_integration_tests/test_mailbox.rs | 25 +++++++++++++++++++ 7 files changed, 74 insertions(+), 2 deletions(-) diff --git a/FROZEN_IMAGES.sha384sum b/FROZEN_IMAGES.sha384sum index 3019b7572c..6b4d5d9475 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 -c34775cd25fa7d601b6eba2d53a22ac880acfb619db0249f9aa540b8d015422b126b5bdf24af71bee0c0a838cdbcdd87 caliptra-rom-no-log.bin -43b02b420fcd8c0f220dd3f1dc32ca47034afbea08ac27ac66582b5ddf984af7b17f98d239fa367ad3910f8ad37a0a58 caliptra-rom-with-log.bin +91b951fbe655919a1e123b86add18ab604d049f6d2b2bbefac4cd554a4411eaf22247973c47490e243b9a5b1d197feb3 caliptra-rom-no-log.bin +105cda4bbc0f2f0096d058eda9090670da0d90c8e3066cb44027843e9a490db61933b524ca78fe78351a7fd26a124c03 caliptra-rom-with-log.bin diff --git a/drivers/src/mailbox.rs b/drivers/src/mailbox.rs index e6ee0e2569..df84d7bee6 100644 --- a/drivers/src/mailbox.rs +++ b/drivers/src/mailbox.rs @@ -267,6 +267,12 @@ impl<'a> MailboxRecvPeek<'a> { mbox.cmd().read() } + /// Returns the value stored in the user register + pub fn user(&self) -> u32 { + let mbox = self.mbox.regs(); + mbox.user().read() + } + /// Returns the value stored in the data length register. This is the total /// size of the mailbox data in bytes. pub fn dlen(&self) -> u32 { diff --git a/error/src/lib.rs b/error/src/lib.rs index 05848f07c6..7d94ae0834 100644 --- a/error/src/lib.rs +++ b/error/src/lib.rs @@ -440,6 +440,7 @@ impl CaliptraError { CaliptraError::new_const(0x000E004D); 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); /// FMC Errors pub const FMC_GLOBAL_NMI: CaliptraError = CaliptraError::new_const(0x000F0001); @@ -495,6 +496,7 @@ impl CaliptraError { pub const FW_PROC_MAILBOX_PROCESS_FAILURE: CaliptraError = CaliptraError::new_const(0x01020007); 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); /// FMC Alias Layer : Certificate Verification Failure. pub const FMC_ALIAS_CERT_VERIFY: CaliptraError = CaliptraError::new_const(0x01030001); diff --git a/rom/dev/src/flow/cold_reset/fw_processor.rs b/rom/dev/src/flow/cold_reset/fw_processor.rs index 8a29b44298..f9aadebbe0 100644 --- a/rom/dev/src/flow/cold_reset/fw_processor.rs +++ b/rom/dev/src/flow/cold_reset/fw_processor.rs @@ -40,6 +40,8 @@ use core::mem::ManuallyDrop; use zerocopy::{AsBytes, LayoutVerified}; use zeroize::Zeroize; +const RESERVED_PAUSER: u32 = 0xFFFFFFFF; + #[derive(Debug, Default, Zeroize)] pub struct FwProcInfo { pub fmc_cert_valid_not_before: NotBefore, @@ -185,6 +187,12 @@ impl FirmwareProcessor { if let Some(txn) = mbox.peek_recv() { report_fw_error_non_fatal(0); + + // Drop all commands for invalid PAUSER + if txn.user() == RESERVED_PAUSER { + return Err(CaliptraError::FW_PROC_MAILBOX_RESERVED_PAUSER); + } + cprintln!("[fwproc] Received command 0x{:08x}", txn.cmd()); // Handle FW load as a separate case due to the re-borrow explained below 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 21404e3546..b9dd96a036 100644 --- a/rom/dev/tests/rom_integration_tests/test_mailbox_errors.rs +++ b/rom/dev/tests/rom_integration_tests/test_mailbox_errors.rs @@ -151,3 +151,27 @@ fn test_mailbox_invalid_req_size_zero() { )) ); } + +#[test] +// Changing PAUSER not supported on sw emulator +#[cfg(any(feature = "verilator", feature = "fpga_realtime"))] +fn test_mailbox_reserved_pauser() { + let (mut hw, _image_bundle) = + helpers::build_hw_model_and_image_bundle(Fuses::default(), ImageOptions::default()); + + // Set pauser to the reserved value + hw.set_apb_pauser(0xffffffff); + + // Send anything + assert_eq!( + hw.mailbox_execute(0x0, &[]), + Err(ModelError::MailboxCmdFailed( + CaliptraError::FW_PROC_MAILBOX_RESERVED_PAUSER.into() + )) + ); + + hw.step_until_fatal_error( + CaliptraError::FW_PROC_MAILBOX_RESERVED_PAUSER.into(), + MAX_WAIT_CYCLES, + ); +} diff --git a/runtime/src/lib.rs b/runtime/src/lib.rs index 6d4dce49cb..83959dd920 100644 --- a/runtime/src/lib.rs +++ b/runtime/src/lib.rs @@ -113,6 +113,8 @@ pub const PL0_PAUSER_FLAG: u32 = 1; pub const PL0_DPE_ACTIVE_CONTEXT_THRESHOLD: usize = 16; pub const PL1_DPE_ACTIVE_CONTEXT_THRESHOLD: usize = 16; +const RESERVED_PAUSER: u32 = 0xFFFFFFFF; + pub struct CptraDpeTypes; impl DpeTypes for CptraDpeTypes { @@ -150,6 +152,11 @@ fn enter_idle(drivers: &mut Drivers) { /// /// * `MboxStatusE` - the mailbox status (DataReady when we send a response) fn handle_command(drivers: &mut Drivers) -> CaliptraResult { + // Drop all commands for invalid PAUSER + if drivers.mbox.user() == RESERVED_PAUSER { + return Err(CaliptraError::RUNTIME_CMD_RESERVED_PAUSER); + } + // For firmware update, don't read data from the mailbox if drivers.mbox.cmd() == CommandId::FIRMWARE_LOAD { cfi_assert_eq(drivers.mbox.cmd(), CommandId::FIRMWARE_LOAD); diff --git a/runtime/tests/runtime_integration_tests/test_mailbox.rs b/runtime/tests/runtime_integration_tests/test_mailbox.rs index ed2ef24f59..2872499027 100644 --- a/runtime/tests/runtime_integration_tests/test_mailbox.rs +++ b/runtime/tests/runtime_integration_tests/test_mailbox.rs @@ -56,3 +56,28 @@ fn test_unimplemented_cmds() { resp, ); } + +#[test] +// 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); + + model.step_until(|m| m.soc_mbox().status().read().mbox_fsm_ps().mbox_idle()); + + // Set pauser to the reserved value + model.set_apb_pauser(0xffffffff); + + // Send anything + let payload = MailboxReqHeader { + chksum: caliptra_common::checksum::calc_checksum(u32::from(CommandId::VERSION), &[]), + }; + let resp = model + .mailbox_execute(u32::from(CommandId::VERSION), payload.as_bytes()) + .unwrap_err(); + assert_error( + &mut model, + caliptra_drivers::CaliptraError::RUNTIME_CMD_RESERVED_PAUSER, + resp, + ); +}