From e06ee14d03c9768e7a10bebf912be927d3df98be Mon Sep 17 00:00:00 2001 From: Nick Quarton <139178705+nquarton@users.noreply.github.com> Date: Thu, 15 Aug 2024 12:08:01 -0700 Subject: [PATCH] Caliptra 1.0.3 ROM Updates (#1633) * Changing SHA384ACC KAT to SHA512 (#1562) * Changing SHA384ACC KAT to SHA512 - Adding support for SHA512 digest in the SHA acclerator driver - Enabling support for SHA512 in the SW emulator SHA accelerator * Renaming sha384acc to sha2_512_384acc * Adding ECC error checking during waits (#1610) * [bugfix] hmac384 driver: Reload kv keys for each block. This fixes #1520 / #1550: HMAC operations larger than a single block produce the incorrect results when using data or keys from the keyvault. Add a multi-block hmac384 test that uses the key-vault. smoke-test: Verify FMC key derivation with independent impl. * Updating DPE to fix sporadic test failure * Updating ROM version to 1.0.3 * Removing publish website step for nightly release --------- Co-authored-by: Kor Nielsen --- .github/workflows/nightly-release.yml | 17 +- FROZEN_IMAGES.sha384sum | 4 +- builder/src/firmware.rs | 6 +- builder/src/version.rs | 2 +- common/src/error_handler.rs | 6 +- dpe | 2 +- drivers/src/ecc384.rs | 44 ++- drivers/src/hmac384.rs | 129 ++++++--- drivers/src/lib.rs | 6 +- .../src/{sha384acc.rs => sha2_512_384acc.rs} | 115 ++++++-- drivers/test-fw/Cargo.toml | 4 +- drivers/test-fw/src/bin/hmac384_tests.rs | 46 ++++ ...4acc_tests.rs => sha2_512_384acc_tests.rs} | 182 +++++++++++-- .../tests/drivers_integration_tests/main.rs | 4 +- error/README.md | 6 +- error/src/lib.rs | 17 +- fmc/src/fmc_env.rs | 8 +- hw-model/src/lib.rs | 2 +- kat/src/kats_env.rs | 6 +- kat/src/lib.rs | 8 +- kat/src/sha2_512_384acc_kat.rs | 84 ++++++ kat/src/sha384acc_kat.rs | 67 ----- rom/dev/doc/error-attribution.md | 8 +- rom/dev/src/flow/cold_reset/fw_processor.rs | 4 +- rom/dev/src/flow/fake.rs | 2 +- rom/dev/src/main.rs | 12 +- rom/dev/src/rom_env.rs | 8 +- runtime/src/drivers.rs | 10 +- runtime/src/fips.rs | 10 +- .../runtime_integration_tests/test_ecdsa.rs | 29 ++ sw-emulator/lib/periph/src/asym_ecc384.rs | 10 + sw-emulator/lib/periph/src/sha512_acc.rs | 250 ++++++++++++++++-- test/dpe_verification/go.mod | 10 +- test/dpe_verification/go.sum | 12 +- test/src/derive.rs | 85 +++++- .../caliptra_integration_tests/smoke_test.rs | 23 +- 36 files changed, 971 insertions(+), 267 deletions(-) rename drivers/src/{sha384acc.rs => sha2_512_384acc.rs} (62%) rename drivers/test-fw/src/bin/{sha384acc_tests.rs => sha2_512_384acc_tests.rs} (50%) create mode 100644 kat/src/sha2_512_384acc_kat.rs delete mode 100644 kat/src/sha384acc_kat.rs diff --git a/.github/workflows/nightly-release.yml b/.github/workflows/nightly-release.yml index 667b9759c4..b68fd89f24 100644 --- a/.github/workflows/nightly-release.yml +++ b/.github/workflows/nightly-release.yml @@ -215,11 +215,12 @@ jobs: name: release-info path: /tmp/release-info - publish-website: - name: Publish https://caliptra-sw.github.io/ - needs: - create-release - uses: ./.github/workflows/publish-website.yml - permissions: - pages: write - id-token: write + # SKIP Publishing the test results when we are not on the main branch + # publish-website: + # name: Publish https://caliptra-sw.github.io/ + # needs: + # create-release + # uses: ./.github/workflows/publish-website.yml + # permissions: + # pages: write + # id-token: write diff --git a/FROZEN_IMAGES.sha384sum b/FROZEN_IMAGES.sha384sum index 0795facf18..4fae700648 100644 --- a/FROZEN_IMAGES.sha384sum +++ b/FROZEN_IMAGES.sha384sum @@ -1,3 +1,3 @@ # WARNING: Do not update this file without the approval of the Caliptra TAC -a6d9b0b6ae4abe19b11a838b2bebaa93f7e8f901c86cdd1e5dae31ae7fed833eff1e46968abbeff5cb3c7fe020565d82 caliptra-rom-no-log.bin -f6df64ab5a31ecbbf4380e55a13ade0f43e797cf73defb288f719cabc1e60c5bf4da85b54f068e3182040db0675b4f4b caliptra-rom-with-log.bin +89ac48da7ac14cc456b9545c68f5ff70e6a6fcdd4deba3d7d94a65b7d3ad092273a723114073a925728fa82c3c8ca225 caliptra-rom-no-log.bin +ab399aa651019bb77c379ccb184444b2dd17d118f27072827477d2bf561616251b0ea149973ac13659b25e81beffafe6 caliptra-rom-with-log.bin diff --git a/builder/src/firmware.rs b/builder/src/firmware.rs index 4ec34d497c..63ab2e63e6 100644 --- a/builder/src/firmware.rs +++ b/builder/src/firmware.rs @@ -228,8 +228,8 @@ pub mod driver_tests { ..BASE_FWID }; - pub const SHA384ACC: FwId = FwId { - bin_name: "sha384acc", + pub const SHA2_512_384ACC: FwId = FwId { + bin_name: "sha2_512_384acc", ..BASE_FWID }; @@ -415,7 +415,7 @@ pub const REGISTERED_FW: &[&FwId] = &[ &driver_tests::SHA1, &driver_tests::SHA256, &driver_tests::SHA384, - &driver_tests::SHA384ACC, + &driver_tests::SHA2_512_384ACC, &driver_tests::STATUS_REPORTER, &driver_tests::TEST_LMS_24, &driver_tests::TEST_LMS_32, diff --git a/builder/src/version.rs b/builder/src/version.rs index 91f90273e0..759714e9eb 100755 --- a/builder/src/version.rs +++ b/builder/src/version.rs @@ -2,7 +2,7 @@ pub const ROM_VERSION_MAJOR: u16 = 1; pub const ROM_VERSION_MINOR: u16 = 0; -pub const ROM_VERSION_PATCH: u16 = 2; +pub const ROM_VERSION_PATCH: u16 = 3; pub const FMC_VERSION_MAJOR: u16 = 1; pub const FMC_VERSION_MINOR: u16 = 0; diff --git a/common/src/error_handler.rs b/common/src/error_handler.rs index 2ed709d518..d0be139338 100644 --- a/common/src/error_handler.rs +++ b/common/src/error_handler.rs @@ -1,7 +1,7 @@ // Licensed under the Apache-2.0 license use caliptra_drivers::{ cprintln, report_fw_error_fatal, report_fw_error_non_fatal, Ecc384, Hmac384, KeyVault, Mailbox, - Sha256, Sha384, Sha384Acc, SocIfc, + Sha256, Sha2_512_384Acc, Sha384, SocIfc, }; #[allow(clippy::empty_loop)] @@ -20,13 +20,13 @@ pub fn handle_fatal_error(code: u32) -> ! { Hmac384::zeroize(); Sha256::zeroize(); Sha384::zeroize(); - Sha384Acc::zeroize(); + Sha2_512_384Acc::zeroize(); // Zeroize the key vault. KeyVault::zeroize(); // Lock the SHA Accelerator. - Sha384Acc::lock(); + Sha2_512_384Acc::lock(); // Stop the watchdog timer. // Note: This is an idempotent operation. diff --git a/dpe b/dpe index 86a220a8de..8690f1f92e 160000 --- a/dpe +++ b/dpe @@ -1 +1 @@ -Subproject commit 86a220a8dec75dbbbe8a1387b81bef5b609984fa +Subproject commit 8690f1f92e26b374172d33e47f3f7852ab178d09 diff --git a/drivers/src/ecc384.rs b/drivers/src/ecc384.rs index 6bf4ecfea5..1333c0ad1c 100644 --- a/drivers/src/ecc384.rs +++ b/drivers/src/ecc384.rs @@ -19,7 +19,7 @@ use crate::{ }; #[cfg(not(feature = "no-cfi"))] use caliptra_cfi_derive::cfi_impl_fn; -use caliptra_registers::ecc::EccReg; +use caliptra_registers::ecc::{EccReg, RegisterBlock}; use core::cmp::Ordering; use zerocopy::{AsBytes, FromBytes}; use zeroize::Zeroize; @@ -182,6 +182,32 @@ impl Ecc384 { false } + // Wait on the provided condition OR the error condition defined in this function + // In the event of the error condition being set, clear the error bits and return an error + fn wait(regs: RegisterBlock, condition: F) -> CaliptraResult<()> + where + F: Fn() -> bool, + { + let err_condition = || { + (u32::from(regs.intr_block_rf().error_global_intr_r().read()) != 0) + || (u32::from(regs.intr_block_rf().error_internal_intr_r().read()) != 0) + }; + + // Wait for either the given condition or the error condition + wait::until(|| (condition() || err_condition())); + + if err_condition() { + // Clear the errors + // error_global_intr_r is RO + regs.intr_block_rf() + .error_internal_intr_r() + .write(|_| u32::from(regs.intr_block_rf().error_internal_intr_r().read()).into()); + return Err(CaliptraError::DRIVER_ECC384_HW_ERROR); + } + + Ok(()) + } + /// Generate ECC-384 Key Pair /// /// # Arguments @@ -206,7 +232,7 @@ impl Ecc384 { let mut priv_key = priv_key; // Wait for hardware ready - wait::until(|| ecc.status().read().ready()); + Ecc384::wait(ecc, || ecc.status().read().ready())?; // Configure hardware to route keys to user specified hardware blocks match &mut priv_key { @@ -245,7 +271,7 @@ impl Ecc384 { ecc.ctrl().write(|w| w.ctrl(|w| w.keygen())); // Wait for command to complete - wait::until(|| ecc.status().read().valid()); + Ecc384::wait(ecc, || ecc.status().read().valid())?; // Copy the private key match &mut priv_key { @@ -290,7 +316,7 @@ impl Ecc384 { let ecc = self.ecc.regs_mut(); // Wait for hardware ready - wait::until(|| ecc.status().read().ready()); + Ecc384::wait(ecc, || ecc.status().read().ready())?; // Generate an IV. let iv = trng.generate()?; @@ -299,7 +325,7 @@ impl Ecc384 { ecc.ctrl().write(|w| w.pcr_sign(true).ctrl(|w| w.signing())); // Wait for command to complete - wait::until(|| ecc.status().read().valid()); + Ecc384::wait(ecc, || ecc.status().read().valid())?; // Copy signature let signature = Ecc384Signature { @@ -322,7 +348,7 @@ impl Ecc384 { let ecc = self.ecc.regs_mut(); // Wait for hardware ready - wait::until(|| ecc.status().read().ready()); + Ecc384::wait(ecc, || ecc.status().read().ready())?; // Copy private key match priv_key { @@ -344,7 +370,7 @@ impl Ecc384 { ecc.ctrl().write(|w| w.ctrl(|w| w.signing())); // Wait for command to complete - wait::until(|| ecc.status().read().valid()); + Ecc384::wait(ecc, || ecc.status().read().valid())?; // Copy signature let signature = Ecc384Signature { @@ -455,7 +481,7 @@ impl Ecc384 { let ecc = self.ecc.regs_mut(); // Wait for hardware ready - wait::until(|| ecc.status().read().ready()); + Ecc384::wait(ecc, || ecc.status().read().ready())?; // Copy public key to registers pub_key.x.write_to_reg(ecc.pubkey_x()); @@ -472,7 +498,7 @@ impl Ecc384 { ecc.ctrl().write(|w| w.ctrl(|w| w.verifying())); // Wait for command to complete - wait::until(|| ecc.status().read().valid()); + Ecc384::wait(ecc, || ecc.status().read().valid())?; // Copy the random value let verify_r = Array4x12::read_from_reg(ecc.verify_r()); diff --git a/drivers/src/hmac384.rs b/drivers/src/hmac384.rs index a6cb319c09..19bbcf51e4 100644 --- a/drivers/src/hmac384.rs +++ b/drivers/src/hmac384.rs @@ -136,23 +136,18 @@ impl Hmac384 { // Configure the hardware so that the output tag is stored at a location specified by the // caller. - match &mut tag { - Hmac384Tag::Array4x12(_arr) => { - KvAccess::begin_copy_to_arr(hmac.kv_wr_status(), hmac.kv_wr_ctrl())? - } - Hmac384Tag::Key(key) => { - KvAccess::begin_copy_to_kv(hmac.kv_wr_status(), hmac.kv_wr_ctrl(), *key)? - } + if matches!(&mut tag, Hmac384Tag::Array4x12(_)) { + KvAccess::begin_copy_to_arr(hmac.kv_wr_status(), hmac.kv_wr_ctrl())?; } // Configure the hardware to use key to use for the HMAC operation - match key { - Hmac384Key::Array4x12(arr) => KvAccess::copy_from_arr(arr, hmac.key())?, - Hmac384Key::Key(key) => { - KvAccess::copy_from_kv(*key, hmac.kv_rd_key_status(), hmac.kv_rd_key_ctrl()) - .map_err(|err| err.into_read_key_err())? + let key = match key { + Hmac384Key::Array4x12(arr) => { + KvAccess::copy_from_arr(arr, hmac.key())?; + None } - } + Hmac384Key::Key(key) => Some(*key), + }; // Generate an LFSR seed. let rand_data = trng.generate()?; @@ -161,6 +156,7 @@ impl Hmac384 { let op = Hmac384Op { hmac_engine: self, + key, state: Hmac384OpState::Init, buf: [0u8; HMAC384_BLOCK_SIZE_BYTES], buf_idx: 0, @@ -193,23 +189,22 @@ impl Hmac384 { // Configure the hardware so that the output tag is stored at a location specified by the // caller. - match &mut tag { + let dest_key = match &mut tag { Hmac384Tag::Array4x12(_arr) => { - KvAccess::begin_copy_to_arr(hmac.kv_wr_status(), hmac.kv_wr_ctrl())? - } - Hmac384Tag::Key(key) => { - KvAccess::begin_copy_to_kv(hmac.kv_wr_status(), hmac.kv_wr_ctrl(), *key)? + KvAccess::begin_copy_to_arr(hmac.kv_wr_status(), hmac.kv_wr_ctrl())?; + None } - } + Hmac384Tag::Key(dest_key) => Some(*dest_key), + }; // Configure the hardware to use key to use for the HMAC operation - match key { - Hmac384Key::Array4x12(arr) => KvAccess::copy_from_arr(arr, hmac.key())?, - Hmac384Key::Key(key) => { - KvAccess::copy_from_kv(*key, hmac.kv_rd_key_status(), hmac.kv_rd_key_ctrl()) - .map_err(|err| err.into_read_key_err())? + let key = match *key { + Hmac384Key::Array4x12(arr) => { + KvAccess::copy_from_arr(arr, hmac.key())?; + None } - } + Hmac384Key::Key(key) => Some(key), + }; // Generate an LFSR seed. let rand_data = trng.generate()?; @@ -218,16 +213,15 @@ impl Hmac384 { // Calculate the hmac match data { - Hmac384Data::Slice(buf) => self.hmac_buf(buf)?, - Hmac384Data::Key(key) => self.hmac_key(*key)?, + Hmac384Data::Slice(buf) => self.hmac_buf(buf, key, dest_key)?, + Hmac384Data::Key(data_key) => self.hmac_key(*data_key, key, dest_key)?, } let hmac = self.hmac.regs(); // Copy the tag to the specified location let result = match &mut tag { Hmac384Tag::Array4x12(arr) => KvAccess::end_copy_to_arr(hmac.tag(), arr), - Hmac384Tag::Key(key) => KvAccess::end_copy_to_kv(hmac.kv_wr_status(), *key) - .map_err(|err| err.into_write_tag_err()), + _ => Ok(()), }; self.zeroize_internal(); @@ -262,7 +256,12 @@ impl Hmac384 { /// /// * `buf` - Buffer to calculate the hmac over /// - fn hmac_buf(&mut self, buf: &[u8]) -> CaliptraResult<()> { + fn hmac_buf( + &mut self, + buf: &[u8], + key: Option, + dest_key: Option, + ) -> CaliptraResult<()> { // Check if the buffer is within the size that we support if buf.len() > HMAC384_MAX_DATA_SIZE { return Err(CaliptraError::DRIVER_HMAC384_MAX_DATA); @@ -280,7 +279,7 @@ impl Hmac384 { // the panic. if let Some(slice) = buf.get(offset..) { - self.hmac_partial_block(slice, first, buf.len())?; + self.hmac_partial_block(slice, first, buf.len(), key, dest_key)?; break; } else { return Err(CaliptraError::DRIVER_HMAC384_INVALID_SLICE); @@ -293,7 +292,7 @@ impl Hmac384 { // the panic. if let Some(slice) = buf.get(offset..offset + HMAC384_BLOCK_SIZE_BYTES) { let block = <&[u8; HMAC384_BLOCK_SIZE_BYTES]>::try_from(slice).unwrap(); - self.hmac_block(block, first)?; + self.hmac_block(block, first, key, dest_key)?; bytes_remaining -= HMAC384_BLOCK_SIZE_BYTES; first = false; } else { @@ -313,13 +312,18 @@ impl Hmac384 { /// /// * `key` - Key to calculate hmac for /// - fn hmac_key(&mut self, key: KeyReadArgs) -> CaliptraResult<()> { + fn hmac_key( + &mut self, + data_key: KeyReadArgs, + key: Option, + dest_key: Option, + ) -> CaliptraResult<()> { let hmac = self.hmac.regs_mut(); - KvAccess::copy_from_kv(key, hmac.kv_rd_block_status(), hmac.kv_rd_block_ctrl()) + KvAccess::copy_from_kv(data_key, hmac.kv_rd_block_status(), hmac.kv_rd_block_ctrl()) .map_err(|err| err.into_read_data_err())?; - self.hmac_op(true) + self.hmac_op(true, key, dest_key) } fn hmac_partial_block( @@ -327,6 +331,8 @@ impl Hmac384 { slice: &[u8], first: bool, buf_size: usize, + key: Option, + dest_key: Option, ) -> CaliptraResult<()> { /// Set block length fn set_block_len(buf_size: usize, block: &mut [u8; HMAC384_BLOCK_SIZE_BYTES]) { @@ -349,13 +355,13 @@ impl Hmac384 { } // Calculate the digest of the op - self.hmac_block(&block, first)?; + self.hmac_block(&block, first, key, dest_key)?; // Add a padding block if one is needed if slice.len() >= HMAC384_BLOCK_LEN_OFFSET { block.fill(0); set_block_len(buf_size, &mut block); - self.hmac_block(&block, false)?; + self.hmac_block(&block, false, key, dest_key)?; } Ok(()) @@ -373,10 +379,12 @@ impl Hmac384 { &mut self, block: &[u8; HMAC384_BLOCK_SIZE_BYTES], first: bool, + key: Option, + dest_key: Option, ) -> CaliptraResult<()> { let hmac384 = self.hmac.regs_mut(); Array4x32::from(block).write_to_reg(hmac384.block()); - self.hmac_op(first) + self.hmac_op(first, key, dest_key) } /// @@ -386,9 +394,22 @@ impl Hmac384 { /// /// * `first` - Flag indicating if this is the first block /// - fn hmac_op(&mut self, first: bool) -> CaliptraResult<()> { + fn hmac_op( + &mut self, + first: bool, + key: Option, + dest_key: Option, + ) -> CaliptraResult<()> { let hmac = self.hmac.regs_mut(); + if let Some(key) = key { + KvAccess::copy_from_kv(key, hmac.kv_rd_key_status(), hmac.kv_rd_key_ctrl()) + .map_err(|err| err.into_read_key_err())? + }; + if let Some(dest_key) = dest_key { + KvAccess::begin_copy_to_kv(hmac.kv_wr_status(), hmac.kv_wr_ctrl(), dest_key)?; + } + // Wait for the hardware to be ready wait::until(|| hmac.status().read().ready()); @@ -403,6 +424,11 @@ impl Hmac384 { // Wait for the hmac operation to finish wait::until(|| hmac.status().read().valid()); + if let Some(dest_key) = dest_key { + KvAccess::end_copy_to_kv(hmac.kv_wr_status(), dest_key) + .map_err(|err| err.into_write_tag_err())?; + } + Ok(()) } } @@ -427,6 +453,9 @@ pub struct Hmac384Op<'a> { /// State state: Hmac384OpState, + // The keyvault key used to compute the hmac + key: Option, + /// Staging buffer buf: [u8; HMAC384_BLOCK_SIZE_BYTES], @@ -472,7 +501,12 @@ impl<'a> Hmac384Op<'a> { // If the buffer is full calculate the digest of accumulated data if self.buf_idx == self.buf.len() { - self.hmac_engine.hmac_block(&self.buf, self.is_first())?; + self.hmac_engine.hmac_block( + &self.buf, + self.is_first(), + self.key, + self.dest_key(), + )?; self.reset_buf_state(); } } @@ -492,8 +526,13 @@ impl<'a> Hmac384Op<'a> { // Calculate the hmac of the final block let buf = &self.buf[..self.buf_idx]; - self.hmac_engine - .hmac_partial_block(buf, self.is_first(), self.data_size)?; + self.hmac_engine.hmac_partial_block( + buf, + self.is_first(), + self.data_size, + self.key, + self.dest_key(), + )?; // Set the state of the operation to final self.state = Hmac384OpState::Final; @@ -507,6 +546,12 @@ impl<'a> Hmac384Op<'a> { .map_err(|err| err.into_write_tag_err()), } } + fn dest_key(&self) -> Option { + match self.tag { + Hmac384Tag::Key(key) => Some(key), + _ => None, + } + } /// Check if this the first digest operation fn is_first(&self) -> bool { diff --git a/drivers/src/lib.rs b/drivers/src/lib.rs index 31718cc09a..ce8c140259 100644 --- a/drivers/src/lib.rs +++ b/drivers/src/lib.rs @@ -44,13 +44,13 @@ pub mod pic; pub mod printer; mod sha1; mod sha256; +mod sha2_512_384acc; mod sha384; -mod sha384acc; mod soc_ifc; mod trng; mod trng_ext; -pub use array::{Array4x12, Array4x4, Array4x5, Array4x8, Array4xN}; +pub use array::{Array4x12, Array4x16, Array4x4, Array4x5, Array4x8, Array4xN}; pub use array_concat::array_concat3; pub use bounded_address::{BoundedAddr, MemBounds, RomAddr}; pub use caliptra_error::{CaliptraError, CaliptraResult}; @@ -89,8 +89,8 @@ pub use persistent::{ pub use pic::{IntSource, Pic}; pub use sha1::{Sha1, Sha1Digest, Sha1DigestOp}; pub use sha256::{Sha256, Sha256Alg, Sha256DigestOp}; +pub use sha2_512_384acc::{Sha2_512_384Acc, Sha2_512_384AccOp, ShaAccLockState}; pub use sha384::{Sha384, Sha384Digest, Sha384DigestOp}; -pub use sha384acc::{Sha384Acc, Sha384AccOp, ShaAccLockState}; pub use soc_ifc::{report_boot_status, Lifecycle, MfgFlags, ResetReason, SocIfc}; pub use trng::Trng; diff --git a/drivers/src/sha384acc.rs b/drivers/src/sha2_512_384acc.rs similarity index 62% rename from drivers/src/sha384acc.rs rename to drivers/src/sha2_512_384acc.rs index cbcd269810..e3ab097f81 100644 --- a/drivers/src/sha384acc.rs +++ b/drivers/src/sha2_512_384acc.rs @@ -4,18 +4,19 @@ Licensed under the Apache-2.0 license. File Name: - sha384acc.rs + sha2_512_384acc.rs Abstract: - File contains API for SHA384 accelerator operations + File contains API for SHA2 512/384 accelerator operations --*/ use crate::wait; -use crate::Array4x12; use crate::CaliptraResult; +use crate::{Array4x12, Array4x16}; use caliptra_error::CaliptraError; +use caliptra_registers::sha512_acc::enums::ShaCmdE; use caliptra_registers::sha512_acc::regs::ExecuteWriteVal; use caliptra_registers::sha512_acc::Sha512AccCsr; @@ -23,6 +24,7 @@ use caliptra_registers::sha512_acc::Sha512AccCsr; const MAX_MAILBOX_CAPACITY_BYTES: u32 = 128 << 10; pub type Sha384Digest<'a> = &'a mut Array4x12; +pub type Sha512Digest<'a> = &'a mut Array4x16; #[repr(u32)] #[derive(Debug, Clone, Copy, PartialEq, Eq)] @@ -31,11 +33,11 @@ pub enum ShaAccLockState { NotAcquired = 0x5555_555A, } -pub struct Sha384Acc { +pub struct Sha2_512_384Acc { sha512_acc: Sha512AccCsr, } -impl Sha384Acc { +impl Sha2_512_384Acc { pub fn new(sha512_acc: Sha512AccCsr) -> Self { Self { sha512_acc } } @@ -56,7 +58,7 @@ impl Sha384Acc { pub fn try_start_operation( &mut self, assumed_lock_state: ShaAccLockState, - ) -> CaliptraResult> { + ) -> CaliptraResult> { let sha_acc = self.sha512_acc.regs(); match assumed_lock_state { @@ -67,7 +69,7 @@ impl Sha384Acc { Ok(None) } else { // The uC acquired the lock just now. - Ok(Some(Sha384AccOp { + Ok(Some(Sha2_512_384AccOp { sha512_acc: &mut self.sha512_acc, })) } @@ -75,12 +77,12 @@ impl Sha384Acc { ShaAccLockState::AssumedLocked => { if sha_acc.lock().read().lock() { // SHA Acc is locked and the caller is assuming that the uC has it. - Ok(Some(Sha384AccOp { + Ok(Some(Sha2_512_384AccOp { sha512_acc: &mut self.sha512_acc, })) } else { // Caller expected uC to already have the lock, but uC actually didn't (bug) - Err(CaliptraError::DRIVER_SHA384ACC_UNEXPECTED_ACQUIRED_LOCK_STATE) + Err(CaliptraError::DRIVER_SHA2_512_384ACC_UNEXPECTED_ACQUIRED_LOCK_STATE) } } } @@ -134,11 +136,11 @@ impl Sha384Acc { } } -pub struct Sha384AccOp<'a> { +pub struct Sha2_512_384AccOp<'a> { sha512_acc: &'a mut Sha512AccCsr, } -impl Drop for Sha384AccOp<'_> { +impl Drop for Sha2_512_384AccOp<'_> { /// Release the SHA384 Accelerator lock. /// /// # Arguments @@ -150,20 +152,28 @@ impl Drop for Sha384AccOp<'_> { } } -impl Sha384AccOp<'_> { - pub fn digest( +impl Sha2_512_384AccOp<'_> { + /// Perform SHA digest with a configurable mode + /// + /// # Arguments + /// + /// * `dlen` - length of data to read from the mailbox + /// * `start_address` - start offset for the data in the mailbox + /// * `maintain_data_endianess` - reorder byte endianess if false, leave as-is if true + /// * `cmd` - SHA mode/command to use from ShaCmdE + fn digest_generic( &mut self, dlen: u32, start_address: u32, maintain_data_endianess: bool, - digest: Sha384Digest, + cmd: ShaCmdE, ) -> CaliptraResult<()> { let sha_acc = self.sha512_acc.regs_mut(); if start_address >= MAX_MAILBOX_CAPACITY_BYTES || (start_address + dlen) > MAX_MAILBOX_CAPACITY_BYTES { - return Err(CaliptraError::DRIVER_SHA384ACC_INDEX_OUT_OF_BOUNDS); + return Err(CaliptraError::DRIVER_SHA2_512_384ACC_INDEX_OUT_OF_BOUNDS); } // Set the data length to read from the mailbox. @@ -172,21 +182,46 @@ impl Sha384AccOp<'_> { // Set the start offset of the data in the mailbox. sha_acc.start_address().write(|_| start_address); - // Set the SHA accelerator mode (only SHA384 supported) and - // set the option to maintain the DWORD endianess of the data in the - // mailbox provided to the SHA384 engine. - sha_acc.mode().write(|w| { - w.mode(|w| w.sha_mbox_384()) - .endian_toggle(maintain_data_endianess) - }); + // Set the SHA accelerator mode and set the option to maintain the DWORD + // endianess of the data in the mailbox provided to the SHA384 engine. + sha_acc + .mode() + .write(|w| w.mode(|_| cmd).endian_toggle(maintain_data_endianess)); - // Trigger the SHA384 operation. + // Trigger the SHA operation. sha_acc.execute().write(|_| ExecuteWriteVal::from(1)); // Wait for the digest operation to finish wait::until(|| sha_acc.status().read().valid()); - self.copy_digest_to_buf(digest)?; + Ok(()) + } + + /// Perform SHA 384 digest + /// + /// # Arguments + /// + /// * `dlen` - length of data to read from the mailbox + /// * `start_address` - start offset for the data in the mailbox + /// * `maintain_data_endianess` - reorder byte endianess if false, leave as-is if true + /// * `digest` - buffer to populate with resulting digest + pub fn digest_384( + &mut self, + dlen: u32, + start_address: u32, + maintain_data_endianess: bool, + digest: Sha384Digest, + ) -> CaliptraResult<()> { + self.digest_generic( + dlen, + start_address, + maintain_data_endianess, + ShaCmdE::ShaMbox384, + )?; + + // Copy digest to buffer + let sha_acc = self.sha512_acc.regs(); + *digest = Array4x12::read_from_reg(sha_acc.digest().truncate::<12>()); // Zeroize the hardware registers. self.sha512_acc @@ -197,14 +232,38 @@ impl Sha384AccOp<'_> { Ok(()) } - /// Copy digest to buffer + /// Perform SHA 512 digest /// /// # Arguments /// - /// * `buf` - Digest buffer - fn copy_digest_to_buf(&mut self, buf: &mut Array4x12) -> CaliptraResult<()> { + /// * `dlen` - length of data to read from the mailbox + /// * `start_address` - start offset for the data in the mailbox + /// * `maintain_data_endianess` - reorder byte endianess if false, leave as-is if true + /// * `digest` - buffer to populate with resulting digest + pub fn digest_512( + &mut self, + dlen: u32, + start_address: u32, + maintain_data_endianess: bool, + digest: Sha512Digest, + ) -> CaliptraResult<()> { + self.digest_generic( + dlen, + start_address, + maintain_data_endianess, + ShaCmdE::ShaMbox512, + )?; + + // Copy digest to buffer let sha_acc = self.sha512_acc.regs(); - *buf = Array4x12::read_from_reg(sha_acc.digest().truncate::<12>()); + *digest = Array4x16::read_from_reg(sha_acc.digest()); + + // Zeroize the hardware registers. + self.sha512_acc + .regs_mut() + .control() + .write(|w| w.zeroize(true)); + Ok(()) } } diff --git a/drivers/test-fw/Cargo.toml b/drivers/test-fw/Cargo.toml index bc47f424ba..400add394d 100644 --- a/drivers/test-fw/Cargo.toml +++ b/drivers/test-fw/Cargo.toml @@ -99,8 +99,8 @@ path = "src/bin/persistent_tests.rs" required-features = ["riscv"] [[bin]] -name = "sha384acc" -path = "src/bin/sha384acc_tests.rs" +name = "sha2_512_384acc" +path = "src/bin/sha2_512_384acc_tests.rs" required-features = ["riscv"] [[bin]] diff --git a/drivers/test-fw/src/bin/hmac384_tests.rs b/drivers/test-fw/src/bin/hmac384_tests.rs index 755009db1b..7c07f41f81 100755 --- a/drivers/test-fw/src/bin/hmac384_tests.rs +++ b/drivers/test-fw/src/bin/hmac384_tests.rs @@ -246,6 +246,51 @@ fn test_hmac4() { test_kv_hmac(&seed, &data, &out_pub_x, &out_pub_y); } +fn test_hmac_kv_multiblock() { + let seed = [ + 0x32, 0x36, 0xcf, 0xba, 0x5d, 0xf3, 0x86, 0x39, 0x3e, 0x41, 0x13, 0x2b, 0x2d, 0x70, 0x6c, + 0x00, 0x66, 0xe9, 0x2a, 0xa7, 0xb6, 0xe7, 0x09, 0x35, 0x16, 0xb6, 0xeb, 0x5f, 0x0b, 0x1e, + 0x09, 0x3d, 0x7c, 0x9f, 0xa8, 0x1a, 0x0e, 0x61, 0x23, 0xac, 0x09, 0x0a, 0x40, 0xa4, 0x42, + 0xf9, 0x3f, 0xaa, + ]; + + let data: [u8; 256] = [ + 0x35, 0xc8, 0x57, 0xb5, 0x0f, 0x0f, 0xb2, 0x1a, 0x39, 0xab, 0xc8, 0xa3, 0xe7, 0xed, 0xf7, + 0xe0, 0x4f, 0x16, 0xa4, 0xd5, 0xe6, 0x86, 0xe3, 0xf2, 0x1f, 0x38, 0xf5, 0x6e, 0xbd, 0x88, + 0x74, 0x3f, 0x0f, 0xfb, 0x27, 0x29, 0x60, 0x3f, 0x84, 0x07, 0x5e, 0x5e, 0xc4, 0x57, 0x79, + 0xce, 0xfa, 0x30, 0x5b, 0xb2, 0xed, 0xdd, 0xd7, 0xe2, 0xd2, 0xb3, 0xa6, 0x7a, 0xd9, 0x1e, + 0x5d, 0x86, 0xa1, 0x96, 0x67, 0x2a, 0x47, 0x48, 0x4e, 0x72, 0xd6, 0xec, 0xde, 0x96, 0xbe, + 0x5f, 0x9f, 0x09, 0x71, 0xbf, 0xe3, 0xc9, 0x06, 0x59, 0x1a, 0x3b, 0x2e, 0x3b, 0xe8, 0x97, + 0x56, 0x27, 0x13, 0x5e, 0xf7, 0xf3, 0x7c, 0xde, 0xe0, 0x94, 0xdd, 0xf3, 0x3d, 0xa0, 0x7f, + 0xf5, 0x77, 0x47, 0xca, 0x32, 0xbc, 0xb3, 0x0d, 0x6a, 0x40, 0xeb, 0xeb, 0x07, 0x86, 0x01, + 0x27, 0x82, 0x55, 0x6b, 0x8e, 0x0a, 0x48, 0x34, 0x9b, 0x72, 0x91, 0x10, 0x55, 0xeb, 0x2b, + 0x0d, 0x53, 0x2d, 0xe2, 0x6b, 0x62, 0xa4, 0x06, 0xfd, 0x03, 0x9b, 0xfd, 0x74, 0x9d, 0xd3, + 0x59, 0x3d, 0x66, 0xd6, 0xfb, 0x09, 0x83, 0x63, 0x7d, 0xbf, 0x34, 0x40, 0x40, 0x5b, 0xf7, + 0xf8, 0xb0, 0xd3, 0xe8, 0x72, 0x7c, 0x4c, 0xc8, 0xd2, 0x01, 0x8a, 0xf4, 0xc3, 0xf0, 0xff, + 0x12, 0x21, 0x17, 0xfb, 0x6a, 0x44, 0x00, 0x52, 0xc2, 0x0c, 0x6a, 0x9b, 0x93, 0x21, 0xd1, + 0x65, 0x22, 0x8d, 0xae, 0x70, 0xbf, 0x90, 0xdb, 0xe4, 0x8a, 0x1a, 0xb9, 0x79, 0x48, 0x7a, + 0x35, 0x6d, 0x96, 0x29, 0x22, 0x82, 0xd1, 0xfb, 0x06, 0x42, 0x09, 0xbc, 0xe5, 0xd0, 0x1c, + 0xec, 0xf5, 0xc1, 0x74, 0x13, 0x4d, 0x89, 0x4a, 0xae, 0xdb, 0xfb, 0xe6, 0xe0, 0x21, 0x89, + 0x32, 0xad, 0xa2, 0x0e, 0xcb, 0xc0, 0x96, 0xc7, 0x01, 0xc5, 0xf8, 0x3b, 0xee, 0xf8, 0x4c, + 0x6a, + ]; + + let out_pub_x = [ + 0x75, 0x08, 0xb8, 0xfe, 0x7f, 0x1e, 0x44, 0x19, 0x1b, 0x12, 0x4e, 0xd6, 0x11, 0x7b, 0x1d, + 0x0b, 0xce, 0x6d, 0xdc, 0x87, 0xf7, 0x1c, 0x0b, 0xb5, 0x5d, 0x88, 0xb7, 0x1a, 0x48, 0x8d, + 0x1b, 0x19, 0x08, 0x3b, 0x30, 0xbf, 0x42, 0x29, 0x2b, 0x8d, 0xf5, 0xdc, 0xd8, 0x0b, 0x89, + 0xc8, 0x23, 0x6d, + ]; + let out_pub_y = [ + 0xab, 0x30, 0x6a, 0x98, 0xa3, 0x75, 0x2d, 0xaa, 0xd2, 0xfd, 0x72, 0xa9, 0x96, 0x85, 0xf4, + 0xcf, 0xe9, 0x8c, 0xbf, 0x0d, 0x94, 0xab, 0x8d, 0x66, 0x86, 0x5e, 0xba, 0x54, 0x56, 0xba, + 0x19, 0x07, 0x4f, 0xd7, 0xfe, 0x3d, 0xc0, 0xa5, 0x56, 0x77, 0xdf, 0x78, 0xab, 0x89, 0x6a, + 0x02, 0x43, 0xb9, + ]; + + test_kv_hmac(&seed, &data, &out_pub_x, &out_pub_y); +} + /// /// Step 1: /// Key From Key Vault @@ -713,6 +758,7 @@ test_suite! { test_hmac2, test_hmac3, test_hmac4, + test_hmac_kv_multiblock, test_hmac5, test_kdf0, test_kdf1, diff --git a/drivers/test-fw/src/bin/sha384acc_tests.rs b/drivers/test-fw/src/bin/sha2_512_384acc_tests.rs similarity index 50% rename from drivers/test-fw/src/bin/sha384acc_tests.rs rename to drivers/test-fw/src/bin/sha2_512_384acc_tests.rs index 3fe7860266..704f60b104 100644 --- a/drivers/test-fw/src/bin/sha384acc_tests.rs +++ b/drivers/test-fw/src/bin/sha2_512_384acc_tests.rs @@ -4,7 +4,7 @@ Licensed under the Apache-2.0 license. File Name: - sha384_tests.rs + sha2_512_384_tests.rs Abstract: @@ -15,8 +15,10 @@ Abstract: #![no_std] #![no_main] -use caliptra_drivers::{memory_layout, Array4x12, Mailbox, Sha384Acc, ShaAccLockState}; -use caliptra_kat::Sha384AccKat; +use caliptra_drivers::{ + memory_layout, Array4x12, Array4x16, Mailbox, Sha2_512_384Acc, ShaAccLockState, +}; +use caliptra_kat::Sha2_512_384AccKat; use caliptra_registers::mbox::MboxCsr; use caliptra_registers::sha512_acc::Sha512AccCsr; use caliptra_test_harness::test_suite; @@ -24,9 +26,10 @@ use core::slice; const MAX_MAILBOX_CAPACITY_BYTES: usize = 128 << 10; const SHA384_HASH_SIZE: usize = 48; +const SHA512_HASH_SIZE: usize = 64; fn test_digest0() { - let mut sha_acc = unsafe { Sha384Acc::new(Sha512AccCsr::new()) }; + let mut sha_acc = unsafe { Sha2_512_384Acc::new(Sha512AccCsr::new()) }; let mut mbox = unsafe { Mailbox::new(MboxCsr::new()) }; let data = "abcd".as_bytes(); @@ -37,18 +40,43 @@ fn test_digest0() { 0xa3, 0xc7, 0x9b, ]; + let expected_512: [u8; SHA512_HASH_SIZE] = [ + 0xd8, 0x02, 0x2f, 0x20, 0x60, 0xad, 0x6e, 0xfd, 0x29, 0x7a, 0xb7, 0x3d, 0xcc, 0x53, 0x55, + 0xc9, 0xb2, 0x14, 0x05, 0x4b, 0x0d, 0x17, 0x76, 0xa1, 0x36, 0xa6, 0x69, 0xd2, 0x6a, 0x7d, + 0x3b, 0x14, 0xf7, 0x3a, 0xa0, 0xd0, 0xeb, 0xff, 0x19, 0xee, 0x33, 0x33, 0x68, 0xf0, 0x16, + 0x4b, 0x64, 0x19, 0xa9, 0x6d, 0xa4, 0x9e, 0x3e, 0x48, 0x17, 0x53, 0xe7, 0xe9, 0x6b, 0x71, + 0x6b, 0xdc, 0xcb, 0x6f, + ]; + if let Some(mut txn) = mbox.try_start_send_txn() { const CMD: u32 = 0x1c; assert!(txn.send_request(CMD, &data).is_ok()); let mut digest = Array4x12::default(); + let mut digest_512 = Array4x16::default(); + if let Some(mut sha_acc_op) = sha_acc .try_start_operation(ShaAccLockState::NotAcquired) .unwrap() { - let result = sha_acc_op.digest(data.len() as u32, 0, false, (&mut digest).into()); + let result = sha_acc_op.digest_384(data.len() as u32, 0, false, (&mut digest).into()); assert!(result.is_ok()); assert_eq!(digest, Array4x12::from(expected)); + + drop(sha_acc_op); + } else { + assert!(false); + } + + if let Some(mut sha_acc_op) = sha_acc + .try_start_operation(ShaAccLockState::NotAcquired) + .unwrap() + { + let result = + sha_acc_op.digest_512(data.len() as u32, 0, false, (&mut digest_512).into()); + assert!(result.is_ok()); + assert_eq!(digest_512, Array4x16::from(expected_512)); + drop(sha_acc_op); } else { assert!(false); @@ -58,7 +86,7 @@ fn test_digest0() { } fn test_digest1() { - let mut sha_acc = unsafe { Sha384Acc::new(Sha512AccCsr::new()) }; + let mut sha_acc = unsafe { Sha2_512_384Acc::new(Sha512AccCsr::new()) }; let mut mbox = unsafe { Mailbox::new(MboxCsr::new()) }; let data = "abcdefghbcdefghicdefghijdefghijkefghijklfghijklmghijklmnhijklmnoijklmnopjklmnopqklmnopqrlmnopqrsmnopqrstnopqrstu".as_bytes(); @@ -68,19 +96,43 @@ fn test_digest1() { 0xF7, 0x12, 0xFC, 0xC7, 0xC7, 0x1A, 0x55, 0x7E, 0x2D, 0xB9, 0x66, 0xC3, 0xE9, 0xFA, 0x91, 0x74, 0x60, 0x39, ]; + let expected_512: [u8; SHA512_HASH_SIZE] = [ + 0x8e, 0x95, 0x9b, 0x75, 0xda, 0xe3, 0x13, 0xda, 0x8c, 0xf4, 0xf7, 0x28, 0x14, 0xfc, 0x14, + 0x3f, 0x8f, 0x77, 0x79, 0xc6, 0xeb, 0x9f, 0x7f, 0xa1, 0x72, 0x99, 0xae, 0xad, 0xb6, 0x88, + 0x90, 0x18, 0x50, 0x1d, 0x28, 0x9e, 0x49, 0x00, 0xf7, 0xe4, 0x33, 0x1b, 0x99, 0xde, 0xc4, + 0xb5, 0x43, 0x3a, 0xc7, 0xd3, 0x29, 0xee, 0xb6, 0xdd, 0x26, 0x54, 0x5e, 0x96, 0xe5, 0x5b, + 0x87, 0x4b, 0xe9, 0x09, + ]; if let Some(mut txn) = mbox.try_start_send_txn() { const CMD: u32 = 0x1c; assert!(txn.send_request(CMD, &data).is_ok()); let mut digest = Array4x12::default(); + let mut digest_512 = Array4x16::default(); + if let Some(mut sha_acc_op) = sha_acc .try_start_operation(ShaAccLockState::NotAcquired) .unwrap() { - let result = sha_acc_op.digest(data.len() as u32, 0, false, (&mut digest).into()); + let result = sha_acc_op.digest_384(data.len() as u32, 0, false, (&mut digest).into()); assert!(result.is_ok()); assert_eq!(digest, Array4x12::from(expected)); + + drop(sha_acc_op); + } else { + assert!(false); + } + + if let Some(mut sha_acc_op) = sha_acc + .try_start_operation(ShaAccLockState::NotAcquired) + .unwrap() + { + let result = + sha_acc_op.digest_512(data.len() as u32, 0, false, (&mut digest_512).into()); + assert!(result.is_ok()); + assert_eq!(digest_512, Array4x16::from(expected_512)); + drop(sha_acc_op); } else { assert!(false); @@ -90,7 +142,7 @@ fn test_digest1() { } fn test_digest2() { - let mut sha_acc = unsafe { Sha384Acc::new(Sha512AccCsr::new()) }; + let mut sha_acc = unsafe { Sha2_512_384Acc::new(Sha512AccCsr::new()) }; let mut mbox = unsafe { Mailbox::new(MboxCsr::new()) }; let data = "abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwx".as_bytes(); @@ -100,8 +152,16 @@ fn test_digest2() { 0x1b, 0xf3, 0x25, 0xd3, 0xeb, 0x56, 0x82, 0x63, 0xa2, 0xe1, 0xe6, 0x85, 0x6a, 0xc7, 0x50, 0x70, 0x06, 0x2a, ]; + let expected_512: [u8; SHA512_HASH_SIZE] = [ + 0x21, 0x7d, 0x3d, 0x9c, 0x09, 0x52, 0xc3, 0xe4, 0x90, 0x7f, 0x06, 0xd4, 0xfb, 0xf3, 0x44, + 0x60, 0xee, 0x85, 0x2c, 0x6a, 0xf5, 0x91, 0xb0, 0x7c, 0x2f, 0xa1, 0xc5, 0xe1, 0x64, 0x55, + 0x83, 0x63, 0x74, 0xc9, 0x5a, 0xe3, 0x3e, 0x18, 0x42, 0x27, 0x91, 0x3f, 0x8a, 0x2e, 0x22, + 0x7e, 0x3b, 0xbd, 0x51, 0x87, 0xce, 0x57, 0xaa, 0x1b, 0xad, 0x11, 0xa8, 0x0f, 0x62, 0x24, + 0x12, 0xeb, 0x08, 0x84, + ]; let mut digest = Array4x12::default(); + let mut digest_512 = Array4x16::default(); if let Some(mut txn) = mbox.try_start_send_txn() { const CMD: u32 = 0x1c; @@ -111,9 +171,24 @@ fn test_digest2() { .try_start_operation(ShaAccLockState::NotAcquired) .unwrap() { - let result = sha_acc_op.digest(data.len() as u32, 0, false, (&mut digest).into()); + let result = sha_acc_op.digest_384(data.len() as u32, 0, false, (&mut digest).into()); assert!(result.is_ok()); assert_eq!(digest, Array4x12::from(expected)); + + drop(sha_acc_op); + } else { + assert!(false); + } + + if let Some(mut sha_acc_op) = sha_acc + .try_start_operation(ShaAccLockState::NotAcquired) + .unwrap() + { + let result = + sha_acc_op.digest_512(data.len() as u32, 0, false, (&mut digest_512).into()); + assert!(result.is_ok()); + assert_eq!(digest_512, Array4x16::from(expected_512)); + drop(sha_acc_op); } else { assert!(false); @@ -123,7 +198,7 @@ fn test_digest2() { } fn test_digest_offset() { - let mut sha_acc = unsafe { Sha384Acc::new(Sha512AccCsr::new()) }; + let mut sha_acc = unsafe { Sha2_512_384Acc::new(Sha512AccCsr::new()) }; let mut mbox = unsafe { Mailbox::new(MboxCsr::new()) }; let data = "abcdefghijklmnopqrst".as_bytes(); @@ -133,8 +208,16 @@ fn test_digest_offset() { 0xcc, 0x09, 0xe9, 0x4a, 0x84, 0x62, 0x83, 0x56, 0x7d, 0x28, 0xd8, 0xc7, 0x73, 0xc1, 0x87, 0x39, 0x07, 0xa7, ]; + let expected_512: [u8; SHA512_HASH_SIZE] = [ + 0xfb, 0x98, 0x27, 0x30, 0xed, 0x3d, 0x46, 0x8a, 0xe7, 0xbe, 0x25, 0x12, 0x1e, 0x45, 0xcf, + 0x4f, 0x7f, 0x2b, 0xd1, 0xfd, 0xd1, 0x77, 0x14, 0xf0, 0xae, 0x5b, 0x1c, 0xa9, 0x2d, 0x1f, + 0xf3, 0xf2, 0x35, 0x2d, 0x57, 0xc0, 0x8f, 0x88, 0xe9, 0x23, 0xf0, 0x88, 0x06, 0xc6, 0x01, + 0x6c, 0xc6, 0x7b, 0xf5, 0xf0, 0x09, 0x28, 0x27, 0x39, 0xa4, 0xe0, 0x0a, 0xf3, 0xce, 0x8c, + 0xa8, 0xf7, 0x04, 0xca, + ]; let mut digest = Array4x12::default(); + let mut digest_512 = Array4x16::default(); if let Some(mut txn) = mbox.try_start_send_txn() { const CMD: u32 = 0x1c; @@ -144,9 +227,23 @@ fn test_digest_offset() { .try_start_operation(ShaAccLockState::NotAcquired) .unwrap() { - let result = sha_acc_op.digest(8, 4, false, (&mut digest).into()); + let result = sha_acc_op.digest_384(8, 4, false, (&mut digest).into()); assert!(result.is_ok()); assert_eq!(digest, Array4x12::from(expected)); + + drop(sha_acc_op); + } else { + assert!(false); + } + + if let Some(mut sha_acc_op) = sha_acc + .try_start_operation(ShaAccLockState::NotAcquired) + .unwrap() + { + let result = sha_acc_op.digest_512(8, 4, false, (&mut digest_512).into()); + assert!(result.is_ok()); + assert_eq!(digest_512, Array4x16::from(expected_512)); + drop(sha_acc_op); } else { assert!(false); @@ -156,7 +253,7 @@ fn test_digest_offset() { } fn test_digest_zero_size_buffer() { - let mut sha_acc = unsafe { Sha384Acc::new(Sha512AccCsr::new()) }; + let mut sha_acc = unsafe { Sha2_512_384Acc::new(Sha512AccCsr::new()) }; let expected: [u8; SHA384_HASH_SIZE] = [ 0x38, 0xB0, 0x60, 0xA7, 0x51, 0xAC, 0x96, 0x38, 0x4C, 0xD9, 0x32, 0x7E, 0xB1, 0xB1, 0xE3, @@ -164,15 +261,38 @@ fn test_digest_zero_size_buffer() { 0xE1, 0xDA, 0x27, 0x4E, 0xDE, 0xBF, 0xE7, 0x6F, 0x65, 0xFB, 0xD5, 0x1A, 0xD2, 0xF1, 0x48, 0x98, 0xB9, 0x5B, ]; + let expected_512: [u8; SHA512_HASH_SIZE] = [ + 0xcf, 0x83, 0xe1, 0x35, 0x7e, 0xef, 0xb8, 0xbd, 0xf1, 0x54, 0x28, 0x50, 0xd6, 0x6d, 0x80, + 0x07, 0xd6, 0x20, 0xe4, 0x05, 0x0b, 0x57, 0x15, 0xdc, 0x83, 0xf4, 0xa9, 0x21, 0xd3, 0x6c, + 0xe9, 0xce, 0x47, 0xd0, 0xd1, 0x3c, 0x5d, 0x85, 0xf2, 0xb0, 0xff, 0x83, 0x18, 0xd2, 0x87, + 0x7e, 0xec, 0x2f, 0x63, 0xb9, 0x31, 0xbd, 0x47, 0x41, 0x7a, 0x81, 0xa5, 0x38, 0x32, 0x7a, + 0xf9, 0x27, 0xda, 0x3e, + ]; let mut digest = Array4x12::default(); + let mut digest_512 = Array4x16::default(); + if let Some(mut sha_acc_op) = sha_acc .try_start_operation(ShaAccLockState::NotAcquired) .unwrap() { - let result = sha_acc_op.digest(0, 0, true, (&mut digest).into()); + let result = sha_acc_op.digest_384(0, 0, true, (&mut digest).into()); assert!(result.is_ok()); assert_eq!(digest, Array4x12::from(expected)); + + drop(sha_acc_op); + } else { + assert!(false); + }; + + if let Some(mut sha_acc_op) = sha_acc + .try_start_operation(ShaAccLockState::NotAcquired) + .unwrap() + { + let result = sha_acc_op.digest_512(0, 0, true, (&mut digest_512).into()); + assert!(result.is_ok()); + assert_eq!(digest_512, Array4x16::from(expected_512)); + drop(sha_acc_op); } else { assert!(false); @@ -180,7 +300,7 @@ fn test_digest_zero_size_buffer() { } fn test_digest_max_mailbox_size() { - let mut sha_acc = unsafe { Sha384Acc::new(Sha512AccCsr::new()) }; + let mut sha_acc = unsafe { Sha2_512_384Acc::new(Sha512AccCsr::new()) }; let expected: [u8; SHA384_HASH_SIZE] = [ 0xca, 0xd1, 0x95, 0xe7, 0xc3, 0xf2, 0xb2, 0x50, 0xb3, 0x5a, 0xc7, 0x8b, 0x17, 0xb7, 0xc2, @@ -188,6 +308,13 @@ fn test_digest_max_mailbox_size() { 0xf8, 0x5e, 0xc0, 0x40, 0x69, 0x3e, 0x5a, 0x22, 0x21, 0x88, 0x79, 0x77, 0xfd, 0xea, 0x6f, 0x89, 0xef, 0xee, ]; + let expected_512: [u8; SHA512_HASH_SIZE] = [ + 0x4e, 0xd8, 0x3e, 0x40, 0xc9, 0xcf, 0x32, 0xac, 0x2c, 0x59, 0x12, 0x5a, 0x01, 0x17, 0x0b, + 0xc9, 0x7f, 0x20, 0x55, 0x09, 0x52, 0xc8, 0xca, 0x20, 0xff, 0xe1, 0xb2, 0xa5, 0x9d, 0x1b, + 0x1e, 0xd9, 0xc8, 0x42, 0x6c, 0x51, 0x5f, 0x76, 0x29, 0xd1, 0xbb, 0x5e, 0x4c, 0xdc, 0x53, + 0xdd, 0x70, 0xff, 0xcf, 0x67, 0x20, 0x3d, 0x59, 0xe7, 0x0a, 0x55, 0x94, 0x92, 0xe5, 0xff, + 0x0e, 0x71, 0x22, 0x78, + ]; { // Clear the mailbox SRAM; FPGA model doesn't clear this on reset. @@ -205,11 +332,13 @@ fn test_digest_max_mailbox_size() { } let mut digest = Array4x12::default(); + let mut digest_512 = Array4x16::default(); + if let Some(mut sha_acc_op) = sha_acc .try_start_operation(ShaAccLockState::NotAcquired) .unwrap() { - let result = sha_acc_op.digest( + let result = sha_acc_op.digest_384( MAX_MAILBOX_CAPACITY_BYTES as u32, 0, true, @@ -217,6 +346,25 @@ fn test_digest_max_mailbox_size() { ); assert!(result.is_ok()); assert_eq!(digest, Array4x12::from(expected)); + + drop(sha_acc_op); + } else { + assert!(false); + }; + + if let Some(mut sha_acc_op) = sha_acc + .try_start_operation(ShaAccLockState::NotAcquired) + .unwrap() + { + let result = sha_acc_op.digest_512( + MAX_MAILBOX_CAPACITY_BYTES as u32, + 0, + true, + (&mut digest_512).into(), + ); + assert!(result.is_ok()); + assert_eq!(digest_512, Array4x16::from(expected_512)); + drop(sha_acc_op); } else { assert!(false); @@ -224,9 +372,9 @@ fn test_digest_max_mailbox_size() { } fn test_kat() { - let mut sha_acc = unsafe { Sha384Acc::new(Sha512AccCsr::new()) }; + let mut sha_acc = unsafe { Sha2_512_384Acc::new(Sha512AccCsr::new()) }; assert_eq!( - Sha384AccKat::default() + Sha2_512_384AccKat::default() .execute(&mut sha_acc, ShaAccLockState::AssumedLocked) .is_ok(), true diff --git a/drivers/tests/drivers_integration_tests/main.rs b/drivers/tests/drivers_integration_tests/main.rs index 12d0400014..70bec3649e 100644 --- a/drivers/tests/drivers_integration_tests/main.rs +++ b/drivers/tests/drivers_integration_tests/main.rs @@ -740,8 +740,8 @@ fn test_sha384() { } #[test] -fn test_sha384acc() { - run_driver_test(&firmware::driver_tests::SHA384ACC); +fn test_sha2_512_384acc() { + run_driver_test(&firmware::driver_tests::SHA2_512_384ACC); } #[test] diff --git a/error/README.md b/error/README.md index e2791b9298..2d91e4a1fa 100644 --- a/error/README.md +++ b/error/README.md @@ -45,9 +45,9 @@ | Driver | Mailbox | No Data Available Error |0x00080003 | | Driver | Mailbox | Enqueue Error |0x00080004 | | Driver | Mailbox | Dequeue Error |0x00080005 | -| Driver | SHA384Acc | Invalid Op |0x00090001 | -| Driver | SHA384Acc | Max Data Err |0x00090002 | -| Driver | SHA384Acc | Index Out of Bounds |0x00090003 | +| Driver | SHA2_512_384Acc | Invalid Op |0x00090001 | +| Driver | SHA2_512_384Acc | Max Data Err |0x00090002 | +| Driver | SHA2_512_384Acc | Index Out of Bounds |0x00090003 | | Driver | SHA1 | Invalid State Error |0x000A0001 | | Driver | SHA1 | Max Data Error |0x000A0002 | | Driver | SHA1 | Invalid Slice Error |0x000A0003 | diff --git a/error/src/lib.rs b/error/src/lib.rs index b82d566a74..d26f20ed90 100644 --- a/error/src/lib.rs +++ b/error/src/lib.rs @@ -52,8 +52,8 @@ impl CaliptraError { pub const DRIVER_SHA384_INDEX_OUT_OF_BOUNDS: CaliptraError = CaliptraError::new_const(0x0003000B); - /// Driver Error: SHA384ACC - pub const DRIVER_SHA384ACC_UNEXPECTED_ACQUIRED_LOCK_STATE: CaliptraError = + /// Driver Error: SHA2_512_384ACC + pub const DRIVER_SHA2_512_384ACC_UNEXPECTED_ACQUIRED_LOCK_STATE: CaliptraError = CaliptraError::new_const(0x00038000); /// Driver Error: HMAC384 @@ -113,6 +113,7 @@ impl CaliptraError { pub const DRIVER_ECC384_SCALAR_RANGE_CHECK_FAILED: CaliptraError = CaliptraError::new_const(0x0005000f); pub const DRIVER_ECC384_KEYGEN_BAD_USAGE: CaliptraError = CaliptraError::new_const(0x00050010); + pub const DRIVER_ECC384_HW_ERROR: CaliptraError = CaliptraError::new_const(0x00050011); pub const DRIVER_KV_ERASE_USE_LOCK_SET_FAILURE: CaliptraError = CaliptraError::new_const(0x00060001); @@ -129,8 +130,8 @@ impl CaliptraError { pub const DRIVER_MAILBOX_UNCORRECTABLE_ECC: CaliptraError = CaliptraError::new_const(0x00080005); - /// SHA384ACC Errors. - pub const DRIVER_SHA384ACC_INDEX_OUT_OF_BOUNDS: CaliptraError = + /// SHA2_512_384ACC Errors. + pub const DRIVER_SHA2_512_384ACC_INDEX_OUT_OF_BOUNDS: CaliptraError = CaliptraError::new_const(0x00090003); /// SHA1 Errors. pub const DRIVER_SHA1_INVALID_STATE: CaliptraError = CaliptraError::new_const(0x000a0001); @@ -545,10 +546,12 @@ impl CaliptraError { CaliptraError::new_const(0x90040002); pub const KAT_ECC384_SIGNATURE_MISMATCH: CaliptraError = CaliptraError::new_const(0x90040003); - pub const KAT_SHA384_ACC_DIGEST_START_OP_FAILURE: CaliptraError = + pub const KAT_SHA2_512_384_ACC_DIGEST_START_OP_FAILURE: CaliptraError = CaliptraError::new_const(0x90050001); - pub const KAT_SHA384_ACC_DIGEST_FAILURE: CaliptraError = CaliptraError::new_const(0x90050002); - pub const KAT_SHA384_ACC_DIGEST_MISMATCH: CaliptraError = CaliptraError::new_const(0x90050003); + pub const KAT_SHA2_512_384_ACC_DIGEST_FAILURE: CaliptraError = + CaliptraError::new_const(0x90050002); + pub const KAT_SHA2_512_384_ACC_DIGEST_MISMATCH: CaliptraError = + CaliptraError::new_const(0x90050003); pub const KAT_SHA1_DIGEST_FAILURE: CaliptraError = CaliptraError::new_const(0x90060001); pub const KAT_SHA1_DIGEST_MISMATCH: CaliptraError = CaliptraError::new_const(0x90060002); diff --git a/fmc/src/fmc_env.rs b/fmc/src/fmc_env.rs index c499b2ea4e..fe79dca97e 100644 --- a/fmc/src/fmc_env.rs +++ b/fmc/src/fmc_env.rs @@ -17,7 +17,7 @@ Abstract: use caliptra_drivers::{ CaliptraResult, DataVault, Ecc384, Hmac384, KeyVault, Mailbox, PcrBank, PersistentDataAccessor, - Sha1, Sha256, Sha384, Sha384Acc, SocIfc, Trng, + Sha1, Sha256, Sha2_512_384Acc, Sha384, SocIfc, Trng, }; use caliptra_registers::{ csrng::CsrngReg, dv::DvReg, ecc::EccReg, entropy_src::EntropySrcReg, hmac::HmacReg, kv::KvReg, @@ -36,8 +36,8 @@ pub struct FmcEnv { // SHA2-384 Engine pub sha384: Sha384, - // SHA2-384 Accelerator - pub sha384_acc: Sha384Acc, + // SHA2-512/384 Accelerator + pub sha2_512_384_acc: Sha2_512_384Acc, /// Hmac384 Engine pub hmac384: Hmac384, @@ -87,7 +87,7 @@ impl FmcEnv { sha1: Sha1::default(), sha256: Sha256::new(Sha256Reg::new()), sha384: Sha384::new(Sha512Reg::new()), - sha384_acc: Sha384Acc::new(Sha512AccCsr::new()), + sha2_512_384_acc: Sha2_512_384Acc::new(Sha512AccCsr::new()), hmac384: Hmac384::new(HmacReg::new()), ecc384: Ecc384::new(EccReg::new()), key_vault: KeyVault::new(KvReg::new()), diff --git a/hw-model/src/lib.rs b/hw-model/src/lib.rs index 737ef0da88..3a907e7d4d 100644 --- a/hw-model/src/lib.rs +++ b/hw-model/src/lib.rs @@ -991,7 +991,7 @@ pub trait HwModel { // Don't check for mbox_idle() unless the hw-model supports // fine-grained timing control; the firmware may proceed to lock the // mailbox shortly after the mailbox transcation finishes (for example, to - // test the sha384_acc peripheral). + // test the sha2_512_384_acc peripheral). // mbox_fsm_ps isn't updated immediately after execute is cleared (!?), // so step an extra clock cycle to wait for fm_ps to update diff --git a/kat/src/kats_env.rs b/kat/src/kats_env.rs index d503681734..b1385219a4 100644 --- a/kat/src/kats_env.rs +++ b/kat/src/kats_env.rs @@ -1,7 +1,7 @@ // Licensed under the Apache-2.0 license use caliptra_drivers::{ - Ecc384, Hmac384, Lms, Sha1, Sha256, Sha384, Sha384Acc, ShaAccLockState, Trng, + Ecc384, Hmac384, Lms, Sha1, Sha256, Sha2_512_384Acc, Sha384, ShaAccLockState, Trng, }; pub struct KatsEnv<'a> { @@ -14,8 +14,8 @@ pub struct KatsEnv<'a> { // SHA2-384 Engine pub sha384: &'a mut Sha384, - // SHA2-384 Accelerator - pub sha384_acc: &'a mut Sha384Acc, + // SHA2-512/384 Accelerator + pub sha2_512_384_acc: &'a mut Sha2_512_384Acc, /// Hmac384 Engine pub hmac384: &'a mut Hmac384, diff --git a/kat/src/lib.rs b/kat/src/lib.rs index 6af171db5d..f71bc6bce6 100644 --- a/kat/src/lib.rs +++ b/kat/src/lib.rs @@ -20,8 +20,8 @@ mod kats_env; mod lms_kat; mod sha1_kat; mod sha256_kat; +mod sha2_512_384acc_kat; mod sha384_kat; -mod sha384acc_kat; pub use caliptra_drivers::{CaliptraError, CaliptraResult}; pub use ecc384_kat::Ecc384Kat; @@ -30,8 +30,8 @@ pub use kats_env::KatsEnv; pub use lms_kat::LmsKat; pub use sha1_kat::Sha1Kat; pub use sha256_kat::Sha256Kat; +pub use sha2_512_384acc_kat::Sha2_512_384AccKat; pub use sha384_kat::Sha384Kat; -pub use sha384acc_kat::Sha384AccKat; use caliptra_drivers::cprintln; @@ -52,8 +52,8 @@ pub fn execute_kat(env: &mut KatsEnv) -> CaliptraResult<()> { cprintln!("[kat] SHA2-384"); Sha384Kat::default().execute(env.sha384)?; - cprintln!("[kat] SHA2-384-ACC"); - Sha384AccKat::default().execute(env.sha384_acc, env.sha_acc_lock_state)?; + cprintln!("[kat] SHA2-512-ACC"); + Sha2_512_384AccKat::default().execute(env.sha2_512_384_acc, env.sha_acc_lock_state)?; cprintln!("[kat] ECC-384"); Ecc384Kat::default().execute(env.ecc384, env.trng)?; diff --git a/kat/src/sha2_512_384acc_kat.rs b/kat/src/sha2_512_384acc_kat.rs new file mode 100644 index 0000000000..1f8ad5c714 --- /dev/null +++ b/kat/src/sha2_512_384acc_kat.rs @@ -0,0 +1,84 @@ +/*++ + +Licensed under the Apache-2.0 license. + +File Name: + + sha2_512_384acc_kat.rs + +Abstract: + + File contains the Known Answer Tests (KAT) for SHA512 accelerator cryptography operations. + +--*/ +use caliptra_drivers::{ + Array4x16, CaliptraError, CaliptraResult, Sha2_512_384Acc, ShaAccLockState, +}; + +const SHA512_EXPECTED_DIGEST: Array4x16 = Array4x16::new([ + 0xcf83e135, 0x7eefb8bd, 0xf1542850, 0xd66d8007, 0xd620e405, 0x0b5715dc, 0x83f4a921, 0xd36ce9ce, + 0x47d0d13c, 0x5d85f2b0, 0xff8318d2, 0x877eec2f, 0x63b931bd, 0x47417a81, 0xa538327a, 0xf927da3e, +]); + +#[derive(Default)] +pub struct Sha2_512_384AccKat {} + +impl Sha2_512_384AccKat { + /// This function executes the Known Answer Tests (aka KAT) for SHA512ACC. + /// Performing this test for SHA512 mode also covers SHA384 + /// + /// Test vector source: + /// https://csrc.nist.gov/CSRC/media/Projects/Cryptographic-Algorithm-Validation-Program/documents/shs/shabytetestvectors.zip + /// + /// # Arguments + /// + /// * `sha_acc` - SHA2-384 Accelerator Driver + /// * `lock_state` - SHA Acc Lock State + /// + /// # Returns + /// + /// * `CaliptraResult` - Result denoting the KAT outcome. + pub fn execute( + &self, + sha_acc: &mut Sha2_512_384Acc, + lock_state: ShaAccLockState, + ) -> CaliptraResult<()> { + self.kat_no_data(sha_acc, lock_state)?; + Ok(()) + } + + fn kat_no_data( + &self, + sha_acc: &mut Sha2_512_384Acc, + lock_state: ShaAccLockState, + ) -> CaliptraResult<()> { + let mut digest = Array4x16::default(); + + if let Some(mut sha_acc_op) = sha_acc.try_start_operation(lock_state)? { + let result = || -> CaliptraResult<()> { + // SHA 512 + sha_acc_op + .digest_512(0, 0, false, &mut digest) + .map_err(|_| CaliptraError::KAT_SHA2_512_384_ACC_DIGEST_FAILURE)?; + if digest != SHA512_EXPECTED_DIGEST { + Err(CaliptraError::KAT_SHA2_512_384_ACC_DIGEST_MISMATCH)?; + } + + Ok(()) + }(); + + // If error, don't drop the operation since that will unlock the + // peripheral for SoC use, which we're not allowed to do if the + // KAT doesn't pass. + if result.is_err() { + caliptra_drivers::cprintln!("Droping operation"); + core::mem::forget(sha_acc_op); + } + result?; + } else { + Err(CaliptraError::KAT_SHA2_512_384_ACC_DIGEST_START_OP_FAILURE)?; + }; + + Ok(()) + } +} diff --git a/kat/src/sha384acc_kat.rs b/kat/src/sha384acc_kat.rs deleted file mode 100644 index 9f221cd188..0000000000 --- a/kat/src/sha384acc_kat.rs +++ /dev/null @@ -1,67 +0,0 @@ -/*++ - -Licensed under the Apache-2.0 license. - -File Name: - - sha384acc_kat.rs - -Abstract: - - File contains the Known Answer Tests (KAT) for SHA384 accelerator cryptography operations. - ---*/ -use crate::sha384_kat::SHA384_EXPECTED_DIGEST; -use caliptra_drivers::{Array4x12, CaliptraError, CaliptraResult, Sha384Acc, ShaAccLockState}; - -#[derive(Default)] -pub struct Sha384AccKat {} - -impl Sha384AccKat { - /// This function executes the Known Answer Tests (aka KAT) for SHA384ACC. - /// - /// Test vector source: - /// https://csrc.nist.gov/CSRC/media/Projects/Cryptographic-Algorithm-Validation-Program/documents/shs/shabytetestvectors.zip - /// - /// # Arguments - /// - /// * `sha_acc` - SHA2-384 Accelerator Driver - /// * `lock_state` - SHA Acc Lock State - /// - /// # Returns - /// - /// * `CaliptraResult` - Result denoting the KAT outcome. - pub fn execute( - &self, - sha_acc: &mut Sha384Acc, - lock_state: ShaAccLockState, - ) -> CaliptraResult<()> { - self.kat_no_data(sha_acc, lock_state)?; - Ok(()) - } - - fn kat_no_data( - &self, - sha_acc: &mut Sha384Acc, - lock_state: ShaAccLockState, - ) -> CaliptraResult<()> { - let mut digest = Array4x12::default(); - - if let Some(mut sha_acc_op) = sha_acc.try_start_operation(lock_state)? { - sha_acc_op - .digest(0, 0, false, &mut digest) - .map_err(|_| CaliptraError::KAT_SHA384_ACC_DIGEST_FAILURE)?; - if digest != SHA384_EXPECTED_DIGEST { - // Don't drop the operation, since that will unlock the - // peripheral for SoC use, which we're not allowed to do if the - // KAT doesn't pass. - core::mem::forget(sha_acc_op); - Err(CaliptraError::KAT_SHA384_ACC_DIGEST_MISMATCH)?; - } - } else { - Err(CaliptraError::KAT_SHA384_ACC_DIGEST_START_OP_FAILURE)?; - } - - Ok(()) - } -} diff --git a/rom/dev/doc/error-attribution.md b/rom/dev/doc/error-attribution.md index 4571d8b073..2ab9b22050 100644 --- a/rom/dev/doc/error-attribution.md +++ b/rom/dev/doc/error-attribution.md @@ -52,7 +52,7 @@ Mailbox Driver | DRIVER_MAILBOX_INVALID_STATE | 0x00080001 Mailbox Driver | DRIVER_MAILBOX_INVALID_DATA_LEN | 0x00080002 Mailbox Driver | DRIVER_MAILBOX_ENQUEUE_ERR | 0x00080004
-Sha384 Accelerator Driver | DRIVER_SHA384ACC_INDEX_OUT_OF_BOUNDS | 0x00090003 +Sha2-512/384 Accelerator Driver | DRIVER_SHA2_512_384ACC_INDEX_OUT_OF_BOUNDS | 0x00090003
Sha1 Driver | DRIVER_SHA1_INVALID_STATE | 0x000a0001 Sha1 Driver | DRIVER_SHA1_MAX_DATA | 0x000a0002 @@ -159,9 +159,9 @@ KAT | KAT_HMAC384_TAG_MISMATCH | 0x90030002 KAT | KAT_ECC384_SIGNATURE_GENERATE_FAILURE | 0x90040001 KAT | KAT_ECC384_SIGNATURE_VERIFY_FAILURE | 0x90040002 KAT | KAT_ECC384_SIGNATURE_MISMATCH | 0x90040003 -KAT | KAT_SHA384_ACC_DIGEST_START_OP_FAILURE | 0x90050001 -KAT | KAT_SHA384_ACC_DIGEST_FAILURE | 0x90050002 -KAT | KAT_SHA384_ACC_DIGEST_MISMATCH | 0x90050003 +KAT | KAT_SHA2_512_384_ACC_DIGEST_START_OP_FAILURE | 0x90050001 +KAT | KAT_SHA2_512_384_ACC_DIGEST_FAILURE | 0x90050002 +KAT | KAT_SHA2_515_384_ACC_DIGEST_MISMATCH | 0x90050003 KAT | KAT_SHA1_DIGEST_FAILURE | 0x90060001 KAT | KAT_SHA1_DIGEST_MISMATCH | 0x90060002 KAT | KAT_LMS_DIGEST_FAILURE | 0x90070001 diff --git a/rom/dev/src/flow/cold_reset/fw_processor.rs b/rom/dev/src/flow/cold_reset/fw_processor.rs index 92c249b0e9..5d0a2e87ea 100644 --- a/rom/dev/src/flow/cold_reset/fw_processor.rs +++ b/rom/dev/src/flow/cold_reset/fw_processor.rs @@ -65,8 +65,8 @@ impl FirmwareProcessor { // SHA2-384 Engine sha384: &mut env.sha384, - // SHA2-384 Accelerator - sha384_acc: &mut env.sha384_acc, + // SHA2-512/384 Accelerator + sha2_512_384_acc: &mut env.sha2_512_384_acc, // Hmac384 Engine hmac384: &mut env.hmac384, diff --git a/rom/dev/src/flow/fake.rs b/rom/dev/src/flow/fake.rs index 819be5906a..57dd203d53 100644 --- a/rom/dev/src/flow/fake.rs +++ b/rom/dev/src/flow/fake.rs @@ -158,7 +158,7 @@ impl FakeRomFlow { // Unlock the SHA Acc by creating a SHA Acc operation and dropping it. // In real ROM, this is done as part of executing the SHA-ACC KAT. let sha_op = env - .sha384_acc + .sha2_512_384_acc .try_start_operation(ShaAccLockState::AssumedLocked)? .unwrap(); drop(sha_op); diff --git a/rom/dev/src/main.rs b/rom/dev/src/main.rs index c357fb050e..007f4adb5d 100644 --- a/rom/dev/src/main.rs +++ b/rom/dev/src/main.rs @@ -25,8 +25,8 @@ use core::hint::black_box; use caliptra_drivers::{ cprintln, report_boot_status, report_fw_error_fatal, report_fw_error_non_fatal, CaliptraError, - Ecc384, Hmac384, KeyVault, Mailbox, ResetReason, Sha256, Sha384, Sha384Acc, ShaAccLockState, - SocIfc, Trng, + Ecc384, Hmac384, KeyVault, Mailbox, ResetReason, Sha256, Sha2_512_384Acc, Sha384, + ShaAccLockState, SocIfc, Trng, }; use caliptra_error::CaliptraResult; use caliptra_image_types::RomInfo; @@ -130,8 +130,8 @@ pub extern "C" fn rom_entry() -> ! { // SHA2-384 Engine sha384: &mut env.sha384, - // SHA2-384 Accelerator - sha384_acc: &mut env.sha384_acc, + // SHA2-512/384 Accelerator + sha2_512_384_acc: &mut env.sha2_512_384_acc, // Hmac384 Engine hmac384: &mut env.hmac384, @@ -349,7 +349,7 @@ fn handle_fatal_error(code: u32) -> ! { Hmac384::zeroize(); Sha256::zeroize(); Sha384::zeroize(); - Sha384Acc::zeroize(); + Sha2_512_384Acc::zeroize(); // Zeroize the key vault. KeyVault::zeroize(); @@ -371,7 +371,7 @@ fn handle_fatal_error(code: u32) -> ! { // // WDT is disabled at this point so there is no issue // of it firing due to the lock taking too long. - Sha384Acc::try_lock(); + Sha2_512_384Acc::try_lock(); } } } diff --git a/rom/dev/src/rom_env.rs b/rom/dev/src/rom_env.rs index bb6287462b..e067aef06c 100644 --- a/rom/dev/src/rom_env.rs +++ b/rom/dev/src/rom_env.rs @@ -18,7 +18,7 @@ Abstract: use crate::fht::FhtDataStore; use caliptra_drivers::{ DataVault, DeobfuscationEngine, Ecc384, Hmac384, KeyVault, Lms, Mailbox, PcrBank, - PersistentDataAccessor, Sha1, Sha256, Sha384, Sha384Acc, SocIfc, Trng, + PersistentDataAccessor, Sha1, Sha256, Sha2_512_384Acc, Sha384, SocIfc, Trng, }; use caliptra_error::CaliptraResult; use caliptra_registers::{ @@ -41,8 +41,8 @@ pub struct RomEnv { // SHA2-384 Engine pub sha384: Sha384, - // SHA2-384 Accelerator - pub sha384_acc: Sha384Acc, + // SHA2-512/384 Accelerator + pub sha2_512_384_acc: Sha2_512_384Acc, /// Hmac384 Engine pub hmac384: Hmac384, @@ -92,7 +92,7 @@ impl RomEnv { sha1: Sha1::default(), sha256: Sha256::new(Sha256Reg::new()), sha384: Sha384::new(Sha512Reg::new()), - sha384_acc: Sha384Acc::new(Sha512AccCsr::new()), + sha2_512_384_acc: Sha2_512_384Acc::new(Sha512AccCsr::new()), hmac384: Hmac384::new(HmacReg::new()), ecc384: Ecc384::new(EccReg::new()), lms: Lms::default(), diff --git a/runtime/src/drivers.rs b/runtime/src/drivers.rs index 09d3156dda..a761b2d922 100644 --- a/runtime/src/drivers.rs +++ b/runtime/src/drivers.rs @@ -32,8 +32,8 @@ use caliptra_drivers::{ DataVault, Ecc384, KeyVault, Lms, PersistentDataAccessor, Pic, ResetReason, Sha1, SocIfc, }; use caliptra_drivers::{ - hand_off::DataStore, Ecc384PubKey, Hmac384, PcrBank, PcrId, Sha256, Sha256Alg, Sha384, - Sha384Acc, Trng, + hand_off::DataStore, Ecc384PubKey, Hmac384, PcrBank, PcrId, Sha256, Sha256Alg, Sha2_512_384Acc, + Sha384, Trng, }; use caliptra_image_types::ImageManifest; use caliptra_registers::el2_pic_ctrl::El2PicCtrl; @@ -71,8 +71,8 @@ pub struct Drivers { // SHA2-384 Engine pub sha384: Sha384, - // SHA2-384 Accelerator - pub sha384_acc: Sha384Acc, + // SHA2-512/384 Accelerator + pub sha2_512_384_acc: Sha2_512_384Acc, /// Hmac384 Engine pub hmac384: Hmac384, @@ -123,7 +123,7 @@ impl Drivers { soc_ifc: SocIfc::new(SocIfcReg::new()), sha256: Sha256::new(Sha256Reg::new()), sha384: Sha384::new(Sha512Reg::new()), - sha384_acc: Sha384Acc::new(Sha512AccCsr::new()), + sha2_512_384_acc: Sha2_512_384Acc::new(Sha512AccCsr::new()), hmac384: Hmac384::new(HmacReg::new()), ecc384: Ecc384::new(EccReg::new()), sha1: Sha1::default(), diff --git a/runtime/src/fips.rs b/runtime/src/fips.rs index 9db9a51d31..d00d07cd89 100644 --- a/runtime/src/fips.rs +++ b/runtime/src/fips.rs @@ -20,8 +20,8 @@ use caliptra_drivers::Ecc384; use caliptra_drivers::Hmac384; use caliptra_drivers::KeyVault; use caliptra_drivers::Sha256; +use caliptra_drivers::Sha2_512_384Acc; use caliptra_drivers::Sha384; -use caliptra_drivers::Sha384Acc; use caliptra_registers::mbox::enums::MboxStatusE; use zeroize::Zeroize; @@ -41,13 +41,13 @@ impl FipsModule { Hmac384::zeroize(); Sha256::zeroize(); Sha384::zeroize(); - Sha384Acc::zeroize(); + Sha2_512_384Acc::zeroize(); // Zeroize the key vault. KeyVault::zeroize(); // Lock the SHA Accelerator. - Sha384Acc::lock(); + Sha2_512_384Acc::lock(); } env.persistent_data.get_mut().zeroize(); } @@ -148,8 +148,8 @@ pub mod fips_self_test_cmd { // SHA2-384 Engine sha384: &mut env.sha384, - // SHA2-384 Accelerator - sha384_acc: &mut env.sha384_acc, + // SHA2-512/384 Accelerator + sha2_512_384_acc: &mut env.sha2_512_384_acc, // Hmac384 Engine hmac384: &mut env.hmac384, diff --git a/runtime/tests/runtime_integration_tests/test_ecdsa.rs b/runtime/tests/runtime_integration_tests/test_ecdsa.rs index b5dbc229bf..c3b646e23c 100644 --- a/runtime/tests/runtime_integration_tests/test_ecdsa.rs +++ b/runtime/tests/runtime_integration_tests/test_ecdsa.rs @@ -248,3 +248,32 @@ fn test_ecdsa_verify_bad_chksum() { resp, ); } + +// HW errors are not supported on the SW emulator yet +#[cfg(any(feature = "verilator", feature = "fpga_realtime"))] +#[test] +fn test_ecdsa_hw_failure() { + let mut model = run_rt_test(None, None, None); + + let mut cmd = MailboxReq::EcdsaVerify(EcdsaVerifyReq { + hdr: MailboxReqHeader { chksum: 0 }, + pub_key_x: [0u8; 48], + pub_key_y: [0u8; 48], + signature_r: [0xa5u8; 48], + signature_s: [0xa5u8; 48], + }); + cmd.populate_chksum().unwrap(); + + let resp = model + .mailbox_execute( + u32::from(CommandId::ECDSA384_VERIFY), + cmd.as_bytes().unwrap(), + ) + .unwrap_err(); + + assert_error( + &mut model, + caliptra_drivers::CaliptraError::DRIVER_ECC384_HW_ERROR, + resp, + ); +} diff --git a/sw-emulator/lib/periph/src/asym_ecc384.rs b/sw-emulator/lib/periph/src/asym_ecc384.rs index c715565837..859890a200 100644 --- a/sw-emulator/lib/periph/src/asym_ecc384.rs +++ b/sw-emulator/lib/periph/src/asym_ecc384.rs @@ -204,6 +204,14 @@ pub struct AsymEcc384 { #[register(offset = 0x0000_0614)] key_write_status: ReadOnlyRegister, + /// Error Global Intr register + #[register(offset = 0x0000_080c)] + error_global_intr: ReadOnlyRegister, + + /// Error Internal Intr register + #[register(offset = 0x0000_0814)] + error_internal_intr: ReadOnlyRegister, + /// Key Vault key_vault: KeyVault, @@ -272,6 +280,8 @@ impl AsymEcc384 { op_key_read_complete_action: None, op_seed_read_complete_action: None, op_key_write_complete_action: None, + error_global_intr: ReadOnlyRegister::new(0), + error_internal_intr: ReadOnlyRegister::new(0), } } diff --git a/sw-emulator/lib/periph/src/sha512_acc.rs b/sw-emulator/lib/periph/src/sha512_acc.rs index 113db939ad..2f06b046db 100644 --- a/sw-emulator/lib/periph/src/sha512_acc.rs +++ b/sw-emulator/lib/periph/src/sha512_acc.rs @@ -50,7 +50,7 @@ register_bitfields! [ SHA512_ACC_MODE_SHA_STREAM_384 = 0, SHA512_ACC_MODE_SHA_STREAM_512 = 1, SHA512_ACC_MODE_MBOX_384 = 2, - SHA512_ACC_MODE_SHA_MBOX_512 = 3, + SHA512_ACC_MODE_MBOX_512 = 3, ], ENDIAN_TOGGLE OFFSET(2) NUMBITS(1) [], RSVD OFFSET(3) NUMBITS(29) [], @@ -351,7 +351,9 @@ impl Sha512AcceleratorRegs { if self.execute.reg.read(Execute::EXECUTE) == 1 { let mode = self.mode.reg.read(ShaMode::MODE); - if mode == ShaMode::MODE::SHA512_ACC_MODE_MBOX_384.value { + if mode == ShaMode::MODE::SHA512_ACC_MODE_MBOX_384.value + || mode == ShaMode::MODE::SHA512_ACC_MODE_MBOX_512.value + { self.compute_mbox_hash(); // Schedule a future call to poll() complete the operation. @@ -437,7 +439,15 @@ impl Sha512AcceleratorRegs { block_arr[totalbytes - 16..].copy_from_slice(&len.to_be_bytes()); block_arr.to_big_endian(); - let mut sha = Sha512::new(Sha512Mode::Sha384); + // Set mode based on the mode reg (default to 384) + let mode = + if self.mode.reg.read(ShaMode::MODE) == ShaMode::MODE::SHA512_ACC_MODE_MBOX_512.value { + Sha512Mode::Sha512 + } else { + Sha512Mode::Sha384 + }; + + let mut sha = Sha512::new(mode); for block_count in 0..totalblocks { sha.update(array_ref![ block_arr, @@ -638,7 +648,7 @@ mod tests { const OFFSET_EXECUTE: RvAddr = 0x18; const OFFSET_STATUS: RvAddr = 0x1c; - fn test_sha_accelerator(data: &[u8], expected: &[u8], start_address: usize) { + fn test_sha_accelerator(data: &[u8], expected: &[u8], start_address: usize, sha_mode: u32) { // Write to the mailbox. let mut mb_ram = MailboxRam::new(); if !data.is_empty() { @@ -676,10 +686,7 @@ mod tests { // Set the mode. let mode = InMemoryRegister::::new(0); - mode.write( - ShaMode::MODE.val(ShaMode::MODE::SHA512_ACC_MODE_MBOX_384.value) - + ShaMode::ENDIAN_TOGGLE.val(1), - ); + mode.write(ShaMode::MODE.val(sha_mode) + ShaMode::ENDIAN_TOGGLE.val(1)); assert_eq!( sha_accl.write(RvSize::Word, OFFSET_MODE, mode.get()).ok(), Some(()) @@ -736,7 +743,13 @@ mod tests { assert_eq!(sha_accl.write(RvSize::Word, OFFSET_LOCK, 1).ok(), Some(())); hash.to_little_endian(); - assert_eq!(&hash[..SHA384_HASH_SIZE], expected); + // Choose length based on mode, default to 512 + let digest_length = if sha_mode == ShaMode::MODE::SHA512_ACC_MODE_MBOX_384.value { + SHA384_HASH_SIZE + } else { + SHA512_HASH_SIZE + }; + assert_eq!(&hash[..digest_length], expected); } #[test] @@ -748,7 +761,12 @@ mod tests { 0x43, 0xFF, 0x5B, 0xED, 0x80, 0x86, 0x07, 0x2B, 0xA1, 0xE7, 0xCC, 0x23, 0x58, 0xBA, 0xEC, 0xA1, 0x34, 0xC8, 0x25, 0xA7, ]; - test_sha_accelerator(data, &expected, 0); + test_sha_accelerator( + data, + &expected, + 0, + ShaMode::MODE::SHA512_ACC_MODE_MBOX_384.value, + ); } #[test] @@ -760,7 +778,12 @@ mod tests { 0x5B, 0x1F, 0xE3, 0xC8, 0x45, 0x2B, ]; let data = "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq".as_bytes(); - test_sha_accelerator(data, &expected, 0); + test_sha_accelerator( + data, + &expected, + 0, + ShaMode::MODE::SHA512_ACC_MODE_MBOX_384.value, + ); } #[test] @@ -772,7 +795,12 @@ mod tests { 0xE9, 0xFA, 0x91, 0x74, 0x60, 0x39, ]; let data = "abcdefghbcdefghicdefghijdefghijkefghijklfghijklmghijklmnhijklmnoijklmnopjklmnopqklmnopqrlmnopqrsmnopqrstnopqrstu".as_bytes(); - test_sha_accelerator(data, &expected, 0); + test_sha_accelerator( + data, + &expected, + 0, + ShaMode::MODE::SHA512_ACC_MODE_MBOX_384.value, + ); } #[test] @@ -784,7 +812,12 @@ mod tests { 0x53, 0x98, 0x4a, 0xb0, 0x01, 0x4e, ]; let data = "abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefgh".as_bytes(); - test_sha_accelerator(data, &expected, 0); + test_sha_accelerator( + data, + &expected, + 0, + ShaMode::MODE::SHA512_ACC_MODE_MBOX_384.value, + ); } #[test] @@ -796,7 +829,12 @@ mod tests { 0xa3, 0x59, 0x14, 0xfc, 0x1e, 0xcd, ]; let data = "abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyz".as_bytes(); - test_sha_accelerator(data, &expected, 0); + test_sha_accelerator( + data, + &expected, + 0, + ShaMode::MODE::SHA512_ACC_MODE_MBOX_384.value, + ); } #[test] @@ -808,9 +846,15 @@ mod tests { 0x5B, 0x1F, 0xE3, 0xC8, 0x45, 0x2B, ]; let data = "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq".as_bytes(); - test_sha_accelerator(data, &expected, 4); + test_sha_accelerator( + data, + &expected, + 4, + ShaMode::MODE::SHA512_ACC_MODE_MBOX_384.value, + ); } + // SHA512 test vectors taken from https://csrc.nist.gov/CSRC/media/Projects/Cryptographic-Algorithm-Validation-Program/documents/shs/shabytetestvectors.zip #[test] fn test_accelerator_sha384_no_data() { let expected: [u8; SHA384_HASH_SIZE] = [ @@ -820,7 +864,12 @@ mod tests { 0xD2, 0xF1, 0x48, 0x98, 0xB9, 0x5B, ]; let data = []; - test_sha_accelerator(&data, &expected, 0); + test_sha_accelerator( + &data, + &expected, + 0, + ShaMode::MODE::SHA512_ACC_MODE_MBOX_384.value, + ); } #[test] @@ -832,7 +881,174 @@ mod tests { 0xfd, 0xea, 0x6f, 0x89, 0xef, 0xee, ]; let data: [u8; MAX_MAILBOX_CAPACITY_BYTES] = [0u8; MAX_MAILBOX_CAPACITY_BYTES]; - test_sha_accelerator(&data, &expected, 0); + test_sha_accelerator( + &data, + &expected, + 0, + ShaMode::MODE::SHA512_ACC_MODE_MBOX_384.value, + ); + } + + #[test] + fn test_accelerator_sha512_1() { + let expected: [u8; SHA512_HASH_SIZE] = [ + 0x55, 0x58, 0x6e, 0xbb, 0xa4, 0x87, 0x68, 0xae, 0xb3, 0x23, 0x65, 0x5a, 0xb6, 0xf4, + 0x29, 0x8f, 0xc9, 0xf6, 0x70, 0x96, 0x4f, 0xc2, 0xe5, 0xf2, 0x73, 0x1e, 0x34, 0xdf, + 0xa4, 0xb0, 0xc0, 0x9e, 0x6e, 0x1e, 0x12, 0xe3, 0xd7, 0x28, 0x6b, 0x31, 0x45, 0xc6, + 0x1c, 0x20, 0x47, 0xfb, 0x1a, 0x2a, 0x12, 0x97, 0xf3, 0x6d, 0xa6, 0x41, 0x60, 0xb3, + 0x1f, 0xa4, 0xc8, 0xc2, 0xcd, 0xdd, 0x2f, 0xb4, + ]; + let data = [0x90, 0x83]; + test_sha_accelerator( + &data, + &expected, + 4, + ShaMode::MODE::SHA512_ACC_MODE_MBOX_512.value, + ); + } + + #[test] + fn test_accelerator_sha512_2() { + let expected: [u8; SHA512_HASH_SIZE] = [ + 0xd3, 0x9e, 0xce, 0xdf, 0xe6, 0xe7, 0x05, 0xa8, 0x21, 0xae, 0xe4, 0xf5, 0x8b, 0xfc, + 0x48, 0x9c, 0x3d, 0x94, 0x33, 0xeb, 0x4a, 0xc1, 0xb0, 0x3a, 0x97, 0xe3, 0x21, 0xa2, + 0x58, 0x6b, 0x40, 0xdd, 0x05, 0x22, 0xf4, 0x0f, 0xa5, 0xae, 0xf3, 0x6a, 0xff, 0xf5, + 0x91, 0xa7, 0x8c, 0x91, 0x6b, 0xfc, 0x6d, 0x1c, 0xa5, 0x15, 0xc4, 0x98, 0x3d, 0xd8, + 0x69, 0x5b, 0x1e, 0xc7, 0x95, 0x1d, 0x72, 0x3e, + ]; + let data = [0xeb, 0x0c, 0xa9, 0x46, 0xc1]; + test_sha_accelerator( + &data, + &expected, + 4, + ShaMode::MODE::SHA512_ACC_MODE_MBOX_512.value, + ); + } + + #[test] + fn test_accelerator_sha512_3() { + let expected: [u8; SHA512_HASH_SIZE] = [ + 0xa3, 0x94, 0x1d, 0xef, 0x28, 0x03, 0xc8, 0xdf, 0xc0, 0x8f, 0x20, 0xc0, 0x6b, 0xa7, + 0xe9, 0xa3, 0x32, 0xae, 0x0c, 0x67, 0xe4, 0x7a, 0xe5, 0x73, 0x65, 0xc2, 0x43, 0xef, + 0x40, 0x05, 0x9b, 0x11, 0xbe, 0x22, 0xc9, 0x1d, 0xa6, 0xa8, 0x0c, 0x2c, 0xff, 0x07, + 0x42, 0xa8, 0xf4, 0xbc, 0xd9, 0x41, 0xbd, 0xee, 0x0b, 0x86, 0x1e, 0xc8, 0x72, 0xb2, + 0x15, 0x43, 0x3c, 0xe8, 0xdc, 0xf3, 0xc0, 0x31, + ]; + let data = [0x6f, 0x8d, 0x58, 0xb7, 0xca, 0xb1, 0x88, 0x8c]; + test_sha_accelerator( + &data, + &expected, + 4, + ShaMode::MODE::SHA512_ACC_MODE_MBOX_512.value, + ); + } + + #[test] + fn test_accelerator_sha512_4() { + let expected: [u8; SHA512_HASH_SIZE] = [ + 0x29, 0x9e, 0x0d, 0xaf, 0x66, 0x05, 0xe5, 0xb0, 0xc3, 0x0e, 0x1e, 0xc8, 0xbb, 0x98, + 0xe7, 0xa3, 0xbd, 0x7b, 0x33, 0xb3, 0x88, 0xbd, 0xb4, 0x57, 0x45, 0x2d, 0xab, 0x50, + 0x95, 0x94, 0x40, 0x6c, 0x8e, 0x7b, 0x84, 0x1e, 0x6f, 0x4e, 0x75, 0xc8, 0xd6, 0xfb, + 0xd6, 0x14, 0xd5, 0xeb, 0x9e, 0x56, 0xc3, 0x59, 0xbf, 0xaf, 0xb4, 0x28, 0x57, 0x54, + 0x78, 0x7a, 0xb7, 0x2b, 0x46, 0xdd, 0x33, 0xf0, + ]; + let data = [ + 0x3e, 0xdf, 0x93, 0x25, 0x13, 0x49, 0xd2, 0x28, 0x06, 0xbe, 0xd2, 0x53, 0x45, 0xfd, + 0x5c, 0x19, 0x0a, 0xac, 0x96, 0xd6, 0xcd, 0xb2, 0xd7, 0x58, 0xb8, + ]; + test_sha_accelerator( + &data, + &expected, + 4, + ShaMode::MODE::SHA512_ACC_MODE_MBOX_512.value, + ); + } + + #[test] + fn test_accelerator_sha512_5() { + let expected: [u8; SHA512_HASH_SIZE] = [ + 0xcb, 0xf1, 0xea, 0x86, 0xfa, 0x5b, 0x3d, 0xbf, 0x67, 0xbe, 0x82, 0xfa, 0xc4, 0x1e, + 0x84, 0xcc, 0xcd, 0x0d, 0x29, 0x6c, 0x75, 0x71, 0x69, 0xb3, 0x78, 0x37, 0xd2, 0x73, + 0xcc, 0xc0, 0x15, 0xee, 0xcd, 0x10, 0x2b, 0x9c, 0xe1, 0xcf, 0xf6, 0x8f, 0xdc, 0x7f, + 0x05, 0xd2, 0x2f, 0x2b, 0x77, 0x47, 0x34, 0xf6, 0x2d, 0xed, 0x54, 0xc8, 0xee, 0x0b, + 0xf5, 0x7a, 0x5a, 0x82, 0x01, 0x0d, 0x74, 0xf5, + ]; + let data = [ + 0x1c, 0x5d, 0xc0, 0xd1, 0xdd, 0x2e, 0x4c, 0x71, 0x76, 0x35, 0xff, 0x3e, 0x9b, 0x67, + 0xca, 0xf9, 0x57, 0xae, 0xc0, 0xf8, 0xf6, 0x3c, 0x1b, 0x1e, 0x22, 0x1e, 0x80, 0x0a, + 0x4c, 0x14, 0x84, 0x8f, 0x4e, 0xa0, 0x6e, 0x64, 0x4e, 0x5d, 0x3e, 0x1d, 0xe5, 0x92, + 0xef, 0x5a, 0x80, 0x07, 0xfa, 0x3f, 0x07, 0x17, 0x1b, 0x24, 0xbd, 0x07, 0x57, 0x8d, + 0x68, 0x96, 0x3e, 0x5c, 0xb1, + ]; + test_sha_accelerator( + &data, + &expected, + 4, + ShaMode::MODE::SHA512_ACC_MODE_MBOX_512.value, + ); + } + + #[test] + fn test_accelerator_sha512_6() { + let expected: [u8; SHA512_HASH_SIZE] = [ + 0x98, 0x2d, 0xc6, 0x1c, 0x91, 0xa9, 0x37, 0x70, 0x58, 0x2e, 0xee, 0x80, 0x25, 0xaa, + 0x55, 0xda, 0x8e, 0x9e, 0xdb, 0x96, 0x6b, 0xf5, 0xcf, 0x70, 0xd4, 0xa6, 0x53, 0x4c, + 0x0d, 0x53, 0xa2, 0x78, 0x9a, 0x8c, 0x4f, 0xb6, 0x5b, 0x7f, 0xed, 0x47, 0x8c, 0xda, + 0x02, 0xed, 0x1e, 0x0d, 0x19, 0x8d, 0x85, 0xc5, 0xc7, 0x35, 0xb2, 0x41, 0x7c, 0x5f, + 0xab, 0x5d, 0x34, 0xe9, 0x69, 0xfc, 0x8e, 0x7e, + ]; + let data = [ + 0x56, 0xd1, 0x8d, 0x3e, 0x2e, 0x49, 0x64, 0x40, 0xd0, 0xa5, 0xc9, 0xe1, 0xbc, 0xb4, + 0x64, 0xfa, 0xf5, 0xbc, 0x70, 0xa8, 0xb5, 0x62, 0x12, 0x4f, 0x5f, 0xc9, 0xe9, 0xde, + 0xb5, 0xfe, 0xe6, 0x54, 0x4b, 0x94, 0x5e, 0x83, 0x3b, 0x8b, 0x5d, 0x13, 0x1b, 0x77, + 0x3e, 0xcb, 0x2c, 0xdd, 0x78, 0x0c, 0xd4, 0xe1, 0xbb, 0x9e, 0x4f, 0x1e, 0x3c, 0xb0, + 0xa1, 0xd6, 0x4d, 0x19, 0xcf, 0x4b, 0x30, 0xe4, 0x4e, 0x6c, 0x2d, 0x0c, 0xbc, 0xb4, + 0xe2, 0x84, 0xce, 0x50, 0xdb, 0x7a, 0x8a, 0x80, 0x62, 0xdd, 0xb6, 0x3f, 0x98, 0x1d, + 0x90, 0x26, 0xc5, 0x32, 0xbf, 0x8e, 0xed, 0xdf, 0x8a, 0xf5, 0xa4, 0x38, 0x48, 0xa3, + 0x22, 0x62, 0x17, 0x8c, + ]; + test_sha_accelerator( + &data, + &expected, + 4, + ShaMode::MODE::SHA512_ACC_MODE_MBOX_512.value, + ); + } + + #[test] + fn test_accelerator_sha512_no_data() { + let expected: [u8; SHA512_HASH_SIZE] = [ + 0xcf, 0x83, 0xe1, 0x35, 0x7e, 0xef, 0xb8, 0xbd, 0xf1, 0x54, 0x28, 0x50, 0xd6, 0x6d, + 0x80, 0x07, 0xd6, 0x20, 0xe4, 0x05, 0x0b, 0x57, 0x15, 0xdc, 0x83, 0xf4, 0xa9, 0x21, + 0xd3, 0x6c, 0xe9, 0xce, 0x47, 0xd0, 0xd1, 0x3c, 0x5d, 0x85, 0xf2, 0xb0, 0xff, 0x83, + 0x18, 0xd2, 0x87, 0x7e, 0xec, 0x2f, 0x63, 0xb9, 0x31, 0xbd, 0x47, 0x41, 0x7a, 0x81, + 0xa5, 0x38, 0x32, 0x7a, 0xf9, 0x27, 0xda, 0x3e, + ]; + let data = []; + test_sha_accelerator( + &data, + &expected, + 4, + ShaMode::MODE::SHA512_ACC_MODE_MBOX_512.value, + ); + } + + #[test] + fn test_accelerator_sha512_mailbox_max_size() { + let expected: [u8; SHA512_HASH_SIZE] = [ + 0x4e, 0xd8, 0x3e, 0x40, 0xc9, 0xcf, 0x32, 0xac, 0x2c, 0x59, 0x12, 0x5a, 0x01, 0x17, + 0x0b, 0xc9, 0x7f, 0x20, 0x55, 0x09, 0x52, 0xc8, 0xca, 0x20, 0xff, 0xe1, 0xb2, 0xa5, + 0x9d, 0x1b, 0x1e, 0xd9, 0xc8, 0x42, 0x6c, 0x51, 0x5f, 0x76, 0x29, 0xd1, 0xbb, 0x5e, + 0x4c, 0xdc, 0x53, 0xdd, 0x70, 0xff, 0xcf, 0x67, 0x20, 0x3d, 0x59, 0xe7, 0x0a, 0x55, + 0x94, 0x92, 0xe5, 0xff, 0x0e, 0x71, 0x22, 0x78, + ]; + let data: [u8; MAX_MAILBOX_CAPACITY_BYTES] = [0u8; MAX_MAILBOX_CAPACITY_BYTES]; + test_sha_accelerator( + &data, + &expected, + 0, + ShaMode::MODE::SHA512_ACC_MODE_MBOX_512.value, + ); } #[test] diff --git a/test/dpe_verification/go.mod b/test/dpe_verification/go.mod index a1289c0259..0d57039ad3 100644 --- a/test/dpe_verification/go.mod +++ b/test/dpe_verification/go.mod @@ -9,12 +9,12 @@ replace github.com/chipsalliance/caliptra-dpe/verification/client => ../../dpe/v replace github.com/chipsalliance/caliptra-dpe/verification/sim => ../../dpe/verification/sim require ( - github.com/chipsalliance/caliptra-dpe/verification/client v0.0.0-20240227181801-29d5ca397c66 + github.com/chipsalliance/caliptra-dpe/verification/client v0.0.0-20240305022518-f4e3dd792a5c github.com/chipsalliance/caliptra-dpe/verification/testing v0.0.0-20240227181801-29d5ca397c66 ) require ( - github.com/chipsalliance/caliptra-dpe/verification/sim v0.0.0-20240227181801-29d5ca397c66 // indirect + github.com/chipsalliance/caliptra-dpe/verification/sim v0.0.0-20240305022518-f4e3dd792a5c // indirect github.com/github/smimesign v0.2.0 // indirect github.com/golang/protobuf v1.5.3 // indirect github.com/google/go-configfs-tsm v0.2.2 // indirect @@ -31,10 +31,10 @@ require ( github.com/zmap/zcrypto v0.0.0-20231219022726-a1f61fb1661c // indirect github.com/zmap/zlint/v3 v3.6.1 // indirect go.uber.org/multierr v1.11.0 // indirect - golang.org/x/crypto v0.20.0 // indirect + golang.org/x/crypto v0.21.0 // indirect golang.org/x/exp v0.0.0-20240222234643-814bf88cf225 // indirect - golang.org/x/net v0.21.0 // indirect - golang.org/x/sys v0.17.0 // indirect + golang.org/x/net v0.22.0 // indirect + golang.org/x/sys v0.18.0 // indirect golang.org/x/text v0.14.0 // indirect google.golang.org/protobuf v1.32.0 // indirect ) diff --git a/test/dpe_verification/go.sum b/test/dpe_verification/go.sum index b84e8e3056..acb2da5749 100644 --- a/test/dpe_verification/go.sum +++ b/test/dpe_verification/go.sum @@ -94,8 +94,8 @@ golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5y golang.org/x/crypto v0.7.0/go.mod h1:pYwdfH91IfpZVANVyUOhSIPZaFoJGxTFbZhFTx+dXZU= golang.org/x/crypto v0.11.0/go.mod h1:xgJhtzW8F9jGdVFWZESrid1U1bjeNy4zgy5cRr/CIio= golang.org/x/crypto v0.17.0/go.mod h1:gCAAfMLgwOJRpTjQ2zCCt2OcSfYMTeZVSRtQlPC7Nq4= -golang.org/x/crypto v0.20.0 h1:jmAMJJZXr5KiCw05dfYK9QnqaqKLYXijU23lsEdcQqg= -golang.org/x/crypto v0.20.0/go.mod h1:Xwo95rrVNIoSMx9wa1JroENMToLWn3RNVrTBpLHgZPQ= +golang.org/x/crypto v0.21.0 h1:X31++rzVUdKhX5sWmSOFZxx8UW/ldWx55cbf08iNAMA= +golang.org/x/crypto v0.21.0/go.mod h1:0BP7YvVV9gBbVKyeTG0Gyn+gZm94bibOW5BjDEYAOMs= golang.org/x/exp v0.0.0-20240222234643-814bf88cf225 h1:LfspQV/FYTatPTr/3HzIcmiUFH7PGP+OQ6mgDYo3yuQ= golang.org/x/exp v0.0.0-20240222234643-814bf88cf225/go.mod h1:CxmFvTBINI24O/j8iY7H1xHzx2i4OsyguNBmN/uPtqc= golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= @@ -111,8 +111,8 @@ golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs= golang.org/x/net v0.8.0/go.mod h1:QVkue5JL9kW//ek3r6jTKnTFis1tRmNAW2P1shuFdJc= golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg= golang.org/x/net v0.12.0/go.mod h1:zEVYFnQC7m/vmpQFELhcD1EWkZlX69l4oqgmer6hfKA= -golang.org/x/net v0.21.0 h1:AQyQV4dYCvJ7vGmJyKki9+PBdyvhkSd8EIx/qb0AYv4= -golang.org/x/net v0.21.0/go.mod h1:bIjVDfnllIU7BJ2DNgfnXvpSvtn8VRwhlsaeUTyUS44= +golang.org/x/net v0.22.0 h1:9sGLhx7iRIHEiX0oAJ3MRZMUCElJgy7Br1nO+AMN3Tc= +golang.org/x/net v0.22.0/go.mod h1:JKghWKKOSdJwpW2GEx0Ja7fmaKnMsbu+MWVZTokSYmg= golang.org/x/oauth2 v0.6.0/go.mod h1:ycmewcwgD4Rpr3eZJLSB4Kyyljb3qDh40vJ8STE5HKw= golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= @@ -135,8 +135,8 @@ golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.10.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.15.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= -golang.org/x/sys v0.17.0 h1:25cE3gD+tdBA7lp7QfhuV+rJiE9YXTcS3VG1SqssI/Y= -golang.org/x/sys v0.17.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/sys v0.18.0 h1:DBdB3niSjOA/O0blCZBqDefyWNYveAYMNF1Wum0DYQ4= +golang.org/x/sys v0.18.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= diff --git a/test/src/derive.rs b/test/src/derive.rs index 932483ab60..17dcb2587a 100644 --- a/test/src/derive.rs +++ b/test/src/derive.rs @@ -5,6 +5,7 @@ /// /// DO NOT REFACTOR THIS FILE TO RE-USE CODE FROM OTHER PARTS OF CALIPTRA use caliptra_hw_model_types::SecurityState; +use caliptra_image_types::ImageManifest; use openssl::{ pkey::{PKey, Public}, sha::{sha256, sha384}, @@ -381,10 +382,39 @@ fn test_derive_pcr0() { ) } +pub struct PcrRtCurrentInput { + pub runtime_digest: [u32; 12], + pub manifest: ImageManifest, +} + +pub struct PcrRtCurrent(pub [u32; 12]); +impl PcrRtCurrent { + pub fn derive(input: &PcrRtCurrentInput) -> Self { + let mut value = [0u8; 48]; + let extend = |value: &mut [u8; 48], buf: &[u8]| { + *value = sha384(&[value.as_slice(), buf].concat()); + }; + extend( + &mut value, + swap_word_bytes(&input.runtime_digest).as_bytes(), + ); + + let manifest_digest = sha384(input.manifest.as_bytes()); + extend(&mut value, &manifest_digest); + println!("Pcr is {:02x?}", value); + + let mut result: [u32; 12] = zerocopy::transmute!(value); + swap_word_bytes_inplace(&mut result); + Self(result) + } +} + #[derive(Clone, Copy, Debug, Eq, PartialEq)] pub struct FmcAliasKey { // The FMC alias private key as stored in the key-vault pub priv_key: [u32; 12], + + pub cdi: [u32; 12], } impl FmcAliasKey { pub fn derive(pcr0: &Pcr0, ldevid: &LDevId) -> Self { @@ -407,7 +437,56 @@ impl FmcAliasKey { swap_word_bytes(&ECDSA_KEYGEN_NONCE).as_bytes() )); swap_word_bytes_inplace(&mut priv_key); - Self { priv_key } + Self { priv_key, cdi } + } + pub fn derive_public_key(&self) -> PKey { + derive_ecdsa_key( + swap_word_bytes(&self.priv_key) + .as_bytes() + .try_into() + .unwrap(), + ) + } +} + +#[derive(Clone, Copy, Debug, Eq, PartialEq)] +pub struct RtAliasKey { + pub cdi: [u32; 12], + + // The FMC alias private key as stored in the key-vault + pub priv_key: [u32; 12], +} +impl RtAliasKey { + pub fn derive(tci_input: &PcrRtCurrentInput, fmc_key: &FmcAliasKey) -> Self { + // NOTE: This works differently than FmcAliasKey. FmcAliasKey takes the + // 48-byte value from Pcr0 as context, this version uses a 96-byte + // concatenation of the runtime digest and manifest digest. + let mut tci: [u8; 96] = [0; 96]; + tci[0..48].copy_from_slice(swap_word_bytes(&tci_input.runtime_digest).as_bytes()); + tci[48..96] + .as_bytes_mut() + .copy_from_slice(&sha384(tci_input.manifest.as_bytes())); + + let mut cdi: [u32; 12] = transmute!(hmac384_kdf( + swap_word_bytes(&fmc_key.cdi).as_bytes(), + b"rt_alias_cdi", + Some(&tci), + )); + swap_word_bytes_inplace(&mut cdi); + + let mut priv_key_seed: [u32; 12] = transmute!(hmac384_kdf( + swap_word_bytes(&cdi).as_bytes(), + b"rt_alias_keygen", + None + )); + swap_word_bytes_inplace(&mut priv_key_seed); + + let mut priv_key: [u32; 12] = transmute!(hmac384_drbg_keygen( + swap_word_bytes(&priv_key_seed).as_bytes(), + swap_word_bytes(&ECDSA_KEYGEN_NONCE).as_bytes() + )); + swap_word_bytes_inplace(&mut priv_key); + Self { priv_key, cdi } } pub fn derive_public_key(&self) -> PKey { derive_ecdsa_key( @@ -440,6 +519,10 @@ fn test_derive_fmc_alias_key() { assert_eq!( fmc_alias_key, FmcAliasKey { + cdi: [ + 0xf4fb8b09, 0xc9233adb, 0x3dfade39, 0xb656f0ef, 0x151404dc, 0xf4fe787a, 0x0664baea, + 0xe9d2de59, 0x22401c7c, 0x59087111, 0xd3aeb5b1, 0x368742da + ], priv_key: [ 0x81a4f53c, 0xeb0749ca, 0x77b0fe32, 0x33fd9798, 0x7412f652, 0xded8f8a5, 0x39a9ebbd, 0x75ce2870, 0xb5f62bb3, 0x25376504, 0xa34f286c, 0x849ea86c, diff --git a/test/tests/caliptra_integration_tests/smoke_test.rs b/test/tests/caliptra_integration_tests/smoke_test.rs index da47a9a022..db27134a5f 100644 --- a/test/tests/caliptra_integration_tests/smoke_test.rs +++ b/test/tests/caliptra_integration_tests/smoke_test.rs @@ -9,6 +9,7 @@ use caliptra_common::RomBootStatus; use caliptra_drivers::CaliptraError; use caliptra_hw_model::{BootParams, HwModel, InitParams, SecurityState}; use caliptra_hw_model_types::{DeviceLifecycle, Fuses, RandomEtrngResponses, RandomNibbles}; +use caliptra_test::derive::{PcrRtCurrentInput, RtAliasKey}; use caliptra_test::{derive, redact_cert, run_test, RedactOpts, UnwrapSingle}; use caliptra_test::{ derive::{DoeInput, DoeOutput, FmcAliasKey, IDevId, LDevId, Pcr0, Pcr0Input}, @@ -176,7 +177,7 @@ fn smoke_test() { assert_output_contains(&output, "[kat] sha1"); assert_output_contains(&output, "[kat] SHA2-256"); assert_output_contains(&output, "[kat] SHA2-384"); - assert_output_contains(&output, "[kat] SHA2-384-ACC"); + assert_output_contains(&output, "[kat] SHA2-512-ACC"); assert_output_contains(&output, "[kat] HMAC-384"); assert_output_contains(&output, "[kat] LMS"); assert_output_contains(&output, "[kat] --"); @@ -410,6 +411,26 @@ fn smoke_test() { let rt_alias_cert = openssl::x509::X509::from_der(rt_alias_cert_der).unwrap(); let rt_alias_cert_txt = String::from_utf8(rt_alias_cert.to_text().unwrap()).unwrap(); + println!( + "Manifest digest is {:02x?}", + image.manifest.runtime.digest.as_bytes() + ); + let expected_rt_alias_key = RtAliasKey::derive( + &PcrRtCurrentInput { + runtime_digest: image.manifest.runtime.digest, + manifest: image.manifest, + }, + &expected_fmc_alias_key, + ); + + // Check that the rt-alias key has the rt measurements input above mixed into it + // If a firmware change causes this assertion to fail, it is likely that the + // logic in the FMC that derives the CDI. Ensure this is intentional, and + // then make the same change to caliptra_test::RtAliasKey::derive(). + assert!(expected_rt_alias_key + .derive_public_key() + .public_eq(&rt_alias_cert.public_key().unwrap())); + println!("rt-alias cert: {rt_alias_cert_txt}"); assert!(