diff --git a/der/src/asn1/any.rs b/der/src/asn1/any.rs index 583fe0304..dc3fd50cc 100644 --- a/der/src/asn1/any.rs +++ b/der/src/asn1/any.rs @@ -311,9 +311,9 @@ mod allocating { } } - impl OwnedToRef for Any { - type Borrowed<'a> = AnyRef<'a>; - fn owned_to_ref(&self) -> Self::Borrowed<'_> { + impl<'a> OwnedToRef<'a> for Any { + type Borrowed = AnyRef<'a>; + fn owned_to_ref(&'a self) -> Self::Borrowed { self.into() } } diff --git a/der/src/asn1/bit_string.rs b/der/src/asn1/bit_string.rs index 1104d2bf4..674fa9f91 100644 --- a/der/src/asn1/bit_string.rs +++ b/der/src/asn1/bit_string.rs @@ -441,10 +441,11 @@ mod allocating { } } - impl OwnedToRef for BitString { - type Borrowed<'a> = BitStringRef<'a>; - fn owned_to_ref(&self) -> Self::Borrowed<'_> { - self.into() + impl<'a> OwnedToRef<'a> for BitString { + type Borrowed = BitStringRef<'a>; + fn owned_to_ref(&'a self) -> Self::Borrowed { + // Ensured to parse successfully in constructor + BitStringRef::new(self.unused_bits, &self.inner).expect("invalid BIT STRING") } } } diff --git a/der/src/asn1/ia5_string.rs b/der/src/asn1/ia5_string.rs index b42cbb40d..aa2de615a 100644 --- a/der/src/asn1/ia5_string.rs +++ b/der/src/asn1/ia5_string.rs @@ -164,9 +164,9 @@ mod allocation { } } - impl OwnedToRef for Ia5String { - type Borrowed<'a> = Ia5StringRef<'a>; - fn owned_to_ref(&self) -> Self::Borrowed<'_> { + impl<'a> OwnedToRef<'a> for Ia5String { + type Borrowed = Ia5StringRef<'a>; + fn owned_to_ref(&'a self) -> Self::Borrowed { Ia5StringRef { inner: self.inner.owned_to_ref(), } diff --git a/der/src/asn1/integer/int.rs b/der/src/asn1/integer/int.rs index 2203ba14e..3fd118699 100644 --- a/der/src/asn1/integer/int.rs +++ b/der/src/asn1/integer/int.rs @@ -294,9 +294,9 @@ mod allocating { } } - impl OwnedToRef for Int { - type Borrowed<'a> = IntRef<'a>; - fn owned_to_ref(&self) -> Self::Borrowed<'_> { + impl<'a> OwnedToRef<'a> for Int { + type Borrowed = IntRef<'a>; + fn owned_to_ref(&'a self) -> Self::Borrowed { let inner = self.inner.owned_to_ref(); IntRef { inner } diff --git a/der/src/asn1/integer/uint.rs b/der/src/asn1/integer/uint.rs index d4ff6f0d1..79b4f5340 100644 --- a/der/src/asn1/integer/uint.rs +++ b/der/src/asn1/integer/uint.rs @@ -265,9 +265,9 @@ mod allocating { } } - impl OwnedToRef for Uint { - type Borrowed<'a> = UintRef<'a>; - fn owned_to_ref(&self) -> Self::Borrowed<'_> { + impl<'a> OwnedToRef<'a> for Uint { + type Borrowed = UintRef<'a>; + fn owned_to_ref(&'a self) -> Self::Borrowed { let inner = self.inner.owned_to_ref(); UintRef { inner } diff --git a/der/src/asn1/octet_string.rs b/der/src/asn1/octet_string.rs index 8813407f1..5130baba2 100644 --- a/der/src/asn1/octet_string.rs +++ b/der/src/asn1/octet_string.rs @@ -2,7 +2,7 @@ use crate::{ BytesRef, Decode, DecodeValue, EncodeValue, Error, ErrorKind, FixedTag, Header, Length, Reader, - Tag, Writer, asn1::AnyRef, ord::OrdIsValueOrd, + Tag, Writer, asn1::AnyRef, ord::OrdIsValueOrd, referenced::RefToOwned, }; /// ASN.1 `OCTET STRING` type: borrowed form. @@ -254,9 +254,9 @@ mod allocating { } } - impl OwnedToRef for OctetString { - type Borrowed<'a> = OctetStringRef<'a>; - fn owned_to_ref(&self) -> Self::Borrowed<'_> { + impl<'a> OwnedToRef<'a> for OctetString { + type Borrowed = OctetStringRef<'a>; + fn owned_to_ref(&'a self) -> Self::Borrowed { self.into() } } diff --git a/der/src/asn1/printable_string.rs b/der/src/asn1/printable_string.rs index b271e809e..c2f16748e 100644 --- a/der/src/asn1/printable_string.rs +++ b/der/src/asn1/printable_string.rs @@ -219,9 +219,9 @@ mod allocation { } } - impl OwnedToRef for PrintableString { - type Borrowed<'a> = PrintableStringRef<'a>; - fn owned_to_ref(&self) -> Self::Borrowed<'_> { + impl<'a> OwnedToRef<'a> for PrintableString { + type Borrowed = PrintableStringRef<'a>; + fn owned_to_ref(&'a self) -> Self::Borrowed { PrintableStringRef { inner: self.inner.owned_to_ref(), } diff --git a/der/src/asn1/teletex_string.rs b/der/src/asn1/teletex_string.rs index 415cea7a2..618a4b26d 100644 --- a/der/src/asn1/teletex_string.rs +++ b/der/src/asn1/teletex_string.rs @@ -181,9 +181,9 @@ mod allocation { } } - impl OwnedToRef for TeletexString { - type Borrowed<'a> = TeletexStringRef<'a>; - fn owned_to_ref(&self) -> Self::Borrowed<'_> { + impl<'a> OwnedToRef<'a> for TeletexString { + type Borrowed = TeletexStringRef<'a>; + fn owned_to_ref(&'a self) -> Self::Borrowed { TeletexStringRef { inner: self.inner.owned_to_ref(), } diff --git a/der/src/bytes_owned.rs b/der/src/bytes_owned.rs index 330ac8bbd..fb190bcde 100644 --- a/der/src/bytes_owned.rs +++ b/der/src/bytes_owned.rs @@ -103,9 +103,9 @@ impl From> for BytesOwned { } } -impl OwnedToRef for BytesOwned { - type Borrowed<'a> = BytesRef<'a>; - fn owned_to_ref(&self) -> Self::Borrowed<'_> { +impl<'a> OwnedToRef<'a> for BytesOwned { + type Borrowed = BytesRef<'a>; + fn owned_to_ref(&'a self) -> Self::Borrowed { BytesRef { length: self.length, inner: self.inner.as_ref(), diff --git a/der/src/referenced.rs b/der/src/referenced.rs index 22060b93b..ef5c19ec1 100644 --- a/der/src/referenced.rs +++ b/der/src/referenced.rs @@ -1,5 +1,7 @@ //! A module for working with referenced data. +use crate::FixedTag; + /// A trait for borrowing data from an owned struct /// /// This converts an object owning the data to one that will borrowing the content. @@ -8,14 +10,14 @@ /// This is similar to [`alloc::borrow::Borrow`] or [`core::convert::AsRef`] but this returns /// an owned structure that references directly the backing slices instead of borrowing /// the whole structure. -pub trait OwnedToRef { +pub trait OwnedToRef<'a> { /// The resulting type referencing back to Self - type Borrowed<'a> + type Borrowed: 'a where Self: 'a; /// Creates a new object referencing back to the self for storage - fn owned_to_ref(&self) -> Self::Borrowed<'_>; + fn owned_to_ref(&'a self) -> Self::Borrowed; } /// A trait for cloning a referenced structure and getting owned objects @@ -26,7 +28,7 @@ pub trait OwnedToRef { /// own the content. pub trait RefToOwned<'a> { /// The resulting type after obtaining ownership. - type Owned: OwnedToRef = Self> + type Owned: OwnedToRef<'a, Borrowed = Self> where Self: 'a; @@ -34,16 +36,13 @@ pub trait RefToOwned<'a> { fn ref_to_owned(&self) -> Self::Owned; } -impl OwnedToRef for Option +impl<'a, T> OwnedToRef<'a> for Option where - T: OwnedToRef, + T: OwnedToRef<'a> + 'a, { - type Borrowed<'a> - = Option> - where - T: 'a; + type Borrowed = Option; - fn owned_to_ref(&self) -> Self::Borrowed<'_> { + fn owned_to_ref(&'a self) -> Self::Borrowed { self.as_ref().map(|o| o.owned_to_ref()) } } @@ -51,7 +50,7 @@ where impl<'a, T> RefToOwned<'a> for Option where T: RefToOwned<'a> + 'a, - T::Owned: OwnedToRef, + T::Owned: OwnedToRef<'a>, { type Owned = Option; fn ref_to_owned(&self) -> Self::Owned { @@ -59,6 +58,83 @@ where } } +/// der crate version of `Cow` +pub enum DerCow<'a, B> +where + B: RefToOwned<'a> + ?Sized, +{ + /// referenced, for example `OctetStringRef` + Borrowed(&'a B), + /// allocated, for example `OctetString` + Owned(>::Owned), +} + +impl<'a, B> core::fmt::Debug for DerCow<'a, B> +where + B: RefToOwned<'a> + ?Sized + core::fmt::Debug, + >::Owned: core::fmt::Debug, +{ + fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { + match self { + Self::Borrowed(arg0) => f.debug_tuple("Borrowed").field(arg0).finish(), + Self::Owned(arg0) => f.debug_tuple("Owned").field(arg0).finish(), + } + } +} + +impl<'a, B> Clone for DerCow<'a, B> +where + B: RefToOwned<'a> + ?Sized, + >::Owned: Clone, +{ + fn clone(&self) -> Self { + match self { + Self::Borrowed(arg0) => Self::Borrowed(arg0), + Self::Owned(arg0) => Self::Owned(arg0.clone()), + } + } +} + +impl<'a, B> FixedTag for DerCow<'a, B> +where + B: RefToOwned<'a> + ?Sized + FixedTag, +{ + const TAG: crate::Tag = B::TAG; +} + +impl<'a, B> PartialEq for DerCow<'a, B> +where + B: RefToOwned<'a> + Sized + PartialEq, + >::Owned: PartialEq, +{ + fn eq(&self, other: &Self) -> bool { + match (self, other) { + (Self::Borrowed(l0), Self::Borrowed(r0)) => l0 == r0, + (Self::Owned(l0), Self::Owned(r0)) => l0 == r0, + (Self::Owned(l0), Self::Borrowed(r0)) => { + let l1 = l0.owned_to_ref(); + *r0 == &l1 + } + _ => false, + } + } +} + +// impl<'a, B> Deref for DerCow<'a, B> +// where +// B: RefToOwned<'a> + ?Sized, +// >::Owned: OwnedToRef, +// { +// type Target = B; + +// fn deref(&self) -> &B { +// match *self { +// Self::Borrowed(borrowed) => borrowed, +// Self::Owned(owned) => owned.owned_to_ref(), +// } +// } +// } + #[cfg(feature = "alloc")] mod allocating { use super::{OwnedToRef, RefToOwned}; @@ -72,10 +148,10 @@ mod allocating { } } - impl OwnedToRef for Box<[u8]> { - type Borrowed<'a> = &'a [u8]; + impl<'a> OwnedToRef<'a> for Box<[u8]> { + type Borrowed = &'a [u8]; - fn owned_to_ref(&self) -> Self::Borrowed<'_> { + fn owned_to_ref(&'a self) -> Self::Borrowed { self.as_ref() } } diff --git a/der/src/str_owned.rs b/der/src/str_owned.rs index be9adea72..73810a2c5 100644 --- a/der/src/str_owned.rs +++ b/der/src/str_owned.rs @@ -95,9 +95,9 @@ impl From> for StrOwned { } } -impl OwnedToRef for StrOwned { - type Borrowed<'a> = StrRef<'a>; - fn owned_to_ref(&self) -> Self::Borrowed<'_> { +impl<'a> OwnedToRef<'a> for StrOwned { + type Borrowed = StrRef<'a>; + fn owned_to_ref(&'a self) -> Self::Borrowed { StrRef { length: self.length, inner: self.inner.as_ref(), diff --git a/x509-cert/src/certificate.rs b/x509-cert/src/certificate.rs index 49e1acb2f..364ddd8ad 100644 --- a/x509-cert/src/certificate.rs +++ b/x509-cert/src/certificate.rs @@ -5,6 +5,8 @@ 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::BitStringRef; +use der::referenced::DerCow; use der::{Decode, Enumerated, ErrorKind, Sequence, Tag, ValueOrd, asn1::BitString}; #[cfg(feature = "pem")] @@ -168,6 +170,35 @@ pub struct TbsCertificateInner { pub(crate) extensions: Option, } +#[derive(Clone, Debug, Eq, PartialEq, Sequence, ValueOrd)] +#[allow(missing_docs)] +pub struct TbsCertificateInnerCow<'a, P: Profile = Rfc5280> { + /// The certificate version. + /// + /// Note that this value defaults to Version 1 per the RFC. However, + /// fields such as `issuer_unique_id`, `subject_unique_id` and `extensions` + /// require later versions. Care should be taken in order to ensure + /// standards compliance. + #[asn1(context_specific = "0", default = "Default::default")] + pub(crate) version: Version, + + pub(crate) serial_number: SerialNumber

, + pub(crate) signature: AlgorithmIdentifier, + pub(crate) issuer: Name, + pub(crate) validity: Validity

, + pub(crate) subject: Name, + pub(crate) subject_public_key_info: SubjectPublicKeyInfo, + + #[asn1(context_specific = "1", tag_mode = "IMPLICIT", optional = "true")] + pub(crate) issuer_unique_id: Option>>, + + #[asn1(context_specific = "2", tag_mode = "IMPLICIT", optional = "true")] + pub(crate) subject_unique_id: Option, + + #[asn1(context_specific = "3", tag_mode = "EXPLICIT", optional = "true")] + pub(crate) extensions: Option, +} + impl TbsCertificateInner

{ /// [`Version`] of this certificate (v1/v2/v3). pub fn version(&self) -> Version {