Skip to content

Commit

Permalink
Add idevid CSR with MLDSA87
Browse files Browse the repository at this point in the history
This increase in struct size requires the stack to be reduced.
  • Loading branch information
ArthurHeymans committed Dec 11, 2024
1 parent 716d695 commit eae2f78
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 = 148 * 1024;
pub const ECC384_IDEVID_CSR_SIZE: u32 = 1024;
pub const MLDSA87_IDEVID_CSR_SIZE: u32 = 8 * 1024;
pub const DATA_SIZE: u32 = 140 * 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 @@ -321,4 +321,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.mldsa.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 @@ -315,7 +315,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 eae2f78

Please sign in to comment.