diff --git a/bao1x-boot/boot1/src/platform/bao1x/slots.rs b/bao1x-boot/boot1/src/platform/bao1x/slots.rs index 93ac6e026..216888f3e 100644 --- a/bao1x-boot/boot1/src/platform/bao1x/slots.rs +++ b/bao1x-boot/boot1/src/platform/bao1x/slots.rs @@ -162,10 +162,6 @@ fn check_and_fix_acls(rram: &mut Reram, slot_mgr: &mut SlotManager, slot_list: & let mut is_consistent = true; let mut acl = match slot_mgr.get_acl(&slot_element) { Ok(settings) => settings, - Err(bao1x_api::AccessError::KeyAclInconsistency(prototype)) => { - is_consistent = false; - AccessSettings::Key(prototype) - } Err(bao1x_api::AccessError::DataAclInconsistency(prototype)) => { is_consistent = false; AccessSettings::Data(prototype) @@ -175,12 +171,6 @@ fn check_and_fix_acls(rram: &mut Reram, slot_mgr: &mut SlotManager, slot_list: & let (pa, rw) = slot_element.get_access_spec(); let is_correct = match acl { AccessSettings::Data(sa) => sa.get_partition_access() == pa && sa.get_rw_permissions() == rw, - AccessSettings::Key(sa) => { - // crate::println!("sa.pa {:x?} pa {:x?}", sa.get_partition_access(), pa); - // crate::println!("sa.rw {:x?} rw {:x?}", sa.get_rw_permissions(), rw); - // crate::println!("sa.akeyid: {:x}", sa.akey_id()); - sa.get_partition_access() == pa && sa.get_rw_permissions() == rw && sa.akey_id() == 0xFF - } }; if !is_correct || !is_consistent { crate::println!( @@ -195,14 +185,14 @@ fn check_and_fix_acls(rram: &mut Reram, slot_mgr: &mut SlotManager, slot_list: & sa.set_partition_access(&pa); sa.set_rw_permissions(rw); } - AccessSettings::Key(sa) => { - sa.set_partition_access(&pa); - sa.set_rw_permissions(rw); - sa.set_akey_id(0xFF); // 0xff disables key chaining to access the key + } + crate::println!("Writing ACL raw value: {:x?}", acl); + match slot_mgr.set_acl(rram, slot_element, &acl) { + Ok(_) => {} + Err(e) => { + crate::println!("Couldn't set ACL for {:?} ({:?})", slot_element, e); } } - crate::println!("Fixed ACL raw value: {:x?}", acl); - slot_mgr.set_acl(rram, slot_element, &acl).unwrap(); } } } @@ -236,16 +226,6 @@ fn print_slots(slot_mgr: &SlotManager, slot_list: &[SlotIndex]) { bytes ); }, - SlotType::Key => unsafe { - let bytes = slot_mgr.read_key_slot(data_index); - let acl = slot_mgr.get_key_acl(acl_index); - crate::println!( - " Key {} ({:x?}): {:x?}", - data_index / SLOT_ELEMENT_LEN_BYTES, - acl, - bytes - ); - }, } } } diff --git a/libs/bao1x-api/src/offsets.rs b/libs/bao1x-api/src/offsets.rs index 3685693c5..1e7fd3e0e 100644 --- a/libs/bao1x-api/src/offsets.rs +++ b/libs/bao1x-api/src/offsets.rs @@ -7,9 +7,6 @@ use core::ops::Range; use arbitrary_int::{Number, u4}; use bitbybit::bitfield; -pub const KEY_SLOT_START: usize = 0x603F_0000; -pub const KEY_SLOT_LEN: usize = 0x1_0000; -pub const MAX_KEY_SLOTS: usize = KEY_SLOT_LEN / SLOT_ELEMENT_LEN_BYTES; pub const DATA_SLOT_START: usize = 0x603E_0000; pub const DATA_SLOT_LEN: usize = 0x1_0000; pub const MAX_DATA_SLOTS: usize = DATA_SLOT_LEN / SLOT_ELEMENT_LEN_BYTES; @@ -17,10 +14,6 @@ pub const SLOT_ELEMENT_LEN_BYTES: usize = 256 / 8; pub const ACRAM_DATASLOT_START: usize = 0x603D_C000; pub const ACRAM_DATASLOT_LEN: usize = 0x2000; -pub const ACRAM_KEYSLOT_START: usize = 0x603D_E000; -pub const ACRAM_KEYSLOT_LEN: usize = 0x2000; -// pub const ACRAM_GKEYSLOT_START: usize = 0x603D_E400; // This is mentioned in the docs but I don't see it in -// the code? pub const IFR_BASE: usize = 0x6040_0000; pub const IFR_LEN: usize = 0x400; /// This number is special: it only appears during certain portions of the chip life cycle in @@ -101,79 +94,6 @@ impl DataSlotAccess { } } -#[bitfield(u32)] -#[derive(PartialEq, Eq, Debug)] -pub struct KeySlotAccess { - #[bits(24..=31, rw)] - akey_id: u8, - #[bit(23, rw)] - fw1: bool, - #[bit(22, rw)] - fw0: bool, - #[bit(21, rw)] - boot1: bool, - #[bit(20, rw)] - boot0: bool, - #[bits(8..=15, rw)] - seg_id: u8, - #[bit(3, rw)] - sce_wr_dis: bool, - #[bit(2, rw)] - sce_rd_dis: bool, - #[bit(1, rw)] - core_wr_dis: bool, - #[bit(0, rw)] - core_rd_dis: bool, -} - -impl KeySlotAccess { - // This method is only valid in no-std currently. Not sure if there is even meaning for us - // to access this in the Xous environment, as this is primarily a secure boot construct - #[cfg(not(feature = "std"))] - pub fn get_entry(slot: usize) -> Self { - let slot_array = - unsafe { core::slice::from_raw_parts(ACRAM_KEYSLOT_START as *const KeySlotAccess, 2048) }; - slot_array[slot] - } - - pub fn get_partition_access(&self) -> PartitionAccess { PartitionAccess::from_raw_u32(self.raw_value()) } - - pub fn set_partition_access(&mut self, pa: &PartitionAccess) { - *self = Self::new_with_raw_value((self.raw_value() & !(0xf << 20)) | (pa.to_raw_u4().as_u32() << 20)); - } - - pub fn get_rw_permissions(&self) -> RwPerms { - match [self.core_rd_dis(), self.core_wr_dis()] { - [true, true] => RwPerms::Denied, - [false, true] => RwPerms::ReadOnly, - [true, false] => RwPerms::WriteOnly, - [false, false] => RwPerms::ReadWrite, - } - } - - pub fn set_rw_permissions(&mut self, spec: RwPerms) { - match spec { - RwPerms::Denied => { - self.set_core_rd_dis(true); - self.set_core_wr_dis(true); - } - RwPerms::ReadOnly => { - self.set_core_rd_dis(false); - self.set_core_wr_dis(true); - } - RwPerms::WriteOnly => { - self.set_core_rd_dis(true); - self.set_core_wr_dis(false); - } - RwPerms::ReadWrite => { - self.set_core_rd_dis(false); - self.set_core_wr_dis(false); - } - RwPerms::Unspecified => panic!("RwPerms must be specified"), - } - } -} - #[derive(PartialEq, Eq, Clone, Copy, Debug)] pub enum AccessError { /// Access is anticipated to be denied by the hardware. Users can attempt to still @@ -196,7 +116,6 @@ pub enum AccessError { /// Returned when a set of slots that should have the same ACL don't. The value /// inside is the value of the first ACL in the set. DataAclInconsistency(DataSlotAccess), - KeyAclInconsistency(KeySlotAccess), } /// Enum to specify read/write permissions to a given slot. @@ -279,28 +198,22 @@ impl PartitionAccess { pub enum SlotIndex { Data(usize, PartitionAccess, RwPerms), DataRange(Range, PartitionAccess, RwPerms), - Key(usize, PartitionAccess, RwPerms), - KeyRange(Range, PartitionAccess, RwPerms), } #[derive(PartialEq, Eq, Clone, Debug)] pub enum SlotType { Data, - Key, } impl SlotIndex { pub fn get_access_spec(&self) -> (PartitionAccess, RwPerms) { match self { Self::Data(_, spec, rw) => (*spec, *rw), Self::DataRange(_, spec, rw) => (*spec, *rw), - Self::Key(_, spec, rw) => (*spec, *rw), - Self::KeyRange(_, spec, rw) => (*spec, *rw), } } pub fn get_type(&self) -> SlotType { match self { Self::Data(_, _, _) | Self::DataRange(_, _, _) => SlotType::Data, - Self::Key(_, _, _) | Self::KeyRange(_, _, _) => SlotType::Key, } } @@ -308,8 +221,6 @@ impl SlotIndex { match self { Self::Data(base, _, _) => *base, Self::DataRange(range, _, _) => range.start, - Self::Key(base, _, _) => *base, - Self::KeyRange(range, _, _) => range.start, } } @@ -317,8 +228,6 @@ impl SlotIndex { match self { Self::Data(_, _, _) => 1, Self::DataRange(range, _, _) => range.len(), - Self::Key(_, _, _) => 1, - Self::KeyRange(range, _, _) => range.len(), } } @@ -333,13 +242,6 @@ impl SlotIndex { Err(AccessError::OutOfBounds) } } - Self::Key(index, _, _) => { - if *index < MAX_KEY_SLOTS { - Ok(*index * SLOT_ELEMENT_LEN_BYTES) - } else { - Err(AccessError::OutOfBounds) - } - } Self::DataRange(range, _, _) => { let index = range.start; if range.end <= MAX_DATA_SLOTS { @@ -348,14 +250,6 @@ impl SlotIndex { Err(AccessError::OutOfBounds) } } - Self::KeyRange(range, _, _) => { - let index = range.start; - if range.end <= MAX_KEY_SLOTS { - Ok(index * SLOT_ELEMENT_LEN_BYTES) - } else { - Err(AccessError::OutOfBounds) - } - } } } @@ -374,19 +268,6 @@ impl SlotIndex { } Ok(SlotOffsetIter::Range(range.clone().map(|idx| idx * SLOT_ELEMENT_LEN_BYTES))) } - Self::Key(index, _, _) => { - if *index < MAX_KEY_SLOTS { - Ok(SlotOffsetIter::Single(core::iter::once(*index * SLOT_ELEMENT_LEN_BYTES))) - } else { - Err(AccessError::OutOfBounds) - } - } - Self::KeyRange(range, _, _) => { - if range.end > MAX_KEY_SLOTS { - return Err(AccessError::OutOfBounds); - } - Ok(SlotOffsetIter::Range(range.clone().map(|idx| idx * SLOT_ELEMENT_LEN_BYTES))) - } } } @@ -399,13 +280,6 @@ impl SlotIndex { Err(AccessError::OutOfBounds) } } - Self::Key(index, _, _) => { - if *index < MAX_KEY_SLOTS { - Ok(*index * size_of::()) - } else { - Err(AccessError::OutOfBounds) - } - } Self::DataRange(range, _, _) => { if range.end <= MAX_DATA_SLOTS { Ok(range.start * size_of::()) @@ -413,13 +287,6 @@ impl SlotIndex { Err(AccessError::OutOfBounds) } } - Self::KeyRange(range, _, _) => { - if range.end <= MAX_KEY_SLOTS { - Ok(range.start * size_of::()) - } else { - Err(AccessError::OutOfBounds) - } - } } } @@ -440,19 +307,6 @@ impl SlotIndex { } Ok(SlotOffsetIter::Range(range.clone().map(|idx| idx * ACL_SIZE))) } - Self::Key(index, _, _) => { - if *index < MAX_KEY_SLOTS { - Ok(SlotOffsetIter::Single(core::iter::once(*index * ACL_SIZE))) - } else { - Err(AccessError::OutOfBounds) - } - } - Self::KeyRange(range, _, _) => { - if range.end > MAX_KEY_SLOTS { - return Err(AccessError::OutOfBounds); - } - Ok(SlotOffsetIter::Range(range.clone().map(|idx| idx * ACL_SIZE))) - } } } } diff --git a/libs/bao1x-api/src/offsets/baosec.rs b/libs/bao1x-api/src/offsets/baosec.rs index e0a00327e..d7bd88041 100644 --- a/libs/bao1x-api/src/offsets/baosec.rs +++ b/libs/bao1x-api/src/offsets/baosec.rs @@ -44,21 +44,21 @@ pub const DEFAULT_FCLK_FREQUENCY: u32 = 700_000_000; /// are derived from. The seed may be blended with other bits of data scattered about /// the RRAM array, other device identifiers and hardware measurements to create the final /// device secret key. -pub const ROOT_SEED: SlotIndex = SlotIndex::Key(256, PartitionAccess::Fw0, RwPerms::ReadWrite); +pub const ROOT_SEED: SlotIndex = SlotIndex::Data(256, PartitionAccess::Fw0, RwPerms::ReadWrite); /// The `RMA_KEY` is a secret parameter that is unique per-device secret which is recorded /// at manufacturing time. Its purpose is to facilitate the creation of a signed RMA /// authorization certificate which upon receipt would blank the device and unlock various /// features for debugging failed hardware. -pub const RMA_KEY: SlotIndex = SlotIndex::Key(257, PartitionAccess::Fw0, RwPerms::ReadWrite); +pub const RMA_KEY: SlotIndex = SlotIndex::Data(257, PartitionAccess::Fw0, RwPerms::ReadWrite); /// Reserved for use as a CP to FT tracking cookie. This is used to help track inventory /// between CP and FT, if such a feature is desired in the supply chain. Blanked on entry /// to developer mode. -pub const CP_COOKIE: SlotIndex = SlotIndex::Key(258, PartitionAccess::Fw0, RwPerms::ReadWrite); +pub const CP_COOKIE: SlotIndex = SlotIndex::Data(258, PartitionAccess::Fw0, RwPerms::ReadWrite); /// The swap encryption key. Used to protect swap images beyond the signing key, if we so desire. -pub const SWAP_KEY: SlotIndex = SlotIndex::Key(259, PartitionAccess::Fw0, RwPerms::ReadWrite); +pub const SWAP_KEY: SlotIndex = SlotIndex::Data(259, PartitionAccess::Fw0, RwPerms::ReadWrite); /// `NUISANCE_KEYS` are hashed together with `ROOT_SEED` to derive the core secret. /// Their primary purpose is to annoy microscopists trying to read the secret key by @@ -85,9 +85,9 @@ pub const SWAP_KEY: SlotIndex = SlotIndex::Key(259, PartitionAccess::Fw0, RwPerm /// numbered data slots. Some of the data slots in the first 8 slots will be read-only at CP time, and /// thus they can't be initialized with random data and be used as a nuisance key. This is a minor degradation /// in security margin. -pub const NUISANCE_KEYS_0: SlotIndex = SlotIndex::KeyRange(8..128, PartitionAccess::Fw0, RwPerms::ReadWrite); +pub const NUISANCE_KEYS_0: SlotIndex = SlotIndex::DataRange(8..128, PartitionAccess::Fw0, RwPerms::ReadWrite); pub const NUISANCE_KEYS_1: SlotIndex = - SlotIndex::KeyRange(1920..2048, PartitionAccess::Fw0, RwPerms::ReadWrite); + SlotIndex::DataRange(1920..2048, PartitionAccess::Fw0, RwPerms::ReadWrite); pub const NUISANCE_KEYS: [SlotIndex; 2] = [NUISANCE_KEYS_0, NUISANCE_KEYS_1]; /// `CHAFF_KEYS` are a bank of keys that are hashed into the key array, but instead of @@ -109,7 +109,7 @@ pub const NUISANCE_KEYS: [SlotIndex; 2] = [NUISANCE_KEYS_0, NUISANCE_KEYS_1]; /// the chaff is cleared, we also don't care as much about side channels since we're now operating /// in a fundamentally insecure regime (e.g. developer mode - you can just read out the data by /// running your own code on the device). -pub const CHAFF_KEYS: SlotIndex = SlotIndex::KeyRange(128..256, PartitionAccess::Fw0, RwPerms::ReadWrite); +pub const CHAFF_KEYS: SlotIndex = SlotIndex::DataRange(128..256, PartitionAccess::Fw0, RwPerms::ReadWrite); /// All the slots of concern located in a single iterator. The idea is that everything is /// condensed here and used to check for access integrity using the array below. @@ -127,4 +127,4 @@ pub const DATA_SLOTS: [SlotIndex; 8] = [ /// In addition to these KEY_SLOTS, the DEVELOPER_MODE one way counter is a security-important parameter /// that should be included as domain separation in any KDF. pub const KEY_SLOTS: [SlotIndex; 6] = - [ROOT_SEED, RMA_KEY, CP_COOKIE, NUISANCE_KEYS_0, NUISANCE_KEYS_1, CHAFF_KEYS]; + [CP_COOKIE, RMA_KEY, ROOT_SEED, NUISANCE_KEYS_0, NUISANCE_KEYS_1, CHAFF_KEYS]; diff --git a/libs/bao1x-hal/src/acram.rs b/libs/bao1x-hal/src/acram.rs index 310f444ab..1ebfc16d0 100644 --- a/libs/bao1x-hal/src/acram.rs +++ b/libs/bao1x-hal/src/acram.rs @@ -137,27 +137,23 @@ impl OneWayCounter { #[derive(PartialEq, Eq, Debug)] pub enum AccessSettings { Data(DataSlotAccess), - Key(KeySlotAccess), } impl AccessSettings { pub fn raw_u32(&self) -> u32 { match self { Self::Data(d) => d.raw_value(), - Self::Key(d) => d.raw_value(), } } pub fn allows_cpu_read(&self) -> bool { match self { Self::Data(d) => !d.core_rd_dis(), - Self::Key(d) => !d.core_rd_dis(), } } pub fn allows_cpu_write(&self) -> bool { match self { Self::Data(d) => !d.core_wr_dis(), - Self::Key(d) => !d.core_wr_dis(), } } @@ -165,7 +161,6 @@ impl AccessSettings { pub fn is_set_only(&self) -> bool { match self { Self::Data(d) => d.write_mode(), - Self::Key(_d) => false, } } } @@ -181,9 +176,11 @@ pub enum AccessType { pub struct SlotManager { data_range: xous::MemoryRange, data_acl_range: xous::MemoryRange, - key_range: xous::MemoryRange, - key_acl_range: xous::MemoryRange, user_id: CoreuserId, + #[cfg(feature = "std")] + data_write_offset: xous::MemoryRange, + #[cfg(feature = "std")] + data_acl_write_offset: xous::MemoryRange, } impl SlotManager { @@ -206,21 +203,13 @@ impl SlotManager { ) .expect("Couldn't map ACL range"); #[cfg(feature = "std")] - let key_range = xous::map_memory( - xous::MemoryAddress::new(KEY_SLOT_START), - None, - KEY_SLOT_LEN, - xous::MemoryFlags::R | xous::MemoryFlags::W, - ) - .expect("Couldn't map slot range"); + // safety: these ranges are valid and pre-aligned + let data_write_offset = unsafe { xous::MemoryRange::new(DATA_SLOT_START, DATA_SLOT_LEN).unwrap() }; #[cfg(feature = "std")] - let key_acl_range = xous::map_memory( - xous::MemoryAddress::new(ACRAM_KEYSLOT_START), - None, - ACRAM_KEYSLOT_LEN, - xous::MemoryFlags::R | xous::MemoryFlags::W, - ) - .expect("Couldn't map ACL range"); + // safety: these ranges are valid and pre-aligned + let data_acl_write_offset = + unsafe { xous::MemoryRange::new(ACRAM_DATASLOT_START, ACRAM_DATASLOT_LEN).unwrap() }; + #[cfg(not(feature = "std"))] // safety: these ranges are valid and pre-aligned let data_range = unsafe { xous::MemoryRange::new(DATA_SLOT_START, DATA_SLOT_LEN).unwrap() }; @@ -228,13 +217,6 @@ impl SlotManager { // safety: these ranges are valid and pre-aligned let data_acl_range = unsafe { xous::MemoryRange::new(ACRAM_DATASLOT_START, ACRAM_DATASLOT_LEN).unwrap() }; - #[cfg(not(feature = "std"))] - // safety: these ranges are valid and pre-aligned - let key_range = unsafe { xous::MemoryRange::new(KEY_SLOT_START, KEY_SLOT_LEN).unwrap() }; - #[cfg(not(feature = "std"))] - // safety: these ranges are valid and pre-aligned - let key_acl_range = - unsafe { xous::MemoryRange::new(ACRAM_KEYSLOT_START, ACRAM_KEYSLOT_LEN).unwrap() }; #[cfg(feature = "std")] let user_id = if xous::process::id() == crate::coreuser::TRUSTED_PID as u32 { @@ -246,15 +228,17 @@ impl SlotManager { #[cfg(not(feature = "std"))] let user_id = crate::coreuser::TRUSTED_USER; - Self { data_range, data_acl_range, key_range, key_acl_range, user_id } + #[cfg(not(feature = "std"))] + let ret = Self { data_range, data_acl_range, user_id }; + #[cfg(feature = "std")] + let ret = Self { data_range, data_acl_range, user_id, data_write_offset, data_acl_write_offset }; + ret } #[cfg(feature = "std")] pub fn register_mapping(&self, rram: &mut Reram) { rram.add_range(DATA_SLOT_START - utralib::HW_RERAM_MEM, self.data_range); rram.add_range(ACRAM_DATASLOT_START - utralib::HW_RERAM_MEM, self.data_acl_range); - rram.add_range(KEY_SLOT_START - utralib::HW_RERAM_MEM, self.key_range); - rram.add_range(ACRAM_KEYSLOT_START - utralib::HW_RERAM_MEM, self.key_acl_range); } pub fn read(&self, slot: &SlotIndex) -> Result<&[u8], AccessError> { @@ -269,15 +253,9 @@ impl SlotManager { SlotIndex::Data(_, _, _) => unsafe { &self.data_range.as_slice()[offset..offset + SLOT_ELEMENT_LEN_BYTES] }, - SlotIndex::Key(_, _, _) => unsafe { - &self.key_range.as_slice()[offset..offset + SLOT_ELEMENT_LEN_BYTES] - }, SlotIndex::DataRange(range, _, _) => unsafe { &self.data_range.as_slice()[offset..offset + SLOT_ELEMENT_LEN_BYTES * range.len()] }, - SlotIndex::KeyRange(range, _, _) => unsafe { - &self.key_range.as_slice()[offset..offset + SLOT_ELEMENT_LEN_BYTES * range.len()] - }, }) } else { Err(AccessError::AccessDenied) @@ -288,26 +266,22 @@ impl SlotManager { /// There is access or type checking done. This is a "raw read" primitive mostly used for debugging. pub unsafe fn read_data_slot(&self, absolute_offset: usize) -> &[u8] { let ptr: *const u8 = &self.data_range.as_slice::()[absolute_offset] as *const u8; - crate::println!("data loc: {:x}", ptr as usize); + crate::println!("data loc: {:x}, offset: {:x}", ptr as usize, absolute_offset); &self.data_range.as_slice()[absolute_offset..absolute_offset + SLOT_ELEMENT_LEN_BYTES] } - /// Safety: the caller must resolve the index into either the data or the key array correctly. - /// There is access or type checking done. This is a "raw read" primitive mostly used for debugging. - pub unsafe fn read_key_slot(&self, absolute_offset: usize) -> &[u8] { - let ptr: *const u8 = &self.key_range.as_slice::()[absolute_offset] as *const u8; - crate::println!("key loc: {:x}", ptr as usize); - &self.key_range.as_slice()[absolute_offset..absolute_offset + SLOT_ELEMENT_LEN_BYTES] - } - pub fn write(&self, writer: &mut Reram, slot: &SlotIndex, value: &[u8]) -> Result<(), AccessError> { let acl = self.get_acl(slot)?; if self.user_id.is_accessible(&acl, &AccessType::Write) { let offset = slot.try_into_data_offset()?; + #[cfg(not(feature = "std"))] let range = match slot { SlotIndex::Data(_, _, _) | SlotIndex::DataRange(_, _, _) => &self.data_range, - SlotIndex::Key(_, _, _) | SlotIndex::KeyRange(_, _, _) => &self.key_range, + }; + #[cfg(feature = "std")] + let range = match slot { + SlotIndex::Data(_, _, _) | SlotIndex::DataRange(_, _, _) => &self.data_write_offset, }; if value.len() != slot.len() * SLOT_ELEMENT_LEN_BYTES { @@ -322,6 +296,7 @@ impl SlotManager { if self.user_id.is_accessible(&acl, &AccessType::Read) { // read-verify only if we have read access let readback = self.read(slot)?; + crate::println!("rbk: {:x?}", &readback[..8]); if readback != value { Err(AccessError::WriteError) } else { Ok(()) } } else { Ok(()) @@ -338,12 +313,6 @@ impl SlotManager { self.data_acl_range.as_slice()[offset..offset + size_of::()].try_into().unwrap() }))) } - SlotIndex::Key(_, _, _) => { - let offset = slot.try_into_acl_offset()?; - AccessSettings::Key(KeySlotAccess::new_with_raw_value(u32::from_le_bytes(unsafe { - self.key_acl_range.as_slice()[offset..offset + size_of::()].try_into().unwrap() - }))) - } SlotIndex::DataRange(_, _, _) => { let mut range = slot.try_into_acl_iter()?; let offset = range.next().unwrap(); @@ -360,22 +329,6 @@ impl SlotManager { } AccessSettings::Data(prototype) } - SlotIndex::KeyRange(_, _, _) => { - let mut range = slot.try_into_acl_iter()?; - let offset = range.next().unwrap(); - let prototype = KeySlotAccess::new_with_raw_value(u32::from_le_bytes(unsafe { - self.key_acl_range.as_slice()[offset..offset + size_of::()].try_into().unwrap() - })); - for offset in range { - let successor = KeySlotAccess::new_with_raw_value(u32::from_le_bytes(unsafe { - self.key_acl_range.as_slice()[offset..offset + size_of::()].try_into().unwrap() - })); - if prototype != successor { - return Err(AccessError::KeyAclInconsistency(prototype)); - } - } - AccessSettings::Key(prototype) - } }) } @@ -389,22 +342,22 @@ impl SlotManager { })) } - /// Safety: the caller must resolve the index into either the data or the key array correctly. - /// There is access or type checking done. This is a "raw read" primitive mostly used for debugging. - pub unsafe fn get_key_acl(&self, absolute_offset: usize) -> KeySlotAccess { - KeySlotAccess::new_with_raw_value(u32::from_le_bytes(unsafe { - self.key_acl_range.as_slice()[absolute_offset..absolute_offset + size_of::()] - .try_into() - .unwrap() - })) - } - pub fn set_acl( &self, writer: &mut Reram, slot: &SlotIndex, setting: &AccessSettings, ) -> Result<(), AccessError> { + #[cfg(not(feature = "std"))] + let ptr = match slot { + SlotIndex::Data(_, _, _) | SlotIndex::DataRange(_, _, _) => self.data_acl_range.as_ptr() as usize, + }; + #[cfg(feature = "std")] + let ptr = match slot { + SlotIndex::Data(_, _, _) | SlotIndex::DataRange(_, _, _) => { + self.data_acl_write_offset.as_ptr() as usize + } + }; // safety: the unsafe blocks here are concerned that the data types of the resulting // slice are all representable. In this case, all bits are valid in the final representation. match slot { @@ -412,45 +365,27 @@ impl SlotManager { let offset = slot.try_into_acl_offset()?; writer .protected_write_slice( - self.data_acl_range.as_ptr() as usize - utralib::HW_RERAM_MEM + offset, - &setting.raw_u32().to_le_bytes(), - ) - .map(|_| ()) - .map_err(|_| AccessError::WriteError) - } - SlotIndex::Key(_, _, _) => { - let offset = slot.try_into_acl_offset()?; - writer - .protected_write_slice( - self.key_acl_range.as_ptr() as usize - utralib::HW_RERAM_MEM + offset, + ptr - utralib::HW_RERAM_MEM + offset, &setting.raw_u32().to_le_bytes(), ) .map(|_| ()) .map_err(|_| AccessError::WriteError) } SlotIndex::DataRange(_, _, _) => { + let mut success = true; for offset in slot.try_into_acl_iter()? { - writer - .protected_write_slice( - self.data_acl_range.as_ptr() as usize - utralib::HW_RERAM_MEM + offset, - &setting.raw_u32().to_le_bytes(), - ) - .map(|_| ()) - .map_err(|_| AccessError::WriteError)? + match writer.protected_write_slice( + ptr - utralib::HW_RERAM_MEM + offset, + &setting.raw_u32().to_le_bytes(), + ) { + Ok(_) => {} + Err(e) => { + success = false; + crate::println!("Can't write to ACL offset {:x}: {:?}", offset, e); + } + } } - Ok(()) - } - SlotIndex::KeyRange(_, _, _) => { - for offset in slot.try_into_acl_iter()? { - writer - .protected_write_slice( - self.key_acl_range.as_ptr() as usize - utralib::HW_RERAM_MEM + offset, - &setting.raw_u32().to_le_bytes(), - ) - .map(|_| ()) - .map_err(|_| AccessError::WriteError)? - } - Ok(()) + if success { Ok(()) } else { Err(AccessError::WriteError) } } } } diff --git a/libs/bao1x-hal/src/sigcheck.rs b/libs/bao1x-hal/src/sigcheck.rs index 6716c0143..cc9eae8dc 100644 --- a/libs/bao1x-hal/src/sigcheck.rs +++ b/libs/bao1x-hal/src/sigcheck.rs @@ -4,7 +4,7 @@ use alloc::vec::Vec; use bao1x_api::signatures::*; #[cfg(not(feature = "std"))] -use bao1x_api::{DEVELOPER_MODE, KeySlotAccess, RwPerms, SLOT_ELEMENT_LEN_BYTES, SlotType}; +use bao1x_api::{DEVELOPER_MODE, DataSlotAccess, RwPerms, SLOT_ELEMENT_LEN_BYTES, SlotType}; use digest::Digest; use sha2_bao1x::{Sha256, Sha512}; use xous::arch::PAGE_SIZE; @@ -226,7 +226,7 @@ pub fn erase_secrets() { // have access permissions, and panic instead of allowing a boot. const ZERO_ERR_THRESH: usize = 2; for slot in crate::board::KEY_SLOTS.iter() { - if slot.get_type() == SlotType::Key { + if slot.get_type() == SlotType::Data { let (_pa, rw_perms) = slot.get_access_spec(); for data_index in slot.try_into_data_iter().unwrap() { match rw_perms { @@ -238,11 +238,11 @@ pub fn erase_secrets() { .set_acl( &mut rram, slot, - &AccessSettings::Key(KeySlotAccess::new_with_raw_value(0)), + &AccessSettings::Data(DataSlotAccess::new_with_raw_value(0)), ) .expect("couldn't reset ACL"); } - let bytes = unsafe { slot_mgr.read_key_slot(data_index) }; + let bytes = unsafe { slot_mgr.read_data_slot(data_index) }; if bytes.iter().all(|&b| b == 0) { zero_key_count += 1; } @@ -253,12 +253,15 @@ pub fn erase_secrets() { alloc::vec::Vec::with_capacity(slot.len() * SLOT_ELEMENT_LEN_BYTES); eraser.resize(slot.len() * SLOT_ELEMENT_LEN_BYTES, ERASE_VALUE); - slot_mgr.write(&mut rram, slot, &eraser).expect("couldn't erase key"); + slot_mgr.write(&mut rram, slot, &eraser).ok(); } - let check = unsafe { slot_mgr.read_key_slot(data_index) }; + let check = unsafe { slot_mgr.read_data_slot(data_index) }; if !check.iter().all(|&b| b == ERASE_VALUE) { crate::println!("Failed to erase key at {}: {:x?}", data_index, check); - panic!("Key erasure did not succeed, refusing to boot!"); + // reboot on failure to erase + let mut rcurst = + utralib::CSR::new(utralib::utra::sysctrl::HW_SYSCTRL_BASE as *mut u32); + rcurst.wo(utralib::utra::sysctrl::SFR_RCURST0, 0x55AA); } else { crate::println!("Key range at {} confirmed erased", slot.get_base()); }