Skip to content

Commit

Permalink
Add test for MANUF debug unlock
Browse files Browse the repository at this point in the history
Signed-off-by: Arthur Heymans <[email protected]>
  • Loading branch information
ArthurHeymans committed Dec 17, 2024
1 parent 4db4c2f commit 9c26ad0
Show file tree
Hide file tree
Showing 13 changed files with 160 additions and 4 deletions.
1 change: 1 addition & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 3 additions & 0 deletions api/src/soc_mgr.rs
Original file line number Diff line number Diff line change
Expand Up @@ -158,6 +158,9 @@ pub trait SocManager {
self.soc_ifc()
.fuse_soc_stepping_id()
.write(|w| w.soc_stepping_id(fuses.soc_stepping_id.into()));
self.soc_ifc()
.fuse_manuf_dbg_unlock_token()
.write(&fuses.manuf_dbg_unlock_token);

self.soc_ifc().cptra_fuse_wr_done().write(|w| w.done(true));

Expand Down
48 changes: 48 additions & 0 deletions api/types/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,9 @@ pub const DEFAULT_CPTRA_OBF_KEY: [u32; 8] = [
0xa0a1a2a3, 0xb0b1b2b3, 0xc0c1c2c3, 0xd0d1d2d3, 0xe0e1e2e3, 0xf0f1f2f3, 0xa4a5a6a7, 0xb4b5b6b7,
];

pub const DEFAULT_MANUF_DEBUG_UNLOCK_TOKEN: [u32; 4] =
[0xcfcecdcc, 0xcbcac9c8, 0xc7c6c5c4, 0xc3c2c1c0];

// Based on device_lifecycle_e from RTL
#[derive(Copy, Clone, Debug, Default, PartialEq, Eq)]
pub enum DeviceLifecycle {
Expand Down Expand Up @@ -82,6 +85,49 @@ impl SecurityState {
}
}

#[derive(Copy, Clone, Debug, Default, PartialEq, Eq)]
pub struct DbgManufServiceRegReq(u32);
impl From<u32> for DbgManufServiceRegReq {
fn from(value: u32) -> Self {
Self(value)
}
}
impl From<DbgManufServiceRegReq> for u32 {
fn from(value: DbgManufServiceRegReq) -> Self {
value.0
}
}

impl DbgManufServiceRegReq {
pub fn set_manuf_dbg_unlock_req(&mut self, val: bool) -> &mut Self {
let mask = 1 << 0;
if val {
self.0 |= mask;
} else {
self.0 &= !mask
};
self
}
pub fn set_prod_dbg_unlock_req(&mut self, val: bool) -> &mut Self {
let mask = 1 << 1;
if val {
self.0 |= mask;
} else {
self.0 &= !mask
};
self
}
pub fn set_uds_program_req(&mut self, val: bool) -> &mut Self {
let mask = 1 << 2;
if val {
self.0 |= mask;
} else {
self.0 &= !mask
};
self
}
}

#[derive(Clone, Copy, PartialEq, Eq, Debug, Default)]
pub enum U4 {
#[default]
Expand Down Expand Up @@ -168,6 +214,7 @@ pub struct Fuses {
pub lms_verify: bool,
pub fuse_lms_revocation: u32,
pub soc_stepping_id: u16,
pub manuf_dbg_unlock_token: [u32; 4],
}
impl Default for Fuses {
fn default() -> Self {
Expand All @@ -186,6 +233,7 @@ impl Default for Fuses {
lms_verify: Default::default(),
fuse_lms_revocation: Default::default(),
soc_stepping_id: Default::default(),
manuf_dbg_unlock_token: DEFAULT_MANUF_DEBUG_UNLOCK_TOKEN,
}
}
}
Expand Down
1 change: 0 additions & 1 deletion drivers/src/fuse_bank.rs
Original file line number Diff line number Diff line change
Expand Up @@ -308,7 +308,6 @@ impl FuseBank<'_> {
/// # Returns
/// manufactoring debug unlock token
///
pub fn manuf_dbg_unlock_token(&self) -> Array4x4 {
let soc_ifc_regs = self.soc_ifc.regs();
Array4x4::read_from_reg(soc_ifc_regs.fuse_manuf_dbg_unlock_token())
Expand Down
2 changes: 2 additions & 0 deletions error/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -662,6 +662,8 @@ impl CaliptraError {
CaliptraError::new_const(0xa0000004);
pub const ROM_SS_DBG_UNLOCK_PROD_INVALID_TOKEN_MBOX_CMD: CaliptraError =
CaliptraError::new_const(0xa0000005);
pub const ROM_SS_DBG_UNLOCK_PROD_INVALID_TOKEN: CaliptraError =
CaliptraError::new_const(0xa0000006);
}

impl From<core::num::NonZeroU32> for crate::CaliptraError {
Expand Down
8 changes: 7 additions & 1 deletion hw-model/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ mod output;
mod rv32_builder;

pub use api::mailbox::mbox_write_fifo;
pub use api_types::{DeviceLifecycle, Fuses, SecurityState, U4};
pub use api_types::{DbgManufServiceRegReq, DeviceLifecycle, Fuses, SecurityState, U4};
pub use caliptra_emu_bus::BusMmio;
use output::ExitStatus;
pub use output::Output;
Expand Down Expand Up @@ -154,6 +154,10 @@ pub struct InitParams<'a> {

pub security_state: SecurityState,

pub dbg_manuf_service: DbgManufServiceRegReq,

pub debug_intent: bool,

// The silicon obfuscation key passed to caliptra_top.
pub cptra_obf_key: [u32; 8],

Expand Down Expand Up @@ -200,6 +204,8 @@ impl<'a> Default for InitParams<'a> {
log_writer: Box::new(stdout()),
security_state: *SecurityState::default()
.set_device_lifecycle(DeviceLifecycle::Unprovisioned),
dbg_manuf_service: Default::default(),
debug_intent: false,
cptra_obf_key: DEFAULT_CPTRA_OBF_KEY,
itrng_nibbles,
etrng_responses,
Expand Down
2 changes: 2 additions & 0 deletions hw-model/src/model_emulated.rs
Original file line number Diff line number Diff line change
Expand Up @@ -160,6 +160,8 @@ impl HwModel for ModelEmulated {
cpu_enabled_cloned.set(true);
}),
security_state: params.security_state,
dbg_manuf_service_req: params.dbg_manuf_service,
debug_intent: params.debug_intent,
cptra_obf_key: params.cptra_obf_key,

itrng_nibbles: Some(params.itrng_nibbles),
Expand Down
3 changes: 3 additions & 0 deletions hw-model/types/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,9 @@ pub const DEFAULT_CPTRA_OBF_KEY: [u32; 8] = [
0xa0a1a2a3, 0xb0b1b2b3, 0xc0c1c2c3, 0xd0d1d2d3, 0xe0e1e2e3, 0xf0f1f2f3, 0xa4a5a6a7, 0xb4b5b6b7,
];

pub const DEFAULT_MANUF_DEBUG_UNLOCK_TOKEN: [u32; 4] =
[0xcfcecdcc, 0xcbcac9c8, 0xc7c6c5c4, 0xc3c2c1c0];

struct SecurityStateWrapper(SecurityState);
impl std::fmt::Debug for SecurityStateWrapper {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
Expand Down
1 change: 1 addition & 0 deletions rom/dev/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ caliptra-builder.workspace = true
caliptra-emu-cpu.workspace = true

caliptra-hw-model.workspace = true
caliptra-hw-model-types.workspace = true
caliptra-image-elf.workspace = true
caliptra-image-fake-keys.workspace = true
caliptra-image-gen.workspace = true
Expand Down
1 change: 1 addition & 0 deletions rom/dev/tests/rom_integration_tests/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ mod rv32_unit_tests;
mod test_capabilities;
mod test_cfi;
mod test_cpu_fault;
mod test_debug_unlock;
mod test_dice_derivations;
mod test_fake_rom;
mod test_fips_hooks;
Expand Down
56 changes: 56 additions & 0 deletions rom/dev/tests/rom_integration_tests/test_debug_unlock.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
// Licensed under the Apache-2.0 license

use caliptra_api::mailbox::{CommandId, MailboxReqHeader, ManufDebugUnlockTokenReq};
use caliptra_api::SocManager;
use caliptra_builder::firmware::ROM_WITH_UART;
use caliptra_hw_model::{DbgManufServiceRegReq, DeviceLifecycle, HwModel, SecurityState};
use zerocopy::AsBytes;

#[test]
fn test_dbg_unlock_manuf() {
let security_state = *SecurityState::default()
.set_debug_locked(true)
.set_device_lifecycle(DeviceLifecycle::Manufacturing);

let dbg_manuf_service = *DbgManufServiceRegReq::default().set_manuf_dbg_unlock_req(true);

let rom = caliptra_builder::build_firmware_rom(&ROM_WITH_UART).unwrap();

let mut hw = caliptra_hw_model::new(
caliptra_hw_model::InitParams {
rom: &rom,
security_state,
dbg_manuf_service,
debug_intent: true,
..Default::default()
},
caliptra_hw_model::BootParams::default(),
)
.unwrap();

let token = ManufDebugUnlockTokenReq {
token: caliptra_hw_model_types::DEFAULT_MANUF_DEBUG_UNLOCK_TOKEN
.as_bytes()
.try_into()
.unwrap(),
..Default::default()
};
let checksum = caliptra_common::checksum::calc_checksum(
u32::from(CommandId::MANUF_DEBUG_UNLOCK_REQ_TOKEN),
&token.as_bytes()[4..],
);
let token = ManufDebugUnlockTokenReq {
hdr: MailboxReqHeader { chksum: checksum },
..token
};
hw.mailbox_execute(
CommandId::MANUF_DEBUG_UNLOCK_REQ_TOKEN.into(),
&token.as_bytes(),
)
.unwrap();

hw.step_until(|m| {
let resp = m.soc_ifc().ss_dbg_manuf_service_reg_rsp().read();
resp.manuf_dbg_unlock_success()
});
}
6 changes: 5 additions & 1 deletion sw-emulator/lib/periph/src/root_bus.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ use crate::{
AsymEcc384, Csrng, Doe, EmuCtrl, HashSha256, HashSha512, HmacSha, KeyVault, MailboxExternal,
MailboxInternal, MailboxRam, Sha512Accelerator, SocRegistersInternal, Uart,
};
use caliptra_api_types::SecurityState;
use caliptra_api_types::{DbgManufServiceRegReq, SecurityState};
use caliptra_emu_bus::{Clock, Ram, Rom};
use caliptra_emu_cpu::{Pic, PicMmioRegisters};
use caliptra_emu_derive::Bus;
Expand Down Expand Up @@ -213,6 +213,8 @@ pub struct CaliptraRootBusArgs {
pub log_dir: PathBuf,
// The security state wires provided to caliptra_top
pub security_state: SecurityState,
pub dbg_manuf_service_req: DbgManufServiceRegReq,
pub debug_intent: bool,

/// Callback to customize application behavior when
/// a write to the tb-services register write is performed.
Expand All @@ -234,6 +236,8 @@ impl Default for CaliptraRootBusArgs {
rom: Default::default(),
log_dir: Default::default(),
security_state: Default::default(),
dbg_manuf_service_req: Default::default(),
debug_intent: false,
tb_services_cb: Default::default(),
ready_for_fw_cb: Default::default(),
upload_update_fw: Default::default(),
Expand Down
32 changes: 31 additions & 1 deletion sw-emulator/lib/periph/src/soc_reg.rs
Original file line number Diff line number Diff line change
Expand Up @@ -214,6 +214,28 @@ register_bitfields! [
DEBUG_INTENT OFFSET(0) NUMBITS(1) [],
],

/// SubSytem Debug Manufacturing Service Request Register
SsDbgManufServiceRegReq [
MANUF_DBG_UNLOCK_REQ OFFSET(0) NUMBITS(1) [],
PROD_DBG_UNLOCK_REQ OFFSET(1) NUMBITS(1) [],
UDS_PROGRAM_REQ OFFSET(2) NUMBITS(1) [],
RSVD OFFSET(3) NUMBITS(29) [],
],

/// SubSytem Debug Manufacturing Service Response Register
SsDbgManufServiceRegRsp [
MANUF_DBG_UNLOCK_SUCCESS OFFSET(0) NUMBITS(1) [],
MANUF_DBG_UNLOCK_FAIL OFFSET(1) NUMBITS(1) [],
MANUF_DBG_UNLOCK_IN_PROGRESS OFFSET(2) NUMBITS(1) [],
PROD_DBG_UNLOCK_SUCCESS OFFSET(3) NUMBITS(1) [],
PROD_DBG_UNLOCK_FAIL OFFSET(4) NUMBITS(1) [],
PROD_DBG_UNLOCK_IN_PROGRESS OFFSET(5) NUMBITS(1) [],
UDS_PROGRAM_SUCCESS OFFSET(6) NUMBITS(1) [],
UDS_PROGRAM_FAIL OFFSET(7) NUMBITS(1) [],
UDS_PROGRAM_IN_PROGRESS OFFSET(8) NUMBITS(1) [],
RSVD OFFSET(9) NUMBITS(23) [],
],

/// Per-Type Interrupt Enable Register
GlobalIntrEn [
ERROR_EN OFFSET(0) NUMBITS(1) [],
Expand Down Expand Up @@ -676,6 +698,12 @@ struct SocRegistersImpl {
#[register(offset = 0x530)]
ss_debug_intent: ReadOnlyRegister<u32, SsDebugIntent::Register>,

#[register(offset = 0x5c0)]
ss_dbg_manuf_service_reg_req: ReadWriteRegister<u32, SsDbgManufServiceRegReq::Register>,

#[register(offset = 0x5c4)]
ss_dbg_manuf_service_reg_rsp: ReadWriteRegister<u32, SsDbgManufServiceRegRsp::Register>,

/// INTERNAL_OBF_KEY Register
internal_obf_key: [u32; 8],

Expand Down Expand Up @@ -868,7 +896,9 @@ impl SocRegistersImpl {
fuse_mldsa_revocation: Default::default(),
fuse_soc_stepping_id: ReadWriteRegister::new(0),
fuse_manuf_dbg_unlock_token: [0; 4],
ss_debug_intent: ReadOnlyRegister::new(0),
ss_debug_intent: ReadOnlyRegister::new(if args.debug_intent { 1 } else { 0 }),
ss_dbg_manuf_service_reg_req: ReadWriteRegister::new(args.dbg_manuf_service_req.into()),
ss_dbg_manuf_service_reg_rsp: ReadWriteRegister::new(0),
internal_obf_key: args.cptra_obf_key,
internal_iccm_lock: ReadWriteRegister::new(0),
internal_fw_update_reset: ReadWriteRegister::new(0),
Expand Down

0 comments on commit 9c26ad0

Please sign in to comment.