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