use crate::internal_alloc::Vec;
use noxtls_core::{Error, Result};
use super::{hmac_sha256, hmac_sha384};
#[must_use]
pub fn hkdf_extract_sha256(salt: &[u8], ikm: &[u8]) -> [u8; 32] {
let effective_salt = if salt.is_empty() {
&[0_u8; 32][..]
} else {
salt
};
hmac_sha256(effective_salt, ikm)
}
pub fn hkdf_expand_sha256(prk: &[u8], info: &[u8], len: usize) -> Result<Vec<u8>> {
if prk.len() < 32 {
return Err(Error::InvalidLength("hkdf prk must be at least 32 bytes"));
}
if len > 32 * 255 {
return Err(Error::InvalidLength("hkdf output length exceeds RFC limit"));
}
let mut okm = Vec::with_capacity(len);
let mut t = Vec::new();
let n = len.div_ceil(32);
for idx in 1..=n {
let mut msg = Vec::with_capacity(t.len() + info.len() + 1);
msg.extend_from_slice(&t);
msg.extend_from_slice(info);
msg.push(idx as u8);
t = hmac_sha256(prk, &msg).to_vec();
okm.extend_from_slice(&t);
}
okm.truncate(len);
Ok(okm)
}
#[must_use]
pub fn hkdf_extract_sha384(salt: &[u8], ikm: &[u8]) -> [u8; 48] {
let effective_salt = if salt.is_empty() {
&[0_u8; 48][..]
} else {
salt
};
hmac_sha384(effective_salt, ikm)
}
pub fn hkdf_expand_sha384(prk: &[u8], info: &[u8], len: usize) -> Result<Vec<u8>> {
if prk.len() < 48 {
return Err(Error::InvalidLength("hkdf prk must be at least 48 bytes"));
}
if len > 48 * 255 {
return Err(Error::InvalidLength("hkdf output length exceeds RFC limit"));
}
let mut okm = Vec::with_capacity(len);
let mut t = Vec::new();
let n = len.div_ceil(48);
for idx in 1..=n {
let mut msg = Vec::with_capacity(t.len() + info.len() + 1);
msg.extend_from_slice(&t);
msg.extend_from_slice(info);
msg.push(idx as u8);
t = hmac_sha384(prk, &msg).to_vec();
okm.extend_from_slice(&t);
}
okm.truncate(len);
Ok(okm)
}