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] Manifest Based Image Authorization - Runtime commands #1649

Merged
merged 4 commits into from
Sep 3, 2024
Merged
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
4 changes: 4 additions & 0 deletions Cargo.lock

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

129 changes: 129 additions & 0 deletions api/src/mailbox.rs
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,12 @@ impl CommandId {

// The capabilities command.
pub const CAPABILITIES: Self = Self(0x4341_5053); // "CAPS"

// The authorization manifest set command.
pub const SET_AUTH_MANIFEST: Self = Self(0x4154_4D4E); // "ATMN"

// The authorize and stash command.
pub const AUTHORIZE_AND_STASH: Self = Self(0x4154_5348); // "ATSH"
}

impl From<u32> for CommandId {
Expand Down Expand Up @@ -140,6 +146,7 @@ pub enum MailboxResp {
GetRtAliasCert(GetRtAliasCertResp),
QuotePcrs(QuotePcrsResp),
CertifyKeyExtended(CertifyKeyExtendedResp),
AuthorizeAndStash(AuthorizeAndStashResp),
}

impl MailboxResp {
Expand All @@ -159,6 +166,7 @@ impl MailboxResp {
MailboxResp::GetRtAliasCert(resp) => resp.as_bytes_partial(),
MailboxResp::QuotePcrs(resp) => Ok(resp.as_bytes()),
MailboxResp::CertifyKeyExtended(resp) => Ok(resp.as_bytes()),
MailboxResp::AuthorizeAndStash(resp) => Ok(resp.as_bytes()),
}
}

Expand All @@ -178,6 +186,7 @@ impl MailboxResp {
MailboxResp::GetRtAliasCert(resp) => resp.as_bytes_partial_mut(),
MailboxResp::QuotePcrs(resp) => Ok(resp.as_bytes_mut()),
MailboxResp::CertifyKeyExtended(resp) => Ok(resp.as_bytes_mut()),
MailboxResp::AuthorizeAndStash(resp) => Ok(resp.as_bytes_mut()),
}
}

Expand Down Expand Up @@ -236,6 +245,8 @@ pub enum MailboxReq {
ExtendPcr(ExtendPcrReq),
AddSubjectAltName(AddSubjectAltNameReq),
CertifyKeyExtended(CertifyKeyExtendedReq),
SetAuthManifest(SetAuthManifestReq),
AuthorizeAndStash(AuthorizeAndStashReq),
}

impl MailboxReq {
Expand All @@ -259,6 +270,8 @@ impl MailboxReq {
MailboxReq::ExtendPcr(req) => Ok(req.as_bytes()),
MailboxReq::AddSubjectAltName(req) => req.as_bytes_partial(),
MailboxReq::CertifyKeyExtended(req) => Ok(req.as_bytes()),
MailboxReq::SetAuthManifest(req) => Ok(req.as_bytes()),
MailboxReq::AuthorizeAndStash(req) => Ok(req.as_bytes()),
}
}

Expand All @@ -282,6 +295,8 @@ impl MailboxReq {
MailboxReq::ExtendPcr(req) => Ok(req.as_bytes_mut()),
MailboxReq::AddSubjectAltName(req) => req.as_bytes_partial_mut(),
MailboxReq::CertifyKeyExtended(req) => Ok(req.as_bytes_mut()),
MailboxReq::SetAuthManifest(req) => Ok(req.as_bytes_mut()),
MailboxReq::AuthorizeAndStash(req) => Ok(req.as_bytes_mut()),
}
}

Expand All @@ -305,6 +320,8 @@ impl MailboxReq {
MailboxReq::ExtendPcr(_) => CommandId::EXTEND_PCR,
MailboxReq::AddSubjectAltName(_) => CommandId::ADD_SUBJECT_ALT_NAME,
MailboxReq::CertifyKeyExtended(_) => CommandId::CERTIFY_KEY_EXTENDED,
MailboxReq::SetAuthManifest(_) => CommandId::SET_AUTH_MANIFEST,
MailboxReq::AuthorizeAndStash(_) => CommandId::AUTHORIZE_AND_STASH,
}
}

Expand Down Expand Up @@ -918,6 +935,118 @@ impl Request for QuotePcrsReq {
type Resp = QuotePcrsResp;
}

