Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[feat] Image generator and verifier updates for Caliptra 2.0 FW ECC + LMS image #1694

Open
wants to merge 7 commits into
base: main-2.x
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 1 commit
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
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.

16 changes: 10 additions & 6 deletions image/app/src/create/config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,20 +13,24 @@ Abstract:
--*/

use anyhow::Context;
use caliptra_image_types::{VENDOR_ECC_KEY_COUNT, VENDOR_LMS_KEY_COUNT};
use caliptra_image_types::{VENDOR_ECC_MAX_KEY_COUNT, VENDOR_LMS_MAX_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_key_count: u32,

pub lms_pub_keys: [String; VENDOR_LMS_KEY_COUNT as usize],
pub ecc_pub_keys: [String; VENDOR_ECC_MAX_KEY_COUNT as usize],
mhatrevi marked this conversation as resolved.
Show resolved Hide resolved

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

pub lms_priv_keys: Option<[String; VENDOR_LMS_KEY_COUNT as usize]>,
pub lms_pub_keys: [String; VENDOR_LMS_MAX_KEY_COUNT as usize],

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

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

/// Owner Key Configuration
Expand All @@ -41,7 +45,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,
manifest_type: if *image_type == 1 {
ManifestType::EccLms
} else {
ManifestType::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_key_count;
let lms_key_count = config.lms_key_count;

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 as u32 {
return Err(anyhow!("Invalid ECC Public Key Index"));
}
if lms_key_idx >= lms_key_count as u32 {
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
8 changes: 5 additions & 3 deletions image/app/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,11 @@ mod create;
fn main() {
let sub_cmds = vec![Command::new("create")
.about("Create a new firmware image bundle")
.arg(
arg!(--"image-type" <U32> "Type of image keys: 1: ECC + LMS; 2: ECC + MLDSA")
.required(true)
.value_parser(value_parser!(u32)),
)
.arg(
arg!(--"key-config" <FILE> "Key Configuration file")
.required(true)
Expand Down Expand Up @@ -114,7 +119,4 @@ fn main() {
};

result.unwrap();

// let exit_code = if result.is_ok() { 0 } else { -1 };
// std::process::exit(exit_code);
}
4 changes: 2 additions & 2 deletions image/elf/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ Abstract:
--*/

use anyhow::{bail, Context};
use caliptra_image_gen::ImageGenratorExecutable;
use caliptra_image_gen::ImageGeneratorExecutable;
use caliptra_image_types::ImageRevision;
use elf::abi::PT_LOAD;
use elf::endian::AnyEndian;
Expand Down Expand Up @@ -108,7 +108,7 @@ impl ElfExecutable {
}
}

impl ImageGenratorExecutable for ElfExecutable {
impl ImageGeneratorExecutable for ElfExecutable {
/// Executable Version Number
fn version(&self) -> u32 {
self.version
Expand Down
4 changes: 3 additions & 1 deletion image/fake-keys/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ use caliptra_image_gen::{ImageGeneratorOwnerConfig, ImageGeneratorVendorConfig};
use caliptra_image_types::{
ImageEccPrivKey, ImageEccPubKey, ImageLmsPrivKey, ImageLmsPublicKey, ImageOwnerPrivKeys,
ImageOwnerPubKeys, ImageVendorPrivKeys, ImageVendorPubKeys, IMAGE_LMS_OTS_TYPE,
IMAGE_LMS_TREE_TYPE,
IMAGE_LMS_TREE_TYPE, VENDOR_ECC_MAX_KEY_COUNT, VENDOR_LMS_MAX_KEY_COUNT,
};
use caliptra_lms_types::bytes_to_words_6;

Expand Down Expand Up @@ -333,6 +333,8 @@ pub const OWNER_PRIVATE_KEYS: ImageOwnerPrivKeys = ImageOwnerPrivKeys {
};

pub const VENDOR_CONFIG_KEY_0: ImageGeneratorVendorConfig = ImageGeneratorVendorConfig {
ecc_key_count: VENDOR_ECC_MAX_KEY_COUNT,
lms_key_count: VENDOR_LMS_MAX_KEY_COUNT,
pub_keys: VENDOR_PUBLIC_KEYS,
ecc_key_idx: 0,
lms_key_idx: 0,
Expand Down
69 changes: 61 additions & 8 deletions image/gen/src/generator.rs
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ impl<Crypto: ImageGeneratorCrypto> ImageGenerator<Crypto> {
/// * `ImageBundle` - Caliptra Image Bundle
pub fn generate<E>(&self, config: &ImageGeneratorConfig<E>) -> anyhow::Result<ImageBundle>
where
E: ImageGenratorExecutable,
E: ImageGeneratorExecutable,
{
let image_size =
IMAGE_MANIFEST_BYTE_SIZE as u32 + config.fmc.size() + config.runtime.size();
Expand Down Expand Up @@ -82,7 +82,7 @@ impl<Crypto: ImageGeneratorCrypto> ImageGenerator<Crypto> {
let toc_digest = self.toc_digest(&fmc_toc, &runtime_toc)?;
let header = self.gen_header(config, ecc_key_idx, lms_key_idx, toc_digest)?;

// Create Preamable
// Create Preamble
let header_digest_vendor = self.header_digest_vendor(&header)?;
let header_digest_owner = self.header_digest_owner(&header)?;
let preamble = self.gen_preamble(
Expand All @@ -97,6 +97,8 @@ impl<Crypto: ImageGeneratorCrypto> ImageGenerator<Crypto> {
let manifest = ImageManifest {
marker: MANIFEST_MARKER,
size: core::mem::size_of::<ImageManifest>() as u32,
manifest_type: config.manifest_type.into(),
reserved: [0u8; 3],
preamble,
header,
fmc: fmc_toc,
Expand All @@ -113,7 +115,7 @@ impl<Crypto: ImageGeneratorCrypto> ImageGenerator<Crypto> {
Ok(image)
}

/// Create preable
/// Create preamble
pub fn gen_preamble<E>(
&self,
config: &ImageGeneratorConfig<E>,
Expand All @@ -123,7 +125,7 @@ impl<Crypto: ImageGeneratorCrypto> ImageGenerator<Crypto> {
digest_owner: &ImageDigest,
) -> anyhow::Result<ImagePreamble>
where
E: ImageGenratorExecutable,
E: ImageGeneratorExecutable,
{
let mut vendor_sigs = ImageSignatures::default();
let mut owner_sigs = ImageSignatures::default();
Expand Down Expand Up @@ -157,17 +159,68 @@ impl<Crypto: ImageGeneratorCrypto> ImageGenerator<Crypto> {
}
}

let mut vendor_pub_key_info = ImageVendorPubKeyInfo::default();

vendor_pub_key_info.ecc_key_descriptor = ImageKeyDescriptor {
marker: KEY_DESCRIPTOR_MARKER,
version: KEY_DESCRIPTOR_VERSION,
intent: Intent::Vendor.into(),
key_type: KeyType::ECC.into(),
key_hash_count: config.vendor_config.ecc_key_count as u8,
};

vendor_pub_key_info.lms_key_descriptor = ImageKeyDescriptor {
marker: KEY_DESCRIPTOR_MARKER,
version: KEY_DESCRIPTOR_VERSION,
intent: Intent::Vendor.into(),
key_type: KeyType::LMS.into(),
key_hash_count: config.vendor_config.lms_key_count as u8,
};

// Hash the ECC and LMS public keys.
for i in 0..config.vendor_config.ecc_key_count {
let ecc_pub_key = config.vendor_config.pub_keys.ecc_pub_keys[i as usize];
let ecc_pub_key_digest = self.crypto.sha384_digest(ecc_pub_key.as_bytes())?;
vendor_pub_key_info.ecc_pub_key_hashes[i as usize] = ecc_pub_key_digest;
}
for i in 0..config.vendor_config.lms_key_count {
let lms_pub_key = config.vendor_config.pub_keys.lms_pub_keys[i as usize];
let lms_pub_key_digest = self.crypto.sha384_digest(lms_pub_key.as_bytes())?;
vendor_pub_key_info.lms_pub_key_hashes[i as usize] = lms_pub_key_digest;
}

let mut preamble = ImagePreamble {
vendor_pub_keys: config.vendor_config.pub_keys,
vendor_pub_key_info: vendor_pub_key_info,
vendor_ecc_pub_key_idx: ecc_vendor_key_idx,
vendor_ecc_active_pub_key: config.vendor_config.pub_keys.ecc_pub_keys
[ecc_vendor_key_idx as usize],
vendor_lms_pub_key_idx: lms_vendor_key_idx,
vendor_lms_active_pub_key: config.vendor_config.pub_keys.lms_pub_keys
[lms_vendor_key_idx as usize],
vendor_sigs,
owner_sigs,
..Default::default()
};

if let Some(owner_config) = &config.owner_config {
preamble.owner_pub_keys = owner_config.pub_keys;

preamble.owner_pub_key_info = ImageOwnerPubKeyInfo {
ecc_key_descriptor: ImageKeyDescriptor {
marker: KEY_DESCRIPTOR_MARKER,
version: KEY_DESCRIPTOR_VERSION,
intent: Intent::Owner.into(),
key_type: KeyType::ECC.into(),
key_hash_count: 0,
},
lms_key_descriptor: ImageKeyDescriptor {
marker: KEY_DESCRIPTOR_MARKER,
version: KEY_DESCRIPTOR_VERSION,
intent: Intent::Owner.into(),
key_type: KeyType::LMS.into(),
key_hash_count: 0,
},
};
}

Ok(preamble)
Expand All @@ -182,7 +235,7 @@ impl<Crypto: ImageGeneratorCrypto> ImageGenerator<Crypto> {
digest: ImageDigest,
) -> anyhow::Result<ImageHeader>
where
E: ImageGenratorExecutable,
E: ImageGeneratorExecutable,
{
let mut header = ImageHeader {
vendor_ecc_pub_key_idx: ecc_key_idx,
Expand Down Expand Up @@ -232,7 +285,7 @@ impl<Crypto: ImageGeneratorCrypto> ImageGenerator<Crypto> {
/// Calculate vendor public key(s) digest
pub fn vendor_pubkey_digest(&self, preamble: &ImagePreamble) -> anyhow::Result<ImageDigest> {
self.crypto
.sha384_digest(preamble.vendor_pub_keys.as_bytes())
.sha384_digest(preamble.vendor_pub_key_info.as_bytes())
}

/// Generate image
Expand All @@ -243,7 +296,7 @@ impl<Crypto: ImageGeneratorCrypto> ImageGenerator<Crypto> {
offset: u32,
) -> anyhow::Result<(ImageTocEntry, Vec<u8>)>
where
E: ImageGenratorExecutable,
E: ImageGeneratorExecutable,
{
let r#type = ImageTocEntryType::Executable;
let digest = self.crypto.sha384_digest(image.content())?;
Expand Down
10 changes: 8 additions & 2 deletions image/gen/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ use caliptra_image_types::*;
use std::path::Path;

/// Image Generator Executable
pub trait ImageGenratorExecutable {
pub trait ImageGeneratorExecutable {
/// Executable Version Number
fn version(&self) -> u32;

Expand Down Expand Up @@ -92,6 +92,10 @@ pub trait ImageGeneratorCrypto {
/// Image Generator Vendor Configuration
#[derive(Default, Clone)]
pub struct ImageGeneratorVendorConfig {
pub ecc_key_count: u32,

pub lms_key_count: u32,

pub pub_keys: ImageVendorPubKeys,

pub ecc_key_idx: u32,
Expand Down Expand Up @@ -125,8 +129,10 @@ pub struct ImageGeneratorOwnerConfig {
#[derive(Default)]
pub struct ImageGeneratorConfig<T>
where
T: ImageGenratorExecutable,
T: ImageGeneratorExecutable,
{
pub manifest_type: ManifestType,

pub vendor_config: ImageGeneratorVendorConfig,

pub owner_config: Option<ImageGeneratorOwnerConfig>,
Expand Down
1 change: 1 addition & 0 deletions image/serde/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -12,4 +12,5 @@ doctest = false
anyhow.workspace = true
caliptra-image-types = { workspace = true, features = ["std"] }
zerocopy.workspace = true
memoffset.workspace = true

Loading
Loading