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}