use crate::OcspGeneralizedTime;
use const_oid::AssociatedOid;
use core::option::Option;
use der::{asn1::Null, Choice, Decode, Sequence};
use x509_cert::{crl::RevokedCert, ext::pkix::CrlReason};
#[derive(Copy, Clone, Debug, Eq, PartialEq, Choice)]
#[allow(missing_docs)]
pub enum CertStatus {
#[asn1(context_specific = "0", tag_mode = "IMPLICIT")]
Good(Null),
#[asn1(context_specific = "1", tag_mode = "IMPLICIT", constructed = "true")]
Revoked(RevokedInfo),
#[asn1(context_specific = "2", tag_mode = "IMPLICIT")]
Unknown(UnknownInfo),
}
impl CertStatus {
pub fn good() -> Self {
Self::Good(Null)
}
pub fn revoked(info: impl Into<RevokedInfo>) -> Self {
Self::Revoked(info.into())
}
pub fn unknown() -> Self {
Self::Unknown(Null)
}
}
#[derive(Copy, Clone, Debug, Eq, PartialEq, Sequence)]
#[allow(missing_docs)]
pub struct RevokedInfo {
pub revocation_time: OcspGeneralizedTime,
#[asn1(context_specific = "0", optional = "true", tag_mode = "EXPLICIT")]
pub revocation_reason: Option<CrlReason>,
}
pub type UnknownInfo = Null;
impl From<&RevokedInfo> for RevokedInfo {
fn from(info: &RevokedInfo) -> Self {
*info
}
}
impl From<&RevokedCert> for RevokedInfo {
fn from(rc: &RevokedCert) -> Self {
Self {
revocation_time: rc.revocation_date.into(),
revocation_reason: match &rc.crl_entry_extensions {
Some(extns) => {
let mut filter = extns.iter().filter(|extn| extn.extn_id == CrlReason::OID);
match filter.next() {
Some(extn) => CrlReason::from_der(extn.extn_value.as_bytes()).ok(),
None => None,
}
}
None => None,
},
}
}
}
impl From<RevokedCert> for RevokedInfo {
fn from(rc: RevokedCert) -> Self {
Self::from(&rc)
}
}