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