1 use alloc::vec::Vec; 2 3 use const_oid::db::rfc5280::{ 4 ANY_EXTENDED_KEY_USAGE, ID_CE_EXT_KEY_USAGE, ID_CE_KEY_USAGE, ID_CE_PRIVATE_KEY_USAGE_PERIOD, 5 }; 6 use const_oid::AssociatedOid; 7 use der::asn1::{GeneralizedTime, ObjectIdentifier}; 8 use der::flagset::{flags, FlagSet}; 9 use der::Sequence; 10 11 flags! { 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)] 48 pub struct KeyUsage(pub FlagSet<KeyUsages>); 49 50 impl AssociatedOid for KeyUsage { 51 const OID: ObjectIdentifier = ID_CE_KEY_USAGE; 52 } 53 54 impl_newtype!(KeyUsage, FlagSet<KeyUsages>); 55 impl_extension!(KeyUsage, critical = true); 56 57 impl KeyUsage { 58 /// The subject public key is used for verifying digital signatures digital_signature(&self) -> bool59 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. non_repudiation(&self) -> bool65 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. key_encipherment(&self) -> bool71 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. data_encipherment(&self) -> bool77 pub fn data_encipherment(&self) -> bool { 78 self.0.contains(KeyUsages::DataEncipherment) 79 } 80 81 /// The subject public key is used for key agreement key_agreement(&self) -> bool82 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. key_cert_sign(&self) -> bool88 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). crl_sign(&self) -> bool95 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. encipher_only(&self) -> bool103 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. decipher_only(&self) -> bool111 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)] 133 pub struct ExtendedKeyUsage(pub Vec<ObjectIdentifier>); 134 135 impl AssociatedOid for ExtendedKeyUsage { 136 const OID: ObjectIdentifier = ID_CE_EXT_KEY_USAGE; 137 } 138 139 impl_newtype!(ExtendedKeyUsage, Vec<ObjectIdentifier>); 140 141 impl crate::ext::AsExtension for ExtendedKeyUsage { critical( &self, _subject: &crate::name::Name, _extensions: &[crate::ext::Extension], ) -> bool142 fn critical( 143 &self, 144 _subject: &crate::name::Name, 145 _extensions: &[crate::ext::Extension], 146 ) -> bool { 147 // https://datatracker.ietf.org/doc/html/rfc5280#section-4.2.1.12 148 // This extension MAY, at the option of the certificate issuer, be 149 // either critical or non-critical. 150 // 151 // If a CA includes extended key usages to satisfy such applications, 152 // but does not wish to restrict usages of the key, the CA can include 153 // the special KeyPurposeId anyExtendedKeyUsage in addition to the 154 // particular key purposes required by the applications. Conforming CAs 155 // SHOULD NOT mark this extension as critical if the anyExtendedKeyUsage 156 // KeyPurposeId is present. Applications that require the presence of a 157 // particular purpose MAY reject certificates that include the 158 // anyExtendedKeyUsage OID but not the particular OID expected for the 159 // application. 160 161 !self.0.iter().any(|el| *el == ANY_EXTENDED_KEY_USAGE) 162 } 163 } 164 165 /// PrivateKeyUsagePeriod as defined in [RFC 3280 Section 4.2.1.4]. 166 /// 167 /// RFC 5280 states "use of this ISO standard extension is neither deprecated nor recommended for use in the Internet PKI." 168 /// 169 /// ```text 170 /// PrivateKeyUsagePeriod ::= SEQUENCE { 171 /// notBefore [0] GeneralizedTime OPTIONAL, 172 /// notAfter [1] GeneralizedTime OPTIONAL } 173 /// -- either notBefore or notAfter MUST be present 174 /// ``` 175 /// 176 /// [RFC 3280 Section 4.2.1.12]: https://datatracker.ietf.org/doc/html/rfc3280#section-4.2.1.4 177 #[derive(Clone, Debug, PartialEq, Eq, Sequence)] 178 #[allow(missing_docs)] 179 pub struct PrivateKeyUsagePeriod { 180 #[asn1(context_specific = "0", tag_mode = "IMPLICIT", optional = "true")] 181 pub not_before: Option<GeneralizedTime>, 182 183 #[asn1(context_specific = "1", tag_mode = "IMPLICIT", optional = "true")] 184 pub not_after: Option<GeneralizedTime>, 185 } 186 187 impl AssociatedOid for PrivateKeyUsagePeriod { 188 const OID: ObjectIdentifier = ID_CE_PRIVATE_KEY_USAGE_PERIOD; 189 } 190 191 impl_extension!(PrivateKeyUsagePeriod, critical = false); 192 193 #[cfg(test)] 194 mod tests { 195 use super::*; 196 197 #[test] digital_signature_contains_digital_signature()198 fn digital_signature_contains_digital_signature() { 199 let key_usage = KeyUsage(KeyUsages::DigitalSignature.into()); 200 assert!(key_usage.digital_signature()); 201 } 202 203 #[test] all_contains_digital_signature()204 fn all_contains_digital_signature() { 205 let key_usage = KeyUsage(FlagSet::full()); 206 assert!(key_usage.digital_signature()); 207 } 208 209 #[test] key_encipherment_not_contains_digital_signature()210 fn key_encipherment_not_contains_digital_signature() { 211 let key_usage = KeyUsage(KeyUsages::KeyEncipherment.into()); 212 assert!(!key_usage.digital_signature()); 213 } 214 215 #[test] empty_not_contains_digital_signature()216 fn empty_not_contains_digital_signature() { 217 let key_usage = KeyUsage(None.into()); 218 assert!(!key_usage.digital_signature()); 219 } 220 } 221