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