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

Add command to retrieve IDevID CSR from persistent storage. #1732

Merged
merged 1 commit into from
Nov 12, 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: 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
fc4ceed3891771c263c42eb56bdfff3026e1baf75e48b09bad58aaf562aea1a31f5df6636ac90f3aab73d533f03f0e5d caliptra-rom-no-log.bin
e6254e3492969108c1340b2f662d82ab72572f38fab970990c72bdb03f0bfbfd18f6a16a5f273df8fd0faf5aefe9c138 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;
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 = 0x50008800;
pub const IDEVID_CSR_ORG: u32 = 0x50008800;
pub const DATA_ORG: u32 = 0x50008C00;

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_MAX_SIZE: u32 = 7 * 1024;
pub const DATA_SIZE: u32 = 70 * 1024;
pub const IDEVID_CSR_SIZE: u32 = 1024;
pub const DATA_SIZE: u32 = 69 * 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
72 changes: 70 additions & 2 deletions drivers/src/persistent.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ use caliptra_auth_man_types::{
AuthManifestImageMetadata, AuthManifestImageMetadataCollection,
AUTH_MANIFEST_IMAGE_METADATA_MAX_COUNT,
};
use caliptra_error::{CaliptraError, CaliptraResult};
use caliptra_image_types::ImageManifest;
#[cfg(feature = "runtime")]
use dpe::{DpeInstance, U8Bool, MAX_HANDLES};
Expand All @@ -23,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 @@ -43,6 +45,65 @@ pub type StashMeasurementArray = [MeasurementLogEntry; MEASUREMENT_MAX_COUNT];
pub type AuthManifestImageMetadataList =
[AuthManifestImageMetadata; AUTH_MANIFEST_IMAGE_METADATA_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 @@ -100,7 +161,11 @@ pub struct PersistentData {
#[cfg(not(feature = "runtime"))]
pub auth_manifest_image_metadata_col:
[u8; memory_layout::AUTH_MAN_IMAGE_METADATA_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 @@ -127,10 +192,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_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 =
jhand2 marked this conversation as resolved.
Show resolved Hide resolved
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);
}
clundin25 marked this conversation as resolved.
Show resolved Hide resolved

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);
clundin25 marked this conversation as resolved.
Show resolved Hide resolved

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
Loading