Skip to content

Commit

Permalink
feat: unit tests for dbg unlock for manuf and prod
Browse files Browse the repository at this point in the history
Signed-off-by: Arthur Heymans <arthur.heymans@9elements.com>
  • Loading branch information
ArthurHeymans committed Jan 23, 2025
1 parent 980b80e commit bb543a1
Show file tree
Hide file tree
Showing 13 changed files with 734 additions and 18 deletions.
5 changes: 5 additions & 0 deletions Cargo.lock

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

1 change: 1 addition & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -189,6 +189,7 @@ zeroize = { version = "1.6.0", default-features = false, features = ["zeroize_de
regex = "1.10.2"
ecdsa = { version = "0.16.9", features = ["pem"]}
sec1 = { version = "0.7.3" }
itertools = "0.12.0"

[profile.firmware]
inherits = "release"
Expand Down
3 changes: 3 additions & 0 deletions api/src/soc_mgr.rs
Original file line number Diff line number Diff line change
Expand Up @@ -161,6 +161,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
1 change: 0 additions & 1 deletion drivers/src/fuse_bank.rs
Original file line number Diff line number Diff line change
Expand Up @@ -334,7 +334,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
4 changes: 2 additions & 2 deletions drivers/src/soc_ifc.rs
Original file line number Diff line number Diff line change
Expand Up @@ -166,8 +166,8 @@ impl SocIfc {
pub fn ss_mci_axi_base(&self) -> AxiAddr {
let soc_ifc_regs = self.soc_ifc.regs();
AxiAddr {
lo: soc_ifc_regs.ss_caliptra_base_addr_l().read(),
hi: soc_ifc_regs.ss_caliptra_base_addr_h().read(),
lo: soc_ifc_regs.ss_mci_base_addr_l().read(),
hi: soc_ifc_regs.ss_mci_base_addr_h().read(),
}
}

Expand Down
4 changes: 3 additions & 1 deletion error/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -704,7 +704,9 @@ 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 =
pub const ROM_SS_DBG_UNLOCK_PROD_INVALID_TOKEN_WRONG_PUBLIC_KEYS: CaliptraError =
CaliptraError::new_const(0xa0000006);
pub const ROM_SS_DBG_UNLOCK_PROD_INVALID_TOKEN_INVALID_SIGNATURE: CaliptraError =
CaliptraError::new_const(0xa0000006);
}

Expand Down
13 changes: 12 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;
pub use caliptra_emu_cpu::{CodeRange, ImageInfo, StackInfo, StackRange};
use output::ExitStatus;
Expand Down Expand Up @@ -155,6 +155,14 @@ pub struct InitParams<'a> {

pub security_state: SecurityState,

pub dbg_manuf_service: DbgManufServiceRegReq,

// Keypairs for production debug unlock levels, from low to high
// ECC384 and MLDSA87 keypairs
pub prod_dbg_unlock_keypairs: Vec<(&'a [u8; 96], &'a [u8; 2592])>,

pub debug_intent: bool,

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

Expand Down Expand Up @@ -205,6 +213,9 @@ 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(),
prod_dbg_unlock_keypairs: Default::default(),
debug_intent: false,
cptra_obf_key: DEFAULT_CPTRA_OBF_KEY,
itrng_nibbles,
etrng_responses,
Expand Down
3 changes: 3 additions & 0 deletions hw-model/src/model_emulated.rs
Original file line number Diff line number Diff line change
Expand Up @@ -160,6 +160,9 @@ impl HwModel for ModelEmulated {
cpu_enabled_cloned.set(true);
}),
security_state: params.security_state,
dbg_manuf_service_req: params.dbg_manuf_service,
prod_dbg_unlock_keypairs: params.prod_dbg_unlock_keypairs,
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
6 changes: 6 additions & 0 deletions rom/dev/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -39,16 +39,22 @@ 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
caliptra-image-crypto.workspace = true
caliptra-image-types.workspace = true
caliptra-test.workspace = true
elf.workspace = true
fips204.workspace = true
hex.workspace = true
memoffset.workspace = true
rand.workspace = true
openssl.workspace = true
p384.workspace = true
sha2.workspace = true
zerocopy.workspace = true

[features]
riscv = []
Expand Down
29 changes: 16 additions & 13 deletions rom/dev/src/flow/debug_unlock.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ Abstract:
--*/

use core::mem::size_of;
use core::mem::{size_of, ManuallyDrop};

use crate::flow::cold_reset::fw_processor::FirmwareProcessor;
use crate::CaliptraResult;
Expand Down Expand Up @@ -70,7 +70,7 @@ fn handle_manufacturing(env: &mut RomEnv) -> CaliptraResult<()> {
Err(CaliptraError::ROM_SS_DBG_UNLOCK_MANUF_INVALID_MBOX_CMD)?
}

let mut txn = txn.start_txn();
let mut txn = ManuallyDrop::new(txn.start_txn());
let mut request = ManufDebugUnlockTokenReq::default();
FirmwareProcessor::copy_req_verify_chksum(&mut txn, request.as_bytes_mut())?;

Expand Down Expand Up @@ -151,7 +151,7 @@ fn handle_production_request(
Err(CaliptraError::ROM_SS_DBG_UNLOCK_PROD_INVALID_REQ_MBOX_CMD)?
}

let mut txn = txn.start_txn();
let mut txn = ManuallyDrop::new(txn.start_txn());
let mut request = ProductionAuthDebugUnlockReq::default();
FirmwareProcessor::copy_req_verify_chksum(&mut txn, request.as_bytes_mut())?;

Expand Down Expand Up @@ -217,22 +217,23 @@ fn handle_production_token(

env.soc_ifc.set_ss_dbg_unlock_in_progress(true);

let mut txn = txn.start_txn();
let mut txn = ManuallyDrop::new(txn.start_txn());
let mut token = ProductionAuthDebugUnlockToken::default();
FirmwareProcessor::copy_req_verify_chksum(&mut txn, token.as_bytes_mut())?;

// Validate payload
if payload_length(token.length)
!= size_of::<ProductionAuthDebugUnlockToken>() - size_of::<MailboxReqHeader>()
{
Err(CaliptraError::ROM_SS_DBG_UNLOCK_PROD_INVALID_TOKEN)?
Err(CaliptraError::ROM_SS_DBG_UNLOCK_PROD_INVALID_TOKEN_INVALID_SIGNATURE)?
}

// Debug level
if payload_length(token.unlock_category) != payload_length(request.unlock_category) {
return Err(CaliptraError::ROM_SS_DBG_UNLOCK_PROD_INVALID_TOKEN);
return Err(CaliptraError::ROM_SS_DBG_UNLOCK_PROD_INVALID_TOKEN_INVALID_SIGNATURE);
}
if cfi_launder(token.challenge) != challenge.challenge {
return Err(CaliptraError::ROM_SS_DBG_UNLOCK_PROD_INVALID_TOKEN);
return Err(CaliptraError::ROM_SS_DBG_UNLOCK_PROD_INVALID_TOKEN_INVALID_SIGNATURE);
} else {
caliptra_cfi_lib::cfi_assert_eq_12_words(
&Array4x12::from(token.challenge).0,
Expand All @@ -247,8 +248,8 @@ fn handle_production_token(
let debug_auth_pk_hash_base = mci_base + debug_auth_pk_offset.into();

let dma = &mut env.dma;
let mut fuse_digest = Array4x16::default();
dma.read_buffer(debug_auth_pk_hash_base, fuse_digest.as_bytes_mut())?;
let mut fuse_digest: [u8; 64] = [0; 64];
dma.read_buffer(debug_auth_pk_hash_base, &mut fuse_digest)?;

let mut digest_op = env.sha2_512_384.sha512_digest_init()?;
digest_op.update(&token.ecc_public_key)?;
Expand All @@ -257,10 +258,11 @@ fn handle_production_token(
digest_op.finalize(&mut request_digest)?;

// Verify that digest of keys match
let fuse_digest = Array4x16::from(fuse_digest);
if cfi_launder(request_digest) != fuse_digest {
env.soc_ifc.finish_ss_dbg_unluck(false);
txn.set_uc_tap_unlock(false);
return Err(CaliptraError::ROM_SS_DBG_UNLOCK_MANUF_INVALID_TOKEN);
return Err(CaliptraError::ROM_SS_DBG_UNLOCK_PROD_INVALID_TOKEN_WRONG_PUBLIC_KEYS);
} else {
caliptra_cfi_lib::cfi_assert_eq_12_words(
&request_digest.0[..12].try_into().unwrap(),
Expand All @@ -287,7 +289,7 @@ fn handle_production_token(
if result == Ecc384Result::SigVerifyFailed {
env.soc_ifc.finish_ss_dbg_unluck(false);
txn.set_uc_tap_unlock(false);
Err(CaliptraError::ROM_SS_DBG_UNLOCK_MANUF_INVALID_TOKEN)?;
return Err(CaliptraError::ROM_SS_DBG_UNLOCK_PROD_INVALID_TOKEN_INVALID_SIGNATURE);
}

let mut digest_op = env.sha2_512_384.sha512_digest_init()?;
Expand All @@ -304,7 +306,7 @@ fn handle_production_token(
)?;

if result == Mldsa87Result::SigVerifyFailed {
return Err(CaliptraError::ROM_SS_DBG_UNLOCK_MANUF_INVALID_TOKEN);
return Err(CaliptraError::ROM_SS_DBG_UNLOCK_PROD_INVALID_TOKEN_INVALID_SIGNATURE);
}
Ok(())
}
Expand All @@ -325,7 +327,8 @@ fn handle_production(env: &mut RomEnv) -> CaliptraResult<()> {
None => continue,
}
};
let mut txn = txn.start_txn();

let mut txn = ManuallyDrop::new(txn.start_txn());

match result {
Ok(()) => {
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
Loading

0 comments on commit bb543a1

Please sign in to comment.