// SET_AUTH_MANIFEST
#[repr(C)]
#[derive(Debug, AsBytes, FromBytes, PartialEq, Eq)]
pub struct SetAuthManifestReq {
pub hdr: MailboxReqHeader,
pub manifest_size: u32,
pub manifest: [u8; SetAuthManifestReq::MAX_MAN_SIZE],
}
impl SetAuthManifestReq {
pub const MAX_MAN_SIZE: usize = 8192;

pub fn as_bytes_partial(&self) -> CaliptraResult<&[u8]> {
if self.manifest_size as usize > Self::MAX_MAN_SIZE {
return Err(CaliptraError::RUNTIME_MAILBOX_API_REQUEST_DATA_LEN_TOO_LARGE);
}
let unused_byte_count = Self::MAX_MAN_SIZE - self.manifest_size as usize;
Ok(&self.as_bytes()[..size_of::<Self>() - unused_byte_count])
}

pub fn as_bytes_partial_mut(&mut self) -> CaliptraResult<&mut [u8]> {
if self.manifest_size as usize > Self::MAX_MAN_SIZE {
return Err(CaliptraError::RUNTIME_MAILBOX_API_REQUEST_DATA_LEN_TOO_LARGE);
}
let unused_byte_count = Self::MAX_MAN_SIZE - self.manifest_size as usize;
Ok(&mut self.as_bytes_mut()[..size_of::<Self>() - unused_byte_count])
}
}
impl Default for SetAuthManifestReq {
fn default() -> Self {
Self {
hdr: MailboxReqHeader::default(),
manifest_size: 0,
manifest: [0u8; SetAuthManifestReq::MAX_MAN_SIZE],
}
}
}

#[repr(u32)]
#[derive(Debug, PartialEq, Eq)]
pub enum ImageHashSource {
Invalid = 0,
InRequest,
ShaAcc,
}

impl From<u32> for ImageHashSource {
fn from(val: u32) -> Self {
match val {
1_u32 => ImageHashSource::InRequest,
2_u32 => ImageHashSource::ShaAcc,
_ => ImageHashSource::Invalid,
}
}
}

bitflags::bitflags! {
pub struct AuthAndStashFlags : u32 {
const SKIP_STASH = 0x1;
}
}

impl From<u32> for AuthAndStashFlags {
/// Converts to this type from the input type.
fn from(value: u32) -> Self {
AuthAndStashFlags::from_bits_truncate(value)
}
}

impl AuthAndStashFlags {
pub fn set_skip_stash(&mut self, skip_stash: bool) {
self.set(AuthAndStashFlags::SKIP_STASH, skip_stash);
}
}

// AUTHORIZE_AND_STASH
#[repr(C)]
#[derive(Debug, AsBytes, FromBytes, PartialEq, Eq)]
pub struct AuthorizeAndStashReq {
pub hdr: MailboxReqHeader,
pub metadata: [u8; 4],
pub measurement: [u8; 48],
pub context: [u8; 48],
pub svn: u32,
pub flags: u32,
pub source: u32,
}
impl Default for AuthorizeAndStashReq {
fn default() -> Self {
Self {
hdr: Default::default(),
metadata: Default::default(),
measurement: [0u8; 48],
context: [0u8; 48],
svn: Default::default(),
flags: AuthAndStashFlags::SKIP_STASH.bits(),
source: ImageHashSource::InRequest as u32,
}
}
}
impl Request for AuthorizeAndStashReq {
const ID: CommandId = CommandId::AUTHORIZE_AND_STASH;
type Resp = StashMeasurementResp;
}

#[repr(C)]
#[derive(Debug, Default, AsBytes, FromBytes, PartialEq, Eq)]
pub struct AuthorizeAndStashResp {
pub hdr: MailboxRespHeader,
pub auth_req_result: u32,
}
impl Response for AuthorizeAndStashResp {}

