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