Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
86 changes: 86 additions & 0 deletions x509/src/crl.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
//! Certificate Revocation List types

use crate::ext::Extensions;
use crate::name::Name;
use crate::time::Time;
use crate::Version;

use alloc::vec::Vec;

use der::asn1::{BitString, UIntBytes};
use der::Sequence;
use spki::AlgorithmIdentifier;

/// `CertificateList` as defined in [RFC 5280 Section 5.1].
///
///```text
/// CertificateList ::= SEQUENCE {
/// tbsCertList TBSCertList,
/// signatureAlgorithm AlgorithmIdentifier,
/// signatureValue BIT STRING
/// }
/// ```
///
/// [RFC 5280 Section 5.1]: https://datatracker.ietf.org/doc/html/rfc5280#section-5.1
#[derive(Clone, Debug, Eq, PartialEq, Sequence)]
#[allow(missing_docs)]
pub struct CertificateList<'a> {
pub tbs_cert_list: TbsCertList<'a>,
pub signature_algorithm: AlgorithmIdentifier<'a>,
pub signature: BitString<'a>,
}

/// Implicit intermediate structure from the ASN.1 definition of `TBSCertList`.
///
/// This type is used for the `revoked_certificates` field of `TbsCertList`.
/// See [RFC 5280 Section 5.1].
///
///```text
/// RevokedCert ::= SEQUENCE {
/// userCertificate CertificateSerialNumber,
/// revocationDate Time,
/// crlEntryExtensions Extensions OPTIONAL
/// }
/// ```
///
/// [RFC 5280 Section 5.1]: https://datatracker.ietf.org/doc/html/rfc5280#section-5.1
#[derive(Clone, Debug, Eq, PartialEq, Sequence)]
#[allow(missing_docs)]
pub struct RevokedCert<'a> {
pub serial_number: UIntBytes<'a>,
pub revocation_date: Time,
pub crl_entry_extensions: Option<Extensions<'a>>,
}

/// `TbsCertList` as defined in [RFC 5280 Section 5.1].
///
/// ```text
/// TBSCertList ::= SEQUENCE {
/// version Version OPTIONAL, -- if present, MUST be v2
/// signature AlgorithmIdentifier,
/// issuer Name,
/// thisUpdate Time,
/// nextUpdate Time OPTIONAL,
/// revokedCertificates SEQUENCE OF SEQUENCE {
/// userCertificate CertificateSerialNumber,
/// revocationDate Time,
/// crlEntryExtensions Extensions OPTIONAL -- if present, version MUST be v2
/// } OPTIONAL,
/// crlExtensions [0] EXPLICIT Extensions OPTIONAL -- if present, version MUST be v2
/// }
/// ```
///
/// [RFC 5280 Section 5.1]: https://datatracker.ietf.org/doc/html/rfc5280#section-5.1
#[derive(Clone, Debug, Eq, PartialEq, Sequence)]
#[allow(missing_docs)]
pub struct TbsCertList<'a> {
pub version: Version,
pub signature: AlgorithmIdentifier<'a>,
pub issuer: Name<'a>,
pub this_update: Time,
pub next_update: Option<Time>,
pub revoked_certificates: Option<Vec<RevokedCert<'a>>>,

#[asn1(context_specific = "0", tag_mode = "EXPLICIT", optional = "true")]
pub crl_extensions: Option<Extensions<'a>>,
}
1 change: 1 addition & 0 deletions x509/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ extern crate std;

pub mod anchor;
pub mod attr;
pub mod crl;
pub mod ext;
pub mod name;
pub mod request;
Expand Down
17 changes: 17 additions & 0 deletions x509/tests/crl.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
use der::Decodable;
use x509::crl::CertificateList;

#[test]
fn decode_crl() {
// vanilla CRL from PKITS
let der_encoded_cert = include_bytes!("examples/GoodCACRL.crl");
let crl = CertificateList::from_der(der_encoded_cert).unwrap();
assert_eq!(2, crl.tbs_cert_list.crl_extensions.unwrap().len());
assert_eq!(2, crl.tbs_cert_list.revoked_certificates.unwrap().len());

// CRL with an entry with no entry extensions
let der_encoded_cert = include_bytes!("examples/tscpbcasha256.crl");
let crl = CertificateList::from_der(der_encoded_cert).unwrap();
assert_eq!(2, crl.tbs_cert_list.crl_extensions.unwrap().len());
assert_eq!(4, crl.tbs_cert_list.revoked_certificates.unwrap().len());
}
Binary file added x509/tests/examples/tscpbcasha256.crl
Binary file not shown.