diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-05-18 02:49:42 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-05-18 02:49:42 +0000 |
commit | 837b550238aa671a591ccf282dddeab29cadb206 (patch) | |
tree | 914b6b8862bace72bd3245ca184d374b08d8a672 /vendor/der/src | |
parent | Adding debian version 1.70.0+dfsg2-1. (diff) | |
download | rustc-837b550238aa671a591ccf282dddeab29cadb206.tar.xz rustc-837b550238aa671a591ccf282dddeab29cadb206.zip |
Merging upstream version 1.71.1+dfsg1.
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'vendor/der/src')
48 files changed, 2645 insertions, 1308 deletions
diff --git a/vendor/der/src/asn1.rs b/vendor/der/src/asn1.rs index 34d692b67..dead9ae02 100644 --- a/vendor/der/src/asn1.rs +++ b/vendor/der/src/asn1.rs @@ -1,6 +1,9 @@ //! Module containing all of the various ASN.1 built-in types supported by //! this library. +#[macro_use] +mod internal_macros; + mod any; mod bit_string; mod boolean; @@ -32,7 +35,7 @@ pub use self::{ context_specific::{ContextSpecific, ContextSpecificRef}, generalized_time::GeneralizedTime, ia5_string::Ia5StringRef, - integer::bigint::UIntRef, + integer::{int::IntRef, uint::UintRef}, null::Null, octet_string::OctetStringRef, printable_string::PrintableStringRef, @@ -46,9 +49,16 @@ pub use self::{ }; #[cfg(feature = "alloc")] -#[cfg_attr(docsrs, doc(cfg(feature = "alloc")))] -pub use self::{any::Any, bit_string::BitString, octet_string::OctetString, set_of::SetOfVec}; +pub use self::{ + any::Any, + bit_string::BitString, + ia5_string::Ia5String, + integer::{int::Int, uint::Uint}, + octet_string::OctetString, + printable_string::PrintableString, + set_of::SetOfVec, + teletex_string::TeletexString, +}; #[cfg(feature = "oid")] -#[cfg_attr(docsrs, doc(cfg(feature = "oid")))] pub use const_oid::ObjectIdentifier; diff --git a/vendor/der/src/asn1/any.rs b/vendor/der/src/asn1/any.rs index cb65f2391..017a90908 100644 --- a/vendor/der/src/asn1/any.rs +++ b/vendor/der/src/asn1/any.rs @@ -1,16 +1,15 @@ //! ASN.1 `ANY` type. +#![cfg_attr(feature = "arbitrary", allow(clippy::integer_arithmetic))] + use crate::{ - asn1::*, ByteSlice, Choice, Decode, DecodeValue, DerOrd, EncodeValue, Error, ErrorKind, - FixedTag, Header, Length, Reader, Result, SliceReader, Tag, Tagged, ValueOrd, Writer, + BytesRef, Choice, Decode, DecodeValue, DerOrd, EncodeValue, Error, ErrorKind, Header, Length, + Reader, Result, SliceReader, Tag, Tagged, ValueOrd, Writer, }; use core::cmp::Ordering; #[cfg(feature = "alloc")] -use alloc::vec::Vec; - -#[cfg(feature = "oid")] -use crate::asn1::ObjectIdentifier; +use crate::SliceWriter; /// ASN.1 `ANY`: represents any explicitly tagged ASN.1 value. /// @@ -23,30 +22,31 @@ use crate::asn1::ObjectIdentifier; /// Nevertheless, this crate defines an `ANY` type as it remains a familiar /// and useful concept which is still extensively used in things like /// PKI-related RFCs. +#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))] #[derive(Copy, Clone, Debug, Eq, PartialEq, PartialOrd, Ord)] pub struct AnyRef<'a> { /// Tag representing the type of the encoded value. tag: Tag, /// Inner value encoded as bytes. - value: ByteSlice<'a>, + value: BytesRef<'a>, } impl<'a> AnyRef<'a> { /// [`AnyRef`] representation of the ASN.1 `NULL` type. pub const NULL: Self = Self { tag: Tag::Null, - value: ByteSlice::EMPTY, + value: BytesRef::EMPTY, }; /// Create a new [`AnyRef`] from the provided [`Tag`] and DER bytes. pub fn new(tag: Tag, bytes: &'a [u8]) -> Result<Self> { - let value = ByteSlice::new(bytes).map_err(|_| ErrorKind::Length { tag })?; + let value = BytesRef::new(bytes).map_err(|_| ErrorKind::Length { tag })?; Ok(Self { tag, value }) } - /// Infallible creation of an [`AnyRef`] from a [`ByteSlice`]. - pub(crate) fn from_tag_and_value(tag: Tag, value: ByteSlice<'a>) -> Self { + /// Infallible creation of an [`AnyRef`] from a [`BytesRef`]. + pub(crate) fn from_tag_and_value(tag: Tag, value: BytesRef<'a>) -> Self { Self { tag, value } } @@ -56,11 +56,14 @@ impl<'a> AnyRef<'a> { } /// Attempt to decode this [`AnyRef`] type into the inner value. - pub fn decode_into<T>(self) -> Result<T> + pub fn decode_as<T>(self) -> Result<T> where - T: DecodeValue<'a> + FixedTag, + T: Choice<'a> + DecodeValue<'a>, { - self.tag.assert_eq(T::TAG)?; + if !T::can_decode(self.tag) { + return Err(self.tag.unexpected_error(None)); + } + let header = Header { tag: self.tag, length: self.value.len(), @@ -76,68 +79,6 @@ impl<'a> AnyRef<'a> { self == Self::NULL } - /// Attempt to decode an ASN.1 `BIT STRING`. - pub fn bit_string(self) -> Result<BitStringRef<'a>> { - self.try_into() - } - - /// Attempt to decode an ASN.1 `CONTEXT-SPECIFIC` field. - pub fn context_specific<T>(self) -> Result<ContextSpecific<T>> - where - T: Decode<'a>, - { - self.try_into() - } - - /// Attempt to decode an ASN.1 `GeneralizedTime`. - pub fn generalized_time(self) -> Result<GeneralizedTime> { - self.try_into() - } - - /// Attempt to decode an ASN.1 `IA5String`. - pub fn ia5_string(self) -> Result<Ia5StringRef<'a>> { - self.try_into() - } - - /// Attempt to decode an ASN.1 `OCTET STRING`. - pub fn octet_string(self) -> Result<OctetStringRef<'a>> { - self.try_into() - } - - /// Attempt to decode an ASN.1 `OBJECT IDENTIFIER`. - #[cfg(feature = "oid")] - #[cfg_attr(docsrs, doc(cfg(feature = "oid")))] - pub fn oid(self) -> Result<ObjectIdentifier> { - self.try_into() - } - - /// Attempt to decode an ASN.1 `OPTIONAL` value. - pub fn optional<T>(self) -> Result<Option<T>> - where - T: Choice<'a> + TryFrom<Self, Error = Error>, - { - if T::can_decode(self.tag) { - T::try_from(self).map(Some) - } else { - Ok(None) - } - } - - /// Attempt to decode an ASN.1 `PrintableString`. - pub fn printable_string(self) -> Result<PrintableStringRef<'a>> { - self.try_into() - } - - /// Attempt to decode an ASN.1 `TeletexString`. - pub fn teletex_string(self) -> Result<TeletexStringRef<'a>> { - self.try_into() - } - - /// Attempt to decode an ASN.1 `VideotexString`. - pub fn videotex_string(self) -> Result<VideotexStringRef<'a>> { - self.try_into() - } - /// Attempt to decode this value an ASN.1 `SEQUENCE`, creating a new /// nested reader and calling the provided argument with it. pub fn sequence<F, T>(self, f: F) -> Result<T> @@ -149,16 +90,6 @@ impl<'a> AnyRef<'a> { let result = f(&mut reader)?; reader.finish(result) } - - /// Attempt to decode an ASN.1 `UTCTime`. - pub fn utc_time(self) -> Result<UtcTime> { - self.try_into() - } - - /// Attempt to decode an ASN.1 `UTF8String`. - pub fn utf8_string(self) -> Result<Utf8StringRef<'a>> { - self.try_into() - } } impl<'a> Choice<'a> for AnyRef<'a> { @@ -170,10 +101,15 @@ impl<'a> Choice<'a> for AnyRef<'a> { impl<'a> Decode<'a> for AnyRef<'a> { fn decode<R: Reader<'a>>(reader: &mut R) -> Result<AnyRef<'a>> { let header = Header::decode(reader)?; + Self::decode_value(reader, header) + } +} +impl<'a> DecodeValue<'a> for AnyRef<'a> { + fn decode_value<R: Reader<'a>>(reader: &mut R, header: Header) -> Result<Self> { Ok(Self { tag: header.tag, - value: ByteSlice::decode_value(reader, header)?, + value: BytesRef::decode_value(reader, header)?, }) } } @@ -183,7 +119,7 @@ impl EncodeValue for AnyRef<'_> { Ok(self.value.len()) } - fn encode_value(&self, writer: &mut dyn Writer) -> Result<()> { + fn encode_value(&self, writer: &mut impl Writer) -> Result<()> { writer.write(self.value()) } } @@ -200,8 +136,8 @@ impl ValueOrd for AnyRef<'_> { } } -impl<'a> From<AnyRef<'a>> for ByteSlice<'a> { - fn from(any: AnyRef<'a>) -> ByteSlice<'a> { +impl<'a> From<AnyRef<'a>> for BytesRef<'a> { + fn from(any: AnyRef<'a>) -> BytesRef<'a> { any.value } } @@ -214,71 +150,166 @@ impl<'a> TryFrom<&'a [u8]> for AnyRef<'a> { } } -/// ASN.1 `ANY`: represents any explicitly tagged ASN.1 value. -/// -/// This type provides the same functionality as [`AnyRef`] but owns the -/// backing data. #[cfg(feature = "alloc")] -#[cfg_attr(docsrs, doc(cfg(feature = "alloc")))] -#[derive(Clone, Debug, Eq, PartialEq, PartialOrd, Ord)] -pub struct Any { - /// Tag representing the type of the encoded value. - tag: Tag, - - /// Inner value encoded as bytes. - value: Vec<u8>, -} +pub use self::allocating::Any; #[cfg(feature = "alloc")] -impl Any { - /// Create a new [`Any`] from the provided [`Tag`] and DER bytes. - pub fn new(tag: Tag, bytes: impl Into<Vec<u8>>) -> Result<Self> { - let value = bytes.into(); +mod allocating { + use super::*; + use crate::{referenced::*, BytesOwned}; + use alloc::boxed::Box; + + /// ASN.1 `ANY`: represents any explicitly tagged ASN.1 value. + /// + /// This type provides the same functionality as [`AnyRef`] but owns the + /// backing data. + #[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))] + #[derive(Clone, Debug, Eq, PartialEq, PartialOrd, Ord)] + pub struct Any { + /// Tag representing the type of the encoded value. + tag: Tag, + + /// Inner value encoded as bytes. + value: BytesOwned, + } + + impl Any { + /// Create a new [`Any`] from the provided [`Tag`] and DER bytes. + pub fn new(tag: Tag, bytes: impl Into<Box<[u8]>>) -> Result<Self> { + let value = BytesOwned::new(bytes)?; + + // Ensure the tag and value are a valid `AnyRef`. + AnyRef::new(tag, value.as_slice())?; + Ok(Self { tag, value }) + } - // Ensure the tag and value are a valid `AnyRef`. - AnyRef::new(tag, &value)?; - Ok(Self { tag, value }) + /// Allow access to value + pub fn value(&self) -> &[u8] { + self.value.as_slice() + } + + /// Attempt to decode this [`Any`] type into the inner value. + pub fn decode_as<'a, T>(&'a self) -> Result<T> + where + T: Choice<'a> + DecodeValue<'a>, + { + AnyRef::from(self).decode_as() + } + + /// Encode the provided type as an [`Any`] value. + pub fn encode_from<T>(msg: &T) -> Result<Self> + where + T: Tagged + EncodeValue, + { + let encoded_len = usize::try_from(msg.value_len()?)?; + let mut buf = vec![0u8; encoded_len]; + let mut writer = SliceWriter::new(&mut buf); + msg.encode_value(&mut writer)?; + writer.finish()?; + Any::new(msg.tag(), buf) + } + + /// Attempt to decode this value an ASN.1 `SEQUENCE`, creating a new + /// nested reader and calling the provided argument with it. + pub fn sequence<'a, F, T>(&'a self, f: F) -> Result<T> + where + F: FnOnce(&mut SliceReader<'a>) -> Result<T>, + { + AnyRef::from(self).sequence(f) + } + + /// [`Any`] representation of the ASN.1 `NULL` type. + pub fn null() -> Self { + Self { + tag: Tag::Null, + value: BytesOwned::default(), + } + } } -} -#[cfg(feature = "alloc")] -impl Choice<'_> for Any { - fn can_decode(_: Tag) -> bool { - true + impl Choice<'_> for Any { + fn can_decode(_: Tag) -> bool { + true + } } -} -#[cfg(feature = "alloc")] -impl<'a> Decode<'a> for Any { - fn decode<R: Reader<'a>>(reader: &mut R) -> Result<Self> { - let header = Header::decode(reader)?; - let value = reader.read_vec(header.length)?; - Self::new(header.tag, value) + impl<'a> Decode<'a> for Any { + fn decode<R: Reader<'a>>(reader: &mut R) -> Result<Self> { + let header = Header::decode(reader)?; + Self::decode_value(reader, header) + } } -} -#[cfg(feature = "alloc")] -impl EncodeValue for Any { - fn value_len(&self) -> Result<Length> { - self.value.len().try_into() + impl<'a> DecodeValue<'a> for Any { + fn decode_value<R: Reader<'a>>(reader: &mut R, header: Header) -> Result<Self> { + let value = reader.read_vec(header.length)?; + Self::new(header.tag, value) + } } - fn encode_value(&self, writer: &mut dyn Writer) -> Result<()> { - writer.write(&self.value) + impl EncodeValue for Any { + fn value_len(&self) -> Result<Length> { + Ok(self.value.len()) + } + + fn encode_value(&self, writer: &mut impl Writer) -> Result<()> { + writer.write(self.value.as_slice()) + } } -} -#[cfg(feature = "alloc")] -impl<'a> From<&'a Any> for AnyRef<'a> { - fn from(any: &'a Any) -> AnyRef<'a> { - // Ensured to parse successfully in constructor - AnyRef::new(any.tag, &any.value).expect("invalid ANY") + impl<'a> From<&'a Any> for AnyRef<'a> { + fn from(any: &'a Any) -> AnyRef<'a> { + // Ensured to parse successfully in constructor + AnyRef::new(any.tag, any.value.as_slice()).expect("invalid ANY") + } } -} -#[cfg(feature = "alloc")] -impl Tagged for Any { - fn tag(&self) -> Tag { - self.tag + impl Tagged for Any { + fn tag(&self) -> Tag { + self.tag + } + } + + impl ValueOrd for Any { + fn value_cmp(&self, other: &Self) -> Result<Ordering> { + self.value.der_cmp(&other.value) + } + } + + impl<'a, T> From<T> for Any + where + T: Into<AnyRef<'a>>, + { + fn from(input: T) -> Any { + let anyref: AnyRef<'a> = input.into(); + Self { + tag: anyref.tag(), + value: BytesOwned::from(anyref.value), + } + } + } + + impl<'a> RefToOwned<'a> for AnyRef<'a> { + type Owned = Any; + fn ref_to_owned(&self) -> Self::Owned { + Any { + tag: self.tag(), + value: BytesOwned::from(self.value), + } + } + } + + impl OwnedToRef for Any { + type Borrowed<'a> = AnyRef<'a>; + fn owned_to_ref(&self) -> Self::Borrowed<'_> { + self.into() + } + } + + impl Any { + /// Is this value an ASN.1 `NULL` value? + pub fn is_null(&self) -> bool { + self.owned_to_ref() == AnyRef::NULL + } } } diff --git a/vendor/der/src/asn1/bit_string.rs b/vendor/der/src/asn1/bit_string.rs index eed14e456..bf3371c40 100644 --- a/vendor/der/src/asn1/bit_string.rs +++ b/vendor/der/src/asn1/bit_string.rs @@ -1,14 +1,11 @@ //! ASN.1 `BIT STRING` support. use crate::{ - asn1::AnyRef, ByteSlice, DecodeValue, DerOrd, EncodeValue, Error, ErrorKind, FixedTag, Header, - Length, Reader, Result, Tag, ValueOrd, Writer, + BytesRef, DecodeValue, DerOrd, EncodeValue, Error, ErrorKind, FixedTag, Header, Length, Reader, + Result, Tag, ValueOrd, Writer, }; use core::{cmp::Ordering, iter::FusedIterator}; -#[cfg(feature = "alloc")] -use alloc::vec::Vec; - /// ASN.1 `BIT STRING` type. /// /// This type contains a sequence of any number of bits, modeled internally as @@ -24,7 +21,7 @@ pub struct BitStringRef<'a> { bit_length: usize, /// Bitstring represented as a slice of bytes. - inner: ByteSlice<'a>, + inner: BytesRef<'a>, } impl<'a> BitStringRef<'a> { @@ -40,7 +37,7 @@ impl<'a> BitStringRef<'a> { return Err(Self::TAG.value_error()); } - let inner = ByteSlice::new(bytes).map_err(|_| Self::TAG.length_error())?; + let inner = BytesRef::new(bytes).map_err(|_| Self::TAG.length_error())?; let bit_length = usize::try_from(inner.len())? .checked_mul(8) @@ -120,6 +117,8 @@ impl<'a> BitStringRef<'a> { } } +impl_any_conversions!(BitStringRef<'a>, 'a); + impl<'a> DecodeValue<'a> for BitStringRef<'a> { fn decode_value<R: Reader<'a>>(reader: &mut R, header: Header) -> Result<Self> { let header = Header { @@ -128,7 +127,7 @@ impl<'a> DecodeValue<'a> for BitStringRef<'a> { }; let unused_bits = reader.read_byte()?; - let inner = ByteSlice::decode_value(reader, header)?; + let inner = BytesRef::decode_value(reader, header)?; Self::new(unused_bits, inner.as_slice()) } } @@ -138,7 +137,7 @@ impl EncodeValue for BitStringRef<'_> { self.byte_len() + Length::ONE } - fn encode_value(&self, writer: &mut dyn Writer) -> Result<()> { + fn encode_value(&self, writer: &mut impl Writer) -> Result<()> { writer.write_byte(self.unused_bits)?; writer.write(self.raw_bytes()) } @@ -159,14 +158,6 @@ impl<'a> From<&BitStringRef<'a>> for BitStringRef<'a> { } } -impl<'a> TryFrom<AnyRef<'a>> for BitStringRef<'a> { - type Error = Error; - - fn try_from(any: AnyRef<'a>) -> Result<BitStringRef<'a>> { - any.decode_into() - } -} - impl<'a> TryFrom<&'a [u8]> for BitStringRef<'a> { type Error = Error; @@ -180,7 +171,7 @@ impl<'a> TryFrom<&&'a [u8]> for BitStringRef<'a> { type Error = Error; fn try_from(bytes: &&'a [u8]) -> Result<BitStringRef<'a>> { - BitStringRef::from_bytes(*bytes) + BitStringRef::from_bytes(bytes) } } @@ -198,141 +189,198 @@ impl<'a> FixedTag for BitStringRef<'a> { const TAG: Tag = Tag::BitString; } -/// Owned form of ASN.1 `BIT STRING` type. -/// -/// This type provides the same functionality as [`BitStringRef`] but owns the -/// backing data. -#[cfg(feature = "alloc")] -#[cfg_attr(docsrs, doc(cfg(feature = "alloc")))] -#[derive(Clone, Debug, Eq, PartialEq, PartialOrd, Ord)] -pub struct BitString { - /// Number of unused bits in the final octet. - unused_bits: u8, - - /// Length of this `BIT STRING` in bits. - bit_length: usize, +// Implement by hand because the derive would create invalid values. +// Use the constructor to create a valid value. +#[cfg(feature = "arbitrary")] +impl<'a> arbitrary::Arbitrary<'a> for BitStringRef<'a> { + fn arbitrary(u: &mut arbitrary::Unstructured<'a>) -> arbitrary::Result<Self> { + Self::new( + u.int_in_range(0..=Self::MAX_UNUSED_BITS)?, + BytesRef::arbitrary(u)?.as_slice(), + ) + .map_err(|_| arbitrary::Error::IncorrectFormat) + } - /// Bitstring represented as a slice of bytes. - inner: Vec<u8>, + fn size_hint(depth: usize) -> (usize, Option<usize>) { + arbitrary::size_hint::and(u8::size_hint(depth), BytesRef::size_hint(depth)) + } } #[cfg(feature = "alloc")] -impl BitString { - /// Maximum number of unused bits allowed. - pub const MAX_UNUSED_BITS: u8 = 7; +pub use self::allocating::BitString; - /// Create a new ASN.1 `BIT STRING` from a byte slice. +#[cfg(feature = "alloc")] +mod allocating { + use super::*; + use crate::referenced::*; + use alloc::vec::Vec; + + /// Owned form of ASN.1 `BIT STRING` type. /// - /// Accepts an optional number of "unused bits" (0-7) which are omitted - /// from the final octet. This number is 0 if the value is octet-aligned. - pub fn new(unused_bits: u8, bytes: impl Into<Vec<u8>>) -> Result<Self> { - let inner = bytes.into(); + /// This type provides the same functionality as [`BitStringRef`] but owns the + /// backing data. + #[derive(Clone, Debug, Eq, PartialEq, PartialOrd, Ord)] + pub struct BitString { + /// Number of unused bits in the final octet. + unused_bits: u8, + + /// Length of this `BIT STRING` in bits. + bit_length: usize, + + /// Bitstring represented as a slice of bytes. + inner: Vec<u8>, + } + + impl BitString { + /// Maximum number of unused bits allowed. + pub const MAX_UNUSED_BITS: u8 = 7; + + /// Create a new ASN.1 `BIT STRING` from a byte slice. + /// + /// Accepts an optional number of "unused bits" (0-7) which are omitted + /// from the final octet. This number is 0 if the value is octet-aligned. + pub fn new(unused_bits: u8, bytes: impl Into<Vec<u8>>) -> Result<Self> { + let inner = bytes.into(); + + // Ensure parameters parse successfully as a `BitStringRef`. + let bit_length = BitStringRef::new(unused_bits, &inner)?.bit_length; + + Ok(BitString { + unused_bits, + bit_length, + inner, + }) + } - // Ensure parameters parse successfully as a `BitStringRef`. - let bit_length = BitStringRef::new(unused_bits, &inner)?.bit_length; + /// Create a new ASN.1 `BIT STRING` from the given bytes. + /// + /// The "unused bits" are set to 0. + pub fn from_bytes(bytes: &[u8]) -> Result<Self> { + Self::new(0, bytes) + } - Ok(BitString { - unused_bits, - bit_length, - inner, - }) - } + /// Get the number of unused bits in the octet serialization of this + /// `BIT STRING`. + pub fn unused_bits(&self) -> u8 { + self.unused_bits + } - /// Create a new ASN.1 `BIT STRING` from the given bytes. - /// - /// The "unused bits" are set to 0. - pub fn from_bytes(bytes: &[u8]) -> Result<Self> { - Self::new(0, bytes) - } + /// Is the number of unused bits a value other than 0? + pub fn has_unused_bits(&self) -> bool { + self.unused_bits != 0 + } - /// Get the number of unused bits in the octet serialization of this - /// `BIT STRING`. - pub fn unused_bits(&self) -> u8 { - self.unused_bits - } + /// Get the length of this `BIT STRING` in bits. + pub fn bit_len(&self) -> usize { + self.bit_length + } - /// Is the number of unused bits a value other than 0? - pub fn has_unused_bits(&self) -> bool { - self.unused_bits != 0 - } + /// Is the inner byte slice empty? + pub fn is_empty(&self) -> bool { + self.inner.is_empty() + } - /// Get the length of this `BIT STRING` in bits. - pub fn bit_len(&self) -> usize { - self.bit_length - } + /// Borrow the inner byte slice. + /// + /// Returns `None` if the number of unused bits is *not* equal to zero, + /// i.e. if the `BIT STRING` is not octet aligned. + /// + /// Use [`BitString::raw_bytes`] to obtain access to the raw value + /// regardless of the presence of unused bits. + pub fn as_bytes(&self) -> Option<&[u8]> { + if self.has_unused_bits() { + None + } else { + Some(self.raw_bytes()) + } + } - /// Is the inner byte slice empty? - pub fn is_empty(&self) -> bool { - self.inner.is_empty() - } + /// Borrow the raw bytes of this `BIT STRING`. + pub fn raw_bytes(&self) -> &[u8] { + self.inner.as_slice() + } - /// Borrow the inner byte slice. - /// - /// Returns `None` if the number of unused bits is *not* equal to zero, - /// i.e. if the `BIT STRING` is not octet aligned. - /// - /// Use [`BitString::raw_bytes`] to obtain access to the raw value - /// regardless of the presence of unused bits. - pub fn as_bytes(&self) -> Option<&[u8]> { - if self.has_unused_bits() { - None - } else { - Some(self.raw_bytes()) + /// Iterator over the bits of this `BIT STRING`. + pub fn bits(&self) -> BitStringIter<'_> { + BitStringRef::from(self).bits() } } - /// Borrow the raw bytes of this `BIT STRING`. - pub fn raw_bytes(&self) -> &[u8] { - self.inner.as_slice() + impl_any_conversions!(BitString); + + impl<'a> DecodeValue<'a> for BitString { + fn decode_value<R: Reader<'a>>(reader: &mut R, header: Header) -> Result<Self> { + let inner_len = (header.length - Length::ONE)?; + let unused_bits = reader.read_byte()?; + let inner = reader.read_vec(inner_len)?; + Self::new(unused_bits, inner) + } } - /// Iterator over the bits of this `BIT STRING`. - pub fn bits(&self) -> BitStringIter<'_> { - BitStringRef::from(self).bits() + impl EncodeValue for BitString { + fn value_len(&self) -> Result<Length> { + Length::ONE + Length::try_from(self.inner.len())? + } + + fn encode_value(&self, writer: &mut impl Writer) -> Result<()> { + writer.write_byte(self.unused_bits)?; + writer.write(&self.inner) + } } -} -#[cfg(feature = "alloc")] -impl<'a> DecodeValue<'a> for BitString { - fn decode_value<R: Reader<'a>>(reader: &mut R, header: Header) -> Result<Self> { - let inner_len = (header.length - Length::ONE)?; - let unused_bits = reader.read_byte()?; - let inner = reader.read_vec(inner_len)?; - Self::new(unused_bits, inner) + impl FixedTag for BitString { + const TAG: Tag = Tag::BitString; } -} -#[cfg(feature = "alloc")] -impl EncodeValue for BitString { - fn value_len(&self) -> Result<Length> { - Length::ONE + Length::try_from(self.inner.len())? + impl<'a> From<&'a BitString> for BitStringRef<'a> { + fn from(bit_string: &'a BitString) -> BitStringRef<'a> { + // Ensured to parse successfully in constructor + BitStringRef::new(bit_string.unused_bits, &bit_string.inner) + .expect("invalid BIT STRING") + } } - fn encode_value(&self, writer: &mut dyn Writer) -> Result<()> { - writer.write_byte(self.unused_bits)?; - writer.write(&self.inner) + impl ValueOrd for BitString { + fn value_cmp(&self, other: &Self) -> Result<Ordering> { + match self.unused_bits.cmp(&other.unused_bits) { + Ordering::Equal => self.inner.der_cmp(&other.inner), + ordering => Ok(ordering), + } + } } -} -#[cfg(feature = "alloc")] -impl FixedTag for BitString { - const TAG: Tag = Tag::BitString; -} + // Implement by hand because the derive would create invalid values. + // Use the constructor to create a valid value. + #[cfg(feature = "arbitrary")] + impl<'a> arbitrary::Arbitrary<'a> for BitString { + fn arbitrary(u: &mut arbitrary::Unstructured<'a>) -> arbitrary::Result<Self> { + Self::new( + u.int_in_range(0..=Self::MAX_UNUSED_BITS)?, + BytesRef::arbitrary(u)?.as_slice(), + ) + .map_err(|_| arbitrary::Error::IncorrectFormat) + } -#[cfg(feature = "alloc")] -impl<'a> From<&'a BitString> for BitStringRef<'a> { - fn from(bit_string: &'a BitString) -> BitStringRef<'a> { - // Ensured to parse successfully in constructor - BitStringRef::new(bit_string.unused_bits, &bit_string.inner).expect("invalid BIT STRING") + fn size_hint(depth: usize) -> (usize, Option<usize>) { + arbitrary::size_hint::and(u8::size_hint(depth), BytesRef::size_hint(depth)) + } } -} -#[cfg(feature = "alloc")] -impl ValueOrd for BitString { - fn value_cmp(&self, other: &Self) -> Result<Ordering> { - match self.unused_bits.cmp(&other.unused_bits) { - Ordering::Equal => self.inner.der_cmp(&other.inner), - ordering => Ok(ordering), + impl<'a> RefToOwned<'a> for BitStringRef<'a> { + type Owned = BitString; + fn ref_to_owned(&self) -> Self::Owned { + BitString { + unused_bits: self.unused_bits, + bit_length: self.bit_length, + inner: Vec::from(self.inner.as_slice()), + } + } + } + + impl OwnedToRef for BitString { + type Borrowed<'a> = BitStringRef<'a>; + fn owned_to_ref(&self) -> Self::Borrowed<'_> { + self.into() } } } @@ -445,7 +493,7 @@ where BitStringRef::new((lead % 8) as u8, buff)?.value_len() } - fn encode_value(&self, writer: &mut dyn Writer) -> Result<()> { + fn encode_value(&self, writer: &mut impl Writer) -> Result<()> { let (lead, buff) = encode_flagset(self); let buff = &buff[..buff.len() - lead / 8]; BitStringRef::new((lead % 8) as u8, buff)?.encode_value(writer) @@ -486,7 +534,7 @@ mod tests { assert_eq!(bits.len(), 18); for bit in [0, 1, 1, 0, 1, 1, 1, 0, 0, 1, 0, 1, 1, 1, 0, 1, 1, 1] { - assert_eq!(bits.next().unwrap() as u8, bit) + assert_eq!(u8::from(bits.next().unwrap()), bit) } // Ensure `None` is returned on successive calls diff --git a/vendor/der/src/asn1/boolean.rs b/vendor/der/src/asn1/boolean.rs index e03218120..3eb0f2e68 100644 --- a/vendor/der/src/asn1/boolean.rs +++ b/vendor/der/src/asn1/boolean.rs @@ -1,8 +1,8 @@ //! ASN.1 `BOOLEAN` support. use crate::{ - asn1::AnyRef, ord::OrdIsValueOrd, ByteSlice, DecodeValue, EncodeValue, Error, ErrorKind, - FixedTag, Header, Length, Reader, Result, Tag, Writer, + asn1::AnyRef, ord::OrdIsValueOrd, DecodeValue, EncodeValue, Error, ErrorKind, FixedTag, Header, + Length, Reader, Result, Tag, Writer, }; /// Byte used to encode `true` in ASN.1 DER. From X.690 Section 11.1: @@ -33,7 +33,7 @@ impl EncodeValue for bool { Ok(Length::ONE) } - fn encode_value(&self, writer: &mut dyn Writer) -> Result<()> { + fn encode_value(&self, writer: &mut impl Writer) -> Result<()> { writer.write_byte(if *self { TRUE_OCTET } else { FALSE_OCTET }) } } @@ -44,17 +44,6 @@ impl FixedTag for bool { impl OrdIsValueOrd for bool {} -impl From<bool> for AnyRef<'static> { - fn from(value: bool) -> AnyRef<'static> { - let value = ByteSlice::from(match value { - false => &[FALSE_OCTET], - true => &[TRUE_OCTET], - }); - - AnyRef::from_tag_and_value(Tag::Boolean, value) - } -} - impl TryFrom<AnyRef<'_>> for bool { type Error = Error; diff --git a/vendor/der/src/asn1/context_specific.rs b/vendor/der/src/asn1/context_specific.rs index 311b5fe74..101ddf022 100644 --- a/vendor/der/src/asn1/context_specific.rs +++ b/vendor/der/src/asn1/context_specific.rs @@ -145,7 +145,7 @@ where } } - fn encode_value(&self, writer: &mut dyn Writer) -> Result<()> { + fn encode_value(&self, writer: &mut impl Writer) -> Result<()> { match self.tag_mode { TagMode::Explicit => self.value.encode(writer), TagMode::Implicit => self.value.encode_value(writer), @@ -239,7 +239,7 @@ where self.encoder().value_len() } - fn encode_value(&self, writer: &mut dyn Writer) -> Result<()> { + fn encode_value(&self, writer: &mut impl Writer) -> Result<()> { self.encoder().encode_value(writer) } } diff --git a/vendor/der/src/asn1/generalized_time.rs b/vendor/der/src/asn1/generalized_time.rs index 9950e368e..f7b6f180f 100644 --- a/vendor/der/src/asn1/generalized_time.rs +++ b/vendor/der/src/asn1/generalized_time.rs @@ -1,16 +1,18 @@ //! ASN.1 `GeneralizedTime` support. +#![cfg_attr(feature = "arbitrary", allow(clippy::integer_arithmetic))] use crate::{ - asn1::AnyRef, datetime::{self, DateTime}, ord::OrdIsValueOrd, - DecodeValue, EncodeValue, Error, ErrorKind, FixedTag, Header, Length, Reader, Result, Tag, - Writer, + DecodeValue, EncodeValue, ErrorKind, FixedTag, Header, Length, Reader, Result, Tag, Writer, }; use core::time::Duration; #[cfg(feature = "std")] -use std::time::SystemTime; +use { + crate::{asn1::AnyRef, Error}, + std::time::SystemTime, +}; #[cfg(feature = "time")] use time::PrimitiveDateTime; @@ -26,6 +28,7 @@ use time::PrimitiveDateTime; /// > is zero. GeneralizedTime values MUST NOT include fractional seconds. /// /// [1]: https://tools.ietf.org/html/rfc5280#section-4.1.2.5.2 +#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))] #[derive(Copy, Clone, Debug, Eq, PartialEq, PartialOrd, Ord)] pub struct GeneralizedTime(DateTime); @@ -58,7 +61,6 @@ impl GeneralizedTime { /// Instantiate from [`SystemTime`]. #[cfg(feature = "std")] - #[cfg_attr(docsrs, doc(cfg(feature = "std")))] pub fn from_system_time(time: SystemTime) -> Result<Self> { DateTime::try_from(time) .map(Into::into) @@ -67,12 +69,13 @@ impl GeneralizedTime { /// Convert to [`SystemTime`]. #[cfg(feature = "std")] - #[cfg_attr(docsrs, doc(cfg(feature = "std")))] pub fn to_system_time(&self) -> SystemTime { self.0.to_system_time() } } +impl_any_conversions!(GeneralizedTime); + impl<'a> DecodeValue<'a> for GeneralizedTime { fn decode_value<R: Reader<'a>>(reader: &mut R, header: Header) -> Result<Self> { if Self::LENGTH != usize::try_from(header.length)? { @@ -111,7 +114,7 @@ impl EncodeValue for GeneralizedTime { Self::LENGTH.try_into() } - fn encode_value(&self, writer: &mut dyn Writer) -> Result<()> { + fn encode_value(&self, writer: &mut impl Writer) -> Result<()> { let year_hi = u8::try_from(self.0.year() / 100)?; let year_lo = u8::try_from(self.0.year() % 100)?; @@ -162,14 +165,6 @@ impl From<&DateTime> for GeneralizedTime { } } -impl TryFrom<AnyRef<'_>> for GeneralizedTime { - type Error = Error; - - fn try_from(any: AnyRef<'_>) -> Result<GeneralizedTime> { - any.decode_into() - } -} - impl<'a> DecodeValue<'a> for DateTime { fn decode_value<R: Reader<'a>>(reader: &mut R, header: Header) -> Result<Self> { Ok(GeneralizedTime::decode_value(reader, header)?.into()) @@ -181,7 +176,7 @@ impl EncodeValue for DateTime { GeneralizedTime::from(self).value_len() } - fn encode_value(&self, writer: &mut dyn Writer) -> Result<()> { + fn encode_value(&self, writer: &mut impl Writer) -> Result<()> { GeneralizedTime::from(self).encode_value(writer) } } @@ -193,7 +188,6 @@ impl FixedTag for DateTime { impl OrdIsValueOrd for DateTime {} #[cfg(feature = "std")] -#[cfg_attr(docsrs, doc(cfg(feature = "std")))] impl<'a> DecodeValue<'a> for SystemTime { fn decode_value<R: Reader<'a>>(reader: &mut R, header: Header) -> Result<Self> { Ok(GeneralizedTime::decode_value(reader, header)?.into()) @@ -201,19 +195,17 @@ impl<'a> DecodeValue<'a> for SystemTime { } #[cfg(feature = "std")] -#[cfg_attr(docsrs, doc(cfg(feature = "std")))] impl EncodeValue for SystemTime { fn value_len(&self) -> Result<Length> { GeneralizedTime::try_from(self)?.value_len() } - fn encode_value(&self, writer: &mut dyn Writer) -> Result<()> { + fn encode_value(&self, writer: &mut impl Writer) -> Result<()> { GeneralizedTime::try_from(self)?.encode_value(writer) } } #[cfg(feature = "std")] -#[cfg_attr(docsrs, doc(cfg(feature = "std")))] impl From<GeneralizedTime> for SystemTime { fn from(time: GeneralizedTime) -> SystemTime { time.to_system_time() @@ -221,7 +213,6 @@ impl From<GeneralizedTime> for SystemTime { } #[cfg(feature = "std")] -#[cfg_attr(docsrs, doc(cfg(feature = "std")))] impl From<&GeneralizedTime> for SystemTime { fn from(time: &GeneralizedTime) -> SystemTime { time.to_system_time() @@ -229,7 +220,6 @@ impl From<&GeneralizedTime> for SystemTime { } #[cfg(feature = "std")] -#[cfg_attr(docsrs, doc(cfg(feature = "std")))] impl TryFrom<SystemTime> for GeneralizedTime { type Error = Error; @@ -239,7 +229,6 @@ impl TryFrom<SystemTime> for GeneralizedTime { } #[cfg(feature = "std")] -#[cfg_attr(docsrs, doc(cfg(feature = "std")))] impl TryFrom<&SystemTime> for GeneralizedTime { type Error = Error; @@ -249,7 +238,6 @@ impl TryFrom<&SystemTime> for GeneralizedTime { } #[cfg(feature = "std")] -#[cfg_attr(docsrs, doc(cfg(feature = "std")))] impl<'a> TryFrom<AnyRef<'a>> for SystemTime { type Error = Error; @@ -259,17 +247,14 @@ impl<'a> TryFrom<AnyRef<'a>> for SystemTime { } #[cfg(feature = "std")] -#[cfg_attr(docsrs, doc(cfg(feature = "std")))] impl FixedTag for SystemTime { const TAG: Tag = Tag::GeneralizedTime; } #[cfg(feature = "std")] -#[cfg_attr(docsrs, doc(cfg(feature = "std")))] impl OrdIsValueOrd for SystemTime {} #[cfg(feature = "time")] -#[cfg_attr(docsrs, doc(cfg(feature = "time")))] impl<'a> DecodeValue<'a> for PrimitiveDateTime { fn decode_value<R: Reader<'a>>(reader: &mut R, header: Header) -> Result<Self> { GeneralizedTime::decode_value(reader, header)?.try_into() @@ -277,29 +262,25 @@ impl<'a> DecodeValue<'a> for PrimitiveDateTime { } #[cfg(feature = "time")] -#[cfg_attr(docsrs, doc(cfg(feature = "time")))] impl EncodeValue for PrimitiveDateTime { fn value_len(&self) -> Result<Length> { GeneralizedTime::try_from(self)?.value_len() } - fn encode_value(&self, writer: &mut dyn Writer) -> Result<()> { + fn encode_value(&self, writer: &mut impl Writer) -> Result<()> { GeneralizedTime::try_from(self)?.encode_value(writer) } } #[cfg(feature = "time")] -#[cfg_attr(docsrs, doc(cfg(feature = "time")))] impl FixedTag for PrimitiveDateTime { const TAG: Tag = Tag::GeneralizedTime; } #[cfg(feature = "time")] -#[cfg_attr(docsrs, doc(cfg(feature = "time")))] impl OrdIsValueOrd for PrimitiveDateTime {} #[cfg(feature = "time")] -#[cfg_attr(docsrs, doc(cfg(feature = "time")))] impl TryFrom<PrimitiveDateTime> for GeneralizedTime { type Error = Error; @@ -309,7 +290,6 @@ impl TryFrom<PrimitiveDateTime> for GeneralizedTime { } #[cfg(feature = "time")] -#[cfg_attr(docsrs, doc(cfg(feature = "time")))] impl TryFrom<&PrimitiveDateTime> for GeneralizedTime { type Error = Error; @@ -319,7 +299,6 @@ impl TryFrom<&PrimitiveDateTime> for GeneralizedTime { } #[cfg(feature = "time")] -#[cfg_attr(docsrs, doc(cfg(feature = "time")))] impl TryFrom<GeneralizedTime> for PrimitiveDateTime { type Error = Error; diff --git a/vendor/der/src/asn1/ia5_string.rs b/vendor/der/src/asn1/ia5_string.rs index 3971270a8..c3f24f01c 100644 --- a/vendor/der/src/asn1/ia5_string.rs +++ b/vendor/der/src/asn1/ia5_string.rs @@ -1,10 +1,26 @@ //! ASN.1 `IA5String` support. -use crate::{ - asn1::AnyRef, ord::OrdIsValueOrd, ByteSlice, DecodeValue, EncodeValue, Error, FixedTag, Header, - Length, Reader, Result, StrSlice, Tag, Writer, -}; -use core::{fmt, ops::Deref, str}; +use crate::{asn1::AnyRef, FixedTag, Result, StrRef, Tag}; +use core::{fmt, ops::Deref}; + +macro_rules! impl_ia5_string { + ($type: ty) => { + impl_ia5_string!($type,); + }; + ($type: ty, $($li: lifetime)?) => { + impl_string_type!($type, $($li),*); + + impl<$($li),*> FixedTag for $type { + const TAG: Tag = Tag::Ia5String; + } + + impl<$($li),*> fmt::Debug for $type { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + write!(f, "Ia5String({:?})", self.as_str()) + } + } + }; +} /// ASN.1 `IA5String` type. /// @@ -21,7 +37,7 @@ use core::{fmt, ops::Deref, str}; #[derive(Copy, Clone, Eq, PartialEq, PartialOrd, Ord)] pub struct Ia5StringRef<'a> { /// Inner value - inner: StrSlice<'a>, + inner: StrRef<'a>, } impl<'a> Ia5StringRef<'a> { @@ -37,83 +53,117 @@ impl<'a> Ia5StringRef<'a> { return Err(Self::TAG.value_error()); } - StrSlice::from_bytes(input) + StrRef::from_bytes(input) .map(|inner| Self { inner }) .map_err(|_| Self::TAG.value_error()) } } +impl_ia5_string!(Ia5StringRef<'a>, 'a); + impl<'a> Deref for Ia5StringRef<'a> { - type Target = StrSlice<'a>; + type Target = StrRef<'a>; fn deref(&self) -> &Self::Target { &self.inner } } -impl AsRef<str> for Ia5StringRef<'_> { - fn as_ref(&self) -> &str { - self.as_str() +impl<'a> From<&Ia5StringRef<'a>> for Ia5StringRef<'a> { + fn from(value: &Ia5StringRef<'a>) -> Ia5StringRef<'a> { + *value } } -impl AsRef<[u8]> for Ia5StringRef<'_> { - fn as_ref(&self) -> &[u8] { - self.as_bytes() +impl<'a> From<Ia5StringRef<'a>> for AnyRef<'a> { + fn from(internationalized_string: Ia5StringRef<'a>) -> AnyRef<'a> { + AnyRef::from_tag_and_value(Tag::Ia5String, internationalized_string.inner.into()) } } -impl<'a> DecodeValue<'a> for Ia5StringRef<'a> { - fn decode_value<R: Reader<'a>>(reader: &mut R, header: Header) -> Result<Self> { - Self::new(ByteSlice::decode_value(reader, header)?.as_slice()) - } -} +#[cfg(feature = "alloc")] +pub use self::allocation::Ia5String; -impl EncodeValue for Ia5StringRef<'_> { - fn value_len(&self) -> Result<Length> { - self.inner.value_len() +#[cfg(feature = "alloc")] +mod allocation { + use super::Ia5StringRef; + use crate::{ + asn1::AnyRef, + referenced::{OwnedToRef, RefToOwned}, + FixedTag, Result, StrOwned, Tag, + }; + use core::{fmt, ops::Deref}; + + /// ASN.1 `IA5String` type. + /// + /// Supports the [International Alphabet No. 5 (IA5)] character encoding, i.e. + /// the lower 128 characters of the ASCII alphabet. (Note: IA5 is now + /// technically known as the International Reference Alphabet or IRA as + /// specified in the ITU-T's T.50 recommendation). + /// + /// For UTF-8, use [`String`][`alloc::string::String`]. + /// + /// [International Alphabet No. 5 (IA5)]: https://en.wikipedia.org/wiki/T.50_%28standard%29 + #[derive(Clone, Eq, PartialEq, PartialOrd, Ord)] + pub struct Ia5String { + /// Inner value + inner: StrOwned, } - fn encode_value(&self, writer: &mut dyn Writer) -> Result<()> { - self.inner.encode_value(writer) + impl Ia5String { + /// Create a new `IA5String`. + pub fn new<T>(input: &T) -> Result<Self> + where + T: AsRef<[u8]> + ?Sized, + { + let input = input.as_ref(); + Ia5StringRef::new(input)?; + + StrOwned::from_bytes(input) + .map(|inner| Self { inner }) + .map_err(|_| Self::TAG.value_error()) + } } -} -impl<'a> FixedTag for Ia5StringRef<'a> { - const TAG: Tag = Tag::Ia5String; -} + impl_ia5_string!(Ia5String); -impl OrdIsValueOrd for Ia5StringRef<'_> {} + impl Deref for Ia5String { + type Target = StrOwned; -impl<'a> From<&Ia5StringRef<'a>> for Ia5StringRef<'a> { - fn from(value: &Ia5StringRef<'a>) -> Ia5StringRef<'a> { - *value + fn deref(&self) -> &Self::Target { + &self.inner + } } -} - -impl<'a> TryFrom<AnyRef<'a>> for Ia5StringRef<'a> { - type Error = Error; - fn try_from(any: AnyRef<'a>) -> Result<Ia5StringRef<'a>> { - any.decode_into() + impl<'a> From<Ia5StringRef<'a>> for Ia5String { + fn from(international_string: Ia5StringRef<'a>) -> Ia5String { + let inner = international_string.inner.into(); + Self { inner } + } } -} -impl<'a> From<Ia5StringRef<'a>> for AnyRef<'a> { - fn from(printable_string: Ia5StringRef<'a>) -> AnyRef<'a> { - AnyRef::from_tag_and_value(Tag::Ia5String, printable_string.inner.into()) + impl<'a> From<&'a Ia5String> for AnyRef<'a> { + fn from(international_string: &'a Ia5String) -> AnyRef<'a> { + AnyRef::from_tag_and_value(Tag::Ia5String, (&international_string.inner).into()) + } } -} -impl<'a> fmt::Display for Ia5StringRef<'a> { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - f.write_str(self.as_str()) + impl<'a> RefToOwned<'a> for Ia5StringRef<'a> { + type Owned = Ia5String; + fn ref_to_owned(&self) -> Self::Owned { + Ia5String { + inner: self.inner.ref_to_owned(), + } + } } -} -impl<'a> fmt::Debug for Ia5StringRef<'a> { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - write!(f, "Ia5String({:?})", self.as_str()) + impl OwnedToRef for Ia5String { + type Borrowed<'a> = Ia5StringRef<'a>; + fn owned_to_ref(&self) -> Self::Borrowed<'_> { + Ia5StringRef { + inner: self.inner.owned_to_ref(), + } + } } } @@ -126,7 +176,7 @@ mod tests { #[test] fn parse_bytes() { let example_bytes = hex!("16 0d 74 65 73 74 31 40 72 73 61 2e 63 6f 6d"); - let printable_string = Ia5StringRef::from_der(&example_bytes).unwrap(); - assert_eq!(printable_string.as_str(), "test1@rsa.com"); + let internationalized_string = Ia5StringRef::from_der(&example_bytes).unwrap(); + assert_eq!(internationalized_string.as_str(), "test1@rsa.com"); } } diff --git a/vendor/der/src/asn1/integer.rs b/vendor/der/src/asn1/integer.rs index 20e2f018f..a6e913d66 100644 --- a/vendor/der/src/asn1/integer.rs +++ b/vendor/der/src/asn1/integer.rs @@ -1,132 +1,17 @@ //! ASN.1 `INTEGER` support. -pub(super) mod bigint; pub(super) mod int; pub(super) mod uint; -use crate::{ - asn1::AnyRef, ByteSlice, DecodeValue, EncodeValue, Error, FixedTag, Header, Length, Reader, - Result, SliceWriter, Tag, ValueOrd, Writer, -}; use core::{cmp::Ordering, mem}; -macro_rules! impl_int_encoding { - ($($int:ty => $uint:ty),+) => { - $( - impl<'a> DecodeValue<'a> for $int { - fn decode_value<R: Reader<'a>>(reader: &mut R, header: Header) -> Result<Self> { - let bytes = ByteSlice::decode_value(reader, header)?.as_slice(); +use crate::{EncodeValue, Result, SliceWriter}; - let result = if is_highest_bit_set(bytes) { - <$uint>::from_be_bytes(int::decode_to_array(bytes)?) as $int - } else { - Self::from_be_bytes(uint::decode_to_array(bytes)?) - }; - - // Ensure we compute the same encoded length as the original any value - if header.length != result.value_len()? { - return Err(Self::TAG.non_canonical_error()); - } - - Ok(result) - } - } - - impl EncodeValue for $int { - fn value_len(&self) -> Result<Length> { - if *self < 0 { - int::encoded_len(&(*self as $uint).to_be_bytes()) - } else { - uint::encoded_len(&self.to_be_bytes()) - } - } - - fn encode_value(&self, writer: &mut dyn Writer) -> Result<()> { - if *self < 0 { - int::encode_bytes(writer, &(*self as $uint).to_be_bytes()) - } else { - uint::encode_bytes(writer, &self.to_be_bytes()) - } - } - } - - impl FixedTag for $int { - const TAG: Tag = Tag::Integer; - } - - impl ValueOrd for $int { - fn value_cmp(&self, other: &Self) -> Result<Ordering> { - value_cmp(*self, *other) - } - } - - impl TryFrom<AnyRef<'_>> for $int { - type Error = Error; - - fn try_from(any: AnyRef<'_>) -> Result<Self> { - any.decode_into() - } - } - )+ - }; -} - -macro_rules! impl_uint_encoding { - ($($uint:ty),+) => { - $( - impl<'a> DecodeValue<'a> for $uint { - fn decode_value<R: Reader<'a>>(reader: &mut R, header: Header) -> Result<Self> { - let bytes = ByteSlice::decode_value(reader, header)?.as_slice(); - let result = Self::from_be_bytes(uint::decode_to_array(bytes)?); - - // Ensure we compute the same encoded length as the original any value - if header.length != result.value_len()? { - return Err(Self::TAG.non_canonical_error()); - } - - Ok(result) - } - } - - impl EncodeValue for $uint { - fn value_len(&self) -> Result<Length> { - uint::encoded_len(&self.to_be_bytes()) - } - - fn encode_value(&self, writer: &mut dyn Writer) -> Result<()> { - uint::encode_bytes(writer, &self.to_be_bytes()) - } - } - - impl FixedTag for $uint { - const TAG: Tag = Tag::Integer; - } - - impl ValueOrd for $uint { - fn value_cmp(&self, other: &Self) -> Result<Ordering> { - value_cmp(*self, *other) - } - } - - impl TryFrom<AnyRef<'_>> for $uint { - type Error = Error; - - fn try_from(any: AnyRef<'_>) -> Result<Self> { - any.decode_into() - } - } - )+ - }; -} - -impl_int_encoding!(i8 => u8, i16 => u16, i32 => u32, i64 => u64, i128 => u128); -impl_uint_encoding!(u8, u16, u32, u64, u128); - -/// Is the highest bit of the first byte in the slice 1? (if present) +/// Is the highest bit of the first byte in the slice set to `1`? (if present) #[inline] fn is_highest_bit_set(bytes: &[u8]) -> bool { bytes - .get(0) + .first() .map(|byte| byte & 0b10000000 != 0) .unwrap_or(false) } diff --git a/vendor/der/src/asn1/integer/bigint.rs b/vendor/der/src/asn1/integer/bigint.rs deleted file mode 100644 index f896406a6..000000000 --- a/vendor/der/src/asn1/integer/bigint.rs +++ /dev/null @@ -1,152 +0,0 @@ -//! "Big" ASN.1 `INTEGER` types. - -use super::uint; -use crate::{ - asn1::AnyRef, ord::OrdIsValueOrd, ByteSlice, DecodeValue, EncodeValue, Error, ErrorKind, - FixedTag, Header, Length, Reader, Result, Tag, Writer, -}; - -/// "Big" unsigned ASN.1 `INTEGER` type. -/// -/// Provides direct access to the underlying big endian bytes which comprise an -/// unsigned integer value. -/// -/// Intended for use cases like very large integers that are used in -/// cryptographic applications (e.g. keys, signatures). -#[derive(Copy, Clone, Debug, Eq, PartialEq, PartialOrd, Ord)] -pub struct UIntRef<'a> { - /// Inner value - inner: ByteSlice<'a>, -} - -impl<'a> UIntRef<'a> { - /// Create a new [`UIntRef`] from a byte slice. - pub fn new(bytes: &'a [u8]) -> Result<Self> { - let inner = ByteSlice::new(uint::strip_leading_zeroes(bytes)) - .map_err(|_| ErrorKind::Length { tag: Self::TAG })?; - - Ok(Self { inner }) - } - - /// Borrow the inner byte slice which contains the least significant bytes - /// of a big endian integer value with all leading zeros stripped. - pub fn as_bytes(&self) -> &'a [u8] { - self.inner.as_slice() - } - - /// Get the length of this [`UIntRef`] in bytes. - pub fn len(&self) -> Length { - self.inner.len() - } - - /// Is the inner byte slice empty? - pub fn is_empty(&self) -> bool { - self.inner.is_empty() - } -} - -impl<'a> DecodeValue<'a> for UIntRef<'a> { - fn decode_value<R: Reader<'a>>(reader: &mut R, header: Header) -> Result<Self> { - let bytes = ByteSlice::decode_value(reader, header)?.as_slice(); - let result = Self::new(uint::decode_to_slice(bytes)?)?; - - // Ensure we compute the same encoded length as the original any value. - if result.value_len()? != header.length { - return Err(Self::TAG.non_canonical_error()); - } - - Ok(result) - } -} - -impl<'a> EncodeValue for UIntRef<'a> { - fn value_len(&self) -> Result<Length> { - uint::encoded_len(self.inner.as_slice()) - } - - fn encode_value(&self, writer: &mut dyn Writer) -> Result<()> { - // Add leading `0x00` byte if required - if self.value_len()? > self.len() { - writer.write_byte(0)?; - } - - writer.write(self.as_bytes()) - } -} - -impl<'a> From<&UIntRef<'a>> for UIntRef<'a> { - fn from(value: &UIntRef<'a>) -> UIntRef<'a> { - *value - } -} - -impl<'a> TryFrom<AnyRef<'a>> for UIntRef<'a> { - type Error = Error; - - fn try_from(any: AnyRef<'a>) -> Result<UIntRef<'a>> { - any.decode_into() - } -} - -impl<'a> FixedTag for UIntRef<'a> { - const TAG: Tag = Tag::Integer; -} - -impl<'a> OrdIsValueOrd for UIntRef<'a> {} - -#[cfg(test)] -mod tests { - use super::UIntRef; - use crate::{ - asn1::{integer::tests::*, AnyRef}, - Decode, Encode, ErrorKind, SliceWriter, Tag, - }; - - #[test] - fn decode_uint_bytes() { - assert_eq!(&[0], UIntRef::from_der(I0_BYTES).unwrap().as_bytes()); - assert_eq!(&[127], UIntRef::from_der(I127_BYTES).unwrap().as_bytes()); - assert_eq!(&[128], UIntRef::from_der(I128_BYTES).unwrap().as_bytes()); - assert_eq!(&[255], UIntRef::from_der(I255_BYTES).unwrap().as_bytes()); - - assert_eq!( - &[0x01, 0x00], - UIntRef::from_der(I256_BYTES).unwrap().as_bytes() - ); - - assert_eq!( - &[0x7F, 0xFF], - UIntRef::from_der(I32767_BYTES).unwrap().as_bytes() - ); - } - - #[test] - fn encode_uint_bytes() { - for &example in &[ - I0_BYTES, - I127_BYTES, - I128_BYTES, - I255_BYTES, - I256_BYTES, - I32767_BYTES, - ] { - let uint = UIntRef::from_der(example).unwrap(); - - let mut buf = [0u8; 128]; - let mut encoder = SliceWriter::new(&mut buf); - uint.encode(&mut encoder).unwrap(); - - let result = encoder.finish().unwrap(); - assert_eq!(example, result); - } - } - - #[test] - fn reject_oversize_without_extra_zero() { - let err = UIntRef::try_from(AnyRef::new(Tag::Integer, &[0x81]).unwrap()) - .err() - .unwrap(); - - assert_eq!(err.kind(), ErrorKind::Value { tag: Tag::Integer }); - } -} diff --git a/vendor/der/src/asn1/integer/int.rs b/vendor/der/src/asn1/integer/int.rs index a9fe43890..bccc5210c 100644 --- a/vendor/der/src/asn1/integer/int.rs +++ b/vendor/der/src/asn1/integer/int.rs @@ -1,12 +1,310 @@ -//! Support for encoding negative integers +//! Support for encoding signed integers -use super::is_highest_bit_set; -use crate::{ErrorKind, Length, Result, Writer}; +use super::{is_highest_bit_set, uint, value_cmp}; +use crate::{ + ord::OrdIsValueOrd, AnyRef, BytesRef, DecodeValue, EncodeValue, Error, ErrorKind, FixedTag, + Header, Length, Reader, Result, Tag, ValueOrd, Writer, +}; +use core::cmp::Ordering; -/// Decode an unsigned integer of the specified size. +#[cfg(feature = "alloc")] +pub use allocating::Int; + +macro_rules! impl_encoding_traits { + ($($int:ty => $uint:ty),+) => { + $( + impl<'a> DecodeValue<'a> for $int { + fn decode_value<R: Reader<'a>>(reader: &mut R, header: Header) -> Result<Self> { + let mut buf = [0u8; Self::BITS as usize / 8]; + let max_length = u32::from(header.length) as usize; + + if max_length > buf.len() { + return Err(Self::TAG.non_canonical_error()); + } + + let bytes = reader.read_into(&mut buf[..max_length])?; + + let result = if is_highest_bit_set(bytes) { + <$uint>::from_be_bytes(decode_to_array(bytes)?) as $int + } else { + Self::from_be_bytes(uint::decode_to_array(bytes)?) + }; + + // Ensure we compute the same encoded length as the original any value + if header.length != result.value_len()? { + return Err(Self::TAG.non_canonical_error()); + } + + Ok(result) + } + } + + impl EncodeValue for $int { + fn value_len(&self) -> Result<Length> { + if *self < 0 { + negative_encoded_len(&(*self as $uint).to_be_bytes()) + } else { + uint::encoded_len(&self.to_be_bytes()) + } + } + + fn encode_value(&self, writer: &mut impl Writer) -> Result<()> { + if *self < 0 { + encode_bytes(writer, &(*self as $uint).to_be_bytes()) + } else { + uint::encode_bytes(writer, &self.to_be_bytes()) + } + } + } + + impl FixedTag for $int { + const TAG: Tag = Tag::Integer; + } + + impl ValueOrd for $int { + fn value_cmp(&self, other: &Self) -> Result<Ordering> { + value_cmp(*self, *other) + } + } + + impl TryFrom<AnyRef<'_>> for $int { + type Error = Error; + + fn try_from(any: AnyRef<'_>) -> Result<Self> { + any.decode_as() + } + } + )+ + }; +} + +impl_encoding_traits!(i8 => u8, i16 => u16, i32 => u32, i64 => u64, i128 => u128); + +/// Signed arbitrary precision ASN.1 `INTEGER` reference type. +/// +/// Provides direct access to the underlying big endian bytes which comprise +/// an signed integer value. +/// +/// Intended for use cases like very large integers that are used in +/// cryptographic applications (e.g. keys, signatures). +#[derive(Copy, Clone, Debug, Eq, PartialEq, PartialOrd, Ord)] +pub struct IntRef<'a> { + /// Inner value + inner: BytesRef<'a>, +} + +impl<'a> IntRef<'a> { + /// Create a new [`IntRef`] from a byte slice. + pub fn new(bytes: &'a [u8]) -> Result<Self> { + let inner = BytesRef::new(strip_leading_ones(bytes)) + .map_err(|_| ErrorKind::Length { tag: Self::TAG })?; + + Ok(Self { inner }) + } + + /// Borrow the inner byte slice which contains the least significant bytes + /// of a big endian integer value with all leading ones stripped. + pub fn as_bytes(&self) -> &'a [u8] { + self.inner.as_slice() + } + + /// Get the length of this [`IntRef`] in bytes. + pub fn len(&self) -> Length { + self.inner.len() + } + + /// Is the inner byte slice empty? + pub fn is_empty(&self) -> bool { + self.inner.is_empty() + } +} + +impl_any_conversions!(IntRef<'a>, 'a); + +impl<'a> DecodeValue<'a> for IntRef<'a> { + fn decode_value<R: Reader<'a>>(reader: &mut R, header: Header) -> Result<Self> { + let bytes = BytesRef::decode_value(reader, header)?; + validate_canonical(bytes.as_slice())?; + + let result = Self::new(bytes.as_slice())?; + + // Ensure we compute the same encoded length as the original any value. + if result.value_len()? != header.length { + return Err(Self::TAG.non_canonical_error()); + } + + Ok(result) + } +} + +impl<'a> EncodeValue for IntRef<'a> { + fn value_len(&self) -> Result<Length> { + // Signed integers always hold their full encoded form. + Ok(self.inner.len()) + } + + fn encode_value(&self, writer: &mut impl Writer) -> Result<()> { + writer.write(self.as_bytes()) + } +} + +impl<'a> From<&IntRef<'a>> for IntRef<'a> { + fn from(value: &IntRef<'a>) -> IntRef<'a> { + *value + } +} + +impl<'a> FixedTag for IntRef<'a> { + const TAG: Tag = Tag::Integer; +} + +impl<'a> OrdIsValueOrd for IntRef<'a> {} + +#[cfg(feature = "alloc")] +mod allocating { + use super::{strip_leading_ones, validate_canonical, IntRef}; + use crate::{ + asn1::Uint, + ord::OrdIsValueOrd, + referenced::{OwnedToRef, RefToOwned}, + BytesOwned, DecodeValue, EncodeValue, ErrorKind, FixedTag, Header, Length, Reader, Result, + Tag, Writer, + }; + use alloc::vec::Vec; + + /// Signed arbitrary precision ASN.1 `INTEGER` type. + /// + /// Provides heap-allocated storage for big endian bytes which comprise an + /// signed integer value. + /// + /// Intended for use cases like very large integers that are used in + /// cryptographic applications (e.g. keys, signatures). + #[derive(Clone, Debug, Eq, PartialEq, PartialOrd, Ord)] + pub struct Int { + /// Inner value + inner: BytesOwned, + } + + impl Int { + /// Create a new [`Int`] from a byte slice. + pub fn new(bytes: &[u8]) -> Result<Self> { + let inner = BytesOwned::new(strip_leading_ones(bytes)) + .map_err(|_| ErrorKind::Length { tag: Self::TAG })?; + + Ok(Self { inner }) + } + + /// Borrow the inner byte slice which contains the least significant bytes + /// of a big endian integer value with all leading ones stripped. + pub fn as_bytes(&self) -> &[u8] { + self.inner.as_slice() + } + + /// Get the length of this [`Int`] in bytes. + pub fn len(&self) -> Length { + self.inner.len() + } + + /// Is the inner byte slice empty? + pub fn is_empty(&self) -> bool { + self.inner.is_empty() + } + } + + impl_any_conversions!(Int); + + impl<'a> DecodeValue<'a> for Int { + fn decode_value<R: Reader<'a>>(reader: &mut R, header: Header) -> Result<Self> { + let bytes = BytesOwned::decode_value(reader, header)?; + validate_canonical(bytes.as_slice())?; + + let result = Self::new(bytes.as_slice())?; + + // Ensure we compute the same encoded length as the original any value. + if result.value_len()? != header.length { + return Err(Self::TAG.non_canonical_error()); + } + + Ok(result) + } + } + + impl EncodeValue for Int { + fn value_len(&self) -> Result<Length> { + // Signed integers always hold their full encoded form. + Ok(self.inner.len()) + } + + fn encode_value(&self, writer: &mut impl Writer) -> Result<()> { + writer.write(self.as_bytes()) + } + } + + impl<'a> From<&IntRef<'a>> for Int { + fn from(value: &IntRef<'a>) -> Int { + let inner = BytesOwned::new(value.as_bytes()).expect("Invalid Int"); + Int { inner } + } + } + + impl From<Uint> for Int { + fn from(value: Uint) -> Self { + let mut inner: Vec<u8> = Vec::new(); + + // Add leading `0x00` byte if required + if value.value_len().expect("invalid Uint") > value.len() { + inner.push(0x00); + } + + inner.extend_from_slice(value.as_bytes()); + let inner = BytesOwned::new(inner).expect("invalid Uint"); + + Int { inner } + } + } + + impl FixedTag for Int { + const TAG: Tag = Tag::Integer; + } + + impl OrdIsValueOrd for Int {} + + impl<'a> RefToOwned<'a> for IntRef<'a> { + type Owned = Int; + fn ref_to_owned(&self) -> Self::Owned { + let inner = self.inner.ref_to_owned(); + + Int { inner } + } + } + + impl OwnedToRef for Int { + type Borrowed<'a> = IntRef<'a>; + fn owned_to_ref(&self) -> Self::Borrowed<'_> { + let inner = self.inner.owned_to_ref(); + + IntRef { inner } + } + } +} + +/// Ensure `INTEGER` is canonically encoded. +fn validate_canonical(bytes: &[u8]) -> Result<()> { + // The `INTEGER` type always encodes a signed value and we're decoding + // as signed here, so we allow a zero extension or sign extension byte, + // but only as permitted under DER canonicalization. + match bytes { + [] => Err(Tag::Integer.non_canonical_error()), + [0x00, byte, ..] if *byte < 0x80 => Err(Tag::Integer.non_canonical_error()), + [0xFF, byte, ..] if *byte >= 0x80 => Err(Tag::Integer.non_canonical_error()), + _ => Ok(()), + } +} + +/// Decode an signed integer of the specified size. /// /// Returns a byte array of the requested size containing a big endian integer. -pub(super) fn decode_to_array<const N: usize>(bytes: &[u8]) -> Result<[u8; N]> { +fn decode_to_array<const N: usize>(bytes: &[u8]) -> Result<[u8; N]> { match N.checked_sub(bytes.len()) { Some(offset) => { let mut output = [0xFFu8; N]; @@ -27,21 +325,21 @@ pub(super) fn decode_to_array<const N: usize>(bytes: &[u8]) -> Result<[u8; N]> { } /// Encode the given big endian bytes representing an integer as ASN.1 DER. -pub(super) fn encode_bytes<W>(writer: &mut W, bytes: &[u8]) -> Result<()> +fn encode_bytes<W>(writer: &mut W, bytes: &[u8]) -> Result<()> where W: Writer + ?Sized, { writer.write(strip_leading_ones(bytes)) } -/// Get the encoded length for the given unsigned integer serialized as bytes. +/// Get the encoded length for the given **negative** integer serialized as bytes. #[inline] -pub(super) fn encoded_len(bytes: &[u8]) -> Result<Length> { +fn negative_encoded_len(bytes: &[u8]) -> Result<Length> { Length::try_from(strip_leading_ones(bytes).len()) } /// Strip the leading all-ones bytes from the given byte slice. -fn strip_leading_ones(mut bytes: &[u8]) -> &[u8] { +pub(crate) fn strip_leading_ones(mut bytes: &[u8]) -> &[u8] { while let Some((byte, rest)) = bytes.split_first() { if *byte == 0xFF && is_highest_bit_set(rest) { bytes = rest; @@ -53,3 +351,92 @@ fn strip_leading_ones(mut bytes: &[u8]) -> &[u8] { bytes } + +#[cfg(test)] +mod tests { + use super::{validate_canonical, IntRef}; + use crate::{asn1::integer::tests::*, Decode, Encode, SliceWriter}; + + #[test] + fn validate_canonical_ok() { + assert_eq!(validate_canonical(&[0x00]), Ok(())); + assert_eq!(validate_canonical(&[0x01]), Ok(())); + assert_eq!(validate_canonical(&[0x00, 0x80]), Ok(())); + assert_eq!(validate_canonical(&[0xFF, 0x00]), Ok(())); + } + + #[test] + fn validate_canonical_err() { + // Empty integers are always non-canonical. + assert!(validate_canonical(&[]).is_err()); + + // Positives with excessive zero extension are non-canonical. + assert!(validate_canonical(&[0x00, 0x00]).is_err()); + + // Negatives with excessive sign extension are non-canonical. + assert!(validate_canonical(&[0xFF, 0x80]).is_err()); + } + + #[test] + fn decode_intref() { + // Positive numbers decode, but have zero extensions as necessary + // (to distinguish them from negative representations). + assert_eq!(&[0], IntRef::from_der(I0_BYTES).unwrap().as_bytes()); + assert_eq!(&[127], IntRef::from_der(I127_BYTES).unwrap().as_bytes()); + assert_eq!(&[0, 128], IntRef::from_der(I128_BYTES).unwrap().as_bytes()); + assert_eq!(&[0, 255], IntRef::from_der(I255_BYTES).unwrap().as_bytes()); + + assert_eq!( + &[0x01, 0x00], + IntRef::from_der(I256_BYTES).unwrap().as_bytes() + ); + + assert_eq!( + &[0x7F, 0xFF], + IntRef::from_der(I32767_BYTES).unwrap().as_bytes() + ); + + // Negative integers decode. + assert_eq!(&[128], IntRef::from_der(INEG128_BYTES).unwrap().as_bytes()); + assert_eq!( + &[255, 127], + IntRef::from_der(INEG129_BYTES).unwrap().as_bytes() + ); + assert_eq!( + &[128, 0], + IntRef::from_der(INEG32768_BYTES).unwrap().as_bytes() + ); + } + + #[test] + fn encode_intref() { + for &example in &[ + I0_BYTES, + I127_BYTES, + I128_BYTES, + I255_BYTES, + I256_BYTES, + I32767_BYTES, + ] { + let uint = IntRef::from_der(example).unwrap(); + + let mut buf = [0u8; 128]; + let mut encoder = SliceWriter::new(&mut buf); + uint.encode(&mut encoder).unwrap(); + + let result = encoder.finish().unwrap(); + assert_eq!(example, result); + } + + for &example in &[INEG128_BYTES, INEG129_BYTES, INEG32768_BYTES] { + let uint = IntRef::from_der(example).unwrap(); + + let mut buf = [0u8; 128]; + let mut encoder = SliceWriter::new(&mut buf); + uint.encode(&mut encoder).unwrap(); + + let result = encoder.finish().unwrap(); + assert_eq!(example, result); + } + } +} diff --git a/vendor/der/src/asn1/integer/uint.rs b/vendor/der/src/asn1/integer/uint.rs index e45a72f2a..95c6297c2 100644 --- a/vendor/der/src/asn1/integer/uint.rs +++ b/vendor/der/src/asn1/integer/uint.rs @@ -1,6 +1,270 @@ //! Unsigned integer decoders/encoders. -use crate::{Length, Result, Tag, Writer}; +use super::value_cmp; +use crate::{ + ord::OrdIsValueOrd, AnyRef, BytesRef, DecodeValue, EncodeValue, Error, ErrorKind, FixedTag, + Header, Length, Reader, Result, Tag, ValueOrd, Writer, +}; +use core::cmp::Ordering; + +#[cfg(feature = "alloc")] +pub use allocating::Uint; + +macro_rules! impl_encoding_traits { + ($($uint:ty),+) => { + $( + impl<'a> DecodeValue<'a> for $uint { + fn decode_value<R: Reader<'a>>(reader: &mut R, header: Header) -> Result<Self> { + // Integers always encodes as a signed value, unsigned gets a leading 0x00 that + // needs to be stripped off. We need to provide room for it. + const UNSIGNED_HEADROOM: usize = 1; + + let mut buf = [0u8; (Self::BITS as usize / 8) + UNSIGNED_HEADROOM]; + let max_length = u32::from(header.length) as usize; + + if max_length > buf.len() { + return Err(Self::TAG.non_canonical_error()); + } + + let bytes = reader.read_into(&mut buf[..max_length])?; + + let result = Self::from_be_bytes(decode_to_array(bytes)?); + + // Ensure we compute the same encoded length as the original any value + if header.length != result.value_len()? { + return Err(Self::TAG.non_canonical_error()); + } + + Ok(result) + } + } + + impl EncodeValue for $uint { + fn value_len(&self) -> Result<Length> { + encoded_len(&self.to_be_bytes()) + } + + fn encode_value(&self, writer: &mut impl Writer) -> Result<()> { + encode_bytes(writer, &self.to_be_bytes()) + } + } + + impl FixedTag for $uint { + const TAG: Tag = Tag::Integer; + } + + impl ValueOrd for $uint { + fn value_cmp(&self, other: &Self) -> Result<Ordering> { + value_cmp(*self, *other) + } + } + + impl TryFrom<AnyRef<'_>> for $uint { + type Error = Error; + + fn try_from(any: AnyRef<'_>) -> Result<Self> { + any.decode_as() + } + } + )+ + }; +} + +impl_encoding_traits!(u8, u16, u32, u64, u128); + +/// Unsigned arbitrary precision ASN.1 `INTEGER` reference type. +/// +/// Provides direct access to the underlying big endian bytes which comprise an +/// unsigned integer value. +/// +/// Intended for use cases like very large integers that are used in +/// cryptographic applications (e.g. keys, signatures). +#[derive(Copy, Clone, Debug, Eq, PartialEq, PartialOrd, Ord)] +pub struct UintRef<'a> { + /// Inner value + inner: BytesRef<'a>, +} + +impl<'a> UintRef<'a> { + /// Create a new [`UintRef`] from a byte slice. + pub fn new(bytes: &'a [u8]) -> Result<Self> { + let inner = BytesRef::new(strip_leading_zeroes(bytes)) + .map_err(|_| ErrorKind::Length { tag: Self::TAG })?; + + Ok(Self { inner }) + } + + /// Borrow the inner byte slice which contains the least significant bytes + /// of a big endian integer value with all leading zeros stripped. + pub fn as_bytes(&self) -> &'a [u8] { + self.inner.as_slice() + } + + /// Get the length of this [`UintRef`] in bytes. + pub fn len(&self) -> Length { + self.inner.len() + } + + /// Is the inner byte slice empty? + pub fn is_empty(&self) -> bool { + self.inner.is_empty() + } +} + +impl_any_conversions!(UintRef<'a>, 'a); + +impl<'a> DecodeValue<'a> for UintRef<'a> { + fn decode_value<R: Reader<'a>>(reader: &mut R, header: Header) -> Result<Self> { + let bytes = BytesRef::decode_value(reader, header)?.as_slice(); + let result = Self::new(decode_to_slice(bytes)?)?; + + // Ensure we compute the same encoded length as the original any value. + if result.value_len()? != header.length { + return Err(Self::TAG.non_canonical_error()); + } + + Ok(result) + } +} + +impl<'a> EncodeValue for UintRef<'a> { + fn value_len(&self) -> Result<Length> { + encoded_len(self.inner.as_slice()) + } + + fn encode_value(&self, writer: &mut impl Writer) -> Result<()> { + // Add leading `0x00` byte if required + if self.value_len()? > self.len() { + writer.write_byte(0)?; + } + + writer.write(self.as_bytes()) + } +} + +impl<'a> From<&UintRef<'a>> for UintRef<'a> { + fn from(value: &UintRef<'a>) -> UintRef<'a> { + *value + } +} + +impl<'a> FixedTag for UintRef<'a> { + const TAG: Tag = Tag::Integer; +} + +impl<'a> OrdIsValueOrd for UintRef<'a> {} + +#[cfg(feature = "alloc")] +mod allocating { + use super::{decode_to_slice, encoded_len, strip_leading_zeroes, UintRef}; + use crate::{ + ord::OrdIsValueOrd, + referenced::{OwnedToRef, RefToOwned}, + BytesOwned, DecodeValue, EncodeValue, ErrorKind, FixedTag, Header, Length, Reader, Result, + Tag, Writer, + }; + + /// Unsigned arbitrary precision ASN.1 `INTEGER` type. + /// + /// Provides heap-allocated storage for big endian bytes which comprise an + /// unsigned integer value. + /// + /// Intended for use cases like very large integers that are used in + /// cryptographic applications (e.g. keys, signatures). + #[derive(Clone, Debug, Eq, PartialEq, PartialOrd, Ord)] + pub struct Uint { + /// Inner value + inner: BytesOwned, + } + + impl Uint { + /// Create a new [`Uint`] from a byte slice. + pub fn new(bytes: &[u8]) -> Result<Self> { + let inner = BytesOwned::new(strip_leading_zeroes(bytes)) + .map_err(|_| ErrorKind::Length { tag: Self::TAG })?; + + Ok(Self { inner }) + } + + /// Borrow the inner byte slice which contains the least significant bytes + /// of a big endian integer value with all leading zeros stripped. + pub fn as_bytes(&self) -> &[u8] { + self.inner.as_slice() + } + + /// Get the length of this [`Uint`] in bytes. + pub fn len(&self) -> Length { + self.inner.len() + } + + /// Is the inner byte slice empty? + pub fn is_empty(&self) -> bool { + self.inner.is_empty() + } + } + + impl_any_conversions!(Uint); + + impl<'a> DecodeValue<'a> for Uint { + fn decode_value<R: Reader<'a>>(reader: &mut R, header: Header) -> Result<Self> { + let bytes = BytesOwned::decode_value(reader, header)?; + let result = Self::new(decode_to_slice(bytes.as_slice())?)?; + + // Ensure we compute the same encoded length as the original any value. + if result.value_len()? != header.length { + return Err(Self::TAG.non_canonical_error()); + } + + Ok(result) + } + } + + impl EncodeValue for Uint { + fn value_len(&self) -> Result<Length> { + encoded_len(self.inner.as_slice()) + } + + fn encode_value(&self, writer: &mut impl Writer) -> Result<()> { + // Add leading `0x00` byte if required + if self.value_len()? > self.len() { + writer.write_byte(0)?; + } + + writer.write(self.as_bytes()) + } + } + + impl<'a> From<&UintRef<'a>> for Uint { + fn from(value: &UintRef<'a>) -> Uint { + let inner = BytesOwned::new(value.as_bytes()).expect("Invalid Uint"); + Uint { inner } + } + } + + impl FixedTag for Uint { + const TAG: Tag = Tag::Integer; + } + + impl OrdIsValueOrd for Uint {} + + impl<'a> RefToOwned<'a> for UintRef<'a> { + type Owned = Uint; + fn ref_to_owned(&self) -> Self::Owned { + let inner = self.inner.ref_to_owned(); + + Uint { inner } + } + } + + impl OwnedToRef for Uint { + type Borrowed<'a> = UintRef<'a>; + fn owned_to_ref(&self) -> Self::Borrowed<'_> { + let inner = self.inner.owned_to_ref(); + + UintRef { inner } + } + } +} /// Decode an unsigned integer into a big endian byte slice with all leading /// zeroes removed. @@ -75,13 +339,13 @@ pub(crate) fn strip_leading_zeroes(mut bytes: &[u8]) -> &[u8] { /// Does the given integer need a leading zero? fn needs_leading_zero(bytes: &[u8]) -> bool { - matches!(bytes.get(0), Some(byte) if *byte >= 0x80) + matches!(bytes.first(), Some(byte) if *byte >= 0x80) } #[cfg(test)] mod tests { - use super::decode_to_array; - use crate::{ErrorKind, Tag}; + use super::{decode_to_array, UintRef}; + use crate::{asn1::integer::tests::*, AnyRef, Decode, Encode, ErrorKind, SliceWriter, Tag}; #[test] fn decode_to_array_no_leading_zero() { @@ -113,4 +377,52 @@ mod tests { let err = decode_to_array::<1>(&[1, 2, 3]).err().unwrap(); assert_eq!(err.kind(), ErrorKind::Length { tag: Tag::Integer }); } + + #[test] + fn decode_uintref() { + assert_eq!(&[0], UintRef::from_der(I0_BYTES).unwrap().as_bytes()); + assert_eq!(&[127], UintRef::from_der(I127_BYTES).unwrap().as_bytes()); + assert_eq!(&[128], UintRef::from_der(I128_BYTES).unwrap().as_bytes()); + assert_eq!(&[255], UintRef::from_der(I255_BYTES).unwrap().as_bytes()); + + assert_eq!( + &[0x01, 0x00], + UintRef::from_der(I256_BYTES).unwrap().as_bytes() + ); + + assert_eq!( + &[0x7F, 0xFF], + UintRef::from_der(I32767_BYTES).unwrap().as_bytes() + ); + } + + #[test] + fn encode_uintref() { + for &example in &[ + I0_BYTES, + I127_BYTES, + I128_BYTES, + I255_BYTES, + I256_BYTES, + I32767_BYTES, + ] { + let uint = UintRef::from_der(example).unwrap(); + + let mut buf = [0u8; 128]; + let mut encoder = SliceWriter::new(&mut buf); + uint.encode(&mut encoder).unwrap(); + + let result = encoder.finish().unwrap(); + assert_eq!(example, result); + } + } + + #[test] + fn reject_oversize_without_extra_zero() { + let err = UintRef::try_from(AnyRef::new(Tag::Integer, &[0x81]).unwrap()) + .err() + .unwrap(); + + assert_eq!(err.kind(), ErrorKind::Value { tag: Tag::Integer }); + } } diff --git a/vendor/der/src/asn1/internal_macros.rs b/vendor/der/src/asn1/internal_macros.rs new file mode 100644 index 000000000..10ad99d23 --- /dev/null +++ b/vendor/der/src/asn1/internal_macros.rs @@ -0,0 +1,75 @@ +macro_rules! impl_any_conversions { + ($type: ty) => { + impl_any_conversions!($type, ); + }; + ($type: ty, $($li: lifetime)?) => { + impl<'__der: $($li),*, $($li),*> TryFrom<$crate::AnyRef<'__der>> for $type { + type Error = $crate::Error; + + fn try_from(any: $crate::AnyRef<'__der>) -> Result<$type> { + any.decode_as() + } + } + + #[cfg(feature = "alloc")] + impl<'__der: $($li),*, $($li),*> TryFrom<&'__der $crate::Any> for $type { + type Error = $crate::Error; + + fn try_from(any: &'__der $crate::Any) -> Result<$type> { + any.decode_as() + } + } + }; +} + +macro_rules! impl_string_type { + ($type: ty, $($li: lifetime)?) => { + impl_any_conversions!($type, $($li),*); + + mod __impl_string { + use super::*; + + use crate::{ + ord::OrdIsValueOrd, BytesRef, DecodeValue, EncodeValue, Header, Length, Reader, + Result, Writer, + }; + use core::{fmt, str}; + + impl<$($li),*> AsRef<str> for $type { + fn as_ref(&self) -> &str { + self.as_str() + } + } + + impl<$($li),*> AsRef<[u8]> for $type { + fn as_ref(&self) -> &[u8] { + self.as_bytes() + } + } + + impl<'__der: $($li),*, $($li),*> DecodeValue<'__der> for $type { + fn decode_value<R: Reader<'__der>>(reader: &mut R, header: Header) -> Result<Self> { + Self::new(BytesRef::decode_value(reader, header)?.as_slice()) + } + } + + impl<$($li),*> EncodeValue for $type { + fn value_len(&self) -> Result<Length> { + self.inner.value_len() + } + + fn encode_value(&self, writer: &mut impl Writer) -> Result<()> { + self.inner.encode_value(writer) + } + } + + impl<$($li),*> OrdIsValueOrd for $type {} + + impl<$($li),*> fmt::Display for $type { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.write_str(self.as_str()) + } + } + } + }; +} diff --git a/vendor/der/src/asn1/null.rs b/vendor/der/src/asn1/null.rs index e87729f18..7c1e2058a 100644 --- a/vendor/der/src/asn1/null.rs +++ b/vendor/der/src/asn1/null.rs @@ -1,7 +1,7 @@ //! ASN.1 `NULL` support. use crate::{ - asn1::AnyRef, ord::OrdIsValueOrd, ByteSlice, DecodeValue, EncodeValue, Error, ErrorKind, + asn1::AnyRef, ord::OrdIsValueOrd, BytesRef, DecodeValue, EncodeValue, Error, ErrorKind, FixedTag, Header, Length, Reader, Result, Tag, Writer, }; @@ -9,6 +9,8 @@ use crate::{ #[derive(Copy, Clone, Debug, Eq, PartialEq, PartialOrd, Ord)] pub struct Null; +impl_any_conversions!(Null); + impl<'a> DecodeValue<'a> for Null { fn decode_value<R: Reader<'a>>(reader: &mut R, header: Header) -> Result<Self> { if header.length.is_zero() { @@ -24,7 +26,7 @@ impl EncodeValue for Null { Ok(Length::ZERO) } - fn encode_value(&self, _writer: &mut dyn Writer) -> Result<()> { + fn encode_value(&self, _writer: &mut impl Writer) -> Result<()> { Ok(()) } } @@ -37,15 +39,7 @@ impl OrdIsValueOrd for Null {} impl<'a> From<Null> for AnyRef<'a> { fn from(_: Null) -> AnyRef<'a> { - AnyRef::from_tag_and_value(Tag::Null, ByteSlice::default()) - } -} - -impl TryFrom<AnyRef<'_>> for Null { - type Error = Error; - - fn try_from(any: AnyRef<'_>) -> Result<Null> { - any.decode_into() + AnyRef::from_tag_and_value(Tag::Null, BytesRef::default()) } } @@ -75,7 +69,7 @@ impl EncodeValue for () { Ok(Length::ZERO) } - fn encode_value(&self, _writer: &mut dyn Writer) -> Result<()> { + fn encode_value(&self, _writer: &mut impl Writer) -> Result<()> { Ok(()) } } diff --git a/vendor/der/src/asn1/octet_string.rs b/vendor/der/src/asn1/octet_string.rs index 6f5b91a3d..d5eb0dd0f 100644 --- a/vendor/der/src/asn1/octet_string.rs +++ b/vendor/der/src/asn1/octet_string.rs @@ -1,13 +1,10 @@ //! ASN.1 `OCTET STRING` support. use crate::{ - asn1::AnyRef, ord::OrdIsValueOrd, ByteSlice, DecodeValue, EncodeValue, Error, ErrorKind, + asn1::AnyRef, ord::OrdIsValueOrd, BytesRef, Decode, DecodeValue, EncodeValue, ErrorKind, FixedTag, Header, Length, Reader, Result, Tag, Writer, }; -#[cfg(feature = "alloc")] -use alloc::vec::Vec; - /// ASN.1 `OCTET STRING` type: borrowed form. /// /// Octet strings represent contiguous sequences of octets, a.k.a. bytes. @@ -16,13 +13,13 @@ use alloc::vec::Vec; #[derive(Copy, Clone, Debug, Eq, PartialEq, PartialOrd, Ord)] pub struct OctetStringRef<'a> { /// Inner value - inner: ByteSlice<'a>, + inner: BytesRef<'a>, } impl<'a> OctetStringRef<'a> { /// Create a new ASN.1 `OCTET STRING` from a byte slice. pub fn new(slice: &'a [u8]) -> Result<Self> { - ByteSlice::new(slice) + BytesRef::new(slice) .map(|inner| Self { inner }) .map_err(|_| ErrorKind::Length { tag: Self::TAG }.into()) } @@ -41,8 +38,15 @@ impl<'a> OctetStringRef<'a> { pub fn is_empty(&self) -> bool { self.inner.is_empty() } + + /// Parse `T` from this `OCTET STRING`'s contents. + pub fn decode_into<T: Decode<'a>>(&self) -> Result<T> { + Decode::from_der(self.as_bytes()) + } } +impl_any_conversions!(OctetStringRef<'a>, 'a); + impl AsRef<[u8]> for OctetStringRef<'_> { fn as_ref(&self) -> &[u8] { self.as_bytes() @@ -51,7 +55,7 @@ impl AsRef<[u8]> for OctetStringRef<'_> { impl<'a> DecodeValue<'a> for OctetStringRef<'a> { fn decode_value<R: Reader<'a>>(reader: &mut R, header: Header) -> Result<Self> { - let inner = ByteSlice::decode_value(reader, header)?; + let inner = BytesRef::decode_value(reader, header)?; Ok(Self { inner }) } } @@ -61,7 +65,7 @@ impl EncodeValue for OctetStringRef<'_> { self.inner.value_len() } - fn encode_value(&self, writer: &mut dyn Writer) -> Result<()> { + fn encode_value(&self, writer: &mut impl Writer) -> Result<()> { self.inner.encode_value(writer) } } @@ -78,14 +82,6 @@ impl<'a> From<&OctetStringRef<'a>> for OctetStringRef<'a> { } } -impl<'a> TryFrom<AnyRef<'a>> for OctetStringRef<'a> { - type Error = Error; - - fn try_from(any: AnyRef<'a>) -> Result<OctetStringRef<'a>> { - any.decode_into() - } -} - impl<'a> From<OctetStringRef<'a>> for AnyRef<'a> { fn from(octet_string: OctetStringRef<'a>) -> AnyRef<'a> { AnyRef::from_tag_and_value(Tag::OctetString, octet_string.inner) @@ -98,85 +94,137 @@ impl<'a> From<OctetStringRef<'a>> for &'a [u8] { } } -/// ASN.1 `OCTET STRING` type: owned form.. -/// -/// Octet strings represent contiguous sequences of octets, a.k.a. bytes. -/// -/// This type provides the same functionality as [`OctetStringRef`] but owns -/// the backing data. #[cfg(feature = "alloc")] -#[cfg_attr(docsrs, doc(cfg(feature = "alloc")))] -#[derive(Clone, Debug, Eq, PartialEq, PartialOrd, Ord)] -pub struct OctetString { - /// Bitstring represented as a slice of bytes. - inner: Vec<u8>, -} +pub use self::allocating::OctetString; #[cfg(feature = "alloc")] -impl OctetString { - /// Create a new ASN.1 `OCTET STRING`. - pub fn new(bytes: impl Into<Vec<u8>>) -> Result<Self> { - let inner = bytes.into(); +mod allocating { + use super::*; + use crate::referenced::*; + use alloc::vec::Vec; - // Ensure the bytes parse successfully as an `OctetStringRef` - OctetStringRef::new(&inner)?; + /// ASN.1 `OCTET STRING` type: owned form.. + /// + /// Octet strings represent contiguous sequences of octets, a.k.a. bytes. + /// + /// This type provides the same functionality as [`OctetStringRef`] but owns + /// the backing data. + #[derive(Clone, Debug, Eq, PartialEq, PartialOrd, Ord)] + pub struct OctetString { + /// Bitstring represented as a slice of bytes. + inner: Vec<u8>, + } - Ok(Self { inner }) + impl OctetString { + /// Create a new ASN.1 `OCTET STRING`. + pub fn new(bytes: impl Into<Vec<u8>>) -> Result<Self> { + let inner = bytes.into(); + + // Ensure the bytes parse successfully as an `OctetStringRef` + OctetStringRef::new(&inner)?; + + Ok(Self { inner }) + } + + /// Borrow the inner byte slice. + pub fn as_bytes(&self) -> &[u8] { + self.inner.as_slice() + } + + /// Take ownership of the octet string. + pub fn into_bytes(self) -> Vec<u8> { + self.inner + } + + /// Get the length of the inner byte slice. + pub fn len(&self) -> Length { + self.value_len().expect("invalid OCTET STRING length") + } + + /// Is the inner byte slice empty? + pub fn is_empty(&self) -> bool { + self.inner.is_empty() + } } - /// Borrow the inner byte slice. - pub fn as_bytes(&self) -> &[u8] { - self.inner.as_slice() + impl_any_conversions!(OctetString); + + impl AsRef<[u8]> for OctetString { + fn as_ref(&self) -> &[u8] { + self.as_bytes() + } } - /// Get the length of the inner byte slice. - pub fn len(&self) -> Length { - self.value_len().expect("invalid OCTET STRING length") + impl<'a> DecodeValue<'a> for OctetString { + fn decode_value<R: Reader<'a>>(reader: &mut R, header: Header) -> Result<Self> { + Self::new(reader.read_vec(header.length)?) + } } - /// Is the inner byte slice empty? - pub fn is_empty(&self) -> bool { - self.inner.is_empty() + impl EncodeValue for OctetString { + fn value_len(&self) -> Result<Length> { + self.inner.len().try_into() + } + + fn encode_value(&self, writer: &mut impl Writer) -> Result<()> { + writer.write(&self.inner) + } } -} -#[cfg(feature = "alloc")] -impl AsRef<[u8]> for OctetString { - fn as_ref(&self) -> &[u8] { - self.as_bytes() + impl FixedTag for OctetString { + const TAG: Tag = Tag::OctetString; } -} -#[cfg(feature = "alloc")] -impl<'a> DecodeValue<'a> for OctetString { - fn decode_value<R: Reader<'a>>(reader: &mut R, header: Header) -> Result<Self> { - Self::new(reader.read_vec(header.length)?) + impl<'a> From<&'a OctetString> for OctetStringRef<'a> { + fn from(octet_string: &'a OctetString) -> OctetStringRef<'a> { + // Ensured to parse successfully in constructor + OctetStringRef::new(&octet_string.inner).expect("invalid OCTET STRING") + } } -} -#[cfg(feature = "alloc")] -impl EncodeValue for OctetString { - fn value_len(&self) -> Result<Length> { - self.inner.len().try_into() + impl OrdIsValueOrd for OctetString {} + + impl<'a> RefToOwned<'a> for OctetStringRef<'a> { + type Owned = OctetString; + fn ref_to_owned(&self) -> Self::Owned { + OctetString { + inner: Vec::from(self.inner.as_slice()), + } + } } - fn encode_value(&self, writer: &mut dyn Writer) -> Result<()> { - writer.write(&self.inner) + impl OwnedToRef for OctetString { + type Borrowed<'a> = OctetStringRef<'a>; + fn owned_to_ref(&self) -> Self::Borrowed<'_> { + self.into() + } } -} -#[cfg(feature = "alloc")] -impl FixedTag for OctetString { - const TAG: Tag = Tag::OctetString; -} + // Implement by hand because the derive would create invalid values. + // Use the constructor to create a valid value. + #[cfg(feature = "arbitrary")] + impl<'a> arbitrary::Arbitrary<'a> for OctetString { + fn arbitrary(u: &mut arbitrary::Unstructured<'a>) -> arbitrary::Result<Self> { + Self::new(Vec::arbitrary(u)?).map_err(|_| arbitrary::Error::IncorrectFormat) + } -#[cfg(feature = "alloc")] -impl<'a> From<&'a OctetString> for OctetStringRef<'a> { - fn from(octet_string: &'a OctetString) -> OctetStringRef<'a> { - // Ensured to parse successfully in constructor - OctetStringRef::new(&octet_string.inner).expect("invalid OCTET STRING") + fn size_hint(depth: usize) -> (usize, Option<usize>) { + arbitrary::size_hint::and(u8::size_hint(depth), Vec::<u8>::size_hint(depth)) + } } } -#[cfg(feature = "alloc")] -impl OrdIsValueOrd for OctetString {} +#[cfg(test)] +mod tests { + use crate::asn1::{OctetStringRef, PrintableStringRef}; + + #[test] + fn octet_string_decode_into() { + // PrintableString "hi" + let der = b"\x13\x02\x68\x69"; + let oct = OctetStringRef::new(der).unwrap(); + + let res = oct.decode_into::<PrintableStringRef<'_>>().unwrap(); + assert_eq!(AsRef::<str>::as_ref(&res), "hi"); + } +} diff --git a/vendor/der/src/asn1/oid.rs b/vendor/der/src/asn1/oid.rs index 8b287183d..3daa452b2 100644 --- a/vendor/der/src/asn1/oid.rs +++ b/vendor/der/src/asn1/oid.rs @@ -6,6 +6,9 @@ use crate::{ }; use const_oid::ObjectIdentifier; +#[cfg(feature = "alloc")] +use super::Any; + impl<'a> DecodeValue<'a> for ObjectIdentifier { fn decode_value<R: Reader<'a>>(reader: &mut R, header: Header) -> Result<Self> { let mut buf = [0u8; ObjectIdentifier::MAX_SIZE]; @@ -24,7 +27,7 @@ impl EncodeValue for ObjectIdentifier { Length::try_from(self.as_bytes().len()) } - fn encode_value(&self, writer: &mut dyn Writer) -> Result<()> { + fn encode_value(&self, writer: &mut impl Writer) -> Result<()> { writer.write(self.as_bytes()) } } @@ -50,6 +53,13 @@ impl<'a> From<&'a ObjectIdentifier> for AnyRef<'a> { } } +#[cfg(feature = "alloc")] +impl From<ObjectIdentifier> for Any { + fn from(oid: ObjectIdentifier) -> Any { + AnyRef::from(&oid).into() + } +} + impl TryFrom<AnyRef<'_>> for ObjectIdentifier { type Error = Error; diff --git a/vendor/der/src/asn1/optional.rs b/vendor/der/src/asn1/optional.rs index a9b923ccc..ecda4f8ec 100644 --- a/vendor/der/src/asn1/optional.rs +++ b/vendor/der/src/asn1/optional.rs @@ -41,7 +41,7 @@ where (&self).encoded_len() } - fn encode(&self, writer: &mut dyn Writer) -> Result<()> { + fn encode(&self, writer: &mut impl Writer) -> Result<()> { (&self).encode(writer) } } @@ -57,7 +57,7 @@ where } } - fn encode(&self, encoder: &mut dyn Writer) -> Result<()> { + fn encode(&self, encoder: &mut impl Writer) -> Result<()> { match self { Some(encodable) => encodable.encode(encoder), None => Ok(()), diff --git a/vendor/der/src/asn1/printable_string.rs b/vendor/der/src/asn1/printable_string.rs index d48f90f09..651c5ba23 100644 --- a/vendor/der/src/asn1/printable_string.rs +++ b/vendor/der/src/asn1/printable_string.rs @@ -1,10 +1,26 @@ //! ASN.1 `PrintableString` support. -use crate::{ - asn1::AnyRef, ord::OrdIsValueOrd, ByteSlice, DecodeValue, EncodeValue, Error, FixedTag, Header, - Length, Reader, Result, StrSlice, Tag, Writer, -}; -use core::{fmt, ops::Deref, str}; +use crate::{asn1::AnyRef, FixedTag, Result, StrRef, Tag}; +use core::{fmt, ops::Deref}; + +macro_rules! impl_printable_string { + ($type: ty) => { + impl_printable_string!($type,); + }; + ($type: ty, $($li: lifetime)?) => { + impl_string_type!($type, $($li),*); + + impl<$($li),*> FixedTag for $type { + const TAG: Tag = Tag::PrintableString; + } + + impl<$($li),*> fmt::Debug for $type { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + write!(f, "PrintableString({:?})", self.as_str()) + } + } + }; +} /// ASN.1 `PrintableString` type. /// @@ -38,7 +54,7 @@ use core::{fmt, ops::Deref, str}; #[derive(Copy, Clone, Eq, PartialEq, PartialOrd, Ord)] pub struct PrintableStringRef<'a> { /// Inner value - inner: StrSlice<'a>, + inner: StrRef<'a>, } impl<'a> PrintableStringRef<'a> { @@ -71,83 +87,138 @@ impl<'a> PrintableStringRef<'a> { } } - StrSlice::from_bytes(input) + StrRef::from_bytes(input) .map(|inner| Self { inner }) .map_err(|_| Self::TAG.value_error()) } } +impl_printable_string!(PrintableStringRef<'a>, 'a); + impl<'a> Deref for PrintableStringRef<'a> { - type Target = StrSlice<'a>; + type Target = StrRef<'a>; fn deref(&self) -> &Self::Target { &self.inner } } - -impl AsRef<str> for PrintableStringRef<'_> { - fn as_ref(&self) -> &str { - self.as_str() +impl<'a> From<&PrintableStringRef<'a>> for PrintableStringRef<'a> { + fn from(value: &PrintableStringRef<'a>) -> PrintableStringRef<'a> { + *value } } -impl AsRef<[u8]> for PrintableStringRef<'_> { - fn as_ref(&self) -> &[u8] { - self.as_bytes() +impl<'a> From<PrintableStringRef<'a>> for AnyRef<'a> { + fn from(printable_string: PrintableStringRef<'a>) -> AnyRef<'a> { + AnyRef::from_tag_and_value(Tag::PrintableString, printable_string.inner.into()) } } -impl<'a> DecodeValue<'a> for PrintableStringRef<'a> { - fn decode_value<R: Reader<'a>>(reader: &mut R, header: Header) -> Result<Self> { - Self::new(ByteSlice::decode_value(reader, header)?.as_slice()) - } -} +#[cfg(feature = "alloc")] +pub use self::allocation::PrintableString; -impl<'a> EncodeValue for PrintableStringRef<'a> { - fn value_len(&self) -> Result<Length> { - self.inner.value_len() +#[cfg(feature = "alloc")] +mod allocation { + use super::PrintableStringRef; + + use crate::{ + asn1::AnyRef, + referenced::{OwnedToRef, RefToOwned}, + BytesRef, FixedTag, Result, StrOwned, Tag, + }; + use core::{fmt, ops::Deref}; + + /// ASN.1 `PrintableString` type. + /// + /// Supports a subset the ASCII character set (described below). + /// + /// For UTF-8, use [`Utf8StringRef`][`crate::asn1::Utf8StringRef`] instead. + /// For the full ASCII character set, use + /// [`Ia5StringRef`][`crate::asn1::Ia5StringRef`]. + /// + /// # Supported characters + /// + /// The following ASCII characters/ranges are supported: + /// + /// - `A..Z` + /// - `a..z` + /// - `0..9` + /// - "` `" (i.e. space) + /// - `\` + /// - `(` + /// - `)` + /// - `+` + /// - `,` + /// - `-` + /// - `.` + /// - `/` + /// - `:` + /// - `=` + /// - `?` + #[derive(Clone, Eq, PartialEq, PartialOrd, Ord)] + pub struct PrintableString { + /// Inner value + inner: StrOwned, } - fn encode_value(&self, writer: &mut dyn Writer) -> Result<()> { - self.inner.encode_value(writer) + impl PrintableString { + /// Create a new ASN.1 `PrintableString`. + pub fn new<T>(input: &T) -> Result<Self> + where + T: AsRef<[u8]> + ?Sized, + { + let input = input.as_ref(); + PrintableStringRef::new(input)?; + + StrOwned::from_bytes(input) + .map(|inner| Self { inner }) + .map_err(|_| Self::TAG.value_error()) + } } -} -impl FixedTag for PrintableStringRef<'_> { - const TAG: Tag = Tag::PrintableString; -} + impl_printable_string!(PrintableString); -impl OrdIsValueOrd for PrintableStringRef<'_> {} + impl Deref for PrintableString { + type Target = StrOwned; -impl<'a> From<&PrintableStringRef<'a>> for PrintableStringRef<'a> { - fn from(value: &PrintableStringRef<'a>) -> PrintableStringRef<'a> { - *value + fn deref(&self) -> &Self::Target { + &self.inner + } } -} - -impl<'a> TryFrom<AnyRef<'a>> for PrintableStringRef<'a> { - type Error = Error; - fn try_from(any: AnyRef<'a>) -> Result<PrintableStringRef<'a>> { - any.decode_into() + impl<'a> From<PrintableStringRef<'a>> for PrintableString { + fn from(value: PrintableStringRef<'a>) -> PrintableString { + let inner = + StrOwned::from_bytes(value.inner.as_bytes()).expect("Invalid PrintableString"); + Self { inner } + } } -} -impl<'a> From<PrintableStringRef<'a>> for AnyRef<'a> { - fn from(printable_string: PrintableStringRef<'a>) -> AnyRef<'a> { - AnyRef::from_tag_and_value(Tag::PrintableString, printable_string.inner.into()) + impl<'a> From<&'a PrintableString> for AnyRef<'a> { + fn from(printable_string: &'a PrintableString) -> AnyRef<'a> { + AnyRef::from_tag_and_value( + Tag::PrintableString, + BytesRef::new(printable_string.inner.as_bytes()).expect("Invalid PrintableString"), + ) + } } -} -impl<'a> fmt::Display for PrintableStringRef<'a> { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - f.write_str(self.as_str()) + impl<'a> RefToOwned<'a> for PrintableStringRef<'a> { + type Owned = PrintableString; + fn ref_to_owned(&self) -> Self::Owned { + PrintableString { + inner: self.inner.ref_to_owned(), + } + } } -} -impl<'a> fmt::Debug for PrintableStringRef<'a> { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - write!(f, "PrintableString({:?})", self.as_str()) + impl OwnedToRef for PrintableString { + type Borrowed<'a> = PrintableStringRef<'a>; + fn owned_to_ref(&self) -> Self::Borrowed<'_> { + PrintableStringRef { + inner: self.inner.owned_to_ref(), + } + } } } diff --git a/vendor/der/src/asn1/real.rs b/vendor/der/src/asn1/real.rs index f872d2d0b..b9f2e67f5 100644 --- a/vendor/der/src/asn1/real.rs +++ b/vendor/der/src/asn1/real.rs @@ -8,22 +8,21 @@ )] use crate::{ - str_slice::StrSlice, ByteSlice, DecodeValue, EncodeValue, FixedTag, Header, Length, Reader, - Result, Tag, Writer, + BytesRef, DecodeValue, EncodeValue, FixedTag, Header, Length, Reader, Result, StrRef, Tag, + Writer, }; use super::integer::uint::strip_leading_zeroes; -#[cfg_attr(docsrs, doc(cfg(feature = "real")))] impl<'a> DecodeValue<'a> for f64 { fn decode_value<R: Reader<'a>>(reader: &mut R, header: Header) -> Result<Self> { - let bytes = ByteSlice::decode_value(reader, header)?.as_slice(); + let bytes = BytesRef::decode_value(reader, header)?.as_slice(); if header.length == Length::ZERO { Ok(0.0) } else if is_nth_bit_one::<7>(bytes) { // Binary encoding from section 8.5.7 applies - let sign: u64 = if is_nth_bit_one::<6>(bytes) { 1 } else { 0 }; + let sign: u64 = u64::from(is_nth_bit_one::<6>(bytes)); // Section 8.5.7.2: Check the base -- the DER specs say that only base 2 should be supported in DER let base = mnth_bits_to_u8::<5, 4>(bytes); @@ -74,7 +73,7 @@ impl<'a> DecodeValue<'a> for f64 { _ => Err(Tag::Real.value_error()), } } else { - let astr = StrSlice::from_bytes(&bytes[1..])?; + let astr = StrRef::from_bytes(&bytes[1..])?; match astr.inner.parse::<f64>() { Ok(val) => Ok(val), // Real related error: encoding not supported or malformed @@ -84,7 +83,6 @@ impl<'a> DecodeValue<'a> for f64 { } } -#[cfg_attr(docsrs, doc(cfg(feature = "real")))] impl EncodeValue for f64 { fn value_len(&self) -> Result<Length> { if self.is_sign_positive() && (*self) < f64::MIN_POSITIVE { @@ -120,7 +118,7 @@ impl EncodeValue for f64 { } } - fn encode_value(&self, writer: &mut dyn Writer) -> Result<()> { + fn encode_value(&self, writer: &mut impl Writer) -> Result<()> { // Check if special value // Encode zero first, if it's zero // Special value from section 8.5.9 if non zero @@ -194,7 +192,6 @@ impl EncodeValue for f64 { } } -#[cfg_attr(docsrs, doc(cfg(feature = "real")))] impl FixedTag for f64 { const TAG: Tag = Tag::Real; } @@ -204,7 +201,7 @@ impl FixedTag for f64 { pub(crate) fn is_nth_bit_one<const N: usize>(bytes: &[u8]) -> bool { if N < 8 { bytes - .get(0) + .first() .map(|byte| byte & (1 << N) != 0) .unwrap_or(false) } else { diff --git a/vendor/der/src/asn1/sequence.rs b/vendor/der/src/asn1/sequence.rs index d2f6bc5d1..ad4a5d52e 100644 --- a/vendor/der/src/asn1/sequence.rs +++ b/vendor/der/src/asn1/sequence.rs @@ -2,69 +2,40 @@ //! `SEQUENCE`s to Rust structs. use crate::{ - ByteSlice, Decode, DecodeValue, Encode, EncodeValue, FixedTag, Header, Length, Reader, Result, - Tag, Writer, + BytesRef, DecodeValue, EncodeValue, FixedTag, Header, Length, Reader, Result, Tag, Writer, }; -/// ASN.1 `SEQUENCE` trait. -/// -/// Types which impl this trait receive blanket impls for the [`Decode`], -/// [`Encode`], and [`FixedTag`] traits. -pub trait Sequence<'a>: Decode<'a> { - /// Call the provided function with a slice of [`Encode`] trait objects - /// representing the fields of this `SEQUENCE`. - /// - /// This method uses a callback because structs with fields which aren't - /// directly [`Encode`] may need to construct temporary values from - /// their fields prior to encoding. - fn fields<F, T>(&self, f: F) -> Result<T> - where - F: FnOnce(&[&dyn Encode]) -> Result<T>; -} - -impl<'a, M> EncodeValue for M -where - M: Sequence<'a>, -{ - fn value_len(&self) -> Result<Length> { - self.fields(|fields| { - fields - .iter() - .try_fold(Length::ZERO, |acc, field| acc + field.encoded_len()?) - }) - } +#[cfg(feature = "alloc")] +use alloc::boxed::Box; - fn encode_value(&self, writer: &mut dyn Writer) -> Result<()> { - self.fields(|fields| { - for &field in fields { - field.encode(writer)?; - } - - Ok(()) - }) - } -} +/// Marker trait for ASN.1 `SEQUENCE`s. +/// +/// This is mainly used for custom derive. +pub trait Sequence<'a>: DecodeValue<'a> + EncodeValue {} -impl<'a, M> FixedTag for M +impl<'a, S> FixedTag for S where - M: Sequence<'a>, + S: Sequence<'a>, { const TAG: Tag = Tag::Sequence; } +#[cfg(feature = "alloc")] +impl<'a, T> Sequence<'a> for Box<T> where T: Sequence<'a> {} + /// The [`SequenceRef`] type provides raw access to the octets which comprise a /// DER-encoded `SEQUENCE`. /// /// This is a zero-copy reference type which borrows from the input data. pub struct SequenceRef<'a> { /// Body of the `SEQUENCE`. - body: ByteSlice<'a>, + body: BytesRef<'a>, } impl<'a> DecodeValue<'a> for SequenceRef<'a> { fn decode_value<R: Reader<'a>>(reader: &mut R, header: Header) -> Result<Self> { Ok(Self { - body: ByteSlice::decode_value(reader, header)?, + body: BytesRef::decode_value(reader, header)?, }) } } @@ -74,11 +45,9 @@ impl EncodeValue for SequenceRef<'_> { Ok(self.body.len()) } - fn encode_value(&self, writer: &mut dyn Writer) -> Result<()> { + fn encode_value(&self, writer: &mut impl Writer) -> Result<()> { self.body.encode_value(writer) } } -impl<'a> FixedTag for SequenceRef<'a> { - const TAG: Tag = Tag::Sequence; -} +impl<'a> Sequence<'a> for SequenceRef<'a> {} diff --git a/vendor/der/src/asn1/sequence_of.rs b/vendor/der/src/asn1/sequence_of.rs index 6334d7197..42c2a9ca8 100644 --- a/vendor/der/src/asn1/sequence_of.rs +++ b/vendor/der/src/asn1/sequence_of.rs @@ -88,7 +88,7 @@ where .fold(Ok(Length::ZERO), |len, elem| len + elem.encoded_len()?) } - fn encode_value(&self, writer: &mut dyn Writer) -> Result<()> { + fn encode_value(&self, writer: &mut impl Writer) -> Result<()> { for elem in self.iter() { elem.encode(writer)?; } @@ -155,7 +155,7 @@ where .fold(Ok(Length::ZERO), |len, elem| len + elem.encoded_len()?) } - fn encode_value(&self, writer: &mut dyn Writer) -> Result<()> { + fn encode_value(&self, writer: &mut impl Writer) -> Result<()> { for elem in self { elem.encode(writer)?; } @@ -178,7 +178,6 @@ where } #[cfg(feature = "alloc")] -#[cfg_attr(docsrs, doc(cfg(feature = "alloc")))] impl<'a, T> DecodeValue<'a> for Vec<T> where T: Decode<'a>, @@ -197,7 +196,6 @@ where } #[cfg(feature = "alloc")] -#[cfg_attr(docsrs, doc(cfg(feature = "alloc")))] impl<T> EncodeValue for Vec<T> where T: Encode, @@ -207,7 +205,7 @@ where .fold(Ok(Length::ZERO), |len, elem| len + elem.encoded_len()?) } - fn encode_value(&self, writer: &mut dyn Writer) -> Result<()> { + fn encode_value(&self, writer: &mut impl Writer) -> Result<()> { for elem in self { elem.encode(writer)?; } @@ -217,13 +215,11 @@ where } #[cfg(feature = "alloc")] -#[cfg_attr(docsrs, doc(cfg(feature = "alloc")))] impl<T> FixedTag for Vec<T> { const TAG: Tag = Tag::Sequence; } #[cfg(feature = "alloc")] -#[cfg_attr(docsrs, doc(cfg(feature = "alloc")))] impl<T> ValueOrd for Vec<T> where T: DerOrd, diff --git a/vendor/der/src/asn1/set_of.rs b/vendor/der/src/asn1/set_of.rs index b8c4b0da4..e8f20e9c3 100644 --- a/vendor/der/src/asn1/set_of.rs +++ b/vendor/der/src/asn1/set_of.rs @@ -119,7 +119,7 @@ where .fold(Ok(Length::ZERO), |len, elem| len + elem.encoded_len()?) } - fn encode_value(&self, writer: &mut dyn Writer) -> Result<()> { + fn encode_value(&self, writer: &mut impl Writer) -> Result<()> { for elem in self.iter() { elem.encode(writer)?; } @@ -185,7 +185,6 @@ impl<'a, T> ExactSizeIterator for SetOfIter<'a, T> {} /// This type implements an append-only `SET OF` type which is heap-backed /// and depends on `alloc` support. #[cfg(feature = "alloc")] -#[cfg_attr(docsrs, doc(cfg(feature = "alloc")))] #[derive(Clone, Debug, Eq, PartialEq, PartialOrd, Ord)] pub struct SetOfVec<T> where @@ -195,7 +194,6 @@ where } #[cfg(feature = "alloc")] -#[cfg_attr(docsrs, doc(cfg(feature = "alloc")))] impl<T: DerOrd> Default for SetOfVec<T> { fn default() -> Self { Self { @@ -205,7 +203,6 @@ impl<T: DerOrd> Default for SetOfVec<T> { } #[cfg(feature = "alloc")] -#[cfg_attr(docsrs, doc(cfg(feature = "alloc")))] impl<T> SetOfVec<T> where T: DerOrd, @@ -265,7 +262,6 @@ where } #[cfg(feature = "alloc")] -#[cfg_attr(docsrs, doc(cfg(feature = "alloc")))] impl<T> AsRef<[T]> for SetOfVec<T> where T: DerOrd, @@ -276,7 +272,6 @@ where } #[cfg(feature = "alloc")] -#[cfg_attr(docsrs, doc(cfg(feature = "alloc")))] impl<'a, T> DecodeValue<'a> for SetOfVec<T> where T: Decode<'a> + DerOrd, @@ -297,7 +292,6 @@ where } #[cfg(feature = "alloc")] -#[cfg_attr(docsrs, doc(cfg(feature = "alloc")))] impl<'a, T> EncodeValue for SetOfVec<T> where T: 'a + Decode<'a> + Encode + DerOrd, @@ -307,7 +301,7 @@ where .fold(Ok(Length::ZERO), |len, elem| len + elem.encoded_len()?) } - fn encode_value(&self, writer: &mut dyn Writer) -> Result<()> { + fn encode_value(&self, writer: &mut impl Writer) -> Result<()> { for elem in self.iter() { elem.encode(writer)?; } @@ -317,7 +311,6 @@ where } #[cfg(feature = "alloc")] -#[cfg_attr(docsrs, doc(cfg(feature = "alloc")))] impl<T> FixedTag for SetOfVec<T> where T: DerOrd, @@ -326,7 +319,6 @@ where } #[cfg(feature = "alloc")] -#[cfg_attr(docsrs, doc(cfg(feature = "alloc")))] impl<T> From<SetOfVec<T>> for Vec<T> where T: DerOrd, @@ -337,7 +329,6 @@ where } #[cfg(feature = "alloc")] -#[cfg_attr(docsrs, doc(cfg(feature = "alloc")))] impl<T> TryFrom<Vec<T>> for SetOfVec<T> where T: DerOrd, @@ -352,7 +343,6 @@ where } #[cfg(feature = "alloc")] -#[cfg_attr(docsrs, doc(cfg(feature = "alloc")))] impl<T, const N: usize> TryFrom<[T; N]> for SetOfVec<T> where T: DerOrd, @@ -365,7 +355,6 @@ where } #[cfg(feature = "alloc")] -#[cfg_attr(docsrs, doc(cfg(feature = "alloc")))] impl<T> ValueOrd for SetOfVec<T> where T: DerOrd, @@ -375,6 +364,26 @@ where } } +// Implement by hand because the derive would create invalid values. +// Use the conversion from Vec to create a valid value. +#[cfg(feature = "arbitrary")] +impl<'a, T> arbitrary::Arbitrary<'a> for SetOfVec<T> +where + T: DerOrd + arbitrary::Arbitrary<'a>, +{ + fn arbitrary(u: &mut arbitrary::Unstructured<'a>) -> arbitrary::Result<Self> { + Self::try_from( + u.arbitrary_iter()? + .collect::<std::result::Result<Vec<_>, _>>()?, + ) + .map_err(|_| arbitrary::Error::IncorrectFormat) + } + + fn size_hint(_depth: usize) -> (usize, Option<usize>) { + (0, None) + } +} + /// Sort a mut slice according to its [`DerOrd`], returning any errors which /// might occur during the comparison. /// diff --git a/vendor/der/src/asn1/teletex_string.rs b/vendor/der/src/asn1/teletex_string.rs index 7d6621d2d..cedf727db 100644 --- a/vendor/der/src/asn1/teletex_string.rs +++ b/vendor/der/src/asn1/teletex_string.rs @@ -1,10 +1,26 @@ //! ASN.1 `TeletexString` support. +//! +use crate::{asn1::AnyRef, FixedTag, Result, StrRef, Tag}; +use core::{fmt, ops::Deref}; + +macro_rules! impl_teletex_string { + ($type: ty) => { + impl_teletex_string!($type,); + }; + ($type: ty, $($li: lifetime)?) => { + impl_string_type!($type, $($li),*); + + impl<$($li),*> FixedTag for $type { + const TAG: Tag = Tag::TeletexString; + } -use crate::{ - asn1::AnyRef, ord::OrdIsValueOrd, ByteSlice, DecodeValue, EncodeValue, Error, FixedTag, Header, - Length, Reader, Result, StrSlice, Tag, Writer, -}; -use core::{fmt, ops::Deref, str}; + impl<$($li),*> fmt::Debug for $type { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + write!(f, "TeletexString({:?})", self.as_str()) + } + } + }; +} /// ASN.1 `TeletexString` type. /// @@ -25,7 +41,7 @@ use core::{fmt, ops::Deref, str}; #[derive(Copy, Clone, Eq, PartialEq, PartialOrd, Ord)] pub struct TeletexStringRef<'a> { /// Inner value - inner: StrSlice<'a>, + inner: StrRef<'a>, } impl<'a> TeletexStringRef<'a> { @@ -41,83 +57,127 @@ impl<'a> TeletexStringRef<'a> { return Err(Self::TAG.value_error()); } - StrSlice::from_bytes(input) + StrRef::from_bytes(input) .map(|inner| Self { inner }) .map_err(|_| Self::TAG.value_error()) } } +impl_teletex_string!(TeletexStringRef<'a>, 'a); + impl<'a> Deref for TeletexStringRef<'a> { - type Target = StrSlice<'a>; + type Target = StrRef<'a>; fn deref(&self) -> &Self::Target { &self.inner } } -impl AsRef<str> for TeletexStringRef<'_> { - fn as_ref(&self) -> &str { - self.as_str() +impl<'a> From<&TeletexStringRef<'a>> for TeletexStringRef<'a> { + fn from(value: &TeletexStringRef<'a>) -> TeletexStringRef<'a> { + *value } } -impl AsRef<[u8]> for TeletexStringRef<'_> { - fn as_ref(&self) -> &[u8] { - self.as_bytes() +impl<'a> From<TeletexStringRef<'a>> for AnyRef<'a> { + fn from(teletex_string: TeletexStringRef<'a>) -> AnyRef<'a> { + AnyRef::from_tag_and_value(Tag::TeletexString, teletex_string.inner.into()) } } -impl<'a> DecodeValue<'a> for TeletexStringRef<'a> { - fn decode_value<R: Reader<'a>>(reader: &mut R, header: Header) -> Result<Self> { - Self::new(ByteSlice::decode_value(reader, header)?.as_slice()) - } -} +#[cfg(feature = "alloc")] +pub use self::allocation::TeletexString; -impl<'a> EncodeValue for TeletexStringRef<'a> { - fn value_len(&self) -> Result<Length> { - self.inner.value_len() - } +#[cfg(feature = "alloc")] +mod allocation { + use super::TeletexStringRef; - fn encode_value(&self, writer: &mut dyn Writer) -> Result<()> { - self.inner.encode_value(writer) + use crate::{ + asn1::AnyRef, + referenced::{OwnedToRef, RefToOwned}, + BytesRef, FixedTag, Result, StrOwned, Tag, + }; + use core::{fmt, ops::Deref}; + + /// ASN.1 `TeletexString` type. + /// + /// Supports a subset the ASCII character set (described below). + /// + /// For UTF-8, use [`Utf8StringRef`][`crate::asn1::Utf8StringRef`] instead. + /// For the full ASCII character set, use + /// [`Ia5StringRef`][`crate::asn1::Ia5StringRef`]. + /// + /// # Supported characters + /// + /// The standard defines a complex character set allowed in this type. However, quoting the ASN.1 + /// mailing list, "a sizable volume of software in the world treats TeletexString (T61String) as a + /// simple 8-bit string with mostly Windows Latin 1 (superset of iso-8859-1) encoding". + /// + #[derive(Clone, Eq, PartialEq, PartialOrd, Ord)] + pub struct TeletexString { + /// Inner value + inner: StrOwned, } -} -impl FixedTag for TeletexStringRef<'_> { - const TAG: Tag = Tag::TeletexString; -} + impl TeletexString { + /// Create a new ASN.1 `TeletexString`. + pub fn new<T>(input: &T) -> Result<Self> + where + T: AsRef<[u8]> + ?Sized, + { + let input = input.as_ref(); -impl OrdIsValueOrd for TeletexStringRef<'_> {} + TeletexStringRef::new(input)?; -impl<'a> From<&TeletexStringRef<'a>> for TeletexStringRef<'a> { - fn from(value: &TeletexStringRef<'a>) -> TeletexStringRef<'a> { - *value + StrOwned::from_bytes(input) + .map(|inner| Self { inner }) + .map_err(|_| Self::TAG.value_error()) + } } -} -impl<'a> TryFrom<AnyRef<'a>> for TeletexStringRef<'a> { - type Error = Error; + impl_teletex_string!(TeletexString); - fn try_from(any: AnyRef<'a>) -> Result<TeletexStringRef<'a>> { - any.decode_into() + impl Deref for TeletexString { + type Target = StrOwned; + + fn deref(&self) -> &Self::Target { + &self.inner + } } -} -impl<'a> From<TeletexStringRef<'a>> for AnyRef<'a> { - fn from(teletex_string: TeletexStringRef<'a>) -> AnyRef<'a> { - AnyRef::from_tag_and_value(Tag::TeletexString, teletex_string.inner.into()) + impl<'a> From<TeletexStringRef<'a>> for TeletexString { + fn from(value: TeletexStringRef<'a>) -> TeletexString { + let inner = + StrOwned::from_bytes(value.inner.as_bytes()).expect("Invalid TeletexString"); + Self { inner } + } } -} -impl<'a> fmt::Display for TeletexStringRef<'a> { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - f.write_str(self.as_str()) + impl<'a> From<&'a TeletexString> for AnyRef<'a> { + fn from(teletex_string: &'a TeletexString) -> AnyRef<'a> { + AnyRef::from_tag_and_value( + Tag::TeletexString, + BytesRef::new(teletex_string.inner.as_bytes()).expect("Invalid TeletexString"), + ) + } } -} -impl<'a> fmt::Debug for TeletexStringRef<'a> { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - write!(f, "TeletexString({:?})", self.as_str()) + impl<'a> RefToOwned<'a> for TeletexStringRef<'a> { + type Owned = TeletexString; + fn ref_to_owned(&self) -> Self::Owned { + TeletexString { + inner: self.inner.ref_to_owned(), + } + } + } + + impl OwnedToRef for TeletexString { + type Borrowed<'a> = TeletexStringRef<'a>; + fn owned_to_ref(&self) -> Self::Borrowed<'_> { + TeletexStringRef { + inner: self.inner.owned_to_ref(), + } + } } } diff --git a/vendor/der/src/asn1/utc_time.rs b/vendor/der/src/asn1/utc_time.rs index 7c2381155..0c10e3aff 100644 --- a/vendor/der/src/asn1/utc_time.rs +++ b/vendor/der/src/asn1/utc_time.rs @@ -1,7 +1,6 @@ //! ASN.1 `UTCTime` support. use crate::{ - asn1::AnyRef, datetime::{self, DateTime}, ord::OrdIsValueOrd, DecodeValue, EncodeValue, Error, ErrorKind, FixedTag, Header, Length, Reader, Result, Tag, @@ -12,9 +11,6 @@ use core::time::Duration; #[cfg(feature = "std")] use std::time::SystemTime; -/// Maximum year that can be represented as a `UTCTime`. -pub const MAX_YEAR: u16 = 2049; - /// ASN.1 `UTCTime` type. /// /// This type implements the validity requirements specified in @@ -37,9 +33,12 @@ impl UtcTime { /// Length of an RFC 5280-flavored ASN.1 DER-encoded [`UtcTime`]. pub const LENGTH: usize = 13; + /// Maximum year that can be represented as a `UTCTime`. + pub const MAX_YEAR: u16 = 2049; + /// Create a [`UtcTime`] from a [`DateTime`]. pub fn from_date_time(datetime: DateTime) -> Result<Self> { - if datetime.year() <= MAX_YEAR { + if datetime.year() <= UtcTime::MAX_YEAR { Ok(Self(datetime)) } else { Err(Self::TAG.value_error()) @@ -64,7 +63,6 @@ impl UtcTime { /// Instantiate from [`SystemTime`]. #[cfg(feature = "std")] - #[cfg_attr(docsrs, doc(cfg(feature = "std")))] pub fn from_system_time(time: SystemTime) -> Result<Self> { DateTime::try_from(time) .map_err(|_| Self::TAG.value_error())? @@ -73,12 +71,13 @@ impl UtcTime { /// Convert to [`SystemTime`]. #[cfg(feature = "std")] - #[cfg_attr(docsrs, doc(cfg(feature = "std")))] pub fn to_system_time(&self) -> SystemTime { self.0.to_system_time() } } +impl_any_conversions!(UtcTime); + impl<'a> DecodeValue<'a> for UtcTime { fn decode_value<R: Reader<'a>>(reader: &mut R, header: Header) -> Result<Self> { if Self::LENGTH != usize::try_from(header.length)? { @@ -120,7 +119,7 @@ impl EncodeValue for UtcTime { Self::LENGTH.try_into() } - fn encode_value(&self, writer: &mut dyn Writer) -> Result<()> { + fn encode_value(&self, writer: &mut impl Writer) -> Result<()> { let year = match self.0.year() { y @ 1950..=1999 => y.checked_sub(1900), y @ 2000..=2049 => y.checked_sub(2000), @@ -180,18 +179,43 @@ impl TryFrom<&DateTime> for UtcTime { } #[cfg(feature = "std")] -#[cfg_attr(docsrs, doc(cfg(feature = "std")))] impl From<UtcTime> for SystemTime { fn from(utc_time: UtcTime) -> SystemTime { utc_time.to_system_time() } } -impl TryFrom<AnyRef<'_>> for UtcTime { - type Error = Error; - - fn try_from(any: AnyRef<'_>) -> Result<UtcTime> { - any.decode_into() +// Implement by hand because the derive would create invalid values. +// Use the conversion from DateTime to create a valid value. +// The DateTime type has a way bigger range of valid years than UtcTime, +// so the DateTime year is mapped into a valid range to throw away less inputs. +#[cfg(feature = "arbitrary")] +impl<'a> arbitrary::Arbitrary<'a> for UtcTime { + fn arbitrary(u: &mut arbitrary::Unstructured<'a>) -> arbitrary::Result<Self> { + const MIN_YEAR: u16 = 1970; + const VALID_YEAR_COUNT: u16 = UtcTime::MAX_YEAR - MIN_YEAR + 1; + const AVERAGE_SECONDS_IN_YEAR: u64 = 31_556_952; + + let datetime = DateTime::arbitrary(u)?; + let year = datetime.year(); + let duration = datetime.unix_duration(); + + // Clamp the year into a valid range to not throw away too much input + let valid_year = (year.saturating_sub(MIN_YEAR)) + .rem_euclid(VALID_YEAR_COUNT) + .saturating_add(MIN_YEAR); + let year_to_remove = year.saturating_sub(valid_year); + let valid_duration = duration + - Duration::from_secs( + u64::from(year_to_remove).saturating_mul(AVERAGE_SECONDS_IN_YEAR), + ); + + Self::from_date_time(DateTime::from_unix_duration(valid_duration).expect("supported range")) + .map_err(|_| arbitrary::Error::IncorrectFormat) + } + + fn size_hint(depth: usize) -> (usize, Option<usize>) { + DateTime::size_hint(depth) } } diff --git a/vendor/der/src/asn1/utf8_string.rs b/vendor/der/src/asn1/utf8_string.rs index 1a0641172..6018750a0 100644 --- a/vendor/der/src/asn1/utf8_string.rs +++ b/vendor/der/src/asn1/utf8_string.rs @@ -1,13 +1,16 @@ //! ASN.1 `UTF8String` support. use crate::{ - asn1::AnyRef, ord::OrdIsValueOrd, ByteSlice, DecodeValue, EncodeValue, Error, FixedTag, Header, - Length, Reader, Result, StrSlice, Tag, Writer, + asn1::AnyRef, ord::OrdIsValueOrd, EncodeValue, Error, FixedTag, Length, Result, StrRef, Tag, + Writer, }; use core::{fmt, ops::Deref, str}; #[cfg(feature = "alloc")] -use alloc::{borrow::ToOwned, string::String}; +use { + crate::{DecodeValue, Header, Reader}, + alloc::{borrow::ToOwned, string::String}, +}; /// ASN.1 `UTF8String` type. /// @@ -26,7 +29,7 @@ use alloc::{borrow::ToOwned, string::String}; #[derive(Copy, Clone, Eq, PartialEq, PartialOrd, Ord)] pub struct Utf8StringRef<'a> { /// Inner value - inner: StrSlice<'a>, + inner: StrRef<'a>, } impl<'a> Utf8StringRef<'a> { @@ -35,75 +38,33 @@ impl<'a> Utf8StringRef<'a> { where T: AsRef<[u8]> + ?Sized, { - StrSlice::from_bytes(input.as_ref()).map(|inner| Self { inner }) + StrRef::from_bytes(input.as_ref()).map(|inner| Self { inner }) } } +impl_string_type!(Utf8StringRef<'a>, 'a); + impl<'a> Deref for Utf8StringRef<'a> { - type Target = StrSlice<'a>; + type Target = StrRef<'a>; fn deref(&self) -> &Self::Target { &self.inner } } -impl AsRef<str> for Utf8StringRef<'_> { - fn as_ref(&self) -> &str { - self.as_str() - } -} - -impl AsRef<[u8]> for Utf8StringRef<'_> { - fn as_ref(&self) -> &[u8] { - self.as_bytes() - } -} - -impl<'a> DecodeValue<'a> for Utf8StringRef<'a> { - fn decode_value<R: Reader<'a>>(reader: &mut R, header: Header) -> Result<Self> { - Self::new(ByteSlice::decode_value(reader, header)?.as_slice()) - } -} - -impl EncodeValue for Utf8StringRef<'_> { - fn value_len(&self) -> Result<Length> { - self.inner.value_len() - } - - fn encode_value(&self, writer: &mut dyn Writer) -> Result<()> { - self.inner.encode_value(writer) - } -} - impl FixedTag for Utf8StringRef<'_> { const TAG: Tag = Tag::Utf8String; } -impl OrdIsValueOrd for Utf8StringRef<'_> {} - impl<'a> From<&Utf8StringRef<'a>> for Utf8StringRef<'a> { fn from(value: &Utf8StringRef<'a>) -> Utf8StringRef<'a> { *value } } -impl<'a> TryFrom<AnyRef<'a>> for Utf8StringRef<'a> { - type Error = Error; - - fn try_from(any: AnyRef<'a>) -> Result<Utf8StringRef<'a>> { - any.decode_into() - } -} - impl<'a> From<Utf8StringRef<'a>> for AnyRef<'a> { - fn from(printable_string: Utf8StringRef<'a>) -> AnyRef<'a> { - AnyRef::from_tag_and_value(Tag::Utf8String, printable_string.inner.into()) - } -} - -impl<'a> fmt::Display for Utf8StringRef<'a> { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - f.write_str(self.as_str()) + fn from(utf_string: Utf8StringRef<'a>) -> AnyRef<'a> { + AnyRef::from_tag_and_value(Tag::Utf8String, utf_string.inner.into()) } } @@ -126,7 +87,7 @@ impl EncodeValue for str { Utf8StringRef::new(self)?.value_len() } - fn encode_value(&self, writer: &mut dyn Writer) -> Result<()> { + fn encode_value(&self, writer: &mut impl Writer) -> Result<()> { Utf8StringRef::new(self)?.encode_value(writer) } } @@ -138,7 +99,6 @@ impl FixedTag for str { impl OrdIsValueOrd for str {} #[cfg(feature = "alloc")] -#[cfg_attr(docsrs, doc(cfg(feature = "alloc")))] impl<'a> From<Utf8StringRef<'a>> for String { fn from(s: Utf8StringRef<'a>) -> String { s.as_str().to_owned() @@ -146,7 +106,6 @@ impl<'a> From<Utf8StringRef<'a>> for String { } #[cfg(feature = "alloc")] -#[cfg_attr(docsrs, doc(cfg(feature = "alloc")))] impl<'a> TryFrom<AnyRef<'a>> for String { type Error = Error; @@ -156,7 +115,6 @@ impl<'a> TryFrom<AnyRef<'a>> for String { } #[cfg(feature = "alloc")] -#[cfg_attr(docsrs, doc(cfg(feature = "alloc")))] impl<'a> DecodeValue<'a> for String { fn decode_value<R: Reader<'a>>(reader: &mut R, header: Header) -> Result<Self> { Ok(String::from_utf8(reader.read_vec(header.length)?)?) @@ -164,25 +122,22 @@ impl<'a> DecodeValue<'a> for String { } #[cfg(feature = "alloc")] -#[cfg_attr(docsrs, doc(cfg(feature = "alloc")))] impl EncodeValue for String { fn value_len(&self) -> Result<Length> { Utf8StringRef::new(self)?.value_len() } - fn encode_value(&self, writer: &mut dyn Writer) -> Result<()> { + fn encode_value(&self, writer: &mut impl Writer) -> Result<()> { Utf8StringRef::new(self)?.encode_value(writer) } } #[cfg(feature = "alloc")] -#[cfg_attr(docsrs, doc(cfg(feature = "alloc")))] impl FixedTag for String { const TAG: Tag = Tag::Utf8String; } #[cfg(feature = "alloc")] -#[cfg_attr(docsrs, doc(cfg(feature = "alloc")))] impl OrdIsValueOrd for String {} #[cfg(test)] diff --git a/vendor/der/src/asn1/videotex_string.rs b/vendor/der/src/asn1/videotex_string.rs index b758a22e6..55b1a49cf 100644 --- a/vendor/der/src/asn1/videotex_string.rs +++ b/vendor/der/src/asn1/videotex_string.rs @@ -1,10 +1,7 @@ //! ASN.1 `VideotexString` support. -use crate::{ - asn1::AnyRef, ord::OrdIsValueOrd, ByteSlice, DecodeValue, EncodeValue, Error, FixedTag, Header, - Length, Reader, Result, StrSlice, Tag, Writer, -}; -use core::{fmt, ops::Deref, str}; +use crate::{asn1::AnyRef, FixedTag, Result, StrRef, Tag}; +use core::{fmt, ops::Deref}; /// ASN.1 `VideotexString` type. /// @@ -23,7 +20,7 @@ use core::{fmt, ops::Deref, str}; #[derive(Copy, Clone, Eq, PartialEq, PartialOrd, Ord)] pub struct VideotexStringRef<'a> { /// Inner value - inner: StrSlice<'a>, + inner: StrRef<'a>, } impl<'a> VideotexStringRef<'a> { @@ -40,68 +37,32 @@ impl<'a> VideotexStringRef<'a> { return Err(Self::TAG.value_error()); } - StrSlice::from_bytes(input) + StrRef::from_bytes(input) .map(|inner| Self { inner }) .map_err(|_| Self::TAG.value_error()) } } +impl_string_type!(VideotexStringRef<'a>, 'a); + impl<'a> Deref for VideotexStringRef<'a> { - type Target = StrSlice<'a>; + type Target = StrRef<'a>; fn deref(&self) -> &Self::Target { &self.inner } } -impl AsRef<str> for VideotexStringRef<'_> { - fn as_ref(&self) -> &str { - self.as_str() - } -} - -impl AsRef<[u8]> for VideotexStringRef<'_> { - fn as_ref(&self) -> &[u8] { - self.as_bytes() - } -} - -impl<'a> DecodeValue<'a> for VideotexStringRef<'a> { - fn decode_value<R: Reader<'a>>(reader: &mut R, header: Header) -> Result<Self> { - Self::new(ByteSlice::decode_value(reader, header)?.as_slice()) - } -} - -impl<'a> EncodeValue for VideotexStringRef<'a> { - fn value_len(&self) -> Result<Length> { - self.inner.value_len() - } - - fn encode_value(&self, writer: &mut dyn Writer) -> Result<()> { - self.inner.encode_value(writer) - } -} - impl FixedTag for VideotexStringRef<'_> { const TAG: Tag = Tag::VideotexString; } -impl OrdIsValueOrd for VideotexStringRef<'_> {} - impl<'a> From<&VideotexStringRef<'a>> for VideotexStringRef<'a> { fn from(value: &VideotexStringRef<'a>) -> VideotexStringRef<'a> { *value } } -impl<'a> TryFrom<AnyRef<'a>> for VideotexStringRef<'a> { - type Error = Error; - - fn try_from(any: AnyRef<'a>) -> Result<VideotexStringRef<'a>> { - any.decode_into() - } -} - impl<'a> From<VideotexStringRef<'a>> for AnyRef<'a> { fn from(printable_string: VideotexStringRef<'a>) -> AnyRef<'a> { AnyRef::from_tag_and_value(Tag::VideotexString, printable_string.inner.into()) @@ -114,12 +75,6 @@ impl<'a> From<VideotexStringRef<'a>> for &'a [u8] { } } -impl<'a> fmt::Display for VideotexStringRef<'a> { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - f.write_str(self.as_str()) - } -} - impl<'a> fmt::Debug for VideotexStringRef<'a> { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { write!(f, "VideotexString({:?})", self.as_str()) diff --git a/vendor/der/src/byte_slice.rs b/vendor/der/src/byte_slice.rs deleted file mode 100644 index 00d46d0f1..000000000 --- a/vendor/der/src/byte_slice.rs +++ /dev/null @@ -1,116 +0,0 @@ -//! Common handling for types backed by byte slices with enforcement of a -//! library-level length limitation i.e. `Length::max()`. - -use crate::{ - str_slice::StrSlice, DecodeValue, DerOrd, EncodeValue, Error, Header, Length, Reader, Result, - Writer, -}; -use core::cmp::Ordering; - -/// Byte slice newtype which respects the `Length::max()` limit. -#[derive(Copy, Clone, Debug, Eq, PartialEq, PartialOrd, Ord)] -pub(crate) struct ByteSlice<'a> { - /// Precomputed `Length` (avoids possible panicking conversions) - length: Length, - - /// Inner value - inner: &'a [u8], -} - -impl<'a> ByteSlice<'a> { - /// Constant value representing an empty byte slice. - pub const EMPTY: Self = Self { - length: Length::ZERO, - inner: &[], - }; - - /// Create a new [`ByteSlice`], ensuring that the provided `slice` value - /// is shorter than `Length::max()`. - pub fn new(slice: &'a [u8]) -> Result<Self> { - Ok(Self { - length: Length::try_from(slice.len())?, - inner: slice, - }) - } - - /// Borrow the inner byte slice - pub fn as_slice(&self) -> &'a [u8] { - self.inner - } - - /// Get the [`Length`] of this [`ByteSlice`] - pub fn len(self) -> Length { - self.length - } - - /// Is this [`ByteSlice`] empty? - pub fn is_empty(self) -> bool { - self.len() == Length::ZERO - } -} - -impl AsRef<[u8]> for ByteSlice<'_> { - fn as_ref(&self) -> &[u8] { - self.as_slice() - } -} - -impl<'a> DecodeValue<'a> for ByteSlice<'a> { - fn decode_value<R: Reader<'a>>(reader: &mut R, header: Header) -> Result<Self> { - reader.read_slice(header.length).and_then(Self::new) - } -} - -impl EncodeValue for ByteSlice<'_> { - fn value_len(&self) -> Result<Length> { - Ok(self.length) - } - - fn encode_value(&self, writer: &mut dyn Writer) -> Result<()> { - writer.write(self.as_ref()) - } -} - -impl Default for ByteSlice<'_> { - fn default() -> Self { - Self { - length: Length::ZERO, - inner: &[], - } - } -} - -impl DerOrd for ByteSlice<'_> { - fn der_cmp(&self, other: &Self) -> Result<Ordering> { - Ok(self.as_slice().cmp(other.as_slice())) - } -} - -impl<'a> From<&'a [u8; 1]> for ByteSlice<'a> { - fn from(byte: &'a [u8; 1]) -> ByteSlice<'a> { - Self { - length: Length::ONE, - inner: byte, - } - } -} - -impl<'a> From<StrSlice<'a>> for ByteSlice<'a> { - fn from(s: StrSlice<'a>) -> ByteSlice<'a> { - let bytes = s.as_bytes(); - debug_assert_eq!(bytes.len(), usize::try_from(s.length).expect("overflow")); - - ByteSlice { - inner: bytes, - length: s.length, - } - } -} - -impl<'a> TryFrom<&'a [u8]> for ByteSlice<'a> { - type Error = Error; - - fn try_from(slice: &'a [u8]) -> Result<Self> { - Self::new(slice) - } -} diff --git a/vendor/der/src/bytes_owned.rs b/vendor/der/src/bytes_owned.rs new file mode 100644 index 000000000..a9f67b21a --- /dev/null +++ b/vendor/der/src/bytes_owned.rs @@ -0,0 +1,156 @@ +//! Common handling for types backed by byte allocation with enforcement of a +//! library-level length limitation i.e. `Length::max()`. + +use crate::{ + referenced::OwnedToRef, BytesRef, DecodeValue, DerOrd, EncodeValue, Error, Header, Length, + Reader, Result, StrRef, Writer, +}; +use alloc::{boxed::Box, vec::Vec}; +use core::cmp::Ordering; + +/// Byte slice newtype which respects the `Length::max()` limit. +#[derive(Clone, Debug, Eq, PartialEq, PartialOrd, Ord)] +pub(crate) struct BytesOwned { + /// Precomputed `Length` (avoids possible panicking conversions) + length: Length, + + /// Inner value + inner: Box<[u8]>, +} + +impl BytesOwned { + /// Create a new [`BytesOwned`], ensuring that the provided `slice` value + /// is shorter than `Length::max()`. + pub fn new(data: impl Into<Box<[u8]>>) -> Result<Self> { + let inner: Box<[u8]> = data.into(); + + Ok(Self { + length: Length::try_from(inner.len())?, + inner, + }) + } + + /// Borrow the inner byte slice + pub fn as_slice(&self) -> &[u8] { + &self.inner + } + + /// Get the [`Length`] of this [`BytesRef`] + pub fn len(&self) -> Length { + self.length + } + + /// Is this [`BytesOwned`] empty? + pub fn is_empty(&self) -> bool { + self.len() == Length::ZERO + } +} + +impl AsRef<[u8]> for BytesOwned { + fn as_ref(&self) -> &[u8] { + self.as_slice() + } +} + +impl<'a> DecodeValue<'a> for BytesOwned { + fn decode_value<R: Reader<'a>>(reader: &mut R, header: Header) -> Result<Self> { + reader.read_vec(header.length).and_then(Self::new) + } +} + +impl EncodeValue for BytesOwned { + fn value_len(&self) -> Result<Length> { + Ok(self.length) + } + + fn encode_value(&self, writer: &mut impl Writer) -> Result<()> { + writer.write(self.as_ref()) + } +} + +impl Default for BytesOwned { + fn default() -> Self { + Self { + length: Length::ZERO, + inner: Box::new([]), + } + } +} + +impl DerOrd for BytesOwned { + fn der_cmp(&self, other: &Self) -> Result<Ordering> { + Ok(self.as_slice().cmp(other.as_slice())) + } +} + +impl From<StrRef<'_>> for BytesOwned { + fn from(s: StrRef<'_>) -> BytesOwned { + let bytes = s.as_bytes(); + debug_assert_eq!(bytes.len(), usize::try_from(s.length).expect("overflow")); + + BytesOwned { + inner: Box::from(bytes), + length: s.length, + } + } +} + +impl OwnedToRef for BytesOwned { + type Borrowed<'a> = BytesRef<'a>; + fn owned_to_ref(&self) -> Self::Borrowed<'_> { + BytesRef { + length: self.length, + inner: self.inner.as_ref(), + } + } +} + +impl From<BytesRef<'_>> for BytesOwned { + fn from(s: BytesRef<'_>) -> BytesOwned { + BytesOwned { + length: s.length, + inner: Box::from(s.inner), + } + } +} + +impl TryFrom<&[u8]> for BytesOwned { + type Error = Error; + + fn try_from(bytes: &[u8]) -> Result<Self> { + Self::new(bytes) + } +} + +impl TryFrom<Box<[u8]>> for BytesOwned { + type Error = Error; + + fn try_from(bytes: Box<[u8]>) -> Result<Self> { + Self::new(bytes) + } +} + +impl TryFrom<Vec<u8>> for BytesOwned { + type Error = Error; + + fn try_from(bytes: Vec<u8>) -> Result<Self> { + Self::new(bytes) + } +} + +// Implement by hand because the derive would create invalid values. +// Make sure the length and the inner.len matches. +#[cfg(feature = "arbitrary")] +impl<'a> arbitrary::Arbitrary<'a> for BytesOwned { + fn arbitrary(u: &mut arbitrary::Unstructured<'a>) -> arbitrary::Result<Self> { + let length = u.arbitrary()?; + Ok(Self { + length, + inner: Box::from(u.bytes(u32::from(length) as usize)?), + }) + } + + fn size_hint(depth: usize) -> (usize, Option<usize>) { + arbitrary::size_hint::and(Length::size_hint(depth), (0, None)) + } +} diff --git a/vendor/der/src/bytes_ref.rs b/vendor/der/src/bytes_ref.rs new file mode 100644 index 000000000..2cee4076e --- /dev/null +++ b/vendor/der/src/bytes_ref.rs @@ -0,0 +1,152 @@ +//! Common handling for types backed by byte slices with enforcement of a +//! library-level length limitation i.e. `Length::max()`. + +use crate::{ + DecodeValue, DerOrd, EncodeValue, Error, Header, Length, Reader, Result, StrRef, Writer, +}; +use core::cmp::Ordering; + +#[cfg(feature = "alloc")] +use crate::StrOwned; + +/// Byte slice newtype which respects the `Length::max()` limit. +#[derive(Copy, Clone, Debug, Eq, PartialEq, PartialOrd, Ord)] +pub(crate) struct BytesRef<'a> { + /// Precomputed `Length` (avoids possible panicking conversions) + pub length: Length, + + /// Inner value + pub inner: &'a [u8], +} + +impl<'a> BytesRef<'a> { + /// Constant value representing an empty byte slice. + pub const EMPTY: Self = Self { + length: Length::ZERO, + inner: &[], + }; + + /// Create a new [`BytesRef`], ensuring that the provided `slice` value + /// is shorter than `Length::max()`. + pub fn new(slice: &'a [u8]) -> Result<Self> { + Ok(Self { + length: Length::try_from(slice.len())?, + inner: slice, + }) + } + + /// Borrow the inner byte slice + pub fn as_slice(&self) -> &'a [u8] { + self.inner + } + + /// Get the [`Length`] of this [`BytesRef`] + pub fn len(self) -> Length { + self.length + } + + /// Is this [`BytesRef`] empty? + pub fn is_empty(self) -> bool { + self.len() == Length::ZERO + } +} + +impl AsRef<[u8]> for BytesRef<'_> { + fn as_ref(&self) -> &[u8] { + self.as_slice() + } +} + +impl<'a> DecodeValue<'a> for BytesRef<'a> { + fn decode_value<R: Reader<'a>>(reader: &mut R, header: Header) -> Result<Self> { + reader.read_slice(header.length).and_then(Self::new) + } +} + +impl EncodeValue for BytesRef<'_> { + fn value_len(&self) -> Result<Length> { + Ok(self.length) + } + + fn encode_value(&self, writer: &mut impl Writer) -> Result<()> { + writer.write(self.as_ref()) + } +} + +impl Default for BytesRef<'_> { + fn default() -> Self { + Self { + length: Length::ZERO, + inner: &[], + } + } +} + +impl DerOrd for BytesRef<'_> { + fn der_cmp(&self, other: &Self) -> Result<Ordering> { + Ok(self.as_slice().cmp(other.as_slice())) + } +} + +impl<'a> From<StrRef<'a>> for BytesRef<'a> { + fn from(s: StrRef<'a>) -> BytesRef<'a> { + let bytes = s.as_bytes(); + debug_assert_eq!(bytes.len(), usize::try_from(s.length).expect("overflow")); + + BytesRef { + inner: bytes, + length: s.length, + } + } +} + +#[cfg(feature = "alloc")] +impl<'a> From<&'a StrOwned> for BytesRef<'a> { + fn from(s: &'a StrOwned) -> BytesRef<'a> { + let bytes = s.as_bytes(); + debug_assert_eq!(bytes.len(), usize::try_from(s.length).expect("overflow")); + + BytesRef { + inner: bytes, + length: s.length, + } + } +} + +impl<'a> TryFrom<&'a [u8]> for BytesRef<'a> { + type Error = Error; + + fn try_from(slice: &'a [u8]) -> Result<Self> { + Self::new(slice) + } +} + +// Implement by hand because the derive would create invalid values. +// Make sure the length and the inner.len matches. +#[cfg(feature = "arbitrary")] +impl<'a> arbitrary::Arbitrary<'a> for BytesRef<'a> { + fn arbitrary(u: &mut arbitrary::Unstructured<'a>) -> arbitrary::Result<Self> { + let length = u.arbitrary()?; + Ok(Self { + length, + inner: u.bytes(u32::from(length) as usize)?, + }) + } + + fn size_hint(depth: usize) -> (usize, Option<usize>) { + arbitrary::size_hint::and(Length::size_hint(depth), (0, None)) + } +} + +#[cfg(feature = "alloc")] +mod allocating { + use super::BytesRef; + use crate::{referenced::RefToOwned, BytesOwned}; + + impl<'a> RefToOwned<'a> for BytesRef<'a> { + type Owned = BytesOwned; + fn ref_to_owned(&self) -> Self::Owned { + BytesOwned::from(*self) + } + } +} diff --git a/vendor/der/src/datetime.rs b/vendor/der/src/datetime.rs index 2b4c504bf..de28d53bb 100644 --- a/vendor/der/src/datetime.rs +++ b/vendor/der/src/datetime.rs @@ -240,7 +240,6 @@ impl DateTime { /// Instantiate from [`SystemTime`]. #[cfg(feature = "std")] - #[cfg_attr(docsrs, doc(cfg(feature = "std")))] pub fn from_system_time(time: SystemTime) -> Result<Self> { time.duration_since(UNIX_EPOCH) .map_err(|_| ErrorKind::DateTime.into()) @@ -249,7 +248,6 @@ impl DateTime { /// Convert to [`SystemTime`]. #[cfg(feature = "std")] - #[cfg_attr(docsrs, doc(cfg(feature = "std")))] pub fn to_system_time(&self) -> SystemTime { UNIX_EPOCH + self.unix_duration() } @@ -258,19 +256,12 @@ impl DateTime { impl FromStr for DateTime { type Err = Error; - // TODO(tarcieri): checked arithmetic - #[allow(clippy::integer_arithmetic)] fn from_str(s: &str) -> Result<Self> { match *s.as_bytes() { [year1, year2, year3, year4, b'-', month1, month2, b'-', day1, day2, b'T', hour1, hour2, b':', min1, min2, b':', sec1, sec2, b'Z'] => { let tag = Tag::GeneralizedTime; - let year = - u16::from(decode_decimal(tag, year1, year2).map_err(|_| ErrorKind::DateTime)?) - * 100 - + u16::from( - decode_decimal(tag, year3, year4).map_err(|_| ErrorKind::DateTime)?, - ); + let year = decode_year(&[year1, year2, year3, year4])?; let month = decode_decimal(tag, month1, month2).map_err(|_| ErrorKind::DateTime)?; let day = decode_decimal(tag, day1, day2).map_err(|_| ErrorKind::DateTime)?; let hour = decode_decimal(tag, hour1, hour2).map_err(|_| ErrorKind::DateTime)?; @@ -294,7 +285,6 @@ impl fmt::Display for DateTime { } #[cfg(feature = "std")] -#[cfg_attr(docsrs, doc(cfg(feature = "std")))] impl From<DateTime> for SystemTime { fn from(time: DateTime) -> SystemTime { time.to_system_time() @@ -302,7 +292,6 @@ impl From<DateTime> for SystemTime { } #[cfg(feature = "std")] -#[cfg_attr(docsrs, doc(cfg(feature = "std")))] impl From<&DateTime> for SystemTime { fn from(time: &DateTime) -> SystemTime { time.to_system_time() @@ -310,7 +299,6 @@ impl From<&DateTime> for SystemTime { } #[cfg(feature = "std")] -#[cfg_attr(docsrs, doc(cfg(feature = "std")))] impl TryFrom<SystemTime> for DateTime { type Error = Error; @@ -320,7 +308,6 @@ impl TryFrom<SystemTime> for DateTime { } #[cfg(feature = "std")] -#[cfg_attr(docsrs, doc(cfg(feature = "std")))] impl TryFrom<&SystemTime> for DateTime { type Error = Error; @@ -330,12 +317,11 @@ impl TryFrom<&SystemTime> for DateTime { } #[cfg(feature = "time")] -#[cfg_attr(docsrs, doc(cfg(feature = "time")))] impl TryFrom<DateTime> for PrimitiveDateTime { type Error = Error; fn try_from(time: DateTime) -> Result<PrimitiveDateTime> { - let month = (time.month() as u8).try_into()?; + let month = time.month().try_into()?; let date = time::Date::from_calendar_date(i32::from(time.year()), month, time.day())?; let time = time::Time::from_hms(time.hour(), time.minutes(), time.seconds())?; @@ -344,7 +330,6 @@ impl TryFrom<DateTime> for PrimitiveDateTime { } #[cfg(feature = "time")] -#[cfg_attr(docsrs, doc(cfg(feature = "time")))] impl TryFrom<PrimitiveDateTime> for DateTime { type Error = Error; @@ -360,11 +345,28 @@ impl TryFrom<PrimitiveDateTime> for DateTime { } } +// Implement by hand because the derive would create invalid values. +// Use the conversion from Duration to create a valid value. +#[cfg(feature = "arbitrary")] +impl<'a> arbitrary::Arbitrary<'a> for DateTime { + fn arbitrary(u: &mut arbitrary::Unstructured<'a>) -> arbitrary::Result<Self> { + Self::from_unix_duration(Duration::new( + u.int_in_range(0..=MAX_UNIX_DURATION.as_secs().saturating_sub(1))?, + u.int_in_range(0..=999_999_999)?, + )) + .map_err(|_| arbitrary::Error::IncorrectFormat) + } + + fn size_hint(depth: usize) -> (usize, Option<usize>) { + arbitrary::size_hint::and(u64::size_hint(depth), u32::size_hint(depth)) + } +} + /// Decode 2-digit decimal value // TODO(tarcieri): checked arithmetic #[allow(clippy::integer_arithmetic)] pub(crate) fn decode_decimal(tag: Tag, hi: u8, lo: u8) -> Result<u8> { - if (b'0'..=b'9').contains(&hi) && (b'0'..=b'9').contains(&lo) { + if hi.is_ascii_digit() && lo.is_ascii_digit() { Ok((hi - b'0') * 10 + (lo - b'0')) } else { Err(tag.value_error()) @@ -386,6 +388,16 @@ where writer.write_byte(b'0'.checked_add(value % 10).ok_or(ErrorKind::Overflow)?) } +/// Decode 4-digit year. +// TODO(tarcieri): checked arithmetic +#[allow(clippy::integer_arithmetic)] +fn decode_year(year: &[u8; 4]) -> Result<u16> { + let tag = Tag::GeneralizedTime; + let hi = decode_decimal(tag, year[0], year[1]).map_err(|_| ErrorKind::DateTime)?; + let lo = decode_decimal(tag, year[2], year[3]).map_err(|_| ErrorKind::DateTime)?; + Ok(u16::from(hi) * 100 + u16::from(lo)) +} + #[cfg(test)] mod tests { use super::DateTime; diff --git a/vendor/der/src/decode.rs b/vendor/der/src/decode.rs index 1c63b322a..0efcae69f 100644 --- a/vendor/der/src/decode.rs +++ b/vendor/der/src/decode.rs @@ -8,6 +8,9 @@ use crate::{pem::PemLabel, PemReader}; #[cfg(doc)] use crate::{Length, Tag}; +#[cfg(feature = "alloc")] +use alloc::boxed::Box; + /// Decoding trait. /// /// This trait provides the core abstraction upon which all decoding operations @@ -52,14 +55,12 @@ impl<T> DecodeOwned for T where T: for<'a> Decode<'a> {} /// This trait is automatically impl'd for any type which impls both /// [`DecodeOwned`] and [`PemLabel`]. #[cfg(feature = "pem")] -#[cfg_attr(docsrs, doc(cfg(feature = "pem")))] pub trait DecodePem: DecodeOwned + PemLabel { /// Try to decode this type from PEM. fn from_pem(pem: impl AsRef<[u8]>) -> Result<Self>; } #[cfg(feature = "pem")] -#[cfg_attr(docsrs, doc(cfg(feature = "pem")))] impl<T: DecodeOwned + PemLabel> DecodePem for T { fn from_pem(pem: impl AsRef<[u8]>) -> Result<Self> { let mut reader = PemReader::new(pem.as_ref())?; @@ -74,3 +75,13 @@ pub trait DecodeValue<'a>: Sized { /// Attempt to decode this message using the provided [`Reader`]. fn decode_value<R: Reader<'a>>(reader: &mut R, header: Header) -> Result<Self>; } + +#[cfg(feature = "alloc")] +impl<'a, T> DecodeValue<'a> for Box<T> +where + T: DecodeValue<'a>, +{ + fn decode_value<R: Reader<'a>>(reader: &mut R, header: Header) -> Result<Self> { + Ok(Box::new(T::decode_value(reader, header)?)) + } +} diff --git a/vendor/der/src/document.rs b/vendor/der/src/document.rs index aa953cd46..78355a67a 100644 --- a/vendor/der/src/document.rs +++ b/vendor/der/src/document.rs @@ -27,7 +27,6 @@ use zeroize::{Zeroize, ZeroizeOnDrop, Zeroizing}; /// /// The [`SecretDocument`] provides a wrapper for this type with additional /// hardening applied. -#[cfg_attr(docsrs, doc(cfg(feature = "alloc")))] #[derive(Clone, Eq, PartialEq)] pub struct Document { /// ASN.1 DER encoded bytes. @@ -45,7 +44,6 @@ impl Document { /// Convert to a [`SecretDocument`]. #[cfg(feature = "zeroize")] - #[cfg_attr(docsrs, doc(cfg(feature = "zeroize")))] pub fn into_secret(self) -> SecretDocument { SecretDocument(self) } @@ -74,14 +72,13 @@ impl Document { /// Encode the provided type as ASN.1 DER, storing the resulting encoded DER /// as a [`Document`]. pub fn encode_msg<T: Encode>(msg: &T) -> Result<Self> { - msg.to_vec()?.try_into() + msg.to_der()?.try_into() } /// Decode ASN.1 DER document from PEM. /// /// Returns the PEM label and decoded [`Document`] on success. #[cfg(feature = "pem")] - #[cfg_attr(docsrs, doc(cfg(feature = "pem")))] pub fn from_pem(pem: &str) -> Result<(&str, Self)> { let (label, der_bytes) = pem::decode_vec(pem.as_bytes())?; Ok((label, der_bytes.try_into()?)) @@ -90,35 +87,30 @@ impl Document { /// Encode ASN.1 DER document as a PEM string with encapsulation boundaries /// containing the provided PEM type `label` (e.g. `CERTIFICATE`). #[cfg(feature = "pem")] - #[cfg_attr(docsrs, doc(cfg(feature = "pem")))] pub fn to_pem(&self, label: &'static str, line_ending: pem::LineEnding) -> Result<String> { Ok(pem::encode_string(label, line_ending, self.as_bytes())?) } /// Read ASN.1 DER document from a file. #[cfg(feature = "std")] - #[cfg_attr(docsrs, doc(cfg(feature = "std")))] pub fn read_der_file(path: impl AsRef<Path>) -> Result<Self> { fs::read(path)?.try_into() } /// Write ASN.1 DER document to a file. #[cfg(feature = "std")] - #[cfg_attr(docsrs, doc(cfg(feature = "std")))] pub fn write_der_file(&self, path: impl AsRef<Path>) -> Result<()> { Ok(fs::write(path, self.as_bytes())?) } /// Read PEM-encoded ASN.1 DER document from a file. #[cfg(all(feature = "pem", feature = "std"))] - #[cfg_attr(docsrs, doc(cfg(all(feature = "pem", feature = "std"))))] pub fn read_pem_file(path: impl AsRef<Path>) -> Result<(String, Self)> { Self::from_pem(&fs::read_to_string(path)?).map(|(label, doc)| (label.to_owned(), doc)) } /// Write PEM-encoded ASN.1 DER document to a file. #[cfg(all(feature = "pem", feature = "std"))] - #[cfg_attr(docsrs, doc(cfg(all(feature = "pem", feature = "std"))))] pub fn write_pem_file( &self, path: impl AsRef<Path>, @@ -166,7 +158,7 @@ impl Encode for Document { Ok(self.len()) } - fn encode(&self, writer: &mut dyn Writer) -> Result<()> { + fn encode(&self, writer: &mut impl Writer) -> Result<()> { writer.write(self.as_bytes()) } } @@ -205,7 +197,6 @@ impl TryFrom<Vec<u8>> for Document { /// are zeroized-on-drop, and also using more restrictive file permissions when /// writing files to disk. #[cfg(feature = "zeroize")] -#[cfg_attr(docsrs, doc(cfg(all(feature = "alloc", feature = "zeroize"))))] #[derive(Clone)] pub struct SecretDocument(Document); @@ -238,14 +229,12 @@ impl SecretDocument { /// Decode ASN.1 DER document from PEM. #[cfg(feature = "pem")] - #[cfg_attr(docsrs, doc(cfg(feature = "pem")))] pub fn from_pem(pem: &str) -> Result<(&str, Self)> { Document::from_pem(pem).map(|(label, doc)| (label, Self(doc))) } /// Encode ASN.1 DER document as a PEM string. #[cfg(feature = "pem")] - #[cfg_attr(docsrs, doc(cfg(feature = "pem")))] pub fn to_pem( &self, label: &'static str, @@ -256,28 +245,24 @@ impl SecretDocument { /// Read ASN.1 DER document from a file. #[cfg(feature = "std")] - #[cfg_attr(docsrs, doc(cfg(feature = "std")))] pub fn read_der_file(path: impl AsRef<Path>) -> Result<Self> { Document::read_der_file(path).map(Self) } /// Write ASN.1 DER document to a file. #[cfg(feature = "std")] - #[cfg_attr(docsrs, doc(cfg(feature = "std")))] pub fn write_der_file(&self, path: impl AsRef<Path>) -> Result<()> { write_secret_file(path, self.as_bytes()) } /// Read PEM-encoded ASN.1 DER document from a file. #[cfg(all(feature = "pem", feature = "std"))] - #[cfg_attr(docsrs, doc(cfg(all(feature = "pem", feature = "std"))))] pub fn read_pem_file(path: impl AsRef<Path>) -> Result<(String, Self)> { Document::read_pem_file(path).map(|(label, doc)| (label, Self(doc))) } /// Write PEM-encoded ASN.1 DER document to a file. #[cfg(all(feature = "pem", feature = "std"))] - #[cfg_attr(docsrs, doc(cfg(all(feature = "pem", feature = "std"))))] pub fn write_pem_file( &self, path: impl AsRef<Path>, diff --git a/vendor/der/src/encode.rs b/vendor/der/src/encode.rs index 51fc13d8b..d480b7bbd 100644 --- a/vendor/der/src/encode.rs +++ b/vendor/der/src/encode.rs @@ -3,7 +3,7 @@ use crate::{Header, Length, Result, SliceWriter, Tagged, Writer}; #[cfg(feature = "alloc")] -use {alloc::vec::Vec, core::iter}; +use {alloc::boxed::Box, alloc::vec::Vec, core::iter}; #[cfg(feature = "pem")] use { @@ -24,7 +24,7 @@ pub trait Encode { fn encoded_len(&self) -> Result<Length>; /// Encode this value as ASN.1 DER using the provided [`Writer`]. - fn encode(&self, encoder: &mut dyn Writer) -> Result<()>; + fn encode(&self, encoder: &mut impl Writer) -> Result<()>; /// Encode this value to the provided byte slice, returning a sub-slice /// containing the encoded message. @@ -37,7 +37,6 @@ pub trait Encode { /// Encode this message as ASN.1 DER, appending it to the provided /// byte vector. #[cfg(feature = "alloc")] - #[cfg_attr(docsrs, doc(cfg(feature = "alloc")))] fn encode_to_vec(&self, buf: &mut Vec<u8>) -> Result<Length> { let expected_len = usize::try_from(self.encoded_len()?)?; buf.reserve(expected_len); @@ -58,10 +57,9 @@ pub trait Encode { actual_len.try_into() } - /// Serialize this message as a byte vector. + /// Encode this type as DER, returning a byte vector. #[cfg(feature = "alloc")] - #[cfg_attr(docsrs, doc(cfg(feature = "alloc")))] - fn to_vec(&self) -> Result<Vec<u8>> { + fn to_der(&self) -> Result<Vec<u8>> { let mut buf = Vec::new(); self.encode_to_vec(&mut buf)?; Ok(buf) @@ -78,7 +76,7 @@ where } /// Encode this value as ASN.1 DER using the provided [`Writer`]. - fn encode(&self, writer: &mut dyn Writer) -> Result<()> { + fn encode(&self, writer: &mut impl Writer) -> Result<()> { self.header()?.encode(writer)?; self.encode_value(writer) } @@ -89,14 +87,12 @@ where /// This trait is automatically impl'd for any type which impls both /// [`Encode`] and [`PemLabel`]. #[cfg(feature = "pem")] -#[cfg_attr(docsrs, doc(cfg(feature = "pem")))] pub trait EncodePem: Encode + PemLabel { /// Try to encode this type as PEM. fn to_pem(&self, line_ending: LineEnding) -> Result<String>; } #[cfg(feature = "pem")] -#[cfg_attr(docsrs, doc(cfg(feature = "pem")))] impl<T: Encode + PemLabel> EncodePem for T { fn to_pem(&self, line_ending: LineEnding) -> Result<String> { let der_len = usize::try_from(self.encoded_len()?)?; @@ -129,5 +125,18 @@ pub trait EncodeValue { /// Encode value (sans [`Tag`]+[`Length`] header) as ASN.1 DER using the /// provided [`Writer`]. - fn encode_value(&self, encoder: &mut dyn Writer) -> Result<()>; + fn encode_value(&self, encoder: &mut impl Writer) -> Result<()>; +} + +#[cfg(feature = "alloc")] +impl<T> EncodeValue for Box<T> +where + T: EncodeValue, +{ + fn value_len(&self) -> Result<Length> { + T::value_len(self) + } + fn encode_value(&self, writer: &mut impl Writer) -> Result<()> { + T::encode_value(self, writer) + } } diff --git a/vendor/der/src/encode_ref.rs b/vendor/der/src/encode_ref.rs index c1e4f03f4..8a60a933f 100644 --- a/vendor/der/src/encode_ref.rs +++ b/vendor/der/src/encode_ref.rs @@ -22,7 +22,7 @@ where self.0.encoded_len() } - fn encode(&self, writer: &mut dyn Writer) -> Result<()> { + fn encode(&self, writer: &mut impl Writer) -> Result<()> { self.0.encode(writer) } } @@ -47,7 +47,7 @@ where self.0.value_len() } - fn encode_value(&self, writer: &mut dyn Writer) -> Result<()> { + fn encode_value(&self, writer: &mut impl Writer) -> Result<()> { self.0.encode_value(writer) } } diff --git a/vendor/der/src/error.rs b/vendor/der/src/error.rs index 5e492a48d..94378ef71 100644 --- a/vendor/der/src/error.rs +++ b/vendor/der/src/error.rs @@ -174,7 +174,6 @@ pub enum ErrorKind { /// File not found error. #[cfg(feature = "std")] - #[cfg_attr(docsrs, doc(cfg(feature = "std")))] FileNotFound, /// Message is incomplete and does not contain all of the expected data. @@ -194,9 +193,11 @@ pub enum ErrorKind { /// I/O errors. #[cfg(feature = "std")] - #[cfg_attr(docsrs, doc(cfg(feature = "std")))] Io(std::io::ErrorKind), + /// Indefinite length disallowed. + IndefiniteLength, + /// Incorrect length for a given field. Length { /// Tag of the value being decoded. @@ -221,7 +222,6 @@ pub enum ErrorKind { /// to determine which OID(s) are causing the error (and then potentially /// contribute upstream support for algorithms they care about). #[cfg(feature = "oid")] - #[cfg_attr(docsrs, doc(cfg(feature = "oid")))] OidUnknown { /// OID value that was unrecognized by a parser for a DER-based format. oid: ObjectIdentifier, @@ -238,12 +238,10 @@ pub enum ErrorKind { /// PEM encoding errors. #[cfg(feature = "pem")] - #[cfg_attr(docsrs, doc(cfg(feature = "pem")))] Pem(pem::Error), /// Permission denied reading file. #[cfg(feature = "std")] - #[cfg_attr(docsrs, doc(cfg(feature = "std")))] PermissionDenied, /// Reader does not support the requested operation. @@ -321,6 +319,7 @@ impl fmt::Display for ErrorKind { ), #[cfg(feature = "std")] ErrorKind::Io(err) => write!(f, "I/O error: {:?}", err), + ErrorKind::IndefiniteLength => write!(f, "indefinite length disallowed"), ErrorKind::Length { tag } => write!(f, "incorrect length for {}", tag), ErrorKind::Noncanonical { tag } => { write!(f, "ASN.1 {} not canonically encoded as DER", tag) diff --git a/vendor/der/src/header.rs b/vendor/der/src/header.rs index ddb484ee7..ad303810c 100644 --- a/vendor/der/src/header.rs +++ b/vendor/der/src/header.rs @@ -44,7 +44,7 @@ impl Encode for Header { self.tag.encoded_len()? + self.length.encoded_len()? } - fn encode(&self, writer: &mut dyn Writer) -> Result<()> { + fn encode(&self, writer: &mut impl Writer) -> Result<()> { self.tag.encode(writer)?; self.length.encode(writer) } diff --git a/vendor/der/src/length.rs b/vendor/der/src/length.rs index 76ee0e997..d183a69fe 100644 --- a/vendor/der/src/length.rs +++ b/vendor/der/src/length.rs @@ -14,6 +14,13 @@ const MAX_DER_OCTETS: usize = 5; /// Maximum length as a `u32` (256 MiB). const MAX_U32: u32 = 0xfff_ffff; +/// Octet identifying an indefinite length as described in X.690 Section +/// 8.1.3.6.1: +/// +/// > The single octet shall have bit 8 set to one, and bits 7 to +/// > 1 set to zero. +const INDEFINITE_LENGTH_OCTET: u8 = 0b10000000; // 0x80 + /// ASN.1-encoded length. /// /// Maximum length is defined by the [`Length::MAX`] constant (256 MiB). @@ -204,7 +211,8 @@ impl<'a> Decode<'a> for Length { match reader.read_byte()? { // Note: per X.690 Section 8.1.3.6.1 the byte 0x80 encodes indefinite // lengths, which are not allowed in DER, so disallow that byte. - len if len < 0x80 => Ok(len.into()), + len if len < INDEFINITE_LENGTH_OCTET => Ok(len.into()), + INDEFINITE_LENGTH_OCTET => Err(ErrorKind::IndefiniteLength.into()), // 1-4 byte variable-sized length prefix tag @ 0x81..=0x84 => { let nbytes = tag.checked_sub(0x80).ok_or(ErrorKind::Overlength)? as usize; @@ -246,7 +254,7 @@ impl Encode for Length { } } - fn encode(&self, writer: &mut dyn Writer) -> Result<()> { + fn encode(&self, writer: &mut impl Writer) -> Result<()> { match self.initial_octet() { Some(tag_byte) => { writer.write_byte(tag_byte)?; @@ -286,9 +294,126 @@ impl fmt::Display for Length { } } +// Implement by hand because the derive would create invalid values. +// Generate a u32 with a valid range. +#[cfg(feature = "arbitrary")] +impl<'a> arbitrary::Arbitrary<'a> for Length { + fn arbitrary(u: &mut arbitrary::Unstructured<'a>) -> arbitrary::Result<Self> { + Ok(Self(u.int_in_range(0..=MAX_U32)?)) + } + + fn size_hint(depth: usize) -> (usize, Option<usize>) { + u32::size_hint(depth) + } +} + +/// Length type with support for indefinite lengths as used by ASN.1 BER, +/// as described in X.690 Section 8.1.3.6: +/// +/// > 8.1.3.6 For the indefinite form, the length octets indicate that the +/// > contents octets are terminated by end-of-contents +/// > octets (see 8.1.5), and shall consist of a single octet. +/// > +/// > 8.1.3.6.1 The single octet shall have bit 8 set to one, and bits 7 to +/// > 1 set to zero. +/// > +/// > 8.1.3.6.2 If this form of length is used, then end-of-contents octets +/// > (see 8.1.5) shall be present in the encoding following the contents +/// > octets. +/// +/// Indefinite lengths are non-canonical and therefore invalid DER, however +/// there are interoperability corner cases where we have little choice but to +/// tolerate some BER productions where this is helpful. +#[derive(Copy, Clone, Debug, Eq, PartialEq, PartialOrd, Ord)] +pub struct IndefiniteLength(Option<Length>); + +impl IndefiniteLength { + /// Length of `0`. + pub const ZERO: Self = Self(Some(Length::ZERO)); + + /// Length of `1`. + pub const ONE: Self = Self(Some(Length::ONE)); + + /// Indefinite length. + pub const INDEFINITE: Self = Self(None); +} + +impl IndefiniteLength { + /// Create a definite length from a type which can be converted into a + /// `Length`. + pub fn new(length: impl Into<Length>) -> Self { + Self(Some(length.into())) + } + + /// Is this length definite? + pub fn is_definite(self) -> bool { + self.0.is_some() + } + /// Is this length indefinite? + pub fn is_indefinite(self) -> bool { + self.0.is_none() + } +} + +impl<'a> Decode<'a> for IndefiniteLength { + fn decode<R: Reader<'a>>(reader: &mut R) -> Result<IndefiniteLength> { + if reader.peek_byte() == Some(INDEFINITE_LENGTH_OCTET) { + // Consume the byte we already peeked at. + let byte = reader.read_byte()?; + debug_assert_eq!(byte, INDEFINITE_LENGTH_OCTET); + + Ok(Self::INDEFINITE) + } else { + Length::decode(reader).map(Into::into) + } + } +} + +impl Encode for IndefiniteLength { + fn encoded_len(&self) -> Result<Length> { + match self.0 { + Some(length) => length.encoded_len(), + None => Ok(Length::ONE), + } + } + + fn encode(&self, writer: &mut impl Writer) -> Result<()> { + match self.0 { + Some(length) => length.encode(writer), + None => writer.write_byte(INDEFINITE_LENGTH_OCTET), + } + } +} + +impl From<Length> for IndefiniteLength { + fn from(length: Length) -> IndefiniteLength { + Self(Some(length)) + } +} + +impl From<Option<Length>> for IndefiniteLength { + fn from(length: Option<Length>) -> IndefiniteLength { + IndefiniteLength(length) + } +} + +impl From<IndefiniteLength> for Option<Length> { + fn from(length: IndefiniteLength) -> Option<Length> { + length.0 + } +} + +impl TryFrom<IndefiniteLength> for Length { + type Error = Error; + + fn try_from(length: IndefiniteLength) -> Result<Length> { + length.0.ok_or_else(|| ErrorKind::IndefiniteLength.into()) + } +} + #[cfg(test)] mod tests { - use super::Length; + use super::{IndefiniteLength, Length}; use crate::{Decode, DerOrd, Encode, ErrorKind}; use core::cmp::Ordering; @@ -355,8 +480,22 @@ mod tests { } #[test] - fn reject_indefinite_lengths() { + fn indefinite_lengths() { + // DER disallows indefinite lengths assert!(Length::from_der(&[0x80]).is_err()); + + // The `IndefiniteLength` type supports them + let indefinite_length = IndefiniteLength::from_der(&[0x80]).unwrap(); + assert!(indefinite_length.is_indefinite()); + assert_eq!(indefinite_length, IndefiniteLength::INDEFINITE); + + // It also supports definite lengths. + let length = IndefiniteLength::from_der(&[0x83, 0x01, 0x00, 0x00]).unwrap(); + assert!(length.is_definite()); + assert_eq!( + Length::try_from(0x10000u32).unwrap(), + length.try_into().unwrap() + ); } #[test] diff --git a/vendor/der/src/lib.rs b/vendor/der/src/lib.rs index 413b2e4af..dcd5097d4 100644 --- a/vendor/der/src/lib.rs +++ b/vendor/der/src/lib.rs @@ -1,5 +1,5 @@ #![no_std] -#![cfg_attr(docsrs, feature(doc_cfg))] +#![cfg_attr(docsrs, feature(doc_auto_cfg))] #![doc = include_str!("../README.md")] #![doc( html_logo_url = "https://raw.githubusercontent.com/RustCrypto/media/6ee8e381/logo.svg", @@ -15,6 +15,7 @@ clippy::checked_conversions, clippy::implicit_saturating_sub, clippy::integer_arithmetic, + clippy::mod_module_files, clippy::panic, clippy::panic_in_result_fn, clippy::unwrap_used, @@ -56,7 +57,7 @@ //! - [`VideotexStringRef`]: ASN.1 `VideotexString`. //! - [`SequenceOf`]: ASN.1 `SEQUENCE OF`. //! - [`SetOf`], [`SetOfVec`]: ASN.1 `SET OF`. -//! - [`UIntRef`]: ASN.1 unsigned `INTEGER` with raw access to encoded bytes. +//! - [`UintRef`]: ASN.1 unsigned `INTEGER` with raw access to encoded bytes. //! - [`UtcTime`]: ASN.1 `UTCTime`. //! - [`Utf8StringRef`]: ASN.1 `UTF8String`. //! @@ -139,33 +140,20 @@ //! } //! } //! -//! impl<'a> Sequence<'a> for AlgorithmIdentifier<'a> { -//! // The `Sequence::fields` method is used for encoding and functions as -//! // a visitor for all of the fields in a message. -//! // -//! // To implement it, you must define a slice containing `Encode` -//! // trait objects, then pass it to the provided `field_encoder` -//! // function, which is implemented by the `der` crate and handles -//! // message serialization. -//! // -//! // Trait objects are used because they allow for slices containing -//! // heterogeneous field types, and a callback is used to allow for the -//! // construction of temporary field encoder types. The latter means -//! // that the fields of your Rust struct don't necessarily need to -//! // impl the `Encode` trait, but if they don't you must construct -//! // a temporary wrapper value which does. -//! // -//! // Types which impl the `Sequence` trait receive blanket impls of both -//! // the `Encode` and `Tagged` traits (where the latter is impl'd as -//! // `Tagged::TAG = der::Tag::Sequence`. -//! fn fields<F, T>(&self, field_encoder: F) -> der::Result<T> -//! where -//! F: FnOnce(&[&dyn Encode]) -> der::Result<T>, -//! { -//! field_encoder(&[&self.algorithm, &self.parameters]) +//! impl<'a> ::der::EncodeValue for AlgorithmIdentifier<'a> { +//! fn value_len(&self) -> ::der::Result<::der::Length> { +//! self.algorithm.encoded_len()? + self.parameters.encoded_len()? +//! } +//! +//! fn encode_value(&self, writer: &mut impl ::der::Writer) -> ::der::Result<()> { +//! self.algorithm.encode(writer)?; +//! self.parameters.encode(writer)?; +//! Ok(()) //! } //! } //! +//! impl<'a> Sequence<'a> for AlgorithmIdentifier<'a> {} +//! //! // Example parameters value: OID for the NIST P-256 elliptic curve. //! let parameters = "1.2.840.10045.3.1.7".parse::<ObjectIdentifier>().unwrap(); //! @@ -182,7 +170,7 @@ //! // If you would prefer to avoid allocations, you can create a byte array //! // as backing storage instead, pass that to `der::Encoder::new`, and then //! // encode the `parameters` value using `encoder.encode(parameters)`. -//! let der_encoded_parameters = parameters.to_vec().unwrap(); +//! let der_encoded_parameters = parameters.to_der().unwrap(); //! //! let algorithm_identifier = AlgorithmIdentifier { //! // OID for `id-ecPublicKey`, if you're curious @@ -201,7 +189,7 @@ //! // reference to it, then encode the message using //! // `encoder.encode(algorithm_identifier)`, then finally `encoder.finish()` //! // to obtain a byte slice containing the encoded message. -//! let der_encoded_algorithm_identifier = algorithm_identifier.to_vec().unwrap(); +//! let der_encoded_algorithm_identifier = algorithm_identifier.to_der().unwrap(); //! //! // Deserialize the `AlgorithmIdentifier` we just serialized from ASN.1 DER //! // using `der::Decode::from_bytes`. @@ -255,7 +243,7 @@ //! }; //! //! // Encode -//! let der_encoded_algorithm_identifier = algorithm_identifier.to_vec().unwrap(); +//! let der_encoded_algorithm_identifier = algorithm_identifier.to_der().unwrap(); //! //! // Decode //! let decoded_algorithm_identifier = AlgorithmIdentifier::from_der( @@ -328,7 +316,7 @@ //! [`SequenceOf`]: asn1::SequenceOf //! [`SetOf`]: asn1::SetOf //! [`SetOfVec`]: asn1::SetOfVec -//! [`UIntRef`]: asn1::UIntRef +//! [`UintRef`]: asn1::UintRef //! [`UtcTime`]: asn1::UtcTime //! [`Utf8StringRef`]: asn1::Utf8StringRef @@ -340,9 +328,10 @@ extern crate alloc; extern crate std; pub mod asn1; +pub mod referenced; pub(crate) mod arrayvec; -mod byte_slice; +mod bytes_ref; mod datetime; mod decode; mod encode; @@ -352,12 +341,16 @@ mod header; mod length; mod ord; mod reader; -mod str_slice; +mod str_ref; mod tag; mod writer; #[cfg(feature = "alloc")] +mod bytes_owned; +#[cfg(feature = "alloc")] mod document; +#[cfg(feature = "alloc")] +mod str_owned; pub use crate::{ asn1::{AnyRef, Choice, Sequence}, @@ -367,37 +360,35 @@ pub use crate::{ encode_ref::{EncodeRef, EncodeValueRef}, error::{Error, ErrorKind, Result}, header::Header, - length::Length, + length::{IndefiniteLength, Length}, ord::{DerOrd, ValueOrd}, - reader::{slice::SliceReader, Reader}, + reader::{nested::NestedReader, slice::SliceReader, Reader}, tag::{Class, FixedTag, Tag, TagMode, TagNumber, Tagged}, writer::{slice::SliceWriter, Writer}, }; #[cfg(feature = "alloc")] -pub use crate::document::Document; +pub use crate::{asn1::Any, document::Document}; #[cfg(feature = "bigint")] -#[cfg_attr(docsrs, doc(cfg(feature = "bigint")))] pub use crypto_bigint as bigint; #[cfg(feature = "derive")] -#[cfg_attr(docsrs, doc(cfg(feature = "derive")))] pub use der_derive::{Choice, Enumerated, Sequence, ValueOrd}; +#[cfg(feature = "flagset")] +pub use flagset; + #[cfg(feature = "oid")] -#[cfg_attr(docsrs, doc(cfg(feature = "oid")))] pub use const_oid as oid; #[cfg(feature = "pem")] -#[cfg_attr(docsrs, doc(cfg(feature = "pem")))] pub use { crate::{decode::DecodePem, encode::EncodePem, reader::pem::PemReader, writer::pem::PemWriter}, pem_rfc7468 as pem, }; #[cfg(feature = "time")] -#[cfg_attr(docsrs, doc(cfg(feature = "time")))] pub use time; #[cfg(feature = "zeroize")] @@ -406,4 +397,6 @@ pub use zeroize; #[cfg(all(feature = "alloc", feature = "zeroize"))] pub use crate::document::SecretDocument; -pub(crate) use crate::{arrayvec::ArrayVec, byte_slice::ByteSlice, str_slice::StrSlice}; +pub(crate) use crate::{arrayvec::ArrayVec, bytes_ref::BytesRef, str_ref::StrRef}; +#[cfg(feature = "alloc")] +pub(crate) use crate::{bytes_owned::BytesOwned, str_owned::StrOwned}; diff --git a/vendor/der/src/reader.rs b/vendor/der/src/reader.rs index b917323c2..ea52f7bde 100644 --- a/vendor/der/src/reader.rs +++ b/vendor/der/src/reader.rs @@ -1,6 +1,6 @@ //! Reader trait. -mod nested; +pub(crate) mod nested; #[cfg(feature = "pem")] pub(crate) mod pem; pub(crate) mod slice; @@ -135,7 +135,6 @@ pub trait Reader<'r>: Sized { /// Read a byte vector of the given length. #[cfg(feature = "alloc")] - #[cfg_attr(docsrs, doc(cfg(feature = "alloc")))] fn read_vec(&mut self, len: Length) -> Result<Vec<u8>> { let mut bytes = vec![0u8; usize::try_from(len)?]; self.read_into(&mut bytes)?; diff --git a/vendor/der/src/reader/pem.rs b/vendor/der/src/reader/pem.rs index 01bb4f20e..f11341aa6 100644 --- a/vendor/der/src/reader/pem.rs +++ b/vendor/der/src/reader/pem.rs @@ -1,16 +1,134 @@ //! Streaming PEM reader. use super::Reader; -use crate::{ErrorKind, Header, Length, Result}; -use pem_rfc7468::Decoder; +use crate::{Decode, Error, ErrorKind, Header, Length, Result}; +use core::cell::RefCell; + +#[allow(clippy::integer_arithmetic)] +mod utils { + use crate::{Error, Length, Result}; + use pem_rfc7468::Decoder; + + #[derive(Clone)] + pub(super) struct BufReader<'i> { + /// Inner PEM decoder. + decoder: Decoder<'i>, + + /// Remaining after base64 decoding + remaining: usize, + + /// Read buffer + buf: [u8; BufReader::CAPACITY], + + /// Position of the head in the buffer, + pos: usize, + + /// Position of the tail in the buffer, + cap: usize, + } + + impl<'i> BufReader<'i> { + const CAPACITY: usize = 256; + + pub fn new(pem: &'i [u8]) -> Result<Self> { + let decoder = Decoder::new(pem)?; + let remaining = decoder.remaining_len(); + + Ok(Self { + decoder, + remaining, + buf: [0u8; 256], + pos: 0, + cap: 0, + }) + } + + pub fn remaining_len(&self) -> usize { + self.decoder.remaining_len() + self.cap - self.pos + } + + fn fill_buffer(&mut self) -> Result<()> { + debug_assert!(self.pos <= self.cap); + + if self.is_empty() { + self.pos = 0; + self.cap = 0; + } + + let end = (self.cap + self.remaining).min(Self::CAPACITY); + let writable_slice = &mut self.buf[self.cap..end]; + if writable_slice.is_empty() { + return Ok(()); + } + + let wrote = self.decoder.decode(writable_slice)?.len(); + if wrote == 0 { + return Err(Error::incomplete(Length::try_from(self.pos)?)); + } + + self.cap += wrote; + self.remaining -= wrote; + debug_assert!(self.cap <= Self::CAPACITY); + + Ok(()) + } + + /// Get the PEM label which will be used in the encapsulation boundaries + /// for this document. + pub fn type_label(&self) -> &'i str { + self.decoder.type_label() + } + + fn is_empty(&self) -> bool { + self.pos == self.cap + } + + fn as_slice(&self) -> &[u8] { + &self.buf[self.pos..self.cap] + } + } + + impl<'i> BufReader<'i> { + pub fn peek_byte(&self) -> Option<u8> { + let s = self.as_slice(); + s.first().copied() + } + + pub fn copy_to_slice<'o>(&mut self, buf: &'o mut [u8]) -> Result<&'o [u8]> { + let mut output_pos = 0; + + while output_pos < buf.len() { + if self.is_empty() { + self.fill_buffer()?; + } + + let available = &self.buf[self.pos..self.cap]; + let window_len = (buf.len() - output_pos).min(available.len()); + let window = &mut buf[output_pos..output_pos + window_len]; + + window.copy_from_slice(&available[..window_len]); + self.pos += window_len; + output_pos += window_len; + } + + // Don't leave the read buffer empty for peek_byte() + if self.is_empty() && self.decoder.remaining_len() != 0 { + self.fill_buffer()? + } + + debug_assert_eq!(output_pos, buf.len()); + + Ok(buf) + } + } +} /// `Reader` type which decodes PEM on-the-fly. #[cfg(feature = "pem")] -#[cfg_attr(docsrs, doc(cfg(feature = "pem")))] #[derive(Clone)] pub struct PemReader<'i> { - /// Inner PEM decoder. - decoder: Decoder<'i>, + /// Inner PEM decoder wrapped in a BufReader. + reader: RefCell<utils::BufReader<'i>>, /// Input length (in bytes after Base64 decoding). input_len: Length, @@ -20,17 +138,16 @@ pub struct PemReader<'i> { } #[cfg(feature = "pem")] -#[cfg_attr(docsrs, doc(cfg(feature = "pem")))] impl<'i> PemReader<'i> { /// Create a new PEM reader which decodes data on-the-fly. /// /// Uses the default 64-character line wrapping. pub fn new(pem: &'i [u8]) -> Result<Self> { - let decoder = Decoder::new(pem)?; - let input_len = Length::try_from(decoder.remaining_len())?; + let reader = utils::BufReader::new(pem)?; + let input_len = Length::try_from(reader.remaining_len())?; Ok(Self { - decoder, + reader: RefCell::new(reader), input_len, position: Length::ZERO, }) @@ -39,25 +156,30 @@ impl<'i> PemReader<'i> { /// Get the PEM label which will be used in the encapsulation boundaries /// for this document. pub fn type_label(&self) -> &'i str { - self.decoder.type_label() + self.reader.borrow().type_label() } } #[cfg(feature = "pem")] -#[cfg_attr(docsrs, doc(cfg(feature = "pem")))] impl<'i> Reader<'i> for PemReader<'i> { fn input_len(&self) -> Length { self.input_len } fn peek_byte(&self) -> Option<u8> { - // TODO(tarcieri): lookahead buffer - None + if self.is_finished() { + None + } else { + self.reader.borrow().peek_byte() + } } fn peek_header(&self) -> Result<Header> { - // TODO(tarcieri): lookahead buffer - Err(ErrorKind::Reader.into()) + if self.is_finished() { + Err(Error::incomplete(self.offset())) + } else { + Header::decode(&mut self.clone()) + } } fn position(&self) -> Length { @@ -70,12 +192,13 @@ impl<'i> Reader<'i> for PemReader<'i> { } fn read_into<'o>(&mut self, buf: &'o mut [u8]) -> Result<&'o [u8]> { - let bytes = self.decoder.decode(buf)?; + let bytes = self.reader.borrow_mut().copy_to_slice(buf)?; + self.position = (self.position + bytes.len())?; debug_assert_eq!( self.position, - (self.input_len - Length::try_from(self.decoder.remaining_len())?)? + (self.input_len - Length::try_from(self.reader.borrow().remaining_len())?)? ); Ok(bytes) diff --git a/vendor/der/src/reader/slice.rs b/vendor/der/src/reader/slice.rs index 6bab091f3..e78468fed 100644 --- a/vendor/der/src/reader/slice.rs +++ b/vendor/der/src/reader/slice.rs @@ -1,12 +1,12 @@ //! Slice reader. -use crate::{ByteSlice, Decode, Error, ErrorKind, Header, Length, Reader, Result, Tag}; +use crate::{BytesRef, Decode, Error, ErrorKind, Header, Length, Reader, Result, Tag}; /// [`Reader`] which consumes an input byte slice. #[derive(Clone, Debug)] pub struct SliceReader<'a> { /// Byte slice being decoded. - bytes: ByteSlice<'a>, + bytes: BytesRef<'a>, /// Did the decoding operation fail? failed: bool, @@ -19,7 +19,7 @@ impl<'a> SliceReader<'a> { /// Create a new slice reader for the given byte slice. pub fn new(bytes: &'a [u8]) -> Result<Self> { Ok(Self { - bytes: ByteSlice::new(bytes)?, + bytes: BytesRef::new(bytes)?, failed: false, position: Length::ZERO, }) @@ -64,7 +64,7 @@ impl<'a> Reader<'a> for SliceReader<'a> { fn peek_byte(&self) -> Option<u8> { self.remaining() .ok() - .and_then(|bytes| bytes.get(0).cloned()) + .and_then(|bytes| bytes.first().cloned()) } fn peek_header(&self) -> Result<Header> { diff --git a/vendor/der/src/referenced.rs b/vendor/der/src/referenced.rs new file mode 100644 index 000000000..bb920db3a --- /dev/null +++ b/vendor/der/src/referenced.rs @@ -0,0 +1,47 @@ +//! A module for working with referenced data. + +/// A trait for borrowing data from an owned struct +pub trait OwnedToRef { + /// The resulting type referencing back to Self + type Borrowed<'a> + where + Self: 'a; + + /// Creates a new object referencing back to the self for storage + fn owned_to_ref(&self) -> Self::Borrowed<'_>; +} + +/// A trait for cloning a referenced structure and getting owned objects +/// +/// This is the pendant to [`OwnedToRef`] +pub trait RefToOwned<'a> { + /// The resulting type after obtaining ownership. + type Owned: OwnedToRef<Borrowed<'a> = Self> + where + Self: 'a; + + /// Creates a new object taking ownership of the data + fn ref_to_owned(&self) -> Self::Owned; +} + +impl<T> OwnedToRef for Option<T> +where + T: OwnedToRef, +{ + type Borrowed<'a> = Option<T::Borrowed<'a>> where T: 'a; + + fn owned_to_ref(&self) -> Self::Borrowed<'_> { + self.as_ref().map(|o| o.owned_to_ref()) + } +} + +impl<'a, T> RefToOwned<'a> for Option<T> +where + T: RefToOwned<'a> + 'a, + T::Owned: OwnedToRef, +{ + type Owned = Option<T::Owned>; + fn ref_to_owned(&self) -> Self::Owned { + self.as_ref().map(|o| o.ref_to_owned()) + } +} diff --git a/vendor/der/src/str_owned.rs b/vendor/der/src/str_owned.rs new file mode 100644 index 000000000..25c258e4f --- /dev/null +++ b/vendor/der/src/str_owned.rs @@ -0,0 +1,105 @@ +//! Common handling for types backed by `String` with enforcement of a +//! library-level length limitation i.e. `Length::max()`. + +use crate::{ + referenced::OwnedToRef, BytesRef, DecodeValue, EncodeValue, Header, Length, Reader, Result, + StrRef, Writer, +}; +use alloc::string::String; +use core::str; + +/// String newtype which respects the [`Length::max`] limit. +#[derive(Clone, Debug, Eq, PartialEq, PartialOrd, Ord)] +pub struct StrOwned { + /// Inner value + pub(crate) inner: String, + + /// Precomputed `Length` (avoids possible panicking conversions) + pub(crate) length: Length, +} + +impl StrOwned { + /// Create a new [`StrOwned`], ensuring that the byte representation of + /// the provided `str` value is shorter than `Length::max()`. + pub fn new(s: &str) -> Result<Self> { + Ok(Self { + inner: String::from(s), + length: Length::try_from(s.as_bytes().len())?, + }) + } + + /// Parse a [`String`] from UTF-8 encoded bytes. + pub fn from_bytes(bytes: &[u8]) -> Result<Self> { + Ok(Self { + inner: String::from_utf8(bytes.to_vec())?, + length: Length::try_from(bytes.len())?, + }) + } + + /// Borrow the inner `str` + pub fn as_str(&self) -> &str { + &self.inner + } + + /// Borrow the inner byte slice + pub fn as_bytes(&self) -> &[u8] { + self.inner.as_bytes() + } + + /// Get the [`Length`] of this [`StrOwned`] + pub fn len(&self) -> Length { + self.length + } + + /// Is this [`StrOwned`] empty? + pub fn is_empty(&self) -> bool { + self.len() == Length::ZERO + } +} + +impl AsRef<str> for StrOwned { + fn as_ref(&self) -> &str { + self.as_str() + } +} + +impl AsRef<[u8]> for StrOwned { + fn as_ref(&self) -> &[u8] { + self.as_bytes() + } +} + +impl<'a> DecodeValue<'a> for StrOwned { + fn decode_value<R: Reader<'a>>(reader: &mut R, header: Header) -> Result<Self> { + Self::from_bytes(BytesRef::decode_value(reader, header)?.as_slice()) + } +} + +impl EncodeValue for StrOwned { + fn value_len(&self) -> Result<Length> { + Ok(self.length) + } + + fn encode_value(&self, writer: &mut impl Writer) -> Result<()> { + writer.write(self.as_ref()) + } +} + +impl From<StrRef<'_>> for StrOwned { + fn from(s: StrRef<'_>) -> StrOwned { + Self { + inner: String::from(s.inner), + length: s.length, + } + } +} + +impl OwnedToRef for StrOwned { + type Borrowed<'a> = StrRef<'a>; + fn owned_to_ref(&self) -> Self::Borrowed<'_> { + StrRef { + length: self.length, + inner: self.inner.as_ref(), + } + } +} diff --git a/vendor/der/src/str_slice.rs b/vendor/der/src/str_ref.rs index 8c94528aa..899c7506b 100644 --- a/vendor/der/src/str_slice.rs +++ b/vendor/der/src/str_ref.rs @@ -1,12 +1,12 @@ //! Common handling for types backed by `str` slices with enforcement of a //! library-level length limitation i.e. `Length::max()`. -use crate::{ByteSlice, DecodeValue, EncodeValue, Header, Length, Reader, Result, Writer}; +use crate::{BytesRef, DecodeValue, EncodeValue, Header, Length, Reader, Result, Writer}; use core::str; /// String slice newtype which respects the [`Length::max`] limit. #[derive(Copy, Clone, Debug, Eq, PartialEq, PartialOrd, Ord)] -pub struct StrSlice<'a> { +pub struct StrRef<'a> { /// Inner value pub(crate) inner: &'a str, @@ -14,8 +14,8 @@ pub struct StrSlice<'a> { pub(crate) length: Length, } -impl<'a> StrSlice<'a> { - /// Create a new [`StrSlice`], ensuring that the byte representation of +impl<'a> StrRef<'a> { + /// Create a new [`StrRef`], ensuring that the byte representation of /// the provided `str` value is shorter than `Length::max()`. pub fn new(s: &'a str) -> Result<Self> { Ok(Self { @@ -24,7 +24,7 @@ impl<'a> StrSlice<'a> { }) } - /// Parse a [`StrSlice`] from UTF-8 encoded bytes. + /// Parse a [`StrRef`] from UTF-8 encoded bytes. pub fn from_bytes(bytes: &'a [u8]) -> Result<Self> { Self::new(str::from_utf8(bytes)?) } @@ -39,41 +39,54 @@ impl<'a> StrSlice<'a> { self.inner.as_bytes() } - /// Get the [`Length`] of this [`StrSlice`] + /// Get the [`Length`] of this [`StrRef`] pub fn len(self) -> Length { self.length } - /// Is this [`StrSlice`] empty? + /// Is this [`StrRef`] empty? pub fn is_empty(self) -> bool { self.len() == Length::ZERO } } -impl AsRef<str> for StrSlice<'_> { +impl AsRef<str> for StrRef<'_> { fn as_ref(&self) -> &str { self.as_str() } } -impl AsRef<[u8]> for StrSlice<'_> { +impl AsRef<[u8]> for StrRef<'_> { fn as_ref(&self) -> &[u8] { self.as_bytes() } } -impl<'a> DecodeValue<'a> for StrSlice<'a> { +impl<'a> DecodeValue<'a> for StrRef<'a> { fn decode_value<R: Reader<'a>>(reader: &mut R, header: Header) -> Result<Self> { - Self::from_bytes(ByteSlice::decode_value(reader, header)?.as_slice()) + Self::from_bytes(BytesRef::decode_value(reader, header)?.as_slice()) } } -impl<'a> EncodeValue for StrSlice<'a> { +impl<'a> EncodeValue for StrRef<'a> { fn value_len(&self) -> Result<Length> { Ok(self.length) } - fn encode_value(&self, writer: &mut dyn Writer) -> Result<()> { + fn encode_value(&self, writer: &mut impl Writer) -> Result<()> { writer.write(self.as_ref()) } } + +#[cfg(feature = "alloc")] +mod allocating { + use super::StrRef; + use crate::{referenced::RefToOwned, StrOwned}; + + impl<'a> RefToOwned<'a> for StrRef<'a> { + type Owned = StrOwned; + fn ref_to_owned(&self) -> Self::Owned { + StrOwned::from(*self) + } + } +} diff --git a/vendor/der/src/tag.rs b/vendor/der/src/tag.rs index 0e7bf2013..b0853a846 100644 --- a/vendor/der/src/tag.rs +++ b/vendor/der/src/tag.rs @@ -1,4 +1,5 @@ //! ASN.1 tags. +#![cfg_attr(feature = "arbitrary", allow(clippy::integer_arithmetic))] mod class; mod mode; @@ -46,6 +47,7 @@ impl<T: FixedTag> Tagged for T { /// - Bits 8/7: [`Class`] /// - Bit 6: primitive (0) or constructed (1) /// - Bits 5-1: tag number +#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))] #[derive(Copy, Clone, Eq, PartialEq, PartialOrd, Ord)] #[non_exhaustive] pub enum Tag { @@ -323,7 +325,7 @@ impl Encode for Tag { Ok(Length::ONE) } - fn encode(&self, writer: &mut dyn Writer) -> Result<()> { + fn encode(&self, writer: &mut impl Writer) -> Result<()> { writer.write_byte(self.into()) } } diff --git a/vendor/der/src/tag/mode.rs b/vendor/der/src/tag/mode.rs index 892ce3d81..ecdaf023a 100644 --- a/vendor/der/src/tag/mode.rs +++ b/vendor/der/src/tag/mode.rs @@ -4,11 +4,12 @@ use crate::{Error, ErrorKind, Result}; use core::{fmt, str::FromStr}; /// Tagging modes: `EXPLICIT` versus `IMPLICIT`. -#[derive(Copy, Clone, Debug, Eq, PartialEq, PartialOrd, Ord)] +#[derive(Copy, Clone, Debug, Default, Eq, PartialEq, PartialOrd, Ord)] pub enum TagMode { /// `EXPLICIT` tagging. /// /// Tag is added in addition to the inner tag of the type. + #[default] Explicit, /// `IMPLICIT` tagging. @@ -17,12 +18,6 @@ pub enum TagMode { Implicit, } -impl Default for TagMode { - fn default() -> TagMode { - TagMode::Explicit - } -} - impl FromStr for TagMode { type Err = Error; diff --git a/vendor/der/src/tag/number.rs b/vendor/der/src/tag/number.rs index 1930e9436..6a7eaae22 100644 --- a/vendor/der/src/tag/number.rs +++ b/vendor/der/src/tag/number.rs @@ -186,3 +186,16 @@ impl fmt::Display for TagNumber { write!(f, "{}", self.0) } } + +// Implement by hand because the derive would create invalid values. +// Use the constructor to create a valid value. +#[cfg(feature = "arbitrary")] +impl<'a> arbitrary::Arbitrary<'a> for TagNumber { + fn arbitrary(u: &mut arbitrary::Unstructured<'a>) -> arbitrary::Result<Self> { + Ok(Self::new(u.int_in_range(0..=Self::MAX)?)) + } + + fn size_hint(depth: usize) -> (usize, Option<usize>) { + u8::size_hint(depth) + } +} diff --git a/vendor/der/src/writer.rs b/vendor/der/src/writer.rs index 5e9774413..164b215f7 100644 --- a/vendor/der/src/writer.rs +++ b/vendor/der/src/writer.rs @@ -21,7 +21,6 @@ pub trait Writer { } #[cfg(feature = "std")] -#[cfg_attr(docsrs, doc(cfg(feature = "std")))] impl<W: io::Write> Writer for W { fn write(&mut self, slice: &[u8]) -> Result<()> { <Self as io::Write>::write(self, slice)?; diff --git a/vendor/der/src/writer/pem.rs b/vendor/der/src/writer/pem.rs index c554632a8..87a6f8fd8 100644 --- a/vendor/der/src/writer/pem.rs +++ b/vendor/der/src/writer/pem.rs @@ -5,7 +5,6 @@ use crate::Result; use pem_rfc7468::{Encoder, LineEnding}; /// `Writer` type which outputs PEM-encoded data. -#[cfg_attr(docsrs, doc(cfg(feature = "pem")))] pub struct PemWriter<'w>(Encoder<'static, 'w>); impl<'w> PemWriter<'w> { |