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! {
#[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,
}
}
#[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 {
pub fn digital_signature(&self) -> bool {
self.0.contains(KeyUsages::DigitalSignature)
}
pub fn non_repudiation(&self) -> bool {
self.0.contains(KeyUsages::NonRepudiation)
}
pub fn key_encipherment(&self) -> bool {
self.0.contains(KeyUsages::KeyEncipherment)
}
pub fn data_encipherment(&self) -> bool {
self.0.contains(KeyUsages::DataEncipherment)
}
pub fn key_agreement(&self) -> bool {
self.0.contains(KeyUsages::KeyAgreement)
}
pub fn key_cert_sign(&self) -> bool {
self.0.contains(KeyUsages::KeyCertSign)
}
pub fn crl_sign(&self) -> bool {
self.0.contains(KeyUsages::CRLSign)
}
pub fn encipher_only(&self) -> bool {
self.0.contains(KeyUsages::EncipherOnly)
}
pub fn decipher_only(&self) -> bool {
self.0.contains(KeyUsages::DecipherOnly)
}
}
#[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 {
!self.0.iter().any(|el| *el == ANY_EXTENDED_KEY_USAGE)
}
}
#[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());
}
}