sequoia_openpgp/types/
revocation_key.rs

1#[cfg(test)]
2use quickcheck::{Arbitrary, Gen};
3
4use crate::{
5    cert::prelude::*,
6    Error,
7    Fingerprint,
8    Result,
9    types::{
10        PublicKeyAlgorithm,
11    },
12};
13
14/// Designates a key as a valid third-party revoker.
15///
16/// This is described in [Section 5.2.3.23 of RFC 9580].
17///
18/// [Section 5.2.3.23 of RFC 9580]: https://www.rfc-editor.org/rfc/rfc9580.html#section-5.2.3.23
19///
20/// Revocation keys can be retrieved using [`ValidAmalgamation::revocation_keys`]
21/// and set using [`CertBuilder::set_revocation_keys`].
22///
23/// [`ValidAmalgamation::revocation_keys`]: crate::cert::amalgamation::ValidAmalgamation::revocation_keys()
24/// [`CertBuilder::set_revocation_keys`]: crate::cert::CertBuilder::set_revocation_keys()
25///
26/// # Examples
27///
28/// ```
29/// use sequoia_openpgp as openpgp;
30/// # use openpgp::Result;
31/// use openpgp::cert::prelude::*;
32/// use openpgp::policy::StandardPolicy;
33/// use openpgp::types::RevocationKey;
34///
35/// # fn main() -> Result<()> {
36/// let p = &StandardPolicy::new();
37///
38/// let (alice, _) =
39///     CertBuilder::general_purpose(Some("alice@example.org"))
40///     .generate()?;
41///
42/// // Make Alice a designated revoker for Bob.
43/// let (bob, _) =
44///     CertBuilder::general_purpose(Some("bob@example.org"))
45///     .set_revocation_keys(vec![(&alice).into()])
46///     .generate()?;
47///
48/// // Make sure Alice is listed as a designated revoker for Bob.
49/// assert_eq!(bob.with_policy(p, None)?.revocation_keys()
50///                .collect::<Vec<&RevocationKey>>(),
51///            vec![&(&alice).into()]);
52/// # Ok(()) }
53/// ```
54#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
55pub struct RevocationKey {
56    /// The public key algorithm used by the authorized key.
57    pk_algo: PublicKeyAlgorithm,
58
59    /// Fingerprint of authorized key.
60    fp: Fingerprint,
61
62    /// Indicates that the relation between revoker and revokee is
63    /// of a sensitive nature.
64    sensitive: bool,
65
66    /// Other bits are for future expansion to other kinds of
67    /// authorizations.
68    unknown: u8,
69}
70assert_send_and_sync!(RevocationKey);
71
72impl From<&Cert> for RevocationKey {
73    fn from(cert: &Cert) -> Self {
74        RevocationKey::new(cert.primary_key().key().pk_algo(),
75                           cert.fingerprint(),
76                           false)
77    }
78}
79
80impl RevocationKey {
81    /// Creates a new instance.
82    pub fn new(pk_algo: PublicKeyAlgorithm, fp: Fingerprint, sensitive: bool)
83               -> Self
84    {
85        RevocationKey {
86            pk_algo, fp, sensitive, unknown: 0,
87        }
88    }
89
90    /// Creates a new instance from the raw `class` parameter.
91    pub fn from_bits(pk_algo: PublicKeyAlgorithm, fp: Fingerprint, class: u8)
92                     -> Result<Self> {
93        if class & REVOCATION_KEY_FLAG_MUST_BE_SET == 0 {
94            return Err(Error::InvalidArgument(
95                "Most significant bit of class must be set".into()).into());
96        }
97        let sensitive = class & REVOCATION_KEY_FLAG_SENSITIVE > 0;
98        let unknown = class & REVOCATION_KEY_MASK_UNKNOWN;
99        Ok(RevocationKey {
100            pk_algo, fp, sensitive, unknown,
101        })
102    }
103
104    /// Returns the `class` octet, the sum of all flags.
105    pub fn class(&self) -> u8 {
106        REVOCATION_KEY_FLAG_MUST_BE_SET
107            | if self.sensitive() {
108                REVOCATION_KEY_FLAG_SENSITIVE
109            } else {
110                0
111            }
112            | self.unknown
113    }
114
115    /// Returns the revoker's identity.
116    pub fn revoker(&self) -> (PublicKeyAlgorithm, &Fingerprint) {
117        (self.pk_algo, &self.fp)
118    }
119
120    /// Sets the revoker's identity.
121    pub fn set_revoker(&mut self, pk_algo: PublicKeyAlgorithm, fp: Fingerprint)
122                       -> (PublicKeyAlgorithm, Fingerprint) {
123        let pk_algo = std::mem::replace(&mut self.pk_algo, pk_algo);
124        let fp = std::mem::replace(&mut self.fp, fp);
125        (pk_algo, fp)
126    }
127
128    /// Returns whether the relation between revoker and
129    /// revokee is of a sensitive nature.
130    pub fn sensitive(&self) -> bool {
131        self.sensitive
132    }
133
134    /// Sets whether the relation between revoker and revokee
135    /// is of a sensitive nature.
136    pub fn set_sensitive(mut self, v: bool) -> Self {
137        self.sensitive = v;
138        self
139    }
140}
141
142/// This bit must be set.
143const REVOCATION_KEY_FLAG_MUST_BE_SET: u8 = 0x80;
144
145/// Relation is of a sensitive nature.
146const REVOCATION_KEY_FLAG_SENSITIVE: u8 = 0x40;
147
148/// Mask covering the unknown bits.
149const REVOCATION_KEY_MASK_UNKNOWN: u8 = ! (REVOCATION_KEY_FLAG_MUST_BE_SET
150                                           | REVOCATION_KEY_FLAG_SENSITIVE);
151
152#[cfg(test)]
153impl Arbitrary for RevocationKey {
154    fn arbitrary(g: &mut Gen) -> Self {
155        RevocationKey {
156            pk_algo: Arbitrary::arbitrary(g),
157            fp: Arbitrary::arbitrary(g),
158            sensitive: Arbitrary::arbitrary(g),
159            unknown: u8::arbitrary(g) & REVOCATION_KEY_MASK_UNKNOWN,
160        }
161    }
162}