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:
kaczmarczyck
2023-04-11 14:48:42 +02:00
committed by GitHub
parent be42b47caf
commit a1d6ed0223
6 changed files with 96 additions and 30 deletions

View File

@@ -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)
}
}

View File

@@ -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];

View File

@@ -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

View File

@@ -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)
}
}

View File

@@ -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