#![no_std]
extern crate alloc;
use alloc::vec::Vec;
pub mod hacl;
mod impl_hacl;
pub use impl_hacl::{HkdfSha2_256, HkdfSha2_384, HkdfSha2_512};
pub trait HkdfMode<const HASH_LEN: usize> {
const MODE: Algorithm;
fn extract(prk: &mut [u8; HASH_LEN], salt: &[u8], ikm: &[u8]) -> Result<(), Error>;
fn expand<const OKM_LEN: usize>(
okm: &mut [u8; OKM_LEN],
prk: &[u8],
info: &[u8],
) -> Result<(), Error>;
fn expand_vec(prk: &[u8], info: &[u8], okm_len: usize) -> Result<Vec<u8>, Error>;
#[inline(always)]
fn hkdf<const OKM_LEN: usize>(
okm: &mut [u8; OKM_LEN],
salt: &[u8],
ikm: &[u8],
info: &[u8],
) -> Result<(), Error> {
let mut prk = [0u8; HASH_LEN];
Self::extract(&mut prk, salt, ikm)?;
Self::expand(okm, &prk, info)
}
#[inline(always)]
fn hkdf_vec(salt: &[u8], ikm: &[u8], info: &[u8], okm_len: usize) -> Result<Vec<u8>, Error> {
let mut prk = [0u8; HASH_LEN];
Self::extract(&mut prk, salt, ikm)?;
Self::expand_vec(&prk, info, okm_len)
}
}
#[derive(Copy, Clone, Debug, PartialEq)]
pub enum Algorithm {
Sha256,
Sha384,
Sha512,
}
impl Algorithm {
pub const fn hash_len(self) -> usize {
match self {
Algorithm::Sha256 => 32,
Algorithm::Sha384 => 48,
Algorithm::Sha512 => 64,
}
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum Error {
OkmTooLarge,
ArgumentsTooLarge,
}
#[inline(always)]
pub fn extract(
alg: Algorithm,
salt: impl AsRef<[u8]>,
ikm: impl AsRef<[u8]>,
) -> Result<Vec<u8>, Error> {
let salt = salt.as_ref();
let ikm = ikm.as_ref();
match alg {
Algorithm::Sha256 => allocbuf(|prk| HkdfSha2_256::extract(prk, salt, ikm)),
Algorithm::Sha384 => allocbuf(|prk| HkdfSha2_384::extract(prk, salt, ikm)),
Algorithm::Sha512 => allocbuf(|prk| HkdfSha2_512::extract(prk, salt, ikm)),
}
}
#[inline(always)]
pub fn expand(
alg: Algorithm,
prk: impl AsRef<[u8]>,
info: impl AsRef<[u8]>,
okm_len: usize,
) -> Result<Vec<u8>, Error> {
let prk = prk.as_ref();
let info = info.as_ref();
match alg {
Algorithm::Sha256 => HkdfSha2_256::expand_vec(prk, info, okm_len),
Algorithm::Sha384 => HkdfSha2_384::expand_vec(prk, info, okm_len),
Algorithm::Sha512 => HkdfSha2_512::expand_vec(prk, info, okm_len),
}
}
#[inline(always)]
pub fn hkdf(
mode: Algorithm,
salt: impl AsRef<[u8]>,
ikm: impl AsRef<[u8]>,
info: impl AsRef<[u8]>,
okm_len: usize,
) -> Result<Vec<u8>, Error> {
let salt = salt.as_ref();
let ikm = ikm.as_ref();
let info = info.as_ref();
match mode {
Algorithm::Sha256 => HkdfSha2_256::hkdf_vec(salt, ikm, info, okm_len),
Algorithm::Sha384 => HkdfSha2_384::hkdf_vec(salt, ikm, info, okm_len),
Algorithm::Sha512 => HkdfSha2_512::hkdf_vec(salt, ikm, info, okm_len),
}
}
#[inline(always)]
fn allocbuf<const N: usize, T, E, F: Fn(&mut [u8; N]) -> Result<T, E>>(f: F) -> Result<Vec<u8>, E> {
let mut buf = [0u8; N];
f(&mut buf).map(|_| buf.into())
}