pub mod auth;
mod crypto;
pub(crate) mod encode;
mod engine;
mod privacy;
mod usm;
pub use auth::{LocalizedKey, MasterKey, MasterKeys};
#[cfg(feature = "crypto-fips")]
pub use crypto::AwsLcFipsProvider;
#[cfg(feature = "crypto-rustcrypto")]
pub use crypto::RustCryptoProvider;
pub use crypto::{CryptoError, CryptoProvider, CryptoResult};
pub use engine::report_oids;
pub use engine::{
DEFAULT_MSG_MAX_SIZE, EngineCache, EngineState, MAX_ENGINE_TIME, TIME_WINDOW,
compute_engine_boots_time, parse_discovery_response, parse_discovery_response_with_limits,
};
pub use engine::{
is_decryption_error_report, is_not_in_time_window_report, is_unknown_engine_id_report,
is_unknown_user_name_report, is_unsupported_sec_level_report, is_wrong_digest_report,
};
pub use privacy::{PrivKey, PrivacyError, PrivacyResult, SaltCounter};
pub use usm::UsmSecurityParams;
#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
pub(crate) enum KeyExtension {
#[default]
None,
Blumenthal,
Reeder,
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct ParseProtocolError {
input: String,
kind: ProtocolKind,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
enum ProtocolKind {
Auth,
Priv,
}
impl std::fmt::Display for ParseProtocolError {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self.kind {
ProtocolKind::Auth => write!(
f,
"unknown authentication protocol '{}'; expected one of: MD5, SHA, SHA-224, SHA-256, SHA-384, SHA-512",
self.input
),
ProtocolKind::Priv => write!(
f,
"unknown privacy protocol '{}'; expected one of: DES, AES, AES-128, AES-192, AES-256",
self.input
),
}
}
}
impl std::error::Error for ParseProtocolError {}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum AuthProtocol {
Md5,
Sha1,
Sha224,
Sha256,
Sha384,
Sha512,
}
impl std::fmt::Display for AuthProtocol {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
Self::Md5 => write!(f, "MD5"),
Self::Sha1 => write!(f, "SHA"),
Self::Sha224 => write!(f, "SHA-224"),
Self::Sha256 => write!(f, "SHA-256"),
Self::Sha384 => write!(f, "SHA-384"),
Self::Sha512 => write!(f, "SHA-512"),
}
}
}
impl std::str::FromStr for AuthProtocol {
type Err = ParseProtocolError;
fn from_str(s: &str) -> Result<Self, Self::Err> {
match s.to_ascii_uppercase().as_str() {
"MD5" => Ok(Self::Md5),
"SHA" | "SHA1" | "SHA-1" => Ok(Self::Sha1),
"SHA224" | "SHA-224" => Ok(Self::Sha224),
"SHA256" | "SHA-256" => Ok(Self::Sha256),
"SHA384" | "SHA-384" => Ok(Self::Sha384),
"SHA512" | "SHA-512" => Ok(Self::Sha512),
_ => Err(ParseProtocolError {
input: s.to_string(),
kind: ProtocolKind::Auth,
}),
}
}
}
impl AuthProtocol {
pub fn digest_len(self) -> usize {
match self {
Self::Md5 => 16,
Self::Sha1 => 20,
Self::Sha224 => 28,
Self::Sha256 => 32,
Self::Sha384 => 48,
Self::Sha512 => 64,
}
}
pub fn mac_len(self) -> usize {
match self {
Self::Md5 | Self::Sha1 => 12, Self::Sha224 => 16, Self::Sha256 => 24, Self::Sha384 => 32, Self::Sha512 => 48, }
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum PrivProtocol {
Des,
Des3,
Aes128,
Aes192,
Aes256,
}
impl std::fmt::Display for PrivProtocol {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
Self::Des => write!(f, "DES"),
Self::Des3 => write!(f, "3DES"),
Self::Aes128 => write!(f, "AES"),
Self::Aes192 => write!(f, "AES-192"),
Self::Aes256 => write!(f, "AES-256"),
}
}
}
impl std::str::FromStr for PrivProtocol {
type Err = ParseProtocolError;
fn from_str(s: &str) -> Result<Self, Self::Err> {
match s.to_ascii_uppercase().as_str() {
"DES" => Ok(Self::Des),
"3DES" | "3DES-EDE" | "DES3" | "TDES" => Ok(Self::Des3),
"AES" | "AES128" | "AES-128" => Ok(Self::Aes128),
"AES192" | "AES-192" => Ok(Self::Aes192),
"AES256" | "AES-256" => Ok(Self::Aes256),
_ => Err(ParseProtocolError {
input: s.to_string(),
kind: ProtocolKind::Priv,
}),
}
}
}
impl PrivProtocol {
pub fn key_len(self) -> usize {
match self {
Self::Des => 16, Self::Des3 => 32, Self::Aes128 => 16,
Self::Aes192 => 24,
Self::Aes256 => 32,
}
}
pub fn salt_len(self) -> usize {
8 }
pub(crate) fn key_extension_for(self, auth_protocol: AuthProtocol) -> KeyExtension {
let auth_len = auth_protocol.digest_len();
let priv_len = self.key_len();
if auth_len >= priv_len {
return KeyExtension::None;
}
match self {
Self::Des3 => KeyExtension::Reeder,
Self::Aes192 | Self::Aes256 => KeyExtension::Blumenthal,
Self::Des | Self::Aes128 => KeyExtension::None, }
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_auth_protocol_display() {
assert_eq!(format!("{}", AuthProtocol::Md5), "MD5");
assert_eq!(format!("{}", AuthProtocol::Sha1), "SHA");
assert_eq!(format!("{}", AuthProtocol::Sha224), "SHA-224");
assert_eq!(format!("{}", AuthProtocol::Sha256), "SHA-256");
assert_eq!(format!("{}", AuthProtocol::Sha384), "SHA-384");
assert_eq!(format!("{}", AuthProtocol::Sha512), "SHA-512");
}
#[test]
fn test_auth_protocol_from_str() {
assert_eq!("MD5".parse::<AuthProtocol>().unwrap(), AuthProtocol::Md5);
assert_eq!("md5".parse::<AuthProtocol>().unwrap(), AuthProtocol::Md5);
assert_eq!("SHA".parse::<AuthProtocol>().unwrap(), AuthProtocol::Sha1);
assert_eq!("sha1".parse::<AuthProtocol>().unwrap(), AuthProtocol::Sha1);
assert_eq!("SHA-1".parse::<AuthProtocol>().unwrap(), AuthProtocol::Sha1);
assert_eq!(
"sha-224".parse::<AuthProtocol>().unwrap(),
AuthProtocol::Sha224
);
assert_eq!(
"SHA256".parse::<AuthProtocol>().unwrap(),
AuthProtocol::Sha256
);
assert_eq!(
"SHA-256".parse::<AuthProtocol>().unwrap(),
AuthProtocol::Sha256
);
assert_eq!(
"sha384".parse::<AuthProtocol>().unwrap(),
AuthProtocol::Sha384
);
assert_eq!(
"SHA-512".parse::<AuthProtocol>().unwrap(),
AuthProtocol::Sha512
);
assert!("invalid".parse::<AuthProtocol>().is_err());
}
#[test]
fn test_priv_protocol_display() {
assert_eq!(format!("{}", PrivProtocol::Des), "DES");
assert_eq!(format!("{}", PrivProtocol::Des3), "3DES");
assert_eq!(format!("{}", PrivProtocol::Aes128), "AES");
assert_eq!(format!("{}", PrivProtocol::Aes192), "AES-192");
assert_eq!(format!("{}", PrivProtocol::Aes256), "AES-256");
}
#[test]
fn test_priv_protocol_from_str() {
assert_eq!("DES".parse::<PrivProtocol>().unwrap(), PrivProtocol::Des);
assert_eq!("des".parse::<PrivProtocol>().unwrap(), PrivProtocol::Des);
assert_eq!("3DES".parse::<PrivProtocol>().unwrap(), PrivProtocol::Des3);
assert_eq!("3des".parse::<PrivProtocol>().unwrap(), PrivProtocol::Des3);
assert_eq!(
"3DES-EDE".parse::<PrivProtocol>().unwrap(),
PrivProtocol::Des3
);
assert_eq!("DES3".parse::<PrivProtocol>().unwrap(), PrivProtocol::Des3);
assert_eq!("TDES".parse::<PrivProtocol>().unwrap(), PrivProtocol::Des3);
assert_eq!("AES".parse::<PrivProtocol>().unwrap(), PrivProtocol::Aes128);
assert_eq!("aes".parse::<PrivProtocol>().unwrap(), PrivProtocol::Aes128);
assert_eq!(
"AES128".parse::<PrivProtocol>().unwrap(),
PrivProtocol::Aes128
);
assert_eq!(
"AES-128".parse::<PrivProtocol>().unwrap(),
PrivProtocol::Aes128
);
assert_eq!(
"aes192".parse::<PrivProtocol>().unwrap(),
PrivProtocol::Aes192
);
assert_eq!(
"AES-192".parse::<PrivProtocol>().unwrap(),
PrivProtocol::Aes192
);
assert_eq!(
"aes256".parse::<PrivProtocol>().unwrap(),
PrivProtocol::Aes256
);
assert_eq!(
"AES-256".parse::<PrivProtocol>().unwrap(),
PrivProtocol::Aes256
);
assert!("invalid".parse::<PrivProtocol>().is_err());
}
#[test]
fn test_parse_protocol_error_display() {
let err = "bogus".parse::<AuthProtocol>().unwrap_err();
assert!(err.to_string().contains("bogus"));
assert!(err.to_string().contains("authentication protocol"));
let err = "bogus".parse::<PrivProtocol>().unwrap_err();
assert!(err.to_string().contains("bogus"));
assert!(err.to_string().contains("privacy protocol"));
}
}