Skip to content

Commit

Permalink
Adding command to get owner pub key hash received with image bundle
Browse files Browse the repository at this point in the history
  • Loading branch information
nquarton committed Dec 10, 2024
1 parent 2f8f19b commit ac23241
Show file tree
Hide file tree
Showing 11 changed files with 170 additions and 0 deletions.
40 changes: 40 additions & 0 deletions api/src/mailbox.rs
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,9 @@ impl CommandId {

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

// The get Owner Pub Key Hash command.
pub const GET_OWNER_PUB_KEY_HASH: Self = Self(0x4F50_5542); // "OPUB"
}

impl From<u32> for CommandId {
Expand Down Expand Up @@ -155,6 +158,7 @@ pub enum MailboxResp {
CertifyKeyExtended(CertifyKeyExtendedResp),
AuthorizeAndStash(AuthorizeAndStashResp),
GetIdevCsr(GetIdevCsrResp),
GetOwnerPubKeyHash(GetOwnerPubKeyHashResp),
}

impl MailboxResp {
Expand All @@ -176,6 +180,7 @@ impl MailboxResp {
MailboxResp::CertifyKeyExtended(resp) => Ok(resp.as_bytes()),
MailboxResp::AuthorizeAndStash(resp) => Ok(resp.as_bytes()),
MailboxResp::GetIdevCsr(resp) => Ok(resp.as_bytes()),
MailboxResp::GetOwnerPubKeyHash(resp) => Ok(resp.as_bytes()),
}
}

Expand All @@ -197,6 +202,7 @@ impl MailboxResp {
MailboxResp::CertifyKeyExtended(resp) => Ok(resp.as_bytes_mut()),
MailboxResp::AuthorizeAndStash(resp) => Ok(resp.as_bytes_mut()),
MailboxResp::GetIdevCsr(resp) => Ok(resp.as_bytes_mut()),
MailboxResp::GetOwnerPubKeyHash(resp) => Ok(resp.as_bytes_mut()),
}
}

Expand Down Expand Up @@ -257,6 +263,7 @@ pub enum MailboxReq {
CertifyKeyExtended(CertifyKeyExtendedReq),
SetAuthManifest(SetAuthManifestReq),
AuthorizeAndStash(AuthorizeAndStashReq),
GetOwnerPubKeyHash(GetOwnerPubKeyHashReq),
}

impl MailboxReq {
Expand All @@ -282,6 +289,7 @@ impl MailboxReq {
MailboxReq::CertifyKeyExtended(req) => Ok(req.as_bytes()),
MailboxReq::SetAuthManifest(req) => Ok(req.as_bytes()),
MailboxReq::AuthorizeAndStash(req) => Ok(req.as_bytes()),
MailboxReq::GetOwnerPubKeyHash(req) => Ok(req.as_bytes()),
}
}

Expand All @@ -307,6 +315,7 @@ impl MailboxReq {
MailboxReq::CertifyKeyExtended(req) => Ok(req.as_bytes_mut()),
MailboxReq::SetAuthManifest(req) => Ok(req.as_bytes_mut()),
MailboxReq::AuthorizeAndStash(req) => Ok(req.as_bytes_mut()),
MailboxReq::GetOwnerPubKeyHash(req) => Ok(req.as_bytes_mut()),
}
}

Expand All @@ -332,6 +341,7 @@ impl MailboxReq {
MailboxReq::CertifyKeyExtended(_) => CommandId::CERTIFY_KEY_EXTENDED,
MailboxReq::SetAuthManifest(_) => CommandId::SET_AUTH_MANIFEST,
MailboxReq::AuthorizeAndStash(_) => CommandId::AUTHORIZE_AND_STASH,
MailboxReq::GetOwnerPubKeyHash(_) => CommandId::GET_OWNER_PUB_KEY_HASH,
}
}

Expand Down Expand Up @@ -1092,6 +1102,36 @@ pub struct AuthorizeAndStashResp {
}
impl Response for AuthorizeAndStashResp {}

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

impl Request for GetOwnerPubKeyHashReq {
const ID: CommandId = CommandId::GET_OWNER_PUB_KEY_HASH;
type Resp = GetOwnerPubKeyHashResp;
}

#[repr(C)]
#[derive(Debug, AsBytes, FromBytes, PartialEq, Eq)]
pub struct GetOwnerPubKeyHashResp {
pub hdr: MailboxRespHeader,
pub key_hash: [u8; 48],
}

impl ResponseVarSize for GetOwnerPubKeyHashResp {}

impl Default for GetOwnerPubKeyHashResp {
fn default() -> Self {
Self {
hdr: MailboxRespHeader::default(),
key_hash: [0u8; 48],
}
}
}

