Skip to content

Commit

Permalink
Add idevid CSR with MLDSA87
Browse files Browse the repository at this point in the history
  • Loading branch information
ArthurHeymans authored and mhatrevi committed Dec 15, 2024
1 parent 0001d50 commit 281864d
Show file tree
Hide file tree
Showing 31 changed files with 1,178 additions and 281 deletions.
6 changes: 3 additions & 3 deletions drivers/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -95,9 +95,9 @@ pub use pcr_reset::PcrResetCounter;
#[cfg(feature = "runtime")]
pub use persistent::AuthManifestImageMetadataList;
pub use persistent::{
FuseLogArray, IdevIdCsr, PcrLogArray, PersistentData, PersistentDataAccessor,
StashMeasurementArray, FUSE_LOG_MAX_COUNT, MAX_CSR_SIZE, MEASUREMENT_MAX_COUNT,
PCR_LOG_MAX_COUNT,
Ecc384IdevIdCsr, FuseLogArray, Mldsa87IdevIdCsr, PcrLogArray, PersistentData,
PersistentDataAccessor, StashMeasurementArray, ECC384_MAX_CSR_SIZE, FUSE_LOG_MAX_COUNT,
MEASUREMENT_MAX_COUNT, MLDSA87_MAX_CSR_SIZE, PCR_LOG_MAX_COUNT,
};
pub use pic::{IntSource, Pic};
pub use sha1::{Sha1, Sha1Digest, Sha1DigestOp};
Expand Down
30 changes: 25 additions & 5 deletions drivers/src/memory_layout.rs
Original file line number Diff line number Diff line change
Expand Up @@ -44,8 +44,10 @@ pub const FUSE_LOG_ORG: u32 = MEASUREMENT_LOG_ORG + MEASUREMENT_LOG_SIZE;
pub const DPE_ORG: u32 = FUSE_LOG_ORG + FUSE_LOG_SIZE;
pub const PCR_RESET_COUNTER_ORG: u32 = DPE_ORG + DPE_SIZE;
pub const AUTH_MAN_IMAGE_METADATA_LIST_ORG: u32 = PCR_RESET_COUNTER_ORG + PCR_RESET_COUNTER_SIZE;
pub const IDEVID_CSR_ORG: u32 = AUTH_MAN_IMAGE_METADATA_LIST_ORG + AUTH_MAN_IMAGE_METADATA_MAX_SIZE;
pub const DATA_ORG: u32 = IDEVID_CSR_ORG + IDEVID_CSR_SIZE;
pub const ECC384_IDEVID_CSR_ORG: u32 =
AUTH_MAN_IMAGE_METADATA_LIST_ORG + AUTH_MAN_IMAGE_METADATA_MAX_SIZE;
pub const MLDSA87_IDEVID_CSR_ORG: u32 = ECC384_IDEVID_CSR_ORG + ECC384_IDEVID_CSR_SIZE;
pub const DATA_ORG: u32 = MLDSA87_IDEVID_CSR_ORG + MLDSA87_IDEVID_CSR_SIZE;

pub const STACK_ORG: u32 = DATA_ORG + DATA_SIZE;
pub const ROM_STACK_ORG: u32 = STACK_ORG + (STACK_SIZE - ROM_STACK_SIZE);
Expand All @@ -56,6 +58,8 @@ pub const ROM_ESTACK_ORG: u32 = ESTACK_ORG;
pub const NSTACK_ORG: u32 = ROM_ESTACK_ORG + ROM_ESTACK_SIZE;
pub const ROM_NSTACK_ORG: u32 = NSTACK_ORG;

pub const LAST_REGION_END: u32 = NSTACK_ORG + NSTACK_SIZE;

