Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions emulator/app/src/emulator.rs
Original file line number Diff line number Diff line change
Expand Up @@ -259,6 +259,8 @@ pub struct EmulatorArgs {
pub fuse_soc_manifest_max_svn: Option<u32>,
#[arg(long)]
pub fuse_vendor_hashes_prod_partition: Option<String>,
#[arg(long)]
pub fuse_vendor_test_partition: Option<String>,
}

pub struct Emulator {
Expand Down Expand Up @@ -731,6 +733,9 @@ impl Emulator {
let fuse_vendor_hashes_prod_partition = cli
.fuse_vendor_hashes_prod_partition
.map(|fuse| hex::decode(fuse).expect("Invalid hex in vendor_hashes_prod_partition"));
let fuse_vendor_test_partition = cli
.fuse_vendor_test_partition
.map(|fuse| hex::decode(fuse).expect("Invalid hex in vendor_test_partition"));

let lc = LcCtrl::new();

Expand All @@ -744,6 +749,7 @@ impl Emulator {
soc_manifest_svn: cli.fuse_soc_manifest_svn.map(|v| v as u8),
soc_manifest_max_svn: cli.fuse_soc_manifest_max_svn.map(|v| v as u8),
vendor_hashes_prod_partition: fuse_vendor_hashes_prod_partition,
vendor_test_partition: fuse_vendor_test_partition,
..Default::default()
},
)?;
Expand Down
2 changes: 2 additions & 0 deletions emulator/cbinding/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -195,6 +195,7 @@ pub struct CEmulatorConfig {
pub fuse_soc_manifest_svn: c_longlong,
pub fuse_soc_manifest_max_svn: c_longlong,
pub fuse_vendor_hashes_prod_partition: *const c_char, // Optional, can be null
pub fuse_vendor_test_partition: *const c_char, // Optional, can be null

// External device callbacks (can be null)
pub external_read_callback: *const std::ffi::c_void,
Expand Down Expand Up @@ -344,6 +345,7 @@ pub unsafe extern "C" fn emulator_init(
fuse_vendor_hashes_prod_partition: convert_optional_c_string(
config.fuse_vendor_hashes_prod_partition,
),
fuse_vendor_test_partition: convert_optional_c_string(config.fuse_vendor_test_partition),
};

// Convert C callbacks to Rust callbacks if provided
Expand Down
1 change: 1 addition & 0 deletions emulator/cbinding/src/simple_test.rs
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,7 @@ fn test_emulator_args_creation() {
fuse_soc_manifest_max_svn: None,
fuse_soc_manifest_svn: None,
fuse_vendor_hashes_prod_partition: None,
fuse_vendor_test_partition: None,
};

println!("EmulatorArgs created successfully");
Expand Down
8 changes: 8 additions & 0 deletions emulator/periph/src/otp.rs
Original file line number Diff line number Diff line change
Expand Up @@ -115,6 +115,7 @@ pub struct OtpArgs {
pub soc_manifest_svn: Option<u8>,
pub soc_manifest_max_svn: Option<u8>,
pub vendor_hashes_prod_partition: Option<Vec<u8>>,
pub vendor_test_partition: Option<Vec<u8>>,
}

//#[derive(Bus)]
Expand Down Expand Up @@ -213,6 +214,13 @@ impl Otp {
otp.partitions[dst_start..dst_start + copy_len]
.copy_from_slice(&vendor_hashes_prod_partition[..copy_len]);
}
if let Some(vendor_test_partition) = args.vendor_test_partition {
let dst_start = fuses::VENDOR_TEST_PARTITION_BYTE_OFFSET;
let max_len = fuses::VENDOR_TEST_PARTITION_BYTE_SIZE;
let copy_len = vendor_test_partition.len().min(max_len);
otp.partitions[dst_start..dst_start + copy_len]
.copy_from_slice(&vendor_test_partition[..copy_len]);
}

// if there were digests that were pending a reset, then calculate them now
otp.calculate_digests()?;
Expand Down
3 changes: 2 additions & 1 deletion platforms/emulator/rom/src/mcu_image_verifier.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ pub struct McuImageVerifier;

impl ImageVerifier for McuImageVerifier {
fn verify_header(&self, _header: &[u8], _fuses: &Fuses) -> bool {
// TODO: make this unconditional and use proper fuses for it instead of test fuses
#[cfg(any(feature = "test-mcu-svn-gt-fuse", feature = "test-mcu-svn-lt-fuse"))]
{
let Ok((header, _)) = McuImageHeader::ref_from_prefix(_header) else {
Expand All @@ -21,7 +22,7 @@ impl ImageVerifier for McuImageVerifier {

let mut fuse_vendor_svn: u16 = 0;
// Use the first 128 bits of vendor test partition as SVN
for byte in _fuses.vendor_hashes_prod_partition[..16].iter() {
for byte in _fuses.vendor_test_partition[..16].iter() {
// Count contiguous 1's in the byte
let mut count = 0;
for bit in 0..8 {
Expand Down
12 changes: 6 additions & 6 deletions rom/src/fuses.rs
Original file line number Diff line number Diff line change
Expand Up @@ -675,12 +675,12 @@ impl Otp {
fuses::VENDOR_HASHES_PROD_PARTITION_BYTE_SIZE,
&mut fuses.vendor_hashes_prod_partition,
)?;
// romtime::println!("[mcu-rom-otp] Reading vendor revocations production partition");
// self.read_data(
// fuses::VENDOR_REVOCATIONS_PROD_PARTITION_BYTE_OFFSET,
// fuses::VENDOR_REVOCATIONS_PROD_PARTITION_BYTE_SIZE,
// &mut fuses.vendor_revocations_prod_partition,
// )?;
romtime::println!("[mcu-rom-otp] Reading vendor revocations production partition");
self.read_data(
fuses::VENDOR_REVOCATIONS_PROD_PARTITION_BYTE_OFFSET,
fuses::VENDOR_REVOCATIONS_PROD_PARTITION_BYTE_SIZE,
&mut fuses.vendor_revocations_prod_partition,
)?;
// romtime::println!("[mcu-rom-otp] Reading vendor non-secret production partition");
// self.read_data(
// fuses::VENDOR_NON_SECRET_PROD_PARTITION_BYTE_OFFSET,
Expand Down
62 changes: 59 additions & 3 deletions rom/src/rom.rs
Original file line number Diff line number Diff line change
Expand Up @@ -272,9 +272,65 @@ impl Soc {
}

// TODO: vendor-specific fuses when those are supported
// TODO: load ECC Revocation CSRs.
// TODO: load LMS Revocation CSRs.
// TODO: load MLDSA Revocation CSRs.
// Load Owner ECC/LMS/MLDSA revocation CSRs.
// ECC Revocation.
let vendor_ecc_revocation =
u32::from_le_bytes(fuses.cptra_core_ecc_revocation_0().try_into().unwrap());
self.registers
.fuse_ecc_revocation
.set(vendor_ecc_revocation);

// LMS Revocation.

let vendor_lms_revocation = u32::from_le_bytes(
fuses
.cptra_core_lms_revocation_0()
.try_into()
.unwrap_or_else(|_| {
fatal_error(McuError::ROM_SOC_KEY_MANIFEST_PK_HASH_LEN_MISMATCH)
}),
);
self.registers
.fuse_lms_revocation
.set(vendor_lms_revocation);

// MLDSA Revocation.
let vendor_mldsa_revocation = u32::from_le_bytes(
fuses
.cptra_core_mldsa_revocation_0()
.try_into()
.unwrap_or_else(|_| {
fatal_error(McuError::ROM_SOC_KEY_MANIFEST_PK_HASH_LEN_MISMATCH)
}),
);
self.registers
.fuse_mldsa_revocation
.set(vendor_mldsa_revocation);

// Owner PK Hash.
// TBD: Device Ownership Transfer
if !fuses.cptra_ss_owner_pk_hash().iter().all(|&x| x == 0) {
romtime::print!("[mcu-fuse-write] Writing fuse key owner PK hash: ");

if size_of_val(fuses.cptra_ss_owner_pk_hash())
!= size_of_val(&self.registers.cptra_owner_pk_hash)
{
fatal_error(McuError::ROM_SOC_KEY_MANIFEST_PK_HASH_LEN_MISMATCH);
}
for i in 0..self.registers.cptra_owner_pk_hash.len() {
let word = u32::from_le_bytes(
fuses.cptra_ss_owner_pk_hash()[i * 4..i * 4 + 4]
.try_into()
.unwrap_or_else(|_| {
fatal_error(McuError::ROM_SOC_KEY_MANIFEST_PK_HASH_LEN_MISMATCH)
}),
);
romtime::print!("{}", HexWord(word));
self.registers.cptra_owner_pk_hash[i].set(word);
}
romtime::println!("");
}

// TODO: load HEK Seed CSRs.

// SoC Stepping ID (only 16-bits are relevant).
Expand Down
13 changes: 6 additions & 7 deletions tests/integration/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -281,7 +281,7 @@ mod test {
hw_revision: Option<String>,
fuse_soc_manifest_svn: Option<u8>,
fuse_soc_manifest_max_svn: Option<u8>,
fuse_vendor_hashes_prod_partition: Option<Vec<u8>>,
fuse_vendor_test_partition: Option<Vec<u8>>,
) -> i32 {
let mut cargo_run_args = vec![
"run",
Expand Down Expand Up @@ -451,12 +451,11 @@ mod test {
cargo_run_args.push(soc_manifest_max_svn_str.as_str());
}

let fuse_vendor_hashes_prod_partition_str;
if let Some(fuse_vendor_hashes_prod_partition) = fuse_vendor_hashes_prod_partition {
cargo_run_args.push("--fuse-vendor-hashes-prod-partition");
fuse_vendor_hashes_prod_partition_str =
hex::encode(fuse_vendor_hashes_prod_partition);
cargo_run_args.push(fuse_vendor_hashes_prod_partition_str.as_str());
let fuse_vendor_test_partition_str;
if let Some(fuse_vendor_test_partition) = fuse_vendor_test_partition {
cargo_run_args.push("--fuse-vendor-test-partition");
fuse_vendor_test_partition_str = hex::encode(fuse_vendor_test_partition);
cargo_run_args.push(fuse_vendor_test_partition_str.as_str());
}

println!("Running test firmware {}", feature.replace("_", "-"));
Expand Down
Loading