diff --git a/loader/src/main.rs b/loader/src/main.rs index 46a06b6ec..11b08dff5 100644 --- a/loader/src/main.rs +++ b/loader/src/main.rs @@ -254,6 +254,14 @@ pub unsafe extern "C" fn rust_entry(signed_buffer: *const usize, signature: u32) } } + #[cfg(feature = "bao1x")] + let mut csprng = bao1x_hal::hardening::Csprng::new(); + #[cfg(feature = "bao1x")] + csprng.random_delay(); + #[cfg(feature = "bao1x")] + // it's security-important to ensure we're running off the PLL + bao1x_hal::hardening::check_pll(); + // Run kernel image validation now that the heap is set up. #[cfg(feature = "bao1x")] let detached_app = { @@ -270,13 +278,18 @@ pub unsafe extern "C" fn rust_entry(signed_buffer: *const usize, signature: u32) ], false, None, + Some(&mut csprng), ) { - Ok((k, tag)) => { + Ok((k, k2, tag)) => { println!( - "*** Kernel signature check by key @ {}({}) OK ***", + "*** Kernel signature check by key @ {}/{}({}) OK ***", k, + k2, core::str::from_utf8(&tag).unwrap_or("invalid tag") ); + if k != k2 { + bao1x_hal::sigcheck::die_no_std(); + } // k is just a nominal slot number. If either match, assume we are dealing with a // developer image. if tag == *bao1x_api::pubkeys::KEYSLOT_INITIAL_TAGS[bao1x_api::pubkeys::DEVELOPER_KEY_SLOT] @@ -313,15 +326,20 @@ pub unsafe extern "C" fn rust_entry(signed_buffer: *const usize, signature: u32) &[FunctionCode::App as u32, FunctionCode::UpdatedApp as u32], false, None, + Some(&mut csprng), ) { - Ok((k, tag)) => { + Ok((k, k2, tag)) => { println!( - "*** Detached app signature check by key @ {}({}) OK ***", + "*** Detached app signature check by key @ {}/{}({}) OK ***", k, + k2, core::str::from_utf8(&tag).unwrap_or("invalid tag") ); // k is just a nominal slot number. If either match, assume we are dealing with a // developer image. + if k != k2 { + bao1x_hal::sigcheck::die_no_std(); + } if tag == *bao1x_api::pubkeys::KEYSLOT_INITIAL_TAGS[bao1x_api::pubkeys::DEVELOPER_KEY_SLOT] || k == bao1x_api::pubkeys::DEVELOPER_KEY_SLOT @@ -353,6 +371,15 @@ pub unsafe extern "C" fn rust_entry(signed_buffer: *const usize, signature: u32) false } }; + + #[cfg(feature = "bao1x")] + { + // Follow up the mesh check in loader - it takes 100ms or so for the mesh to settle, we can't afford + // to wait that long in boot1. + let one_way = bao1x_hal::acram::OneWayCounter::new(); + bao1x_hal::hardening::mesh_check_and_react(&mut csprng, &one_way); + } + #[cfg(not(feature = "bao1x"))] let detached_app = false; diff --git a/loader/src/platform/bao1x/bao1x.rs b/loader/src/platform/bao1x/bao1x.rs index bc224bc5b..425835cb0 100644 --- a/loader/src/platform/bao1x/bao1x.rs +++ b/loader/src/platform/bao1x/bao1x.rs @@ -256,8 +256,7 @@ pub unsafe fn init_clock_asic(freq_hz: u32) -> u32 { const UNIT_MHZ: u32 = 1000 * 1000; const PFD_F_MHZ: u32 = 16; const FREQ_0: u32 = 16 * UNIT_MHZ; - const FREQ_OSC_MHZ: u32 = 48; // Actually 48MHz - const M: u32 = FREQ_OSC_MHZ / PFD_F_MHZ; // - 1; // OSC input was 24, replace with 48 + const M: u32 = bao1x_api::FREQ_OSC_MHZ / PFD_F_MHZ; // - 1; // OSC input was 24, replace with 48 const TBL_Q: [u16; 7] = [ // keep later DIV even number as possible @@ -290,19 +289,19 @@ pub unsafe fn init_clock_asic(freq_hz: u32) -> u32 { daric_cgu.add(utra::sysctrl::SFR_CGUFD_CFGFDCR_0_4_4.offset()).write_volatile(0x070f); // pclk // calculate perclk divider. Target 100MHz. - let (min_cycle, fd, perclk) = if let Some((min_cycle, fd, perclk)) = clk_to_per(freq_hz / 1_000_000, 100) - { - daric_cgu - .add(utra::sysctrl::SFR_CGUFDPER.offset()) - .write_volatile((min_cycle as u32) << 16 | (fd as u32) << 8 | fd as u32); - (min_cycle, fd, perclk * 1_000_000) - } else if freq_hz > 400_000_000 { - daric_cgu.add(utra::sysctrl::SFR_CGUFDPER.offset()).write_volatile(0x07_ff_ff); - (7, 0xff, freq_hz / 8) - } else { - daric_cgu.add(utra::sysctrl::SFR_CGUFDPER.offset()).write_volatile(0x03_ff_ff); - (3, 0xff, freq_hz / 4) - }; + let (min_cycle, fd, perclk) = + if let Some((min_cycle, fd, perclk)) = bao1x_api::clk_to_per(freq_hz / 1_000_000, 100) { + daric_cgu + .add(utra::sysctrl::SFR_CGUFDPER.offset()) + .write_volatile((min_cycle as u32) << 16 | (fd as u32) << 8 | fd as u32); + (min_cycle, fd, perclk * 1_000_000) + } else if freq_hz > 400_000_000 { + daric_cgu.add(utra::sysctrl::SFR_CGUFDPER.offset()).write_volatile(0x07_ff_ff); + (7, 0xff, freq_hz / 8) + } else { + daric_cgu.add(utra::sysctrl::SFR_CGUFDPER.offset()).write_volatile(0x03_ff_ff); + (3, 0xff, freq_hz / 4) + }; /* perclk fields: min-cycle-lp | min-cycle | fd-lp | fd @@ -354,13 +353,13 @@ pub unsafe fn init_clock_asic(freq_hz: u32) -> u32 { crate::println!("...done"); cgu.wo(sysctrl::SFR_CGUSEL1, 1); - cgu.wo(sysctrl::SFR_CGUFSCR, FREQ_OSC_MHZ); + cgu.wo(sysctrl::SFR_CGUFSCR, bao1x_api::FREQ_OSC_MHZ); cgu.wo(sysctrl::SFR_CGUSET, 0x32); let duart = utra::duart::HW_DUART_BASE as *mut u32; duart.add(utra::duart::SFR_CR.offset()).write_volatile(0); // set the ETUC now that we're on the xosc. - duart.add(utra::duart::SFR_ETUC.offset()).write_volatile(FREQ_OSC_MHZ); + duart.add(utra::duart::SFR_ETUC.offset()).write_volatile(bao1x_api::FREQ_OSC_MHZ); duart.add(utra::duart::SFR_CR.offset()).write_volatile(1); if freq_hz <= 1_000_000 { @@ -516,28 +515,6 @@ pub fn coreuser_config() { crate::println!("coreuser locked!"); } -/// Takes in the top clock in MHz, desired perclk in MHz, and returns a tuple of -/// (min cycle, fd, actual freq) -/// *tested* -#[allow(dead_code)] -pub fn clk_to_per(top_in_mhz: u32, perclk_in_mhz: u32) -> Option<(u8, u8, u32)> { - let fd_platonic = ((256 * perclk_in_mhz) / (top_in_mhz / 2)).min(256); - if fd_platonic > 0 { - let fd = fd_platonic - 1; - let min_cycle = (2 * (256 / (fd + 1))).max(1); - let min_freq = top_in_mhz / min_cycle; - let target_freq = top_in_mhz * (fd + 1) / 512; - let actual_freq = target_freq.max(min_freq); - if fd < 256 && min_cycle < 256 && min_cycle > 0 { - Some(((min_cycle - 1) as u8, fd as u8, actual_freq)) - } else { - None - } - } else { - None - } -} - /// Delay with a given system clock frequency. Useful during power mode switching. #[allow(dead_code)] pub fn delay_at_sysfreq(ms: usize, sysclk_freq: u32) { diff --git a/loader/src/platform/bao1x/swap.rs b/loader/src/platform/bao1x/swap.rs index 9fbc50aa7..929a3a79d 100644 --- a/loader/src/platform/bao1x/swap.rs +++ b/loader/src/platform/bao1x/swap.rs @@ -242,13 +242,18 @@ impl SwapHal { &[FunctionCode::Swap as u32, FunctionCode::UpdatedSwap as u32], false, Some(&mut hal.flash_spim), + None, ) { - Ok((k, tag)) => { + Ok((k, k2, tag)) => { println!( - "*** Swap signature check by key @ {}({}) OK ***", + "*** Swap signature check by key @ {}/{}({}) OK ***", k, + k2, core::str::from_utf8(&tag).unwrap_or("invalid tag") ); + if k != k2 { + bao1x_hal::sigcheck::die_no_std(); + } // k is just a nominal slot number. If either match, assume we are dealing // with a developer image. if tag