Skip to content

Commit

Permalink
Add command to retrieve IDevID CSR from persistent storage.
Browse files Browse the repository at this point in the history
* This resolves
  #1687, for ROM.
  • Loading branch information
clundin25 committed Nov 8, 2024
1 parent b914976 commit 07bf939
Show file tree
Hide file tree
Showing 19 changed files with 432 additions and 44 deletions.
4 changes: 2 additions & 2 deletions FROZEN_IMAGES.sha384sum
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
# WARNING: Do not update this file without the approval of the Caliptra TAC
ad1064cba5b190e4f5258c175b7ec7c697ccb188ba0ed18302c6e924f0ea0b10457dc753d6d2963f415fbaf761eace96 caliptra-rom-no-log.bin
2aae08cbe6e13559201fee432a7bbf535d27d94df4e8b4d05adab11c4f27b57c6d8392b71a24ee459af7b9663ce9c31f caliptra-rom-with-log.bin
39297297d917e76c678f0e3ecc67b1585269aa47b41efcd081f5d07c40c1379201e1e287a11321a7ad4e437c741d87b9 caliptra-rom-no-log.bin
bfc1ba46d404bff6496ed9aa04183b89a2e589ff928baf21b882d25e9961f2daccfab7b215c29bdccfd58bd4ae88e79d caliptra-rom-with-log.bin
41 changes: 41 additions & 0 deletions api/src/mailbox.rs
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,9 @@ impl CommandId {

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

// The get IDevID CSR command.
pub const GET_IDEV_CSR: Self = Self(0x4944_4352); // "IDCR"
}

impl From<u32> for CommandId {
Expand Down Expand Up @@ -151,6 +154,7 @@ pub enum MailboxResp {
QuotePcrs(QuotePcrsResp),
CertifyKeyExtended(CertifyKeyExtendedResp),
AuthorizeAndStash(AuthorizeAndStashResp),
GetIdevIdCsr(GetIdevIdCsrResp),
}

impl MailboxResp {
Expand All @@ -171,6 +175,7 @@ impl MailboxResp {
MailboxResp::QuotePcrs(resp) => Ok(resp.as_bytes()),
MailboxResp::CertifyKeyExtended(resp) => Ok(resp.as_bytes()),
MailboxResp::AuthorizeAndStash(resp) => Ok(resp.as_bytes()),
MailboxResp::GetIdevIdCsr(resp) => Ok(resp.as_bytes()),
}
}

Expand All @@ -191,6 +196,7 @@ impl MailboxResp {
MailboxResp::QuotePcrs(resp) => Ok(resp.as_bytes_mut()),
MailboxResp::CertifyKeyExtended(resp) => Ok(resp.as_bytes_mut()),
MailboxResp::AuthorizeAndStash(resp) => Ok(resp.as_bytes_mut()),
MailboxResp::GetIdevIdCsr(resp) => Ok(resp.as_bytes_mut()),
}
}

