use std::fmt;
use std::str::FromStr;
use std::result;
use quickcheck::{Arbitrary, Gen};
use crate::Error;
use crate::Result;
mod features;
pub use self::features::Features;
mod key_flags;
pub use self::key_flags::KeyFlags;
mod server_preferences;
pub use self::server_preferences::KeyServerPreferences;
mod timestamp;
pub use timestamp::{Timestamp, Duration};
pub(crate) fn bitfield_remove_padding(b: &mut Vec<u8>) -> usize {
let pad_to = b.len();
while b.last() == Some(&0) {
b.pop();
}
pad_to
}
#[derive(Clone, Copy, Hash, PartialEq, Eq, Debug, PartialOrd, Ord)]
pub enum PublicKeyAlgorithm {
RSAEncryptSign,
#[deprecated(since = "rfc4880",
note = "Use `PublicKeyAlgorithm::RSAEncryptSign`.")]
RSAEncrypt,
#[deprecated(since = "rfc4880",
note = "Use `PublicKeyAlgorithm::RSAEncryptSign`.")]
RSASign,
ElgamalEncrypt,
DSA,
ECDH,
ECDSA,
#[deprecated(since = "rfc4880",
note = "If you really must, use \
`PublicKeyAlgorithm::ElgamalEncrypt`.")]
ElgamalEncryptSign,
EdDSA,
Private(u8),
Unknown(u8),
}
impl PublicKeyAlgorithm {
pub fn for_signing(&self) -> bool {
use self::PublicKeyAlgorithm::*;
#[allow(deprecated)]
match &self {
RSAEncryptSign | RSASign | DSA | ECDSA | ElgamalEncryptSign
| EdDSA => true,
_ => false,
}
}
pub fn can_encrypt(&self) -> bool {
use self::PublicKeyAlgorithm::*;
#[allow(deprecated)]
match &self {
RSAEncryptSign | RSAEncrypt | ElgamalEncrypt | ECDH
| ElgamalEncryptSign => true,
_ => false,
}
}
pub fn is_supported(&self) -> bool {
use self::PublicKeyAlgorithm::*;
#[allow(deprecated)]
match &self {
RSAEncryptSign | RSAEncrypt | RSASign | DSA | ECDH | ECDSA | EdDSA
=> true,
ElgamalEncrypt | ElgamalEncryptSign | Private(_) | Unknown(_)
=> false,
}
}
}
impl From<u8> for PublicKeyAlgorithm {
fn from(u: u8) -> Self {
use crate::PublicKeyAlgorithm::*;
#[allow(deprecated)]
match u {
1 => RSAEncryptSign,
2 => RSAEncrypt,
3 => RSASign,
16 => ElgamalEncrypt,
17 => DSA,
18 => ECDH,
19 => ECDSA,
20 => ElgamalEncryptSign,
22 => EdDSA,
100..=110 => Private(u),
u => Unknown(u),
}
}
}
impl From<PublicKeyAlgorithm> for u8 {
fn from(p: PublicKeyAlgorithm) -> u8 {
use crate::PublicKeyAlgorithm::*;
#[allow(deprecated)]
match p {
RSAEncryptSign => 1,
RSAEncrypt => 2,
RSASign => 3,
ElgamalEncrypt => 16,
DSA => 17,
ECDH => 18,
ECDSA => 19,
ElgamalEncryptSign => 20,
EdDSA => 22,
Private(u) => u,
Unknown(u) => u,
}
}
}
impl fmt::Display for PublicKeyAlgorithm {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
use crate::PublicKeyAlgorithm::*;
#[allow(deprecated)]
match *self {
RSAEncryptSign => f.write_str("RSA (Encrypt or Sign)"),
RSAEncrypt => f.write_str("RSA Encrypt-Only"),
RSASign => f.write_str("RSA Sign-Only"),
ElgamalEncrypt => f.write_str("Elgamal (Encrypt-Only)"),
DSA => f.write_str("DSA (Digital Signature Algorithm)"),
ECDSA => f.write_str("ECDSA public key algorithm"),
ElgamalEncryptSign => f.write_str("Elgamal (Encrypt or Sign)"),
ECDH => f.write_str("ECDH public key algorithm"),
EdDSA => f.write_str("EdDSA Edwards-curve Digital Signature Algorithm"),
Private(u) =>
f.write_fmt(format_args!("Private/Experimental public key algorithm {}", u)),
Unknown(u) =>
f.write_fmt(format_args!("Unknown public key algorithm {}", u)),
}
}
}
impl Arbitrary for PublicKeyAlgorithm {
fn arbitrary<G: Gen>(g: &mut G) -> Self {
u8::arbitrary(g).into()
}
}
#[derive(Debug, Clone, Hash, PartialEq, Eq, PartialOrd, Ord)]
pub enum Curve {
NistP256,
NistP384,
NistP521,
BrainpoolP256,
BrainpoolP512,
Ed25519,
Cv25519,
Unknown(Box<[u8]>),
}
impl Curve {
pub fn bits(&self) -> Option<usize> {
use self::Curve::*;
match self {
NistP256 => Some(256),
NistP384 => Some(384),
NistP521 => Some(521),
BrainpoolP256 => Some(256),
BrainpoolP512 => Some(512),
Ed25519 => Some(256),
Cv25519 => Some(256),
Unknown(_) => None,
}
}
}
impl fmt::Display for Curve {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
use self::Curve::*;
match *self {
NistP256 => f.write_str("NIST curve P-256"),
NistP384 => f.write_str("NIST curve P-384"),
NistP521 => f.write_str("NIST curve P-521"),
BrainpoolP256 => f.write_str("brainpoolP256r1"),
BrainpoolP512 => f.write_str("brainpoolP512r1"),
Ed25519
=> f.write_str("D.J. Bernstein's \"Twisted\" Edwards curve Ed25519"),
Cv25519
=> f.write_str("Elliptic curve Diffie-Hellman using D.J. Bernstein's Curve25519"),
Unknown(ref oid)
=> write!(f, "Unknown curve (OID: {:?})", oid),
}
}
}
const NIST_P256_OID: &[u8] = &[0x2A, 0x86, 0x48, 0xCE, 0x3D, 0x03, 0x01, 0x07];
const NIST_P384_OID: &[u8] = &[0x2B, 0x81, 0x04, 0x00, 0x22];
const NIST_P521_OID: &[u8] = &[0x2B, 0x81, 0x04, 0x00, 0x23];
const BRAINPOOL_P256_OID: &[u8] =
&[0x2B, 0x24, 0x03, 0x03, 0x02, 0x08, 0x01, 0x01, 0x07];
const BRAINPOOL_P512_OID: &[u8] =
&[0x2B, 0x24, 0x03, 0x03, 0x02, 0x08, 0x01, 0x01, 0x0D];
const ED25519_OID: &[u8] =
&[0x2B, 0x06, 0x01, 0x04, 0x01, 0xDA, 0x47, 0x0F, 0x01];
const CV25519_OID: &[u8] =
&[0x2B, 0x06, 0x01, 0x04, 0x01, 0x97, 0x55, 0x01, 0x05, 0x01];
impl Curve {
pub fn from_oid(oid: &[u8]) -> Curve {
match oid {
NIST_P256_OID => Curve::NistP256,
NIST_P384_OID => Curve::NistP384,
NIST_P521_OID => Curve::NistP521,
BRAINPOOL_P256_OID => Curve::BrainpoolP256,
BRAINPOOL_P512_OID => Curve::BrainpoolP512,
ED25519_OID => Curve::Ed25519,
CV25519_OID => Curve::Cv25519,
oid => Curve::Unknown(Vec::from(oid).into_boxed_slice()),
}
}
pub fn oid(&self) -> &[u8] {
match self {
&Curve::NistP256 => NIST_P256_OID,
&Curve::NistP384 => NIST_P384_OID,
&Curve::NistP521 => NIST_P521_OID,
&Curve::BrainpoolP256 => BRAINPOOL_P256_OID,
&Curve::BrainpoolP512 => BRAINPOOL_P512_OID,
&Curve::Ed25519 => ED25519_OID,
&Curve::Cv25519 => CV25519_OID,
&Curve::Unknown(ref oid) => oid,
}
}
pub fn len(&self) -> Result<usize> {
match self {
&Curve::NistP256 => Ok(256),
&Curve::NistP384 => Ok(384),
&Curve::NistP521 => Ok(521),
&Curve::BrainpoolP256 => Ok(256),
&Curve::BrainpoolP512 => Ok(512),
&Curve::Ed25519 => Ok(256),
&Curve::Cv25519 => Ok(256),
&Curve::Unknown(_) =>
Err(Error::UnsupportedEllipticCurve(self.clone())
.into()),
}
}
pub fn is_supported(&self) -> bool {
use self::Curve::*;
match &self {
NistP256 | NistP384 | NistP521 | Ed25519 | Cv25519
=> true,
BrainpoolP256 | BrainpoolP512 | Unknown(_)
=> false,
}
}
}
impl Arbitrary for Curve {
fn arbitrary<G: Gen>(g: &mut G) -> Self {
match u8::arbitrary(g) % 8 {
0 => Curve::NistP256,
1 => Curve::NistP384,
2 => Curve::NistP521,
3 => Curve::BrainpoolP256,
4 => Curve::BrainpoolP512,
5 => Curve::Ed25519,
6 => Curve::Cv25519,
7 => Curve::Unknown(Vec::<u8>::arbitrary(g).into_boxed_slice()),
_ => unreachable!(),
}
}
}
#[derive(Clone, Copy, Hash, PartialEq, Eq, Debug, PartialOrd, Ord)]
pub enum SymmetricAlgorithm {
Unencrypted,
IDEA,
TripleDES,
CAST5,
Blowfish,
AES128,
AES192,
AES256,
Twofish,
Camellia128,
Camellia192,
Camellia256,
Private(u8),
Unknown(u8),
}
impl Default for SymmetricAlgorithm {
fn default() -> Self {
SymmetricAlgorithm::AES256
}
}
impl SymmetricAlgorithm {
pub fn is_supported(&self) -> bool {
use self::SymmetricAlgorithm::*;
match &self {
TripleDES | CAST5 | Blowfish | AES128 | AES192 | AES256 | Twofish
| Camellia128 | Camellia192 | Camellia256
=> true,
Unencrypted | IDEA | Private(_) | Unknown(_)
=> false,
}
}
}
impl From<u8> for SymmetricAlgorithm {
fn from(u: u8) -> Self {
match u {
0 => SymmetricAlgorithm::Unencrypted,
1 => SymmetricAlgorithm::IDEA,
2 => SymmetricAlgorithm::TripleDES,
3 => SymmetricAlgorithm::CAST5,
4 => SymmetricAlgorithm::Blowfish,
7 => SymmetricAlgorithm::AES128,
8 => SymmetricAlgorithm::AES192,
9 => SymmetricAlgorithm::AES256,
10 => SymmetricAlgorithm::Twofish,
11 => SymmetricAlgorithm::Camellia128,
12 => SymmetricAlgorithm::Camellia192,
13 => SymmetricAlgorithm::Camellia256,
100..=110 => SymmetricAlgorithm::Private(u),
u => SymmetricAlgorithm::Unknown(u),
}
}
}
impl From<SymmetricAlgorithm> for u8 {
fn from(s: SymmetricAlgorithm) -> u8 {
match s {
SymmetricAlgorithm::Unencrypted => 0,
SymmetricAlgorithm::IDEA => 1,
SymmetricAlgorithm::TripleDES => 2,
SymmetricAlgorithm::CAST5 => 3,
SymmetricAlgorithm::Blowfish => 4,
SymmetricAlgorithm::AES128 => 7,
SymmetricAlgorithm::AES192 => 8,
SymmetricAlgorithm::AES256 => 9,
SymmetricAlgorithm::Twofish => 10,
SymmetricAlgorithm::Camellia128 => 11,
SymmetricAlgorithm::Camellia192 => 12,
SymmetricAlgorithm::Camellia256 => 13,
SymmetricAlgorithm::Private(u) => u,
SymmetricAlgorithm::Unknown(u) => u,
}
}
}
impl fmt::Display for SymmetricAlgorithm {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match *self {
SymmetricAlgorithm::Unencrypted =>
f.write_str("Unencrypted"),
SymmetricAlgorithm::IDEA =>
f.write_str("IDEA"),
SymmetricAlgorithm::TripleDES =>
f.write_str("TripleDES (EDE-DES, 168 bit key derived from 192))"),
SymmetricAlgorithm::CAST5 =>
f.write_str("CAST5 (128 bit key, 16 rounds)"),
SymmetricAlgorithm::Blowfish =>
f.write_str("Blowfish (128 bit key, 16 rounds)"),
SymmetricAlgorithm::AES128 =>
f.write_str("AES with 128-bit key"),
SymmetricAlgorithm::AES192 =>
f.write_str("AES with 192-bit key"),
SymmetricAlgorithm::AES256 =>
f.write_str("AES with 256-bit key"),
SymmetricAlgorithm::Twofish =>
f.write_str("Twofish with 256-bit key"),
SymmetricAlgorithm::Camellia128 =>
f.write_str("Camellia with 128-bit key"),
SymmetricAlgorithm::Camellia192 =>
f.write_str("Camellia with 192-bit key"),
SymmetricAlgorithm::Camellia256 =>
f.write_str("Camellia with 256-bit key"),
SymmetricAlgorithm::Private(u) =>
f.write_fmt(format_args!("Private/Experimental symmetric key algorithm {}", u)),
SymmetricAlgorithm::Unknown(u) =>
f.write_fmt(format_args!("Unknown symmetric key algorithm {}", u)),
}
}
}
impl Arbitrary for SymmetricAlgorithm {
fn arbitrary<G: Gen>(g: &mut G) -> Self {
u8::arbitrary(g).into()
}
}
#[derive(Clone, Copy, Hash, PartialEq, Eq, Debug, PartialOrd, Ord)]
pub enum AEADAlgorithm {
EAX,
OCB,
Private(u8),
Unknown(u8),
}
impl AEADAlgorithm {
pub fn is_supported(&self) -> bool {
use self::AEADAlgorithm::*;
match &self {
EAX
=> true,
OCB | Private(_) | Unknown(_)
=> false,
}
}
}
impl From<u8> for AEADAlgorithm {
fn from(u: u8) -> Self {
match u {
1 => AEADAlgorithm::EAX,
2 => AEADAlgorithm::OCB,
100..=110 => AEADAlgorithm::Private(u),
u => AEADAlgorithm::Unknown(u),
}
}
}
impl From<AEADAlgorithm> for u8 {
fn from(s: AEADAlgorithm) -> u8 {
match s {
AEADAlgorithm::EAX => 1,
AEADAlgorithm::OCB => 2,
AEADAlgorithm::Private(u) => u,
AEADAlgorithm::Unknown(u) => u,
}
}
}
impl fmt::Display for AEADAlgorithm {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match *self {
AEADAlgorithm::EAX =>
f.write_str("EAX mode"),
AEADAlgorithm::OCB =>
f.write_str("OCB mode"),
AEADAlgorithm::Private(u) =>
f.write_fmt(format_args!("Private/Experimental AEAD algorithm {}", u)),
AEADAlgorithm::Unknown(u) =>
f.write_fmt(format_args!("Unknown AEAD algorithm {}", u)),
}
}
}
impl Arbitrary for AEADAlgorithm {
fn arbitrary<G: Gen>(g: &mut G) -> Self {
u8::arbitrary(g).into()
}
}
#[derive(Clone, Copy, Hash, PartialEq, Eq, Debug, PartialOrd, Ord)]
pub enum CompressionAlgorithm {
Uncompressed,
Zip,
Zlib,
BZip2,
Private(u8),
Unknown(u8),
}
impl Default for CompressionAlgorithm {
fn default() -> Self {
use self::CompressionAlgorithm::*;
#[cfg(feature = "compression-deflate")]
{ Zip }
#[cfg(all(feature = "compression-bzip2",
not(feature = "compression-deflate")))]
{ BZip2 }
#[cfg(all(not(feature = "compression-bzip2"),
not(feature = "compression-deflate")))]
{ Uncompressed }
}
}
impl CompressionAlgorithm {
pub fn is_supported(&self) -> bool {
use self::CompressionAlgorithm::*;
match &self {
Uncompressed => true,
#[cfg(feature = "compression-deflate")]
Zip | Zlib => true,
#[cfg(feature = "compression-bzip2")]
BZip2 => true,
_ => false,
}
}
}
impl From<u8> for CompressionAlgorithm {
fn from(u: u8) -> Self {
match u {
0 => CompressionAlgorithm::Uncompressed,
1 => CompressionAlgorithm::Zip,
2 => CompressionAlgorithm::Zlib,
3 => CompressionAlgorithm::BZip2,
100..=110 => CompressionAlgorithm::Private(u),
u => CompressionAlgorithm::Unknown(u),
}
}
}
impl From<CompressionAlgorithm> for u8 {
fn from(c: CompressionAlgorithm) -> u8 {
match c {
CompressionAlgorithm::Uncompressed => 0,
CompressionAlgorithm::Zip => 1,
CompressionAlgorithm::Zlib => 2,
CompressionAlgorithm::BZip2 => 3,
CompressionAlgorithm::Private(u) => u,
CompressionAlgorithm::Unknown(u) => u,
}
}
}
impl fmt::Display for CompressionAlgorithm {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match *self {
CompressionAlgorithm::Uncompressed => f.write_str("Uncompressed"),
CompressionAlgorithm::Zip => f.write_str("ZIP"),
CompressionAlgorithm::Zlib => f.write_str("ZLIB"),
CompressionAlgorithm::BZip2 => f.write_str("BZip2"),
CompressionAlgorithm::Private(u) =>
f.write_fmt(format_args!("Private/Experimental compression algorithm {}", u)),
CompressionAlgorithm::Unknown(u) =>
f.write_fmt(format_args!("Unknown comppression algorithm {}", u)),
}
}
}
impl Arbitrary for CompressionAlgorithm {
fn arbitrary<G: Gen>(g: &mut G) -> Self {
u8::arbitrary(g).into()
}
}
#[derive(Clone, Copy, Hash, PartialEq, Eq, Debug, PartialOrd, Ord)]
pub enum HashAlgorithm {
MD5,
SHA1,
RipeMD,
SHA256,
SHA384,
SHA512,
SHA224,
Private(u8),
Unknown(u8),
}
impl Default for HashAlgorithm {
fn default() -> Self {
HashAlgorithm::SHA256
}
}
impl From<u8> for HashAlgorithm {
fn from(u: u8) -> Self {
match u {
1 => HashAlgorithm::MD5,
2 => HashAlgorithm::SHA1,
3 => HashAlgorithm::RipeMD,
8 => HashAlgorithm::SHA256,
9 => HashAlgorithm::SHA384,
10 => HashAlgorithm::SHA512,
11 => HashAlgorithm::SHA224,
100..=110 => HashAlgorithm::Private(u),
u => HashAlgorithm::Unknown(u),
}
}
}
impl From<HashAlgorithm> for u8 {
fn from(h: HashAlgorithm) -> u8 {
match h {
HashAlgorithm::MD5 => 1,
HashAlgorithm::SHA1 => 2,
HashAlgorithm::RipeMD => 3,
HashAlgorithm::SHA256 => 8,
HashAlgorithm::SHA384 => 9,
HashAlgorithm::SHA512 => 10,
HashAlgorithm::SHA224 => 11,
HashAlgorithm::Private(u) => u,
HashAlgorithm::Unknown(u) => u,
}
}
}
impl FromStr for HashAlgorithm {
type Err = ();
fn from_str(s: &str) -> result::Result<Self, ()> {
if s == "MD5" {
Ok(HashAlgorithm::MD5)
} else if s == "SHA1" {
Ok(HashAlgorithm::SHA1)
} else if s == "RipeMD160" {
Ok(HashAlgorithm::RipeMD)
} else if s == "SHA256" {
Ok(HashAlgorithm::SHA256)
} else if s == "SHA384" {
Ok(HashAlgorithm::SHA384)
} else if s == "SHA512" {
Ok(HashAlgorithm::SHA512)
} else if s == "SHA224" {
Ok(HashAlgorithm::SHA224)
} else {
Err(())
}
}
}
impl fmt::Display for HashAlgorithm {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match *self {
HashAlgorithm::MD5 => f.write_str("MD5"),
HashAlgorithm::SHA1 => f.write_str("SHA1"),
HashAlgorithm::RipeMD => f.write_str("RipeMD160"),
HashAlgorithm::SHA256 => f.write_str("SHA256"),
HashAlgorithm::SHA384 => f.write_str("SHA384"),
HashAlgorithm::SHA512 => f.write_str("SHA512"),
HashAlgorithm::SHA224 => f.write_str("SHA224"),
HashAlgorithm::Private(u) =>
f.write_fmt(format_args!("Private/Experimental hash algorithm {}", u)),
HashAlgorithm::Unknown(u) =>
f.write_fmt(format_args!("Unknown hash algorithm {}", u)),
}
}
}
impl Arbitrary for HashAlgorithm {
fn arbitrary<G: Gen>(g: &mut G) -> Self {
u8::arbitrary(g).into()
}
}
#[derive(Clone, Copy, Hash, PartialEq, Eq, Debug)]
pub enum SignatureType {
Binary,
Text,
Standalone,
GenericCertification,
PersonaCertification,
CasualCertification,
PositiveCertification,
SubkeyBinding,
PrimaryKeyBinding,
DirectKey,
KeyRevocation,
SubkeyRevocation,
CertificationRevocation,
Timestamp,
Confirmation,
Unknown(u8),
}
impl From<u8> for SignatureType {
fn from(u: u8) -> Self {
match u {
0x00 => SignatureType::Binary,
0x01 => SignatureType::Text,
0x02 => SignatureType::Standalone,
0x10 => SignatureType::GenericCertification,
0x11 => SignatureType::PersonaCertification,
0x12 => SignatureType::CasualCertification,
0x13 => SignatureType::PositiveCertification,
0x18 => SignatureType::SubkeyBinding,
0x19 => SignatureType::PrimaryKeyBinding,
0x1f => SignatureType::DirectKey,
0x20 => SignatureType::KeyRevocation,
0x28 => SignatureType::SubkeyRevocation,
0x30 => SignatureType::CertificationRevocation,
0x40 => SignatureType::Timestamp,
0x50 => SignatureType::Confirmation,
_ => SignatureType::Unknown(u),
}
}
}
impl From<SignatureType> for u8 {
fn from(t: SignatureType) -> Self {
match t {
SignatureType::Binary => 0x00,
SignatureType::Text => 0x01,
SignatureType::Standalone => 0x02,
SignatureType::GenericCertification => 0x10,
SignatureType::PersonaCertification => 0x11,
SignatureType::CasualCertification => 0x12,
SignatureType::PositiveCertification => 0x13,
SignatureType::SubkeyBinding => 0x18,
SignatureType::PrimaryKeyBinding => 0x19,
SignatureType::DirectKey => 0x1f,
SignatureType::KeyRevocation => 0x20,
SignatureType::SubkeyRevocation => 0x28,
SignatureType::CertificationRevocation => 0x30,
SignatureType::Timestamp => 0x40,
SignatureType::Confirmation => 0x50,
SignatureType::Unknown(u) => u,
}
}
}
impl fmt::Display for SignatureType {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match *self {
SignatureType::Binary =>
f.write_str("Binary"),
SignatureType::Text =>
f.write_str("Text"),
SignatureType::Standalone =>
f.write_str("Standalone"),
SignatureType::GenericCertification =>
f.write_str("GenericCertification"),
SignatureType::PersonaCertification =>
f.write_str("PersonaCertification"),
SignatureType::CasualCertification =>
f.write_str("CasualCertification"),
SignatureType::PositiveCertification =>
f.write_str("PositiveCertification"),
SignatureType::SubkeyBinding =>
f.write_str("SubkeyBinding"),
SignatureType::PrimaryKeyBinding =>
f.write_str("PrimaryKeyBinding"),
SignatureType::DirectKey =>
f.write_str("DirectKey"),
SignatureType::KeyRevocation =>
f.write_str("KeyRevocation"),
SignatureType::SubkeyRevocation =>
f.write_str("SubkeyRevocation"),
SignatureType::CertificationRevocation =>
f.write_str("CertificationRevocation"),
SignatureType::Timestamp =>
f.write_str("Timestamp"),
SignatureType::Confirmation =>
f.write_str("Confirmation"),
SignatureType::Unknown(u) =>
f.write_fmt(format_args!("Unknown signature type 0x{:x}", u)),
}
}
}
impl Arbitrary for SignatureType {
fn arbitrary<G: Gen>(g: &mut G) -> Self {
u8::arbitrary(g).into()
}
}
#[derive(Clone, Copy, Hash, PartialEq, Eq, Debug, PartialOrd, Ord)]
pub enum ReasonForRevocation {
Unspecified,
KeySuperseded,
KeyCompromised,
KeyRetired,
UIDRetired,
Private(u8),
Unknown(u8),
}
impl From<u8> for ReasonForRevocation {
fn from(u: u8) -> Self {
use self::ReasonForRevocation::*;
match u {
0 => Unspecified,
1 => KeySuperseded,
2 => KeyCompromised,
3 => KeyRetired,
32 => UIDRetired,
100..=110 => Private(u),
u => Unknown(u),
}
}
}
impl From<ReasonForRevocation> for u8 {
fn from(r: ReasonForRevocation) -> u8 {
use self::ReasonForRevocation::*;
match r {
Unspecified => 0,
KeySuperseded => 1,
KeyCompromised => 2,
KeyRetired => 3,
UIDRetired => 32,
Private(u) => u,
Unknown(u) => u,
}
}
}
impl fmt::Display for ReasonForRevocation {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
use self::ReasonForRevocation::*;
match *self {
Unspecified =>
f.write_str("No reason specified"),
KeySuperseded =>
f.write_str("Key is superseded"),
KeyCompromised =>
f.write_str("Key material has been compromised"),
KeyRetired =>
f.write_str("Key is retired and no longer used"),
UIDRetired =>
f.write_str("User ID information is no longer valid"),
Private(u) =>
f.write_fmt(format_args!(
"Private/Experimental revocation reason {}", u)),
Unknown(u) =>
f.write_fmt(format_args!(
"Unknown revocation reason {}", u)),
}
}
}
impl Arbitrary for ReasonForRevocation {
fn arbitrary<G: Gen>(g: &mut G) -> Self {
u8::arbitrary(g).into()
}
}
#[derive(Clone, Copy, PartialEq, Eq)]
pub enum RevocationType {
Hard,
Soft,
}
impl ReasonForRevocation {
pub fn revocation_type(&self) -> RevocationType {
match self {
ReasonForRevocation::Unspecified => RevocationType::Hard,
ReasonForRevocation::KeySuperseded => RevocationType::Soft,
ReasonForRevocation::KeyCompromised => RevocationType::Hard,
ReasonForRevocation::KeyRetired => RevocationType::Soft,
ReasonForRevocation::UIDRetired => RevocationType::Soft,
ReasonForRevocation::Private(_) => RevocationType::Hard,
ReasonForRevocation::Unknown(_) => RevocationType::Hard,
}
}
}
#[derive(Clone, Copy, Hash, PartialEq, Eq, Debug, PartialOrd, Ord)]
pub enum DataFormat {
Binary,
Text,
Unicode,
MIME,
Unknown(char),
}
impl Default for DataFormat {
fn default() -> Self {
DataFormat::Binary
}
}
impl From<u8> for DataFormat {
fn from(u: u8) -> Self {
(u as char).into()
}
}
impl From<char> for DataFormat {
fn from(c: char) -> Self {
use self::DataFormat::*;
match c {
'b' => Binary,
't' => Text,
'u' => Unicode,
'm' => MIME,
c => Unknown(c),
}
}
}
impl From<DataFormat> for u8 {
fn from(f: DataFormat) -> u8 {
char::from(f) as u8
}
}
impl From<DataFormat> for char {
fn from(f: DataFormat) -> char {
use self::DataFormat::*;
match f {
Binary => 'b',
Text => 't',
Unicode => 'u',
MIME => 'm',
Unknown(c) => c,
}
}
}
impl fmt::Display for DataFormat {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
use self::DataFormat::*;
match *self {
Binary =>
f.write_str("Binary data"),
Text =>
f.write_str("Text data"),
Unicode =>
f.write_str("Text data (UTF-8)"),
MIME =>
f.write_str("MIME message body part"),
Unknown(c) =>
f.write_fmt(format_args!(
"Unknown data format identifier {:?}", c)),
}
}
}
impl Arbitrary for DataFormat {
fn arbitrary<G: Gen>(g: &mut G) -> Self {
u8::arbitrary(g).into()
}
}
#[cfg(test)]
mod tests {
use super::*;
quickcheck! {
fn comp_roundtrip(comp: CompressionAlgorithm) -> bool {
let val: u8 = comp.clone().into();
comp == CompressionAlgorithm::from(val)
}
}
quickcheck! {
fn comp_display(comp: CompressionAlgorithm) -> bool {
let s = format!("{}", comp);
!s.is_empty()
}
}
quickcheck! {
fn comp_parse(comp: CompressionAlgorithm) -> bool {
match comp {
CompressionAlgorithm::Unknown(u) => u > 110 || (u > 3 && u < 100),
CompressionAlgorithm::Private(u) => u >= 100 && u <= 110,
_ => true
}
}
}
quickcheck! {
fn sym_roundtrip(sym: SymmetricAlgorithm) -> bool {
let val: u8 = sym.clone().into();
sym == SymmetricAlgorithm::from(val)
}
}
quickcheck! {
fn sym_display(sym: SymmetricAlgorithm) -> bool {
let s = format!("{}", sym);
!s.is_empty()
}
}
quickcheck! {
fn sym_parse(sym: SymmetricAlgorithm) -> bool {
match sym {
SymmetricAlgorithm::Unknown(u) =>
u == 5 || u == 6 || u > 110 || (u > 10 && u < 100),
SymmetricAlgorithm::Private(u) =>
u >= 100 && u <= 110,
_ => true
}
}
}
quickcheck! {
fn aead_roundtrip(aead: AEADAlgorithm) -> bool {
let val: u8 = aead.clone().into();
aead == AEADAlgorithm::from(val)
}
}
quickcheck! {
fn aead_display(aead: AEADAlgorithm) -> bool {
let s = format!("{}", aead);
!s.is_empty()
}
}
quickcheck! {
fn aead_parse(aead: AEADAlgorithm) -> bool {
match aead {
AEADAlgorithm::Unknown(u) =>
u == 0 || u > 110 || (u > 2 && u < 100),
AEADAlgorithm::Private(u) =>
u >= 100 && u <= 110,
_ => true
}
}
}
quickcheck! {
fn pk_roundtrip(pk: PublicKeyAlgorithm) -> bool {
let val: u8 = pk.clone().into();
pk == PublicKeyAlgorithm::from(val)
}
}
quickcheck! {
fn pk_display(pk: PublicKeyAlgorithm) -> bool {
let s = format!("{}", pk);
!s.is_empty()
}
}
quickcheck! {
fn pk_parse(pk: PublicKeyAlgorithm) -> bool {
match pk {
PublicKeyAlgorithm::Unknown(u) =>
u == 0 || u > 110 || (u >= 4 && u <= 15)
|| (u >= 18 && u < 100),
PublicKeyAlgorithm::Private(u) => u >= 100 && u <= 110,
_ => true
}
}
}
quickcheck! {
fn curve_roundtrip(curve: Curve) -> bool {
curve == Curve::from_oid(curve.oid())
}
}
quickcheck! {
fn signature_type_roundtrip(t: SignatureType) -> bool {
let val: u8 = t.clone().into();
t == SignatureType::from(val)
}
}
quickcheck! {
fn signature_type_display(t: SignatureType) -> bool {
let s = format!("{}", t);
!s.is_empty()
}
}
quickcheck! {
fn hash_roundtrip(hash: HashAlgorithm) -> bool {
let val: u8 = hash.clone().into();
hash == HashAlgorithm::from(val)
}
}
quickcheck! {
fn hash_roundtrip_str(hash: HashAlgorithm) -> bool {
match hash {
HashAlgorithm::Private(_) | HashAlgorithm::Unknown(_) => true,
hash => {
let s = format!("{}", hash);
hash == HashAlgorithm::from_str(&s).unwrap()
}
}
}
}
quickcheck! {
fn hash_display(hash: HashAlgorithm) -> bool {
let s = format!("{}", hash);
!s.is_empty()
}
}
quickcheck! {
fn hash_parse(hash: HashAlgorithm) -> bool {
match hash {
HashAlgorithm::Unknown(u) => u == 0 || (u > 11 && u < 100) ||
u > 110 || (u >= 4 && u <= 7) || u == 0,
HashAlgorithm::Private(u) => u >= 100 && u <= 110,
_ => true
}
}
}
quickcheck! {
fn rfr_roundtrip(rfr: ReasonForRevocation) -> bool {
let val: u8 = rfr.clone().into();
rfr == ReasonForRevocation::from(val)
}
}
quickcheck! {
fn rfr_display(rfr: ReasonForRevocation) -> bool {
let s = format!("{}", rfr);
!s.is_empty()
}
}
quickcheck! {
fn rfr_parse(rfr: ReasonForRevocation) -> bool {
match rfr {
ReasonForRevocation::Unknown(u) =>
(u > 3 && u < 32)
|| (u > 32 && u < 100)
|| u > 110,
ReasonForRevocation::Private(u) =>
u >= 100 && u <= 110,
_ => true
}
}
}
quickcheck! {
fn df_roundtrip(df: DataFormat) -> bool {
let val: u8 = df.clone().into();
df == DataFormat::from(val)
}
}
quickcheck! {
fn df_display(df: DataFormat) -> bool {
let s = format!("{}", df);
!s.is_empty()
}
}
quickcheck! {
fn df_parse(df: DataFormat) -> bool {
match df {
DataFormat::Unknown(u) =>
u != 'b' && u != 't' && u != 'u' && u != 'm',
_ => true
}
}
}
}