Skip to content

Commit

Permalink
Addressing CR feedback: Iteration 1
Browse files Browse the repository at this point in the history
  • Loading branch information
mhatrevi committed Aug 22, 2024
1 parent a13faca commit 1fa10b6
Show file tree
Hide file tree
Showing 8 changed files with 107 additions and 86 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.

22 changes: 14 additions & 8 deletions auth-manifest/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,27 +3,33 @@
The Caliptra SOC manifest has two main components:

- ### **Preamble**
The Preamble section contains the authorization manifest ECC and LMS public keys of the manufacturer and the owner. These public keys correspond to the private keys that sign the Image Metadata Collection (IMC) section. These signatures are included in the Preamble. The Caliptra firmware’s private keys endorse the manifest’s public keys, and these endorsements (signatures) are part of the Preamble as well.
The Preamble section contains the authorization manifest ECC and LMS public keys of the vendor and the owner. These public keys correspond to the private keys that sign the Image Metadata Collection (IMC) section. These signatures are included in the Preamble. The Caliptra firmware’s ECC and LMS private keys endorse the manifest’s public keys, and these endorsements (signatures) are part of the Preamble as well.

*Note: All fields are little endian unless specified*

| Field | Size (bytes) | Description|
|-------|--------|------------|
| Manifest Marker | 4 | Magic Number marking the start of the manifest. The value must be 0x41544D4EE (‘ATMN’ in ASCII)|
| Manifest Marker | 4 | Magic Number marking the start of the manifest. The value must be 0x41544D4E (‘ATMN’ in ASCII)|
| Manifest Size | 4 | Size of the full manifest structure |
| Version | 4 | Manifest version |
| Flags | 4 | Feature flags. <br> **Bit0:** - Vendor Signature Required. If set, verify the vendor public key endorsement(s) <br>**Bit1-Bit31:** Reserved |
| Manufacturer ECC Public Key | 96 | ECC P-384 public key used to verify the IMC Signature. <br> **X-Coordinate:** Public Key X-Coordinate (48 bytes) <br> **Y-Coordinate:** Public Key Y-Coordinate (48 bytes) |
| Manufacturer LMS Public Key | 48 | LMS public key used to verify the IMC Signature. <br> **tree_type:** LMS Algorithm Type (4 bytes) <br> **otstype:** LMS Ots Algorithm Type (4 bytes) <br> **id:** (16 bytes) <br> **digest:** (24 bytes) |
| Manufacturer ECC Signature | 96 | Manufacturer ECDSA P-384 signature of the Version, Flags, Manufacturer ECC and LMS public keys, hashed using SHA2-384. <br> **R-Coordinate:** Random Point (48 bytes) <br> **S-Coordinate:** Proof (48 bytes) |
| Manufacturer LMS Signature | 1620 | Manufacturer LMS signature of the Version, Flags, Manufacturer ECC and LMS public keys, hashed using SHA2-384. <br> **q:** Leaf of the Merkle tree where the OTS public key appears (4 bytes) <br> **ots:** Lmots Signature (1252 bytes) <br> **tree_type:** Lms Algorithm Type (4 bytes) <br> **tree_path:** Path through the tree from the leaf associated with the LM-OTS signature to the root. (360 bytes) |
| Flags | 4 | Feature flags. <br> **Bit0:** - Vendor Signature Required. If set, verify the vendor IMC signature(s) <br>**Bit1-Bit31:** Reserved |
| Vendor ECC Public Key | 96 | ECC P-384 public key used to verify the IMC Signature. <br> **X-Coordinate:** Public Key X-Coordinate (48 bytes) <br> **Y-Coordinate:** Public Key Y-Coordinate (48 bytes) |
| Vendor LMS Public Key | 48 | LMS public key used to verify the IMC Signature. <br> **tree_type:** LMS Algorithm Type (4 bytes) <br> **otstype:** LMS Ots Algorithm Type (4 bytes) <br> **id:** (16 bytes) <br> **digest:** (24 bytes) |
| Vendor ECC Signature | 96 | Vendor ECDSA P-384 signature of the Version, Flags, Vendor ECC and LMS public keys, hashed using SHA2-384. <br> **R-Coordinate:** Random Point (48 bytes) <br> **S-Coordinate:** Proof (48 bytes) |
| Vendor LMS Signature | 1620 | Vendor LMS signature of the Version, Flags, Vendor ECC and LMS public keys, hashed using SHA2-384. <br> **q:** Leaf of the Merkle tree where the OTS public key appears (4 bytes) <br> **ots:** Lmots Signature (1252 bytes) <br> **tree_type:** Lms Algorithm Type (4 bytes) <br> **tree_path:** Path through the tree from the leaf associated with the LM-OTS signature to the root. (360 bytes) |
| Owner ECC Public Key | 96 | ECC P-384 public key used to verify the IMC Signature. <br> **X-Coordinate:** Public Key X-Coordinate (48 bytes) <br> **Y-Coordinate:** Public Key Y-Coordinate (48 bytes) |
| Owner LMS Public Key | 48 | LMS public key used to verify the IMC Signature. <br> **tree_type:** LMS Algorithm Type (4 bytes) <br> **otstype:** LMS Ots Algorithm Type (4 bytes) <br> **id:** (16 bytes) <br> **digest:** (24 bytes) |
| Owner ECC Signature | 96 | Owner ECDSA P-384 signature of the Version, Flags, Owner ECC and LMS public keys, hashed using SHA2-384. <br> **R-Coordinate:** Random Point (48 bytes) <br> **S-Coordinate:** Proof (48 bytes) |
| Owner LMS Signature | 1620 | Owner LMS signature of the Version, Flags, Owner ECC and LMS public keys, hashed using SHA2-384. <br> **q:** Leaf of the Merkle tree where the OTS public key appears (4 bytes) <br> **ots:** Lmots Signature (1252 bytes) <br> **tree_type:** Lms Algorithm Type (4 bytes) <br> **tree_path:** Path through the tree from the leaf associated with the LM-OTS signature to the root. (360 bytes) |