//
// Memory Sizes In Bytes
//
Expand All @@ -78,8 +82,9 @@ pub const FUSE_LOG_SIZE: u32 = 1024;
pub const DPE_SIZE: u32 = 5 * 1024;
pub const PCR_RESET_COUNTER_SIZE: u32 = 1024;
pub const AUTH_MAN_IMAGE_METADATA_MAX_SIZE: u32 = 7 * 1024;
pub const IDEVID_CSR_SIZE: u32 = 1024;
pub const DATA_SIZE: u32 = 130 * 1024;
pub const ECC384_IDEVID_CSR_SIZE: u32 = 1024;
pub const MLDSA87_IDEVID_CSR_SIZE: u32 = 8 * 1024;
pub const DATA_SIZE: u32 = 122 * 1024;
pub const STACK_SIZE: u32 = 64 * 1024;
pub const ROM_STACK_SIZE: u32 = 14 * 1024;
pub const ESTACK_SIZE: u32 = 1024;
Expand Down Expand Up @@ -173,7 +178,16 @@ fn mem_layout_test_pcr_reset_counter() {
#[test]
#[allow(clippy::assertions_on_constants)]
fn mem_layout_test_idevid_csr() {
assert_eq!((DATA_ORG - IDEVID_CSR_ORG), IDEVID_CSR_SIZE);
assert_eq!(
(MLDSA87_IDEVID_CSR_ORG - ECC384_IDEVID_CSR_ORG),
ECC384_IDEVID_CSR_SIZE
);
}

#[test]
#[allow(clippy::assertions_on_constants)]
fn mem_layout_test_mldsa87_idevid_csr() {
assert_eq!((DATA_ORG - MLDSA87_IDEVID_CSR_ORG), MLDSA87_IDEVID_CSR_SIZE);
}

#[test]
Expand All @@ -193,3 +207,9 @@ fn mem_layout_test_stack() {
fn mem_layout_test_estack() {
assert_eq!((NSTACK_ORG - ESTACK_ORG), ESTACK_SIZE);
}

#[test]
#[allow(clippy::assertions_on_constants)]
fn dccm_overflow() {
assert!(DCCM_ORG + DCCM_SIZE >= LAST_REGION_END);
}
128 changes: 81 additions & 47 deletions drivers/src/persistent.rs
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,8 @@ use crate::{
#[cfg(feature = "runtime")]
use crate::pcr_reset::PcrResetCounter;

pub const MAX_CSR_SIZE: usize = 512;
pub const ECC384_MAX_CSR_SIZE: usize = 512;
pub const MLDSA87_MAX_CSR_SIZE: usize = 7680;
pub const PCR_LOG_MAX_COUNT: usize = 17;
pub const FUSE_LOG_MAX_COUNT: usize = 62;
pub const MEASUREMENT_MAX_COUNT: usize = 8;
Expand All @@ -47,62 +48,86 @@ pub type AuthManifestImageMetadataList =

#[derive(Clone, FromBytes, AsBytes, Zeroize)]
#[repr(C)]
pub struct IdevIdCsr {
pub struct Ecc384IdevIdCsr {
csr_len: u32,
csr: [u8; MAX_CSR_SIZE],
csr: [u8; ECC384_MAX_CSR_SIZE],
}

impl Default for IdevIdCsr {
#[derive(Clone, FromBytes, AsBytes, Zeroize)]
#[repr(C)]
pub struct Mldsa87IdevIdCsr {
csr_len: u32,
csr: [u8; MLDSA87_MAX_CSR_SIZE],
}

impl Default for Ecc384IdevIdCsr {
fn default() -> Self {
Self {
csr_len: Self::UNPROVISIONED_CSR,
csr: [0; MAX_CSR_SIZE],
csr: [0; ECC384_MAX_CSR_SIZE],
}
}
}

impl IdevIdCsr {
/// The `csr_len` field is set to this constant when a ROM image supports CSR generation but
/// the CSR generation flag was not enabled.
///
/// This is used by the runtime to distinguish ROM images that support CSR generation from
/// ones that do not.
///
/// u32::MAX is too large to be a valid CSR, so we use it to encode this state.
pub const UNPROVISIONED_CSR: u32 = u32::MAX;

/// Get the CSR buffer
pub fn get(&self) -> Option<&[u8]> {
self.csr.get(..self.csr_len as usize)
}

/// Create `Self` from a csr slice. `csr_len` MUST be the actual length of the csr.
pub fn new(csr_buf: &[u8], csr_len: usize) -> CaliptraResult<Self> {
if csr_len >= MAX_CSR_SIZE {
return Err(CaliptraError::ROM_IDEVID_INVALID_CSR);
impl Default for Mldsa87IdevIdCsr {
fn default() -> Self {
Self {
csr_len: Self::UNPROVISIONED_CSR,
csr: [0; MLDSA87_MAX_CSR_SIZE],
}

let mut _self = Self {
csr_len: csr_len as u32,
csr: [0; MAX_CSR_SIZE],
};
_self.csr[..csr_len].copy_from_slice(&csr_buf[..csr_len]);

Ok(_self)
}

/// Get the length of the CSR in bytes.
pub fn get_csr_len(&self) -> u32 {
self.csr_len
}
}

/// Check if the CSR was unprovisioned
pub fn is_unprovisioned(&self) -> bool {
self.csr_len == Self::UNPROVISIONED_CSR
}
macro_rules! impl_idevid_csr {
($type:ty, $size:expr) => {
impl $type {
/// The `csr_len` field is set to this constant when a ROM image supports CSR generation but
/// the CSR generation flag was not enabled.
///
/// This is used by the runtime to distinguish ROM images that support CSR generation from
/// ones that do not.
///
/// u32::MAX is too large to be a valid CSR, so we use it to encode this state.
pub const UNPROVISIONED_CSR: u32 = u32::MAX;

/// Get the CSR buffer
pub fn get(&self) -> Option<&[u8]> {
self.csr.get(..self.csr_len as usize)
}

/// Create `Self` from a csr slice. `csr_len` MUST be the actual length of the csr.
pub fn new(csr_buf: &[u8], csr_len: usize) -> CaliptraResult<Self> {
if csr_len >= $size {
return Err(CaliptraError::ROM_IDEVID_INVALID_CSR);
}

let mut _self = Self {
csr_len: csr_len as u32,
csr: [0; $size],
};
_self.csr[..csr_len].copy_from_slice(&csr_buf[..csr_len]);

Ok(_self)
}

/// Get the length of the CSR in bytes.
pub fn get_csr_len(&self) -> u32 {
self.csr_len
}

/// Check if the CSR was unprovisioned
pub fn is_unprovisioned(&self) -> bool {
self.csr_len == Self::UNPROVISIONED_CSR
}
}
};
}

const _: () = assert!(size_of::<IdevIdCsr>() < memory_layout::IDEVID_CSR_SIZE as usize);
impl_idevid_csr!(Ecc384IdevIdCsr, ECC384_MAX_CSR_SIZE);
impl_idevid_csr!(Mldsa87IdevIdCsr, MLDSA87_MAX_CSR_SIZE);

const _: () =
assert!(size_of::<Ecc384IdevIdCsr>() < memory_layout::ECC384_IDEVID_CSR_SIZE as usize);

#[derive(FromBytes, AsBytes, Zeroize)]
#[repr(C)]
Expand Down Expand Up @@ -166,8 +191,13 @@ pub struct PersistentData {
pub auth_manifest_image_metadata_col:
[u8; memory_layout::AUTH_MAN_IMAGE_METADATA_MAX_SIZE as usize],

pub idevid_csr: IdevIdCsr,
reserved10: [u8; memory_layout::IDEVID_CSR_SIZE as usize - size_of::<IdevIdCsr>()],
pub ecc384_idevid_csr: Ecc384IdevIdCsr,
reserved10: [u8; memory_layout::ECC384_IDEVID_CSR_SIZE as usize - size_of::<Ecc384IdevIdCsr>()],

// New field addition
pub mldsa87_idevid_csr: Mldsa87IdevIdCsr,
reserved11:
[u8; memory_layout::MLDSA87_IDEVID_CSR_SIZE as usize - size_of::<Mldsa87IdevIdCsr>()],
}

impl PersistentData {
Expand Down Expand Up @@ -201,12 +231,16 @@ impl PersistentData {
memory_layout::AUTH_MAN_IMAGE_METADATA_LIST_ORG
);
assert_eq!(
addr_of!((*P).idevid_csr) as u32,
memory_layout::IDEVID_CSR_ORG
addr_of!((*P).ecc384_idevid_csr) as u32,
memory_layout::ECC384_IDEVID_CSR_ORG
);
assert_eq!(
addr_of!((*P).mldsa87_idevid_csr) as u32,
memory_layout::MLDSA87_IDEVID_CSR_ORG
);
assert_eq!(
P.add(1) as u32,
memory_layout::IDEVID_CSR_ORG + memory_layout::IDEVID_CSR_SIZE
memory_layout::MLDSA87_IDEVID_CSR_ORG + memory_layout::MLDSA87_IDEVID_CSR_SIZE
);
}
}
Expand Down
10 changes: 5 additions & 5 deletions fmc/src/flow/rt_alias.rs
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ use caliptra_drivers::{
okref, report_boot_status, CaliptraError, CaliptraResult, Ecc384Result, KeyId, PersistentData,
ResetReason,
};
use caliptra_x509::{NotAfter, NotBefore, RtAliasCertTbs, RtAliasCertTbsParams};
use caliptra_x509::{NotAfter, NotBefore, RtAliasCertTbsEcc384, RtAliasCertTbsEcc384Params};

const SHA384_HASH_SIZE: usize = 48;

Expand Down Expand Up @@ -271,8 +271,8 @@ impl RtAliasLayer {
env: &mut FmcEnv,
input: &DiceInput,
output: &DiceOutput,
not_before: &[u8; RtAliasCertTbsParams::NOT_BEFORE_LEN],
not_after: &[u8; RtAliasCertTbsParams::NOT_AFTER_LEN],
not_before: &[u8; RtAliasCertTbsEcc384Params::NOT_BEFORE_LEN],
not_after: &[u8; RtAliasCertTbsEcc384Params::NOT_AFTER_LEN],
) -> CaliptraResult<()> {
let auth_priv_key = input.auth_key_pair.priv_key;
let auth_pub_key = &input.auth_key_pair.pub_key;
Expand All @@ -284,7 +284,7 @@ impl RtAliasLayer {
let rt_svn = HandOff::rt_svn(env) as u8;

// Certificate `To Be Signed` Parameters
let params = RtAliasCertTbsParams {
let params = RtAliasCertTbsEcc384Params {
// Do we need the UEID here?
ueid: &X509::ueid(env)?,
subject_sn: &output.subj_sn,
Expand All @@ -301,7 +301,7 @@ impl RtAliasLayer {
};

// Generate the `To Be Signed` portion of the CSR
let tbs = RtAliasCertTbs::new(&params);
let tbs = RtAliasCertTbsEcc384::new(&params);

// Sign the `To Be Signed` portion
cprintln!(
Expand Down
36 changes: 36 additions & 0 deletions rom/dev/src/crypto.rs
Original file line number Diff line number Diff line change
Expand Up @@ -322,4 +322,40 @@ impl Crypto {
pub_key,
})
}

/// Sign the data using MLDSA Private Key.
/// Verify the signature using the MLDSA Public Key.
///
/// This routine calculates the digest of the `data`, signs the hash and returns the signature.
/// This routine also verifies the signature using the public key.
///
/// # Arguments
///
/// * `env` - ROM Environment
/// * `priv_key` - Key slot to retrieve the private key
/// * `data` - Input data to hash
///
/// # Returns
///
/// * `Mldsa384Signature` - Signature
#[inline(always)]
pub fn mldsa87_sign_and_verify(
env: &mut RomEnv,
priv_key: KeyId,
pub_key: &Mldsa87PubKey,
data: &[u8],
) -> CaliptraResult<Mldsa87Signature> {
let mut digest = Self::sha512_digest(env, data);
let digest = okmutref(&mut digest)?;
let priv_key_args = KeyReadArgs::new(priv_key);
let result = env.mldsa87.sign(
&priv_key_args,
pub_key,
digest,
&Mldsa87SignRnd::default(),
&mut env.trng,
);
digest.0.zeroize();
result
}
}
6 changes: 3 additions & 3 deletions rom/dev/src/flow/cold_reset/fmc_alias.rs
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ use caliptra_common::RomBootStatus::*;
use caliptra_drivers::{
okmutref, report_boot_status, Array4x12, CaliptraResult, HmacMode, KeyId, Lifecycle,
};
use caliptra_x509::{FmcAliasCertTbs, FmcAliasCertTbsParams};
use caliptra_x509::{FmcAliasCertTbsEcc384, FmcAliasCertTbsEcc384Params};
use zeroize::Zeroize;

#[derive(Default)]
Expand Down Expand Up @@ -219,7 +219,7 @@ impl FmcAliasLayer {
hasher.finalize(&mut fuse_info_digest)?;

// Certificate `To Be Signed` Parameters
let params = FmcAliasCertTbsParams {
let params = FmcAliasCertTbsEcc384Params {
ueid: &X509::ueid(env)?,
subject_sn: &output.ecc_subj_sn,
subject_key_id: &output.ecc_subj_key_id,
Expand All @@ -237,7 +237,7 @@ impl FmcAliasLayer {
};

// Generate the `To Be Signed` portion of the CSR
let tbs = FmcAliasCertTbs::new(&params);
let tbs = FmcAliasCertTbsEcc384::new(&params);

// Sign the `To Be Signed` portion
cprintln!(
Expand Down
2 changes: 1 addition & 1 deletion rom/dev/src/flow/cold_reset/fw_processor.rs
Original file line number Diff line number Diff line change
Expand Up @@ -316,7 +316,7 @@ impl FirmwareProcessor {
let mut request = MailboxReqHeader::default();
Self::copy_req_verify_chksum(&mut txn, request.as_bytes_mut())?;

let csr_persistent_mem = &persistent_data.idevid_csr;
let csr_persistent_mem = &persistent_data.ecc384_idevid_csr;
let mut resp = GetIdevCsrResp::default();

if csr_persistent_mem.is_unprovisioned() {
Expand Down
Loading

0 comments on commit 281864d

Please sign in to comment.