Skip to main content

oxicrypto_core/traits/
mac.rs

1use alloc::vec::Vec;
2
3use crate::CryptoError;
4
5/// Message Authentication Code (HMAC, CMAC, KMAC, Poly1305, …).
6///
7/// # Minimum key lengths
8///
9/// For security, MAC keys must meet the following minimum lengths.  Passing a
10/// key shorter than `min_key_len()` is accepted at the API level (the MAC spec
11/// does not mandate rejection) but **reduces the security level significantly**.
12///
13/// | Algorithm | Minimum recommended key | Notes |
14/// |-----------|------------------------|-------|
15/// | HMAC-SHA-256 | 32 bytes (= output length) | RFC 2104: key < block-size is padded |
16/// | HMAC-SHA-384 | 48 bytes | same rule |
17/// | HMAC-SHA-512 | 64 bytes | same rule |
18/// | HMAC-SHA3-256/512 | output length | same rule |
19/// | CMAC-AES-128 | 16 bytes (exact) | AES block cipher key |
20/// | CMAC-AES-256 | 32 bytes (exact) | AES block cipher key |
21/// | Poly1305 | 32 bytes (exact) | one-time key; **must not be reused** |
22/// | KMAC128 / KMAC256 | 16 bytes | NIST SP 800-185 recommendation |
23pub trait Mac: Send + Sync + crate::traits::MaybeDebug {
24    /// Human-readable algorithm identifier (e.g. `"HMAC-SHA-256"`).
25    #[must_use]
26    fn name(&self) -> &'static str;
27    /// Required key length in bytes (the *minimum acceptable* for this MAC).
28    ///
29    /// For HMAC variants this returns the hash output length.
30    /// For CMAC-AES this returns the exact AES key size (16 or 32 bytes).
31    /// For Poly1305 this returns 32 (the one-time key size).
32    #[must_use]
33    fn key_len(&self) -> usize;
34    /// Output tag length in bytes.
35    #[must_use]
36    fn output_len(&self) -> usize;
37    /// Compute a MAC tag for `msg` under `key` and write it into `out`.
38    #[must_use = "result must be checked"]
39    fn mac(&self, key: &[u8], msg: &[u8], out: &mut [u8]) -> Result<(), CryptoError>;
40    /// Verify a MAC tag in constant time.
41    ///
42    /// Returns [`CryptoError::InvalidTag`] on mismatch.
43    #[must_use = "result must be checked"]
44    fn verify(&self, key: &[u8], msg: &[u8], tag: &[u8]) -> Result<(), CryptoError>;
45
46    /// Minimum recommended key length in bytes.
47    ///
48    /// Providing a shorter key is accepted but reduces security.
49    /// Default returns `self.key_len()` (which for most MACs returns `output_len()`).
50    #[must_use]
51    fn min_key_len(&self) -> usize {
52        self.key_len()
53    }
54
55    /// Convenience: compute MAC and return the tag as a [`Vec<u8>`].
56    #[must_use = "result must be checked"]
57    fn mac_to_vec(&self, key: &[u8], msg: &[u8]) -> Result<Vec<u8>, CryptoError> {
58        let mut out = alloc::vec![0u8; self.output_len()];
59        self.mac(key, msg, &mut out)?;
60        Ok(out)
61    }
62}
63
64/// Incremental (streaming) MAC computation.
65pub trait StreamingMac: Send {
66    /// Feed additional data into the MAC state.
67    fn update(&mut self, data: &[u8]);
68    /// Consume the MAC state and write the tag into `out`.
69    #[must_use = "result must be checked"]
70    fn finalize(self, out: &mut [u8]) -> Result<(), CryptoError>;
71    /// Consume the MAC state, compute the tag, and verify against `expected`
72    /// in constant time.
73    #[must_use = "result must be checked"]
74    fn verify(self, expected: &[u8]) -> Result<(), CryptoError>;
75}