use crate::hash::{Digest, Sha256, Sha384, Sha512};
use crate::kdf::{hkdf_expand, hkdf_extract};
use alloc::vec::Vec;
#[derive(Copy, Clone, PartialEq, Eq, Debug)]
pub enum HpkeKdf {
HkdfSha256,
HkdfSha384,
HkdfSha512,
}
impl HpkeKdf {
pub const fn id(self) -> u16 {
match self {
HpkeKdf::HkdfSha256 => 0x0001,
HpkeKdf::HkdfSha384 => 0x0002,
HpkeKdf::HkdfSha512 => 0x0003,
}
}
pub const fn output_len(self) -> usize {
match self {
HpkeKdf::HkdfSha256 => Sha256::OUTPUT_LEN,
HpkeKdf::HkdfSha384 => Sha384::OUTPUT_LEN,
HpkeKdf::HkdfSha512 => Sha512::OUTPUT_LEN,
}
}
pub(crate) fn extract(self, salt: &[u8], ikm: &[u8]) -> Vec<u8> {
match self {
HpkeKdf::HkdfSha256 => {
let prk = hkdf_extract::<Sha256>(salt, ikm);
prk.as_ref().to_vec()
}
HpkeKdf::HkdfSha384 => {
let prk = hkdf_extract::<Sha384>(salt, ikm);
prk.as_ref().to_vec()
}
HpkeKdf::HkdfSha512 => {
let prk = hkdf_extract::<Sha512>(salt, ikm);
prk.as_ref().to_vec()
}
}
}
pub(crate) fn expand(self, prk: &[u8], info: &[u8], out: &mut [u8]) {
assert_eq!(
prk.len(),
self.output_len(),
"HPKE HKDF prk length must equal output_len()"
);
match self {
HpkeKdf::HkdfSha256 => {
let mut p = <Sha256 as Digest>::zeroed_output();
p.as_mut().copy_from_slice(prk);
hkdf_expand::<Sha256>(&p, info, out);
}
HpkeKdf::HkdfSha384 => {
let mut p = <Sha384 as Digest>::zeroed_output();
p.as_mut().copy_from_slice(prk);
hkdf_expand::<Sha384>(&p, info, out);
}
HpkeKdf::HkdfSha512 => {
let mut p = <Sha512 as Digest>::zeroed_output();
p.as_mut().copy_from_slice(prk);
hkdf_expand::<Sha512>(&p, info, out);
}
}
}
}