1 | use alloc::boxed::Box; |
2 | |
3 | use zeroize::Zeroize; |
4 | |
5 | /// A concrete HMAC implementation, for a single cryptographic hash function. |
6 | /// |
7 | /// You should have one object that implements this trait for HMAC-SHA256, another |
8 | /// for HMAC-SHA384, etc. |
9 | pub trait Hmac: Send + Sync { |
10 | /// Prepare to use `key` as a HMAC key. |
11 | fn with_key(&self, key: &[u8]) -> Box<dyn Key>; |
12 | |
13 | /// Give the length of the underlying hash function. In RFC2104 terminology this is `L`. |
14 | fn hash_output_len(&self) -> usize; |
15 | } |
16 | |
17 | /// A HMAC tag, stored as a value. |
18 | #[derive (Clone)] |
19 | pub struct Tag { |
20 | buf: [u8; Self::MAX_LEN], |
21 | used: usize, |
22 | } |
23 | |
24 | impl Tag { |
25 | /// Build a tag by copying a byte slice. |
26 | /// |
27 | /// The slice can be up to [`Tag::MAX_LEN`] bytes in length. |
28 | pub fn new(bytes: &[u8]) -> Self { |
29 | let mut tag: Tag = Self { |
30 | buf: [0u8; Self::MAX_LEN], |
31 | used: bytes.len(), |
32 | }; |
33 | tag.buf[..bytes.len()].copy_from_slice(src:bytes); |
34 | tag |
35 | } |
36 | |
37 | /// Maximum supported HMAC tag size: supports up to SHA512. |
38 | pub const MAX_LEN: usize = 64; |
39 | } |
40 | |
41 | impl Drop for Tag { |
42 | fn drop(&mut self) { |
43 | self.buf.zeroize(); |
44 | } |
45 | } |
46 | |
47 | impl AsRef<[u8]> for Tag { |
48 | fn as_ref(&self) -> &[u8] { |
49 | &self.buf[..self.used] |
50 | } |
51 | } |
52 | |
53 | /// A HMAC key that is ready for use. |
54 | /// |
55 | /// The algorithm used is implicit in the `Hmac` object that produced the key. |
56 | pub trait Key: Send + Sync { |
57 | /// Calculates a tag over `data` -- a slice of byte slices. |
58 | fn sign(&self, data: &[&[u8]]) -> Tag { |
59 | self.sign_concat(&[], middle:data, &[]) |
60 | } |
61 | |
62 | /// Calculates a tag over the concatenation of `first`, the items in `middle`, and `last`. |
63 | fn sign_concat(&self, first: &[u8], middle: &[&[u8]], last: &[u8]) -> Tag; |
64 | |
65 | /// Returns the length of the tag returned by a computation using |
66 | /// this key. |
67 | fn tag_len(&self) -> usize; |
68 | } |
69 | |