libcrux/
hmac.rs

1//! HMAC
2//!
3//! This module implements HMAC on SHA 1 and SHA 2 (except for SHA 224).
4
5use crate::hkdf;
6
7/// The HMAC algorithm defining the used hash function.
8#[derive(Copy, Clone, Debug, PartialEq)]
9pub enum Algorithm {
10    Sha1,
11    // Not implemented
12    // Sha224
13    Sha256,
14    Sha384,
15    Sha512,
16}
17
18impl From<hkdf::Algorithm> for Algorithm {
19    fn from(value: hkdf::Algorithm) -> Self {
20        match value {
21            hkdf::Algorithm::Sha256 => Self::Sha256,
22            hkdf::Algorithm::Sha384 => Self::Sha384,
23            hkdf::Algorithm::Sha512 => Self::Sha512,
24        }
25    }
26}
27
28/// Get the tag size for a given algorithm.
29pub const fn tag_size(alg: Algorithm) -> usize {
30    match alg {
31        Algorithm::Sha1 => 20,
32        Algorithm::Sha256 => 32,
33        Algorithm::Sha384 => 48,
34        Algorithm::Sha512 => 64,
35    }
36}
37
38/// Compute the HMAC value with the given `alg` and `key` on `data` with an
39/// output tag length of `tag_length`.
40/// Returns a vector of length `tag_length`.
41pub fn hmac(alg: Algorithm, key: &[u8], data: &[u8], tag_length: Option<usize>) -> Vec<u8> {
42    let native_tag_length = tag_size(alg);
43    let tag_length = match tag_length {
44        Some(v) => v,
45        None => native_tag_length,
46    };
47    let mut dst: Vec<_> = match alg {
48        Algorithm::Sha1 => crate::hacl::hmac::sha1(key, data).into(),
49        Algorithm::Sha256 => crate::hacl::hmac::sha2_256(key, data).into(),
50        Algorithm::Sha384 => crate::hacl::hmac::sha2_384(key, data).into(),
51        Algorithm::Sha512 => crate::hacl::hmac::sha2_512(key, data).into(),
52    };
53    dst.truncate(tag_length);
54    dst
55}