From ac23241840cf02226d179b329ae68202c4f3ba28 Mon Sep 17 00:00:00 2001 From: Nick Quarton <139178705+nquarton@users.noreply.github.com> Date: Mon, 9 Dec 2024 16:50:56 -0800 Subject: [PATCH] Adding command to get owner pub key hash received with image bundle --- api/src/mailbox.rs | 40 +++++++++++++++++++ libcaliptra/examples/generic/test.c | 12 ++++++ libcaliptra/inc/caliptra_api.h | 3 ++ libcaliptra/inc/caliptra_types.h | 5 +++ libcaliptra/src/caliptra_api.c | 15 +++++++ libcaliptra/src/caliptra_mbox.h | 1 + runtime/README.md | 20 ++++++++++ runtime/src/get_owner_pub_key_hash.rs | 33 +++++++++++++++ runtime/src/lib.rs | 3 ++ .../tests/runtime_integration_tests/main.rs | 1 + .../test_get_owner_pub_key_hash.rs | 37 +++++++++++++++++ 11 files changed, 170 insertions(+) create mode 100644 runtime/src/get_owner_pub_key_hash.rs create mode 100644 runtime/tests/runtime_integration_tests/test_get_owner_pub_key_hash.rs diff --git a/api/src/mailbox.rs b/api/src/mailbox.rs index 9db5ff59f0..66707d7de8 100644 --- a/api/src/mailbox.rs +++ b/api/src/mailbox.rs @@ -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 for CommandId { @@ -155,6 +158,7 @@ pub enum MailboxResp { CertifyKeyExtended(CertifyKeyExtendedResp), AuthorizeAndStash(AuthorizeAndStashResp), GetIdevCsr(GetIdevCsrResp), + GetOwnerPubKeyHash(GetOwnerPubKeyHashResp), } impl MailboxResp { @@ -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()), } } @@ -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()), } } @@ -257,6 +263,7 @@ pub enum MailboxReq { CertifyKeyExtended(CertifyKeyExtendedReq), SetAuthManifest(SetAuthManifestReq), AuthorizeAndStash(AuthorizeAndStashReq), + GetOwnerPubKeyHash(GetOwnerPubKeyHashReq), } impl MailboxReq { @@ -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()), } } @@ -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()), } } @@ -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, } } @@ -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, diff --git a/libcaliptra/examples/generic/test.c b/libcaliptra/examples/generic/test.c index bdd421e7e2..e12fd85076 100644 --- a/libcaliptra/examples/generic/test.c +++ b/libcaliptra/examples/generic/test.c @@ -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; diff --git a/libcaliptra/inc/caliptra_api.h b/libcaliptra/inc/caliptra_api.h index 8992dad882..8e19a70ed4 100644 --- a/libcaliptra/inc/caliptra_api.h +++ b/libcaliptra/inc/caliptra_api.h @@ -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); diff --git a/libcaliptra/inc/caliptra_types.h b/libcaliptra/inc/caliptra_types.h index 9058f50bd7..3941af2014 100644 --- a/libcaliptra/inc/caliptra_types.h +++ b/libcaliptra/inc/caliptra_types.h @@ -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" diff --git a/libcaliptra/src/caliptra_api.c b/libcaliptra/src/caliptra_api.c index cf8d4b9924..e91a0f401c 100644 --- a/libcaliptra/src/caliptra_api.c +++ b/libcaliptra/src/caliptra_api.c @@ -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) { diff --git a/libcaliptra/src/caliptra_mbox.h b/libcaliptra/src/caliptra_mbox.h index 2b5d77b5df..79e91bff07 100644 --- a/libcaliptra/src/caliptra_mbox.h +++ b/libcaliptra/src/caliptra_mbox.h @@ -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 { diff --git a/runtime/README.md b/runtime/README.md index 5a1e74e964..b22a6ff2f5 100644 --- a/runtime/README.md +++ b/runtime/README.md @@ -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. | @@ -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 diff --git a/runtime/src/get_owner_pub_key_hash.rs b/runtime/src/get_owner_pub_key_hash.rs new file mode 100644 index 0000000000..a215aa3e06 --- /dev/null +++ b/runtime/src/get_owner_pub_key_hash.rs @@ -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 { + 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) + } + } +} diff --git a/runtime/src/lib.rs b/runtime/src/lib.rs index 2e4fe0b862..4ea2e424ae 100644 --- a/runtime/src/lib.rs +++ b/runtime/src/lib.rs @@ -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; @@ -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; @@ -229,6 +231,7 @@ fn handle_command(drivers: &mut Drivers) -> CaliptraResult { 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), }?; diff --git a/runtime/tests/runtime_integration_tests/main.rs b/runtime/tests/runtime_integration_tests/main.rs index 417946cda3..dbd4645fa2 100644 --- a/runtime/tests/runtime_integration_tests/main.rs +++ b/runtime/tests/runtime_integration_tests/main.rs @@ -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; diff --git a/runtime/tests/runtime_integration_tests/test_get_owner_pub_key_hash.rs b/runtime/tests/runtime_integration_tests/test_get_owner_pub_key_hash.rs new file mode 100644 index 0000000000..b3ff761c3d --- /dev/null +++ b/runtime/tests/runtime_integration_tests/test_get_owner_pub_key_hash.rs @@ -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); +}