Skip to main content
This is unreleased documentation for the main (development) branch of crypto-glue.

x509_cert/ext/pkix/
keyusage.rs

1use alloc::vec::Vec;
2
3use const_oid::AssociatedOid;
4use const_oid::db::rfc5280::{
5    ID_CE_EXT_KEY_USAGE, ID_CE_KEY_USAGE, ID_CE_PRIVATE_KEY_USAGE_PERIOD,
6};
7use der::Sequence;
8use der::asn1::{GeneralizedTime, ObjectIdentifier};
9use der::flagset::{FlagSet, flags};
10
11flags! {
12    /// Key usage flags as defined in [RFC 5280 Section 4.2.1.3].
13    ///
14    /// ```text
15    /// KeyUsage ::= BIT STRING {
16    ///      digitalSignature        (0),
17    ///      nonRepudiation          (1),  -- recent editions of X.509 have
18    ///                                    -- renamed this bit to contentCommitment
19    ///      keyEncipherment         (2),
20    ///      dataEncipherment        (3),
21    ///      keyAgreement            (4),
22    ///      keyCertSign             (5),
23    ///      cRLSign                 (6),
24    ///      encipherOnly            (7),
25    ///      decipherOnly            (8)
26    /// }
27    /// ```
28    ///
29    /// [RFC 5280 Section 4.2.1.3]: https://datatracker.ietf.org/doc/html/rfc5280#section-4.2.1.3
30    #[allow(missing_docs)]
31    pub enum KeyUsages: u16 {
32        DigitalSignature = 1 << 0,
33        NonRepudiation = 1 << 1,
34        KeyEncipherment = 1 << 2,
35        DataEncipherment = 1 << 3,
36        KeyAgreement = 1 << 4,
37        KeyCertSign = 1 << 5,
38        CRLSign = 1 << 6,
39        EncipherOnly = 1 << 7,
40        DecipherOnly = 1 << 8,
41    }
42}
43
44/// KeyUsage as defined in [RFC 5280 Section 4.2.1.3].
45///
46/// [RFC 5280 Section 4.2.1.3]: https://datatracker.ietf.org/doc/html/rfc5280#section-4.2.1.3
47#[derive(Copy, Clone, Debug, PartialEq, Eq)]
48pub struct KeyUsage(pub FlagSet<KeyUsages>);
49
50impl AssociatedOid for KeyUsage {
51    const OID: ObjectIdentifier = ID_CE_KEY_USAGE;
52}
53
54impl_newtype!(KeyUsage, FlagSet<KeyUsages>);
55impl_extension!(KeyUsage, critical = true);
56
57impl KeyUsage {
58    /// The subject public key is used for verifying digital signatures
59    pub fn digital_signature(&self) -> bool {
60        self.0.contains(KeyUsages::DigitalSignature)
61    }
62
63    /// When the subject public key is used to verify digital signatures,
64    /// it is asserted as non-repudiation.
65    pub fn non_repudiation(&self) -> bool {
66        self.0.contains(KeyUsages::NonRepudiation)
67    }
68
69    /// The subject public key is used for enciphering private or
70    /// secret keys, i.e., for key transport.
71    pub fn key_encipherment(&self) -> bool {
72        self.0.contains(KeyUsages::KeyEncipherment)
73    }
74
75    /// The subject public key is used for directly enciphering
76    /// raw user data without the use of an intermediate symmetric cipher.
77    pub fn data_encipherment(&self) -> bool {
78        self.0.contains(KeyUsages::DataEncipherment)
79    }
80
81    /// The subject public key is used for key agreement
82    pub fn key_agreement(&self) -> bool {
83        self.0.contains(KeyUsages::KeyAgreement)
84    }
85
86    /// The subject public key is used for enciphering private or
87    /// secret keys, i.e., for key transport.
88    pub fn key_cert_sign(&self) -> bool {
89        self.0.contains(KeyUsages::KeyCertSign)
90    }
91
92    /// The subject public key is used for verifying signatures
93    /// on certificate revocation lists (e.g., CRLs, delta CRLs,
94    /// or ARLs).
95    pub fn crl_sign(&self) -> bool {
96        self.0.contains(KeyUsages::CRLSign)
97    }
98
99    /// The meaning of the `encipher_only` is undefined when `key_agreement`
100    /// returns false.  When `encipher_only` returns true and
101    /// `key_agreement` also returns true, the subject public key may be
102    /// used only for enciphering data while performing key agreement.
103    pub fn encipher_only(&self) -> bool {
104        self.0.contains(KeyUsages::EncipherOnly)
105    }
106
107    /// The meaning of the `decipher_only` is undefined when `key_agreement`
108    /// returns false.  When `encipher_only` returns true and
109    /// `key_agreement` also returns true, the subject public key may be
110    /// used only for deciphering data while performing key agreement.
111    pub fn decipher_only(&self) -> bool {
112        self.0.contains(KeyUsages::DecipherOnly)
113    }
114}
115
116/// ExtKeyUsageSyntax as defined in [RFC 5280 Section 4.2.1.12].
117///
118/// Many extended key usage values include:
119/// - [`PKIX_CE_ANYEXTENDEDKEYUSAGE`](constant.PKIX_CE_ANYEXTENDEDKEYUSAGE.html),
120/// - [`PKIX_KP_SERVERAUTH`](constant.PKIX_KP_SERVERAUTH.html),
121/// - [`PKIX_KP_CLIENTAUTH`](constant.PKIX_KP_CLIENTAUTH.html),
122/// - [`PKIX_KP_CODESIGNING`](constant.PKIX_KP_CODESIGNING.html),
123/// - [`PKIX_KP_EMAILPROTECTION`](constant.PKIX_KP_EMAILPROTECTION.html),
124/// - [`PKIX_KP_TIMESTAMPING`](constant.PKIX_KP_TIMESTAMPING.html),
125///
126/// ```text
127/// ExtKeyUsageSyntax ::= SEQUENCE SIZE (1..MAX) OF KeyPurposeId
128/// KeyPurposeId ::= OBJECT IDENTIFIER
129/// ```
130///
131/// [RFC 5280 Section 4.2.1.12]: https://datatracker.ietf.org/doc/html/rfc5280#section-4.2.1.12
132#[derive(Clone, Debug, PartialEq, Eq)]
133pub struct ExtendedKeyUsage(pub Vec<ObjectIdentifier>);
134
135impl AssociatedOid for ExtendedKeyUsage {
136    const OID: ObjectIdentifier = ID_CE_EXT_KEY_USAGE;
137}
138
139impl_newtype!(ExtendedKeyUsage, Vec<ObjectIdentifier>);
140
141impl_extension!(ExtendedKeyUsage, critical = false);
142
143/// PrivateKeyUsagePeriod as defined in [RFC 3280 Section 4.2.1.4].
144///
145/// RFC 5280 states "use of this ISO standard extension is neither deprecated nor recommended for use in the Internet PKI."
146///
147/// ```text
148/// PrivateKeyUsagePeriod ::= SEQUENCE {
149///      notBefore       [0]     GeneralizedTime OPTIONAL,
150///      notAfter        [1]     GeneralizedTime OPTIONAL }
151///      -- either notBefore or notAfter MUST be present
152/// ```
153///
154/// [RFC 3280 Section 4.2.1.12]: https://datatracker.ietf.org/doc/html/rfc3280#section-4.2.1.4
155#[derive(Clone, Debug, PartialEq, Eq, Sequence)]
156#[allow(missing_docs)]
157pub struct PrivateKeyUsagePeriod {
158    #[asn1(context_specific = "0", tag_mode = "IMPLICIT", optional = "true")]
159    pub not_before: Option<GeneralizedTime>,
160
161    #[asn1(context_specific = "1", tag_mode = "IMPLICIT", optional = "true")]
162    pub not_after: Option<GeneralizedTime>,
163}
164
165impl AssociatedOid for PrivateKeyUsagePeriod {
166    const OID: ObjectIdentifier = ID_CE_PRIVATE_KEY_USAGE_PERIOD;
167}
168
169impl_extension!(PrivateKeyUsagePeriod, critical = false);
170
171#[cfg(test)]
172mod tests {
173    use super::*;
174
175    #[test]
176    fn digital_signature_contains_digital_signature() {
177        let key_usage = KeyUsage(KeyUsages::DigitalSignature.into());
178        assert!(key_usage.digital_signature());
179    }
180
181    #[test]
182    fn all_contains_digital_signature() {
183        let key_usage = KeyUsage(FlagSet::full());
184        assert!(key_usage.digital_signature());
185    }
186
187    #[test]
188    fn key_encipherment_not_contains_digital_signature() {
189        let key_usage = KeyUsage(KeyUsages::KeyEncipherment.into());
190        assert!(!key_usage.digital_signature());
191    }
192
193    #[test]
194    fn empty_not_contains_digital_signature() {
195        let key_usage = KeyUsage(None.into());
196        assert!(!key_usage.digital_signature());
197    }
198}