libcrux/
hkdf.rs

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
//! HKDF
//!
//! This module implements HKDF on SHA 1 and SHA 2 (except for SHA 224).

/// The HKDF algorithm defining the used hash function.
#[derive(Copy, Clone, Debug, PartialEq)]
pub enum Algorithm {
    Sha256,
    Sha384,
    Sha512,
}

/// HKDF Errors
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum Error {
    OkmLengthTooLarge,
}

/// HKDF extract using hash function `mode`, `salt`, and the input key material `ikm`.
/// Returns the pre-key material in a vector of tag length.
pub fn extract(alg: Algorithm, salt: impl AsRef<[u8]>, ikm: impl AsRef<[u8]>) -> Vec<u8> {
    match alg {
        Algorithm::Sha256 => {
            crate::hacl::hkdf::sha2_256::extract(salt.as_ref(), ikm.as_ref()).into()
        }
        Algorithm::Sha384 => {
            crate::hacl::hkdf::sha2_384::extract(salt.as_ref(), ikm.as_ref()).into()
        }
        Algorithm::Sha512 => {
            crate::hacl::hkdf::sha2_512::extract(salt.as_ref(), ikm.as_ref()).into()
        }
    }
}

/// HKDF expand using hash function `mode`, pre-key material `prk`, `info`, and output length `okm_len`.
/// Returns the key material in a vector of length `okm_len` or [`Error::OkmLengthTooLarge`]
/// if the requested output length is too large.
pub fn expand(
    alg: Algorithm,
    prk: impl AsRef<[u8]>,
    info: impl AsRef<[u8]>,
    okm_len: usize,
) -> Result<Vec<u8>, Error> {
    match alg {
        Algorithm::Sha256 => {
            crate::hacl::hkdf::sha2_256::vec::expand(prk.as_ref(), info.as_ref(), okm_len)
                .map_err(|_| Error::OkmLengthTooLarge)
        }
        Algorithm::Sha384 => {
            crate::hacl::hkdf::sha2_384::vec::expand(prk.as_ref(), info.as_ref(), okm_len)
                .map_err(|_| Error::OkmLengthTooLarge)
        }
        Algorithm::Sha512 => {
            crate::hacl::hkdf::sha2_512::vec::expand(prk.as_ref(), info.as_ref(), okm_len)
                .map_err(|_| Error::OkmLengthTooLarge)
        }
    }
}

/// HKDF using hash function `mode`, `salt`, input key material `ikm`, `info`, and output length `okm_len`.
/// Calls `extract` and `expand` with the given input.
/// Returns the key material in a vector of length `okm_len` or [`Error::OkmLengthTooLarge`]
/// if the requested output length is too large.
pub fn hkdf(
    mode: Algorithm,
    salt: &[u8],
    ikm: &[u8],
    info: &[u8],
    okm_len: usize,
) -> Result<Vec<u8>, Error> {
    let prk = extract(mode, salt, ikm);
    expand(mode, prk, info, okm_len)
}