Skip to content

Commit

Permalink
Adding KAT for ECC deterministic key pair generation (chipsalliance#1655
Browse files Browse the repository at this point in the history
)
  • Loading branch information
nquarton authored Nov 15, 2024
1 parent 665bfd1 commit 86a37b0
Show file tree
Hide file tree
Showing 6 changed files with 155 additions and 43 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
133bf3969893178e041b61001d75bfb504be3b3676cac608a40877f1e4b46b4855f86c1859cfc3e22745327102fba4b0 caliptra-rom-no-log.bin
44f5bbbc4b71d7f0926f85b7d81ef7e17f721557b38379b650497eb8dd19d0a74ab5a1e2177c7e99653a878d2daed3b3 caliptra-rom-with-log.bin
9fe3c2a8031c31e7a9ce56e5b8b430414d74db9d04161512b90fb60d5df120cc3998c8881eea10b7c4e1c1bea4326b27 caliptra-rom-no-log.bin
f1a8736ab386897c62a173032910ed03566043b01305ceaab7d25614b86e86ef97dd90bf9cdf7aaa7eb470f9e155133b caliptra-rom-with-log.bin
74 changes: 70 additions & 4 deletions drivers/src/ecc384.rs
Original file line number Diff line number Diff line change
Expand Up @@ -228,6 +228,58 @@ impl Ecc384 {
trng: &mut Trng,
priv_key: Ecc384PrivKeyOut,
) -> CaliptraResult<Ecc384PubKey> {
self.key_pair_base(seed, nonce, trng, priv_key, None)
}

/// Generate ECC-384 Key Pair for FIPS KAT testing
/// ONLY to be used for KAT testing
///
/// # Arguments
///
/// * `trng` - TRNG driver instance
/// * `priv_key` - Generate ECC-384 Private key
/// * `pct_sig` - Ecc 384 signature to return signature generated during the pairwise consistency test
///
/// # Returns
///
/// * `Ecc384PubKey` - Generated ECC-384 Public Key
#[cfg_attr(not(feature = "no-cfi"), cfi_impl_fn)]
pub fn key_pair_for_fips_kat(
&mut self,
trng: &mut Trng,
priv_key: Ecc384PrivKeyOut,
pct_sig: &mut Ecc384Signature,
) -> CaliptraResult<Ecc384PubKey> {
let seed = Array4x12::new([0u32; 12]);
let nonce = Array4x12::new([0u32; 12]);
self.key_pair_base(
&Ecc384Seed::from(&seed),
&nonce,
trng,
priv_key,
Some(pct_sig),
)
}

