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 core_interface::key_material::{KeyMaterial256, KeyType};
11//! use core_interface::traits::MAC;
12//! use encoders::hex;
13//! use factory::AlgorithmFactory;
14//! use 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(hmac::HMAC_SHA3_256_NAME).unwrap();
24//!
25//! // Generate the MAC value
26//! let mac_value: Vec<u8> = hmac.mac(&key, data).unwrap();
27//!
28//! // Verify the MAC value
29//! match hmac.verify(&key, data, &mac_value,) {
30//!     Ok(()) => println!("MAC verified successfully!"),
31//!     Err(e) => println!("MAC verification failed"),
32//! }
33//! ```
34//!
35//! You can equivalently construct an instance of [MACFactory] by string instead of using the constant:
36//!
37//! ```
38//! use factory::AlgorithmFactory;
39//! use factory::mac_factory::MACFactory;
40//!
41//! let hmac = MACFactory::new("HMAC-SHA256").unwrap();
42//! ```
43//!
44//! Or if you don't particularly care which algorithm is used, you can use the built-in default:
45//!
46//! ```
47//! use factory::AlgorithmFactory;
48//! use factory::mac_factory::MACFactory;
49//!
50//! let hmac = MACFactory::default();
51//! ```
52
53use bouncycastle_core_interface::errors::MACError;
54use crate::{FactoryError, DEFAULT, DEFAULT_128_BIT, DEFAULT_256_BIT};
55use bouncycastle_core_interface::traits::{KeyMaterial, SecurityStrength, MAC};
56use bouncycastle_hmac as hmac;
57use bouncycastle_sha2 as sha2;
58use bouncycastle_sha3 as sha3;
59use bouncycastle_hmac::{HMAC_SHA224_NAME, HMAC_SHA256_NAME, HMAC_SHA384_NAME, HMAC_SHA512_NAME};
60use bouncycastle_hmac::{HMAC_SHA3_224_NAME, HMAC_SHA3_256_NAME, HMAC_SHA3_384_NAME, HMAC_SHA3_512_NAME};
61
62/*** Defaults ***/
63pub const DEFAULT_MAC_NAME: &str = HMAC_SHA256_NAME;
64pub const DEFAULT_128BIT_MAC_NAME: &str = HMAC_SHA256_NAME;
65pub const DEFAULT_256BIT_MAC_NAME: &str = HMAC_SHA256_NAME;
66
67#[allow(non_camel_case_types)]
68
69/// MACFactory deviates from the usual AlgorithmFactory trait because MAC objects do not have a no-arg constructor;
70/// instead they have a constructor that takes a [KeyMaterial] and can return an error.
71pub enum MACFactory {
72    // All members must impl MAC.
73    HMAC_SHA224(hmac::HMAC<sha2::SHA224>),
74    HMAC_SHA256(hmac::HMAC<sha2::SHA256>),
75    HMAC_SHA384(hmac::HMAC<sha2::SHA384>),
76    HMAC_SHA512(hmac::HMAC<sha2::SHA512>),
77    HMAC_SHA3_224(hmac::HMAC<sha3::SHA3_224>),
78    HMAC_SHA3_256(hmac::HMAC<sha3::SHA3_256>),
79    HMAC_SHA3_384(hmac::HMAC<sha3::SHA3_384>),
80    HMAC_SHA3_512(hmac::HMAC<sha3::SHA3_512>),
81}
82
83
84impl MACFactory {
85    pub fn default(key: &impl KeyMaterial) -> Result<Self, FactoryError> {
86        Self::new(DEFAULT_MAC_NAME, key)
87    }
88
89    pub fn default_128_bit(key: &impl KeyMaterial) -> Result<Self, FactoryError> {
90        Self::new(DEFAULT_128BIT_MAC_NAME, key)
91    }
92
93    pub fn default_256_bit(key: &impl KeyMaterial) -> Result<Self, FactoryError> {
94        Self::new(DEFAULT_256BIT_MAC_NAME, key)
95    }
96
97    pub fn new(alg_name: &str, key: &impl KeyMaterial) -> Result<Self, FactoryError> {
98        match alg_name {
99            DEFAULT => Self::default(key),
100            DEFAULT_128_BIT => Self::default_128_bit(key),
101            DEFAULT_256_BIT => Self::default_256_bit(key),
102            HMAC_SHA224_NAME => Ok(Self::HMAC_SHA224(hmac::HMAC::<sha2::SHA224>::new(key)?)),
103            HMAC_SHA256_NAME => Ok(Self::HMAC_SHA256(hmac::HMAC::<sha2::SHA256>::new(key)?)),
104            HMAC_SHA384_NAME => Ok(Self::HMAC_SHA384(hmac::HMAC::<sha2::SHA384>::new(key)?)),
105            HMAC_SHA512_NAME => Ok(Self::HMAC_SHA512(hmac::HMAC::<sha2::SHA512>::new(key)?)),
106            HMAC_SHA3_224_NAME => Ok(Self::HMAC_SHA3_224(hmac::HMAC::<sha3::SHA3_224>::new(key)?)),
107            HMAC_SHA3_256_NAME => Ok(Self::HMAC_SHA3_256(hmac::HMAC::<sha3::SHA3_256>::new(key)?)),
108            HMAC_SHA3_384_NAME => Ok(Self::HMAC_SHA3_384(hmac::HMAC::<sha3::SHA3_384>::new(key)?)),
109            HMAC_SHA3_512_NAME => Ok(Self::HMAC_SHA3_512(hmac::HMAC::<sha3::SHA3_512>::new(key)?)),
110            _ => Err(FactoryError::UnsupportedAlgorithm(format!("The algorithm: \"{}\" is not a known MAC", alg_name))),
111        }
112    }
113}
114
115impl MAC for MACFactory {
116    /// This is a dummy function, required by the [MAC] trait. Don't call it, it doesn't do anything.
117    fn new(_key: &impl KeyMaterial) -> Result<Self, MACError> {
118        unimplemented!()
119    }
120
121    /// This is a dummy function, required by the [MAC] trait. Don't call it, it doesn't do anything.
122    fn new_allow_weak_key(_key: &impl KeyMaterial) -> Result<Self, MACError> {
123        unimplemented!()
124    }
125
126    fn output_len(&self) -> usize {
127        match self {
128            Self::HMAC_SHA224(h) => h.output_len(),
129            Self::HMAC_SHA256(h) => h.output_len(),
130            Self::HMAC_SHA384(h) => h.output_len(),
131            Self::HMAC_SHA512(h) => h.output_len(),
132            Self::HMAC_SHA3_224(h) => h.output_len(),
133            Self::HMAC_SHA3_256(h) => h.output_len(),
134            Self::HMAC_SHA3_384(h) => h.output_len(),
135            Self::HMAC_SHA3_512(h) => h.output_len(),
136        }
137    }
138
139    fn mac(self, data: &[u8]) -> Vec<u8> {
140        match self {
141            Self::HMAC_SHA224(h) => h.mac(data),
142            Self::HMAC_SHA256(h) => h.mac(data),
143            Self::HMAC_SHA384(h) => h.mac(data),
144            Self::HMAC_SHA512(h) => h.mac(data),
145            Self::HMAC_SHA3_224(h) => h.mac(data),
146            Self::HMAC_SHA3_256(h) => h.mac(data),
147            Self::HMAC_SHA3_384(h) => h.mac(data),
148            Self::HMAC_SHA3_512(h) => h.mac(data),
149        }
150    }
151
152    fn mac_out(self, data: &[u8], out: &mut [u8]) -> Result<usize, MACError> {
153        match self {
154            Self::HMAC_SHA224(h) => h.mac_out(data, out),
155            Self::HMAC_SHA256(h) => h.mac_out(data, out),
156            Self::HMAC_SHA384(h) => h.mac_out(data, out),
157            Self::HMAC_SHA512(h) => h.mac_out(data, out),
158            Self::HMAC_SHA3_224(h) => h.mac_out(data, out),
159            Self::HMAC_SHA3_256(h) => h.mac_out(data, out),
160            Self::HMAC_SHA3_384(h) => h.mac_out(data, out),
161            Self::HMAC_SHA3_512(h) => h.mac_out(data, out),
162        }
163    }
164
165    fn verify(self, data: &[u8], mac: &[u8]) -> bool {
166        match self {
167            Self::HMAC_SHA224(h) => h.verify(data, mac),
168            Self::HMAC_SHA256(h) => h.verify(data, mac),
169            Self::HMAC_SHA384(h) => h.verify(data, mac),
170            Self::HMAC_SHA512(h) => h.verify(data, mac),
171            Self::HMAC_SHA3_224(h) => h.verify(data, mac),
172            Self::HMAC_SHA3_256(h) => h.verify(data, mac),
173            Self::HMAC_SHA3_384(h) => h.verify(data, mac),
174            Self::HMAC_SHA3_512(h) => h.verify(data, mac),
175        }
176    }
177
178    fn do_update(&mut self, data: &[u8]) {
179        match self {
180            Self::HMAC_SHA224(h) => h.do_update(data),
181            Self::HMAC_SHA256(h) => h.do_update(data),
182            Self::HMAC_SHA384(h) => h.do_update(data),
183            Self::HMAC_SHA512(h) => h.do_update(data),
184            Self::HMAC_SHA3_224(h) => h.do_update(data),
185            Self::HMAC_SHA3_256(h) => h.do_update(data),
186            Self::HMAC_SHA3_384(h) => h.do_update(data),
187            Self::HMAC_SHA3_512(h) => h.do_update(data),
188        }
189    }
190
191    fn do_final(self) -> Vec<u8> {
192        match self {
193            Self::HMAC_SHA224(h) => h.do_final(),
194            Self::HMAC_SHA256(h) => h.do_final(),
195            Self::HMAC_SHA384(h) => h.do_final(),
196            Self::HMAC_SHA512(h) => h.do_final(),
197            Self::HMAC_SHA3_224(h) => h.do_final(),
198            Self::HMAC_SHA3_256(h) => h.do_final(),
199            Self::HMAC_SHA3_384(h) => h.do_final(),
200            Self::HMAC_SHA3_512(h) => h.do_final(),
201        }
202    }
203
204    fn do_final_out(self, mut out: &mut [u8]) -> Result<usize, MACError> {
205        match self {
206            Self::HMAC_SHA224(h) => h.do_final_out(&mut out),
207            Self::HMAC_SHA256(h) => h.do_final_out(&mut out),
208            Self::HMAC_SHA384(h) => h.do_final_out(&mut out),
209            Self::HMAC_SHA512(h) => h.do_final_out(&mut out),
210            Self::HMAC_SHA3_224(h) => h.do_final_out(&mut out),
211            Self::HMAC_SHA3_256(h) => h.do_final_out(&mut out),
212            Self::HMAC_SHA3_384(h) => h.do_final_out(&mut out),
213            Self::HMAC_SHA3_512(h) => h.do_final_out(&mut out),
214        }
215    }
216
217    fn do_verify_final(self, mac: &[u8]) -> bool {
218        match self {
219            Self::HMAC_SHA224(h) => h.do_verify_final(mac),
220            Self::HMAC_SHA256(h) => h.do_verify_final(mac),
221            Self::HMAC_SHA384(h) => h.do_verify_final(mac),
222            Self::HMAC_SHA512(h) => h.do_verify_final(mac),
223            Self::HMAC_SHA3_224(h) => h.do_verify_final(mac),
224            Self::HMAC_SHA3_256(h) => h.do_verify_final(mac),
225            Self::HMAC_SHA3_384(h) => h.do_verify_final(mac),
226            Self::HMAC_SHA3_512(h) => h.do_verify_final(mac),
227        }
228    }
229
230    fn max_security_strength(&self) -> SecurityStrength {
231        match self {
232            Self::HMAC_SHA224(h) => h.max_security_strength(),
233            Self::HMAC_SHA256(h) => h.max_security_strength(),
234            Self::HMAC_SHA384(h) => h.max_security_strength(),
235            Self::HMAC_SHA512(h) => h.max_security_strength(),
236            Self::HMAC_SHA3_224(h) => h.max_security_strength(),
237            Self::HMAC_SHA3_256(h) => h.max_security_strength(),
238            Self::HMAC_SHA3_384(h) => h.max_security_strength(),
239            Self::HMAC_SHA3_512(h) => h.max_security_strength(),
240        }
241    }
242}