/// Retrieves dlen bytes from the mailbox.
pub fn mbox_read_response(
mbox: mbox::RegisterBlock<impl MmioMut>,
Expand Down
12 changes: 12 additions & 0 deletions libcaliptra/examples/generic/test.c
Original file line number Diff line number Diff line change
Expand Up @@ -550,6 +550,18 @@ int rt_test_all_commands(const test_info* info)
printf("Certify Key Extended: OK\n");
}

// GET OWNER PUB KEY HASH
struct caliptra_get_owner_pub_key_hash_resp pub_key_hash_resp;

status = caliptra_get_owner_pub_key_hash(&pub_key_hash_resp, false);

if (status) {
printf("Get Owner Pub Key Hash failed: 0x%x\n", status);
dump_caliptra_error_codes();
failure = 1;
} else {
printf("Get Owner Pub Key Hash: OK\n");
}

// FIPS_VERSION
struct caliptra_fips_version_resp version_resp;
Expand Down
3 changes: 3 additions & 0 deletions libcaliptra/inc/caliptra_api.h
Original file line number Diff line number Diff line change
Expand Up @@ -183,6 +183,9 @@ int caliptra_fips_version(struct caliptra_fips_version_resp *resp, bool async);
// Get IDev CSR
int caliptra_get_idev_csr(struct caliptra_get_idev_csr_resp *resp, bool async);

// Get Owner Public Keys Hash
int caliptra_get_owner_pub_key_hash(struct caliptra_get_owner_pub_key_hash_resp *resp, bool async);

// Self test start
int caliptra_self_test_start(bool async);

Expand Down
5 changes: 5 additions & 0 deletions libcaliptra/inc/caliptra_types.h
Original file line number Diff line number Diff line change
Expand Up @@ -224,6 +224,11 @@ struct caliptra_get_idev_csr_resp {
uint8_t data[512];
};

struct caliptra_get_owner_pub_key_hash_resp {
struct caliptra_resp_header hdr;
uint8_t key_hash[48];
};

// DPE commands

#define DPE_MAGIC 0x44504543 // "DPEC"
Expand Down
15 changes: 15 additions & 0 deletions libcaliptra/src/caliptra_api.c
Original file line number Diff line number Diff line change
Expand Up @@ -1185,6 +1185,21 @@ int caliptra_get_idev_csr(struct caliptra_get_idev_csr_resp *resp, bool async)
return pack_and_execute_command(&p, async);
}

// Get owner public keys hash
int caliptra_get_owner_pub_key_hash(struct caliptra_get_owner_pub_key_hash_resp *resp, bool async)
{
if (!resp)
{
return INVALID_PARAMS;
}

caliptra_checksum checksum = 0;

CREATE_PARCEL(p, OP_GET_OWNER_PUB_KEY_HASH, &checksum, resp);

return pack_and_execute_command(&p, async);
}

