1pub mod auth;
18mod crypto;
19pub(crate) mod encode;
20mod engine;
21mod privacy;
22pub(crate) mod process;
23mod usm;
24
25pub use auth::{LocalizedKey, MasterKey, MasterKeys};
26#[cfg(feature = "crypto-fips")]
27pub use crypto::AwsLcFipsProvider;
28#[cfg(feature = "crypto-rustcrypto")]
29pub use crypto::RustCryptoProvider;
30pub use crypto::{CryptoError, CryptoProvider, CryptoResult};
31pub use engine::report_oids;
32pub use engine::{
33 DEFAULT_MSG_MAX_SIZE, EngineCache, EngineState, MAX_ENGINE_ID_LEN, MAX_ENGINE_TIME,
34 MIN_ENGINE_ID_LEN, TIME_WINDOW, compute_engine_boots_time, generate_engine_id,
35 in_authoritative_time_window, parse_discovery_response, parse_discovery_response_with_limits,
36 validate_engine_id,
37};
38pub use engine::{
39 is_decryption_error_report, is_not_in_time_window_report, is_unknown_engine_id_report,
40 is_unknown_user_name_report, is_unsupported_sec_level_report, is_wrong_digest_report,
41};
42pub use privacy::{PrivKey, PrivacyError, PrivacyResult, SaltCounter};
43pub use usm::UsmSecurityParams;
44
45#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
51pub(crate) enum KeyExtension {
52 #[default]
54 None,
55 Blumenthal,
57 Reeder,
59}
60
61#[derive(Debug, Clone, PartialEq, Eq)]
63pub struct ParseProtocolError {
64 input: String,
65 kind: ProtocolKind,
66}
67
68#[derive(Debug, Clone, Copy, PartialEq, Eq)]
69enum ProtocolKind {
70 Auth,
71 Priv,
72}
73
74impl std::fmt::Display for ParseProtocolError {
75 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
76 match self.kind {
77 ProtocolKind::Auth => write!(
78 f,
79 "unknown authentication protocol '{}'; expected one of: MD5, SHA, SHA-224, SHA-256, SHA-384, SHA-512",
80 self.input
81 ),
82 ProtocolKind::Priv => write!(
83 f,
84 "unknown privacy protocol '{}'; expected one of: DES, AES, AES-128, AES-192, AES-256",
85 self.input
86 ),
87 }
88 }
89}
90
91impl std::error::Error for ParseProtocolError {}
92
93#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
95pub enum AuthProtocol {
96 Md5,
98 Sha1,
100 Sha224,
102 Sha256,
104 Sha384,
106 Sha512,
108}
109
110impl std::fmt::Display for AuthProtocol {
111 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
112 match self {
113 Self::Md5 => write!(f, "MD5"),
114 Self::Sha1 => write!(f, "SHA"),
115 Self::Sha224 => write!(f, "SHA-224"),
116 Self::Sha256 => write!(f, "SHA-256"),
117 Self::Sha384 => write!(f, "SHA-384"),
118 Self::Sha512 => write!(f, "SHA-512"),
119 }
120 }
121}
122
123impl std::str::FromStr for AuthProtocol {
124 type Err = ParseProtocolError;
125
126 fn from_str(s: &str) -> Result<Self, Self::Err> {
127 match s.to_ascii_uppercase().as_str() {
128 "MD5" => Ok(Self::Md5),
129 "SHA" | "SHA1" | "SHA-1" => Ok(Self::Sha1),
130 "SHA224" | "SHA-224" => Ok(Self::Sha224),
131 "SHA256" | "SHA-256" => Ok(Self::Sha256),
132 "SHA384" | "SHA-384" => Ok(Self::Sha384),
133 "SHA512" | "SHA-512" => Ok(Self::Sha512),
134 _ => Err(ParseProtocolError {
135 input: s.to_string(),
136 kind: ProtocolKind::Auth,
137 }),
138 }
139 }
140}
141
142impl AuthProtocol {
143 #[must_use]
148 pub fn digest_len(self) -> usize {
149 match self {
150 Self::Md5 => 16,
151 Self::Sha1 => 20,
152 Self::Sha224 => 28,
153 Self::Sha256 => 32,
154 Self::Sha384 => 48,
155 Self::Sha512 => 64,
156 }
157 }
158
159 #[must_use]
161 pub fn mac_len(self) -> usize {
162 match self {
163 Self::Md5 | Self::Sha1 => 12, Self::Sha224 => 16, Self::Sha256 => 24, Self::Sha384 => 32, Self::Sha512 => 48, }
169 }
170}
171
172#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
174pub enum PrivProtocol {
175 Des,
180 Des3,
185 Aes128,
187 Aes192,
190 Aes256,
193}
194
195impl std::fmt::Display for PrivProtocol {
196 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
197 match self {
198 Self::Des => write!(f, "DES"),
199 Self::Des3 => write!(f, "3DES"),
200 Self::Aes128 => write!(f, "AES"),
201 Self::Aes192 => write!(f, "AES-192"),
202 Self::Aes256 => write!(f, "AES-256"),
203 }
204 }
205}
206
207impl std::str::FromStr for PrivProtocol {
208 type Err = ParseProtocolError;
209
210 fn from_str(s: &str) -> Result<Self, Self::Err> {
211 match s.to_ascii_uppercase().as_str() {
212 "DES" => Ok(Self::Des),
213 "3DES" | "3DES-EDE" | "DES3" | "TDES" => Ok(Self::Des3),
214 "AES" | "AES128" | "AES-128" => Ok(Self::Aes128),
215 "AES192" | "AES-192" => Ok(Self::Aes192),
216 "AES256" | "AES-256" => Ok(Self::Aes256),
217 _ => Err(ParseProtocolError {
218 input: s.to_string(),
219 kind: ProtocolKind::Priv,
220 }),
221 }
222 }
223}
224
225impl PrivProtocol {
226 #[must_use]
228 pub fn key_len(self) -> usize {
229 match self {
230 Self::Des => 16, Self::Des3 => 32, Self::Aes128 => 16,
233 Self::Aes192 => 24,
234 Self::Aes256 => 32,
235 }
236 }
237
238 #[must_use]
240 pub fn salt_len(self) -> usize {
241 8 }
243
244 pub(crate) fn key_extension_for(self, auth_protocol: AuthProtocol) -> KeyExtension {
253 let auth_len = auth_protocol.digest_len();
254 let priv_len = self.key_len();
255
256 if auth_len >= priv_len {
257 return KeyExtension::None;
258 }
259
260 match self {
261 Self::Des3 => KeyExtension::Reeder,
262 Self::Aes192 | Self::Aes256 => KeyExtension::Blumenthal,
263 Self::Des | Self::Aes128 => KeyExtension::None, }
265 }
266}
267
268#[cfg(test)]
269mod tests {
270 use super::*;
271
272 #[test]
273 fn test_auth_protocol_display() {
274 assert_eq!(format!("{}", AuthProtocol::Md5), "MD5");
275 assert_eq!(format!("{}", AuthProtocol::Sha1), "SHA");
276 assert_eq!(format!("{}", AuthProtocol::Sha224), "SHA-224");
277 assert_eq!(format!("{}", AuthProtocol::Sha256), "SHA-256");
278 assert_eq!(format!("{}", AuthProtocol::Sha384), "SHA-384");
279 assert_eq!(format!("{}", AuthProtocol::Sha512), "SHA-512");
280 }
281
282 #[test]
283 fn test_auth_protocol_from_str() {
284 assert_eq!("MD5".parse::<AuthProtocol>().unwrap(), AuthProtocol::Md5);
285 assert_eq!("md5".parse::<AuthProtocol>().unwrap(), AuthProtocol::Md5);
286 assert_eq!("SHA".parse::<AuthProtocol>().unwrap(), AuthProtocol::Sha1);
287 assert_eq!("sha1".parse::<AuthProtocol>().unwrap(), AuthProtocol::Sha1);
288 assert_eq!("SHA-1".parse::<AuthProtocol>().unwrap(), AuthProtocol::Sha1);
289 assert_eq!(
290 "sha-224".parse::<AuthProtocol>().unwrap(),
291 AuthProtocol::Sha224
292 );
293 assert_eq!(
294 "SHA256".parse::<AuthProtocol>().unwrap(),
295 AuthProtocol::Sha256
296 );
297 assert_eq!(
298 "SHA-256".parse::<AuthProtocol>().unwrap(),
299 AuthProtocol::Sha256
300 );
301 assert_eq!(
302 "sha384".parse::<AuthProtocol>().unwrap(),
303 AuthProtocol::Sha384
304 );
305 assert_eq!(
306 "SHA-512".parse::<AuthProtocol>().unwrap(),
307 AuthProtocol::Sha512
308 );
309
310 assert!("invalid".parse::<AuthProtocol>().is_err());
311 }
312
313 #[test]
314 fn test_priv_protocol_display() {
315 assert_eq!(format!("{}", PrivProtocol::Des), "DES");
316 assert_eq!(format!("{}", PrivProtocol::Des3), "3DES");
317 assert_eq!(format!("{}", PrivProtocol::Aes128), "AES");
318 assert_eq!(format!("{}", PrivProtocol::Aes192), "AES-192");
319 assert_eq!(format!("{}", PrivProtocol::Aes256), "AES-256");
320 }
321
322 #[test]
323 fn test_priv_protocol_from_str() {
324 assert_eq!("DES".parse::<PrivProtocol>().unwrap(), PrivProtocol::Des);
325 assert_eq!("des".parse::<PrivProtocol>().unwrap(), PrivProtocol::Des);
326 assert_eq!("3DES".parse::<PrivProtocol>().unwrap(), PrivProtocol::Des3);
327 assert_eq!("3des".parse::<PrivProtocol>().unwrap(), PrivProtocol::Des3);
328 assert_eq!(
329 "3DES-EDE".parse::<PrivProtocol>().unwrap(),
330 PrivProtocol::Des3
331 );
332 assert_eq!("DES3".parse::<PrivProtocol>().unwrap(), PrivProtocol::Des3);
333 assert_eq!("TDES".parse::<PrivProtocol>().unwrap(), PrivProtocol::Des3);
334 assert_eq!("AES".parse::<PrivProtocol>().unwrap(), PrivProtocol::Aes128);
335 assert_eq!("aes".parse::<PrivProtocol>().unwrap(), PrivProtocol::Aes128);
336 assert_eq!(
337 "AES128".parse::<PrivProtocol>().unwrap(),
338 PrivProtocol::Aes128
339 );
340 assert_eq!(
341 "AES-128".parse::<PrivProtocol>().unwrap(),
342 PrivProtocol::Aes128
343 );
344 assert_eq!(
345 "aes192".parse::<PrivProtocol>().unwrap(),
346 PrivProtocol::Aes192
347 );
348 assert_eq!(
349 "AES-192".parse::<PrivProtocol>().unwrap(),
350 PrivProtocol::Aes192
351 );
352 assert_eq!(
353 "aes256".parse::<PrivProtocol>().unwrap(),
354 PrivProtocol::Aes256
355 );
356 assert_eq!(
357 "AES-256".parse::<PrivProtocol>().unwrap(),
358 PrivProtocol::Aes256
359 );
360
361 assert!("invalid".parse::<PrivProtocol>().is_err());
362 }
363
364 #[test]
365 fn test_parse_protocol_error_display() {
366 let err = "bogus".parse::<AuthProtocol>().unwrap_err();
367 assert!(err.to_string().contains("bogus"));
368 assert!(err.to_string().contains("authentication protocol"));
369
370 let err = "bogus".parse::<PrivProtocol>().unwrap_err();
371 assert!(err.to_string().contains("bogus"));
372 assert!(err.to_string().contains("privacy protocol"));
373 }
374}