Skip to content

Commit

Permalink
Update verifier to use SHA accelerator (#1986)
Browse files Browse the repository at this point in the history
  • Loading branch information
mtimkovich authored Feb 28, 2025
1 parent 615ccaa commit b4c8333
Show file tree
Hide file tree
Showing 11 changed files with 197 additions and 81 deletions.
1 change: 1 addition & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

45 changes: 45 additions & 0 deletions common/src/verifier.rs
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ use caliptra_drivers::memory_layout::ICCM_RANGE;
pub struct FirmwareImageVerificationEnv<'a, 'b> {
pub sha256: &'a mut Sha256,
pub sha2_512_384: &'a mut Sha2_512_384,
pub sha2_512_384_acc: &'a mut Sha2_512_384Acc,
pub soc_ifc: &'a mut SocIfc,
pub ecc384: &'a mut Ecc384,
pub mldsa87: &'a mut Mldsa87,
Expand Down Expand Up @@ -58,6 +59,50 @@ impl ImageVerificationEnv for &mut FirmwareImageVerificationEnv<'_, '_> {
Ok(self.sha2_512_384.sha512_digest(data)?.0)
}

fn sha384_acc_digest(
&mut self,
offset: u32,
len: u32,
digest_failure: CaliptraError,
) -> CaliptraResult<ImageDigest384> {
let mut digest = Array4x12::default();

if let Some(mut sha_acc_op) = self
.sha2_512_384_acc
.try_start_operation(ShaAccLockState::NotAcquired)?
{
sha_acc_op
.digest_384(len, offset, false, &mut digest)
.map_err(|_| digest_failure)?;
} else {
Err(CaliptraError::KAT_SHA2_512_384_ACC_DIGEST_START_OP_FAILURE)?;
};

Ok(digest.0)
}

fn sha512_acc_digest(
&mut self,
offset: u32,
len: u32,
digest_failure: CaliptraError,
) -> CaliptraResult<ImageDigest512> {
let mut digest = Array4x16::default();

if let Some(mut sha_acc_op) = self
.sha2_512_384_acc
.try_start_operation(ShaAccLockState::NotAcquired)?
{
sha_acc_op
.digest_512(len, offset, false, &mut digest)
.map_err(|_| digest_failure)?;
} else {
Err(CaliptraError::KAT_SHA2_512_384_ACC_DIGEST_START_OP_FAILURE)?;
};

Ok(digest.0)
}

/// ECC-384 Verification routine
fn ecc384_verify(
&mut self,
Expand Down
2 changes: 1 addition & 1 deletion drivers/src/mailbox.rs
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ pub struct Mailbox {
mbox: MboxCsr,
}

const MAX_MAILBOX_LEN: u32 = 256 * 1024;
pub const MAX_MAILBOX_LEN: u32 = 256 * 1024;

impl Mailbox {
pub fn new(mbox: MboxCsr) -> Self {
Expand Down
15 changes: 9 additions & 6 deletions drivers/src/sha2_512_384acc.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
// Licensed under the Apache-2.0 license

use crate::mailbox::MAX_MAILBOX_LEN;
/*++
Licensed under the Apache-2.0 license.
Expand All @@ -20,9 +23,6 @@ use caliptra_registers::sha512_acc::enums::ShaCmdE;
use caliptra_registers::sha512_acc::regs::ExecuteWriteVal;
use caliptra_registers::sha512_acc::Sha512AccCsr;

/// Maximum mailbox capacity in Bytes.
const MAX_MAILBOX_CAPACITY_BYTES: u32 = 256 << 10;

pub type Sha384Digest<'a> = &'a mut Array4x12;
pub type Sha512Digest<'a> = &'a mut Array4x16;

Expand Down Expand Up @@ -179,9 +179,7 @@ impl Sha2_512_384AccOp<'_> {
) -> CaliptraResult<()> {
let sha_acc = self.sha512_acc.regs_mut();

if start_address >= MAX_MAILBOX_CAPACITY_BYTES
|| (start_address + dlen) > MAX_MAILBOX_CAPACITY_BYTES
{
if start_address >= MAX_MAILBOX_LEN || (start_address + dlen) > MAX_MAILBOX_LEN {
return Err(CaliptraError::DRIVER_SHA2_512_384ACC_INDEX_OUT_OF_BOUNDS);
}

Expand Down Expand Up @@ -221,6 +219,11 @@ impl Sha2_512_384AccOp<'_> {
maintain_data_endianess: bool,
digest: Sha384Digest,
) -> CaliptraResult<()> {
#[cfg(feature = "fips-test-hooks")]
unsafe {
crate::FipsTestHook::error_if_hook_set(crate::FipsTestHook::SHA384_DIGEST_FAILURE)?
}

self.digest_generic(
dlen,
start_address,
Expand Down
1 change: 1 addition & 0 deletions image/verify/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ doctest = false
[dependencies]
bitflags.workspace = true
caliptra-drivers.workspace = true
caliptra-registers.workspace = true
caliptra-image-types = { workspace = true, default-features = false }
memoffset.workspace = true
zerocopy.workspace = true
Expand Down
16 changes: 16 additions & 0 deletions image/verify/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -108,6 +108,22 @@ pub trait ImageVerificationEnv {
/// Calculate SHA-512 Digest
fn sha512_digest(&mut self, offset: u32, len: u32) -> CaliptraResult<ImageDigest512>;

/// Calculate SHA-384 Digest with accelerator
fn sha384_acc_digest(
&mut self,
offset: u32,
len: u32,
digest_failure: CaliptraError,
) -> CaliptraResult<ImageDigest384>;

/// Calculate SHA-512 Digest with accelerator
fn sha512_acc_digest(
&mut self,
offset: u32,
len: u32,
digest_failure: CaliptraError,
) -> CaliptraResult<ImageDigest512>;

/// Perform ECC-384 Verification
fn ecc384_verify(
&mut self,
Expand Down
147 changes: 73 additions & 74 deletions image/verify/src/verifier.rs
Original file line number Diff line number Diff line change
Expand Up @@ -503,13 +503,11 @@ impl<Env: ImageVerificationEnv> ImageVerifier<Env> {
)
};

let actual = &self
.env
.sha384_digest(range.start, range.len() as u32)
.map_err(|err| {
self.env.set_fw_extended_error(err.into());
CaliptraError::IMAGE_VERIFIER_ERR_VENDOR_PUB_KEY_DIGEST_FAILURE
})?;
let actual = &self.env.sha384_acc_digest(
range.start,
range.len() as u32,
CaliptraError::IMAGE_VERIFIER_ERR_VENDOR_PUB_KEY_DIGEST_FAILURE,
)?;

if cfi_launder(expected) != actual {
Err(CaliptraError::IMAGE_VERIFIER_ERR_VENDOR_PUB_KEY_DIGEST_MISMATCH)?;
Expand Down Expand Up @@ -539,13 +537,11 @@ impl<Env: ImageVerificationEnv> ImageVerifier<Env> {
span.start as u32 + offset..span.end as u32 + offset
};

let actual = &self
.env
.sha384_digest(range.start, range.len() as u32)
.map_err(|err| {
self.env.set_fw_extended_error(err.into());
CaliptraError::IMAGE_VERIFIER_ERR_VENDOR_PUB_KEY_DIGEST_FAILURE
})?;
let actual = &self.env.sha384_acc_digest(
range.start,
range.len() as u32,
CaliptraError::IMAGE_VERIFIER_ERR_VENDOR_PUB_KEY_DIGEST_FAILURE,
)?;

if cfi_launder(expected) != actual {
Err(CaliptraError::IMAGE_VERIFIER_ERR_VENDOR_ECC_PUB_KEY_DIGEST_MISMATCH)?;
Expand Down Expand Up @@ -592,10 +588,11 @@ impl<Env: ImageVerificationEnv> ImageVerifier<Env> {
LMS_PUB_KEY_BYTE_SIZE
} as u32;

let actual = &self.env.sha384_digest(start, size).map_err(|err| {
self.env.set_fw_extended_error(err.into());
CaliptraError::IMAGE_VERIFIER_ERR_VENDOR_PUB_KEY_DIGEST_FAILURE
})?;
let actual = &self.env.sha384_acc_digest(
start,
size,
CaliptraError::IMAGE_VERIFIER_ERR_VENDOR_PUB_KEY_DIGEST_FAILURE,
)?;

if cfi_launder(expected) != actual {
Err(CaliptraError::IMAGE_VERIFIER_ERR_VENDOR_PQC_PUB_KEY_DIGEST_MISMATCH)?;
Expand All @@ -622,13 +619,11 @@ impl<Env: ImageVerificationEnv> ImageVerifier<Env> {
)
};

let actual = &self
.env
.sha384_digest(range.start, range.len() as u32)
.map_err(|err| {
self.env.set_fw_extended_error(err.into());
CaliptraError::IMAGE_VERIFIER_ERR_OWNER_PUB_KEY_DIGEST_FAILURE
})?;
let actual = &self.env.sha384_acc_digest(
range.start,
range.len() as u32,
CaliptraError::IMAGE_VERIFIER_ERR_OWNER_PUB_KEY_DIGEST_FAILURE,
)?;

let fuses_digest = &self.env.owner_pub_key_digest_fuses();

Expand Down Expand Up @@ -674,26 +669,22 @@ impl<Env: ImageVerificationEnv> ImageVerifier<Env> {
};

// Vendor header digest is calculated up to the owner_data field.
let vendor_digest_384 = self
.env
.sha384_digest(range.start, vendor_header_len as u32)
.map_err(|err| {
self.env.set_fw_extended_error(err.into());
CaliptraError::IMAGE_VERIFIER_ERR_HEADER_DIGEST_FAILURE
})?;
let vendor_digest_384 = self.env.sha384_acc_digest(
range.start,
vendor_header_len as u32,
CaliptraError::IMAGE_VERIFIER_ERR_HEADER_DIGEST_FAILURE,
)?;

let mut vendor_digest_holder = ImageDigestHolder {
digest_384: &vendor_digest_384,
digest_512: None,
};

let owner_digest_384 = self
.env
.sha384_digest(range.start, range.len() as u32)
.map_err(|err| {
self.env.set_fw_extended_error(err.into());
CaliptraError::IMAGE_VERIFIER_ERR_HEADER_DIGEST_FAILURE
})?;
let owner_digest_384 = self.env.sha384_acc_digest(
range.start,
range.len() as u32,
CaliptraError::IMAGE_VERIFIER_ERR_HEADER_DIGEST_FAILURE,
)?;

let mut owner_digest_holder = ImageDigestHolder {
digest_384: &owner_digest_384,
Expand All @@ -705,22 +696,18 @@ impl<Env: ImageVerificationEnv> ImageVerifier<Env> {

// Update vendor_digest_holder and owner_digest_holder with SHA512 digests if MLDSA validation i required.
if let PqcKeyInfo::Mldsa(_, _) = info.vendor_pqc_info {
vendor_digest_512 = self
.env
.sha512_digest(range.start, vendor_header_len as u32)
.map_err(|err| {
self.env.set_fw_extended_error(err.into());
CaliptraError::IMAGE_VERIFIER_ERR_HEADER_DIGEST_FAILURE
})?;
vendor_digest_512 = self.env.sha512_acc_digest(
range.start,
vendor_header_len as u32,
CaliptraError::IMAGE_VERIFIER_ERR_HEADER_DIGEST_FAILURE,
)?;
vendor_digest_holder.digest_512 = Some(&vendor_digest_512);

owner_digest_512 = self
.env
.sha512_digest(range.start, range.len() as u32)
.map_err(|err| {
self.env.set_fw_extended_error(err.into());
CaliptraError::IMAGE_VERIFIER_ERR_HEADER_DIGEST_FAILURE
})?;
owner_digest_512 = self.env.sha512_acc_digest(
range.start,
range.len() as u32,
CaliptraError::IMAGE_VERIFIER_ERR_HEADER_DIGEST_FAILURE,
)?;
owner_digest_holder.digest_512 = Some(&owner_digest_512);
}

Expand Down Expand Up @@ -1031,13 +1018,11 @@ impl<Env: ImageVerificationEnv> ImageVerifier<Env> {
)
};

let actual = self
.env
.sha384_digest(range.start, range.len() as u32)
.map_err(|err| {
self.env.set_fw_extended_error(err.into());
CaliptraError::IMAGE_VERIFIER_ERR_TOC_DIGEST_FAILURE
})?;
let actual = self.env.sha384_acc_digest(
range.start,
range.len() as u32,
CaliptraError::IMAGE_VERIFIER_ERR_TOC_DIGEST_FAILURE,
)?;

if cfi_launder(*verify_info.digest) != actual {
Err(CaliptraError::IMAGE_VERIFIER_ERR_TOC_DIGEST_MISMATCH)?;
Expand Down Expand Up @@ -1140,13 +1125,11 @@ impl<Env: ImageVerificationEnv> ImageVerifier<Env> {
)
};

let actual = self
.env
.sha384_digest(range.start, range.len() as u32)
.map_err(|err| {
self.env.set_fw_extended_error(err.into());
CaliptraError::IMAGE_VERIFIER_ERR_FMC_DIGEST_FAILURE
})?;
let actual = self.env.sha384_acc_digest(
range.start,
range.len() as u32,
CaliptraError::IMAGE_VERIFIER_ERR_FMC_DIGEST_FAILURE,
)?;

if cfi_launder(verify_info.digest) != actual {
Err(CaliptraError::IMAGE_VERIFIER_ERR_FMC_DIGEST_MISMATCH)?;
Expand Down Expand Up @@ -1210,13 +1193,11 @@ impl<Env: ImageVerificationEnv> ImageVerifier<Env> {
)
};

let actual = self
.env
.sha384_digest(range.start, range.len() as u32)
.map_err(|err| {
self.env.set_fw_extended_error(err.into());
CaliptraError::IMAGE_VERIFIER_ERR_RUNTIME_DIGEST_FAILURE
})?;
let actual = self.env.sha384_acc_digest(
range.start,
range.len() as u32,
CaliptraError::IMAGE_VERIFIER_ERR_RUNTIME_DIGEST_FAILURE,
)?;

if cfi_launder(verify_info.digest) != actual {
Err(CaliptraError::IMAGE_VERIFIER_ERR_RUNTIME_DIGEST_MISMATCH)?;
Expand Down Expand Up @@ -2382,6 +2363,24 @@ mod tests {
Ok(self.digest_512)
}

fn sha384_acc_digest(
&mut self,
_offset: u32,
_len: u32,
_digest_failure: CaliptraError,
) -> CaliptraResult<ImageDigest384> {
Ok(self.digest_384)
}

fn sha512_acc_digest(
&mut self,
_offset: u32,
_len: u32,
_digest_failure: CaliptraError,
) -> CaliptraResult<ImageDigest512> {
Ok(self.digest_512)
}

fn ecc384_verify(
&mut self,
_digest: &ImageDigest384,
Expand Down
2 changes: 2 additions & 0 deletions rom/dev/src/flow/cold_reset/fw_processor.rs
Original file line number Diff line number Diff line change
Expand Up @@ -120,6 +120,7 @@ impl FirmwareProcessor {
let mut venv = FirmwareImageVerificationEnv {
sha256: &mut env.sha256,
sha2_512_384: &mut env.sha2_512_384,
sha2_512_384_acc: &mut env.sha2_512_384_acc,
soc_ifc: &mut env.soc_ifc,
ecc384: &mut env.ecc384,
mldsa87: &mut env.mldsa87,
Expand Down Expand Up @@ -448,6 +449,7 @@ impl FirmwareProcessor {
let venv = &mut FakeRomImageVerificationEnv {
sha256: venv.sha256,
sha2_512_384: venv.sha2_512_384,
sha2_512_384_acc: venv.sha2_512_384_acc,
soc_ifc: venv.soc_ifc,
data_vault: venv.data_vault,
ecc384: venv.ecc384,
Expand Down
Loading

0 comments on commit b4c8333

Please sign in to comment.