fix: use concat_kdf crate instead of hand rolled NIST SP 800-56A KDF (#7106)

This commit is contained in:
Dan Cline
2024-03-12 10:52:46 -04:00
committed by GitHub
parent 22d585df17
commit 99711550d8
3 changed files with 38 additions and 16 deletions

View File

@ -35,6 +35,7 @@ rand.workspace = true
ctr = "0.9.2"
digest = "0.10.5"
secp256k1 = { workspace = true, features = ["global-context", "rand-std", "recovery"] }
concat-kdf = { version = "0.1.0" }
sha2 = "0.10.6"
sha3 = "0.10.5"
aes = "0.8.1"

View File

@ -36,23 +36,19 @@ fn ecdh_x(public_key: &PublicKey, secret_key: &SecretKey) -> B256 {
B256::from_slice(&secp256k1::ecdh::shared_secret_point(public_key, secret_key)[..32])
}
/// This is the NIST SP 800-56A Concatenation Key Derivation Function (KDF) using SHA-256.
///
/// Internally this uses [`concat_kdf::derive_key_into`] to derive a key into the given `dest`
/// slice.
///
/// # Panics
/// * If the `dest` is empty
/// * If `s1` is empty
/// * If the `dest` len is greater than or equal to the hash output len * the max counter value. In
/// this case, the hash output len is 32 bytes, and the max counter value is 2^32 - 1. So the dest
/// cannot have a len greater than 32 * 2^32 - 1.
fn kdf(secret: B256, s1: &[u8], dest: &mut [u8]) {
// SEC/ISO/Shoup specify counter size SHOULD be equivalent
// to size of hash output, however, it also notes that
// the 4 bytes is okay. NIST specifies 4 bytes.
let mut ctr = 1_u32;
let mut written = 0_usize;
while written < dest.len() {
let mut hasher = Sha256::default();
let ctrs = [(ctr >> 24) as u8, (ctr >> 16) as u8, (ctr >> 8) as u8, ctr as u8];
hasher.update(ctrs);
hasher.update(secret.as_slice());
hasher.update(s1);
let d = hasher.finalize();
dest[written..(written + 32)].copy_from_slice(&d);
written += 32;
ctr += 1;
}
concat_kdf::derive_key_into::<Sha256>(secret.as_slice(), s1, dest).unwrap();
}
#[derive(Educe)]
@ -778,4 +774,19 @@ mod tests {
test_client.read_ack(&mut ack2.to_vec()).unwrap();
test_client.read_ack(&mut ack3.to_vec()).unwrap();
}
#[test]
fn kdf_out_of_bounds() {
// ensures that the kdf method does not panic if the dest is too small
let len_range = 1..65;
for len in len_range {
let mut dest = vec![1u8; len];
kdf(
b256!("7000000000000000000000000000000000000000000000000000000000000007"),
&[0x01, 0x33, 0x70, 0xbe, 0xef],
&mut dest,
);
}
std::hint::black_box(());
}
}