Skip to main content

bouncycastle_factory/
mac_factory.rs

1//! MAC factory for creating instances of algorithms that implement the [`MAC`] trait.
2//!
3//! As with all Factory objects, this implements constructions from strings and defaults, and
4//! returns a [`MACFactory`] object which itself implements the [`MAC`] trait as a pass-through to the underlying algorithm.
5//!
6//! Example usage:
7//! Generating and verifying a MAC value for a given piece of data:
8//!
9//! ```
10//! use bouncycastle_core::key_material::{KeyMaterial256, KeyType};
11//! use bouncycastle_core::traits::MAC;
12//! use bouncycastle_hex as hex;
13//! use bouncycastle_factory::AlgorithmFactory;
14//! use bouncycastle_factory::mac_factory::MACFactory;
15//!
16//! let data = b"Hi There!";
17//! let key = KeyMaterial256::from_bytes_as_type(
18//!         // Note: This would be a bad key to use in a production application!
19//!         // But we'll hard-code a silly key for demonstration purposes.
20//!         &hex::decode("0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b").unwrap(),
21//!         KeyType::MACKey,
22//!     ).unwrap();
23//! let hmac = MACFactory::new(bouncycastle_hmac::HMAC_SHA3_256_NAME, &key).unwrap();
24//!
25//! // Generate the MAC value
26//! let mac_value: Vec<u8> = hmac.mac(data);
27//!
28//! // Verify the MAC value
29//! let hmac = MACFactory::new(bouncycastle_hmac::HMAC_SHA3_256_NAME, &key).unwrap();
30//! if hmac.verify(data, &mac_value,) {
31//!     println!("MAC verified successfully!")
32//! } else {
33//!     println!("MAC verification failed")
34//! }
35//! ```
36//!
37//! Equivalently, an instance of [`MACFactory`] may be constructed by string instead of using the constant:
38//!
39//! ```
40//! use bouncycastle_core::key_material::{KeyMaterial256, KeyType};
41//! use bouncycastle_factory::AlgorithmFactory;
42//! use bouncycastle_hex as hex;
43//! use bouncycastle_factory::mac_factory::MACFactory;
44//!
45//! let key = KeyMaterial256::from_bytes_as_type(
46//!         // Note: This would be a bad key to use in a production application!
47//!         // But we'll hard-code a silly key for demonstration purposes.
48//!         &hex::decode("0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b").unwrap(),
49//!         KeyType::MACKey,
50//!     ).unwrap();
51//!
52//! let hmac = MACFactory::new("HMAC-SHA256", &key).unwrap();
53//! ```
54//!
55//! If the algorithm used is not particularly important, the built-in default may be used:
56//!
57//! ```
58//! use bouncycastle_core::key_material::{KeyMaterial256, KeyType};
59//! use bouncycastle_factory::AlgorithmFactory;
60//! use bouncycastle_hex as hex;
61//! use bouncycastle_factory::mac_factory::MACFactory;
62//!
63//! let key = KeyMaterial256::from_bytes_as_type(
64//!         // Note: This would be a bad key to use in a production application!
65//!         // But we'll hard-code a silly key for demonstration purposes.
66//!         &hex::decode("0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b").unwrap(),
67//!         KeyType::MACKey,
68//!     ).unwrap();
69//!
70//! let hmac = MACFactory::default(&key);
71//! ```
72
73use crate::{DEFAULT, DEFAULT_128_BIT, DEFAULT_256_BIT, FactoryError};
74use bouncycastle_core::errors::MACError;
75use bouncycastle_core::key_material::KeyMaterialTrait;
76use bouncycastle_core::traits::{MAC, SecurityStrength};
77use bouncycastle_hmac as hmac;
78use bouncycastle_hmac::{
79    HMAC_SHA3_224_NAME, HMAC_SHA3_256_NAME, HMAC_SHA3_384_NAME, HMAC_SHA3_512_NAME,
80};
81use bouncycastle_hmac::{HMAC_SHA224_NAME, HMAC_SHA256_NAME, HMAC_SHA384_NAME, HMAC_SHA512_NAME};
82use bouncycastle_sha2 as sha2;
83use bouncycastle_sha3 as sha3;
84
85/*** Defaults ***/
86///
87pub const DEFAULT_MAC_NAME: &str = HMAC_SHA256_NAME;
88///
89pub const DEFAULT_128BIT_MAC_NAME: &str = HMAC_SHA256_NAME;
90///
91pub const DEFAULT_256BIT_MAC_NAME: &str = HMAC_SHA256_NAME;
92
93#[allow(non_camel_case_types)]
94
95/// Wrapper object for all algorithms that impl [`MAC`].
96/// MACFactory deviates from the usual AlgorithmFactory trait because MAC objects do not have a no-arg constructor;
97/// instead they have a constructor that takes a [`KeyMaterialTrait`] and can return an error.
98pub enum MACFactory {
99    ///
100    HMAC_SHA224(hmac::HMAC<sha2::SHA224>),
101    ///
102    HMAC_SHA256(hmac::HMAC<sha2::SHA256>),
103    ///
104    HMAC_SHA384(hmac::HMAC<sha2::SHA384>),
105    ///
106    HMAC_SHA512(hmac::HMAC<sha2::SHA512>),
107    ///
108    HMAC_SHA3_224(hmac::HMAC<sha3::SHA3_224>),
109    ///
110    HMAC_SHA3_256(hmac::HMAC<sha3::SHA3_256>),
111    ///
112    HMAC_SHA3_384(hmac::HMAC<sha3::SHA3_384>),
113    ///
114    HMAC_SHA3_512(hmac::HMAC<sha3::SHA3_512>),
115}
116
117impl MACFactory {
118    /// Get the default MAC algorithm.
119    pub fn default(key: &impl KeyMaterialTrait) -> Result<Self, FactoryError> {
120        Self::new(DEFAULT_MAC_NAME, key)
121    }
122    /// Get the default 128-bit MAC algorithm.
123    pub fn default_128_bit(key: &impl KeyMaterialTrait) -> Result<Self, FactoryError> {
124        Self::new(DEFAULT_128BIT_MAC_NAME, key)
125    }
126    /// Get the default 256-bit MAC algorithm.
127    pub fn default_256_bit(key: &impl KeyMaterialTrait) -> Result<Self, FactoryError> {
128        Self::new(DEFAULT_256BIT_MAC_NAME, key)
129    }
130    /// Get an instance of the algorithm by name.
131    pub fn new(alg_name: &str, key: &impl KeyMaterialTrait) -> Result<Self, FactoryError> {
132        match alg_name {
133            DEFAULT => Self::default(key),
134            DEFAULT_128_BIT => Self::default_128_bit(key),
135            DEFAULT_256_BIT => Self::default_256_bit(key),
136            HMAC_SHA224_NAME => Ok(Self::HMAC_SHA224(hmac::HMAC::<sha2::SHA224>::new(key)?)),
137            HMAC_SHA256_NAME => Ok(Self::HMAC_SHA256(hmac::HMAC::<sha2::SHA256>::new(key)?)),
138            HMAC_SHA384_NAME => Ok(Self::HMAC_SHA384(hmac::HMAC::<sha2::SHA384>::new(key)?)),
139            HMAC_SHA512_NAME => Ok(Self::HMAC_SHA512(hmac::HMAC::<sha2::SHA512>::new(key)?)),
140            HMAC_SHA3_224_NAME => Ok(Self::HMAC_SHA3_224(hmac::HMAC::<sha3::SHA3_224>::new(key)?)),
141            HMAC_SHA3_256_NAME => Ok(Self::HMAC_SHA3_256(hmac::HMAC::<sha3::SHA3_256>::new(key)?)),
142            HMAC_SHA3_384_NAME => Ok(Self::HMAC_SHA3_384(hmac::HMAC::<sha3::SHA3_384>::new(key)?)),
143            HMAC_SHA3_512_NAME => Ok(Self::HMAC_SHA3_512(hmac::HMAC::<sha3::SHA3_512>::new(key)?)),
144            _ => Err(FactoryError::UnsupportedAlgorithm(format!(
145                "The algorithm: \"{}\" is not a known MAC",
146                alg_name
147            ))),
148        }
149    }
150}
151
152impl MAC for MACFactory {
153    /// This is a dummy function, required by the [`MAC`] trait. DO NOT call it, it does not do anything.
154    fn new(_key: &impl KeyMaterialTrait) -> Result<Self, MACError> {
155        unimplemented!()
156    }
157
158    /// This is a dummy function, required by the [`MAC`] trait. DO NOT call it, it does not do anything.
159    fn new_allow_weak_key(_key: &impl KeyMaterialTrait) -> Result<Self, MACError> {
160        unimplemented!()
161    }
162
163    fn output_len(&self) -> usize {
164        match self {
165            Self::HMAC_SHA224(h) => h.output_len(),
166            Self::HMAC_SHA256(h) => h.output_len(),
167            Self::HMAC_SHA384(h) => h.output_len(),
168            Self::HMAC_SHA512(h) => h.output_len(),
169            Self::HMAC_SHA3_224(h) => h.output_len(),
170            Self::HMAC_SHA3_256(h) => h.output_len(),
171            Self::HMAC_SHA3_384(h) => h.output_len(),
172            Self::HMAC_SHA3_512(h) => h.output_len(),
173        }
174    }
175
176    fn mac(self, data: &[u8]) -> Vec<u8> {
177        match self {
178            Self::HMAC_SHA224(h) => h.mac(data),
179            Self::HMAC_SHA256(h) => h.mac(data),
180            Self::HMAC_SHA384(h) => h.mac(data),
181            Self::HMAC_SHA512(h) => h.mac(data),
182            Self::HMAC_SHA3_224(h) => h.mac(data),
183            Self::HMAC_SHA3_256(h) => h.mac(data),
184            Self::HMAC_SHA3_384(h) => h.mac(data),
185            Self::HMAC_SHA3_512(h) => h.mac(data),
186        }
187    }
188
189    fn mac_out(self, data: &[u8], out: &mut [u8]) -> Result<usize, MACError> {
190        out.fill(0);
191
192        match self {
193            Self::HMAC_SHA224(h) => h.mac_out(data, out),
194            Self::HMAC_SHA256(h) => h.mac_out(data, out),
195            Self::HMAC_SHA384(h) => h.mac_out(data, out),
196            Self::HMAC_SHA512(h) => h.mac_out(data, out),
197            Self::HMAC_SHA3_224(h) => h.mac_out(data, out),
198            Self::HMAC_SHA3_256(h) => h.mac_out(data, out),
199            Self::HMAC_SHA3_384(h) => h.mac_out(data, out),
200            Self::HMAC_SHA3_512(h) => h.mac_out(data, out),
201        }
202    }
203
204    fn verify(self, data: &[u8], mac: &[u8]) -> bool {
205        match self {
206            Self::HMAC_SHA224(h) => h.verify(data, mac),
207            Self::HMAC_SHA256(h) => h.verify(data, mac),
208            Self::HMAC_SHA384(h) => h.verify(data, mac),
209            Self::HMAC_SHA512(h) => h.verify(data, mac),
210            Self::HMAC_SHA3_224(h) => h.verify(data, mac),
211            Self::HMAC_SHA3_256(h) => h.verify(data, mac),
212            Self::HMAC_SHA3_384(h) => h.verify(data, mac),
213            Self::HMAC_SHA3_512(h) => h.verify(data, mac),
214        }
215    }
216
217    fn do_update(&mut self, data: &[u8]) {
218        match self {
219            Self::HMAC_SHA224(h) => h.do_update(data),
220            Self::HMAC_SHA256(h) => h.do_update(data),
221            Self::HMAC_SHA384(h) => h.do_update(data),
222            Self::HMAC_SHA512(h) => h.do_update(data),
223            Self::HMAC_SHA3_224(h) => h.do_update(data),
224            Self::HMAC_SHA3_256(h) => h.do_update(data),
225            Self::HMAC_SHA3_384(h) => h.do_update(data),
226            Self::HMAC_SHA3_512(h) => h.do_update(data),
227        }
228    }
229
230    fn do_final(self) -> Vec<u8> {
231        match self {
232            Self::HMAC_SHA224(h) => h.do_final(),
233            Self::HMAC_SHA256(h) => h.do_final(),
234            Self::HMAC_SHA384(h) => h.do_final(),
235            Self::HMAC_SHA512(h) => h.do_final(),
236            Self::HMAC_SHA3_224(h) => h.do_final(),
237            Self::HMAC_SHA3_256(h) => h.do_final(),
238            Self::HMAC_SHA3_384(h) => h.do_final(),
239            Self::HMAC_SHA3_512(h) => h.do_final(),
240        }
241    }
242
243    fn do_final_out(self, mut out: &mut [u8]) -> Result<usize, MACError> {
244        out.fill(0);
245
246        match self {
247            Self::HMAC_SHA224(h) => h.do_final_out(&mut out),
248            Self::HMAC_SHA256(h) => h.do_final_out(&mut out),
249            Self::HMAC_SHA384(h) => h.do_final_out(&mut out),
250            Self::HMAC_SHA512(h) => h.do_final_out(&mut out),
251            Self::HMAC_SHA3_224(h) => h.do_final_out(&mut out),
252            Self::HMAC_SHA3_256(h) => h.do_final_out(&mut out),
253            Self::HMAC_SHA3_384(h) => h.do_final_out(&mut out),
254            Self::HMAC_SHA3_512(h) => h.do_final_out(&mut out),
255        }
256    }
257
258    fn do_verify_final(self, mac: &[u8]) -> bool {
259        match self {
260            Self::HMAC_SHA224(h) => h.do_verify_final(mac),
261            Self::HMAC_SHA256(h) => h.do_verify_final(mac),
262            Self::HMAC_SHA384(h) => h.do_verify_final(mac),
263            Self::HMAC_SHA512(h) => h.do_verify_final(mac),
264            Self::HMAC_SHA3_224(h) => h.do_verify_final(mac),
265            Self::HMAC_SHA3_256(h) => h.do_verify_final(mac),
266            Self::HMAC_SHA3_384(h) => h.do_verify_final(mac),
267            Self::HMAC_SHA3_512(h) => h.do_verify_final(mac),
268        }
269    }
270
271    fn max_security_strength(&self) -> SecurityStrength {
272        match self {
273            Self::HMAC_SHA224(h) => h.max_security_strength(),
274            Self::HMAC_SHA256(h) => h.max_security_strength(),
275            Self::HMAC_SHA384(h) => h.max_security_strength(),
276            Self::HMAC_SHA512(h) => h.max_security_strength(),
277            Self::HMAC_SHA3_224(h) => h.max_security_strength(),
278            Self::HMAC_SHA3_256(h) => h.max_security_strength(),
279            Self::HMAC_SHA3_384(h) => h.max_security_strength(),
280            Self::HMAC_SHA3_512(h) => h.max_security_strength(),
281        }
282    }
283}