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

Set auth manifest tests #1829

Closed
wants to merge 14 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
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
2 changes: 2 additions & 0 deletions Cargo.lock

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

4 changes: 2 additions & 2 deletions api/src/mailbox.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1059,8 +1059,8 @@ impl AuthAndStashFlags {
#[derive(Debug, AsBytes, FromBytes, PartialEq, Eq)]
pub struct AuthorizeAndStashReq {
pub hdr: MailboxReqHeader,
pub metadata: [u8; 4],
pub measurement: [u8; 48],
pub metadata: [u8; 4], // Firmware Id.
pub measurement: [u8; 48], // Image digest.
pub context: [u8; 48],
pub svn: u32,
pub flags: u32,
Expand Down
6 changes: 6 additions & 0 deletions auth-manifest/app/src/auth-man.toml
Original file line number Diff line number Diff line change
Expand Up @@ -27,11 +27,17 @@ lms_priv_key = "own-lms-priv-key.pem"
[[image_metadata_list]]
digest = "C120EED0004B4CF6C344B00F5F501E7B7167C7010B6EA1D36AEE20CC90F1AE373DF1EC91C9AD9E0A5A969326A54E2517"
source = 1
fw_id = 1
ignore_auth_check = false

[[image_metadata_list]]
digest = "99514329186b2f6ae4a1329e7ee6c610a729636335174ac6b740f9028396fcc803d0e93863a7c3d90f86beee782f4f3f"
source = 2
fw_id = 2
ignore_auth_check = true

[[image_metadata_list]]
digest = "9B514329186b2f6ae4a1329e7ee6c610a729636335174ac6b740f9028396fcc803d0e93863a7c3d90f86beee782f4f3f"
source = 2
fw_id = 3
ignore_auth_check = false
21 changes: 18 additions & 3 deletions auth-manifest/app/src/config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,8 @@ Abstract:

use anyhow::Context;
use caliptra_auth_man_gen::AuthManifestGeneratorKeyConfig;
use caliptra_auth_man_types::AuthManifestPubKeys;
use caliptra_auth_man_types::{AuthManifestImageMetadata, AuthManifestPrivKeys};
use caliptra_auth_man_types::{AuthManifestPubKeys, ImageMetadataFlags};
#[cfg(feature = "openssl")]
use caliptra_image_crypto::OsslCrypto as Crypto;
#[cfg(feature = "rustcrypto")]
Expand All @@ -41,6 +41,8 @@ pub(crate) struct AuthManifestKeyConfigFromFile {
pub struct ImageMetadataConfigFromFile {
digest: String,
source: u32,
fw_id: u32,
ignore_auth_check: bool,
}

// Authorization Manifest configuration from TOML file
Expand Down Expand Up @@ -119,14 +121,27 @@ pub(crate) fn image_metadata_config_from_file(
config: &Vec<ImageMetadataConfigFromFile>,
) -> anyhow::Result<Vec<AuthManifestImageMetadata>> {
let mut image_metadata_list = Vec::new();
let mut fw_ids: Vec<u32> = Vec::new();

for image in config {
// Check if the firmware ID is already present in the list.
if fw_ids.contains(&image.fw_id) {
return Err(anyhow::anyhow!(
"Duplicate firmware ID found in the image metadata list"
));
} else {
fw_ids.push(image.fw_id);
}

let digest_vec = hex::decode(&image.digest)?;
let image_source = image.source;
let mut flags = ImageMetadataFlags(0);
flags.set_ignore_auth_check(image.ignore_auth_check);
flags.set_image_source(image.source);

let image_metadata = AuthManifestImageMetadata {
fw_id: image.fw_id,
flags: flags.0,
digest: digest_vec.try_into().unwrap(),
image_source,
};

image_metadata_list.push(image_metadata);
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 @@ -17,6 +17,7 @@ caliptra-error = { workspace = true, default-features = false }
zeroize.workspace = true
caliptra-image-types = { workspace = true, default-features = false }
bitflags.workspace = true
bitfield.workspace = true

[features]
default = ["std"]
Expand Down
24 changes: 17 additions & 7 deletions auth-manifest/types/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,16 +14,16 @@ Abstract:

#![no_std]

use core::ops::Range;

use bitfield::bitfield;
use caliptra_image_types::*;
use core::default::Default;
use core::ops::Range;
use memoffset::span_of;
use zerocopy::{AsBytes, FromBytes};
use zeroize::Zeroize;

pub const AUTH_MANIFEST_MARKER: u32 = 0x4154_4D4E;
pub const AUTH_MANIFEST_IMAGE_METADATA_MAX_COUNT: usize = 128;
pub const AUTH_MANIFEST_IMAGE_METADATA_MAX_COUNT: usize = 127;

bitflags::bitflags! {
#[derive(Default, Copy, Clone, Debug)]
Expand Down Expand Up @@ -76,7 +76,7 @@ pub struct AuthManifestPreamble {

pub version: u32,

pub flags: u32,
pub flags: u32, // AuthManifestFlags(VENDOR_SIGNATURE_REQUIRED)

pub vendor_pub_keys: AuthManifestPubKeys,

Expand Down Expand Up @@ -129,21 +129,31 @@ impl AuthManifestPreamble {
}
}

bitfield! {
#[derive(Debug, PartialEq, Eq, Clone, Copy)]
pub struct ImageMetadataFlags(u32);
pub image_source, set_image_source: 1, 0;
pub ignore_auth_check, set_ignore_auth_check: 2;
}

/// Caliptra Authorization Manifest Image Metadata
#[repr(C)]
#[derive(AsBytes, FromBytes, Clone, Copy, Debug, Zeroize)]
#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
pub struct AuthManifestImageMetadata {
pub digest: [u8; 48],
pub fw_id: u32,

pub image_source: u32,
pub flags: u32, // ImageMetadataFlags(image_source, ignore_auth_check)

pub digest: [u8; 48],
}

impl Default for AuthManifestImageMetadata {
fn default() -> Self {
AuthManifestImageMetadata {
fw_id: u32::MAX,
flags: 0,
digest: [0; 48],
image_source: 0,
}
}
}
Expand Down
2 changes: 2 additions & 0 deletions error/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -447,6 +447,8 @@ impl CaliptraError {
CaliptraError::new_const(0x000E0051);
pub const RUNTIME_GET_IDEV_ID_UNSUPPORTED_ROM: CaliptraError =
CaliptraError::new_const(0x000E0052);
pub const RUNTIME_AUTH_MANIFEST_IMAGE_METADATA_LIST_DUPLICATE_FIRMWARE_ID: CaliptraError =
CaliptraError::new_const(0x000E0053);

/// FMC Errors
pub const FMC_GLOBAL_NMI: CaliptraError = CaliptraError::new_const(0x000F0001);
Expand Down
3 changes: 2 additions & 1 deletion runtime/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@ caliptra-auth-man-gen.workspace = true
caliptra-image-serde.workspace = true
caliptra-cfi-lib-git = { workspace = true, features = ["cfi-test"] }
openssl.workspace = true
rand = "0.8"
sha2 = { version = "0.10.2", default-features = false, features = ["compress"] }
cms.workspace = true
wycheproof.workspace = true
Expand All @@ -64,4 +65,4 @@ fips_self_test=[]
no-cfi = ["caliptra-image-verify/no-cfi", "caliptra-drivers/no-cfi"]
fpga_realtime = ["caliptra-drivers/fpga_realtime"]
"hw-1.0" = ["caliptra-builder/hw-1.0", "caliptra-drivers/hw-1.0", "caliptra-registers/hw-1.0", "caliptra-kat/hw-1.0","caliptra-cpu/hw-1.0"]
fips-test-hooks = ["caliptra-drivers/fips-test-hooks"]
fips-test-hooks = ["caliptra-drivers/fips-test-hooks"]
29 changes: 19 additions & 10 deletions runtime/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -725,7 +725,7 @@ Command Code: `0x4154_4D4E` ("ATMN")
| preamble\_marker | u32 | Marker needs to be 0x4154_4D4E for the preamble to be valid |
| preamble\_size | u32 | Size of the preamble |
| preamble\_version | u32 | Version of the preamble |
| preamble\_flags | u32 | Preamble flags |
| preamble\_flags | u32 | Manifest flags. See AUTH_MANIFEST_FLAGS below |
| preamble\_vendor\_ecc384\_key | u32[24] | Vendor ECC384 key with X and Y coordinates in that order |
| preamble\_vendor\_lms\_key | u32[6] | Vendor LMS-SHA192-H15 key |
| preamble\_vendor\_ecc384\_sig | u32[24] | Vendor ECC384 signature |
Expand All @@ -739,7 +739,7 @@ Command Code: `0x4154_4D4E` ("ATMN")
| metadata\_owner\_ecc384\_sig | u32[24] | Metadata Owner ECC384 signature |
| metadata\_owner\_LMS\_sig | u32[1344] | Metadata Owner LMOTS-SHA192-W4 signature |
| metadata\_entry\_entry\_count | u32 | number of metadata entries |
| metadata\_entries | MetaData[128] | The max number of metadata entries is 128 but less can be used |
| metadata\_entries | Metadata[127] | The max number of metadata entries is 127 but less can be used |


*Table: `AUTH_MANIFEST_FLAGS` input flags*
Expand All @@ -750,10 +750,19 @@ Command Code: `0x4154_4D4E` ("ATMN")

*Table: `AUTH_MANIFEST_METADATA_ENTRY` digest entries*

| **Name** | **Type** | **Description** |
|---------------|----------|------------------------|
| digest | u32[48] | Digest of the metadata |
| image\_source | u32 | Image source |
| **Name** | **Type** | **Description** |
|---------------|----------|--------------------------------|
| fw\_id | u32 | Id of the image |
| flags | u32 | See METADATA_ENTRY_FLAGS below |
| digest | u32[48] | Digest of the image |


*Table: `METADATA_ENTRY_FLAGS` input flags*

| **Name** | **Size (Bits)** | **Description** |
|---------------------|-----------------|-----------------|
| image\_source | 2 | 1: InRequest |
| ignore\_auth\_check | 1 | If set, the image digest is not compared for the firmware id |

*Table: `SET_AUTH_MANIFEST` output arguments*

Expand All @@ -772,11 +781,11 @@ Command Code: `0x4154_5348` ("ATSH")
| **Name** | **Type** | **Description**
| -------- | -------- | ---------------
| chksum | u32 | Checksum over other input arguments, computed by the caller. Little endian. |
| metadata | u8[4] | 4-byte measurement identifier. |
| measurement | u8[48] | Digest of measured |
| metadata | u8[4] | Firmware id of the image, in little-endian format |
| measurement | u8[48] | Digest of the image requested for authorization |
| context | u8[48] | Context field for `svn`; e.g., a hash of the public key that authenticated the SVN. |
| svn | u32 | SVN |
| flags | u32 | Flags |
| flags | u32 | See AUTHORIZE_AND_STASH_FLAGS below |
| source | u32 | Enumeration values: { InRequest(1), ShaAcc (2) } |

*Table: `AUTHORIZE_AND_STASH_FLAGS` input flags*
Expand All @@ -790,7 +799,7 @@ Command Code: `0x4154_5348` ("ATSH")
| -------- | -------- | ---------------
| chksum | u32 | Checksum over other output arguments, computed by Caliptra. Little endian. |
| fips_status | u32 | Indicates if the command is FIPS approved or an error. |
| auth_req_result | u32 | AUTHORIZE_IMAGE: 0xDEADC0DE and DENY_IMAGE_AUTHORIZATION: 0x21523F21 |
| auth_req_result | u32 | AUTHORIZE_IMAGE (0xDEADC0DE), IMAGE_NOT_AUTHORIZED (0x21523F21) or IMAGE_HASH_MISMATCH (0x8BFB95CB) |

### GET\_IDEVID\_CSR

Expand Down
65 changes: 52 additions & 13 deletions runtime/src/authorize_and_stash.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,15 +12,16 @@ Abstract:

--*/

use core::cmp::min;
use core::cmp::{self, min};
use core::mem::size_of;

use crate::{dpe_crypto::DpeCrypto, CptraDpeTypes, DpePlatform, Drivers, StashMeasurementCmd};
use caliptra_auth_man_types::{
AuthManifestImageMetadataCollection, AuthManifestPreamble, AUTH_MANIFEST_MARKER,
AuthManifestImageMetadata, AuthManifestImageMetadataCollection, AuthManifestPreamble,
ImageMetadataFlags, AUTH_MANIFEST_MARKER,
};
use caliptra_cfi_derive_git::cfi_impl_fn;
use caliptra_cfi_lib_git::cfi_launder;
use caliptra_cfi_lib_git::{cfi_assert, cfi_assert_eq, cfi_launder};
use caliptra_common::mailbox_api::{
AuthAndStashFlags, AuthorizeAndStashReq, AuthorizeAndStashResp, ImageHashSource, MailboxResp,
MailboxRespHeader, SetAuthManifestReq,
Expand All @@ -44,8 +45,9 @@ use dpe::{
use memoffset::offset_of;
use zerocopy::{AsBytes, FromBytes};

pub const AUTHORIZE_IMAGE: u32 = 0xDEADC0DE;
pub const DENY_IMAGE_AUTHORIZATION: u32 = 0x21523F21;
pub const IMAGE_AUTHORIZED: u32 = 0xDEADC0DE; // Either FW ID and image digest matched or 'ignore_auth_check' is set for the FW ID.
pub const IMAGE_NOT_AUTHORIZED: u32 = 0x21523F21; // FW ID not found in the image metadata entry collection.
pub const IMAGE_HASH_MISMATCH: u32 = 0x8BFB95CB; // FW ID matched, but image digest mismatched.

pub struct AuthorizeAndStashCmd;
impl AuthorizeAndStashCmd {
Expand All @@ -57,25 +59,35 @@ impl AuthorizeAndStashCmd {
Err(CaliptraError::RUNTIME_AUTH_AND_STASH_UNSUPPORTED_IMAGE_SOURCE)?;
}

// Check if image hash is present in the image metadata entry collection.
// Check if firmware id is present in the image metadata entry collection.
let persistent_data = drivers.persistent_data.get();
let auth_manifest_image_metadata_col =
&persistent_data.auth_manifest_image_metadata_col;

let mut auth_result = DENY_IMAGE_AUTHORIZATION;
for metadata_entry in auth_manifest_image_metadata_col.image_metadata_list.iter() {
if cfi_launder(metadata_entry.digest) == cmd.measurement {
let cmd_fw_id = u32::from_le_bytes(cmd.metadata);
let auth_result = if let Some(metadata_entry) =
Self::find_metadata_entry(auth_manifest_image_metadata_col, cmd_fw_id)
{
// If 'ignore_auth_check' is set, then skip the image digest comparison and authorize the image.
let flags = ImageMetadataFlags(metadata_entry.flags);
if flags.ignore_auth_check() {
cfi_assert!(cfi_launder(flags.ignore_auth_check()));
IMAGE_AUTHORIZED
} else if cfi_launder(metadata_entry.digest) == cmd.measurement {
caliptra_cfi_lib_git::cfi_assert_eq_12_words(
&Array4x12::from(metadata_entry.digest).0,
&Array4x12::from(cmd.measurement).0,
);
auth_result = AUTHORIZE_IMAGE;
break;
IMAGE_AUTHORIZED
} else {
IMAGE_HASH_MISMATCH
}
}
} else {
IMAGE_NOT_AUTHORIZED
};

// Stash the measurement if the image is authorized.
if auth_result == AUTHORIZE_IMAGE {
if auth_result == IMAGE_AUTHORIZED {
let flags: AuthAndStashFlags = cmd.flags.into();
if !flags.contains(AuthAndStashFlags::SKIP_STASH) {
let dpe_result = StashMeasurementCmd::stash_measurement(
Expand All @@ -100,4 +112,31 @@ impl AuthorizeAndStashCmd {
Err(CaliptraError::RUNTIME_INSUFFICIENT_MEMORY)
}
}

/// Search for a metadata entry in the sorted `AuthManifestImageMetadataCollection` that matches the firmware ID.
///
/// This function performs a binary search on the `image_metadata_list` of the provided `AuthManifestImageMetadataCollection`.
/// It compares the firmware ID (`fw_id`) of each metadata entry with the provided `cmd_fw_id`.
///
/// # Arguments
///
/// * `auth_manifest_image_metadata_col` - A reference to the `AuthManifestImageMetadataCollection` containing the metadata entries.
/// * `cmd_fw_id` - The firmware ID from the command to search for.
///
/// # Returns
///
/// * `Option<&AuthManifestImageMetadata>` - Returns `Some(&AuthManifestImageMetadata)` if a matching entry is found,
/// otherwise returns `None`.
///
#[inline(never)]
fn find_metadata_entry(
auth_manifest_image_metadata_col: &AuthManifestImageMetadataCollection,
cmd_fw_id: u32,
) -> Option<&AuthManifestImageMetadata> {
auth_manifest_image_metadata_col
.image_metadata_list
.binary_search_by(|metadata| metadata.fw_id.cmp(&cmd_fw_id))
.ok()
.map(|index| &auth_manifest_image_metadata_col.image_metadata_list[index])
}
}
2 changes: 1 addition & 1 deletion runtime/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ use crate::capabilities::CapabilitiesCmd;
pub use crate::certify_key_extended::CertifyKeyExtendedCmd;
pub use crate::hmac::Hmac;
pub use crate::subject_alt_name::AddSubjectAltNameCmd;
pub use authorize_and_stash::{AUTHORIZE_IMAGE, DENY_IMAGE_AUTHORIZATION};
pub use authorize_and_stash::{IMAGE_AUTHORIZED, IMAGE_HASH_MISMATCH, IMAGE_NOT_AUTHORIZED};
pub use caliptra_common::fips::FipsVersionCmd;
pub use dice::{GetFmcAliasCertCmd, GetLdevCertCmd, IDevIdCertCmd};
pub use disable::DisableAttestationCmd;
Expand Down
Loading
Loading