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}