From 98df8cbd3b3cf7d2c5c0bc419301bf73e1abc564 Mon Sep 17 00:00:00 2001 From: Vishal Mhatre <38512878+mhatrevi@users.noreply.github.com> Date: Wed, 20 Nov 2024 09:59:02 -0800 Subject: [PATCH 1/2] [feat] ROM LDEVID DICE changes for MLDSA support (#1798) --- rom/dev/src/flow/cold_reset/crypto.rs | 10 +- rom/dev/src/flow/cold_reset/dice.rs | 21 +++- rom/dev/src/flow/cold_reset/fmc_alias.rs | 20 ++-- rom/dev/src/flow/cold_reset/idev_id.rs | 30 +++-- rom/dev/src/flow/cold_reset/ldev_id.rs | 111 +++++++++++------- rom/dev/src/flow/cold_reset/mod.rs | 9 +- rom/dev/src/flow/cold_reset/x509.rs | 74 +++++++++--- test/src/derive.rs | 8 +- .../fmc_alias_cert_redacted.der | Bin 874 -> 874 bytes .../fmc_alias_cert_redacted.txt | 4 +- .../smoke_testdata/ldevid_cert.der | Bin 673 -> 674 bytes .../smoke_testdata/ldevid_cert.txt | 32 ++--- 12 files changed, 203 insertions(+), 116 deletions(-) diff --git a/rom/dev/src/flow/cold_reset/crypto.rs b/rom/dev/src/flow/cold_reset/crypto.rs index 9a816fd3e2..04b4079e78 100644 --- a/rom/dev/src/flow/cold_reset/crypto.rs +++ b/rom/dev/src/flow/cold_reset/crypto.rs @@ -37,7 +37,7 @@ impl Ecdsa384SignatureAdapter for Ecc384Signature { } } -/// DICE Layer Key Pair +/// DICE Layer ECC Key Pair #[derive(Debug, Zeroize)] pub struct Ecc384KeyPair { /// Private Key KV Slot Id @@ -48,7 +48,7 @@ pub struct Ecc384KeyPair { pub pub_key: Ecc384PubKey, } -/// DICE Layer Key Pair +/// DICE Layer MLDSA Key Pair #[derive(Debug, Zeroize)] pub struct MlDsaKeyPair { /// Key Pair Generation KV Slot Id @@ -59,6 +59,12 @@ pub struct MlDsaKeyPair { pub pub_key: Mldsa87PubKey, } +#[derive(Debug)] +pub enum PubKey<'a> { + Ecc(&'a Ecc384PubKey), + Mldsa(&'a Mldsa87PubKey), +} + pub enum Crypto {} impl Crypto { diff --git a/rom/dev/src/flow/cold_reset/dice.rs b/rom/dev/src/flow/cold_reset/dice.rs index f0a234b740..92b5a19c56 100644 --- a/rom/dev/src/flow/cold_reset/dice.rs +++ b/rom/dev/src/flow/cold_reset/dice.rs @@ -19,14 +19,23 @@ use zeroize::Zeroize; /// DICE Layer Input #[derive(Debug)] pub struct DiceInput<'a> { - /// Authority Key Pair - pub auth_key_pair: &'a Ecc384KeyPair, + /// ECC Authority Key Pair + pub ecc_auth_key_pair: &'a Ecc384KeyPair, - /// Authority Serial Number - pub auth_sn: &'a [u8; 64], + /// ECC Authority Serial Number + pub ecc_auth_sn: &'a [u8; 64], - /// Authority Key Identifier - pub auth_key_id: &'a [u8; 20], + /// ECC Authority Key Identifier + pub ecc_auth_key_id: &'a [u8; 20], + + /// MLDSA Authority Key Pair + pub mldsa_auth_key_pair: &'a MlDsaKeyPair, + + /// MLDSA Authority Serial Number + pub mldsa_auth_sn: &'a [u8; 64], + + /// MLDSA Authority Key Identifier + pub mldsa_auth_key_id: &'a [u8; 20], } /// DICE Layer Output diff --git a/rom/dev/src/flow/cold_reset/fmc_alias.rs b/rom/dev/src/flow/cold_reset/fmc_alias.rs index 94f1ba18ca..e6a02bdeb7 100644 --- a/rom/dev/src/flow/cold_reset/fmc_alias.rs +++ b/rom/dev/src/flow/cold_reset/fmc_alias.rs @@ -18,7 +18,7 @@ use super::dice::{DiceInput, DiceOutput}; use super::fw_processor::FwProcInfo; use super::x509::X509; use crate::cprintln; -use crate::flow::cold_reset::crypto::MlDsaKeyPair; +use crate::flow::cold_reset::crypto::{MlDsaKeyPair, PubKey}; use crate::flow::cold_reset::{copy_tbs, TbsType}; use crate::print::HexBytes; use crate::rom_env::RomEnv; @@ -50,8 +50,8 @@ impl FmcAliasLayer { cprintln!("[afmc] CDI.KEYID = {}", KEY_ID_ROM_FMC_CDI as u8); cprintln!("[afmc] SUBJECT.KEYID = {}", KEY_ID_FMC_ECDSA_PRIV_KEY as u8); cprintln!( - "[afmc] AUTHORITY.KEYID = {}", - input.auth_key_pair.priv_key as u8 + "[afmc] ECC AUTHORITY.KEYID = {}", + input.ecc_auth_key_pair.priv_key as u8 ); // We use the value of PCR0 as the measurement for deriving the CDI. @@ -70,10 +70,10 @@ impl FmcAliasLayer { // // This information will be used by next DICE Layer while generating // certificates - let ecc_subj_sn = X509::subj_sn(env, &ecc_key_pair.pub_key)?; + let ecc_subj_sn = X509::subj_sn(env, &PubKey::Ecc(&ecc_key_pair.pub_key))?; report_boot_status(FmcAliasSubjIdSnGenerationComplete.into()); - let ecc_subj_key_id = X509::subj_key_id(env, &ecc_key_pair.pub_key)?; + let ecc_subj_key_id = X509::subj_key_id(env, &PubKey::Ecc(&ecc_key_pair.pub_key))?; report_boot_status(FmcAliasSubjKeyIdGenerationComplete.into()); // Generate the output for next layer @@ -158,8 +158,8 @@ impl FmcAliasLayer { output: &DiceOutput, fw_proc_info: &FwProcInfo, ) -> CaliptraResult<()> { - let auth_priv_key = input.auth_key_pair.priv_key; - let auth_pub_key = &input.auth_key_pair.pub_key; + let auth_priv_key = input.ecc_auth_key_pair.priv_key; + let auth_pub_key = &input.ecc_auth_key_pair.pub_key; let pub_key = &output.ecc_subj_key_pair.pub_key; let flags = Self::make_flags(env.soc_ifc.lifecycle(), env.soc_ifc.debug_locked()); @@ -189,9 +189,9 @@ impl FmcAliasLayer { ueid: &X509::ueid(env)?, subject_sn: &output.ecc_subj_sn, subject_key_id: &output.ecc_subj_key_id, - issuer_sn: input.auth_sn, - authority_key_id: input.auth_key_id, - serial_number: &X509::cert_sn(env, pub_key)?, + issuer_sn: input.ecc_auth_sn, + authority_key_id: input.ecc_auth_key_id, + serial_number: &X509::ecc_cert_sn(env, pub_key)?, public_key: &pub_key.to_der(), tcb_info_fmc_tci: &(&env.data_vault.fmc_tci()).into(), tcb_info_device_info_hash: &fuse_info_digest.into(), diff --git a/rom/dev/src/flow/cold_reset/idev_id.rs b/rom/dev/src/flow/cold_reset/idev_id.rs index 6397edb54a..2168d19d57 100644 --- a/rom/dev/src/flow/cold_reset/idev_id.rs +++ b/rom/dev/src/flow/cold_reset/idev_id.rs @@ -88,22 +88,23 @@ impl InitDevIdLayer { // Generate the Subject Serial Number and Subject Key Identifier for ECC. // This information will be used by next DICE Layer while generating // certificates - let ecc_subj_sn = X509::subj_sn(env, &ecc_key_pair.pub_key)?; + let ecc_subj_sn = X509::subj_sn(env, &PubKey::Ecc(&ecc_key_pair.pub_key))?; + let mldsa_subj_sn = X509::subj_sn(env, &PubKey::Mldsa(&mldsa_key_pair.pub_key))?; report_boot_status(IDevIdSubjIdSnGenerationComplete.into()); - let ecc_subj_key_id = X509::idev_subj_key_id(env, &ecc_key_pair.pub_key)?; + let ecc_subj_key_id = X509::idev_subj_key_id(env, &PubKey::Ecc(&ecc_key_pair.pub_key))?; + let mldsa_subj_key_id = + X509::idev_subj_key_id(env, &PubKey::Mldsa(&mldsa_key_pair.pub_key))?; report_boot_status(IDevIdSubjKeyIdGenerationComplete.into()); - // [TODO] Generate the Subject Serial Number and Subject Key Identifier for MLDSA. - // Generate the output for next layer let output = DiceOutput { ecc_subj_key_pair: ecc_key_pair, ecc_subj_sn, ecc_subj_key_id, - mldsa_subj_key_id: [0; 20], + mldsa_subj_key_id, mldsa_subj_key_pair: mldsa_key_pair, - mldsa_subj_sn: [0; 64], + mldsa_subj_sn, }; // Generate the Initial DevID Certificate Signing Request (CSR) @@ -193,7 +194,7 @@ impl InitDevIdLayer { /// /// * `env` - ROM Environment /// * `cdi` - Composite Device Identity - /// * `ecdsa_priv_key` - Key slot to store the ECC private key into + /// * `ecc_priv_key` - Key slot to store the ECC private key into /// * `mldsa_keypair_seed` - Key slot to store the MLDSA key pair seed /// /// # Returns @@ -203,10 +204,10 @@ impl InitDevIdLayer { fn derive_key_pair( env: &mut RomEnv, cdi: KeyId, - ecdsa_priv_key: KeyId, + ecc_priv_key: KeyId, mldsa_keypair_seed: KeyId, ) -> CaliptraResult<(Ecc384KeyPair, MlDsaKeyPair)> { - let result = Crypto::ecc384_key_gen(env, cdi, b"idevid_ecc_key", ecdsa_priv_key); + let result = Crypto::ecc384_key_gen(env, cdi, b"idevid_ecc_key", ecc_priv_key); if cfi_launder(result.is_ok()) { cfi_assert!(result.is_ok()); } else { @@ -215,11 +216,16 @@ impl InitDevIdLayer { let ecc_keypair = result?; // Derive the MLDSA Key Pair. - let mldsa_key_pair = - Crypto::mldsa_key_gen(env, cdi, b"idevid_mldsa_key", mldsa_keypair_seed)?; + let result = Crypto::mldsa_key_gen(env, cdi, b"idevid_mldsa_key", mldsa_keypair_seed); + if cfi_launder(result.is_ok()) { + cfi_assert!(result.is_ok()); + } else { + cfi_assert!(result.is_err()); + } + let mldsa_keypair = result?; report_boot_status(IDevIdKeyPairDerivationComplete.into()); - Ok((ecc_keypair, mldsa_key_pair)) + Ok((ecc_keypair, mldsa_keypair)) } /// Generate Local Device ID CSR diff --git a/rom/dev/src/flow/cold_reset/ldev_id.rs b/rom/dev/src/flow/cold_reset/ldev_id.rs index f294185be1..8f2c1f35db 100644 --- a/rom/dev/src/flow/cold_reset/ldev_id.rs +++ b/rom/dev/src/flow/cold_reset/ldev_id.rs @@ -50,12 +50,14 @@ impl LocalDevIdLayer { cprintln!("[ldev] ++"); cprintln!("[ldev] CDI.KEYID = {}", KEY_ID_ROM_FMC_CDI as u8); cprintln!( - "[ldev] SUBJECT.KEYID = {}", - KEY_ID_LDEVID_ECDSA_PRIV_KEY as u8 + "[ldev] ECC SUBJECT.KEYID = {}, MLDSA SUBJECT.KEYID = {}", + KEY_ID_LDEVID_ECDSA_PRIV_KEY as u8, + KEY_ID_LDEVID_MLDSA_KEYPAIR_SEED as u8, ); cprintln!( - "[ldev] AUTHORITY.KEYID = {}", - input.auth_key_pair.priv_key as u8 + "[ldev] ECC AUTHORITY.KEYID = {}, MLDSA AUTHORITY.KEYID = {}", + input.ecc_auth_key_pair.priv_key as u8, + input.mldsa_auth_key_pair.key_pair_seed as u8, ); cprintln!("[ldev] FE.KEYID = {}", KEY_ID_FE as u8); @@ -65,31 +67,34 @@ impl LocalDevIdLayer { // This is the decrypted Field Entropy Self::derive_cdi(env, KEY_ID_FE, KEY_ID_ROM_FMC_CDI)?; - // Derive DICE Key Pair from CDI - let key_pair = - Self::derive_key_pair(env, KEY_ID_ROM_FMC_CDI, KEY_ID_LDEVID_ECDSA_PRIV_KEY)?; + // Derive DICE ECC and MLDSA Key Pairs from CDI + let (ecc_key_pair, mldsa_key_pair) = Self::derive_key_pair( + env, + KEY_ID_ROM_FMC_CDI, + KEY_ID_LDEVID_ECDSA_PRIV_KEY, + KEY_ID_LDEVID_MLDSA_KEYPAIR_SEED, + )?; // Generate the Subject Serial Number and Subject Key Identifier. // // This information will be used by the next DICE Layer while generating // certificates - let ecc_subj_sn = X509::subj_sn(env, &key_pair.pub_key)?; + let ecc_subj_sn = X509::subj_sn(env, &PubKey::Ecc(&ecc_key_pair.pub_key))?; + let mldsa_subj_sn = X509::subj_sn(env, &PubKey::Mldsa(&mldsa_key_pair.pub_key))?; report_boot_status(LDevIdSubjIdSnGenerationComplete.into()); - let ecc_subj_key_id = X509::subj_key_id(env, &key_pair.pub_key)?; + let ecc_subj_key_id = X509::subj_key_id(env, &PubKey::Ecc(&ecc_key_pair.pub_key))?; + let mldsa_subj_key_id = X509::subj_key_id(env, &PubKey::Mldsa(&mldsa_key_pair.pub_key))?; report_boot_status(LDevIdSubjKeyIdGenerationComplete.into()); // Generate the output for next layer let output = DiceOutput { - ecc_subj_key_pair: key_pair, + ecc_subj_key_pair: ecc_key_pair, ecc_subj_sn, ecc_subj_key_id, - mldsa_subj_key_id: [0; 20], - mldsa_subj_key_pair: MlDsaKeyPair { - key_pair_seed: KEY_ID_LDEVID_MLDSA_KEYPAIR_SEED, - pub_key: Default::default(), - }, - mldsa_subj_sn: [0; 64], + mldsa_subj_key_pair: mldsa_key_pair, + mldsa_subj_sn, + mldsa_subj_key_id, }; // Generate Local Device ID Certificate @@ -125,25 +130,38 @@ impl LocalDevIdLayer { /// /// * `env` - ROM Environment /// * `cdi` - Composite Device Identity - /// * `priv_key` - Key slot to store the private key into + /// * `ecc_priv_key` - Key slot to store the ECC private key into + /// * `mldsa_keypair_seed` - Key slot to store the MLDSA key pair seed /// /// # Returns /// - /// * `Ecc384KeyPair` - Derive DICE Layer Key Pair + /// * `(Ecc384KeyPair, MlDsaKeyPair)` - DICE Layer ECC and MLDSA Key Pairs #[cfg_attr(not(feature = "no-cfi"), cfi_impl_fn)] fn derive_key_pair( env: &mut RomEnv, cdi: KeyId, - priv_key: KeyId, - ) -> CaliptraResult { - let result = Crypto::ecc384_key_gen(env, cdi, b"ldevid_keygen", priv_key); + ecc_priv_key: KeyId, + mldsa_keypair_seed: KeyId, + ) -> CaliptraResult<(Ecc384KeyPair, MlDsaKeyPair)> { + let result = Crypto::ecc384_key_gen(env, cdi, b"ldevid_ecc_key", ecc_priv_key); if cfi_launder(result.is_ok()) { cfi_assert!(result.is_ok()); - report_boot_status(LDevIdKeyPairDerivationComplete.into()); } else { cfi_assert!(result.is_err()); } - result + let ecc_keypair = result?; + + // Derive the MLDSA Key Pair. + let result = Crypto::mldsa_key_gen(env, cdi, b"ldevid_mldsa_key", mldsa_keypair_seed); + if cfi_launder(result.is_ok()) { + cfi_assert!(result.is_ok()); + } else { + cfi_assert!(result.is_err()); + } + let mldsa_keypair = result?; + + report_boot_status(LDevIdKeyPairDerivationComplete.into()); + Ok((ecc_keypair, mldsa_keypair)) } /// Generate Local Device ID Certificate Signature @@ -158,45 +176,50 @@ impl LocalDevIdLayer { input: &DiceInput, output: &DiceOutput, ) -> CaliptraResult<()> { - let auth_priv_key = input.auth_key_pair.priv_key; - let auth_pub_key = &input.auth_key_pair.pub_key; - let pub_key = &output.ecc_subj_key_pair.pub_key; + let ecc_auth_priv_key = input.ecc_auth_key_pair.priv_key; + let ecc_auth_pub_key = &input.ecc_auth_key_pair.pub_key; + let ecc_pub_key = &output.ecc_subj_key_pair.pub_key; - let serial_number = X509::cert_sn(env, pub_key); - let serial_number = okref(&serial_number)?; + let ecc_serial_number = X509::ecc_cert_sn(env, ecc_pub_key); + let ecc_serial_number = okref(&ecc_serial_number)?; // CSR `To Be Signed` Parameters - let params = LocalDevIdCertTbsParams { + let ecc_tbs_params = LocalDevIdCertTbsParams { ueid: &X509::ueid(env)?, subject_sn: &output.ecc_subj_sn, subject_key_id: &output.ecc_subj_key_id, - issuer_sn: input.auth_sn, - authority_key_id: input.auth_key_id, - serial_number, - public_key: &pub_key.to_der(), + issuer_sn: input.ecc_auth_sn, + authority_key_id: input.ecc_auth_key_id, + serial_number: ecc_serial_number, + public_key: &ecc_pub_key.to_der(), not_before: &NotBefore::default().value, not_after: &NotAfter::default().value, }; - // Generate the `To Be Signed` portion of the CSR - let tbs = LocalDevIdCertTbs::new(¶ms); + // Generate the ECC `To Be Signed` portion of the CSR + let ecc_tbs = LocalDevIdCertTbs::new(&ecc_tbs_params); // Sign the `To Be Signed` portion cprintln!( - "[ldev] Signing Cert w/ AUTHORITY.KEYID = {}", - auth_priv_key as u8 + "[ldev] Signing Cert with ECC AUTHORITY.KEYID = {}", + ecc_auth_priv_key as u8 + ); + let mut sig = Crypto::ecdsa384_sign_and_verify( + env, + ecc_auth_priv_key, + ecc_auth_pub_key, + ecc_tbs.tbs(), ); - let mut sig = Crypto::ecdsa384_sign_and_verify(env, auth_priv_key, auth_pub_key, tbs.tbs()); let sig = okmutref(&mut sig)?; // Clear the authority private key - env.key_vault.erase_key(auth_priv_key).map_err(|err| { + env.key_vault.erase_key(ecc_auth_priv_key).map_err(|err| { sig.zeroize(); err })?; - let _pub_x: [u8; 48] = (&pub_key.x).into(); - let _pub_y: [u8; 48] = (&pub_key.y).into(); + let _pub_x: [u8; 48] = (&ecc_pub_key.x).into(); + let _pub_y: [u8; 48] = (&ecc_pub_key.y).into(); cprintln!("[ldev] PUB.X = {}", HexBytes(&_pub_x)); cprintln!("[ldev] PUB.Y = {}", HexBytes(&_pub_y)); @@ -212,10 +235,12 @@ impl LocalDevIdLayer { // Lock the Local Device ID public key in data vault until // cold reset - env.data_vault.set_ldev_dice_pub_key(pub_key); + env.data_vault.set_ldev_dice_pub_key(ecc_pub_key); // Copy TBS to DCCM. - copy_tbs(tbs.tbs(), TbsType::LdevidTbs, env)?; + copy_tbs(ecc_tbs.tbs(), TbsType::LdevidTbs, env)?; + + // [CAP2][TODO] Generate the MLDSA TBS report_boot_status(LDevIdCertSigGenerationComplete.into()); Ok(()) diff --git a/rom/dev/src/flow/cold_reset/mod.rs b/rom/dev/src/flow/cold_reset/mod.rs index 9beee585da..0b07a8d003 100644 --- a/rom/dev/src/flow/cold_reset/mod.rs +++ b/rom/dev/src/flow/cold_reset/mod.rs @@ -130,8 +130,11 @@ pub fn copy_tbs(tbs: &[u8], tbs_type: TbsType, env: &mut RomEnv) -> CaliptraResu fn dice_input_from_output(dice_output: &DiceOutput) -> DiceInput { DiceInput { - auth_key_pair: &dice_output.ecc_subj_key_pair, - auth_sn: &dice_output.ecc_subj_sn, - auth_key_id: &dice_output.ecc_subj_key_id, + ecc_auth_key_pair: &dice_output.ecc_subj_key_pair, + ecc_auth_sn: &dice_output.ecc_subj_sn, + ecc_auth_key_id: &dice_output.ecc_subj_key_id, + mldsa_auth_key_pair: &dice_output.mldsa_subj_key_pair, + mldsa_auth_sn: &dice_output.mldsa_subj_sn, + mldsa_auth_key_id: &dice_output.mldsa_subj_key_id, } } diff --git a/rom/dev/src/flow/cold_reset/x509.rs b/rom/dev/src/flow/cold_reset/x509.rs index e62dadfdda..c48a63429b 100644 --- a/rom/dev/src/flow/cold_reset/x509.rs +++ b/rom/dev/src/flow/cold_reset/x509.rs @@ -11,10 +11,13 @@ Abstract: File contains X509 Certificate & CSR related utility functions --*/ -use super::crypto::Crypto; +use super::crypto::{Crypto, PubKey}; use crate::cprintln; use crate::rom_env::RomEnv; use caliptra_drivers::*; +use core::mem::size_of; +use core::usize; +use zerocopy::AsBytes; /// X509 API pub enum X509 {} @@ -34,19 +37,51 @@ impl X509 { Ok(ueid) } - /// Get X509 Subject Serial Number + fn get_pubkey_bytes(pub_key: &PubKey, pub_key_bytes: &mut [u8]) -> usize { + fn copy_and_swap_endianess(src: &[u8], dst: &mut [u8]) { + for i in (0..src.len()).step_by(4) { + if i + 3 < src.len() && i + 3 < dst.len() { + dst[i] = src[i + 3]; + dst[i + 1] = src[i + 2]; + dst[i + 2] = src[i + 1]; + dst[i + 3] = src[i]; + } + } + } + + match pub_key { + PubKey::Ecc(pub_key) => { + let ecc_pubkey_der = pub_key.to_der(); + pub_key_bytes[..ecc_pubkey_der.len()].copy_from_slice(&ecc_pubkey_der); + ecc_pubkey_der.len() + } + PubKey::Mldsa(pub_key) => { + // pub_key is in Caliptra Hw format (big-endian DWORDs). Convert it to little-endian DWORDs. + copy_and_swap_endianess(pub_key.0.as_bytes(), pub_key_bytes); + pub_key_bytes.len() + } + } + } + + fn pub_key_digest(env: &mut RomEnv, pub_key: &PubKey) -> CaliptraResult { + // Define an array large enough to hold the largest public key. + let mut pub_key_bytes: [u8; size_of::()] = [0; size_of::()]; + let pub_key_size = Self::get_pubkey_bytes(pub_key, &mut pub_key_bytes); + Crypto::sha256_digest(env, &pub_key_bytes[..pub_key_size]) + } + + /// Get X509 Subject Serial Number from public key /// /// # Arguments /// /// * `env` - ROM Environment - /// * `pub_key` - Public Key + /// * `pub_key` - ECC or MLDSA Public Key /// /// # Returns /// /// `[u8; 64]` - X509 Subject Identifier serial number - pub fn subj_sn(env: &mut RomEnv, pub_key: &Ecc384PubKey) -> CaliptraResult<[u8; 64]> { - let data = pub_key.to_der(); - let digest = Crypto::sha256_digest(env, &data); + pub fn subj_sn(env: &mut RomEnv, pub_key: &PubKey) -> CaliptraResult<[u8; 64]> { + let digest = Self::pub_key_digest(env, pub_key); let digest = okref(&digest)?; Ok(Self::hex(&digest.into())) } @@ -56,29 +91,33 @@ impl X509 { /// # Arguments /// /// * `env` - ROM Environment - /// * `pub_key` - Public Key + /// * `pub_key` - ECC or MLDSA Public Key /// /// # Returns /// /// `[u8; 20]` - X509 Subject Key Identifier - pub fn idev_subj_key_id(env: &mut RomEnv, pub_key: &Ecc384PubKey) -> CaliptraResult<[u8; 20]> { - let data = pub_key.to_der(); + pub fn idev_subj_key_id(env: &mut RomEnv, pub_key: &PubKey) -> CaliptraResult<[u8; 20]> { + let mut pub_key_bytes: [u8; size_of::()] = [0; size_of::()]; + let pub_key_size = Self::get_pubkey_bytes(pub_key, &mut pub_key_bytes); + let data: &[u8] = &pub_key_bytes[..pub_key_size]; + + // [CAP2][TODO] Get the hash algorithm if the key is MLDSA. let digest: [u8; 20] = match env.soc_ifc.fuse_bank().idev_id_x509_key_id_algo() { X509KeyIdAlgo::Sha1 => { cprintln!("[idev] Sha1 KeyId Algorithm"); - let digest = Crypto::sha1_digest(env, &data); + let digest = Crypto::sha1_digest(env, data); okref(&digest)?.into() } X509KeyIdAlgo::Sha256 => { cprintln!("[idev] Sha256 KeyId Algorithm"); - let digest = Crypto::sha256_digest(env, &data); + let digest = Crypto::sha256_digest(env, data); let digest: [u8; 32] = okref(&digest)?.into(); digest[..20].try_into().unwrap() } X509KeyIdAlgo::Sha384 => { cprintln!("[idev] Sha384 KeyId Algorithm"); - let digest = Crypto::sha384_digest(env, &data); + let digest = Crypto::sha384_digest(env, data); let digest: [u8; 48] = okref(&digest)?.into(); digest[..20].try_into().unwrap() } @@ -101,24 +140,23 @@ impl X509 { /// # Returns /// /// `[u8; 20]` - X509 Subject Key Identifier - pub fn subj_key_id(env: &mut RomEnv, pub_key: &Ecc384PubKey) -> CaliptraResult<[u8; 20]> { - let data = pub_key.to_der(); - let digest = Crypto::sha256_digest(env, &data); + pub fn subj_key_id(env: &mut RomEnv, pub_key: &PubKey) -> CaliptraResult<[u8; 20]> { + let digest = Self::pub_key_digest(env, pub_key); let digest: [u8; 32] = okref(&digest)?.into(); Ok(digest[..20].try_into().unwrap()) } - /// Get Cert Serial Number + /// Get Serial Number for ECC certificate. /// /// # Arguments /// /// * `env` - ROM Environment - /// * `pub_key` - Public Key + /// * `pub_key` - ECC Public Key /// /// # Returns /// /// `[u8; 20]` - X509 Serial Number - pub fn cert_sn(env: &mut RomEnv, pub_key: &Ecc384PubKey) -> CaliptraResult<[u8; 20]> { + pub fn ecc_cert_sn(env: &mut RomEnv, pub_key: &Ecc384PubKey) -> CaliptraResult<[u8; 20]> { let data = pub_key.to_der(); let digest = Crypto::sha256_digest(env, &data); let mut digest: [u8; 32] = okref(&digest)?.into(); diff --git a/test/src/derive.rs b/test/src/derive.rs index b7b28bccc0..946007db33 100644 --- a/test/src/derive.rs +++ b/test/src/derive.rs @@ -242,7 +242,7 @@ impl LDevId { let mut priv_key_seed: [u32; 12] = transmute!(hmac384_kdf( swap_word_bytes(&cdi).as_bytes(), - b"ldevid_keygen", + b"ldevid_ecc_key", None )); swap_word_bytes_inplace(&mut priv_key_seed); @@ -285,9 +285,9 @@ fn test_ldevid() { 0x6f1271bc, 0xf35c0619, 0x0856f1e3, 0x7d560cf2, 0xaa227256, ], priv_key: [ - 0xd6cb583, 0x3a6de03c, 0x2cbf7476, 0x5cfd3cf0, 0x36871eae, 0xd4144aea, 0xce3cec09, - 0x8168274, 0xb97d7cfe, 0x5b106642, 0x6c8d2cc2, 0xf2edcb8b, - ], + 0xce7579e1, 0x37fe98bd, 0x54dd77e6, 0xc20331d, 0xe0ae1006, 0x64577cf9, 0xd04306f5, + 0x434d4dde, 0x43974611, 0x1ceb42a1, 0x2b6d1959, 0xbebeb390, + ] } ); } diff --git a/test/tests/caliptra_integration_tests/smoke_testdata/fmc_alias_cert_redacted.der b/test/tests/caliptra_integration_tests/smoke_testdata/fmc_alias_cert_redacted.der index 42eec06ea6733956bd1ca03be62f6337154e9ee8..ce0d4844c5e0260128b759ba3cd5baa1e55be5b5 100644 GIT binary patch delta 99 zcmV-p0G$8o2I>ZoT0ccWHZeFvLPSDEMMW?-I6*TvIX6Q!MKeN0LpC@yHA6HpHZVd% zGcZFmK{PcpGc`CdMmaP?HA6T;G(s~sFtM3P0u<_DjlI6^2Z}eB#pAxlgAW8rL delta 99 zcmaFG_KIynl)aImtE;P$x!ra-_$k4*V z)YQ_=#K6tX($w7C+||Os(8R)G<4g}G5yf}!XZa*v+4=aU_ba!b3$>1Q)I6H}m8lc} Dg$W^* diff --git a/test/tests/caliptra_integration_tests/smoke_testdata/fmc_alias_cert_redacted.txt b/test/tests/caliptra_integration_tests/smoke_testdata/fmc_alias_cert_redacted.txt index 4aede310cc..50bdec9b40 100644 --- a/test/tests/caliptra_integration_tests/smoke_testdata/fmc_alias_cert_redacted.txt +++ b/test/tests/caliptra_integration_tests/smoke_testdata/fmc_alias_cert_redacted.txt @@ -4,7 +4,7 @@ Certificate: Serial Number: 44:44:44:44:44:44:44:44:44:44:44:44:44:44:44:44:44:44:44:44 Signature Algorithm: ecdsa-with-SHA384 - Issuer: CN=Caliptra 1.0 LDevID/serialNumber=21EEEF9A4C61D4B9E3D94BEA46F9A12AC6887CE2188559F40FF95777E8014889 + Issuer: CN=Caliptra 1.0 LDevID/serialNumber=EA618DBDBEEE078A3797C5E3BEC6855C4160BC30C4A4533581F94C5C8B4B3709 Validity Not Before: Jan 1 00:00:00 2023 GMT Not After : Dec 31 23:59:59 9999 GMT @@ -34,7 +34,7 @@ Certificate: X509v3 Subject Key Identifier: 44:44:44:44:44:44:44:44:44:44:44:44:44:44:44:44:44:44:44:44 X509v3 Authority Key Identifier: - 21:EE:EF:9A:4C:61:D4:B9:E3:D9:4B:EA:46:F9:A1:2A:C6:88:7C:E2 + EA:61:8D:BD:BE:EE:07:8A:37:97:C5:E3:BE:C6:85:5C:41:60:BC:30 Signature Algorithm: ecdsa-with-SHA384 Signature Value: 30:64:02:30:44:44:44:44:44:44:44:44:44:44:44:44:44:44: diff --git a/test/tests/caliptra_integration_tests/smoke_testdata/ldevid_cert.der b/test/tests/caliptra_integration_tests/smoke_testdata/ldevid_cert.der index 1d64c96b20617730d1313adb2ec41961c419bfc2..dce4f7d88d22834c7a8d0172c1df5c1b92f8c27e 100644 GIT binary patch delta 364 zcmZ3;x`22^efbj)5l;jr^QO9zgsu7`6bq(v4zUe?$ZIAi{yIllJRru!!=-@jXx z^J#kgDHm1qzXeV#N0+zkZeMg*aa*DVw~J#_`{ad;VIr@v_-ZmYlU`;9gFz~jLBRR< zTKc#D8YlDm-E+Q$%qaM=dDavkCPRjs zuIJN#Se*|sxMIt{bnC77vWFgb8kewI(-m7R}odcSh}xlrp^N6n*&%E#)B3|(Da z-7FnVoXrefOq?uTja@8FoLn7E%z%Q1Mvl&A78d5tu11Cy7N(|_ZYBn9ZkDFz=H{*z z28JdU7M2EO1_EsCT5TTZY?&C@ShX8j7?hZk7+6|#7}m3{IrCa1&`;NV!{JqnBt8a& zf4s9pWs%4X?h?0-1sz>X(|^@k9)0-g#wnqRx0U8-yl$)5^MavChh3@PG3&`(#lF}@ zpDwOgRC{pN{j{!y_T+_(VIqoHd^MSyNiQRv!61dn!2jlk zEPcCQEWhI4ryV+UV_n1<%cWcj)s@>zc5b=)hS?xSG{ks$@x6M#3mh_wXLGJ(GRRZy zzf^qs+2RGqU1yx!dwv)9Rf9tpxObkbb@Wb7TE#l4ZI^5Q#|8$2tj}E Date: Wed, 20 Nov 2024 13:59:23 -0800 Subject: [PATCH 2/2] [feat] ROM ALIAS FMC DICE changes for MLDSA support (#1799) --- rom/dev/src/flow/cold_reset/fmc_alias.rs | 61 ++++++++++++++++-------- test/src/derive.rs | 16 +++---- 2 files changed, 50 insertions(+), 27 deletions(-) diff --git a/rom/dev/src/flow/cold_reset/fmc_alias.rs b/rom/dev/src/flow/cold_reset/fmc_alias.rs index e6a02bdeb7..b466270ec9 100644 --- a/rom/dev/src/flow/cold_reset/fmc_alias.rs +++ b/rom/dev/src/flow/cold_reset/fmc_alias.rs @@ -48,10 +48,15 @@ impl FmcAliasLayer { ) -> CaliptraResult<()> { cprintln!("[afmc] ++"); cprintln!("[afmc] CDI.KEYID = {}", KEY_ID_ROM_FMC_CDI as u8); - cprintln!("[afmc] SUBJECT.KEYID = {}", KEY_ID_FMC_ECDSA_PRIV_KEY as u8); cprintln!( - "[afmc] ECC AUTHORITY.KEYID = {}", - input.ecc_auth_key_pair.priv_key as u8 + "[afmc] ECC SUBJECT.KEYID = {}, MLDSA SUBJECT.KEYID = {}", + KEY_ID_FMC_ECDSA_PRIV_KEY as u8, + KEY_ID_FMC_MLDSA_KEYPAIR_SEED as u8 + ); + cprintln!( + "[afmc] ECC AUTHORITY.KEYID = {}, MLDSA AUTHORITY.KEYID = {}", + input.ecc_auth_key_pair.priv_key as u8, + input.mldsa_auth_key_pair.key_pair_seed as u8 ); // We use the value of PCR0 as the measurement for deriving the CDI. @@ -62,18 +67,24 @@ impl FmcAliasLayer { measurement.0.zeroize(); result?; - // Derive DICE Key Pair from CDI - let ecc_key_pair = - Self::derive_key_pair(env, KEY_ID_ROM_FMC_CDI, KEY_ID_FMC_ECDSA_PRIV_KEY)?; + // Derive DICE ECC and MLDSA Key Pairs from CDI + let (ecc_key_pair, mldsa_key_pair) = Self::derive_key_pair( + env, + KEY_ID_ROM_FMC_CDI, + KEY_ID_FMC_ECDSA_PRIV_KEY, + KEY_ID_FMC_MLDSA_KEYPAIR_SEED, + )?; // Generate the Subject Serial Number and Subject Key Identifier. // // This information will be used by next DICE Layer while generating // certificates let ecc_subj_sn = X509::subj_sn(env, &PubKey::Ecc(&ecc_key_pair.pub_key))?; + let mldsa_subj_sn = X509::subj_sn(env, &PubKey::Mldsa(&mldsa_key_pair.pub_key))?; report_boot_status(FmcAliasSubjIdSnGenerationComplete.into()); let ecc_subj_key_id = X509::subj_key_id(env, &PubKey::Ecc(&ecc_key_pair.pub_key))?; + let mldsa_subj_key_id = X509::subj_key_id(env, &PubKey::Mldsa(&mldsa_key_pair.pub_key))?; report_boot_status(FmcAliasSubjKeyIdGenerationComplete.into()); // Generate the output for next layer @@ -81,12 +92,9 @@ impl FmcAliasLayer { ecc_subj_key_pair: ecc_key_pair, ecc_subj_sn, ecc_subj_key_id, - mldsa_subj_key_id: [0; 20], - mldsa_subj_key_pair: MlDsaKeyPair { - key_pair_seed: KEY_ID_FMC_MLDSA_KEYPAIR_SEED, - pub_key: Default::default(), - }, - mldsa_subj_sn: [0; 64], + mldsa_subj_key_pair: mldsa_key_pair, + mldsa_subj_sn, + mldsa_subj_key_id, }; // Generate FMC Alias Certificate @@ -111,7 +119,7 @@ impl FmcAliasLayer { fn derive_cdi(env: &mut RomEnv, measurements: &Array4x12, cdi: KeyId) -> CaliptraResult<()> { let mut measurements: [u8; 48] = measurements.into(); - let result = Crypto::hmac384_kdf(env, cdi, b"fmc_alias_cdi", Some(&measurements), cdi); + let result = Crypto::hmac384_kdf(env, cdi, b"alias_fmc_cdi", Some(&measurements), cdi); measurements.zeroize(); result?; report_boot_status(FmcAliasDeriveCdiComplete.into()); @@ -124,7 +132,8 @@ impl FmcAliasLayer { /// /// * `env` - ROM Environment /// * `cdi` - Composite Device Identity - /// * `priv_key` - Key slot to store the private key into + /// * `ecc_priv_key` - Key slot to store the ECC private key into + /// * `mldsa_keypair_seed` - Key slot to store the MLDSA key pair seed /// /// # Returns /// @@ -133,16 +142,28 @@ impl FmcAliasLayer { fn derive_key_pair( env: &mut RomEnv, cdi: KeyId, - priv_key: KeyId, - ) -> CaliptraResult { - let result = Crypto::ecc384_key_gen(env, cdi, b"fmc_alias_keygen", priv_key); + ecc_priv_key: KeyId, + mldsa_keypair_seed: KeyId, + ) -> CaliptraResult<(Ecc384KeyPair, MlDsaKeyPair)> { + let result = Crypto::ecc384_key_gen(env, cdi, b"alias_fmc_ecc_key", ecc_priv_key); + if cfi_launder(result.is_ok()) { + cfi_assert!(result.is_ok()); + } else { + cfi_assert!(result.is_err()); + } + let ecc_keypair = result?; + + // Derive the MLDSA Key Pair. + let result = Crypto::mldsa_key_gen(env, cdi, b"alias_fmc_mldsa_key", mldsa_keypair_seed); if cfi_launder(result.is_ok()) { cfi_assert!(result.is_ok()); - report_boot_status(FmcAliasKeyPairDerivationComplete.into()); } else { cfi_assert!(result.is_err()); } - result + let mldsa_keypair = result?; + + report_boot_status(FmcAliasKeyPairDerivationComplete.into()); + Ok((ecc_keypair, mldsa_keypair)) } /// Generate Local Device ID Certificate Signature @@ -240,6 +261,8 @@ impl FmcAliasLayer { // Copy TBS to DCCM. copy_tbs(tbs.tbs(), TbsType::FmcaliasTbs, env)?; + // [CAP2][TODO] Generate MLDSA certificate signature, TBS. + report_boot_status(FmcAliasCertSigGenerationComplete.into()); Ok(()) } diff --git a/test/src/derive.rs b/test/src/derive.rs index 946007db33..964375b3b3 100644 --- a/test/src/derive.rs +++ b/test/src/derive.rs @@ -420,14 +420,14 @@ impl FmcAliasKey { pub fn derive(pcr0: &Pcr0, ldevid: &LDevId) -> Self { let mut cdi: [u32; 12] = transmute!(hmac384_kdf( swap_word_bytes(&ldevid.cdi).as_bytes(), - b"fmc_alias_cdi", + b"alias_fmc_cdi", Some(swap_word_bytes(&pcr0.0).as_bytes()), )); swap_word_bytes_inplace(&mut cdi); let mut priv_key_seed: [u32; 12] = transmute!(hmac384_kdf( swap_word_bytes(&cdi).as_bytes(), - b"fmc_alias_keygen", + b"alias_fmc_ecc_key", None )); swap_word_bytes_inplace(&mut priv_key_seed); @@ -519,13 +519,13 @@ fn test_derive_fmc_alias_key() { assert_eq!( fmc_alias_key, FmcAliasKey { - cdi: [ - 0xf4fb8b09, 0xc9233adb, 0x3dfade39, 0xb656f0ef, 0x151404dc, 0xf4fe787a, 0x0664baea, - 0xe9d2de59, 0x22401c7c, 0x59087111, 0xd3aeb5b1, 0x368742da - ], priv_key: [ - 0x81a4f53c, 0xeb0749ca, 0x77b0fe32, 0x33fd9798, 0x7412f652, 0xded8f8a5, 0x39a9ebbd, - 0x75ce2870, 0xb5f62bb3, 0x25376504, 0xa34f286c, 0x849ea86c, + 0xB0490161, 0xA1D2393A, 0x752E2F60, 0x4BB9A01E, 0x293B9E47, 0x61698007, 0x2CED9BAF, + 0x1F828679, 0xCB5054CD, 0xFD0EB072, 0x8D6BE59F, 0x75C55332 + ], + cdi: [ + 0xCEAA7956, 0x4E5A8809, 0x7F1BF1B8, 0xA3A9C903, 0x37B4335F, 0xEA8A93D2, 0x5D02F1BF, + 0x16B1A537, 0xFE5DB006, 0xD8427583, 0x72C836F1, 0x9BE74AF5, ], } );