// Self test start
int caliptra_self_test_start(bool async)
{
Expand Down
1 change: 1 addition & 0 deletions libcaliptra/src/caliptra_mbox.h
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,7 @@ enum mailbox_command {
OP_SHUTDOWN = 0x46505344, // "FPSD"
OP_CAPABILITIES = 0x43415053, // "CAPS"
OP_GET_IDEV_CSR = 0x49444352, // "IDCR"
OP_GET_OWNER_PUB_KEY_HASH = 0x4F505542, // "OPUB"
};

struct parcel {
Expand Down
20 changes: 20 additions & 0 deletions runtime/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -806,6 +806,7 @@ Command Code: `0x4944_4352` ("IDCR")
| **Name** | **Type** | **Description**
| -------- | -------- | ---------------
| 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.
| data\_size | u32 | Length in bytes of the valid data in the data field. |
| data | u8[...] | DER-encoded IDevID certificate signing request. |

Expand All @@ -819,6 +820,25 @@ When called from runtime, if the CSR was not previously provisioned this command

When the `mfg_flag_gen_idev_id_csr` flag has been set, the SoC **MUST** wait for the `flow_status_set_idevid_csr_ready` bit to be set by Caliptra. Once set, the SoC **MUST** clear the `mfg_flag_gen_idev_id_csr` flag for Caliptra to progress.

### GET\_OWNER\_PUB\_KEY\_HASH

Retreives the sha384 hash of the owner public keys provided in the image bundle manifest.

Command Code: `0x4F50_5542` ("OPUB")

*Table: `GET_OWNER_PUB_KEY_HASH` input arguments*

| **Name** | **Type** | **Description**
| -------- | -------- | ---------------
| chksum | u32 | Checksum over other input arguments, computed by the caller. Little endian. |

*Table: `GET_OWNER_PUB_KEY_HASH` output arguments*
| **Name** | **Type** | **Description**
| -------- | -------- | ---------------
| 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. |
| key\_hash | u8[48] | Hash of the owner public keys provided in the image bundle manifest |

## Checksum

For every command except for FW_LOAD, the request and response feature a checksum. This
Expand Down
33 changes: 33 additions & 0 deletions runtime/src/get_owner_pub_key_hash.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
// Licensed under the Apache-2.0 license

use crate::Drivers;

use caliptra_cfi_derive_git::cfi_impl_fn;
use caliptra_cfi_lib_git::cfi_launder;

use caliptra_common::{
cprintln,
mailbox_api::{GetOwnerPubKeyHashReq, GetOwnerPubKeyHashResp, MailboxResp, MailboxRespHeader},
};
use caliptra_error::{CaliptraError, CaliptraResult};

use zerocopy::{AsBytes, FromBytes};

pub struct GetOwnerPubKeyHashCmd;
impl GetOwnerPubKeyHashCmd {
#[cfg_attr(not(feature = "no-cfi"), cfi_impl_fn)]
#[inline(never)]
pub(crate) fn execute(drivers: &mut Drivers, cmd_args: &[u8]) -> CaliptraResult<MailboxResp> {
if let Some(cmd) = GetOwnerPubKeyHashReq::read_from(cmd_args) {
let mut resp = GetOwnerPubKeyHashResp::default();

// Copy the pub key hash from the last cold boot from the data vault
resp.key_hash
.copy_from_slice(drivers.data_vault.owner_pk_hash().as_bytes());

Ok(MailboxResp::GetOwnerPubKeyHash(resp))
} else {
Err(CaliptraError::RUNTIME_INSUFFICIENT_MEMORY)
}
}
}
3 changes: 3 additions & 0 deletions runtime/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ mod dpe_platform;
mod drivers;
pub mod fips;
mod get_idev_csr;
mod get_owner_pub_key_hash;
pub mod handoff;
mod hmac;
pub mod info;
Expand All @@ -41,6 +42,7 @@ use authorize_and_stash::AuthorizeAndStashCmd;
use caliptra_cfi_lib_git::{cfi_assert, cfi_assert_eq, cfi_assert_ne, cfi_launder, CfiCounter};
use caliptra_registers::soc_ifc::SocIfcReg;
pub use drivers::{Drivers, PauserPrivileges};
use get_owner_pub_key_hash::GetOwnerPubKeyHashCmd;
use mailbox::Mailbox;

use crate::capabilities::CapabilitiesCmd;
Expand Down Expand Up @@ -229,6 +231,7 @@ fn handle_command(drivers: &mut Drivers) -> CaliptraResult<MboxStatusE> {
CommandId::SET_AUTH_MANIFEST => SetAuthManifestCmd::execute(drivers, cmd_bytes),
CommandId::AUTHORIZE_AND_STASH => AuthorizeAndStashCmd::execute(drivers, cmd_bytes),
CommandId::GET_IDEV_CSR => GetIdevCsrCmd::execute(drivers, cmd_bytes),
CommandId::GET_OWNER_PUB_KEY_HASH => GetOwnerPubKeyHashCmd::execute(drivers, cmd_bytes),
_ => Err(CaliptraError::RUNTIME_UNIMPLEMENTED_COMMAND),
}?;

Expand Down
1 change: 1 addition & 0 deletions runtime/tests/runtime_integration_tests/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ mod test_disable;
mod test_ecdsa;
mod test_fips;
mod test_get_idev_csr;
mod test_get_owner_pub_key_hash;
mod test_info;
mod test_invoke_dpe;
mod test_lms;
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
// Licensed under the Apache-2.0 license

use caliptra_api::mailbox::GetOwnerPubKeyHashResp;
use caliptra_common::mailbox_api::{CommandId, MailboxReqHeader};
use caliptra_hw_model::HwModel;
use zerocopy::{AsBytes, FromBytes};

use crate::common::{run_rt_test, RuntimeTestArgs};

#[test]
fn test_get_owner_pub_key_hash() {
let mut model = run_rt_test(RuntimeTestArgs::default());

let payload = MailboxReqHeader {
chksum: caliptra_common::checksum::calc_checksum(
u32::from(CommandId::GET_OWNER_PUB_KEY_HASH),
&[],
),
};

let result =
model.mailbox_execute(CommandId::GET_OWNER_PUB_KEY_HASH.into(), payload.as_bytes());

let response = result.unwrap().unwrap();

let get_owner_pub_key_hash_resp =
GetOwnerPubKeyHashResp::read_from(response.as_bytes()).unwrap();

// Check against our fake owner public key hash
let mut exp_pub_key_hash =
openssl::sha::sha384(caliptra_image_fake_keys::OWNER_PUBLIC_KEYS.as_bytes());
// FLip endianness by each dword for the hash
for dword in exp_pub_key_hash.chunks_exact_mut(4) {
dword.reverse();
}
assert_eq!(exp_pub_key_hash, get_owner_pub_key_hash_resp.key_hash);
}

0 comments on commit ac23241

Please sign in to comment.