mirror of
https://github.com/saymrwulf/xous-core.git
synced 2026-11-04 04:27:34 +00:00
loader hardening
The loader is only lightly hardened at this point. Some minmal random delay + bollards inserted. The signature check routine inherits all the hardening of boot0 because it uses the same code. PLL mode is checked at least once. more loader hardening will happen in a future PR - at the moment, we're focused on boot0/boot1 hardening.
This commit is contained in:
parent
4b25e24d7e
commit
3f7dce3052
3 changed files with 54 additions and 45 deletions
|
|
@ -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;
|
||||
|
||||
|
|
|
|||
|
|
@ -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) {
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
Loading…
Reference in a new issue