Skip to content

Commit

Permalink
[feat] Image generator and verifier updates for Caliptra 2.0 FW ECC +…
Browse files Browse the repository at this point in the history
… LMS image (#1694)
  • Loading branch information
mhatrevi authored Nov 2, 2024
1 parent c805128 commit 7565578
Show file tree
Hide file tree
Showing 40 changed files with 845 additions and 324 deletions.
1 change: 1 addition & 0 deletions Cargo.lock

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

5 changes: 4 additions & 1 deletion builder/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ use caliptra_image_elf::ElfExecutable;
use caliptra_image_gen::{
ImageGenerator, ImageGeneratorConfig, ImageGeneratorOwnerConfig, ImageGeneratorVendorConfig,
};
use caliptra_image_types::{ImageBundle, ImageRevision, RomInfo};
use caliptra_image_types::{FwImageType, ImageBundle, ImageRevision, RomInfo};
use elf::endian::LittleEndian;
use nix::fcntl::FlockArg;
use zerocopy::AsBytes;
Expand Down Expand Up @@ -444,6 +444,7 @@ pub struct ImageOptions {
pub app_svn: u32,
pub vendor_config: ImageGeneratorVendorConfig,
pub owner_config: Option<ImageGeneratorOwnerConfig>,
pub fw_image_type: FwImageType,
}
impl Default for ImageOptions {
fn default() -> Self {
Expand All @@ -454,6 +455,7 @@ impl Default for ImageOptions {
app_svn: Default::default(),
vendor_config: caliptra_image_fake_keys::VENDOR_CONFIG_KEY_0,
owner_config: Some(caliptra_image_fake_keys::OWNER_CONFIG),
fw_image_type: FwImageType::EccLms,
}
}
}
Expand All @@ -476,6 +478,7 @@ pub fn build_and_sign_image(
runtime: ElfExecutable::new(&app_elf, opts.app_version, opts.app_svn, image_revision()?)?,
vendor_config: opts.vendor_config,
owner_config: opts.owner_config,
fw_image_type: opts.fw_image_type,
})?;
Ok(image)
}
Expand Down
53 changes: 50 additions & 3 deletions common/src/verifier.rs
Original file line number Diff line number Diff line change
Expand Up @@ -78,9 +78,56 @@ impl<'a, 'b> ImageVerificationEnv for &mut FirmwareImageVerificationEnv<'a, 'b>
Lms::default().verify_lms_signature_cfi(self.sha256, &message, pub_key, sig)
}

/// Retrieve Vendor Public Key Digest
fn vendor_pub_key_digest(&self) -> ImageDigest {
self.soc_ifc.fuse_bank().vendor_pub_key_hash().into()
/// Retrieve Vendor Public Key Info Digest
fn vendor_pub_key_info_digest_fuses(&self) -> ImageDigest {
self.soc_ifc.fuse_bank().vendor_pub_key_info_hash().into()
}

/// Retrieve Vendor Public Key Info Digest
fn vendor_pub_key_info_digest_from_image(
&mut self,
ecc_key_desc: (u32, u32),
ecc_pub_key_hashes: (u32, u32),
lms_key_desc: (u32, u32),
lms_pub_key_hashes: (u32, u32),
) -> CaliptraResult<ImageDigest> {
let err = CaliptraError::IMAGE_VERIFIER_ERR_DIGEST_OUT_OF_BOUNDS;
let ecc_key_desc = self
.image
.get(ecc_key_desc.0 as usize..)
.ok_or(err)?
.get(..ecc_key_desc.1 as usize)
.ok_or(err)?;

let ecc_pub_key_hashes = self
.image
.get(ecc_pub_key_hashes.0 as usize..)
.ok_or(err)?
.get(..ecc_pub_key_hashes.1 as usize)
.ok_or(err)?;

let lms_key_desc = self
.image
.get(lms_key_desc.0 as usize..)
.ok_or(err)?
.get(..lms_key_desc.1 as usize)
.ok_or(err)?;

let lms_pub_key_hashes = self
.image
.get(lms_pub_key_hashes.0 as usize..)
.ok_or(err)?
.get(..lms_pub_key_hashes.1 as usize)
.ok_or(err)?;

let mut digest = Array4x12::default();
let mut op = self.sha384.digest_init()?;
op.update(ecc_key_desc)?;
op.update(ecc_pub_key_hashes)?;
op.update(lms_key_desc)?;
op.update(lms_pub_key_hashes)?;
op.finalize(&mut digest)?;
Ok(digest.0)
}

/// Retrieve Vendor ECC Public Key Revocation Bitmask
Expand Down
6 changes: 3 additions & 3 deletions drivers/src/fuse_bank.rs
Original file line number Diff line number Diff line change
Expand Up @@ -179,15 +179,15 @@ impl FuseBank<'_> {
subject_key_id
}

