Skip to content

Commit 228ca4a

Browse files
committed
lpc55-rng: Include SN from platform id cert in initial PRNG seed.
Platforms assigned a unique serial number can include this string in the initial seed to ensure uniqueness in the bit stream produced by the RNG. We now construct the intial seed as: ``` SEED_0 = sha3_256(DICE_SEED | SN | HRNG(32)) ``` Extracting the Platform Id / serial number from the platform identity cert required exposing the relevant module from the lib-dice crate. We also add additional constants to the template module that are required to know the length of the platform id string at compile time. Finally this feature is gated by the same `dice-seed` feature used for the seed derived by measured boot for simplicity.
1 parent b0a17f5 commit 228ca4a

File tree

8 files changed

+83
-26
lines changed

8 files changed

+83
-26
lines changed

Cargo.lock

+1
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

app/lpc55xpresso/app.toml

+2-2
Original file line numberDiff line numberDiff line change
@@ -116,9 +116,9 @@ features = ["dice-seed"]
116116
priority = 3
117117
uses = ["rng", "pmc"]
118118
start = true
119-
stacksize = 2704
119+
stacksize = 4200
120120
task-slots = ["syscon_driver"]
121-
extern-regions = ["dice_rng"]
121+
extern-regions = ["dice_certs", "dice_rng"]
122122

123123
[tasks.pong]
124124
name = "task-pong"

app/rot-carrier/app.toml

+2-2
Original file line numberDiff line numberDiff line change
@@ -101,9 +101,9 @@ name = "drv-lpc55-rng"
101101
priority = 5
102102
uses = ["rng", "pmc"]
103103
start = true
104-
stacksize = 2704
104+
stacksize = 4200
105105
task-slots = ["syscon_driver"]
106-
extern-regions = ["dice_rng"]
106+
extern-regions = ["dice_certs", "dice_rng"]
107107

108108
[tasks.sprot]
109109
name = "drv-lpc55-sprot-server"

drv/lpc55-rng/Cargo.toml

+2-1
Original file line numberDiff line numberDiff line change
@@ -28,10 +28,11 @@ anyhow.workspace = true
2828
build-util.path = "../../build/util"
2929
cfg-if.workspace = true
3030
idol.workspace = true
31+
indexmap = { workspace = true, optional = true }
3132
serde.workspace = true
3233

3334
[features]
34-
dice-seed = ["stage0-handoff"]
35+
dice-seed = ["indexmap", "stage0-handoff"]
3536
no-ipc-counters = ["idol/no-counters"]
3637

3738
# This section is here to discourage RLS/rust-analyzer from doing test builds,

drv/lpc55-rng/build.rs

+25-12
Original file line numberDiff line numberDiff line change
@@ -12,12 +12,35 @@ cfg_if::cfg_if! {
1212
}
1313
use anyhow::Context;
1414
use config::DataRegion;
15+
use indexmap::IndexMap;
1516
use std::{fs::File, io::Write};
1617

1718
const CFG_SRC: &str = "rng-config.rs";
1819
}
1920
}
2021