Expand Down Expand Up @@ -458,6 +464,7 @@ pub struct GetIdevInfoResp {
pub struct GetLdevCertReq {
header: MailboxReqHeader,
}

impl Request for GetLdevCertReq {
const ID: CommandId = CommandId::GET_LDEV_CERT;
type Resp = GetLdevCertResp;
Expand Down Expand Up @@ -976,6 +983,40 @@ impl Default for SetAuthManifestReq {
}
}

// GET_IDEVID_CSR
#[repr(C)]
#[derive(Default, Debug, AsBytes, FromBytes, PartialEq, Eq)]
pub struct GetIdevIdCsrReq {
pub hdr: MailboxReqHeader,
}

impl Request for GetIdevIdCsrReq {
const ID: CommandId = CommandId::GET_IDEV_CSR;
type Resp = GetIdevIdCsrResp;
}

#[repr(C)]
#[derive(Debug, AsBytes, FromBytes, PartialEq, Eq)]
pub struct GetIdevIdCsrResp {
pub hdr: MailboxRespHeader,
pub data_size: u32,
pub data: [u8; Self::DATA_MAX_SIZE],
}
impl GetIdevIdCsrResp {
pub const DATA_MAX_SIZE: usize = 512;
}
impl ResponseVarSize for GetIdevIdCsrResp {}

impl Default for GetIdevIdCsrResp {
fn default() -> Self {
Self {
hdr: MailboxRespHeader::default(),
data_size: 0,
data: [0u8; Self::DATA_MAX_SIZE],
}
}
}

#[repr(u32)]
#[derive(Debug, PartialEq, Eq)]
pub enum ImageHashSource {
Expand Down
5 changes: 3 additions & 2 deletions drivers/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -89,8 +89,9 @@ 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,
FuseLogArray, IdevIdCsr, PcrLogArray, PersistentData, PersistentDataAccessor,
StashMeasurementArray, FUSE_LOG_MAX_COUNT, MAX_CSR_SIZE, MEASUREMENT_MAX_COUNT,
PCR_LOG_MAX_COUNT,
};
pub use pic::{IntSource, Pic};
pub use sha1::{Sha1, Sha1Digest, Sha1DigestOp};
Expand Down
12 changes: 10 additions & 2 deletions drivers/src/memory_layout.rs
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,8 @@ 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 IDEVID_CSR_ORG: u32 = 0x50007000;
pub const DATA_ORG: u32 = 0x50007400;

pub const STACK_ORG: u32 = 0x5001A000;
pub const ROM_STACK_ORG: u32 = 0x5001C000;
Expand Down Expand Up @@ -72,7 +73,8 @@ 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 IDEVID_CSR_SIZE: u32 = 1024;
pub const DATA_SIZE: u32 = 75 * 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 @@ -153,6 +155,12 @@ fn mem_layout_test_pcr_reset_counter() {
);
}

#[test]
#[allow(clippy::assertions_on_constants)]
fn mem_layout_test_idevid_csr() {
assert_eq!((DATA_ORG - IDEVID_CSR_ORG), IDEVID_CSR_SIZE);
}

