use crate::hmac::{HmacSha256, HmacSha384};
pub fn extract_sha256(salt: &[u8], ikm: &[u8]) -> [u8; 32] {
let s: &[u8] = if salt.is_empty() { &[0u8; 32] } else { salt };
HmacSha256::one_shot(s, ikm)
}
pub fn expand_sha256(prk: &[u8], info: &[u8], okm: &mut [u8]) -> Result<(), crate::Error> {
if okm.len() > 255 * 32 {
return Err(crate::Error::InvalidInput);
}
let mut t = [0u8; 32];
expand_generic::<32, _>(HmacSha256::one_shot, prk, info, &mut t, okm);
Ok(())
}
pub fn extract_sha384(salt: &[u8], ikm: &[u8]) -> [u8; 48] {
let s: &[u8] = if salt.is_empty() { &[0u8; 48] } else { salt };
HmacSha384::one_shot(s, ikm)
}
pub fn expand_sha384(prk: &[u8], info: &[u8], okm: &mut [u8]) -> Result<(), crate::Error> {
if okm.len() > 255 * 48 {
return Err(crate::Error::InvalidInput);
}
let mut t = [0u8; 48];
expand_generic::<48, _>(HmacSha384::one_shot, prk, info, &mut t, okm);
Ok(())
}
fn expand_generic<const L: usize, F>(
hmac: F,
prk: &[u8],
info: &[u8],
t: &mut [u8; L],
okm: &mut [u8],
) where
F: Fn(&[u8], &[u8]) -> [u8; L],
{
let mut t_len = 0usize;
let mut counter = 1u8;
let mut done = 0usize;
while done < okm.len() {
let mut input = Vec::with_capacity(t_len + info.len() + 1);
input.extend_from_slice(&t[..t_len]);
input.extend_from_slice(info);
input.push(counter);
*t = hmac(prk, &input);
t_len = L;
let n = (okm.len() - done).min(L);
okm[done..done + n].copy_from_slice(&t[..n]);
done += n;
counter = counter.wrapping_add(1);
}
t.fill(0);
}