22+
#[cfg(feature = "dice-seed")]
23+
fn extern_region_to_cfg<W: Write>(
24+
out: &mut W,
25+
data_regions: &IndexMap<String, DataRegion>,
26+
name: &str,
27+
) -> Result<()> {
28+
let region = data_regions
29+
.get(name)
30+
.ok_or_else(|| anyhow::anyhow!("dice_certs data region not found"))?;
31+
32+
Ok(writeln!(
33+
out,
34+
r##"pub const {}: DataRegion = DataRegion {{
35+
address: {:#x},
36+
size: {:#x},
37+
}};"##,
38+
name.to_uppercase(),
39+
region.address,
40+
region.size
41+
)?)
42+
}
43+
2144
#[cfg(feature = "dice-seed")]
2245
fn extern_regions_to_cfg(path: &str) -> Result<()> {
2346
let out_dir = build_util::out_dir();
@@ -32,18 +55,8 @@ fn extern_regions_to_cfg(path: &str) -> Result<()> {
3255

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

35-
let region = data_regions
36-
.get("dice_rng")
37-
.ok_or_else(|| anyhow::anyhow!("dice_certs data region not found"))?;
38-
39-
Ok(writeln!(
40-
out,
41-
r##"pub const DICE_RNG: DataRegion = DataRegion {{
42-
address: {:#x},
43-
size: {:#x},
44-
}};"##,
45-
region.address, region.size
46-
)?)
58+
extern_region_to_cfg(&mut out, &data_regions, "dice_certs")?;
59+
extern_region_to_cfg(&mut out, &data_regions, "dice_rng")
4760
}
4861

4962
fn main() -> Result<()> {

drv/lpc55-rng/src/main.rs

+46-7
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ use core::{cmp, usize};
1515
use drv_lpc55_syscon_api::Syscon;
1616
use drv_rng_api::RngError;
1717
use idol_runtime::{ClientError, NotificationHandler, RequestError};
18-
use lib_dice::{RngSeed, SeedBuf};
18+
use lib_dice::{persistid_cert_tmpl::SUBJECT_CN_LENGTH, RngSeed, SeedBuf};
1919
use lib_lpc55_rng::Lpc55Rng;
2020
use rand_chacha::ChaCha20Rng;
2121
use rand_core::{impls, Error, RngCore, SeedableRng};
@@ -29,10 +29,10 @@ use userlib::*;
2929
use zeroize::Zeroizing;
3030

3131
cfg_if::cfg_if! {
32-
if #[cfg(any(feature = "dice-seed"))] {
32+
if #[cfg(feature = "dice-seed")] {
3333
use config::DataRegion;
3434
use hubpack::SerializedSize;
35-
use lib_dice::RngData;
35+
use lib_dice::{persistid_cert_tmpl::SUBJECT_CN_RANGE, CertData, RngData};
3636
use ringbuf::ringbuf_entry;
3737
use serde::Deserialize;
3838
use stage0_handoff::{HandoffData, HandoffDataLoadError};
@@ -44,7 +44,7 @@ cfg_if::cfg_if! {
4444
include!(concat!(env!("OUT_DIR"), "/rng-config.rs"));
4545
}
4646

47-
use build::DICE_RNG;
47+
use build::{DICE_CERTS, DICE_RNG};
4848
}
4949
}
5050

@@ -56,6 +56,8 @@ enum Trace {
5656
NoDiceSeed,
5757
#[cfg(feature = "dice-seed")]
5858
HandoffError(HandoffDataLoadError),
59+
#[cfg(feature = "dice-seed")]
60+
NoSeedPersonalization,
5961
None,
6062
}
6163

@@ -80,6 +82,7 @@ where
8082
fn new(
8183
seed: Option<&RngSeed>,
8284
mut reseeder: R,
85+
pid: Option<&[u8; SUBJECT_CN_LENGTH]>,
8386
threshold: usize,
8487
) -> Result<Self, Error> {
8588
let threshold = if threshold == 0 {
@@ -94,6 +97,11 @@ where
9497
Digest::update(&mut mixer, seed.as_bytes());
9598
}
9699

100+
if let Some(pid) = pid {
101+
// mix in unique platform id
102+
Digest::update(&mut mixer, pid);
103+
}
104+
97105
// w/ 32 bytes from HRNG
98106
let mut buf = Zeroizing::new(T::Seed::default());
99107
reseeder.try_fill_bytes(buf.as_mut())?;
@@ -172,10 +180,11 @@ impl Lpc55RngServer {
172180
fn new(
173181
seed: Option<&RngSeed>,
174182
reseeder: Lpc55Rng,
183+
pid: Option<&[u8; SUBJECT_CN_LENGTH]>,
175184
threshold: usize,
176185
) -> Result<Self, Error> {
177186
Ok(Lpc55RngServer(ReseedingRng::new(
178-
seed, reseeder, threshold,
187+
seed, reseeder, pid, threshold,
179188
)?))
180189
}
181190
}
@@ -265,15 +274,45 @@ pub fn get_dice_seed() -> Option<RngSeed> {
265274
}
266275
}
267276

277+
/// Get the platform identifier / barcode string from the platform identity
278+
/// cert passed to hubris by the lpc55-rot-startup through the stage0-handoff
279+
/// memory region.
280+
///
281+
/// If use of the platform identifier string is not enabled then this function
282+
/// will return `None`. Otherwise it will try to get the platform identity
283+
/// string from the stage0-handoff region. If it's unable to get this data it
284+
/// will put an entry into the ringbuf and panic.
285+
pub fn get_seed_personalization() -> Option<[u8; SUBJECT_CN_LENGTH]> {
286+
cfg_if::cfg_if! {
287+
if #[cfg(feature = "dice-seed")] {
288+
match load_data_from_region::<CertData>(&DICE_CERTS) {
289+
Some(cert_data) => Some(
290+
cert_data.persistid_cert.0.as_bytes()[SUBJECT_CN_RANGE]
291+
.try_into()
292+
.unwrap_lite(),
293+
),
294+
_ => {
295+
ringbuf_entry!(Trace::NoSeedPersonalization);
296+
panic!();
297+
},
298+
}
299+
} else {
300+
None
301+
}
302+
}
303+
}
304+
268305
#[export_name = "main"]
269306
fn main() -> ! {
270307
let seed = get_dice_seed();
308+
let pid = get_seed_personalization();
271309

272310
let rng = Lpc55Rng::new(&Syscon::from(SYSCON.get_task_id()));
273311

274312
let threshold = 0x100000; // 1 MiB
275-
let mut rng = Lpc55RngServer::new(seed.as_ref(), rng, threshold)
276-
.expect("Failed to create Lpc55RngServer");
313+
let mut rng =
314+
Lpc55RngServer::new(seed.as_ref(), rng, pid.as_ref(), threshold)
315+
.expect("Failed to create Lpc55RngServer");
277316
let mut buffer = [0u8; idl::INCOMING_SIZE];
278317

279318
loop {

lib/dice/src/lib.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ mod alias_cert_tmpl;
3030
mod deviceid_cert_tmpl;
3131
mod handoff;
3232
mod mfg;
33-
mod persistid_cert_tmpl;
33+
pub mod persistid_cert_tmpl;
3434
mod persistid_csr_tmpl;
3535
pub use crate::mfg::{
3636
DiceMfg, DiceMfgState, PersistIdSeed, SelfMfg, SerialMfg,

lib/dice/src/persistid_cert_tmpl.rs

+4-1
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,10 @@ use core::ops::Range;
1212
pub const SIZE: usize = 441;
1313
pub const SERIAL_NUMBER_RANGE: Range<usize> = 15..16;
1414
pub const ISSUER_CN_RANGE: Range<usize> = 82..114;
15-
pub const SUBJECT_CN_RANGE: Range<usize> = 207..239;
15+
pub const SUBJECT_CN_START: usize = 207;
16+
pub const SUBJECT_CN_END: usize = 239;
17+
pub const SUBJECT_CN_RANGE: Range<usize> = SUBJECT_CN_START..SUBJECT_CN_END;
18+
pub const SUBJECT_CN_LENGTH: usize = SUBJECT_CN_END - SUBJECT_CN_START;
1619
pub const PUB_RANGE: Range<usize> = 251..283;
1720
pub const SIG_RANGE: Range<usize> = 377..441;
1821
pub const SIGNDATA_RANGE: Range<usize> = 4..367;

0 commit comments

Comments
 (0)