- ### **Image Metadata Entry**
| Field | Size (bytes) | Description|
|-------|--------|------------|
| Image Hash | 48 | SHA2-384 hash of a SOC image |
| Image Source | 4 | <TBD> |

- ### **Image Metadata Collection**
The Image Metadata Collection (IMC) is a collection of Image Metadata entries (IME). Each IME has a hash that matches a SOC images. The manifest manufacturer and owner private keys sign the IMC. The Preamble holds the IMC signatures. The manifest IMC manufacturer signatures are optional and are validated only if the FLAGS field Bit 0 = 1. Up to sixteen image hashes will be supported.
The Image Metadata Collection (IMC) is a collection of Image Metadata entries (IME). Each IME has a hash that matches a SOC images. The manifest vendor and owner private keys sign the IMC. The Preamble holds the IMC signatures. The manifest IMC vendor signatures are optional and are validated only if the FLAGS field Bit 0 = 1. Up to sixteen image hashes are supported.

| Field | Size (bytes) | Description|
|-------|--------|------------|
Expand Down
63 changes: 31 additions & 32 deletions auth-manifest/app/src/config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ Abstract:

use anyhow::Context;
use caliptra_auth_man_gen::AuthManifestGeneratorKeyConfig;
use caliptra_auth_man_types::AuthManifestPubKeys;
use caliptra_auth_man_types::{AuthManifestImageMetadata, AuthManifestPrivKeys};
#[cfg(feature = "openssl")]
use caliptra_image_crypto::OsslCrypto as Crypto;
Expand All @@ -24,9 +25,9 @@ use caliptra_image_gen::*;
use serde_derive::{Deserialize, Serialize};
use std::path::{Path, PathBuf};

