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//! You can equivalently construct an instance of [MACFactory] 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//! Or if you don't particularly care which algorithm is used, you can use the built-in default:
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 ***/
86pub const DEFAULT_MAC_NAME: &str = HMAC_SHA256_NAME;
87pub const DEFAULT_128BIT_MAC_NAME: &str = HMAC_SHA256_NAME;
88pub const DEFAULT_256BIT_MAC_NAME: &str = HMAC_SHA256_NAME;
89
90#[allow(non_camel_case_types)]
91
92/// MACFactory deviates from the usual AlgorithmFactory trait because MAC objects do not have a no-arg constructor;
93/// instead they have a constructor that takes a [KeyMaterialTrait] and can return an error.
94pub enum MACFactory {
95    // All members must impl MAC.
96    HMAC_SHA224(hmac::HMAC<sha2::SHA224>),
97    HMAC_SHA256(hmac::HMAC<sha2::SHA256>),
98    HMAC_SHA384(hmac::HMAC<sha2::SHA384>),
99    HMAC_SHA512(hmac::HMAC<sha2::SHA512>),
100    HMAC_SHA3_224(hmac::HMAC<sha3::SHA3_224>),
101    HMAC_SHA3_256(hmac::HMAC<sha3::SHA3_256>),
102    HMAC_SHA3_384(hmac::HMAC<sha3::SHA3_384>),
103    HMAC_SHA3_512(hmac::HMAC<sha3::SHA3_512>),
104}
105
106impl MACFactory {
107    pub fn default(key: &impl KeyMaterialTrait) -> Result<Self, FactoryError> {
108        Self::new(DEFAULT_MAC_NAME, key)
109    }
110
111    pub fn default_128_bit(key: &impl KeyMaterialTrait) -> Result<Self, FactoryError> {
112        Self::new(DEFAULT_128BIT_MAC_NAME, key)
113    }
114
115    pub fn default_256_bit(key: &impl KeyMaterialTrait) -> Result<Self, FactoryError> {
116        Self::new(DEFAULT_256BIT_MAC_NAME, key)
117    }
118
119    pub fn new(alg_name: &str, key: &impl KeyMaterialTrait) -> Result<Self, FactoryError> {
120        match alg_name {
121            DEFAULT => Self::default(key),
122            DEFAULT_128_BIT => Self::default_128_bit(key),
123            DEFAULT_256_BIT => Self::default_256_bit(key),
124            HMAC_SHA224_NAME => Ok(Self::HMAC_SHA224(hmac::HMAC::<sha2::SHA224>::new(key)?)),
125            HMAC_SHA256_NAME => Ok(Self::HMAC_SHA256(hmac::HMAC::<sha2::SHA256>::new(key)?)),
126            HMAC_SHA384_NAME => Ok(Self::HMAC_SHA384(hmac::HMAC::<sha2::SHA384>::new(key)?)),
127            HMAC_SHA512_NAME => Ok(Self::HMAC_SHA512(hmac::HMAC::<sha2::SHA512>::new(key)?)),
128            HMAC_SHA3_224_NAME => Ok(Self::HMAC_SHA3_224(hmac::HMAC::<sha3::SHA3_224>::new(key)?)),
129            HMAC_SHA3_256_NAME => Ok(Self::HMAC_SHA3_256(hmac::HMAC::<sha3::SHA3_256>::new(key)?)),
130            HMAC_SHA3_384_NAME => Ok(Self::HMAC_SHA3_384(hmac::HMAC::<sha3::SHA3_384>::new(key)?)),
131            HMAC_SHA3_512_NAME => Ok(Self::HMAC_SHA3_512(hmac::HMAC::<sha3::SHA3_512>::new(key)?)),
132            _ => Err(FactoryError::UnsupportedAlgorithm(format!(
133                "The algorithm: \"{}\" is not a known MAC",
134                alg_name
135            ))),
136        }
137    }
138}
139
140impl MAC for MACFactory {
141    /// This is a dummy function, required by the [MAC] trait. Don't call it, it doesn't do anything.
142    fn new(_key: &impl KeyMaterialTrait) -> Result<Self, MACError> {
143        unimplemented!()
144    }
145
146    /// This is a dummy function, required by the [MAC] trait. Don't call it, it doesn't do anything.
147    fn new_allow_weak_key(_key: &impl KeyMaterialTrait) -> Result<Self, MACError> {
148        unimplemented!()
149    }
150
151    fn output_len(&self) -> usize {
152        match self {
153            Self::HMAC_SHA224(h) => h.output_len(),
154            Self::HMAC_SHA256(h) => h.output_len(),
155            Self::HMAC_SHA384(h) => h.output_len(),
156            Self::HMAC_SHA512(h) => h.output_len(),
157            Self::HMAC_SHA3_224(h) => h.output_len(),
158            Self::HMAC_SHA3_256(h) => h.output_len(),
159            Self::HMAC_SHA3_384(h) => h.output_len(),
160            Self::HMAC_SHA3_512(h) => h.output_len(),
161        }
162    }
163
164    fn mac(self, data: &[u8]) -> Vec<u8> {
165        match self {
166            Self::HMAC_SHA224(h) => h.mac(data),
167            Self::HMAC_SHA256(h) => h.mac(data),
168            Self::HMAC_SHA384(h) => h.mac(data),
169            Self::HMAC_SHA512(h) => h.mac(data),
170            Self::HMAC_SHA3_224(h) => h.mac(data),
171            Self::HMAC_SHA3_256(h) => h.mac(data),
172            Self::HMAC_SHA3_384(h) => h.mac(data),
173            Self::HMAC_SHA3_512(h) => h.mac(data),
174        }
175    }
176
177    fn mac_out(self, data: &[u8], out: &mut [u8]) -> Result<usize, MACError> {
178        match self {
179            Self::HMAC_SHA224(h) => h.mac_out(data, out),
180            Self::HMAC_SHA256(h) => h.mac_out(data, out),
181            Self::HMAC_SHA384(h) => h.mac_out(data, out),
182            Self::HMAC_SHA512(h) => h.mac_out(data, out),
183            Self::HMAC_SHA3_224(h) => h.mac_out(data, out),
184            Self::HMAC_SHA3_256(h) => h.mac_out(data, out),
185            Self::HMAC_SHA3_384(h) => h.mac_out(data, out),
186            Self::HMAC_SHA3_512(h) => h.mac_out(data, out),
187        }
188    }
189
190    fn verify(self, data: &[u8], mac: &[u8]) -> bool {
191        match self {
192            Self::HMAC_SHA224(h) => h.verify(data, mac),
193            Self::HMAC_SHA256(h) => h.verify(data, mac),
194            Self::HMAC_SHA384(h) => h.verify(data, mac),
195            Self::HMAC_SHA512(h) => h.verify(data, mac),
196            Self::HMAC_SHA3_224(h) => h.verify(data, mac),
197            Self::HMAC_SHA3_256(h) => h.verify(data, mac),
198            Self::HMAC_SHA3_384(h) => h.verify(data, mac),
199            Self::HMAC_SHA3_512(h) => h.verify(data, mac),
200        }
201    }
202
203    fn do_update(&mut self, data: &[u8]) {
204        match self {
205            Self::HMAC_SHA224(h) => h.do_update(data),
206            Self::HMAC_SHA256(h) => h.do_update(data),
207            Self::HMAC_SHA384(h) => h.do_update(data),
208            Self::HMAC_SHA512(h) => h.do_update(data),
209            Self::HMAC_SHA3_224(h) => h.do_update(data),
210            Self::HMAC_SHA3_256(h) => h.do_update(data),
211            Self::HMAC_SHA3_384(h) => h.do_update(data),
212            Self::HMAC_SHA3_512(h) => h.do_update(data),
213        }
214    }
215
216    fn do_final(self) -> Vec<u8> {
217        match self {
218            Self::HMAC_SHA224(h) => h.do_final(),
219            Self::HMAC_SHA256(h) => h.do_final(),
220            Self::HMAC_SHA384(h) => h.do_final(),
221            Self::HMAC_SHA512(h) => h.do_final(),
222            Self::HMAC_SHA3_224(h) => h.do_final(),
223            Self::HMAC_SHA3_256(h) => h.do_final(),
224            Self::HMAC_SHA3_384(h) => h.do_final(),
225            Self::HMAC_SHA3_512(h) => h.do_final(),
226        }
227    }
228
229    fn do_final_out(self, mut out: &mut [u8]) -> Result<usize, MACError> {
230        match self {
231            Self::HMAC_SHA224(h) => h.do_final_out(&mut out),
232            Self::HMAC_SHA256(h) => h.do_final_out(&mut out),
233            Self::HMAC_SHA384(h) => h.do_final_out(&mut out),
234            Self::HMAC_SHA512(h) => h.do_final_out(&mut out),
235            Self::HMAC_SHA3_224(h) => h.do_final_out(&mut out),
236            Self::HMAC_SHA3_256(h) => h.do_final_out(&mut out),
237            Self::HMAC_SHA3_384(h) => h.do_final_out(&mut out),
238            Self::HMAC_SHA3_512(h) => h.do_final_out(&mut out),
239        }
240    }
241
242    fn do_verify_final(self, mac: &[u8]) -> bool {
243        match self {
244            Self::HMAC_SHA224(h) => h.do_verify_final(mac),
245            Self::HMAC_SHA256(h) => h.do_verify_final(mac),
246            Self::HMAC_SHA384(h) => h.do_verify_final(mac),
247            Self::HMAC_SHA512(h) => h.do_verify_final(mac),
248            Self::HMAC_SHA3_224(h) => h.do_verify_final(mac),
249            Self::HMAC_SHA3_256(h) => h.do_verify_final(mac),
250            Self::HMAC_SHA3_384(h) => h.do_verify_final(mac),
251            Self::HMAC_SHA3_512(h) => h.do_verify_final(mac),
252        }
253    }
254
255    fn max_security_strength(&self) -> SecurityStrength {
256        match self {
257            Self::HMAC_SHA224(h) => h.max_security_strength(),
258            Self::HMAC_SHA256(h) => h.max_security_strength(),
259            Self::HMAC_SHA384(h) => h.max_security_strength(),
260            Self::HMAC_SHA512(h) => h.max_security_strength(),
261            Self::HMAC_SHA3_224(h) => h.max_security_strength(),
262            Self::HMAC_SHA3_256(h) => h.max_security_strength(),
263            Self::HMAC_SHA3_384(h) => h.max_security_strength(),
264            Self::HMAC_SHA3_512(h) => h.max_security_strength(),
265        }
266    }
267}