diff --git a/der/src/asn1.rs b/der/src/asn1.rs index 60a7b2dec..b727aaa93 100644 --- a/der/src/asn1.rs +++ b/der/src/asn1.rs @@ -36,7 +36,7 @@ mod videotex_string; pub use self::{ any::AnyRef, application::{Application, ApplicationRef}, - bit_string::{BitStringIter, BitStringRef}, + bit_string::{AsBitStringRef, BitStringIter, BitStringRef}, choice::Choice, context_specific::{ContextSpecific, ContextSpecificRef}, general_string::GeneralStringRef, diff --git a/der/src/asn1/bit_string.rs b/der/src/asn1/bit_string.rs index 1104d2bf4..26b2bcd2b 100644 --- a/der/src/asn1/bit_string.rs +++ b/der/src/asn1/bit_string.rs @@ -241,6 +241,17 @@ impl<'a> arbitrary::Arbitrary<'a> for BitStringRef<'a> { arbitrary::size_hint::and(u8::size_hint(depth), BytesRef::size_hint(depth)) } } +/// How write it better? Like `AsRef>` +pub trait AsBitStringRef<'a> { + /// Implemented on BitString and BitStringRef + fn as_bitstring_ref(&'a self) -> BitStringRef<'a>; +} + +impl<'a> AsBitStringRef<'a> for BitStringRef<'a> { + fn as_bitstring_ref(&'a self) -> BitStringRef<'a> { + self.clone() + } +} #[cfg(feature = "alloc")] pub use self::allocating::BitString; @@ -447,6 +458,12 @@ mod allocating { self.into() } } + + impl<'a> AsBitStringRef<'a> for BitString { + fn as_bitstring_ref(&'a self) -> BitStringRef<'a> { + self.into() + } + } } /// Iterator over the bits of a [`BitString`]. diff --git a/x509-cert/src/anchor.rs b/x509-cert/src/anchor.rs index 9b2d60704..f6dd98e2f 100644 --- a/x509-cert/src/anchor.rs +++ b/x509-cert/src/anchor.rs @@ -1,6 +1,6 @@ //! Trust anchor-related structures as defined in RFC 5914 -use crate::certificate::{CertificateInner, Profile, Rfc5280, TbsCertificateInner}; +use crate::certificate::{AllocDerMemory, CertificateInner, Profile, Rfc5280, TbsCertificateInner}; use crate::ext::pkix::{NameConstraints, certpolicy::CertificatePolicies}; use crate::{ext::Extensions, name::Name}; @@ -76,7 +76,7 @@ pub struct CertPathControls { pub ta_name: Name, #[asn1(context_specific = "0", tag_mode = "IMPLICIT", optional = "true")] - pub certificate: Option>, + pub certificate: Option>, #[asn1(context_specific = "1", tag_mode = "IMPLICIT", optional = "true")] pub policy_set: Option, @@ -91,6 +91,45 @@ pub struct CertPathControls { pub path_len_constraint: Option, } +impl<'__der_lifetime, P: Profile> CertPathControls

{ + fn decode_value_inner2>( + reader: &mut R, + ) -> ::core::result::Result { + use ::der::{Decode as _, DecodeValue as _, Reader as _}; + let ta_name = reader.decode()?; + use der::Decode; + + let certificate: CertificateInner<'__der_lifetime, AllocDerMemory, P> = + Decode::decode(reader)?; + let certificate = Some(certificate); + // let certificate = ::der::asn1::ContextSpecific::decode_implicit( + // reader, + // ::der::TagNumber(0u32), + // )? + // .map(|cs| cs.value); + let policy_set = + ::der::asn1::ContextSpecific::decode_implicit(reader, ::der::TagNumber(1u32))? + .map(|cs| cs.value); + let policy_flags = + ::der::asn1::ContextSpecific::decode_implicit(reader, ::der::TagNumber(2u32))? + .map(|cs| cs.value); + let name_constr = + ::der::asn1::ContextSpecific::decode_implicit(reader, ::der::TagNumber(3u32))? + .map(|cs| cs.value); + let path_len_constraint = + ::der::asn1::ContextSpecific::decode_implicit(reader, ::der::TagNumber(4u32))? + .map(|cs| cs.value); + Ok(Self { + ta_name, + certificate, + policy_set, + policy_flags, + name_constr, + path_len_constraint, + }) + } +} + flags! { /// Certificate policies as defined in [RFC 5280 Section 4.2.1.13]. /// diff --git a/x509-cert/src/certificate.rs b/x509-cert/src/certificate.rs index 49e1acb2f..794ca5bc7 100644 --- a/x509-cert/src/certificate.rs +++ b/x509-cert/src/certificate.rs @@ -5,7 +5,9 @@ use crate::{ext, name::Name, serial_number::SerialNumber, time::Validity}; use alloc::vec::Vec; use const_oid::AssociatedOid; use core::{cmp::Ordering, fmt::Debug}; +use der::asn1::{AsBitStringRef, BitStringRef}; use der::{Decode, Enumerated, ErrorKind, Sequence, Tag, ValueOrd, asn1::BitString}; +use der::{DecodeValue, DerOrd, EncodeValue, FixedTag}; #[cfg(feature = "pem")] use der::{ @@ -111,8 +113,24 @@ impl Default for Version { } /// X.509 `TbsCertificate` as defined in [RFC 5280 Section 4.1] -pub type TbsCertificate = TbsCertificateInner; - +pub type TbsCertificate = TbsCertificateInner<'static, Rfc5280>; + +pub trait DerMemory { + type BITSTRING<'m>: FixedTag + + DecodeValue<'m, Error = der::Error> + + EncodeValue + + DerOrd + + Clone + + Debug + + Eq + + PartialEq + + AsBitStringRef<'m>; +} +#[derive(Clone, Debug, Eq, PartialEq, Default)] +pub struct AllocDerMemory; +impl DerMemory for AllocDerMemory { + type BITSTRING<'a> = BitString; +} /// X.509 `TbsCertificate` as defined in [RFC 5280 Section 4.1] /// /// ASN.1 structure containing the names of the subject and issuer, a public @@ -141,7 +159,7 @@ pub type TbsCertificate = TbsCertificateInner; #[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))] #[derive(Clone, Debug, Eq, PartialEq, Sequence, ValueOrd)] #[allow(missing_docs)] -pub struct TbsCertificateInner { +pub struct TbsCertificateInner<'m, MEM: DerMemory + 'static, P: Profile = Rfc5280> { /// The certificate version. /// /// Note that this value defaults to Version 1 per the RFC. However, @@ -162,13 +180,13 @@ pub struct TbsCertificateInner { pub(crate) issuer_unique_id: Option, #[asn1(context_specific = "2", tag_mode = "IMPLICIT", optional = "true")] - pub(crate) subject_unique_id: Option, + pub(crate) subject_unique_id: Option>, #[asn1(context_specific = "3", tag_mode = "EXPLICIT", optional = "true")] pub(crate) extensions: Option, } -impl TbsCertificateInner

{ +impl<'m, MEM: DerMemory, P: Profile> TbsCertificateInner<'m, MEM, P> { /// [`Version`] of this certificate (v1/v2/v3). pub fn version(&self) -> Version { self.version @@ -225,8 +243,10 @@ impl TbsCertificateInner

{ /// issuing CA. /// /// (NOTE: added in X.509 v2) - pub fn subject_unique_id(&self) -> &Option { - &self.subject_unique_id + pub fn subject_unique_id(&'m self) -> Option> { + self.subject_unique_id + .as_ref() + .map(|id| id.as_bitstring_ref()) } /// Certificate extensions. @@ -318,7 +338,7 @@ impl TbsCertificateInner

{ /// X.509 certificates are defined in [RFC 5280 Section 4.1]. /// /// [RFC 5280 Section 4.1]: https://datatracker.ietf.org/doc/html/rfc5280#section-4.1 -pub type Certificate = CertificateInner; +pub type Certificate = CertificateInner<'static, Rfc5280>; /// X.509 certificates are defined in [RFC 5280 Section 4.1]. /// @@ -334,15 +354,15 @@ pub type Certificate = CertificateInner; #[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))] #[derive(Clone, Debug, Eq, PartialEq, Sequence, ValueOrd)] #[allow(missing_docs)] -pub struct CertificateInner { - pub(crate) tbs_certificate: TbsCertificateInner

, +pub struct CertificateInner<'m, MEM: DerMemory + 'static, P: Profile = Rfc5280> { + pub(crate) tbs_certificate: TbsCertificateInner<'m, MEM, P>, pub(crate) signature_algorithm: AlgorithmIdentifier, pub(crate) signature: BitString, } -impl CertificateInner

{ +impl<'m, MEM: DerMemory, P: Profile> CertificateInner<'m, MEM, P> { /// Get the [`TbsCertificateInner`] (i.e. the part the signature is computed over). - pub fn tbs_certificate(&self) -> &TbsCertificateInner

{ + pub fn tbs_certificate(&self) -> &TbsCertificateInner<'m, MEM, P> { &self.tbs_certificate } @@ -359,7 +379,7 @@ impl CertificateInner

{ } #[cfg(feature = "pem")] -impl PemLabel for CertificateInner

{ +impl<'m, MEM: DerMemory, P: Profile> PemLabel for CertificateInner<'m, MEM, P> { const PEM_LABEL: &'static str = "CERTIFICATE"; } @@ -377,7 +397,7 @@ impl PemLabel for CertificateInner

{ pub type PkiPath = Vec; #[cfg(feature = "pem")] -impl CertificateInner

{ +impl CertificateInner<'static, AllocDerMemory, P> { /// Parse a chain of pem-encoded certificates from a slice. /// /// Returns the list of certificates.