dcrypt_algorithms/mac/
mod.rs1use crate::error::Result;
7use subtle::ConstantTimeEq;
8use zeroize::Zeroize;
9
10pub mod hmac;
11pub mod poly1305;
12
13pub use hmac::Hmac;
15pub use poly1305::{Poly1305, POLY1305_KEY_SIZE, POLY1305_TAG_SIZE};
16
17pub trait MacAlgorithm {
19 const KEY_SIZE: usize;
21
22 const TAG_SIZE: usize;
24
25 const BLOCK_SIZE: usize;
27
28 fn name() -> &'static str;
30}
31
32pub trait Mac: Sized {
34 type Key: AsRef<[u8]> + AsMut<[u8]> + Clone + Zeroize;
36
37 type Tag: AsRef<[u8]> + AsMut<[u8]> + Clone;
39
40 fn new(key: &[u8]) -> Result<Self>;
42
43 fn update(&mut self, data: &[u8]) -> Result<&mut Self>;
45
46 fn finalize(&mut self) -> Result<Self::Tag>;
48
49 fn reset(&mut self) -> Result<()>;
51
52 fn compute_tag(key: &[u8], data: &[u8]) -> Result<Self::Tag> {
54 let mut mac = Self::new(key)?;
55 mac.update(data)?;
56 mac.finalize()
57 }
58
59 fn verify_tag(key: &[u8], data: &[u8], tag: &[u8]) -> Result<bool> {
61 let computed = Self::compute_tag(key, data)?;
62
63 if computed.as_ref().len() != tag.len() {
64 return Ok(false);
65 }
66
67 Ok(computed.as_ref().ct_eq(tag).into())
68 }
69}
70
71pub trait MacBuilder<'a, M: Mac>: Sized {
73 fn update(self, data: &'a [u8]) -> Result<Self>;
75
76 fn update_multi(self, data: &[&'a [u8]]) -> Result<Self>;
78
79 fn finalize(self) -> Result<M::Tag>;
81
82 fn verify(self, expected: &'a [u8]) -> Result<bool>;
84}
85
86pub struct GenericMacBuilder<'a, M: Mac> {
88 mac: &'a mut M,
90}
91
92impl<'a, M: Mac> MacBuilder<'a, M> for GenericMacBuilder<'a, M> {
93 fn update(self, data: &'a [u8]) -> Result<Self> {
94 self.mac.update(data)?;
95 Ok(self)
96 }
97
98 fn update_multi(self, data: &[&'a [u8]]) -> Result<Self> {
99 for chunk in data {
100 self.mac.update(chunk)?;
101 }
102 Ok(self)
103 }
104
105 fn finalize(self) -> Result<M::Tag> {
106 self.mac.finalize()
107 }
108
109 fn verify(self, expected: &'a [u8]) -> Result<bool> {
110 let tag = self.mac.finalize()?;
111
112 if tag.as_ref().len() != expected.len() {
113 return Ok(false);
114 }
115
116 Ok(tag.as_ref().ct_eq(expected).into())
117 }
118}
119
120pub trait MacExt: Mac {
122 fn builder(&mut self) -> GenericMacBuilder<'_, Self>;
124}
125
126impl<T: Mac> MacExt for T {
127 fn builder(&mut self) -> GenericMacBuilder<'_, Self> {
128 GenericMacBuilder { mac: self }
129 }
130}