From 9af061ec43f184f54bc276bcf8933e19f9ce11dd Mon Sep 17 00:00:00 2001 From: Jordan Hand Date: Fri, 25 Aug 2023 17:16:06 -0700 Subject: [PATCH] Add populate_chksum API for Mailbox requests Do the same thing as mailbox responses; add a MailboxReq enum which implements a populate_chksum API. This simplifies client code which needs to populate the checksum. --- api/Cargo.toml | 3 + api/src/mailbox.rs | 91 +++++++++++++++++++ common/Cargo.toml | 1 + runtime/Cargo.toml | 2 +- .../tests/runtime_integration_tests/ecdsa.rs | 15 +-- .../tests/runtime_integration_tests/hmac.rs | 19 ++-- .../integration_tests.rs | 77 ++++------------ 7 files changed, 123 insertions(+), 85 deletions(-) diff --git a/api/Cargo.toml b/api/Cargo.toml index f1d082579d..42f42f0927 100644 --- a/api/Cargo.toml +++ b/api/Cargo.toml @@ -11,3 +11,6 @@ edition = "2021" bitflags.workspace = true caliptra-error.workspace = true zerocopy.workspace = true + +[features] +test_only_commands = [] diff --git a/api/src/mailbox.rs b/api/src/mailbox.rs index c88e0f1017..a8a4babdb2 100644 --- a/api/src/mailbox.rs +++ b/api/src/mailbox.rs @@ -126,6 +126,97 @@ impl Default for MailboxResp { } } +#[cfg_attr(test, derive(PartialEq, Debug, Eq))] +#[allow(clippy::large_enum_variant)] +pub enum MailboxReq { + EcdsaVerify(EcdsaVerifyReq), + GetIdevCsr(MailboxReqHeader), + GetLdevCert(MailboxReqHeader), + StashMeasurement(StashMeasurementReq), + InvokeDpeCommand(InvokeDpeReq), + FipsVersion(MailboxReqHeader), + FwInfo(MailboxReqHeader), + + #[cfg(feature = "test_only_commands")] + TestHmacVerify(HmacVerifyReq), + #[cfg(feature = "test_only_commands")] + TestGetFmcAliasCert(MailboxReqHeader), +} + +impl MailboxReq { + pub fn as_bytes(&self) -> &[u8] { + match self { + MailboxReq::EcdsaVerify(req) => req.as_bytes(), + MailboxReq::StashMeasurement(req) => req.as_bytes(), + MailboxReq::InvokeDpeCommand(req) => req.as_bytes(), + MailboxReq::FipsVersion(req) => req.as_bytes(), + MailboxReq::FwInfo(req) => req.as_bytes(), + MailboxReq::GetIdevCsr(req) => req.as_bytes(), + MailboxReq::GetLdevCert(req) => req.as_bytes(), + + #[cfg(feature = "test_only_commands")] + MailboxReq::TestGetFmcAliasCert(req) => req.as_bytes(), + #[cfg(feature = "test_only_commands")] + MailboxReq::TestHmacVerify(req) => req.as_bytes(), + } + } + + pub fn as_bytes_mut(&mut self) -> &mut [u8] { + match self { + MailboxReq::EcdsaVerify(req) => req.as_bytes_mut(), + MailboxReq::GetIdevCsr(req) => req.as_bytes_mut(), + MailboxReq::GetLdevCert(req) => req.as_bytes_mut(), + MailboxReq::StashMeasurement(req) => req.as_bytes_mut(), + MailboxReq::InvokeDpeCommand(req) => req.as_bytes_mut(), + MailboxReq::FipsVersion(req) => req.as_bytes_mut(), + MailboxReq::FwInfo(req) => req.as_bytes_mut(), + + #[cfg(feature = "test_only_commands")] + MailboxReq::TestHmacVerify(req) => req.as_bytes_mut(), + #[cfg(feature = "test_only_commands")] + MailboxReq::TestGetFmcAliasCert(req) => req.as_bytes_mut(), + } + } + + pub fn cmd_code(&self) -> CommandId { + match self { + MailboxReq::EcdsaVerify(_) => CommandId::ECDSA384_VERIFY, + MailboxReq::GetIdevCsr(_) => CommandId::GET_IDEV_CSR, + MailboxReq::GetLdevCert(_) => CommandId::GET_LDEV_CERT, + MailboxReq::StashMeasurement(_) => CommandId::STASH_MEASUREMENT, + MailboxReq::InvokeDpeCommand(_) => CommandId::INVOKE_DPE, + MailboxReq::FipsVersion(_) => CommandId::VERSION, + MailboxReq::FwInfo(_) => CommandId::FW_INFO, + + #[cfg(feature = "test_only_commands")] + MailboxReq::TestHmacVerify(_) => CommandId::TEST_ONLY_HMAC384_VERIFY, + #[cfg(feature = "test_only_commands")] + MailboxReq::TestGetFmcAliasCert(_) => CommandId::TEST_ONLY_GET_FMC_ALIAS_CERT, + } + } + + /// Calculate and set the checksum for a request payload + pub fn populate_chksum(&mut self) -> CaliptraResult<()> { + // Calc checksum, use the size override if provided + let checksum = crate::checksum::calc_checksum( + self.cmd_code().into(), + &self.as_bytes()[size_of::()..], + ); + + // cast as header struct + let hdr: &mut MailboxReqHeader = LayoutVerified::<&mut [u8], MailboxReqHeader>::new( + &mut self.as_bytes_mut()[..size_of::()], + ) + .ok_or(CaliptraError::RUNTIME_INSUFFICIENT_MEMORY)? + .into_mut(); + + // Set the chksum field + hdr.chksum = checksum; + + Ok(()) + } +} + // HEADER #[repr(C)] #[derive(Default, Debug, AsBytes, FromBytes, PartialEq, Eq)] diff --git a/common/Cargo.toml b/common/Cargo.toml index 475d8593bd..572d409850 100644 --- a/common/Cargo.toml +++ b/common/Cargo.toml @@ -22,3 +22,4 @@ zerocopy.workspace = true default = ["std"] emu = ["caliptra-drivers/emu"] std = [] +test_only_commands = ["caliptra-api/test_only_commands"] diff --git a/runtime/Cargo.toml b/runtime/Cargo.toml index 1da3198ef4..f5804c4d1b 100644 --- a/runtime/Cargo.toml +++ b/runtime/Cargo.toml @@ -46,7 +46,7 @@ emu = ["caliptra_common/emu", "caliptra-drivers/emu"] itrng = ["caliptra-hw-model/itrng"] riscv = ["caliptra-cpu/riscv"] std = ["ufmt/std", "caliptra_common/std"] -test_only_commands = [] +test_only_commands = ["caliptra_common/test_only_commands"] slow_tests = [] verilator = ["caliptra-hw-model/verilator"] fips_self_test=[] diff --git a/runtime/tests/runtime_integration_tests/ecdsa.rs b/runtime/tests/runtime_integration_tests/ecdsa.rs index 66eef7366e..0d8b909357 100644 --- a/runtime/tests/runtime_integration_tests/ecdsa.rs +++ b/runtime/tests/runtime_integration_tests/ecdsa.rs @@ -2,7 +2,7 @@ use crate::common::run_rt_test; use caliptra_common::mailbox_api::{ - CommandId, EcdsaVerifyReq, MailboxReqHeader, MailboxRespHeader, + CommandId, EcdsaVerifyReq, MailboxReq, MailboxReqHeader, MailboxRespHeader, }; use caliptra_hw_model::{HwModel, ShaAccMode}; use caliptra_runtime::RtBootStatus; @@ -81,7 +81,7 @@ fn ecdsa_cmd_run_wycheproof() { .compute_sha512_acc_digest(test.msg.as_slice(), ShaAccMode::Sha384Stream) .unwrap(); - let cmd = EcdsaVerifyReq { + let mut cmd = MailboxReq::EcdsaVerify(EcdsaVerifyReq { hdr: MailboxReqHeader { chksum: 0 }, pub_key_x: test_group.key.affine_x.as_slice()[..].try_into().unwrap(), pub_key_y: test_group.key.affine_y.as_slice()[..].try_into().unwrap(), @@ -100,15 +100,8 @@ fn ecdsa_cmd_run_wycheproof() { .try_into() .unwrap(), // Do tests on mailbox - }; - let checksum = caliptra_common::checksum::calc_checksum( - u32::from(CommandId::ECDSA384_VERIFY), - &cmd.as_bytes()[4..], - ); - let cmd = EcdsaVerifyReq { - hdr: MailboxReqHeader { chksum: checksum }, - ..cmd - }; + }); + cmd.populate_chksum().unwrap(); let resp = model.mailbox_execute(u32::from(CommandId::ECDSA384_VERIFY), cmd.as_bytes()); match test.result { wycheproof::TestResult::Valid | wycheproof::TestResult::Acceptable => match resp { diff --git a/runtime/tests/runtime_integration_tests/hmac.rs b/runtime/tests/runtime_integration_tests/hmac.rs index 95d824cf05..4bfdefff95 100644 --- a/runtime/tests/runtime_integration_tests/hmac.rs +++ b/runtime/tests/runtime_integration_tests/hmac.rs @@ -1,9 +1,11 @@ // Licensed under the Apache-2.0 license. use crate::common::run_rt_test; -use caliptra_common::mailbox_api::{CommandId, HmacVerifyReq, MailboxReqHeader, MailboxRespHeader}; +use caliptra_common::mailbox_api::{ + CommandId, HmacVerifyReq, MailboxReq, MailboxReqHeader, MailboxRespHeader, +}; use caliptra_hw_model::HwModel; -use zerocopy::{AsBytes, FromBytes}; +use zerocopy::FromBytes; #[test] fn hmac_cmd_run_wycheproof() { @@ -37,21 +39,14 @@ fn hmac_cmd_run_wycheproof() { }); let mut msg = [0; 256]; msg[..test.msg.len()].copy_from_slice(test.msg.as_slice()); - let cmd = HmacVerifyReq { + let mut cmd = MailboxReq::TestHmacVerify(HmacVerifyReq { hdr: MailboxReqHeader { chksum: 0 }, key: test.key[..].try_into().unwrap(), tag: test.tag[..].try_into().unwrap(), len: test.msg.len().try_into().unwrap(), msg, - }; - let checksum = caliptra_common::checksum::calc_checksum( - u32::from(CommandId::TEST_ONLY_HMAC384_VERIFY), - &cmd.as_bytes()[4..], - ); - let cmd = HmacVerifyReq { - hdr: MailboxReqHeader { chksum: checksum }, - ..cmd - }; + }); + cmd.populate_chksum().unwrap(); let resp = model.mailbox_execute( u32::from(CommandId::TEST_ONLY_HMAC384_VERIFY), cmd.as_bytes(), diff --git a/runtime/tests/runtime_integration_tests/integration_tests.rs b/runtime/tests/runtime_integration_tests/integration_tests.rs index 6a30a10368..cb9d7b907a 100644 --- a/runtime/tests/runtime_integration_tests/integration_tests.rs +++ b/runtime/tests/runtime_integration_tests/integration_tests.rs @@ -7,7 +7,7 @@ use caliptra_builder::{ }; use caliptra_common::mailbox_api::{ CommandId, EcdsaVerifyReq, FipsVersionResp, FwInfoResp, GetIdevCertReq, GetIdevCertResp, - GetIdevInfoResp, InvokeDpeReq, InvokeDpeResp, MailboxReqHeader, MailboxRespHeader, + GetIdevInfoResp, InvokeDpeReq, InvokeDpeResp, MailboxReq, MailboxReqHeader, MailboxRespHeader, PopulateIdevCertReq, StashMeasurementReq, StashMeasurementResp, }; use caliptra_drivers::{CaliptraError, Ecc384PubKey}; @@ -319,23 +319,14 @@ fn test_stash_measurement() { m.soc_ifc().cptra_boot_status().read() == u32::from(RtBootStatus::RtReadyForCommands) }); - let cmd = StashMeasurementReq { + let mut cmd = MailboxReq::StashMeasurement(StashMeasurementReq { hdr: MailboxReqHeader { chksum: 0 }, metadata: [0u8; 4], measurement: [0u8; 48], context: [0u8; 48], svn: 0, - }; - - let checksum = caliptra_common::checksum::calc_checksum( - u32::from(CommandId::STASH_MEASUREMENT), - &cmd.as_bytes()[4..], - ); - - let cmd = StashMeasurementReq { - hdr: MailboxReqHeader { chksum: checksum }, - ..cmd - }; + }); + cmd.populate_chksum().unwrap(); let resp = model .mailbox_execute(u32::from(CommandId::STASH_MEASUREMENT), cmd.as_bytes()) @@ -400,20 +391,11 @@ fn test_invoke_dpe_get_profile_cmd() { assert_eq!(profile.flags, DPE_SUPPORT.bits()); // Test with data_size too big. - let cmd = InvokeDpeReq { + let mut cmd = MailboxReq::InvokeDpeCommand(InvokeDpeReq { data_size: InvokeDpeReq::DATA_MAX_SIZE as u32 + 1, ..cmd - }; - - let checksum = caliptra_common::checksum::calc_checksum( - u32::from(CommandId::INVOKE_DPE), - &cmd.as_bytes()[4..], - ); - - let cmd = InvokeDpeReq { - hdr: MailboxReqHeader { chksum: checksum }, - ..cmd - }; + }); + cmd.populate_chksum().unwrap(); // Make sure the command execution fails. let resp = model @@ -449,21 +431,12 @@ fn test_invoke_dpe_get_certificate_chain_cmd() { data[..cmd_hdr_buf.len()].copy_from_slice(cmd_hdr_buf); let dpe_cmd_buf = get_cert_chain_cmd.as_bytes(); data[cmd_hdr_buf.len()..cmd_hdr_buf.len() + dpe_cmd_buf.len()].copy_from_slice(dpe_cmd_buf); - let cmd = InvokeDpeReq { + let mut cmd = MailboxReq::InvokeDpeCommand(InvokeDpeReq { hdr: MailboxReqHeader { chksum: 0 }, data, data_size: (cmd_hdr_buf.len() + dpe_cmd_buf.len()) as u32, - }; - - let checksum = caliptra_common::checksum::calc_checksum( - u32::from(CommandId::INVOKE_DPE), - &cmd.as_bytes()[4..], - ); - - let cmd = InvokeDpeReq { - hdr: MailboxReqHeader { chksum: checksum }, - ..cmd - }; + }); + cmd.populate_chksum().unwrap(); let resp = model .mailbox_execute(u32::from(CommandId::INVOKE_DPE), cmd.as_bytes()) @@ -498,21 +471,12 @@ fn get_full_cert_chain(model: &mut DefaultHwModel, out: &mut [u8; 4096]) -> usiz data[..cmd_hdr_buf.len()].copy_from_slice(cmd_hdr_buf); let dpe_cmd_buf = get_cert_chain_cmd.as_bytes(); data[cmd_hdr_buf.len()..cmd_hdr_buf.len() + dpe_cmd_buf.len()].copy_from_slice(dpe_cmd_buf); - let cmd = InvokeDpeReq { + let mut cmd = MailboxReq::InvokeDpeCommand(InvokeDpeReq { hdr: MailboxReqHeader { chksum: 0 }, data, data_size: (cmd_hdr_buf.len() + dpe_cmd_buf.len()) as u32, - }; - - let checksum = caliptra_common::checksum::calc_checksum( - u32::from(CommandId::INVOKE_DPE), - &cmd.as_bytes()[4..], - ); - - let cmd = InvokeDpeReq { - hdr: MailboxReqHeader { chksum: checksum }, - ..cmd - }; + }); + cmd.populate_chksum().unwrap(); let resp = model .mailbox_execute(u32::from(CommandId::INVOKE_DPE), cmd.as_bytes()) @@ -538,21 +502,12 @@ fn get_full_cert_chain(model: &mut DefaultHwModel, out: &mut [u8; 4096]) -> usiz data[..cmd_hdr_buf.len()].copy_from_slice(cmd_hdr_buf); let dpe_cmd_buf = get_cert_chain_cmd.as_bytes(); data[cmd_hdr_buf.len()..cmd_hdr_buf.len() + dpe_cmd_buf.len()].copy_from_slice(dpe_cmd_buf); - let cmd = InvokeDpeReq { + let mut cmd = MailboxReq::InvokeDpeCommand(InvokeDpeReq { hdr: MailboxReqHeader { chksum: 0 }, data, data_size: (cmd_hdr_buf.len() + dpe_cmd_buf.len()) as u32, - }; - - let checksum = caliptra_common::checksum::calc_checksum( - u32::from(CommandId::INVOKE_DPE), - &cmd.as_bytes()[4..], - ); - - let cmd = InvokeDpeReq { - hdr: MailboxReqHeader { chksum: checksum }, - ..cmd - }; + }); + cmd.populate_chksum().unwrap(); let resp = model .mailbox_execute(u32::from(CommandId::INVOKE_DPE), cmd.as_bytes())