Skip to content

Commit

Permalink
Make safety comment on code loading data from handoff region true.
Browse files Browse the repository at this point in the history
This prevents the caller from attempting to deserialize data from arbitrary
memory regions.
  • Loading branch information
flihp committed Sep 24, 2024
1 parent c29dffa commit cf2704f
Show file tree
Hide file tree
Showing 4 changed files with 91 additions and 69 deletions.
16 changes: 8 additions & 8 deletions drv/lpc55-rng/build.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,11 @@ use idol::{server::ServerStyle, CounterSettings};

cfg_if::cfg_if! {
if #[cfg(feature = "dice-seed")] {
mod config {
include!("src/config.rs");
mod data_region {
include!("src/data-region.rs");
}
use anyhow::Context;
use config::DataRegion;
use data_region::DataRegion;
use indexmap::IndexMap;
use std::{fs::File, io::Write};

Expand All @@ -25,13 +25,13 @@ fn extern_region_to_cfg<W: Write>(
data_regions: &IndexMap<String, DataRegion>,
name: &str,
) -> Result<()> {
let region = data_regions
.get(name)
.ok_or_else(|| anyhow::anyhow!("dice_certs data region not found"))?;
let region = data_regions.get(name).ok_or_else(|| {
anyhow::anyhow!(format!("external region not found: {}", name))
})?;

Ok(writeln!(
out,
r##"pub const {}: DataRegion = DataRegion {{
r##"pub const {}_REGION: DataRegion = DataRegion {{
address: {:#x},
size: {:#x},
}};"##,
Expand All @@ -53,7 +53,7 @@ fn extern_regions_to_cfg(path: &str) -> Result<()> {
return Err(anyhow!("no data regions found"));
}

writeln!(out, "use crate::config::DataRegion;\n\n")?;
writeln!(out, "use crate::data_region::DataRegion;\n\n")?;

extern_region_to_cfg(&mut out, &data_regions, "dice_certs")?;
extern_region_to_cfg(&mut out, &data_regions, "dice_rng")
Expand Down
54 changes: 48 additions & 6 deletions drv/lpc55-rng/src/config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,52 @@
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at https://mozilla.org/MPL/2.0/.

#[derive(serde::Deserialize, Default, Debug)]
#[serde(rename_all = "kebab-case")]
#[cfg(feature = "dice-seed")]
pub struct DataRegion {
pub address: usize,
pub size: usize,
use crate::data_region::DataRegion;
use hubpack::SerializedSize;
use serde::Deserialize;
use stage0_handoff::{HandoffData, HandoffDataLoadError};

pub enum HandoffDataRegion {
DiceCerts,
DiceRng,
}

pub const DICE_CERTS: HandoffDataRegion = HandoffDataRegion::DiceCerts;
pub const DICE_RNG: HandoffDataRegion = HandoffDataRegion::DiceRng;

// This file is generated by the crate build.rs.
mod build {
include!(concat!(env!("OUT_DIR"), "/rng-config.rs"));
}

use build::{DICE_CERTS_REGION, DICE_RNG_REGION};

impl HandoffDataRegion {
pub fn data_region(&self) -> DataRegion {
match self {
Self::DiceCerts => DICE_CERTS_REGION,
Self::DiceRng => DICE_RNG_REGION,
}
}

/// Load a type implementing HandoffData (and others) from a config::DataRegion.
/// Errors will be reported in the ringbuf and will return None.
pub fn load_data<
T: for<'a> Deserialize<'a> + HandoffData + SerializedSize,
>(
&self,
) -> Result<T, HandoffDataLoadError> {
use core::slice;

let region = self.data_region();
// Safety: This memory is setup by code executed before hubris and
// exposed using the kernel `extern-regions` mechanism. The safety of
// this code is an extension of our trust in the hubris pre-main, kernel,
// and build process.
let data = unsafe {
slice::from_raw_parts(region.address as *mut u8, region.size)
};

T::load_from_addr(data)
}
}
10 changes: 10 additions & 0 deletions drv/lpc55-rng/src/data-region.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at https://mozilla.org/MPL/2.0/.

#[derive(serde::Deserialize, Default, Debug)]
#[serde(rename_all = "kebab-case")]
pub struct DataRegion {
pub address: usize,
pub size: usize,
}
80 changes: 25 additions & 55 deletions drv/lpc55-rng/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,6 @@
#![no_std]
#![no_main]

mod config;

use core::{cmp, usize};
use drv_lpc55_syscon_api::Syscon;
use drv_rng_api::RngError;
Expand All @@ -31,22 +29,13 @@ use zeroize::Zeroizing;

cfg_if::cfg_if! {
if #[cfg(feature = "dice-seed")] {
use config::DataRegion;
use hubpack::SerializedSize;
use lib_dice::{persistid_cert_tmpl::SUBJECT_CN_RANGE, CertData, RngData};
mod config;
#[path="data-region.rs"]
mod data_region;

use ringbuf::ringbuf_entry;
use serde::Deserialize;
use stage0_handoff::{HandoffData, HandoffDataLoadError};
use stage0_handoff::HandoffDataLoadError;
use userlib::UnwrapLite;

// This file is generated by the crate build.rs. It contains instances
// of config::DataRegion structs describing regions of memory
// configured & exposed to this task by the hubris build.
mod build {
include!(concat!(env!("OUT_DIR"), "/rng-config.rs"));
}

use build::{DICE_CERTS, DICE_RNG};
}
}

Expand All @@ -56,11 +45,9 @@ task_slot!(SYSCON, syscon_driver);
enum Trace {
None,
#[cfg(feature = "dice-seed")]
NoDiceSeed,
NoDiceSeed(HandoffDataLoadError),
#[cfg(feature = "dice-seed")]
HandoffError(HandoffDataLoadError),
#[cfg(feature = "dice-seed")]
NoSeedPersonalization,
NoSeedPersonalization(HandoffDataLoadError),
}

ringbuf!(Trace, 16, Trace::None);
Expand Down Expand Up @@ -226,29 +213,6 @@ impl NotificationHandler for Lpc55RngServer {
}
}

/// Load a type implementing HandoffData (and others) from a config::DataRegion.
/// Errors will be reported in the ringbuf and will return None.
#[cfg(feature = "dice-seed")]
fn load_data_from_region<
T: for<'a> Deserialize<'a> + HandoffData + SerializedSize,
>(
region: &DataRegion,
) -> Option<T> {
use core::slice;

// Safety: This memory is setup by code executed before hubris and
// exposed using the kernel `extern-regions` mechanism. The safety of
// this code is an extension of our trust in the hubris pre-main, kernel,
// and build process.
let data = unsafe {
slice::from_raw_parts(region.address as *mut u8, region.size)
};

T::load_from_addr(data)
.inspect_err(|e| ringbuf_entry!(Trace::HandoffError(*e)))
.ok()
}

/// Get the seed derived by the lpc55-rot-startup and passed to us through
/// the stage0-handoff memory region.
///
Expand All @@ -259,10 +223,13 @@ fn load_data_from_region<
pub fn get_dice_seed() -> Option<RngSeed> {
cfg_if::cfg_if! {
if #[cfg(feature = "dice-seed")] {
match load_data_from_region::<RngData>(&DICE_RNG) {
Some(rng_data) => Some(rng_data.seed),
_ => {
ringbuf_entry!(Trace::NoDiceSeed);
use config::DICE_RNG;
use lib_dice::RngData;

match DICE_RNG.load_data::<RngData>() {
Ok(rng_data) => Some(rng_data.seed),
Err(e) => {
ringbuf_entry!(Trace::NoDiceSeed(e));
panic!();
},
}
Expand All @@ -283,14 +250,17 @@ pub fn get_dice_seed() -> Option<RngSeed> {
pub fn get_seed_personalization() -> Option<[u8; SUBJECT_CN_LENGTH]> {
cfg_if::cfg_if! {
if #[cfg(feature = "dice-seed")] {
match load_data_from_region::<CertData>(&DICE_CERTS) {
Some(cert_data) => Some(
cert_data.persistid_cert.0.as_bytes()[SUBJECT_CN_RANGE]
.try_into()
.unwrap_lite(),
),
_ => {
ringbuf_entry!(Trace::NoSeedPersonalization);
use config::DICE_CERTS;
use lib_dice::{persistid_cert_tmpl::SUBJECT_CN_RANGE, CertData};

match DICE_CERTS.load_data::<CertData>() {
Ok(cert_data) => Some(
cert_data.persistid_cert.0.as_bytes()[SUBJECT_CN_RANGE]
.try_into()
.unwrap_lite(),
),
Err(e) => {
ringbuf_entry!(Trace::NoSeedPersonalization(e));
panic!();
},
}
Expand Down

0 comments on commit cf2704f

Please sign in to comment.