Skip to content

Commit

Permalink
x509-cert: accept rfc5280-invalid certificates as trustanchor (#1403)
Browse files Browse the repository at this point in the history
This commit brings the profiles introduced in #987 to
`TrustAnchorChoice` and `Crl`.

This is intended for the support of invalid certificates in
https://github.com/carl-wallace/rust-pki/tree/main/certval
  • Loading branch information
baloo authored May 20, 2024
1 parent 9ffa83b commit 31e3b0c
Show file tree
Hide file tree
Showing 4 changed files with 33 additions and 24 deletions.
23 changes: 14 additions & 9 deletions x509-cert/src/anchor.rs
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
//! Trust anchor-related structures as defined in RFC 5914
use crate::certificate::{CertificateInner, Profile, Rfc5280, TbsCertificateInner};
use crate::ext::pkix::{certpolicy::CertificatePolicies, NameConstraints};
use crate::{ext::Extensions, name::Name};
use crate::{Certificate, TbsCertificate};

use alloc::string::String;
use der::asn1::OctetString;
Expand Down Expand Up @@ -37,7 +37,7 @@ pub enum Version {
/// ```
#[derive(Clone, Debug, PartialEq, Eq, Sequence)]
#[allow(missing_docs)]
pub struct TrustAnchorInfo {
pub struct TrustAnchorInfo<P: Profile + 'static = Rfc5280> {
#[asn1(default = "Default::default")]
pub version: Version,

Expand All @@ -49,7 +49,7 @@ pub struct TrustAnchorInfo {
pub ta_title: Option<String>,

#[asn1(optional = "true")]
pub cert_path: Option<CertPathControls>,
pub cert_path: Option<CertPathControls<P>>,

#[asn1(context_specific = "1", tag_mode = "EXPLICIT", optional = "true")]
pub extensions: Option<Extensions>,
Expand All @@ -70,11 +70,11 @@ pub struct TrustAnchorInfo {
/// ```
#[derive(Clone, Debug, Eq, PartialEq, Sequence)]
#[allow(missing_docs)]
pub struct CertPathControls {
pub struct CertPathControls<P: Profile + 'static = Rfc5280> {
pub ta_name: Name,

#[asn1(context_specific = "0", tag_mode = "IMPLICIT", optional = "true")]
pub certificate: Option<Certificate>,
pub certificate: Option<CertificateInner<P>>,

#[asn1(context_specific = "1", tag_mode = "IMPLICIT", optional = "true")]
pub policy_set: Option<CertificatePolicies>,
Expand Down Expand Up @@ -114,22 +114,27 @@ flags! {
/// [RFC 5280 Section 4.2.1.13]: https://datatracker.ietf.org/doc/html/rfc5280#section-4.2.1.13
pub type CertPolicyFlags = FlagSet<CertPolicies>;

/// TrustAnchorInfo allows for the representation of a single trust anchor.
/// Defined in [RFC 5914 Section 3].
///
/// ```text
/// TrustAnchorChoice ::= CHOICE {
/// certificate Certificate,
/// tbsCert [1] EXPLICIT TBSCertificate,
/// taInfo [2] EXPLICIT TrustAnchorInfo
/// }
/// ```
///
/// [RFC 5914 Section 3]: https://www.rfc-editor.org/rfc/rfc5914#section-3
#[derive(Clone, Debug, PartialEq, Eq, Choice)]
#[allow(clippy::large_enum_variant)]
#[allow(missing_docs)]
pub enum TrustAnchorChoice {
Certificate(Certificate),
pub enum TrustAnchorChoice<P: Profile + 'static = Rfc5280> {
Certificate(CertificateInner<P>),

#[asn1(context_specific = "1", tag_mode = "EXPLICIT", constructed = "true")]
TbsCertificate(TbsCertificate),
TbsCertificate(TbsCertificateInner<P>),

#[asn1(context_specific = "2", tag_mode = "EXPLICIT", constructed = "true")]
TaInfo(TrustAnchorInfo),
TaInfo(TrustAnchorInfo<P>),
}
13 changes: 7 additions & 6 deletions x509-cert/src/crl.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
//! Certificate Revocation List types
use crate::certificate::{Profile, Rfc5280};
use crate::ext::Extensions;
use crate::name::Name;
use crate::serial_number::SerialNumber;
Expand All @@ -25,8 +26,8 @@ use spki::AlgorithmIdentifierOwned;
/// [RFC 5280 Section 5.1]: https://datatracker.ietf.org/doc/html/rfc5280#section-5.1
#[derive(Clone, Debug, Eq, PartialEq, Sequence, ValueOrd)]
#[allow(missing_docs)]
pub struct CertificateList {
pub tbs_cert_list: TbsCertList,
pub struct CertificateList<P: Profile + 'static = Rfc5280> {
pub tbs_cert_list: TbsCertList<P>,
pub signature_algorithm: AlgorithmIdentifierOwned,
pub signature: BitString,
}
Expand All @@ -47,8 +48,8 @@ pub struct CertificateList {
/// [RFC 5280 Section 5.1]: https://datatracker.ietf.org/doc/html/rfc5280#section-5.1
#[derive(Clone, Debug, Eq, PartialEq, Sequence, ValueOrd)]
#[allow(missing_docs)]
pub struct RevokedCert {
pub serial_number: SerialNumber,
pub struct RevokedCert<P: Profile + 'static = Rfc5280> {
pub serial_number: SerialNumber<P>,
pub revocation_date: Time,
pub crl_entry_extensions: Option<Extensions>,
}
Expand All @@ -74,13 +75,13 @@ pub struct RevokedCert {
/// [RFC 5280 Section 5.1]: https://datatracker.ietf.org/doc/html/rfc5280#section-5.1
#[derive(Clone, Debug, Eq, PartialEq, Sequence, ValueOrd)]
#[allow(missing_docs)]
pub struct TbsCertList {
pub struct TbsCertList<P: Profile + 'static = Rfc5280> {
pub version: Version,
pub signature: AlgorithmIdentifierOwned,
pub issuer: Name,
pub this_update: Time,
pub next_update: Option<Time>,
pub revoked_certificates: Option<Vec<RevokedCert>>,
pub revoked_certificates: Option<Vec<RevokedCert<P>>>,

#[asn1(context_specific = "0", tag_mode = "EXPLICIT", optional = "true")]
pub crl_extensions: Option<Extensions>,
Expand Down
6 changes: 3 additions & 3 deletions x509-cert/tests/crl.rs
Original file line number Diff line number Diff line change
@@ -1,17 +1,17 @@
use der::Decode;
use x509_cert::crl::CertificateList;
use x509_cert::{certificate::Rfc5280, 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();
let crl = CertificateList::<Rfc5280>::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();
let crl = CertificateList::<Rfc5280>::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());
}
15 changes: 9 additions & 6 deletions x509-cert/tests/trust_anchor_format.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,11 @@ use der::{
Decode, Encode, SliceReader,
};
use hex_literal::hex;
use x509_cert::anchor::{CertPolicies, TrustAnchorChoice};
use x509_cert::ext::pkix::name::GeneralName;
use x509_cert::{
anchor::{CertPolicies, TrustAnchorChoice},
certificate::Rfc5280,
ext::pkix::name::GeneralName,
};

#[test]
fn decode_ta1() {
Expand All @@ -14,7 +17,7 @@ fn decode_ta1() {
let der_encoded_cert = include_bytes!("examples/eca.der");

let mut decoder = SliceReader::new(der_encoded_tac).unwrap();
let tac = TrustAnchorChoice::decode(&mut decoder).unwrap();
let tac = TrustAnchorChoice::<Rfc5280>::decode(&mut decoder).unwrap();
let reencoded_tac = tac.to_der().unwrap();
println!("Original : {:02X?}", der_encoded_cert);
println!("Reencoded: {:02X?}", reencoded_tac);
Expand Down Expand Up @@ -143,7 +146,7 @@ fn decode_ta2() {
let der_encoded_cert = include_bytes!("examples/entrust.der");

let mut decoder = SliceReader::new(der_encoded_tac).unwrap();
let tac = TrustAnchorChoice::decode(&mut decoder).unwrap();
let tac = TrustAnchorChoice::<Rfc5280>::decode(&mut decoder).unwrap();
let reencoded_tac = tac.to_der().unwrap();
println!("Original : {:02X?}", der_encoded_cert);
println!("Reencoded: {:02X?}", reencoded_tac);
Expand Down Expand Up @@ -263,7 +266,7 @@ fn decode_ta3() {
let der_encoded_cert = include_bytes!("examples/exostar.der");

let mut decoder = SliceReader::new(der_encoded_tac).unwrap();
let tac = TrustAnchorChoice::decode(&mut decoder).unwrap();
let tac = TrustAnchorChoice::<Rfc5280>::decode(&mut decoder).unwrap();
let reencoded_tac = tac.to_der().unwrap();
println!("Original : {:02X?}", der_encoded_cert);
println!("Reencoded: {:02X?}", reencoded_tac);
Expand Down Expand Up @@ -390,7 +393,7 @@ fn decode_ta4() {
let der_encoded_cert = include_bytes!("examples/raytheon.der");

let mut decoder = SliceReader::new(der_encoded_tac).unwrap();
let tac = TrustAnchorChoice::decode(&mut decoder).unwrap();
let tac = TrustAnchorChoice::<Rfc5280>::decode(&mut decoder).unwrap();
let reencoded_tac = tac.to_der().unwrap();
println!("Original : {:02X?}", der_encoded_cert);
println!("Reencoded: {:02X?}", reencoded_tac);
Expand Down

0 comments on commit 31e3b0c

Please sign in to comment.