diff options
Diffstat (limited to 'openpgp')
-rw-r--r-- | openpgp/src/constants.rs | 117 | ||||
-rw-r--r-- | openpgp/src/serialize/mod.rs | 2 | ||||
-rw-r--r-- | openpgp/src/subpacket.rs | 22 |
3 files changed, 132 insertions, 9 deletions
diff --git a/openpgp/src/constants.rs b/openpgp/src/constants.rs index ee7be8ee..bf41e428 100644 --- a/openpgp/src/constants.rs +++ b/openpgp/src/constants.rs @@ -664,6 +664,95 @@ impl Arbitrary for SignatureType { } } +/// Describes the reason for a revocation. +/// +/// See the description of revocation subpackets [Section 5.2.3.23 of RFC 4880]. +/// +/// [Section 5.2.3.23 of RFC 4880]: https://tools.ietf.org/html/rfc4880#section-5.2.3.23 +#[derive(Clone, Copy, PartialEq, Eq, Debug, PartialOrd, Ord)] +pub enum ReasonForRevocation { + /// No reason specified (key revocations or cert revocations) + Unspecified, + + /// Key is superseded (key revocations) + KeySuperseeded, + + /// Key material has been compromised (key revocations) + KeyCompromised, + + /// Key is retired and no longer used (key revocations) + KeyRetired, + + /// User ID information is no longer valid (cert revocations) + UIDRetired, + + /// Private reason identifier. + Private(u8), + + /// Unknown reason identifier. + Unknown(u8), +} + +impl From<u8> for ReasonForRevocation { + fn from(u: u8) -> Self { + use self::ReasonForRevocation::*; + match u { + 0 => Unspecified, + 1 => KeySuperseeded, + 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, + KeySuperseeded => 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"), + KeySuperseeded => + 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() + } +} + #[cfg(test)] mod tests { use super::*; @@ -805,4 +894,32 @@ mod tests { } } } + + 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 + } + } + } } diff --git a/openpgp/src/serialize/mod.rs b/openpgp/src/serialize/mod.rs index 82c97347..039eacb1 100644 --- a/openpgp/src/serialize/mod.rs +++ b/openpgp/src/serialize/mod.rs @@ -464,7 +464,7 @@ impl<'a> Serialize for SubpacketValue<'a> { SignersUserID(ref uid) => o.write_all(uid)?, ReasonForRevocation { ref code, ref reason } => { - o.write_all(&[*code])?; + o.write_all(&[(*code).into()])?; o.write_all(reason)?; }, Features(ref f) => diff --git a/openpgp/src/subpacket.rs b/openpgp/src/subpacket.rs index 677eca49..c79d3965 100644 --- a/openpgp/src/subpacket.rs +++ b/openpgp/src/subpacket.rs @@ -77,6 +77,7 @@ use constants::{ CompressionAlgorithm, HashAlgorithm, PublicKeyAlgorithm, + ReasonForRevocation, SymmetricAlgorithm, }; use conversions::{ @@ -616,7 +617,7 @@ pub enum SubpacketValue<'a> { /// 1 octet of revocation code, N octets of reason string ReasonForRevocation { /// Machine-readable reason for revocation. - code: u8, + code: ReasonForRevocation, /// Human-readable reason for revocation. reason: &'a [u8], @@ -937,7 +938,7 @@ impl<'a> From<SubpacketRaw<'a>> for Subpacket<'a> { // 1 octet of revocation code, N octets of reason string if raw.value.len() >= 1 { Some(SubpacketValue::ReasonForRevocation { - code: raw.value[0], + code: raw.value[0].into(), reason: &raw.value[1..], }) } else { @@ -2190,7 +2191,8 @@ impl Signature { /// /// Note: if the signature contains multiple instances of this /// subpacket, only the last one is considered. - pub fn reason_for_revocation(&self) -> Option<(u8, &[u8])> { + pub fn reason_for_revocation(&self) + -> Option<(ReasonForRevocation, &[u8])> { // 1 octet of revocation code, N octets of reason string if let Some(sb) = self.subpacket(SubpacketTag::ReasonForRevocation) { if let SubpacketValue::ReasonForRevocation { @@ -2206,7 +2208,8 @@ impl Signature { } /// Sets the value of the Reason for Revocation subpacket. - pub fn set_reason_for_revocation(&mut self, code: u8, reason: &[u8]) + pub fn set_reason_for_revocation(&mut self, code: ReasonForRevocation, + reason: &[u8]) -> Result<()> { self.hashed_area.replace(Subpacket::new( SubpacketValue::ReasonForRevocation { @@ -2505,8 +2508,10 @@ fn accessors() { sig.set_signers_user_id(b"foobar").unwrap(); assert_eq!(sig.signers_user_id(), Some(&b"foobar"[..])); - sig.set_reason_for_revocation(3, b"foobar").unwrap(); - assert_eq!(sig.reason_for_revocation(), Some((3, &b"foobar"[..]))); + sig.set_reason_for_revocation(ReasonForRevocation::KeyRetired, + b"foobar").unwrap(); + assert_eq!(sig.reason_for_revocation(), + Some((ReasonForRevocation::KeyRetired, &b"foobar"[..]))); let feats = Features::default().set_mdc(true); sig.set_features(&feats).unwrap(); @@ -2916,13 +2921,14 @@ fn subpacket_test_2() { })); assert_eq!(sig.reason_for_revocation(), - Some((0, &b"Forgot to set a sig expiration."[..]))); + Some((ReasonForRevocation::Unspecified, + &b"Forgot to set a sig expiration."[..]))); assert_eq!(sig.subpacket(SubpacketTag::ReasonForRevocation), Some(Subpacket { critical: false, tag: SubpacketTag::ReasonForRevocation, value: SubpacketValue::ReasonForRevocation { - code: 0, + code: ReasonForRevocation::Unspecified, reason: &b"Forgot to set a sig expiration."[..], }, })); |