mirror of
https://github.com/saymrwulf/xous-core.git
synced 2026-11-15 08:30:02 +00:00
upgrade boot1 path to implement signature hardening
multi-pass signature checking and jump target hardening per boot0 standards implemented here
This commit is contained in:
parent
006eab2084
commit
8be0f1004b
1 changed files with 39 additions and 31 deletions
|
|
@ -1,14 +1,6 @@
|
|||
use bao1x_api::{bollard, signatures::FunctionCode};
|
||||
use bao1x_api::{PARANOID_MODE, PARANOID_MODE_DUPE, bollard, pubkeys::BOOT1_TO_LOADER_OR_BAREMETAL};
|
||||
use bao1x_hal::hardening::Csprng;
|
||||
|
||||
pub const ALLOWED_FUNCTIONS: [u32; 5] = [
|
||||
FunctionCode::Baremetal as u32,
|
||||
FunctionCode::UpdatedBaremetal as u32,
|
||||
FunctionCode::Loader as u32,
|
||||
FunctionCode::UpdatedLoader as u32,
|
||||
FunctionCode::Developer as u32,
|
||||
];
|
||||
|
||||
#[inline(always)]
|
||||
fn seal_boot1_keys() {
|
||||
// This is a security-critical initialization. Failure to do this correctly totally breaks
|
||||
|
|
@ -25,25 +17,26 @@ fn seal_boot1_keys() {
|
|||
}
|
||||
|
||||
pub fn try_boot(or_die: bool, csprng: &mut Csprng) {
|
||||
let one_way = bao1x_hal::acram::OneWayCounter::new();
|
||||
bollard!(bao1x_hal::sigcheck::die_no_std, 4);
|
||||
csprng.random_delay();
|
||||
let (paranoid1, paranoid2) = one_way.hardened_get2(PARANOID_MODE, PARANOID_MODE_DUPE).unwrap();
|
||||
csprng.random_delay();
|
||||
|
||||
// loader is at the same offset as baremetal. Accept either as valid boot.
|
||||
// This diverges if the signature check is successful
|
||||
match bao1x_hal::sigcheck::validate_image(
|
||||
bao1x_api::LOADER_START as *const u32,
|
||||
bao1x_api::BOOT1_START as *const u32,
|
||||
bao1x_api::BOOT1_REVOCATION_OFFSET,
|
||||
&ALLOWED_FUNCTIONS,
|
||||
false,
|
||||
None,
|
||||
Some(csprng),
|
||||
) {
|
||||
Ok((k, k2, tag)) => {
|
||||
crate::println!(
|
||||
"Booting with key {}/{}({})",
|
||||
k,
|
||||
k2,
|
||||
core::str::from_utf8(&tag).unwrap_or("invalid tag")
|
||||
);
|
||||
if k != k2 {
|
||||
match bao1x_hal::sigcheck::validate_image(BOOT1_TO_LOADER_OR_BAREMETAL, None, Some(csprng)) {
|
||||
Ok((key, key_inv, tag, target)) => {
|
||||
if paranoid1 == 0 && paranoid2 == 0 {
|
||||
// only emit prints if not in paranoid mode
|
||||
crate::println!(
|
||||
"Booting with key {}/{}({})",
|
||||
key,
|
||||
!key_inv,
|
||||
core::str::from_utf8(&tag).unwrap_or("invalid tag")
|
||||
);
|
||||
}
|
||||
if key != !key_inv {
|
||||
bao1x_hal::sigcheck::die_no_std();
|
||||
}
|
||||
|
||||
|
|
@ -53,20 +46,35 @@ pub fn try_boot(or_die: bool, csprng: &mut Csprng) {
|
|||
// the tag is from signed, trusted data
|
||||
// k is just a nominal slot number. If either match, assume we are dealing with a
|
||||
// developer image.
|
||||
bao1x_hal::sigcheck::hardened_erase_policy(paranoid1, paranoid2, key, key_inv, tag, csprng)
|
||||
.inspect_err(|e| crate::println!("{}", e))
|
||||
.ok(); // "ok" because the expected error is a check on logic/configuration bugs, not attacks
|
||||
|
||||
// this print message is not hardened, and it's actually retrospective of the policy
|
||||
// implementation
|
||||
if tag == *bao1x_api::pubkeys::KEYSLOT_INITIAL_TAGS[bao1x_api::pubkeys::DEVELOPER_KEY_SLOT]
|
||||
|| k == bao1x_api::pubkeys::DEVELOPER_KEY_SLOT
|
||||
|| key == bao1x_api::pubkeys::DEVELOPER_KEY_SLOT
|
||||
|| !key_inv == bao1x_api::pubkeys::DEVELOPER_KEY_SLOT
|
||||
{
|
||||
crate::println!("Developer key detected, ensuring secrets are erased");
|
||||
bao1x_hal::sigcheck::erase_secrets(&mut Some(csprng));
|
||||
}
|
||||
|
||||
// double up the security check if in paranoid mode
|
||||
csprng.random_delay();
|
||||
if paranoid1 != 0 || paranoid2 != 0 {
|
||||
bollard!(bao1x_hal::sigcheck::die_no_std, 4);
|
||||
bao1x_hal::sigcheck::validate_image(BOOT1_TO_LOADER_OR_BAREMETAL, None, Some(csprng))
|
||||
.unwrap_or_else(|_| bao1x_hal::hardening::die());
|
||||
}
|
||||
|
||||
csprng.random_delay();
|
||||
bollard!(bao1x_hal::sigcheck::die_no_std, 4);
|
||||
// this has to be called *after* erase_secrets, because we can't erase the secrets
|
||||
// once the mappings have been sealed off. This is why we can't use the auto-jump method
|
||||
// like we do in boot0.
|
||||
csprng.random_delay();
|
||||
bollard!(bao1x_hal::sigcheck::die_no_std, 4);
|
||||
seal_boot1_keys();
|
||||
bollard!(bao1x_hal::sigcheck::die_no_std, 4);
|
||||
bao1x_hal::sigcheck::jump_to(bao1x_api::LOADER_START);
|
||||
bao1x_hal::sigcheck::jump_to((target ^ u32::from_le_bytes(tag)) as usize);
|
||||
}
|
||||
Err(e) => crate::println!("Image did not validate: {:?}", e),
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in a new issue