/// Get the vendor public key hash.
/// Get the vendor public key info hash.
///
/// # Arguments
/// * None
///
/// # Returns
/// vendor public key hash
/// vendor public key info hash
///
pub fn vendor_pub_key_hash(&self) -> Array4x12 {
pub fn vendor_pub_key_info_hash(&self) -> Array4x12 {
let soc_ifc_regs = self.soc_ifc.regs();
Array4x12::read_from_reg(soc_ifc_regs.fuse_key_manifest_pk_hash())
}
Expand Down
30 changes: 15 additions & 15 deletions drivers/src/memory_layout.rs
Original file line number Diff line number Diff line change
Expand Up @@ -29,18 +29,18 @@ pub const ROM_DATA_ORG: u32 = 0x50000000;
pub const CFI_STATE_ORG: u32 = 0x500003E4; // size = 6 words
pub const BOOT_STATUS_ORG: u32 = 0x500003FC;
pub const MAN1_ORG: u32 = 0x50000400;
pub const MAN2_ORG: u32 = 0x50001C00;
pub const FHT_ORG: u32 = 0x50003400;
pub const LDEVID_TBS_ORG: u32 = 0x50003C00;
pub const FMCALIAS_TBS_ORG: u32 = 0x50004000;
pub const RTALIAS_TBS_ORG: u32 = 0x50004400;
pub const PCR_LOG_ORG: u32 = 0x50004800;
pub const MEASUREMENT_LOG_ORG: u32 = 0x50004C00;
pub const FUSE_LOG_ORG: u32 = 0x50005000;
pub const DPE_ORG: u32 = 0x50005400;
pub const PCR_RESET_COUNTER_ORG: u32 = 0x50006800;
pub const AUTH_MAN_IMAGE_METADATA_LIST_ORG: u32 = 0x50006C00;
pub const DATA_ORG: u32 = 0x50007000;
pub const MAN2_ORG: u32 = 0x50002400;
pub const FHT_ORG: u32 = 0x50004400;
pub const LDEVID_TBS_ORG: u32 = 0x50004C00;
pub const FMCALIAS_TBS_ORG: u32 = 0x50005000;
pub const RTALIAS_TBS_ORG: u32 = 0x50005400;
pub const PCR_LOG_ORG: u32 = 0x50005800;
pub const MEASUREMENT_LOG_ORG: u32 = 0x50005C00;
pub const FUSE_LOG_ORG: u32 = 0x50006000;
pub const DPE_ORG: u32 = 0x50006400;
pub const PCR_RESET_COUNTER_ORG: u32 = 0x50007800;
pub const AUTH_MAN_IMAGE_METADATA_LIST_ORG: u32 = 0x50007C00;
pub const DATA_ORG: u32 = 0x50008000;

pub const STACK_ORG: u32 = 0x5001A000;
pub const ROM_STACK_ORG: u32 = 0x5001C000;
Expand All @@ -60,8 +60,8 @@ pub const MBOX_SIZE: u32 = 128 * 1024;
pub const ICCM_SIZE: u32 = 128 * 1024;
pub const DCCM_SIZE: u32 = 128 * 1024;
pub const ROM_DATA_SIZE: u32 = 996;
pub const MAN1_SIZE: u32 = 6 * 1024;
pub const MAN2_SIZE: u32 = 6 * 1024;
pub const MAN1_SIZE: u32 = 8 * 1024;
pub const MAN2_SIZE: u32 = 8 * 1024;
pub const FHT_SIZE: u32 = 2 * 1024;
pub const LDEVID_TBS_SIZE: u32 = 1024;
pub const FMCALIAS_TBS_SIZE: u32 = 1024;
Expand All @@ -72,7 +72,7 @@ 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_LIST_MAX_SIZE: u32 = 1024;
pub const DATA_SIZE: u32 = 76 * 1024;
pub const DATA_SIZE: u32 = 72 * 1024;
pub const STACK_SIZE: u32 = 22 * 1024;
pub const ROM_STACK_SIZE: u32 = 14 * 1024;
pub const ESTACK_SIZE: u32 = 1024;
Expand Down
18 changes: 9 additions & 9 deletions drivers/src/pcr_log.rs
Original file line number Diff line number Diff line change
Expand Up @@ -25,21 +25,21 @@ pub const PCR_ID_STASH_MEASUREMENT: PcrId = PcrId::PcrId31;
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum PcrLogEntryId {
Invalid = 0,
DeviceStatus = 1, // data size = 9 bytes
VendorPubKeyHash = 2, // data size = 48 bytes
OwnerPubKeyHash = 3, // data size = 48 bytes
FmcTci = 4, // data size = 48 bytes
StashMeasurement = 5, // data size = 48 bytes
RtTci = 6, // data size = 48 bytes
FwImageManifest = 7, // data size = 48 bytes
DeviceStatus = 1, // data size = 9 bytes
VendorPubKeyInfoHash = 2, // data size = 48 bytes
OwnerPubKeyHash = 3, // data size = 48 bytes
FmcTci = 4, // data size = 48 bytes
StashMeasurement = 5, // data size = 48 bytes
RtTci = 6, // data size = 48 bytes
FwImageManifest = 7, // data size = 48 bytes
}

impl From<u16> for PcrLogEntryId {
/// Converts to this type from the input type.
fn from(id: u16) -> PcrLogEntryId {
match id {
1 => PcrLogEntryId::DeviceStatus,
2 => PcrLogEntryId::VendorPubKeyHash,
2 => PcrLogEntryId::VendorPubKeyInfoHash,
3 => PcrLogEntryId::OwnerPubKeyHash,
4 => PcrLogEntryId::FmcTci,
5 => PcrLogEntryId::StashMeasurement,
Expand Down Expand Up @@ -71,7 +71,7 @@ impl PcrLogEntry {
let data_len = match PcrLogEntryId::from(self.id) {
PcrLogEntryId::Invalid => 0,
PcrLogEntryId::DeviceStatus => 9,
PcrLogEntryId::VendorPubKeyHash => 48,
PcrLogEntryId::VendorPubKeyInfoHash => 48,
PcrLogEntryId::OwnerPubKeyHash => 48,
PcrLogEntryId::FmcTci => 48,
PcrLogEntryId::StashMeasurement => 48,
Expand Down
22 changes: 22 additions & 0 deletions error/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -267,6 +267,28 @@ impl CaliptraError {
CaliptraError::new_const(0x000b0040);
pub const IMAGE_VERIFIER_ERR_DIGEST_OUT_OF_BOUNDS: CaliptraError =
CaliptraError::new_const(0x000b0041);
pub const IMAGE_VERIFIER_ERR_ECC_KEY_DESCRIPTOR_MARKER_MISMATCH: CaliptraError =
CaliptraError::new_const(0x000b0042);
pub const IMAGE_VERIFIER_ERR_ECC_KEY_DESCRIPTOR_VERSION_MISMATCH: CaliptraError =
CaliptraError::new_const(0x000b0043);
pub const IMAGE_VERIFIER_ERR_ECC_KEY_DESCRIPTOR_INTENT_MISMATCH: CaliptraError =
CaliptraError::new_const(0x000b0044);
pub const IMAGE_VERIFIER_ERR_ECC_KEY_DESCRIPTOR_HASH_COUNT_GT_MAX: CaliptraError =
CaliptraError::new_const(0x000b0046);
pub const IMAGE_VERIFIER_ERR_LMS_KEY_DESCRIPTOR_MARKER_MISMATCH: CaliptraError =
CaliptraError::new_const(0x000b0047);
pub const IMAGE_VERIFIER_ERR_LMS_KEY_DESCRIPTOR_VERSION_MISMATCH: CaliptraError =
CaliptraError::new_const(0x000b0048);
pub const IMAGE_VERIFIER_ERR_LMS_KEY_DESCRIPTOR_INTENT_MISMATCH: CaliptraError =
CaliptraError::new_const(0x000b0049);
pub const IMAGE_VERIFIER_ERR_LMS_KEY_DESCRIPTOR_TYPE_MISMATCH: CaliptraError =
CaliptraError::new_const(0x000b004a);
pub const IMAGE_VERIFIER_ERR_LMS_KEY_DESCRIPTOR_HASH_COUNT_GT_MAX: CaliptraError =
CaliptraError::new_const(0x000b004b);
pub const IMAGE_VERIFIER_ERR_ECC_KEY_DESCRIPTOR_INVALID_HASH_COUNT: CaliptraError =
CaliptraError::new_const(0x000b004c);
pub const IMAGE_VERIFIER_ERR_LMS_KEY_DESCRIPTOR_INVALID_HASH_COUNT: CaliptraError =
CaliptraError::new_const(0x000b004d);

/// Driver Error: LMS
pub const DRIVER_LMS_INVALID_LMS_ALGO_TYPE: CaliptraError =
Expand Down
10 changes: 5 additions & 5 deletions fmc/tests/fmc_integration_tests/test_rtalias.rs
Original file line number Diff line number Diff line change
Expand Up @@ -92,11 +92,11 @@ fn test_fht_info() {
let fht = FirmwareHandoffTable::read_from_prefix(data.as_bytes()).unwrap();
assert_eq!(fht.ldevid_tbs_size, 552);
assert_eq!(fht.fmcalias_tbs_size, 786);
assert_eq!(fht.ldevid_tbs_addr, 0x50003C00);
assert_eq!(fht.fmcalias_tbs_addr, 0x50004000);
assert_eq!(fht.pcr_log_addr, 0x50004800);
assert_eq!(fht.meas_log_addr, 0x50004C00);
assert_eq!(fht.fuse_log_addr, 0x50005000);
assert_eq!(fht.ldevid_tbs_addr, 0x50004C00);
assert_eq!(fht.fmcalias_tbs_addr, 0x50005000);
assert_eq!(fht.pcr_log_addr, 0x50005800);
assert_eq!(fht.meas_log_addr, 0x50005C00);
assert_eq!(fht.fuse_log_addr, 0x50006000);
}

#[test]
Expand Down
11 changes: 5 additions & 6 deletions image/app/src/create/config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,20 +13,19 @@ Abstract:
--*/

use anyhow::Context;
use caliptra_image_types::{VENDOR_ECC_KEY_COUNT, VENDOR_LMS_KEY_COUNT};
use serde_derive::{Deserialize, Serialize};
use std::path::PathBuf;

/// Vendor Key Configuration
#[derive(Default, Serialize, Deserialize)]
pub(crate) struct VendorKeyConfig {
pub ecc_pub_keys: [String; VENDOR_ECC_KEY_COUNT as usize],
pub ecc_pub_keys: Vec<String>,

pub lms_pub_keys: [String; VENDOR_LMS_KEY_COUNT as usize],
pub lms_pub_keys: Vec<String>,

pub ecc_priv_keys: Option<[String; VENDOR_ECC_KEY_COUNT as usize]>,
pub ecc_priv_keys: Option<Vec<String>>,

pub lms_priv_keys: Option<[String; VENDOR_LMS_KEY_COUNT as usize]>,
pub lms_priv_keys: Option<Vec<String>>,
}

/// Owner Key Configuration
Expand All @@ -41,7 +40,7 @@ pub(crate) struct OwnerKeyConfig {
pub lms_priv_key: Option<String>,
}

//Key Configuration
// Key Configuration
#[derive(Default, Serialize, Deserialize)]
pub(crate) struct KeyConfig {
pub vendor: VendorKeyConfig,
Expand Down
48 changes: 33 additions & 15 deletions image/app/src/create/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,10 @@ fn check_date(from_date: &str, to_date: &str) -> anyhow::Result<bool> {

/// Run the command
pub(crate) fn run_cmd(args: &ArgMatches) -> anyhow::Result<()> {
let image_type: &u32 = args
.get_one::<u32>("image-type")
.with_context(|| "image-type arg not specified")?;

let config_path: &PathBuf = args
.get_one::<PathBuf>("key-config")
.with_context(|| "key-config arg not specified")?;
Expand Down Expand Up @@ -182,6 +186,11 @@ pub(crate) fn run_cmd(args: &ArgMatches) -> anyhow::Result<()> {
owner_config: owner_config(config_dir, &config.owner, own_from_date, own_to_date)?,
fmc,
runtime,
fw_image_type: if *image_type == 1 {
FwImageType::EccLms
} else {
FwImageType::EccMldsa
},
};

let gen = ImageGenerator::new(Crypto::default());
Expand Down Expand Up @@ -210,24 +219,31 @@ fn vendor_config(
to_date: [u8; 15],
) -> anyhow::Result<ImageGeneratorVendorConfig> {
let mut gen_config = ImageGeneratorVendorConfig::default();
let ecc_pub_keys = &config.ecc_pub_keys;

for (i, pem_file) in ecc_pub_keys
.iter()
.enumerate()
.take(VENDOR_ECC_KEY_COUNT as usize)
{
let ecc_key_count = config.ecc_pub_keys.len() as u32;
let lms_key_count = config.lms_pub_keys.len() as u32;

if ecc_key_count > VENDOR_ECC_MAX_KEY_COUNT {
return Err(anyhow!("Invalid ECC Public Key Count"));
}
if lms_key_count > VENDOR_LMS_MAX_KEY_COUNT {
return Err(anyhow!("Invalid LMS Public Key Count"));
}

if ecc_key_idx >= ecc_key_count {
return Err(anyhow!("Invalid ECC Public Key Index"));
}
if lms_key_idx >= lms_key_count {
return Err(anyhow!("Invalid LMS Public Key Index"));
}

let ecc_pub_keys = &config.ecc_pub_keys;
for (i, pem_file) in ecc_pub_keys.iter().enumerate().take(ecc_key_count as usize) {
let pub_key_path = path.join(pem_file);
gen_config.pub_keys.ecc_pub_keys[i] = Crypto::ecc_pub_key_from_pem(&pub_key_path)?;
}

let lms_pub_keys = &config.lms_pub_keys;

for (i, pem_file) in lms_pub_keys
.iter()
.enumerate()
.take(VENDOR_LMS_KEY_COUNT as usize)
{
for (i, pem_file) in lms_pub_keys.iter().enumerate().take(lms_key_count as usize) {
let pub_key_path = path.join(pem_file);
gen_config.pub_keys.lms_pub_keys[i] = lms_pub_key_from_pem(&pub_key_path)?;
}
Expand All @@ -237,7 +253,7 @@ fn vendor_config(
for (i, pem_file) in ecc_priv_keys
.iter()
.enumerate()
.take(VENDOR_ECC_KEY_COUNT as usize)
.take(ecc_key_count as usize)
{
let priv_key_path = path.join(pem_file);
priv_keys.ecc_priv_keys[i] = Crypto::ecc_priv_key_from_pem(&priv_key_path)?;
Expand All @@ -249,7 +265,7 @@ fn vendor_config(
for (i, pem_file) in lms_priv_keys
.iter()
.enumerate()
.take(VENDOR_LMS_KEY_COUNT as usize)
.take(lms_key_count as usize)
{
let priv_key_path = path.join(pem_file);
priv_keys.lms_priv_keys[i] = lms_priv_key_from_pem(&priv_key_path)?;
Expand All @@ -261,6 +277,8 @@ fn vendor_config(
gen_config.lms_key_idx = lms_key_idx;
gen_config.not_before = from_date;
gen_config.not_after = to_date;
gen_config.ecc_key_count = ecc_key_count;
gen_config.lms_key_count = lms_key_count;

Ok(gen_config)
}
Expand Down
Loading

0 comments on commit 7565578

Please sign in to comment.