#[cfg(test)]
mod tests {
use super::*;
Expand Down
2 changes: 1 addition & 1 deletion auth-manifest/gen/src/generator.rs
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ impl<Crypto: ImageGeneratorCrypto> AuthManifestGenerator<Crypto> {

// Generate the Image Metadata List.
let slice = config.image_metadata_list.as_slice();
auth_manifest.image_metadata_col.image_metadata_array[..slice.len()].copy_from_slice(slice);
auth_manifest.image_metadata_col.image_metadata_list[..slice.len()].copy_from_slice(slice);

auth_manifest.image_metadata_col.header.entry_count =
config.image_metadata_list.len() as u32;
Expand Down
10 changes: 8 additions & 2 deletions auth-manifest/types/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,6 @@ use zeroize::Zeroize;

pub const AUTH_MANIFEST_MARKER: u32 = 0x4154_4D4E;
pub const AUTH_MANIFEST_IMAGE_METADATA_MAX_COUNT: usize = 16;
pub const AUTH_MANIFEST_VENDOR_SIGNATURE_REQURIED_FLAG: u32 = 0x1;

bitflags::bitflags! {
#[derive(Default, Copy, Clone, Debug)]
Expand All @@ -33,6 +32,13 @@ bitflags::bitflags! {
}
}

impl From<u32> for AuthManifestFlags {
/// Converts to this type from the input type.
fn from(value: u32) -> Self {
AuthManifestFlags::from_bits_truncate(value)
}
}

#[repr(C)]
#[derive(AsBytes, FromBytes, Default, Debug, Clone, Copy, Zeroize)]
#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
Expand Down Expand Up @@ -161,7 +167,7 @@ impl Default for AuthManifestImageMetadata {
pub struct AuthManifestImageMetadataCollection {
pub header: AuthManifestImageMetadataCollectionHeader,

pub image_metadata_array: [AuthManifestImageMetadata; AUTH_MANIFEST_IMAGE_METADATA_MAX_COUNT],
pub image_metadata_list: [AuthManifestImageMetadata; AUTH_MANIFEST_IMAGE_METADATA_MAX_COUNT],
}

/// Caliptra Image Authorization Manifest
Expand Down
2 changes: 1 addition & 1 deletion common/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ pub use pcr::{PcrLogEntry, PcrLogEntryId, RT_FW_CURRENT_PCR, RT_FW_JOURNEY_PCR};
pub const FMC_ORG: u32 = 0x40000000;
pub const FMC_SIZE: u32 = 20 * 1024;
pub const RUNTIME_ORG: u32 = FMC_ORG + FMC_SIZE;
pub const RUNTIME_SIZE: u32 = 94 * 1024;
pub const RUNTIME_SIZE: u32 = 97 * 1024;

pub use memory_layout::{DATA_ORG, FHT_ORG, FHT_SIZE, MAN1_ORG};
pub use wdt::{restart_wdt, start_wdt, stop_wdt, WdtTimeout};
1 change: 1 addition & 0 deletions drivers/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ bitflags.workspace = true
caliptra-error = { workspace = true, default-features = false }
caliptra-image-types.workspace = true
caliptra-lms-types.workspace = true
caliptra-auth-man-types.workspace = true
caliptra-registers.workspace = true
cfg-if.workspace = true
dpe = { workspace = true, optional = true }
Expand Down
2 changes: 2 additions & 0 deletions drivers/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,8 @@ pub use okref::okmutref;
pub use okref::okref;
pub use pcr_bank::{PcrBank, PcrId};
pub use pcr_reset::PcrResetCounter;
#[cfg(feature = "runtime")]
pub use persistent::{AuthManifestImageMetadataList, AUTH_MANIFEST_IMAGE_METADATA_LIST_MAX_COUNT};
pub use persistent::{
FuseLogArray, PcrLogArray, PersistentData, PersistentDataAccessor, StashMeasurementArray,
FUSE_LOG_MAX_COUNT, MEASUREMENT_MAX_COUNT, PCR_LOG_MAX_COUNT,
Expand Down
11 changes: 8 additions & 3 deletions drivers/src/memory_layout.rs
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,8 @@ 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 DATA_ORG: u32 = 0x50006C00;
pub const AUTH_MAN_IMAGE_METADATA_LIST_ORG: u32 = 0x50006C00;
pub const DATA_ORG: u32 = 0x50007000;
jhand2 marked this conversation as resolved.
Show resolved Hide resolved

pub const STACK_ORG: u32 = 0x5001A000;
pub const ROM_STACK_ORG: u32 = 0x5001C000;
Expand Down Expand Up @@ -70,7 +71,8 @@ pub const MEASUREMENT_LOG_SIZE: u32 = 1024;
pub const FUSE_LOG_SIZE: u32 = 1024;
pub const DPE_SIZE: u32 = 5 * 1024;
pub const PCR_RESET_COUNTER_SIZE: u32 = 1024;
pub const DATA_SIZE: u32 = 77 * 1024;
pub const AUTH_MAN_IMAGE_METADATA_LIST_MAX_SIZE: u32 = 1024;
pub const DATA_SIZE: u32 = 76 * 1024;
pub const STACK_SIZE: u32 = 22 * 1024;
pub const ROM_STACK_SIZE: u32 = 14 * 1024;
pub const ESTACK_SIZE: u32 = 1024;
Expand Down Expand Up @@ -145,7 +147,10 @@ fn mem_layout_test_dpe() {
#[test]
#[allow(clippy::assertions_on_constants)]
fn mem_layout_test_pcr_reset_counter() {
assert_eq!((DATA_ORG - PCR_RESET_COUNTER_ORG), PCR_RESET_COUNTER_SIZE);
assert_eq!(
(AUTH_MAN_IMAGE_METADATA_LIST_ORG - PCR_RESET_COUNTER_ORG),
PCR_RESET_COUNTER_SIZE
);
}

#[test]
Expand Down
26 changes: 25 additions & 1 deletion drivers/src/persistent.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,10 @@

use core::{marker::PhantomData, mem::size_of, ptr::addr_of};

#[cfg(feature = "runtime")]
use caliptra_auth_man_types::AuthManifestImageMetadata;
#[cfg(feature = "runtime")]
use caliptra_auth_man_types::AuthManifestImageMetadataCollection;
use caliptra_image_types::ImageManifest;
#[cfg(feature = "runtime")]
use dpe::{DpeInstance, U8Bool, MAX_HANDLES};
Expand All @@ -21,6 +25,8 @@ use crate::pcr_reset::PcrResetCounter;
pub const PCR_LOG_MAX_COUNT: usize = 17;
pub const FUSE_LOG_MAX_COUNT: usize = 62;
pub const MEASUREMENT_MAX_COUNT: usize = 8;
#[cfg(feature = "runtime")]
pub const AUTH_MANIFEST_IMAGE_METADATA_LIST_MAX_COUNT: usize = 8;

#[cfg(feature = "runtime")]
const DPE_DCCM_STORAGE: usize = size_of::<DpeInstance>()
Expand All @@ -34,6 +40,9 @@ const _: () = assert!(DPE_DCCM_STORAGE < memory_layout::DPE_SIZE as usize);
pub type PcrLogArray = [PcrLogEntry; PCR_LOG_MAX_COUNT];
pub type FuseLogArray = [FuseLogEntry; FUSE_LOG_MAX_COUNT];
pub type StashMeasurementArray = [MeasurementLogEntry; MEASUREMENT_MAX_COUNT];
#[cfg(feature = "runtime")]
pub type AuthManifestImageMetadataList =
[AuthManifestImageMetadata; AUTH_MANIFEST_IMAGE_METADATA_LIST_MAX_COUNT];

#[derive(FromBytes, AsBytes, Zeroize)]
#[repr(C)]
Expand Down Expand Up @@ -82,6 +91,16 @@ pub struct PersistentData {

#[cfg(not(feature = "runtime"))]
pcr_reset: [u8; memory_layout::PCR_RESET_COUNTER_SIZE as usize],

#[cfg(feature = "runtime")]
pub auth_manifest_image_metadata_col: AuthManifestImageMetadataCollection,
#[cfg(feature = "runtime")]
reserved9: [u8; memory_layout::AUTH_MAN_IMAGE_METADATA_LIST_MAX_SIZE as usize
- size_of::<AuthManifestImageMetadataCollection>()],

#[cfg(not(feature = "runtime"))]
pub auth_manifest_image_metadata_col:
[u8; memory_layout::AUTH_MAN_IMAGE_METADATA_LIST_MAX_SIZE as usize],
}
impl PersistentData {
pub fn assert_matches_layout() {
Expand All @@ -105,9 +124,14 @@ impl PersistentData {
addr_of!((*P).pcr_reset) as u32,
memory_layout::PCR_RESET_COUNTER_ORG
);
assert_eq!(
addr_of!((*P).auth_manifest_image_metadata_col) as u32,
memory_layout::AUTH_MAN_IMAGE_METADATA_LIST_ORG
);
assert_eq!(
P.add(1) as u32,
memory_layout::PCR_RESET_COUNTER_ORG + memory_layout::PCR_RESET_COUNTER_SIZE
memory_layout::AUTH_MAN_IMAGE_METADATA_LIST_ORG
+ memory_layout::AUTH_MAN_IMAGE_METADATA_LIST_MAX_SIZE
);
}
}
Expand Down
Loading
Loading