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