use serde::{Deserialize, Serialize};
#[derive(Copy, Clone, Debug, PartialEq, Serialize, Deserialize)]
pub enum Algorithm {
None,
Hash(Hash),
Mac(Mac),
Cipher(Cipher),
Aead(Aead),
AsymmetricSignature(AsymmetricSignature),
AsymmetricEncryption(AsymmetricEncryption),
KeyAgreement(KeyAgreement),
KeyDerivation(KeyDerivation),
}
impl Algorithm {
pub fn is_hmac(self) -> bool {
match self {
Algorithm::Mac(mac_alg) => mac_alg.is_hmac(),
_ => false,
}
}
}
#[derive(Copy, Clone, Debug, PartialEq, Serialize, Deserialize)]
#[allow(deprecated)]
pub enum Hash {
#[deprecated = "The MD2 hash is weak and deprecated and is only recommended for use in legacy protocols."]
Md2,
#[deprecated = "The MD4 hash is weak and deprecated and is only recommended for use in legacy protocols."]
Md4,
#[deprecated = "The MD5 hash is weak and deprecated and is only recommended for use in legacy protocols."]
Md5,
Ripemd160,
#[deprecated = "The SHA-1 hash is weak and deprecated and is only recommended for use in legacy protocols."]
Sha1,
Sha224,
Sha256,
Sha384,
Sha512,
Sha512_224,
Sha512_256,
Sha3_224,
Sha3_256,
Sha3_384,
Sha3_512,
Any,
}
impl Hash {
pub fn permits_alg(self, alg: Hash) -> bool {
if alg == Hash::Any {
false
} else if self == Hash::Any {
true
} else {
self == alg
}
}
}
#[derive(Copy, Clone, Debug, PartialEq, Serialize, Deserialize)]
pub enum FullLengthMac {
Hmac {
hash_alg: Hash,
},
CbcMac,
Cmac,
}
impl FullLengthMac {
pub fn permits_alg(self, alg: FullLengthMac) -> bool {
match self {
FullLengthMac::Hmac {
hash_alg: hash_policy,
} => {
if let FullLengthMac::Hmac { hash_alg } = alg {
hash_policy.permits_alg(hash_alg)
} else {
false
}
}
mac_alg => mac_alg == alg,
}
}
}
#[derive(Copy, Clone, Debug, PartialEq, Serialize, Deserialize)]
pub enum Mac {
FullLength(FullLengthMac),
Truncated {
mac_alg: FullLengthMac,
mac_length: usize,
},
}
impl Mac {
pub fn permits_alg(self, alg: Mac) -> bool {
match self {
Mac::FullLength(full_length_mac_alg_policy) => {
if let Mac::FullLength(full_length_mac_alg) = alg {
full_length_mac_alg_policy.permits_alg(full_length_mac_alg)
} else {
false
}
}
Mac::Truncated {
mac_alg: mac_alg_policy,
mac_length: mac_length_policy,
} => {
if let Mac::Truncated {
mac_alg,
mac_length,
} = alg
{
mac_alg_policy.permits_alg(mac_alg) && mac_length_policy == mac_length
} else {
false
}
}
}
}
pub fn is_hmac(self) -> bool {
match self {
Mac::FullLength(FullLengthMac::Hmac { .. })
| Mac::Truncated {
mac_alg: FullLengthMac::Hmac { .. },
..
} => true,
_ => false,
}
}
pub fn needs_block_cipher(self) -> bool {
match self {
Mac::FullLength(FullLengthMac::CbcMac)
| Mac::FullLength(FullLengthMac::Cmac)
| Mac::Truncated {
mac_alg: FullLengthMac::CbcMac,
..
}
| Mac::Truncated {
mac_alg: FullLengthMac::Cmac,
..
} => true,
_ => false,
}
}
}
#[derive(Copy, Clone, Debug, PartialEq, Serialize, Deserialize)]
#[allow(clippy::pub_enum_variant_names)]
pub enum Cipher {
StreamCipher,
Ctr,
Cfb,
Ofb,
Xts,
EcbNoPadding,
CbcNoPadding,
CbcPkcs7,
}
impl Cipher {
pub fn is_block_cipher_mode(self) -> bool {
match self {
Cipher::Ctr
| Cipher::Cfb
| Cipher::Ofb
| Cipher::Xts
| Cipher::EcbNoPadding
| Cipher::CbcNoPadding
| Cipher::CbcPkcs7 => true,
_ => false,
}
}
}
#[derive(Copy, Clone, Debug, PartialEq, Serialize, Deserialize)]
pub enum AeadWithDefaultLengthTag {
Ccm,
Gcm,
Chacha20Poly1305,
}
#[derive(Copy, Clone, Debug, PartialEq, Serialize, Deserialize)]
pub enum Aead {
AeadWithDefaultLengthTag(AeadWithDefaultLengthTag),
AeadWithShortenedTag {
aead_alg: AeadWithDefaultLengthTag,
tag_length: usize,
},
}
impl Aead {
pub fn needs_block_cipher(self) -> bool {
match self {
Aead::AeadWithDefaultLengthTag(AeadWithDefaultLengthTag::Ccm)
| Aead::AeadWithDefaultLengthTag(AeadWithDefaultLengthTag::Gcm)
| Aead::AeadWithShortenedTag {
aead_alg: AeadWithDefaultLengthTag::Ccm,
..
}
| Aead::AeadWithShortenedTag {
aead_alg: AeadWithDefaultLengthTag::Gcm,
..
} => true,
_ => false,
}
}
pub fn is_chacha20_poly1305_alg(self) -> bool {
match self {
Aead::AeadWithDefaultLengthTag(AeadWithDefaultLengthTag::Chacha20Poly1305)
| Aead::AeadWithShortenedTag {
aead_alg: AeadWithDefaultLengthTag::Chacha20Poly1305,
..
} => true,
_ => false,
}
}
}
#[derive(Copy, Clone, Debug, PartialEq, Serialize, Deserialize)]
pub enum AsymmetricSignature {
RsaPkcs1v15Sign {
hash_alg: Hash,
},
RsaPkcs1v15SignRaw,
RsaPss {
hash_alg: Hash,
},
Ecdsa {
hash_alg: Hash,
},
EcdsaAny,
DeterministicEcdsa {
hash_alg: Hash,
},
}
impl AsymmetricSignature {
pub fn permits_alg(self, alg: AsymmetricSignature) -> bool {
match self {
AsymmetricSignature::RsaPkcs1v15Sign {
hash_alg: hash_policy,
} => {
if let AsymmetricSignature::RsaPkcs1v15Sign { hash_alg } = alg {
hash_policy.permits_alg(hash_alg)
} else {
false
}
}
AsymmetricSignature::RsaPss {
hash_alg: hash_policy,
} => {
if let AsymmetricSignature::RsaPss { hash_alg } = alg {
hash_policy.permits_alg(hash_alg)
} else {
false
}
}
AsymmetricSignature::Ecdsa {
hash_alg: hash_policy,
} => {
if let AsymmetricSignature::Ecdsa { hash_alg } = alg {
hash_policy.permits_alg(hash_alg)
} else {
false
}
}
AsymmetricSignature::DeterministicEcdsa {
hash_alg: hash_policy,
} => {
if let AsymmetricSignature::DeterministicEcdsa { hash_alg } = alg {
hash_policy.permits_alg(hash_alg)
} else {
false
}
}
asymmetric_signature_alg => asymmetric_signature_alg == alg,
}
}
pub fn is_rsa_alg(self) -> bool {
match self {
AsymmetricSignature::RsaPkcs1v15Sign { .. }
| AsymmetricSignature::RsaPkcs1v15SignRaw
| AsymmetricSignature::RsaPss { .. } => true,
_ => false,
}
}
pub fn is_ecc_alg(self) -> bool {
match self {
AsymmetricSignature::Ecdsa { .. }
| AsymmetricSignature::EcdsaAny
| AsymmetricSignature::DeterministicEcdsa { .. } => true,
_ => false,
}
}
}
#[derive(Copy, Clone, Debug, PartialEq, Serialize, Deserialize)]
pub enum AsymmetricEncryption {
RsaPkcs1v15Crypt,
RsaOaep {
hash_alg: Hash,
},
}
impl AsymmetricEncryption {
pub fn permits_alg(self, alg: AsymmetricEncryption) -> bool {
match self {
AsymmetricEncryption::RsaOaep {
hash_alg: hash_policy,
} => {
if let AsymmetricEncryption::RsaOaep { hash_alg } = alg {
hash_policy.permits_alg(hash_alg)
} else {
false
}
}
asymmetric_encryption_alg => asymmetric_encryption_alg == alg,
}
}
}
#[derive(Copy, Clone, Debug, PartialEq, Serialize, Deserialize)]
pub enum RawKeyAgreement {
Ffdh,
Ecdh,
}
#[derive(Copy, Clone, Debug, PartialEq, Serialize, Deserialize)]
pub enum KeyAgreement {
Raw(RawKeyAgreement),
WithKeyDerivation {
ka_alg: RawKeyAgreement,
kdf_alg: KeyDerivation,
},
}
impl KeyAgreement {
pub fn permits_alg(self, alg: KeyAgreement) -> bool {
match self {
KeyAgreement::WithKeyDerivation {
ka_alg: ka_alg_policy,
kdf_alg: kdf_alg_policy,
} => {
if let KeyAgreement::WithKeyDerivation { ka_alg, kdf_alg } = alg {
kdf_alg_policy.permits_alg(kdf_alg) && ka_alg_policy == ka_alg
} else {
false
}
}
key_agreement_alg => key_agreement_alg == alg,
}
}
}
#[derive(Copy, Clone, Debug, PartialEq, Serialize, Deserialize)]
pub enum KeyDerivation {
Hkdf {
hash_alg: Hash,
},
Tls12Prf {
hash_alg: Hash,
},
Tls12PskToMs {
hash_alg: Hash,
},
}
impl KeyDerivation {
pub fn permits_alg(self, alg: KeyDerivation) -> bool {
match self {
KeyDerivation::Hkdf {
hash_alg: hash_policy,
} => {
if let KeyDerivation::Hkdf { hash_alg } = alg {
hash_policy.permits_alg(hash_alg)
} else {
false
}
}
KeyDerivation::Tls12Prf {
hash_alg: hash_policy,
} => {
if let KeyDerivation::Tls12Prf { hash_alg } = alg {
hash_policy.permits_alg(hash_alg)
} else {
false
}
}
KeyDerivation::Tls12PskToMs {
hash_alg: hash_policy,
} => {
if let KeyDerivation::Tls12PskToMs { hash_alg } = alg {
hash_policy.permits_alg(hash_alg)
} else {
false
}
}
}
}
}
impl From<Hash> for Algorithm {
fn from(alg: Hash) -> Self {
Algorithm::Hash(alg)
}
}
impl From<Mac> for Algorithm {
fn from(alg: Mac) -> Self {
Algorithm::Mac(alg)
}
}
impl From<Cipher> for Algorithm {
fn from(alg: Cipher) -> Self {
Algorithm::Cipher(alg)
}
}
impl From<Aead> for Algorithm {
fn from(alg: Aead) -> Self {
Algorithm::Aead(alg)
}
}
impl From<AsymmetricSignature> for Algorithm {
fn from(alg: AsymmetricSignature) -> Self {
Algorithm::AsymmetricSignature(alg)
}
}
impl From<AsymmetricEncryption> for Algorithm {
fn from(alg: AsymmetricEncryption) -> Self {
Algorithm::AsymmetricEncryption(alg)
}
}
impl From<KeyAgreement> for Algorithm {
fn from(alg: KeyAgreement) -> Self {
Algorithm::KeyAgreement(alg)
}
}
impl From<KeyDerivation> for Algorithm {
fn from(alg: KeyDerivation) -> Self {
Algorithm::KeyDerivation(alg)
}
}