#[test]
#[allow(clippy::assertions_on_constants)]
fn mem_layout_test_data() {
Expand Down
73 changes: 71 additions & 2 deletions drivers/src/persistent.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@ use core::{marker::PhantomData, mem::size_of, ptr::addr_of};
use caliptra_auth_man_types::AuthManifestImageMetadata;
#[cfg(feature = "runtime")]
use caliptra_auth_man_types::AuthManifestImageMetadataCollection;
use caliptra_error::CaliptraError;
use caliptra_error::CaliptraResult;
use caliptra_image_types::ImageManifest;
#[cfg(feature = "runtime")]
use dpe::{DpeInstance, U8Bool, MAX_HANDLES};
Expand All @@ -22,6 +24,7 @@ use crate::{
#[cfg(feature = "runtime")]
use crate::pcr_reset::PcrResetCounter;

pub const MAX_CSR_SIZE: usize = 512;
pub const PCR_LOG_MAX_COUNT: usize = 17;
pub const FUSE_LOG_MAX_COUNT: usize = 62;
pub const MEASUREMENT_MAX_COUNT: usize = 8;
Expand All @@ -44,6 +47,65 @@ pub type StashMeasurementArray = [MeasurementLogEntry; MEASUREMENT_MAX_COUNT];
pub type AuthManifestImageMetadataList =
[AuthManifestImageMetadata; AUTH_MANIFEST_IMAGE_METADATA_LIST_MAX_COUNT];

#[derive(Clone, FromBytes, AsBytes, Zeroize)]
#[repr(C)]
pub struct IdevIdCsr {
csr_len: u32,
csr: [u8; MAX_CSR_SIZE],
}

impl Default for IdevIdCsr {
fn default() -> Self {
Self {
csr_len: Self::UNPROVISIONED_CSR,
csr: [0; MAX_CSR_SIZE],
}
}
}

impl IdevIdCsr {
/// The `csr_len` field is set to this constant when a ROM image supports CSR generation but
/// the CSR generation flag was not enabled.
///
/// This is used by the runtime to distinguish ROM images that support CSR generation from
/// ones that do not.
///
/// u32::MAX is too large to be a valid CSR, so we use it to encode this state.
pub const UNPROVISIONED_CSR: u32 = u32::MAX;

/// Get the CSR buffer
pub fn get(&self) -> Option<&[u8]> {
self.csr.get(..self.csr_len as usize)
}

/// Create `Self` from a csr slice. `csr_len` MUST be the actual length of the csr.
pub fn new(csr_buf: &[u8], csr_len: usize) -> CaliptraResult<Self> {
if csr_len >= MAX_CSR_SIZE {
return Err(CaliptraError::ROM_IDEVID_INVALID_CSR);
}

let mut _self = Self {
csr_len: csr_len as u32,
csr: [0; MAX_CSR_SIZE],
};
_self.csr[..csr_len].copy_from_slice(&csr_buf[..csr_len]);

Ok(_self)
}

/// Get the length of the CSR in bytes.
pub fn get_csr_len(&self) -> u32 {
self.csr_len
}

/// Check if the CSR was unprovisioned
pub fn is_unprovisioned(&self) -> bool {
self.csr_len == Self::UNPROVISIONED_CSR
}
}

const _: () = assert!(size_of::<IdevIdCsr>() < memory_layout::IDEVID_CSR_SIZE as usize);

#[derive(FromBytes, AsBytes, Zeroize)]
#[repr(C)]
pub struct PersistentData {
Expand Down Expand Up @@ -101,7 +163,11 @@ pub struct PersistentData {
#[cfg(not(feature = "runtime"))]
pub auth_manifest_image_metadata_col:
[u8; memory_layout::AUTH_MAN_IMAGE_METADATA_LIST_MAX_SIZE as usize],

pub idevid_csr: IdevIdCsr,
reserved10: [u8; memory_layout::IDEVID_CSR_SIZE as usize - size_of::<IdevIdCsr>()],
}

impl PersistentData {
pub fn assert_matches_layout() {
const P: *const PersistentData = memory_layout::MAN1_ORG as *const PersistentData;
Expand All @@ -128,10 +194,13 @@ impl PersistentData {
addr_of!((*P).auth_manifest_image_metadata_col) as u32,
memory_layout::AUTH_MAN_IMAGE_METADATA_LIST_ORG
);
assert_eq!(
addr_of!((*P).idevid_csr) as u32,
memory_layout::IDEVID_CSR_ORG
);
assert_eq!(
P.add(1) as u32,
memory_layout::AUTH_MAN_IMAGE_METADATA_LIST_ORG
+ memory_layout::AUTH_MAN_IMAGE_METADATA_LIST_MAX_SIZE
memory_layout::IDEVID_CSR_ORG + memory_layout::IDEVID_CSR_SIZE
);
}
}
Expand Down
6 changes: 6 additions & 0 deletions error/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -443,6 +443,10 @@ impl CaliptraError {
pub const RUNTIME_CMD_RESERVED_PAUSER: CaliptraError = CaliptraError::new_const(0x000E004F);
pub const RUNTIME_AUTH_AND_STASH_MEASUREMENT_DPE_ERROR: CaliptraError =
CaliptraError::new_const(0x000E0050);
pub const RUNTIME_GET_IDEV_ID_UNPROVISIONED: CaliptraError =
CaliptraError::new_const(0x000E0051);
pub const RUNTIME_GET_IDEV_ID_UNSUPPORTED_ROM: CaliptraError =
CaliptraError::new_const(0x000E0052);

/// FMC Errors
pub const FMC_GLOBAL_NMI: CaliptraError = CaliptraError::new_const(0x000F0001);
Expand Down Expand Up @@ -499,6 +503,8 @@ impl CaliptraError {
pub const FW_PROC_MAILBOX_STASH_MEASUREMENT_MAX_LIMIT: CaliptraError =
CaliptraError::new_const(0x01020008);
pub const FW_PROC_MAILBOX_RESERVED_PAUSER: CaliptraError = CaliptraError::new_const(0x01020009);
pub const FW_PROC_MAILBOX_GET_IDEV_CSR_UNPROVISIONED_CSR: CaliptraError =
CaliptraError::new_const(0x0102000A);

/// FMC Alias Layer : Certificate Verification Failure.
pub const FMC_ALIAS_CERT_VERIFY: CaliptraError = CaliptraError::new_const(0x01030001);
Expand Down
9 changes: 9 additions & 0 deletions hw-model/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -585,6 +585,15 @@ pub trait HwModel: SocManager {
const MAX_WAIT_CYCLES: u32 = 20_000_000;
let mut cycles = 0;
while !self.ready_for_fw() {
// If GENERATE_IDEVID_CSR was set then we need to clear cptra_dbg_manuf_service_reg
// once the CSR is ready to continue making progress.
//
// Generally the CSR should be read from the mailbox at this point, but to
// accommodate test cases that ignore the CSR mailbox, we will ignore it here.
if self.soc_ifc().cptra_flow_status().read().idevid_csr_ready() {
self.soc_ifc().cptra_dbg_manuf_service_reg().write(|_| 0);
}

self.step();
cycles += 1;
if cycles > MAX_WAIT_CYCLES {
Expand Down
1 change: 1 addition & 0 deletions rom/dev/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -381,6 +381,7 @@ ROM supports the following set of commands before handling the FW_DOWNLOAD comma
4. **SELF_TEST_GET_RESULTS**: This command is used to check if a SELF_TEST command is in progress. [Self Test Get Results command](https://github.com/chipsalliance/caliptra-sw/blob/main/runtime/README.md#self_test_get_results).
5. **SHUTDOWN**: This command is used clear the hardware crypto blocks including the keyvault. [Shutdown command](https://github.com/chipsalliance/caliptra-sw/blob/main/runtime/README.md#shutdown).
6. **CAPABILITIES**: This command is used to query the ROM capabilities. Capabilities is a 128-bit value with individual bits indicating a specific capability. Currently, the only capability supported is ROM_BASE (bit 0). [Capabilities command](https://github.com/chipsalliance/caliptra-sw/blob/main/runtime/README.md#capabilities).
7. **GET_IDEVID_CSR**: This command is used to fetch the IDevID CSR from ROM. [Fetch IDevIDCSR command](https://github.com/chipsalliance/caliptra-sw/blob/main/runtime/README.md#get_idevid_csr).

### Downloading images from mailbox

Expand Down
27 changes: 26 additions & 1 deletion rom/dev/src/flow/cold_reset/fw_processor.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ use caliptra_cfi_lib::CfiCounter;
use caliptra_common::capabilities::Capabilities;
use caliptra_common::fips::FipsVersionCmd;
use caliptra_common::mailbox_api::{
CapabilitiesResp, CommandId, MailboxReqHeader, MailboxRespHeader, Response,
CapabilitiesResp, CommandId, GetIdevIdCsrResp, MailboxReqHeader, MailboxRespHeader, Response,
StashMeasurementReq, StashMeasurementResp,
};
use caliptra_common::pcr::PCR_ID_STASH_MEASUREMENT;
Expand Down Expand Up @@ -304,6 +304,31 @@ impl FirmwareProcessor {
resp.populate_chksum();
txn.send_response(resp.as_bytes())?;
}
CommandId::GET_IDEV_CSR => {
let mut request = MailboxReqHeader::default();
Self::copy_req_verify_chksum(&mut txn, request.as_bytes_mut())?;

let csr_persistent_mem = &persistent_data.idevid_csr;
let mut resp = GetIdevIdCsrResp::default();

if csr_persistent_mem.is_unprovisioned() {
// CSR was never written to DCCM. This means the gen_idev_id_csr
// manufacturing flag was not set before booting into ROM.
return Err(
CaliptraError::FW_PROC_MAILBOX_GET_IDEV_CSR_UNPROVISIONED_CSR,
);
}

let csr = csr_persistent_mem
.get()
.ok_or(CaliptraError::ROM_IDEVID_INVALID_CSR)?;

resp.data_size = csr_persistent_mem.get_csr_len();
resp.data[..resp.data_size as usize].copy_from_slice(csr);

resp.populate_chksum();
txn.send_response(resp.as_bytes())?;
}
_ => {
cprintln!("[fwproc] Invalid command received");
// Don't complete the transaction here; let the fatal
Expand Down
Loading

0 comments on commit 07bf939

Please sign in to comment.