Makes our CredRandom derivation FIPS compliant (#613)
* Makes our CredRandom derivation FIPS compliant This change breaks existing usage of CredRandom. * fixes rust_crypto and HKDF test style
This commit is contained in:
@@ -16,11 +16,28 @@ use super::HASH_SIZE;
|
||||
|
||||
/// HKDF using SHA256.
|
||||
pub trait Hkdf256 {
|
||||
/// Computes the HKDF with 256 bit (one block) output.
|
||||
///
|
||||
/// # Arguments
|
||||
///
|
||||
/// * `ikm` - Input keying material
|
||||
/// * `salt` - Byte string that acts as a key
|
||||
/// * `info` - Optional context and application specific information
|
||||
///
|
||||
/// This implementation is equivalent to a standard HKD, with `salt` fixed at a length of
|
||||
/// 32 byte and the output length l as 32.
|
||||
fn hkdf_256(ikm: &[u8], salt: &[u8; HASH_SIZE], info: &[u8]) -> [u8; HASH_SIZE];
|
||||
|
||||
/// Computes the HKDF with empty salt and 256 bit (one block) output.
|
||||
///
|
||||
/// # Arguments
|
||||
///
|
||||
/// * `ikm` - Input keying material
|
||||
/// * `info` - Optional context and application specific information
|
||||
fn hkdf_empty_salt_256(ikm: &[u8], info: &[u8]) -> [u8; HASH_SIZE];
|
||||
///
|
||||
/// This implementation is equivalent to a standard HKDF, with `salt` set to the
|
||||
/// default block of zeros and the output length l as 32.
|
||||
fn hkdf_empty_salt_256(ikm: &[u8], info: &[u8]) -> [u8; HASH_SIZE] {
|
||||
Self::hkdf_256(ikm, &[0; HASH_SIZE], info)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -158,6 +158,16 @@ mod test {
|
||||
assert_eq!(&SoftwareHkdf256::hkdf_empty_salt_256(b"0", &[0]), &okm);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_hkdf_256_matches() {
|
||||
let ikm = [0x11; 16];
|
||||
let salt = [0; 32];
|
||||
let info = [0x22; 16];
|
||||
let empty_salt_output = SoftwareHkdf256::hkdf_empty_salt_256(&ikm, &info);
|
||||
let explicit_output = SoftwareHkdf256::hkdf_256(&ikm, &salt, &info);
|
||||
assert_eq!(empty_salt_output, explicit_output);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_aes_encrypt_decrypt_block() {
|
||||
let mut block = [0x55; AES_BLOCK_SIZE];
|
||||
|
||||
@@ -257,8 +257,8 @@ impl Hmac256 for SoftwareHmac256 {
|
||||
pub struct SoftwareHkdf256;
|
||||
|
||||
impl Hkdf256 for SoftwareHkdf256 {
|
||||
fn hkdf_empty_salt_256(ikm: &[u8], info: &[u8]) -> [u8; HASH_SIZE] {
|
||||
let hk = hkdf::Hkdf::<sha2::Sha256>::new(Some(&[0; HASH_SIZE]), ikm);
|
||||
fn hkdf_256(ikm: &[u8], salt: &[u8; HASH_SIZE], info: &[u8]) -> [u8; HASH_SIZE] {
|
||||
let hk = hkdf::Hkdf::<sha2::Sha256>::new(Some(salt), ikm);
|
||||
let mut okm = [0u8; HASH_SIZE];
|
||||
hk.expand(info, &mut okm).unwrap();
|
||||
okm
|
||||
|
||||
@@ -208,8 +208,8 @@ impl Hmac256 for SoftwareHmac256 {
|
||||
pub struct SoftwareHkdf256;
|
||||
|
||||
impl Hkdf256 for SoftwareHkdf256 {
|
||||
fn hkdf_empty_salt_256(ikm: &[u8], info: &[u8]) -> [u8; HASH_SIZE] {
|
||||
crypto::hkdf::hkdf_empty_salt_256::<crypto::sha256::Sha256>(ikm, info)
|
||||
fn hkdf_256(ikm: &[u8], salt: &[u8; HASH_SIZE], info: &[u8]) -> [u8; HASH_SIZE] {
|
||||
crypto::hkdf::hkdf_256::<crypto::sha256::Sha256>(ikm, salt, info)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -66,14 +66,14 @@ use crate::api::attestation_store::{self, Attestation, AttestationStore};
|
||||
use crate::api::clock::Clock;
|
||||
use crate::api::connection::{HidConnection, SendOrRecvStatus, UsbEndpoint};
|
||||
use crate::api::crypto::ecdsa::{SecretKey as _, Signature};
|
||||
use crate::api::crypto::hmac256::Hmac256;
|
||||
use crate::api::crypto::hkdf256::Hkdf256;
|
||||
use crate::api::crypto::sha256::Sha256;
|
||||
use crate::api::customization::Customization;
|
||||
use crate::api::firmware_protection::FirmwareProtection;
|
||||
use crate::api::rng::Rng;
|
||||
use crate::api::upgrade_storage::UpgradeStorage;
|
||||
use crate::api::user_presence::{UserPresence, UserPresenceError};
|
||||
use crate::env::{EcdsaSk, Env, Hmac, Sha};
|
||||
use crate::env::{EcdsaSk, Env, Hkdf, Sha};
|
||||
use alloc::boxed::Box;
|
||||
use alloc::string::{String, ToString};
|
||||
use alloc::vec;
|
||||
@@ -956,9 +956,10 @@ impl<E: Env> CtapState<E> {
|
||||
private_key: &PrivateKey,
|
||||
has_uv: bool,
|
||||
) -> Result<[u8; 32], Ctap2StatusCode> {
|
||||
let entropy = private_key.to_bytes();
|
||||
let private_key_bytes = private_key.to_bytes();
|
||||
let salt = array_ref!(private_key_bytes, 0, 32);
|
||||
let key = storage::cred_random_secret(env, has_uv)?;
|
||||
Ok(Hmac::<E>::mac(&key, &entropy))
|
||||
Ok(Hkdf::<E>::hkdf_256(&key, salt, b"credRandom"))
|
||||
}
|
||||
|
||||
// Processes the input of a get_assertion operation for a given credential
|
||||
|
||||
Reference in New Issue
Block a user