diff --git a/libs/ec-slimloader-mcxa/src/board.rs b/libs/ec-slimloader-mcxa/src/board.rs index 15890de..255cf58 100644 --- a/libs/ec-slimloader-mcxa/src/board.rs +++ b/libs/ec-slimloader-mcxa/src/board.rs @@ -19,7 +19,6 @@ use embassy_mcxa::rom::NbootBoolValue; use embassy_sync::blocking_mutex::raw::NoopRawMutex; use embedded_storage_async::nor_flash::{ErrorType, NorFlash, NorFlashErrorKind, ReadNorFlash}; use heapless::Vec; -use mcxa_ifr::{LifeCycleState, SecBootEn}; use mcxa_security_provisioning::Provisioner; use partition_manager::{Partition, PartitionManager, RO, RW}; use static_cell::StaticCell; @@ -638,8 +637,7 @@ impl Board for Mcxa { } let Err(if_result) = protected_if::<{ NbootBoolValue::True as u32 }, _, _, _>( - || match verification::verify_authenticity(self.sgi.reborrow(), image_base, || Self::dev_mode() as u32) - { + || match verification::verify_authenticity(self.sgi.reborrow(), image_base, || Self::dev_mode()) { Ok(result) => result as u32, Err(error) => error as u32, // Error has no overlap in value with Nboot bool, so this is safe to do }, @@ -666,17 +664,37 @@ impl Mcxa { } /// Check if the device authenticity should be checked in dev mode (where the keys are self-generated instead of taken from the programmed value) - fn dev_mode() -> bool { + /// Dev mode is active when the returned value is [DEV_VAL] + fn dev_mode() -> u32 { let ifr = unsafe { mcxa_ifr::IFR::current() }; - let secure_boot_enabled = ifr.cmpa.secure_boot_cfg.sec_boot_en() != SecBootEn::OnlyPki; - let develop_lifecycle = ifr.cfpa.header.cfpa_lc_state() == Ok(LifeCycleState::Develop); - // Don't enable dev mode if secure boot is active. That way a flashed key can be tested - develop_lifecycle && !secure_boot_enabled + + let secure_boot_cfg_ptr = &raw const ifr.cmpa.secure_boot_cfg; + + // Read secure boot twice to harden against fault injection where they saturate a register + let secure_boot1 = unsafe { secure_boot_cfg_ptr.read_volatile() } + .sec_boot_en() + .raw_value() + .value() as u32; + let secure_boot2 = unsafe { secure_boot_cfg_ptr.read_volatile() } + .sec_boot_en() + .raw_value() + .value() as u32; + + let lifecycle = match ifr.cfpa.header.cfpa_lc_state() { + Ok(val) => val.raw_value(), + Err(e) => e, + } as u32; + let inv_lifecycle = match ifr.cfpa.header.inv_cfpa_lc_state() { + Ok(val) => val.raw_value(), + Err(e) => e, + } as u32; + + (secure_boot1 << 24) | (secure_boot2 << 16) | (lifecycle << 8) | (inv_lifecycle) } /// Check if the secure boot settings are good fn follows_policy() -> bool { - if Self::dev_mode() { + if Self::dev_mode() == DEV_VAL { true } else { unsafe { Provisioner::new_from_page(true) } @@ -686,6 +704,12 @@ impl Mcxa { } } +pub const DEV_VAL: u32 = 0b00000011_00000011_00000011_11111100; +// SecSecBootEn::OnlyPki ------- ^^ +// SecSecBootEn::OnlyPki ---------------- ^^ +// LifeCycleState::Develop ----------------- ^^^^^^^^ +// InvLifeCycleState::Develop ----------------------- ^^^^^^^^ + #[cfg(test)] mod tests { use super::*; diff --git a/libs/ec-slimloader-mcxa/src/verification.rs b/libs/ec-slimloader-mcxa/src/verification.rs index 36e0f8c..1eae712 100644 --- a/libs/ec-slimloader-mcxa/src/verification.rs +++ b/libs/ec-slimloader-mcxa/src/verification.rs @@ -9,6 +9,7 @@ use fault_rejection::protected_if; use mcxa_ifr::{IFR, RotkEn, RotkUsageVal}; use mcxa_security_provisioning::certificate::derive_image_rkth_pair; +use crate::board::DEV_VAL; use crate::error::map_nboot_status_to_boot_error; fn load_nboot_auth_parms_from_ifr(ifr: &IFR) -> Result { @@ -83,7 +84,7 @@ pub fn verify_authenticity<'d>( defmt_or_log::trace!("Initializing NBOOT context"); let mut n_boot_api = embassy_mcxa::rom::get().nboot().map_err(|_| BootError::Authenticate)?; - let result = protected_if::<{ true as u32 }, Result<(), BootError>, _, _>(dev_mode, || { + let result = protected_if::, _, _>(dev_mode, || { // In dev mode, we're going to lie to nboot and derive the rkth's ourselves so they're always correct // This makes the provisioning process easier. Once no longer in dev mode, this branch is not taken and // only the flashed keys are used