/// Private base function to generate ECC-384 Key Pair
/// pct_sig should only be provided in the KAT use case
#[cfg_attr(not(feature = "no-cfi"), cfi_impl_fn)]
#[inline(never)]
fn key_pair_base(
&mut self,
seed: &Ecc384Seed,
nonce: &Array4x12,
trng: &mut Trng,
priv_key: Ecc384PrivKeyOut,
pct_sig: Option<&mut Ecc384Signature>,
) -> CaliptraResult<Ecc384PubKey> {
#[cfg(feature = "fips-test-hooks")]
unsafe {
crate::FipsTestHook::error_if_hook_set(
crate::FipsTestHook::ECC384_KEY_PAIR_GENERATE_FAILURE,
)?
}

let ecc = self.ecc.regs_mut();
let mut priv_key = priv_key;

Expand Down Expand Up @@ -299,7 +351,13 @@ impl Ecc384 {
};

match self.sign(&priv_key.into(), &pub_key, &digest, trng) {
Ok(mut sig) => sig.zeroize(),
Ok(mut sig) => {
// Return the signature from this test if requested (only used for KAT)
if let Some(output_sig) = pct_sig {
*output_sig = sig;
}
sig.zeroize();
}
Err(_) => {
// Remap error to a pairwise consistency check failure
return Err(CaliptraError::DRIVER_ECC384_KEYGEN_PAIRWISE_CONSISTENCY_FAILURE);
Expand All @@ -308,6 +366,14 @@ impl Ecc384 {

self.zeroize_internal();

#[cfg(feature = "fips-test-hooks")]
let pub_key = unsafe {
crate::FipsTestHook::corrupt_data_if_hook_set(
crate::FipsTestHook::ECC384_CORRUPT_KEY_PAIR,
&pub_key,
)
};

Ok(pub_key)
}

Expand Down Expand Up @@ -431,12 +497,12 @@ impl Ecc384 {
caliptra_cfi_lib::cfi_assert_eq_12_words(&r.0, &sig.r.0);

#[cfg(feature = "fips-test-hooks")]
let sig_result = unsafe {
let sig_result = Ok(unsafe {
crate::FipsTestHook::corrupt_data_if_hook_set(
crate::FipsTestHook::ECC384_CORRUPT_SIGNATURE,
&sig_result,
sig,
)
};
});

sig_result
}
Expand Down
3 changes: 3 additions & 0 deletions drivers/src/fips_test_hooks.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ impl FipsTestHook {
pub const COMPLETE: u8 = 0x1;
// Set by external test
pub const CONTINUE: u8 = 0x10;

pub const HALT_SELF_TESTS: u8 = 0x21;
pub const SHA1_CORRUPT_DIGEST: u8 = 0x22;
pub const SHA256_CORRUPT_DIGEST: u8 = 0x23;
Expand All @@ -22,6 +23,7 @@ impl FipsTestHook {
pub const ECC384_PAIRWISE_CONSISTENCY_ERROR: u8 = 0x29;
pub const HALT_FW_LOAD: u8 = 0x2A;
pub const HALT_SHUTDOWN_RT: u8 = 0x2B;
pub const ECC384_CORRUPT_KEY_PAIR: u8 = 0x2C;

pub const SHA1_DIGEST_FAILURE: u8 = 0x40;
pub const SHA256_DIGEST_FAILURE: u8 = 0x41;
Expand All @@ -32,6 +34,7 @@ impl FipsTestHook {
pub const ECC384_VERIFY_FAILURE: u8 = 0x46;
pub const HMAC384_FAILURE: u8 = 0x47;
pub const LMS_VERIFY_FAILURE: u8 = 0x48;
pub const ECC384_KEY_PAIR_GENERATE_FAILURE: u8 = 0x49;

// FW Load Errors
pub const FW_LOAD_VENDOR_PUB_KEY_DIGEST_FAILURE: u8 = 0x50;
Expand Down
10 changes: 6 additions & 4 deletions error/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -587,11 +587,13 @@ impl CaliptraError {
pub const KAT_HMAC384_FAILURE: CaliptraError = CaliptraError::new_const(0x90030001);
pub const KAT_HMAC384_TAG_MISMATCH: CaliptraError = CaliptraError::new_const(0x90030002);

pub const KAT_ECC384_SIGNATURE_GENERATE_FAILURE: CaliptraError =
CaliptraError::new_const(0x90040001);
pub const KAT_ECC384_SIGNATURE_VERIFY_FAILURE: CaliptraError =
CaliptraError::new_const(0x90040002);
// 0x90040001 was KAT_ECC384_SIGNATURE_GENERATE_FAILURE
// 0x90040002 was KAT_ECC384_SIGNATURE_VERIFY_FAILURE
pub const KAT_ECC384_SIGNATURE_MISMATCH: CaliptraError = CaliptraError::new_const(0x90040003);
pub const KAT_ECC384_KEY_PAIR_GENERATE_FAILURE: CaliptraError =
CaliptraError::new_const(0x90040004);
pub const KAT_ECC384_KEY_PAIR_VERIFY_FAILURE: CaliptraError =
CaliptraError::new_const(0x90040005);

pub const KAT_SHA2_512_384_ACC_DIGEST_START_OP_FAILURE: CaliptraError =
CaliptraError::new_const(0x90050001);
Expand Down
61 changes: 36 additions & 25 deletions kat/src/ecc384_kat.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,34 +13,34 @@ Abstract:
--*/

use caliptra_drivers::{
Array4x12, Array4xN, CaliptraError, CaliptraResult, Ecc384, Ecc384PrivKeyIn, Ecc384PubKey,
Array4x12, Array4xN, CaliptraError, CaliptraResult, Ecc384, Ecc384PrivKeyOut, Ecc384PubKey,
Ecc384Signature, Trng,
};

const PRIV_KEY: Array4x12 = Array4x12::new([
0xc908585a, 0x486c3b3d, 0x8bbe50eb, 0x7d2eb8a0, 0x3aa04e3d, 0x8bde2c31, 0xa8a2a1e3, 0x349dc21c,
0xbbe6c90a, 0xe2f74912, 0x8884b622, 0xbb72b4c5,
const KEY_GEN_PRIV_KEY: Array4x12 = Array4x12::new([
0xfeeef554, 0x4a765649, 0x90128ad1, 0x89e873f2, 0x1f0dfd5a, 0xd7e2fa86, 0x1127ee6e, 0x394ca784,
0x871c1aec, 0x032c7a8b, 0x10b93e0e, 0xab8946d6,
]);

const PUB_KEY: Ecc384PubKey = Ecc384PubKey {
const KEY_GEN_PUB_KEY: Ecc384PubKey = Ecc384PubKey {
x: Array4xN([
0x98233ca, 0x567a3f14, 0xbe784904, 0xc6921d43, 0x3b4f853a, 0x523742e4, 0xbc98767e,
0x23ca3da6, 0x656bec46, 0xa7b1119e, 0x63d266ca, 0x6254977f,
0xd7dd94e0, 0xbffc4cad, 0xe9902b7f, 0xdb154260, 0xd5ec5dfd, 0x57950e83, 0x59015a30,
0x2c8bf7bb, 0xa7e5f6df, 0xfc168516, 0x2bdd35f9, 0xf5c1b0ff,
]),
y: Array4xN([
0x75d0b401, 0xc8bac39a, 0xc5fb0f2b, 0x3b95372c, 0x41d9de40, 0x55fddb06, 0xf7484974,
0x8d0aed85, 0x9b6550ca, 0x750c3cd1, 0x1851e050, 0xbb7d20b2,
0xbb9c3a2f, 0x061e8d70, 0x14278dd5, 0x1e66a918, 0xa6b6f9f1, 0xc1937312, 0xd4e7a921,
0xb18ef0f4, 0x1fdd401d, 0x9e771850, 0x9f8731e9, 0xeec9c31d,
]),
};

const SIGNATURE: Ecc384Signature = Ecc384Signature {
r: Array4xN([
0x36f85014, 0x6f400443, 0x848cae03, 0x57591032, 0xe6a395de, 0x66e7261a, 0x38049fb,
0xee15db19, 0x5dbd9786, 0x9439292a, 0x4f5792e4, 0x3a1231b7,
0x93799D55, 0x12263628, 0x34F60F7B, 0x945290B7, 0xCCE6E996, 0x01FB7EBD, 0x026C2E3C,
0x445D3CD9, 0xB65068DA, 0xC0A848BE, 0x9F0560AA, 0x758FDA27,
]),
s: Array4xN([
0xeeea4294, 0x82fd8fa9, 0xd4d5f960, 0xa09edfa6, 0xc765efe5, 0xff4c17a5, 0x12e694fa,
0xcc45d3f6, 0xfc3d3b5c, 0x62739c1f, 0xb9fcae3, 0x26f54b43,
0xE548E535, 0xA1CC600E, 0x133B5591, 0xAEBAAD78, 0x054006D7, 0x52D0E1DF, 0x94FBFA95,
0xD78F0B3F, 0x8E81B911, 0x9C2BE008, 0xBF6D6F4E, 0x4185F87D,
]),
};

Expand All @@ -51,7 +51,7 @@ impl Ecc384Kat {
/// This function executes the Known Answer Tests (aka KAT) for ECC384.
///
/// Test vector source:
/// Generated using MbedTLS library.
/// Zeroed inputs, outputs verified against python cryptography lib built on OpenSSL
///
/// # Arguments
///
Expand All @@ -61,24 +61,35 @@ impl Ecc384Kat {
///
/// * `CaliptraResult` - Result denoting the KAT outcome.
pub fn execute(&self, ecc: &mut Ecc384, trng: &mut Trng) -> CaliptraResult<()> {
self.kat_signature_generate_and_verify(ecc, trng)
self.kat_key_pair_gen_sign_and_verify(ecc, trng)
}

fn kat_signature_generate_and_verify(
fn kat_key_pair_gen_sign_and_verify(
&self,
ecc: &mut Ecc384,
trng: &mut Trng,
) -> CaliptraResult<()> {
let digest = Array4x12::new([0u32; 12]);
// The driver validates every signature that it generates, so don't need
// to explicitly verify here.
let signature = ecc
.sign(&Ecc384PrivKeyIn::from(&PRIV_KEY), &PUB_KEY, &digest, trng)
.map_err(|_| CaliptraError::KAT_ECC384_SIGNATURE_GENERATE_FAILURE)?;

if signature != SIGNATURE {
Err(CaliptraError::KAT_ECC384_SIGNATURE_VERIFY_FAILURE)?;
let mut priv_key = Array4x12::new([0u32; 12]);
let mut pct_sig = Ecc384Signature {
r: Array4x12::new([0u32; 12]),
s: Array4x12::new([0u32; 12]),
};

let pub_key = ecc
.key_pair_for_fips_kat(trng, Ecc384PrivKeyOut::from(&mut priv_key), &mut pct_sig)
.map_err(|_| CaliptraError::KAT_ECC384_KEY_PAIR_GENERATE_FAILURE)?;

// NOTE: Signature verify step is performed in ECC driver sign function
if priv_key != KEY_GEN_PRIV_KEY {
Err(CaliptraError::KAT_ECC384_KEY_PAIR_VERIFY_FAILURE)?;
}
if pub_key != KEY_GEN_PUB_KEY {
Err(CaliptraError::KAT_ECC384_KEY_PAIR_VERIFY_FAILURE)?;
}
if pct_sig != SIGNATURE {
Err(CaliptraError::KAT_ECC384_SIGNATURE_MISMATCH)?;
}

Ok(())
}
}
46 changes: 38 additions & 8 deletions test/tests/fips_test_suite/self_tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -394,38 +394,68 @@ pub fn kat_sha2_512_384acc_digest_mismatch_rt() {
#[test]
#[cfg(not(feature = "test_env_immutable_rom"))]
pub fn kat_ecc384_signature_generate_failure_rom() {
// Should be KAT_ECC384_SIGNATURE_VERIFY_FAILURE but ROM is using the wrong code
self_test_failure_flow_rom(
FipsTestHook::ECC384_SIGNATURE_GENERATE_FAILURE,
u32::from(CaliptraError::KAT_ECC384_SIGNATURE_GENERATE_FAILURE),
u32::from(CaliptraError::KAT_ECC384_KEY_PAIR_GENERATE_FAILURE),
);
}

#[test]
pub fn kat_ecc384_signature_generate_failure_rt() {
// Should be KAT_ECC384_SIGNATURE_VERIFY_FAILURE but ROM is using the wrong code
self_test_failure_flow_rt(
FipsTestHook::ECC384_SIGNATURE_GENERATE_FAILURE,
u32::from(CaliptraError::KAT_ECC384_SIGNATURE_GENERATE_FAILURE),
u32::from(CaliptraError::KAT_ECC384_KEY_PAIR_GENERATE_FAILURE),
);
}

#[test]
#[cfg(not(feature = "test_env_immutable_rom"))]
pub fn kat_ecc384_signature_verify_failure_rom() {
// Should be KAT_ECC384_SIGNATURE_VERIFY_FAILURE but ROM is using the wrong code
self_test_failure_flow_rom(
FipsTestHook::ECC384_CORRUPT_SIGNATURE,
u32::from(CaliptraError::KAT_ECC384_SIGNATURE_GENERATE_FAILURE),
u32::from(CaliptraError::KAT_ECC384_SIGNATURE_MISMATCH),
);
}

#[test]
pub fn kat_ecc384_signature_verify_failure_rt() {
// Should be KAT_ECC384_SIGNATURE_VERIFY_FAILURE but ROM is using the wrong code
self_test_failure_flow_rt(
FipsTestHook::ECC384_CORRUPT_SIGNATURE,
u32::from(CaliptraError::KAT_ECC384_SIGNATURE_GENERATE_FAILURE),
u32::from(CaliptraError::KAT_ECC384_SIGNATURE_MISMATCH),
);
}

#[test]
#[cfg(not(feature = "test_env_immutable_rom"))]
pub fn kat_ecc384_deterministic_key_gen_generate_failure_rom() {
self_test_failure_flow_rom(
FipsTestHook::ECC384_KEY_PAIR_GENERATE_FAILURE,
u32::from(CaliptraError::KAT_ECC384_KEY_PAIR_GENERATE_FAILURE),
);
}

#[test]
pub fn kat_ecc384_deterministic_key_gen_generate_failure_rt() {
self_test_failure_flow_rt(
FipsTestHook::ECC384_KEY_PAIR_GENERATE_FAILURE,
u32::from(CaliptraError::KAT_ECC384_KEY_PAIR_GENERATE_FAILURE),
);
}

#[test]
#[cfg(not(feature = "test_env_immutable_rom"))]
pub fn kat_ecc384_deterministic_key_gen_verify_failure_rom() {
self_test_failure_flow_rom(
FipsTestHook::ECC384_CORRUPT_KEY_PAIR,
u32::from(CaliptraError::KAT_ECC384_KEY_PAIR_VERIFY_FAILURE),
);
}

#[test]
pub fn kat_ecc384_deterministic_key_gen_verify_failure_rt() {
self_test_failure_flow_rt(
FipsTestHook::ECC384_CORRUPT_KEY_PAIR,
u32::from(CaliptraError::KAT_ECC384_KEY_PAIR_VERIFY_FAILURE),
);
}

Expand Down

0 comments on commit 86a37b0

Please sign in to comment.