Skip to content

Commit

Permalink
Add populate_chksum API for Mailbox requests
Browse files Browse the repository at this point in the history
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.
  • Loading branch information
jhand2 committed Nov 14, 2023
1 parent edeb9e2 commit 9af061e
Show file tree
Hide file tree
Showing 7 changed files with 123 additions and 85 deletions.
3 changes: 3 additions & 0 deletions api/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -11,3 +11,6 @@ edition = "2021"
bitflags.workspace = true
caliptra-error.workspace = true
zerocopy.workspace = true

[features]
test_only_commands = []
91 changes: 91 additions & 0 deletions api/src/mailbox.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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::<i32>()..],
);

// cast as header struct
let hdr: &mut MailboxReqHeader = LayoutVerified::<&mut [u8], MailboxReqHeader>::new(
&mut self.as_bytes_mut()[..size_of::<MailboxReqHeader>()],
)
.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)]
Expand Down
1 change: 1 addition & 0 deletions common/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -22,3 +22,4 @@ zerocopy.workspace = true
default = ["std"]
emu = ["caliptra-drivers/emu"]
std = []
test_only_commands = ["caliptra-api/test_only_commands"]
2 changes: 1 addition & 1 deletion runtime/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -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=[]
Expand Down
15 changes: 4 additions & 11 deletions runtime/tests/runtime_integration_tests/ecdsa.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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(),
Expand All @@ -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 {
Expand Down
19 changes: 7 additions & 12 deletions runtime/tests/runtime_integration_tests/hmac.rs
Original file line number Diff line number Diff line change
@@ -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() {
Expand Down Expand Up @@ -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(),
Expand Down
77 changes: 16 additions & 61 deletions runtime/tests/runtime_integration_tests/integration_tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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};
Expand Down Expand Up @@ -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())
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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())
Expand Down Expand Up @@ -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())
Expand All @@ -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())
Expand Down

0 comments on commit 9af061e

Please sign in to comment.