Skip to content

Commit

Permalink
Adding ECC error checking during waits (#1610)
Browse files Browse the repository at this point in the history
  • Loading branch information
nquarton authored Jul 16, 2024
1 parent 7d9d89c commit 6bfd809
Show file tree
Hide file tree
Showing 5 changed files with 77 additions and 11 deletions.
4 changes: 2 additions & 2 deletions FROZEN_IMAGES.sha384sum
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
# WARNING: Do not update this file without the approval of the Caliptra TAC
e3c62ff9b5ca7873001e516a22b62a3090bc470ddb4664ac6feef2ebabb0b65d880a5a38ff31b5250817a39c79d3a68e caliptra-rom-no-log.bin
cefa26982b60ad32595053ef8e516137642a7760434481b1fe4371b4fbaeeb1528b15e8523f8d8c2c9cc9d5920fe9e9b caliptra-rom-with-log.bin
5a97c3e30c2ceaad209745367a5dfd583e6a0ad4f43a6f4254c03d6e929db671c26ac6ffe738a843b98684761f2241b4 caliptra-rom-no-log.bin
8b08a1ce76fd8411bee31c9453c16ab841e3c6ae5716c10a08bb6891f233523e2bd3b263b73e83aa54e6545ab35322fb caliptra-rom-with-log.bin
44 changes: 35 additions & 9 deletions drivers/src/ecc384.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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<F>(regs: RegisterBlock<ureg::RealMmioMut>, 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
Expand All @@ -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 {
Expand Down Expand Up @@ -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 {
Expand Down Expand Up @@ -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()?;
Expand All @@ -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 {
Expand All @@ -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 {
Expand All @@ -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 {
Expand Down Expand Up @@ -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());
Expand All @@ -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());
Expand Down
1 change: 1 addition & 0 deletions error/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down
29 changes: 29 additions & 0 deletions runtime/tests/runtime_integration_tests/test_ecdsa.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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,
);
}
10 changes: 10 additions & 0 deletions sw-emulator/lib/periph/src/asym_ecc384.rs
Original file line number Diff line number Diff line change
Expand Up @@ -204,6 +204,14 @@ pub struct AsymEcc384 {
#[register(offset = 0x0000_0614)]
key_write_status: ReadOnlyRegister<u32, KeyWriteStatus::Register>,

/// Error Global Intr register
#[register(offset = 0x0000_080c)]
error_global_intr: ReadOnlyRegister<u32>,

/// Error Internal Intr register
#[register(offset = 0x0000_0814)]
error_internal_intr: ReadOnlyRegister<u32>,

/// Key Vault
key_vault: KeyVault,

Expand Down Expand Up @@ -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),
}
}

Expand Down

0 comments on commit 6bfd809

Please sign in to comment.