/// Authorization Manifest Key Configuration
/// Authorization Manifest Key configuration from config file.
#[derive(Default, Serialize, Deserialize)]
pub(crate) struct AuthManKeyConfig {
pub(crate) struct AuthManifestKeyConfigFromFile {
pub ecc_pub_key: String,

pub ecc_priv_key: Option<String>,
Expand All @@ -42,81 +43,79 @@ pub struct ImageMetadata {
source: u32,
}

// Key Configuration
// Authorization Manifest configuration from TOML file
#[derive(Default, Serialize, Deserialize)]
pub(crate) struct AuthManMasterKeyConfig {
pub vendor_fw_key_config: AuthManKeyConfig,
pub(crate) struct AuthManifestConfigFromFile {
pub vendor_fw_key_config: AuthManifestKeyConfigFromFile,

pub vendor_man_key_config: AuthManKeyConfig,
pub vendor_man_key_config: AuthManifestKeyConfigFromFile,

pub owner_fw_key_config: Option<AuthManKeyConfig>,
pub owner_fw_key_config: Option<AuthManifestKeyConfigFromFile>,

pub owner_man_key_config: Option<AuthManKeyConfig>,
pub owner_man_key_config: Option<AuthManifestKeyConfigFromFile>,

pub image_metadata_list: Vec<ImageMetadata>,
}

/// Load Authorization Manifest Key Configuration from file
pub(crate) fn load_auth_man_config(path: &PathBuf) -> anyhow::Result<AuthManMasterKeyConfig> {
pub(crate) fn load_auth_man_config_from_file(
path: &PathBuf,
) -> anyhow::Result<AuthManifestConfigFromFile> {
let config_str = std::fs::read_to_string(path)
.with_context(|| format!("Failed to read the config file {}", path.display()))?;

let config: AuthManMasterKeyConfig = toml::from_str(&config_str)
.with_context(|| format!("Failed to parse config file {}", path.display()))?;
let config: AuthManifestConfigFromFile = toml::from_str(&config_str)
.with_context(|| format!("Failed to parse the config file {}", path.display()))?;

Ok(config)
}

fn key_config(
fn key_config_from_file(
path: &Path,
config: &AuthManKeyConfig,
config: &AuthManifestKeyConfigFromFile,
) -> anyhow::Result<AuthManifestGeneratorKeyConfig> {
let mut gen_config = AuthManifestGeneratorKeyConfig::default();

// Get the Public Keys.
let pub_key_path = path.join(&config.ecc_pub_key);
gen_config.pub_keys.ecc_pub_key = Crypto::ecc_pub_key_from_pem(&pub_key_path)?;

let pub_key_path = path.join(&config.lms_pub_key);
gen_config.pub_keys.lms_pub_key = lms_pub_key_from_pem(&pub_key_path)?;

// Get the Private Keys.
let mut priv_keys = AuthManifestPrivKeys::default();
if let Some(pem_file) = &config.ecc_priv_key {
let priv_key_path = path.join(pem_file);
priv_keys.ecc_priv_key = Crypto::ecc_priv_key_from_pem(&priv_key_path)?;
gen_config.priv_keys = Some(priv_keys);
}

if let Some(pem_file) = &config.lms_priv_key {
let priv_key_path = path.join(pem_file);
priv_keys.lms_priv_key = lms_priv_key_from_pem(&priv_key_path)?;
gen_config.priv_keys = Some(priv_keys);
}

Ok(gen_config)
Ok(AuthManifestGeneratorKeyConfig {
pub_keys: AuthManifestPubKeys {
ecc_pub_key: Crypto::ecc_pub_key_from_pem(&path.join(&config.ecc_pub_key))?,
lms_pub_key: lms_pub_key_from_pem(&path.join(&config.lms_pub_key))?,
},

priv_keys: Some(priv_keys),
})
}

pub(crate) fn vendor_config(
pub(crate) fn vendor_config_from_file(
path: &Path,
config: &AuthManKeyConfig,
config: &AuthManifestKeyConfigFromFile,
) -> anyhow::Result<AuthManifestGeneratorKeyConfig> {
key_config(path, config)
key_config_from_file(path, config)
}

pub(crate) fn owner_config(
pub(crate) fn owner_config_from_file(
path: &Path,
config: &Option<AuthManKeyConfig>,
config: &Option<AuthManifestKeyConfigFromFile>,
) -> anyhow::Result<Option<AuthManifestGeneratorKeyConfig>> {
if let Some(config) = config {
let gen_config = key_config(path, config)?;
let gen_config = key_config_from_file(path, config)?;
Ok(Some(gen_config))
} else {
Ok(None)
}
}

pub(crate) fn image_metadata_config(
pub(crate) fn image_metadata_config_from_file(
config: &Vec<ImageMetadata>,
) -> anyhow::Result<Vec<AuthManifestImageMetadata>> {
let mut image_metadata_list = Vec::new();
Expand Down
39 changes: 22 additions & 17 deletions auth-manifest/app/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ Abstract:

use anyhow::Context;
use caliptra_auth_man_gen::{AuthManifestGenerator, AuthManifestGeneratorConfig};
use caliptra_auth_man_types::AuthManifestFlags;
#[cfg(feature = "openssl")]
use caliptra_image_crypto::OsslCrypto as Crypto;
#[cfg(feature = "rustcrypto")]
Expand Down Expand Up @@ -46,12 +47,7 @@ fn main() {
.value_parser(value_parser!(PathBuf)),
)
.arg(
arg!(--"config" <FILE> "Configuration file")
.required(true)
.value_parser(value_parser!(PathBuf)),
)
.arg(
arg!(--"key-dir" <FILE> "Key files directory path")
arg!(--"config" <FILE> "Manifest configuration file")
.required(true)
.value_parser(value_parser!(PathBuf)),
)
Expand Down Expand Up @@ -80,14 +76,20 @@ pub(crate) fn run_auth_man_cmd(args: &ArgMatches) -> anyhow::Result<()> {
.get_one::<u32>("version")
.with_context(|| "version arg not specified")?;

let flags: &u32 = args
.get_one::<u32>("flags")
.with_context(|| "flags arg not specified")?;
let flags: AuthManifestFlags = AuthManifestFlags::from_bits_truncate(
*args
.get_one::<u32>("flags")
.with_context(|| "flags arg not specified")?,
);

let config_path: &PathBuf = args
.get_one::<PathBuf>("config")
.with_context(|| "config arg not specified")?;

if !config_path.exists() {
return Err(anyhow::anyhow!("Invalid config file path"));
}

let key_dir: &PathBuf = args
.get_one::<PathBuf>("key-dir")
.with_context(|| "key-dir arg not specified")?;
Expand All @@ -100,18 +102,21 @@ pub(crate) fn run_auth_man_cmd(args: &ArgMatches) -> anyhow::Result<()> {
.get_one::<PathBuf>("out")
.with_context(|| "out arg not specified")?;

// Load the configuration from the config file.
let config = config::load_auth_man_config(config_path)?;
// Load the manifest configuration from the config file.
let config = config::load_auth_man_config_from_file(config_path)?;

// Decode the configuration.
let gen_config = AuthManifestGeneratorConfig {
version: *version,
flags: *flags,
vendor_man_key_info: config::vendor_config(key_dir, &config.vendor_man_key_config)?,
owner_man_key_info: config::owner_config(key_dir, &config.owner_man_key_config)?,
vendor_fw_key_info: config::vendor_config(key_dir, &config.vendor_fw_key_config)?,
owner_fw_key_info: config::owner_config(key_dir, &config.owner_fw_key_config)?,
image_metadata_list: config::image_metadata_config(&config.image_metadata_list)?,
flags,
vendor_man_key_info: config::vendor_config_from_file(
key_dir,
&config.vendor_man_key_config,
)?,
owner_man_key_info: config::owner_config_from_file(key_dir, &config.owner_man_key_config)?,
vendor_fw_key_info: config::vendor_config_from_file(key_dir, &config.vendor_fw_key_config)?,
owner_fw_key_info: config::owner_config_from_file(key_dir, &config.owner_fw_key_config)?,
image_metadata_list: config::image_metadata_config_from_file(&config.image_metadata_list)?,
};

let gen = AuthManifestGenerator::new(Crypto::default());
Expand Down
57 changes: 30 additions & 27 deletions auth-manifest/gen/src/generator.rs
Original file line number Diff line number Diff line change
Expand Up @@ -37,10 +37,10 @@ impl<Crypto: ImageGeneratorCrypto> AuthManifestGenerator<Crypto> {

if config.image_metadata_list.len() > AUTH_MANIFEST_IMAGE_METADATA_MAX_COUNT {
eprintln!(
"Encountered an error converting image_metadata_list, only {} entries supported.",
"Unsupported image metadata count, only {} entries supported.",
AUTH_MANIFEST_IMAGE_METADATA_MAX_COUNT
);
return Err(anyhow::anyhow!("Error converting image_metadata_list"));
return Err(anyhow::anyhow!("Error converting image metadata list"));
}

// Generate the Image Metadata List.
Expand All @@ -55,9 +55,9 @@ impl<Crypto: ImageGeneratorCrypto> AuthManifestGenerator<Crypto> {
auth_manifest.preamble.marker = AUTH_MANIFEST_MARKER;
auth_manifest.preamble.size = size_of::<AuthManifestPreamble>() as u32;
auth_manifest.preamble.version = config.version;
auth_manifest.preamble.flags = config.flags;
auth_manifest.preamble.flags = config.flags.bits();

// Sign the vendor manifest keys.
// Sign the vendor manifest public keys.
auth_manifest.preamble.vendor_pub_keys = config.vendor_man_key_info.pub_keys;

let range = AuthManifestPreamble::vendor_signed_data_range();
Expand Down Expand Up @@ -86,37 +86,40 @@ impl<Crypto: ImageGeneratorCrypto> AuthManifestGenerator<Crypto> {
auth_manifest.preamble.vendor_pub_keys_signatures.lms_sig = lms_sig;
}

// Sign the owner manifest keys.
if let Some(owner_fw_config) = &config.owner_fw_key_info {
if let Some(owner_man_config) = &config.owner_man_key_info {
auth_manifest.preamble.owner_pub_keys = owner_man_config.pub_keys;
// Sign the owner manifest public keys.
if let (Some(owner_fw_config), Some(owner_man_config)) =
(&config.owner_fw_key_info, &config.owner_man_key_info)
{
auth_manifest.preamble.owner_pub_keys = owner_man_config.pub_keys;

let digest = self
let digest = self
.crypto
.sha384_digest(auth_manifest.preamble.owner_pub_keys.as_bytes())?;

if let Some(owner_fw_priv_keys) = owner_fw_config.priv_keys {
let sig = self.crypto.ecdsa384_sign(
&digest,
&owner_fw_priv_keys.ecc_priv_key,
&owner_fw_config.pub_keys.ecc_pub_key,
)?;
auth_manifest.preamble.owner_pub_keys_signatures.ecc_sig = sig;
let lms_sig = self
.crypto
.sha384_digest(auth_manifest.preamble.owner_pub_keys.as_bytes())?;

if let Some(owner_fw_priv_keys) = owner_fw_config.priv_keys {
let sig = self.crypto.ecdsa384_sign(
&digest,
&owner_fw_priv_keys.ecc_priv_key,
&owner_fw_config.pub_keys.ecc_pub_key,
)?;
auth_manifest.preamble.owner_pub_keys_signatures.ecc_sig = sig;
let lms_sig = self
.crypto
.lms_sign(&digest, &owner_fw_priv_keys.lms_priv_key)?;
auth_manifest.preamble.owner_pub_keys_signatures.lms_sig = lms_sig;
}
.lms_sign(&digest, &owner_fw_priv_keys.lms_priv_key)?;
auth_manifest.preamble.owner_pub_keys_signatures.lms_sig = lms_sig;
}
}

// Sign the Image Metadata List.
// Hash the IMC.
let digest = self
.crypto
.sha384_digest(auth_manifest.image_metadata_col.as_bytes())?;

// Sign with the vendor manifest public keys if indicated in the flags.
if auth_manifest.preamble.flags & AUTH_MANIFEST_VENDOR_SIGNATURE_REQURIED_FLAG != 0 {
// Sign the IMC with the vendor manifest public keys if indicated in the flags.
if config
.flags
.contains(AuthManifestFlags::VENDOR_SIGNATURE_REQURIED)
{
if let Some(vendor_man_priv_keys) = config.vendor_man_key_info.priv_keys {
let sig = self.crypto.ecdsa384_sign(
&digest,
Expand All @@ -138,7 +141,7 @@ impl<Crypto: ImageGeneratorCrypto> AuthManifestGenerator<Crypto> {
}
}

// Sign with the owner manifest public keys.
// Sign the IMC with the owner manifest public keys.
if let Some(owner_man_config) = &config.owner_man_key_info {
if let Some(owner_man_priv_keys) = &owner_man_config.priv_keys {
let sig = self.crypto.ecdsa384_sign(
Expand Down
3 changes: 1 addition & 2 deletions auth-manifest/gen/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,6 @@ mod generator;

pub use generator::AuthManifestGenerator;

//use auth_man_generator::{AuthManPrivKeys, AuthManPubKeys};
use caliptra_auth_man_types::*;

/// Image Generator Vendor Configuration
Expand All @@ -31,7 +30,7 @@ pub struct AuthManifestGeneratorKeyConfig {
pub struct AuthManifestGeneratorConfig {
pub version: u32,

pub flags: u32,
pub flags: AuthManifestFlags,

pub vendor_fw_key_info: AuthManifestGeneratorKeyConfig,

Expand Down
1 change: 1 addition & 0 deletions auth-manifest/types/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ zerocopy.workspace = true
caliptra-error = { workspace = true, default-features = false }
zeroize.workspace = true
caliptra-image-types = { workspace = true, default-features = false }
bitflags.workspace = true

[features]
default = ["std"]
Expand Down
Loading

0 comments on commit 1fa10b6

Please sign in to comment.