libcrux/
hkdf.rs

1//! HKDF
2//!
3//! This module implements HKDF on SHA 1 and SHA 2 (except for SHA 224).
4
5/// The HKDF algorithm defining the used hash function.
6#[derive(Copy, Clone, Debug, PartialEq)]
7pub enum Algorithm {
8    Sha256,
9    Sha384,
10    Sha512,
11}
12
13/// HKDF Errors
14#[derive(Debug, Clone, Copy, PartialEq, Eq)]
15pub enum Error {
16    OkmLengthTooLarge,
17}
18
19/// HKDF extract using hash function `mode`, `salt`, and the input key material `ikm`.
20/// Returns the pre-key material in a vector of tag length.
21pub fn extract(alg: Algorithm, salt: impl AsRef<[u8]>, ikm: impl AsRef<[u8]>) -> Vec<u8> {
22    match alg {
23        Algorithm::Sha256 => {
24            crate::hacl::hkdf::sha2_256::extract(salt.as_ref(), ikm.as_ref()).into()
25        }
26        Algorithm::Sha384 => {
27            crate::hacl::hkdf::sha2_384::extract(salt.as_ref(), ikm.as_ref()).into()
28        }
29        Algorithm::Sha512 => {
30            crate::hacl::hkdf::sha2_512::extract(salt.as_ref(), ikm.as_ref()).into()
31        }
32    }
33}
34
35/// HKDF expand using hash function `mode`, pre-key material `prk`, `info`, and output length `okm_len`.
36/// Returns the key material in a vector of length `okm_len` or [`Error::OkmLengthTooLarge`]
37/// if the requested output length is too large.
38pub fn expand(
39    alg: Algorithm,
40    prk: impl AsRef<[u8]>,
41    info: impl AsRef<[u8]>,
42    okm_len: usize,
43) -> Result<Vec<u8>, Error> {
44    match alg {
45        Algorithm::Sha256 => {
46            crate::hacl::hkdf::sha2_256::vec::expand(prk.as_ref(), info.as_ref(), okm_len)
47                .map_err(|_| Error::OkmLengthTooLarge)
48        }
49        Algorithm::Sha384 => {
50            crate::hacl::hkdf::sha2_384::vec::expand(prk.as_ref(), info.as_ref(), okm_len)
51                .map_err(|_| Error::OkmLengthTooLarge)
52        }
53        Algorithm::Sha512 => {
54            crate::hacl::hkdf::sha2_512::vec::expand(prk.as_ref(), info.as_ref(), okm_len)
55                .map_err(|_| Error::OkmLengthTooLarge)
56        }
57    }
58}
59
60/// HKDF using hash function `mode`, `salt`, input key material `ikm`, `info`, and output length `okm_len`.
61/// Calls `extract` and `expand` with the given input.
62/// Returns the key material in a vector of length `okm_len` or [`Error::OkmLengthTooLarge`]
63/// if the requested output length is too large.
64pub fn hkdf(
65    mode: Algorithm,
66    salt: &[u8],
67    ikm: &[u8],
68    info: &[u8],
69    okm_len: usize,
70) -> Result<Vec<u8>, Error> {
71    let prk = extract(mode, salt, ikm);
72    expand(mode, prk, info, okm_len)
73}