chore: checkpoint before Python removal

This commit is contained in:
2026-03-26 22:33:59 +00:00
parent 683cec9307
commit e568ddf82a
29972 changed files with 11269302 additions and 2 deletions

145
vendor/der/src/arrayvec.rs vendored Normal file
View File

@@ -0,0 +1,145 @@
//! Array-backed append-only vector type.
// TODO(tarcieri): use `core` impl of `ArrayVec`
// See: https://github.com/rust-lang/rfcs/pull/2990
use crate::{ErrorKind, Result};
/// Array-backed append-only vector type.
#[derive(Clone, Debug, Eq, PartialEq, PartialOrd, Ord)]
pub(crate) struct ArrayVec<T, const N: usize> {
/// Elements of the set.
elements: [Option<T>; N],
/// Last populated element.
length: usize,
}
impl<T, const N: usize> ArrayVec<T, N> {
/// Create a new [`ArrayVec`].
pub fn new() -> Self {
Self {
elements: [(); N].map(|_| None),
length: 0,
}
}
/// Push an item into this [`ArrayVec`].
pub fn push(&mut self, item: T) -> Result<()> {
match self.length.checked_add(1) {
Some(n) if n <= N => {
self.elements[self.length] = Some(item);
self.length = n;
Ok(())
}
_ => Err(ErrorKind::Overlength.into()),
}
}
/// Get an element from this [`ArrayVec`].
pub fn get(&self, index: usize) -> Option<&T> {
match self.elements.get(index) {
Some(Some(ref item)) => Some(item),
_ => None,
}
}
/// Iterate over the elements in this [`ArrayVec`].
pub fn iter(&self) -> Iter<'_, T> {
Iter::new(&self.elements)
}
/// Is this [`ArrayVec`] empty?
pub fn is_empty(&self) -> bool {
self.length == 0
}
/// Get the number of elements in this [`ArrayVec`].
pub fn len(&self) -> usize {
self.length
}
/// Get the last item from this [`ArrayVec`].
pub fn last(&self) -> Option<&T> {
self.length.checked_sub(1).and_then(|n| self.get(n))
}
/// Extract the inner array.
pub fn into_array(self) -> [Option<T>; N] {
self.elements
}
}
impl<T, const N: usize> AsRef<[Option<T>]> for ArrayVec<T, N> {
fn as_ref(&self) -> &[Option<T>] {
&self.elements[..self.length]
}
}
impl<T, const N: usize> AsMut<[Option<T>]> for ArrayVec<T, N> {
fn as_mut(&mut self) -> &mut [Option<T>] {
&mut self.elements[..self.length]
}
}
impl<T, const N: usize> Default for ArrayVec<T, N> {
fn default() -> Self {
Self::new()
}
}
/// Iterator over the elements of an [`ArrayVec`].
#[derive(Clone, Debug)]
pub struct Iter<'a, T> {
/// Decoder which iterates over the elements of the message.
elements: &'a [Option<T>],
/// Position within the iterator.
position: usize,
}
impl<'a, T> Iter<'a, T> {
pub(crate) fn new(elements: &'a [Option<T>]) -> Self {
Self {
elements,
position: 0,
}
}
}
impl<'a, T> Iterator for Iter<'a, T> {
type Item = &'a T;
fn next(&mut self) -> Option<&'a T> {
match self.elements.get(self.position) {
Some(Some(res)) => {
self.position = self.position.checked_add(1)?;
Some(res)
}
_ => None,
}
}
fn size_hint(&self) -> (usize, Option<usize>) {
let len = self.elements.len().saturating_sub(self.position);
(len, Some(len))
}
}
impl<'a, T> ExactSizeIterator for Iter<'a, T> {}
#[cfg(test)]
mod tests {
use super::ArrayVec;
use crate::ErrorKind;
#[test]
fn add() {
let mut vec = ArrayVec::<u8, 3>::new();
vec.push(1).unwrap();
vec.push(2).unwrap();
vec.push(3).unwrap();
assert_eq!(vec.push(4).err().unwrap(), ErrorKind::Overlength.into());
assert_eq!(vec.len(), 3);
}
}

67
vendor/der/src/asn1.rs vendored Normal file
View File

@@ -0,0 +1,67 @@
//! 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;
#[cfg(feature = "alloc")]
mod bmp_string;
mod boolean;
mod choice;
mod context_specific;
mod generalized_time;
mod ia5_string;
mod integer;
mod null;
mod octet_string;
#[cfg(feature = "oid")]
mod oid;
mod optional;
mod printable_string;
#[cfg(feature = "real")]
mod real;
mod sequence;
mod sequence_of;
mod set_of;
mod teletex_string;
mod utc_time;
mod utf8_string;
mod videotex_string;
pub use self::{
any::AnyRef,
bit_string::{BitStringIter, BitStringRef},
choice::Choice,
context_specific::{ContextSpecific, ContextSpecificRef},
generalized_time::GeneralizedTime,
ia5_string::Ia5StringRef,
integer::{int::IntRef, uint::UintRef},
null::Null,
octet_string::OctetStringRef,
printable_string::PrintableStringRef,
sequence::{Sequence, SequenceRef},
sequence_of::{SequenceOf, SequenceOfIter},
set_of::{SetOf, SetOfIter},
teletex_string::TeletexStringRef,
utc_time::UtcTime,
utf8_string::Utf8StringRef,
videotex_string::VideotexStringRef,
};
#[cfg(feature = "alloc")]
pub use self::{
any::Any,
bit_string::BitString,
bmp_string::BmpString,
ia5_string::Ia5String,
integer::{int::Int, uint::Uint},
octet_string::OctetString,
printable_string::PrintableString,
set_of::SetOfVec,
teletex_string::TeletexString,
};
#[cfg(feature = "oid")]
pub use const_oid::ObjectIdentifier;

315
vendor/der/src/asn1/any.rs vendored Normal file
View File

@@ -0,0 +1,315 @@
//! ASN.1 `ANY` type.
#![cfg_attr(feature = "arbitrary", allow(clippy::integer_arithmetic))]
use crate::{
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 crate::SliceWriter;
/// ASN.1 `ANY`: represents any explicitly tagged ASN.1 value.
///
/// This is a zero-copy reference type which borrows from the input data.
///
/// Technically `ANY` hasn't been a recommended part of ASN.1 since the X.209
/// revision from 1988. It was deprecated and replaced by Information Object
/// Classes in X.680 in 1994, and X.690 no longer refers to it whatsoever.
///
/// 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: BytesRef<'a>,
}
impl<'a> AnyRef<'a> {
/// [`AnyRef`] representation of the ASN.1 `NULL` type.
pub const NULL: Self = Self {
tag: Tag::Null,
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 = BytesRef::new(bytes).map_err(|_| ErrorKind::Length { tag })?;
Ok(Self { tag, value })
}
/// Infallible creation of an [`AnyRef`] from a [`BytesRef`].
pub(crate) fn from_tag_and_value(tag: Tag, value: BytesRef<'a>) -> Self {
Self { tag, value }
}
/// Get the raw value for this [`AnyRef`] type as a byte slice.
pub fn value(self) -> &'a [u8] {
self.value.as_slice()
}
/// Attempt to decode this [`AnyRef`] type into the inner value.
pub fn decode_as<T>(self) -> Result<T>
where
T: Choice<'a> + DecodeValue<'a>,
{
if !T::can_decode(self.tag) {
return Err(self.tag.unexpected_error(None));
}
let header = Header {
tag: self.tag,
length: self.value.len(),
};
let mut decoder = SliceReader::new(self.value())?;
let result = T::decode_value(&mut decoder, header)?;
decoder.finish(result)
}
/// Is this value an ASN.1 `NULL` value?
pub fn is_null(self) -> bool {
self == Self::NULL
}
/// 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>
where
F: FnOnce(&mut SliceReader<'a>) -> Result<T>,
{
self.tag.assert_eq(Tag::Sequence)?;
let mut reader = SliceReader::new(self.value.as_slice())?;
let result = f(&mut reader)?;
reader.finish(result)
}
}
impl<'a> Choice<'a> for AnyRef<'a> {
fn can_decode(_: Tag) -> bool {
true
}
}
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: BytesRef::decode_value(reader, header)?,
})
}
}
impl EncodeValue for AnyRef<'_> {
fn value_len(&self) -> Result<Length> {
Ok(self.value.len())
}
fn encode_value(&self, writer: &mut impl Writer) -> Result<()> {
writer.write(self.value())
}
}
impl Tagged for AnyRef<'_> {
fn tag(&self) -> Tag {
self.tag
}
}
impl ValueOrd for AnyRef<'_> {
fn value_cmp(&self, other: &Self) -> Result<Ordering> {
self.value.der_cmp(&other.value)
}
}
impl<'a> From<AnyRef<'a>> for BytesRef<'a> {
fn from(any: AnyRef<'a>) -> BytesRef<'a> {
any.value
}
}
impl<'a> TryFrom<&'a [u8]> for AnyRef<'a> {
type Error = Error;
fn try_from(bytes: &'a [u8]) -> Result<AnyRef<'a>> {
AnyRef::from_der(bytes)
}
}
#[cfg(feature = "alloc")]
pub use self::allocating::Any;
#[cfg(feature = "alloc")]
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 })
}
/// 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(),
}
}
}
impl Choice<'_> for Any {
fn can_decode(_: Tag) -> bool {
true
}
}
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)
}
}
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)
}
}
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())
}
}
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")
}
}
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
}
}
}

552
vendor/der/src/asn1/bit_string.rs vendored Normal file
View File

@@ -0,0 +1,552 @@
//! ASN.1 `BIT STRING` support.
use crate::{
BytesRef, DecodeValue, DerOrd, EncodeValue, Error, ErrorKind, FixedTag, Header, Length, Reader,
Result, Tag, ValueOrd, Writer,
};
use core::{cmp::Ordering, iter::FusedIterator};
/// ASN.1 `BIT STRING` type.
///
/// This type contains a sequence of any number of bits, modeled internally as
/// a sequence of bytes with a known number of "unused bits".
///
/// This is a zero-copy reference type which borrows from the input data.
#[derive(Copy, Clone, Debug, Eq, PartialEq, PartialOrd, Ord)]
pub struct BitStringRef<'a> {
/// 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: BytesRef<'a>,
}
impl<'a> BitStringRef<'a> {
/// 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: &'a [u8]) -> Result<Self> {
if (unused_bits > Self::MAX_UNUSED_BITS) || (unused_bits != 0 && bytes.is_empty()) {
return Err(Self::TAG.value_error());
}
let inner = BytesRef::new(bytes).map_err(|_| Self::TAG.length_error())?;
let bit_length = usize::try_from(inner.len())?
.checked_mul(8)
.and_then(|n| n.checked_sub(usize::from(unused_bits)))
.ok_or(ErrorKind::Overflow)?;
Ok(Self {
unused_bits,
bit_length,
inner,
})
}
/// Create a new ASN.1 `BIT STRING` from the given bytes.
///
/// The "unused bits" are set to 0.
pub fn from_bytes(bytes: &'a [u8]) -> Result<Self> {
Self::new(0, bytes)
}
/// Get the number of unused bits in this byte slice.
pub fn unused_bits(&self) -> u8 {
self.unused_bits
}
/// Is the number of unused bits a value other than 0?
pub fn has_unused_bits(&self) -> bool {
self.unused_bits != 0
}
/// Get the length of this `BIT STRING` in bits.
pub fn bit_len(&self) -> usize {
self.bit_length
}
/// Get the number of bytes/octets needed to represent this `BIT STRING`
/// when serialized in an octet-aligned manner.
pub fn byte_len(&self) -> Length {
self.inner.len()
}
/// Is the inner byte slice empty?
pub fn is_empty(&self) -> bool {
self.inner.is_empty()
}
/// 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<&'a [u8]> {
if self.has_unused_bits() {
None
} else {
Some(self.raw_bytes())
}
}
/// Borrow the raw bytes of this `BIT STRING`.
///
/// Note that the byte string may contain extra unused bits in the final
/// octet. If the number of unused bits is expected to be 0, the
/// [`BitStringRef::as_bytes`] function can be used instead.
pub fn raw_bytes(&self) -> &'a [u8] {
self.inner.as_slice()
}
/// Iterator over the bits of this `BIT STRING`.
pub fn bits(self) -> BitStringIter<'a> {
BitStringIter {
bit_string: self,
position: 0,
}
}
}
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 {
tag: header.tag,
length: (header.length - Length::ONE)?,
};
let unused_bits = reader.read_byte()?;
let inner = BytesRef::decode_value(reader, header)?;
Self::new(unused_bits, inner.as_slice())
}
}
impl EncodeValue for BitStringRef<'_> {
fn value_len(&self) -> Result<Length> {
self.byte_len() + Length::ONE
}
fn encode_value(&self, writer: &mut impl Writer) -> Result<()> {
writer.write_byte(self.unused_bits)?;
writer.write(self.raw_bytes())
}
}
impl ValueOrd for BitStringRef<'_> {
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> From<&BitStringRef<'a>> for BitStringRef<'a> {
fn from(value: &BitStringRef<'a>) -> BitStringRef<'a> {
*value
}
}
impl<'a> TryFrom<&'a [u8]> for BitStringRef<'a> {
type Error = Error;
fn try_from(bytes: &'a [u8]) -> Result<BitStringRef<'a>> {
BitStringRef::from_bytes(bytes)
}
}
/// Hack for simplifying the custom derive use case.
impl<'a> TryFrom<&&'a [u8]> for BitStringRef<'a> {
type Error = Error;
fn try_from(bytes: &&'a [u8]) -> Result<BitStringRef<'a>> {
BitStringRef::from_bytes(bytes)
}
}
impl<'a> TryFrom<BitStringRef<'a>> for &'a [u8] {
type Error = Error;
fn try_from(bit_string: BitStringRef<'a>) -> Result<&'a [u8]> {
bit_string
.as_bytes()
.ok_or_else(|| Tag::BitString.value_error())
}
}
impl<'a> FixedTag for BitStringRef<'a> {
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 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)
}
fn size_hint(depth: usize) -> (usize, Option<usize>) {
arbitrary::size_hint::and(u8::size_hint(depth), BytesRef::size_hint(depth))
}
}
#[cfg(feature = "alloc")]
pub use self::allocating::BitString;
#[cfg(feature = "alloc")]
mod allocating {
use super::*;
use crate::referenced::*;
use alloc::vec::Vec;
/// Owned form of ASN.1 `BIT STRING` type.
///
/// 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,
})
}
/// 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)
}
/// Get the number of unused bits in the octet serialization of this
/// `BIT STRING`.
pub fn unused_bits(&self) -> u8 {
self.unused_bits
}
/// Is the number of unused bits a value other than 0?
pub fn has_unused_bits(&self) -> bool {
self.unused_bits != 0
}
/// Get the length of this `BIT STRING` in bits.
pub fn bit_len(&self) -> usize {
self.bit_length
}
/// Is the inner byte slice empty?
pub fn is_empty(&self) -> bool {
self.inner.is_empty()
}
/// 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())
}
}
/// Borrow the raw bytes of this `BIT STRING`.
pub fn raw_bytes(&self) -> &[u8] {
self.inner.as_slice()
}
/// Iterator over the bits of this `BIT STRING`.
pub fn bits(&self) -> BitStringIter<'_> {
BitStringRef::from(self).bits()
}
}
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)
}
}
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)
}
}
impl FixedTag for BitString {
const TAG: Tag = Tag::BitString;
}
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")
}
}
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),
}
}
}
// 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)
}
fn size_hint(depth: usize) -> (usize, Option<usize>) {
arbitrary::size_hint::and(u8::size_hint(depth), BytesRef::size_hint(depth))
}
}
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()
}
}
}
/// Iterator over the bits of a [`BitString`].
pub struct BitStringIter<'a> {
/// [`BitString`] being iterated over.
bit_string: BitStringRef<'a>,
/// Current bit position within the iterator.
position: usize,
}
impl<'a> Iterator for BitStringIter<'a> {
type Item = bool;
#[allow(clippy::integer_arithmetic)]
fn next(&mut self) -> Option<bool> {
if self.position >= self.bit_string.bit_len() {
return None;
}
let byte = self.bit_string.raw_bytes().get(self.position / 8)?;
let bit = 1u8 << (7 - (self.position % 8));
self.position = self.position.checked_add(1)?;
Some(byte & bit != 0)
}
}
impl<'a> ExactSizeIterator for BitStringIter<'a> {
fn len(&self) -> usize {
self.bit_string.bit_len()
}
}
impl<'a> FusedIterator for BitStringIter<'a> {}
#[cfg(feature = "flagset")]
impl<T: flagset::Flags> FixedTag for flagset::FlagSet<T> {
const TAG: Tag = BitStringRef::TAG;
}
#[cfg(feature = "flagset")]
impl<T> ValueOrd for flagset::FlagSet<T>
where
T: flagset::Flags,
T::Type: Ord,
{
fn value_cmp(&self, other: &Self) -> Result<Ordering> {
Ok(self.bits().cmp(&other.bits()))
}
}
#[cfg(feature = "flagset")]
#[allow(clippy::integer_arithmetic)]
impl<'a, T> DecodeValue<'a> for flagset::FlagSet<T>
where
T: flagset::Flags,
T::Type: From<bool>,
T::Type: core::ops::Shl<usize, Output = T::Type>,
{
fn decode_value<R: Reader<'a>>(reader: &mut R, header: Header) -> Result<Self> {
let position = reader.position();
let bits = BitStringRef::decode_value(reader, header)?;
let mut flags = T::none().bits();
if bits.bit_len() > core::mem::size_of_val(&flags) * 8 {
return Err(Error::new(ErrorKind::Overlength, position));
}
for (i, bit) in bits.bits().enumerate() {
flags |= T::Type::from(bit) << i;
}
Ok(Self::new_truncated(flags))
}
}
#[cfg(feature = "flagset")]
#[allow(clippy::integer_arithmetic)]
#[inline(always)]
fn encode_flagset<T>(set: &flagset::FlagSet<T>) -> (usize, [u8; 16])
where
T: flagset::Flags,
u128: From<T::Type>,
{
let bits: u128 = set.bits().into();
let mut swap = 0u128;
for i in 0..128 {
let on = bits & (1 << i);
swap |= on >> i << (128 - i - 1);
}
(bits.leading_zeros() as usize, swap.to_be_bytes())
}
#[cfg(feature = "flagset")]
#[allow(clippy::cast_possible_truncation, clippy::integer_arithmetic)]
impl<T: flagset::Flags> EncodeValue for flagset::FlagSet<T>
where
T::Type: From<bool>,
T::Type: core::ops::Shl<usize, Output = T::Type>,
u128: From<T::Type>,
{
fn value_len(&self) -> Result<Length> {
let (lead, buff) = encode_flagset(self);
let buff = &buff[..buff.len() - lead / 8];
BitStringRef::new((lead % 8) as u8, buff)?.value_len()
}
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)
}
}
#[cfg(test)]
mod tests {
use super::{BitStringRef, Result, Tag};
use crate::asn1::AnyRef;
use hex_literal::hex;
/// Parse a `BitString` from an ASN.1 `Any` value to test decoding behaviors.
fn parse_bitstring(bytes: &[u8]) -> Result<BitStringRef<'_>> {
AnyRef::new(Tag::BitString, bytes)?.try_into()
}
#[test]
fn decode_empty_bitstring() {
let bs = parse_bitstring(&hex!("00")).unwrap();
assert_eq!(bs.as_bytes().unwrap(), &[]);
}
#[test]
fn decode_non_empty_bitstring() {
let bs = parse_bitstring(&hex!("00010203")).unwrap();
assert_eq!(bs.as_bytes().unwrap(), &[0x01, 0x02, 0x03]);
}
#[test]
fn decode_bitstring_with_unused_bits() {
let bs = parse_bitstring(&hex!("066e5dc0")).unwrap();
assert_eq!(bs.unused_bits(), 6);
assert_eq!(bs.raw_bytes(), &hex!("6e5dc0"));
// Expected: 011011100101110111
let mut bits = bs.bits();
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!(u8::from(bits.next().unwrap()), bit)
}
// Ensure `None` is returned on successive calls
assert_eq!(bits.next(), None);
assert_eq!(bits.next(), None);
}
#[test]
fn reject_unused_bits_in_empty_string() {
assert_eq!(
parse_bitstring(&[0x03]).err().unwrap().kind(),
Tag::BitString.value_error().kind()
)
}
}

164
vendor/der/src/asn1/bmp_string.rs vendored Normal file
View File

@@ -0,0 +1,164 @@
//! ASN.1 `BMPString` support.
use crate::{
BytesOwned, DecodeValue, EncodeValue, Error, FixedTag, Header, Length, Reader, Result, Tag,
Writer,
};
use alloc::{boxed::Box, vec::Vec};
use core::{fmt, str::FromStr};
/// ASN.1 `BMPString` type.
///
/// Encodes Basic Multilingual Plane (BMP) subset of Unicode (ISO 10646),
/// a.k.a. UCS-2.
#[derive(Clone, Eq, PartialEq, PartialOrd, Ord)]
pub struct BmpString {
bytes: BytesOwned,
}
impl BmpString {
/// Create a new [`BmpString`] from its UCS-2 encoding.
pub fn from_ucs2(bytes: impl Into<Box<[u8]>>) -> Result<Self> {
let bytes = bytes.into();
if bytes.len() % 2 != 0 {
return Err(Tag::BmpString.length_error());
}
let ret = Self {
bytes: bytes.try_into()?,
};
for maybe_char in char::decode_utf16(ret.codepoints()) {
match maybe_char {
// All surrogates paired and character is in the Basic Multilingual Plane
Ok(c) if (c as u64) < u64::from(u16::MAX) => (),
// Unpaired surrogates or characters outside Basic Multilingual Plane
_ => return Err(Tag::BmpString.value_error()),
}
}
Ok(ret)
}
/// Create a new [`BmpString`] from a UTF-8 string.
pub fn from_utf8(utf8: &str) -> Result<Self> {
let capacity = utf8
.len()
.checked_mul(2)
.ok_or_else(|| Tag::BmpString.length_error())?;
let mut bytes = Vec::with_capacity(capacity);
for code_point in utf8.encode_utf16() {
bytes.extend(code_point.to_be_bytes());
}
Self::from_ucs2(bytes)
}
/// Borrow the encoded UCS-2 as bytes.
pub fn as_bytes(&self) -> &[u8] {
self.bytes.as_ref()
}
/// Obtain the inner bytes.
#[inline]
pub fn into_bytes(self) -> Box<[u8]> {
self.bytes.into()
}
/// Get an iterator over characters in the string.
pub fn chars(&self) -> impl Iterator<Item = char> + '_ {
char::decode_utf16(self.codepoints())
.map(|maybe_char| maybe_char.expect("unpaired surrogates checked in constructor"))
}
/// Get an iterator over the `u16` codepoints.
pub fn codepoints(&self) -> impl Iterator<Item = u16> + '_ {
// TODO(tarcieri): use `array_chunks`
self.as_bytes()
.chunks_exact(2)
.map(|chunk| u16::from_be_bytes([chunk[0], chunk[1]]))
}
}
impl AsRef<[u8]> for BmpString {
fn as_ref(&self) -> &[u8] {
self.as_bytes()
}
}
impl<'a> DecodeValue<'a> for BmpString {
fn decode_value<R: Reader<'a>>(reader: &mut R, header: Header) -> Result<Self> {
Self::from_ucs2(reader.read_vec(header.length)?)
}
}
impl EncodeValue for BmpString {
fn value_len(&self) -> Result<Length> {
Ok(self.bytes.len())
}
fn encode_value(&self, writer: &mut impl Writer) -> Result<()> {
writer.write(self.as_bytes())
}
}
impl FixedTag for BmpString {
const TAG: Tag = Tag::BmpString;
}
impl FromStr for BmpString {
type Err = Error;
fn from_str(s: &str) -> Result<Self> {
Self::from_utf8(s)
}
}
impl fmt::Debug for BmpString {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "BmpString(\"{}\")", self)
}
}
impl fmt::Display for BmpString {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
for c in self.chars() {
write!(f, "{}", c)?;
}
Ok(())
}
}
#[cfg(test)]
mod tests {
use super::BmpString;
use crate::{Decode, Encode};
use alloc::string::ToString;
use hex_literal::hex;
const EXAMPLE_BYTES: &[u8] = &hex!(
"1e 26 00 43 00 65 00 72 00 74"
" 00 69 00 66 00 69 00 63"
" 00 61 00 74 00 65 00 54"
" 00 65 00 6d 00 70 00 6c"
" 00 61 00 74 00 65"
);
const EXAMPLE_UTF8: &str = "CertificateTemplate";
#[test]
fn decode() {
let bmp_string = BmpString::from_der(EXAMPLE_BYTES).unwrap();
assert_eq!(bmp_string.to_string(), EXAMPLE_UTF8);
}
#[test]
fn encode() {
let bmp_string = BmpString::from_utf8(EXAMPLE_UTF8).unwrap();
let encoded = bmp_string.to_der().unwrap();
assert_eq!(encoded, EXAMPLE_BYTES);
}
}

82
vendor/der/src/asn1/boolean.rs vendored Normal file
View File

@@ -0,0 +1,82 @@
//! ASN.1 `BOOLEAN` support.
use crate::{
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:
///
/// > If the encoding represents the boolean value TRUE, its single contents
/// > octet shall have all eight bits set to one.
const TRUE_OCTET: u8 = 0b11111111;
/// Byte used to encode `false` in ASN.1 DER.
const FALSE_OCTET: u8 = 0b00000000;
impl<'a> DecodeValue<'a> for bool {
fn decode_value<R: Reader<'a>>(reader: &mut R, header: Header) -> Result<Self> {
if header.length != Length::ONE {
return Err(reader.error(ErrorKind::Length { tag: Self::TAG }));
}
match reader.read_byte()? {
FALSE_OCTET => Ok(false),
TRUE_OCTET => Ok(true),
_ => Err(Self::TAG.non_canonical_error()),
}
}
}
impl EncodeValue for bool {
fn value_len(&self) -> Result<Length> {
Ok(Length::ONE)
}
fn encode_value(&self, writer: &mut impl Writer) -> Result<()> {
writer.write_byte(if *self { TRUE_OCTET } else { FALSE_OCTET })
}
}
impl FixedTag for bool {
const TAG: Tag = Tag::Boolean;
}
impl OrdIsValueOrd for bool {}
impl TryFrom<AnyRef<'_>> for bool {
type Error = Error;
fn try_from(any: AnyRef<'_>) -> Result<bool> {
any.try_into()
}
}
#[cfg(test)]
mod tests {
use crate::{Decode, Encode};
#[test]
fn decode() {
assert_eq!(true, bool::from_der(&[0x01, 0x01, 0xFF]).unwrap());
assert_eq!(false, bool::from_der(&[0x01, 0x01, 0x00]).unwrap());
}
#[test]
fn encode() {
let mut buffer = [0u8; 3];
assert_eq!(
&[0x01, 0x01, 0xFF],
true.encode_to_slice(&mut buffer).unwrap()
);
assert_eq!(
&[0x01, 0x01, 0x00],
false.encode_to_slice(&mut buffer).unwrap()
);
}
#[test]
fn reject_non_canonical() {
assert!(bool::from_der(&[0x01, 0x01, 0x01]).is_err());
}
}

26
vendor/der/src/asn1/choice.rs vendored Normal file
View File

@@ -0,0 +1,26 @@
//! ASN.1 `CHOICE` support.
use crate::{Decode, FixedTag, Tag, Tagged};
/// ASN.1 `CHOICE` denotes a union of one or more possible alternatives.
///
/// The types MUST have distinct tags.
///
/// This crate models choice as a trait, with a blanket impl for all types
/// which impl `Decode + FixedTag` (i.e. they are modeled as a `CHOICE`
/// with only one possible variant)
pub trait Choice<'a>: Decode<'a> + Tagged {
/// Is the provided [`Tag`] decodable as a variant of this `CHOICE`?
fn can_decode(tag: Tag) -> bool;
}
/// This blanket impl allows any [`Tagged`] type to function as a [`Choice`]
/// with a single alternative.
impl<'a, T> Choice<'a> for T
where
T: Decode<'a> + FixedTag,
{
fn can_decode(tag: Tag) -> bool {
T::TAG == tag
}
}

354
vendor/der/src/asn1/context_specific.rs vendored Normal file
View File

@@ -0,0 +1,354 @@
//! Context-specific field.
use crate::{
asn1::AnyRef, Choice, Decode, DecodeValue, DerOrd, Encode, EncodeValue, EncodeValueRef, Error,
Header, Length, Reader, Result, Tag, TagMode, TagNumber, Tagged, ValueOrd, Writer,
};
use core::cmp::Ordering;
/// Context-specific field which wraps an owned inner value.
///
/// This type decodes/encodes a field which is specific to a particular context
/// and is identified by a [`TagNumber`].
#[derive(Copy, Clone, Debug, Eq, PartialEq, PartialOrd, Ord)]
pub struct ContextSpecific<T> {
/// Context-specific tag number sans the leading `0b10000000` class
/// identifier bit and `0b100000` constructed flag.
pub tag_number: TagNumber,
/// Tag mode: `EXPLICIT` VS `IMPLICIT`.
pub tag_mode: TagMode,
/// Value of the field.
pub value: T,
}
impl<T> ContextSpecific<T> {
/// Attempt to decode an `EXPLICIT` ASN.1 `CONTEXT-SPECIFIC` field with the
/// provided [`TagNumber`].
///
/// This method has the following behavior which is designed to simplify
/// handling of extension fields, which are denoted in an ASN.1 schema
/// using the `...` ellipsis extension marker:
///
/// - Skips over [`ContextSpecific`] fields with a tag number lower than
/// the current one, consuming and ignoring them.
/// - Returns `Ok(None)` if a [`ContextSpecific`] field with a higher tag
/// number is encountered. These fields are not consumed in this case,
/// allowing a field with a lower tag number to be omitted, then the
/// higher numbered field consumed as a follow-up.
/// - Returns `Ok(None)` if anything other than a [`ContextSpecific`] field
/// is encountered.
pub fn decode_explicit<'a, R: Reader<'a>>(
reader: &mut R,
tag_number: TagNumber,
) -> Result<Option<Self>>
where
T: Decode<'a>,
{
Self::decode_with(reader, tag_number, |reader| Self::decode(reader))
}
/// Attempt to decode an `IMPLICIT` ASN.1 `CONTEXT-SPECIFIC` field with the
/// provided [`TagNumber`].
///
/// This method otherwise behaves the same as `decode_explicit`,
/// but should be used in cases where the particular fields are `IMPLICIT`
/// as opposed to `EXPLICIT`.
pub fn decode_implicit<'a, R: Reader<'a>>(
reader: &mut R,
tag_number: TagNumber,
) -> Result<Option<Self>>
where
T: DecodeValue<'a> + Tagged,
{
Self::decode_with(reader, tag_number, |reader| {
let header = Header::decode(reader)?;
let value = T::decode_value(reader, header)?;
if header.tag.is_constructed() != value.tag().is_constructed() {
return Err(header.tag.non_canonical_error());
}
Ok(Self {
tag_number,
tag_mode: TagMode::Implicit,
value,
})
})
}
/// Attempt to decode a context-specific field with the given
/// helper callback.
fn decode_with<'a, F, R: Reader<'a>>(
reader: &mut R,
tag_number: TagNumber,
f: F,
) -> Result<Option<Self>>
where
F: FnOnce(&mut R) -> Result<Self>,
{
while let Some(octet) = reader.peek_byte() {
let tag = Tag::try_from(octet)?;
if !tag.is_context_specific() || (tag.number() > tag_number) {
break;
} else if tag.number() == tag_number {
return Some(f(reader)).transpose();
} else {
AnyRef::decode(reader)?;
}
}
Ok(None)
}
}
impl<'a, T> Choice<'a> for ContextSpecific<T>
where
T: Decode<'a> + Tagged,
{
fn can_decode(tag: Tag) -> bool {
tag.is_context_specific()
}
}
impl<'a, T> Decode<'a> for ContextSpecific<T>
where
T: Decode<'a>,
{
fn decode<R: Reader<'a>>(reader: &mut R) -> Result<Self> {
let header = Header::decode(reader)?;
match header.tag {
Tag::ContextSpecific {
number,
constructed: true,
} => Ok(Self {
tag_number: number,
tag_mode: TagMode::default(),
value: reader.read_nested(header.length, |reader| T::decode(reader))?,
}),
tag => Err(tag.unexpected_error(None)),
}
}
}
impl<T> EncodeValue for ContextSpecific<T>
where
T: EncodeValue + Tagged,
{
fn value_len(&self) -> Result<Length> {
match self.tag_mode {
TagMode::Explicit => self.value.encoded_len(),
TagMode::Implicit => self.value.value_len(),
}
}
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),
}
}
}
impl<T> Tagged for ContextSpecific<T>
where
T: Tagged,
{
fn tag(&self) -> Tag {
let constructed = match self.tag_mode {
TagMode::Explicit => true,
TagMode::Implicit => self.value.tag().is_constructed(),
};
Tag::ContextSpecific {
number: self.tag_number,
constructed,
}
}
}
impl<'a, T> TryFrom<AnyRef<'a>> for ContextSpecific<T>
where
T: Decode<'a>,
{
type Error = Error;
fn try_from(any: AnyRef<'a>) -> Result<ContextSpecific<T>> {
match any.tag() {
Tag::ContextSpecific {
number,
constructed: true,
} => Ok(Self {
tag_number: number,
tag_mode: TagMode::default(),
value: T::from_der(any.value())?,
}),
tag => Err(tag.unexpected_error(None)),
}
}
}
impl<T> ValueOrd for ContextSpecific<T>
where
T: EncodeValue + ValueOrd + Tagged,
{
fn value_cmp(&self, other: &Self) -> Result<Ordering> {
match self.tag_mode {
TagMode::Explicit => self.der_cmp(other),
TagMode::Implicit => self.value_cmp(other),
}
}
}
/// Context-specific field reference.
///
/// This type encodes a field which is specific to a particular context
/// and is identified by a [`TagNumber`].
#[derive(Copy, Clone, Debug, Eq, PartialEq, PartialOrd, Ord)]
pub struct ContextSpecificRef<'a, T> {
/// Context-specific tag number sans the leading `0b10000000` class
/// identifier bit and `0b100000` constructed flag.
pub tag_number: TagNumber,
/// Tag mode: `EXPLICIT` VS `IMPLICIT`.
pub tag_mode: TagMode,
/// Value of the field.
pub value: &'a T,
}
impl<'a, T> ContextSpecificRef<'a, T> {
/// Convert to a [`ContextSpecific`].
fn encoder(&self) -> ContextSpecific<EncodeValueRef<'a, T>> {
ContextSpecific {
tag_number: self.tag_number,
tag_mode: self.tag_mode,
value: EncodeValueRef(self.value),
}
}
}
impl<'a, T> EncodeValue for ContextSpecificRef<'a, T>
where
T: EncodeValue + Tagged,
{
fn value_len(&self) -> Result<Length> {
self.encoder().value_len()
}
fn encode_value(&self, writer: &mut impl Writer) -> Result<()> {
self.encoder().encode_value(writer)
}
}
impl<'a, T> Tagged for ContextSpecificRef<'a, T>
where
T: Tagged,
{
fn tag(&self) -> Tag {
self.encoder().tag()
}
}
#[cfg(test)]
mod tests {
use super::ContextSpecific;
use crate::{asn1::BitStringRef, Decode, Encode, SliceReader, TagMode, TagNumber};
use hex_literal::hex;
// Public key data from `pkcs8` crate's `ed25519-pkcs8-v2.der`
const EXAMPLE_BYTES: &[u8] =
&hex!("A123032100A3A7EAE3A8373830BC47E1167BC50E1DB551999651E0E2DC587623438EAC3F31");
#[test]
fn round_trip() {
let field = ContextSpecific::<BitStringRef<'_>>::from_der(EXAMPLE_BYTES).unwrap();
assert_eq!(field.tag_number.value(), 1);
assert_eq!(
field.value,
BitStringRef::from_bytes(&EXAMPLE_BYTES[5..]).unwrap()
);
let mut buf = [0u8; 128];
let encoded = field.encode_to_slice(&mut buf).unwrap();
assert_eq!(encoded, EXAMPLE_BYTES);
}
#[test]
fn context_specific_with_explicit_field() {
let tag_number = TagNumber::new(0);
// Empty message
let mut reader = SliceReader::new(&[]).unwrap();
assert_eq!(
ContextSpecific::<u8>::decode_explicit(&mut reader, tag_number).unwrap(),
None
);
// Message containing a non-context-specific type
let mut reader = SliceReader::new(&hex!("020100")).unwrap();
assert_eq!(
ContextSpecific::<u8>::decode_explicit(&mut reader, tag_number).unwrap(),
None
);
// Message containing an EXPLICIT context-specific field
let mut reader = SliceReader::new(&hex!("A003020100")).unwrap();
let field = ContextSpecific::<u8>::decode_explicit(&mut reader, tag_number)
.unwrap()
.unwrap();
assert_eq!(field.tag_number, tag_number);
assert_eq!(field.tag_mode, TagMode::Explicit);
assert_eq!(field.value, 0);
}
#[test]
fn context_specific_with_implicit_field() {
// From RFC8410 Section 10.3:
// <https://datatracker.ietf.org/doc/html/rfc8410#section-10.3>
//
// 81 33: [1] 00 19 BF 44 09 69 84 CD FE 85 41 BA C1 67 DC 3B
// 96 C8 50 86 AA 30 B6 B6 CB 0C 5C 38 AD 70 31 66
// E1
let context_specific_implicit_bytes =
hex!("81210019BF44096984CDFE8541BAC167DC3B96C85086AA30B6B6CB0C5C38AD703166E1");
let tag_number = TagNumber::new(1);
let mut reader = SliceReader::new(&context_specific_implicit_bytes).unwrap();
let field = ContextSpecific::<BitStringRef<'_>>::decode_implicit(&mut reader, tag_number)
.unwrap()
.unwrap();
assert_eq!(field.tag_number, tag_number);
assert_eq!(field.tag_mode, TagMode::Implicit);
assert_eq!(
field.value.as_bytes().unwrap(),
&context_specific_implicit_bytes[3..]
);
}
#[test]
fn context_specific_skipping_unknown_field() {
let tag = TagNumber::new(1);
let mut reader = SliceReader::new(&hex!("A003020100A103020101")).unwrap();
let field = ContextSpecific::<u8>::decode_explicit(&mut reader, tag)
.unwrap()
.unwrap();
assert_eq!(field.value, 1);
}
#[test]
fn context_specific_returns_none_on_greater_tag_number() {
let tag = TagNumber::new(0);
let mut reader = SliceReader::new(&hex!("A103020101")).unwrap();
assert_eq!(
ContextSpecific::<u8>::decode_explicit(&mut reader, tag).unwrap(),
None
);
}
}

327
vendor/der/src/asn1/generalized_time.rs vendored Normal file
View File

@@ -0,0 +1,327 @@
//! ASN.1 `GeneralizedTime` support.
#![cfg_attr(feature = "arbitrary", allow(clippy::integer_arithmetic))]
use crate::{
datetime::{self, DateTime},
ord::OrdIsValueOrd,
DecodeValue, EncodeValue, ErrorKind, FixedTag, Header, Length, Reader, Result, Tag, Writer,
};
use core::time::Duration;
#[cfg(feature = "std")]
use {
crate::{asn1::AnyRef, Error},
std::time::SystemTime,
};
#[cfg(feature = "time")]
use time::PrimitiveDateTime;
/// ASN.1 `GeneralizedTime` type.
///
/// This type implements the validity requirements specified in
/// [RFC 5280 Section 4.1.2.5.2][1], namely:
///
/// > For the purposes of this profile, GeneralizedTime values MUST be
/// > expressed in Greenwich Mean Time (Zulu) and MUST include seconds
/// > (i.e., times are `YYYYMMDDHHMMSSZ`), even where the number of seconds
/// > 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);
impl GeneralizedTime {
/// Length of an RFC 5280-flavored ASN.1 DER-encoded [`GeneralizedTime`].
const LENGTH: usize = 15;
/// Create a [`GeneralizedTime`] from a [`DateTime`].
pub const fn from_date_time(datetime: DateTime) -> Self {
Self(datetime)
}
/// Convert this [`GeneralizedTime`] into a [`DateTime`].
pub fn to_date_time(&self) -> DateTime {
self.0
}
/// Create a new [`GeneralizedTime`] given a [`Duration`] since `UNIX_EPOCH`
/// (a.k.a. "Unix time")
pub fn from_unix_duration(unix_duration: Duration) -> Result<Self> {
DateTime::from_unix_duration(unix_duration)
.map(Into::into)
.map_err(|_| Self::TAG.value_error())
}
/// Get the duration of this timestamp since `UNIX_EPOCH`.
pub fn to_unix_duration(&self) -> Duration {
self.0.unix_duration()
}
/// Instantiate from [`SystemTime`].
#[cfg(feature = "std")]
pub fn from_system_time(time: SystemTime) -> Result<Self> {
DateTime::try_from(time)
.map(Into::into)
.map_err(|_| Self::TAG.value_error())
}
/// Convert to [`SystemTime`].
#[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)? {
return Err(Self::TAG.value_error());
}
let mut bytes = [0u8; Self::LENGTH];
reader.read_into(&mut bytes)?;
match bytes {
// RFC 5280 requires mandatory seconds and Z-normalized time zone
[y1, y2, y3, y4, mon1, mon2, day1, day2, hour1, hour2, min1, min2, sec1, sec2, b'Z'] => {
let year = u16::from(datetime::decode_decimal(Self::TAG, y1, y2)?)
.checked_mul(100)
.and_then(|y| {
y.checked_add(datetime::decode_decimal(Self::TAG, y3, y4).ok()?.into())
})
.ok_or(ErrorKind::DateTime)?;
let month = datetime::decode_decimal(Self::TAG, mon1, mon2)?;
let day = datetime::decode_decimal(Self::TAG, day1, day2)?;
let hour = datetime::decode_decimal(Self::TAG, hour1, hour2)?;
let minute = datetime::decode_decimal(Self::TAG, min1, min2)?;
let second = datetime::decode_decimal(Self::TAG, sec1, sec2)?;
DateTime::new(year, month, day, hour, minute, second)
.map_err(|_| Self::TAG.value_error())
.and_then(|dt| Self::from_unix_duration(dt.unix_duration()))
}
_ => Err(Self::TAG.value_error()),
}
}
}
impl EncodeValue for GeneralizedTime {
fn value_len(&self) -> Result<Length> {
Self::LENGTH.try_into()
}
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)?;
datetime::encode_decimal(writer, Self::TAG, year_hi)?;
datetime::encode_decimal(writer, Self::TAG, year_lo)?;
datetime::encode_decimal(writer, Self::TAG, self.0.month())?;
datetime::encode_decimal(writer, Self::TAG, self.0.day())?;
datetime::encode_decimal(writer, Self::TAG, self.0.hour())?;
datetime::encode_decimal(writer, Self::TAG, self.0.minutes())?;
datetime::encode_decimal(writer, Self::TAG, self.0.seconds())?;
writer.write_byte(b'Z')
}
}
impl FixedTag for GeneralizedTime {
const TAG: Tag = Tag::GeneralizedTime;
}
impl OrdIsValueOrd for GeneralizedTime {}
impl From<&GeneralizedTime> for GeneralizedTime {
fn from(value: &GeneralizedTime) -> GeneralizedTime {
*value
}
}
impl From<GeneralizedTime> for DateTime {
fn from(utc_time: GeneralizedTime) -> DateTime {
utc_time.0
}
}
impl From<&GeneralizedTime> for DateTime {
fn from(utc_time: &GeneralizedTime) -> DateTime {
utc_time.0
}
}
impl From<DateTime> for GeneralizedTime {
fn from(datetime: DateTime) -> Self {
Self::from_date_time(datetime)
}
}
impl From<&DateTime> for GeneralizedTime {
fn from(datetime: &DateTime) -> Self {
Self::from_date_time(*datetime)
}
}
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())
}
}
impl EncodeValue for DateTime {
fn value_len(&self) -> Result<Length> {
GeneralizedTime::from(self).value_len()
}
fn encode_value(&self, writer: &mut impl Writer) -> Result<()> {
GeneralizedTime::from(self).encode_value(writer)
}
}
impl FixedTag for DateTime {
const TAG: Tag = Tag::GeneralizedTime;
}
impl OrdIsValueOrd for DateTime {}
#[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())
}
}
#[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 impl Writer) -> Result<()> {
GeneralizedTime::try_from(self)?.encode_value(writer)
}
}
#[cfg(feature = "std")]
impl From<GeneralizedTime> for SystemTime {
fn from(time: GeneralizedTime) -> SystemTime {
time.to_system_time()
}
}
#[cfg(feature = "std")]
impl From<&GeneralizedTime> for SystemTime {
fn from(time: &GeneralizedTime) -> SystemTime {
time.to_system_time()
}
}
#[cfg(feature = "std")]
impl TryFrom<SystemTime> for GeneralizedTime {
type Error = Error;
fn try_from(time: SystemTime) -> Result<GeneralizedTime> {
GeneralizedTime::from_system_time(time)
}
}
#[cfg(feature = "std")]
impl TryFrom<&SystemTime> for GeneralizedTime {
type Error = Error;
fn try_from(time: &SystemTime) -> Result<GeneralizedTime> {
GeneralizedTime::from_system_time(*time)
}
}
#[cfg(feature = "std")]
impl<'a> TryFrom<AnyRef<'a>> for SystemTime {
type Error = Error;
fn try_from(any: AnyRef<'a>) -> Result<SystemTime> {
GeneralizedTime::try_from(any).map(|s| s.to_system_time())
}
}
#[cfg(feature = "std")]
impl FixedTag for SystemTime {
const TAG: Tag = Tag::GeneralizedTime;
}
#[cfg(feature = "std")]
impl OrdIsValueOrd for SystemTime {}
#[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()
}
}
#[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 impl Writer) -> Result<()> {
GeneralizedTime::try_from(self)?.encode_value(writer)
}
}
#[cfg(feature = "time")]
impl FixedTag for PrimitiveDateTime {
const TAG: Tag = Tag::GeneralizedTime;
}
#[cfg(feature = "time")]
impl OrdIsValueOrd for PrimitiveDateTime {}
#[cfg(feature = "time")]
impl TryFrom<PrimitiveDateTime> for GeneralizedTime {
type Error = Error;
fn try_from(time: PrimitiveDateTime) -> Result<GeneralizedTime> {
Ok(GeneralizedTime::from_date_time(DateTime::try_from(time)?))
}
}
#[cfg(feature = "time")]
impl TryFrom<&PrimitiveDateTime> for GeneralizedTime {
type Error = Error;
fn try_from(time: &PrimitiveDateTime) -> Result<GeneralizedTime> {
Self::try_from(*time)
}
}
#[cfg(feature = "time")]
impl TryFrom<GeneralizedTime> for PrimitiveDateTime {
type Error = Error;
fn try_from(time: GeneralizedTime) -> Result<PrimitiveDateTime> {
time.to_date_time().try_into()
}
}
#[cfg(test)]
mod tests {
use super::GeneralizedTime;
use crate::{Decode, Encode, SliceWriter};
use hex_literal::hex;
#[test]
fn round_trip() {
let example_bytes = hex!("18 0f 31 39 39 31 30 35 30 36 32 33 34 35 34 30 5a");
let utc_time = GeneralizedTime::from_der(&example_bytes).unwrap();
assert_eq!(utc_time.to_unix_duration().as_secs(), 673573540);
let mut buf = [0u8; 128];
let mut encoder = SliceWriter::new(&mut buf);
utc_time.encode(&mut encoder).unwrap();
assert_eq!(example_bytes, encoder.finish().unwrap());
}
}

195
vendor/der/src/asn1/ia5_string.rs vendored Normal file
View File

@@ -0,0 +1,195 @@
//! ASN.1 `IA5String` support.
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.
///
/// 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 [`Utf8StringRef`][`crate::asn1::Utf8StringRef`].
///
/// This is a zero-copy reference type which borrows from the input data.
///
/// [International Alphabet No. 5 (IA5)]: https://en.wikipedia.org/wiki/T.50_%28standard%29
#[derive(Copy, Clone, Eq, PartialEq, PartialOrd, Ord)]
pub struct Ia5StringRef<'a> {
/// Inner value
inner: StrRef<'a>,
}
impl<'a> Ia5StringRef<'a> {
/// Create a new `IA5String`.
pub fn new<T>(input: &'a T) -> Result<Self>
where
T: AsRef<[u8]> + ?Sized,
{
let input = input.as_ref();
// Validate all characters are within IA5String's allowed set
if input.iter().any(|&c| c > 0x7F) {
return Err(Self::TAG.value_error());
}
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 = StrRef<'a>;
fn deref(&self) -> &Self::Target {
&self.inner
}
}
impl<'a> From<&Ia5StringRef<'a>> for Ia5StringRef<'a> {
fn from(value: &Ia5StringRef<'a>) -> Ia5StringRef<'a> {
*value
}
}
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())
}
}
#[cfg(feature = "alloc")]
pub use self::allocation::Ia5String;
#[cfg(feature = "alloc")]
mod allocation {
use super::Ia5StringRef;
use crate::{
asn1::AnyRef,
referenced::{OwnedToRef, RefToOwned},
Error, FixedTag, Result, StrOwned, Tag,
};
use alloc::string::String;
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,
}
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_ia5_string!(Ia5String);
impl Deref for Ia5String {
type Target = StrOwned;
fn deref(&self) -> &Self::Target {
&self.inner
}
}
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<&'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> RefToOwned<'a> for Ia5StringRef<'a> {
type Owned = Ia5String;
fn ref_to_owned(&self) -> Self::Owned {
Ia5String {
inner: self.inner.ref_to_owned(),
}
}
}
impl OwnedToRef for Ia5String {
type Borrowed<'a> = Ia5StringRef<'a>;
fn owned_to_ref(&self) -> Self::Borrowed<'_> {
Ia5StringRef {
inner: self.inner.owned_to_ref(),
}
}
}
impl TryFrom<String> for Ia5String {
type Error = Error;
fn try_from(input: String) -> Result<Self> {
Ia5StringRef::new(&input)?;
StrOwned::new(input)
.map(|inner| Self { inner })
.map_err(|_| Self::TAG.value_error())
}
}
}
#[cfg(test)]
mod tests {
use super::Ia5StringRef;
use crate::Decode;
use hex_literal::hex;
#[test]
fn parse_bytes() {
let example_bytes = hex!("16 0d 74 65 73 74 31 40 72 73 61 2e 63 6f 6d");
let internationalized_string = Ia5StringRef::from_der(&example_bytes).unwrap();
assert_eq!(internationalized_string.as_str(), "test1@rsa.com");
}
}

161
vendor/der/src/asn1/integer.rs vendored Normal file
View File

@@ -0,0 +1,161 @@
//! ASN.1 `INTEGER` support.
pub(super) mod int;
pub(super) mod uint;
use core::{cmp::Ordering, mem};
use crate::{EncodeValue, Result, SliceWriter};
/// 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
.first()
.map(|byte| byte & 0b10000000 != 0)
.unwrap_or(false)
}
/// Compare two integer values
fn value_cmp<T>(a: T, b: T) -> Result<Ordering>
where
T: Copy + EncodeValue + Sized,
{
const MAX_INT_SIZE: usize = 16;
debug_assert!(mem::size_of::<T>() <= MAX_INT_SIZE);
let mut buf1 = [0u8; MAX_INT_SIZE];
let mut encoder1 = SliceWriter::new(&mut buf1);
a.encode_value(&mut encoder1)?;
let mut buf2 = [0u8; MAX_INT_SIZE];
let mut encoder2 = SliceWriter::new(&mut buf2);
b.encode_value(&mut encoder2)?;
Ok(encoder1.finish()?.cmp(encoder2.finish()?))
}
#[cfg(test)]
pub(crate) mod tests {
use crate::{Decode, Encode};
// Vectors from Section 5.7 of:
// https://luca.ntop.org/Teaching/Appunti/asn1.html
pub(crate) const I0_BYTES: &[u8] = &[0x02, 0x01, 0x00];
pub(crate) const I127_BYTES: &[u8] = &[0x02, 0x01, 0x7F];
pub(crate) const I128_BYTES: &[u8] = &[0x02, 0x02, 0x00, 0x80];
pub(crate) const I256_BYTES: &[u8] = &[0x02, 0x02, 0x01, 0x00];
pub(crate) const INEG128_BYTES: &[u8] = &[0x02, 0x01, 0x80];
pub(crate) const INEG129_BYTES: &[u8] = &[0x02, 0x02, 0xFF, 0x7F];
// Additional vectors
pub(crate) const I255_BYTES: &[u8] = &[0x02, 0x02, 0x00, 0xFF];
pub(crate) const I32767_BYTES: &[u8] = &[0x02, 0x02, 0x7F, 0xFF];
pub(crate) const I65535_BYTES: &[u8] = &[0x02, 0x03, 0x00, 0xFF, 0xFF];
pub(crate) const INEG32768_BYTES: &[u8] = &[0x02, 0x02, 0x80, 0x00];
#[test]
fn decode_i8() {
assert_eq!(0, i8::from_der(I0_BYTES).unwrap());
assert_eq!(127, i8::from_der(I127_BYTES).unwrap());
assert_eq!(-128, i8::from_der(INEG128_BYTES).unwrap());
}
#[test]
fn decode_i16() {
assert_eq!(0, i16::from_der(I0_BYTES).unwrap());
assert_eq!(127, i16::from_der(I127_BYTES).unwrap());
assert_eq!(128, i16::from_der(I128_BYTES).unwrap());
assert_eq!(255, i16::from_der(I255_BYTES).unwrap());
assert_eq!(256, i16::from_der(I256_BYTES).unwrap());
assert_eq!(32767, i16::from_der(I32767_BYTES).unwrap());
assert_eq!(-128, i16::from_der(INEG128_BYTES).unwrap());
assert_eq!(-129, i16::from_der(INEG129_BYTES).unwrap());
assert_eq!(-32768, i16::from_der(INEG32768_BYTES).unwrap());
}
#[test]
fn decode_u8() {
assert_eq!(0, u8::from_der(I0_BYTES).unwrap());
assert_eq!(127, u8::from_der(I127_BYTES).unwrap());
assert_eq!(255, u8::from_der(I255_BYTES).unwrap());
}
#[test]
fn decode_u16() {
assert_eq!(0, u16::from_der(I0_BYTES).unwrap());
assert_eq!(127, u16::from_der(I127_BYTES).unwrap());
assert_eq!(255, u16::from_der(I255_BYTES).unwrap());
assert_eq!(256, u16::from_der(I256_BYTES).unwrap());
assert_eq!(32767, u16::from_der(I32767_BYTES).unwrap());
assert_eq!(65535, u16::from_der(I65535_BYTES).unwrap());
}
#[test]
fn encode_i8() {
let mut buffer = [0u8; 3];
assert_eq!(I0_BYTES, 0i8.encode_to_slice(&mut buffer).unwrap());
assert_eq!(I127_BYTES, 127i8.encode_to_slice(&mut buffer).unwrap());
assert_eq!(
INEG128_BYTES,
(-128i8).encode_to_slice(&mut buffer).unwrap()
);
}
#[test]
fn encode_i16() {
let mut buffer = [0u8; 4];
assert_eq!(I0_BYTES, 0i16.encode_to_slice(&mut buffer).unwrap());
assert_eq!(I127_BYTES, 127i16.encode_to_slice(&mut buffer).unwrap());
assert_eq!(I128_BYTES, 128i16.encode_to_slice(&mut buffer).unwrap());
assert_eq!(I255_BYTES, 255i16.encode_to_slice(&mut buffer).unwrap());
assert_eq!(I256_BYTES, 256i16.encode_to_slice(&mut buffer).unwrap());
assert_eq!(I32767_BYTES, 32767i16.encode_to_slice(&mut buffer).unwrap());
assert_eq!(
INEG128_BYTES,
(-128i16).encode_to_slice(&mut buffer).unwrap()
);
assert_eq!(
INEG129_BYTES,
(-129i16).encode_to_slice(&mut buffer).unwrap()
);
assert_eq!(
INEG32768_BYTES,
(-32768i16).encode_to_slice(&mut buffer).unwrap()
);
}
#[test]
fn encode_u8() {
let mut buffer = [0u8; 4];
assert_eq!(I0_BYTES, 0u8.encode_to_slice(&mut buffer).unwrap());
assert_eq!(I127_BYTES, 127u8.encode_to_slice(&mut buffer).unwrap());
assert_eq!(I255_BYTES, 255u8.encode_to_slice(&mut buffer).unwrap());
}
#[test]
fn encode_u16() {
let mut buffer = [0u8; 5];
assert_eq!(I0_BYTES, 0u16.encode_to_slice(&mut buffer).unwrap());
assert_eq!(I127_BYTES, 127u16.encode_to_slice(&mut buffer).unwrap());
assert_eq!(I128_BYTES, 128u16.encode_to_slice(&mut buffer).unwrap());
assert_eq!(I255_BYTES, 255u16.encode_to_slice(&mut buffer).unwrap());
assert_eq!(I256_BYTES, 256u16.encode_to_slice(&mut buffer).unwrap());
assert_eq!(I32767_BYTES, 32767u16.encode_to_slice(&mut buffer).unwrap());
assert_eq!(I65535_BYTES, 65535u16.encode_to_slice(&mut buffer).unwrap());
}
/// Integers must be encoded with a minimum number of octets
#[test]
fn reject_non_canonical() {
assert!(i8::from_der(&[0x02, 0x02, 0x00, 0x00]).is_err());
assert!(i16::from_der(&[0x02, 0x02, 0x00, 0x00]).is_err());
assert!(u8::from_der(&[0x02, 0x02, 0x00, 0x00]).is_err());
assert!(u16::from_der(&[0x02, 0x02, 0x00, 0x00]).is_err());
}
}

442
vendor/der/src/asn1/integer/int.rs vendored Normal file
View File

@@ -0,0 +1,442 @@
//! Support for encoding signed integers
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;
#[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.
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];
output[offset..].copy_from_slice(bytes);
Ok(output)
}
None => {
let expected_len = Length::try_from(N)?;
let actual_len = Length::try_from(bytes.len())?;
Err(ErrorKind::Incomplete {
expected_len,
actual_len,
}
.into())
}
}
}
/// Encode the given big endian bytes representing an integer as ASN.1 DER.
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 **negative** integer serialized as bytes.
#[inline]
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.
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;
continue;
}
break;
}
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);
}
}
}

428
vendor/der/src/asn1/integer/uint.rs vendored Normal file
View File

@@ -0,0 +1,428 @@
//! Unsigned integer decoders/encoders.
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.
///
/// Returns a byte array of the requested size containing a big endian integer.
pub(crate) fn decode_to_slice(bytes: &[u8]) -> Result<&[u8]> {
// The `INTEGER` type always encodes a signed value, so for unsigned
// values the leading `0x00` byte may need to be removed.
//
// We also disallow a leading byte which would overflow a signed ASN.1
// integer (since we're decoding an unsigned integer).
// We expect all such cases to have a leading `0x00` byte.
match bytes {
[] => Err(Tag::Integer.non_canonical_error()),
[0] => Ok(bytes),
[0, byte, ..] if *byte < 0x80 => Err(Tag::Integer.non_canonical_error()),
[0, rest @ ..] => Ok(rest),
[byte, ..] if *byte >= 0x80 => Err(Tag::Integer.value_error()),
_ => Ok(bytes),
}
}
/// Decode an unsigned integer into 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]> {
let input = decode_to_slice(bytes)?;
// Compute number of leading zeroes to add
let num_zeroes = N
.checked_sub(input.len())
.ok_or_else(|| Tag::Integer.length_error())?;
// Copy input into `N`-sized output buffer with leading zeroes
let mut output = [0u8; N];
output[num_zeroes..].copy_from_slice(input);
Ok(output)
}
/// Encode the given big endian bytes representing an integer as ASN.1 DER.
pub(crate) fn encode_bytes<W>(encoder: &mut W, bytes: &[u8]) -> Result<()>
where
W: Writer + ?Sized,
{
let bytes = strip_leading_zeroes(bytes);
if needs_leading_zero(bytes) {
encoder.write_byte(0)?;
}
encoder.write(bytes)
}
/// Get the encoded length for the given unsigned integer serialized as bytes.
#[inline]
pub(crate) fn encoded_len(bytes: &[u8]) -> Result<Length> {
let bytes = strip_leading_zeroes(bytes);
Length::try_from(bytes.len())? + u8::from(needs_leading_zero(bytes))
}
/// Strip the leading zeroes from the given byte slice
pub(crate) fn strip_leading_zeroes(mut bytes: &[u8]) -> &[u8] {
while let Some((byte, rest)) = bytes.split_first() {
if *byte == 0 && !rest.is_empty() {
bytes = rest;
} else {
break;
}
}
bytes
}
/// Does the given integer need a leading zero?
fn needs_leading_zero(bytes: &[u8]) -> bool {
matches!(bytes.first(), Some(byte) if *byte >= 0x80)
}
#[cfg(test)]
mod tests {
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() {
let arr = decode_to_array::<4>(&[1, 2]).unwrap();
assert_eq!(arr, [0, 0, 1, 2]);
}
#[test]
fn decode_to_array_leading_zero() {
let arr = decode_to_array::<4>(&[0x00, 0xFF, 0xFE]).unwrap();
assert_eq!(arr, [0x00, 0x00, 0xFF, 0xFE]);
}
#[test]
fn decode_to_array_extra_zero() {
let err = decode_to_array::<4>(&[0, 1, 2]).err().unwrap();
assert_eq!(err.kind(), ErrorKind::Noncanonical { tag: Tag::Integer });
}
#[test]
fn decode_to_array_missing_zero() {
// We're decoding an unsigned integer, but this value would be signed
let err = decode_to_array::<4>(&[0xFF, 0xFE]).err().unwrap();
assert_eq!(err.kind(), ErrorKind::Value { tag: Tag::Integer });
}
#[test]
fn decode_to_array_oversized_input() {
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 });
}
}

75
vendor/der/src/asn1/internal_macros.rs vendored Normal file
View File

@@ -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())
}
}
}
};
}

102
vendor/der/src/asn1/null.rs vendored Normal file
View File

@@ -0,0 +1,102 @@
//! ASN.1 `NULL` support.
use crate::{
asn1::AnyRef, ord::OrdIsValueOrd, BytesRef, DecodeValue, EncodeValue, Error, ErrorKind,
FixedTag, Header, Length, Reader, Result, Tag, Writer,
};
/// ASN.1 `NULL` type.
#[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() {
Ok(Null)
} else {
Err(reader.error(ErrorKind::Length { tag: Self::TAG }))
}
}
}
impl EncodeValue for Null {
fn value_len(&self) -> Result<Length> {
Ok(Length::ZERO)
}
fn encode_value(&self, _writer: &mut impl Writer) -> Result<()> {
Ok(())
}
}
impl FixedTag for Null {
const TAG: Tag = Tag::Null;
}
impl OrdIsValueOrd for Null {}
impl<'a> From<Null> for AnyRef<'a> {
fn from(_: Null) -> AnyRef<'a> {
AnyRef::from_tag_and_value(Tag::Null, BytesRef::default())
}
}
impl TryFrom<AnyRef<'_>> for () {
type Error = Error;
fn try_from(any: AnyRef<'_>) -> Result<()> {
Null::try_from(any).map(|_| ())
}
}
impl<'a> From<()> for AnyRef<'a> {
fn from(_: ()) -> AnyRef<'a> {
Null.into()
}
}
impl<'a> DecodeValue<'a> for () {
fn decode_value<R: Reader<'a>>(reader: &mut R, header: Header) -> Result<Self> {
Null::decode_value(reader, header)?;
Ok(())
}
}
impl EncodeValue for () {
fn value_len(&self) -> Result<Length> {
Ok(Length::ZERO)
}
fn encode_value(&self, _writer: &mut impl Writer) -> Result<()> {
Ok(())
}
}
impl FixedTag for () {
const TAG: Tag = Tag::Null;
}
#[cfg(test)]
mod tests {
use super::Null;
use crate::{Decode, Encode};
#[test]
fn decode() {
Null::from_der(&[0x05, 0x00]).unwrap();
}
#[test]
fn encode() {
let mut buffer = [0u8; 2];
assert_eq!(&[0x05, 0x00], Null.encode_to_slice(&mut buffer).unwrap());
assert_eq!(&[0x05, 0x00], ().encode_to_slice(&mut buffer).unwrap());
}
#[test]
fn reject_non_canonical() {
assert!(Null::from_der(&[0x05, 0x81, 0x00]).is_err());
}
}

257
vendor/der/src/asn1/octet_string.rs vendored Normal file
View File

@@ -0,0 +1,257 @@
//! ASN.1 `OCTET STRING` support.
use crate::{
asn1::AnyRef, ord::OrdIsValueOrd, BytesRef, Decode, DecodeValue, EncodeValue, ErrorKind,
FixedTag, Header, Length, Reader, Result, Tag, Writer,
};
/// ASN.1 `OCTET STRING` type: borrowed form.
///
/// Octet strings represent contiguous sequences of octets, a.k.a. bytes.
///
/// This is a zero-copy reference type which borrows from the input data.
#[derive(Copy, Clone, Debug, Eq, PartialEq, PartialOrd, Ord)]
pub struct OctetStringRef<'a> {
/// Inner value
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> {
BytesRef::new(slice)
.map(|inner| Self { inner })
.map_err(|_| ErrorKind::Length { tag: Self::TAG }.into())
}
/// Borrow the inner byte slice.
pub fn as_bytes(&self) -> &'a [u8] {
self.inner.as_slice()
}
/// Get the length of the inner byte slice.
pub fn len(&self) -> Length {
self.inner.len()
}
/// Is the inner byte slice empty?
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()
}
}
impl<'a> DecodeValue<'a> for OctetStringRef<'a> {
fn decode_value<R: Reader<'a>>(reader: &mut R, header: Header) -> Result<Self> {
let inner = BytesRef::decode_value(reader, header)?;
Ok(Self { inner })
}
}
impl EncodeValue for OctetStringRef<'_> {
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 FixedTag for OctetStringRef<'_> {
const TAG: Tag = Tag::OctetString;
}
impl OrdIsValueOrd for OctetStringRef<'_> {}
impl<'a> From<&OctetStringRef<'a>> for OctetStringRef<'a> {
fn from(value: &OctetStringRef<'a>) -> OctetStringRef<'a> {
*value
}
}
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)
}
}
impl<'a> From<OctetStringRef<'a>> for &'a [u8] {
fn from(octet_string: OctetStringRef<'a>) -> &'a [u8] {
octet_string.as_bytes()
}
}
#[cfg(feature = "alloc")]
pub use self::allocating::OctetString;
#[cfg(feature = "alloc")]
mod allocating {
use super::*;
use crate::referenced::*;
use alloc::vec::Vec;
/// 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.
pub(super) inner: Vec<u8>,
}
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()
}
}
impl_any_conversions!(OctetString);
impl AsRef<[u8]> for OctetString {
fn as_ref(&self) -> &[u8] {
self.as_bytes()
}
}
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 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)
}
}
impl FixedTag for OctetString {
const TAG: Tag = Tag::OctetString;
}
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")
}
}
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()),
}
}
}
impl OwnedToRef for OctetString {
type Borrowed<'a> = OctetStringRef<'a>;
fn owned_to_ref(&self) -> Self::Borrowed<'_> {
self.into()
}
}
// 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)
}
fn size_hint(depth: usize) -> (usize, Option<usize>) {
arbitrary::size_hint::and(u8::size_hint(depth), Vec::<u8>::size_hint(depth))
}
}
}
#[cfg(feature = "bytes")]
mod bytes {
use super::OctetString;
use crate::{DecodeValue, EncodeValue, FixedTag, Header, Length, Reader, Result, Tag, Writer};
use bytes::Bytes;
impl<'a> DecodeValue<'a> for Bytes {
fn decode_value<R: Reader<'a>>(reader: &mut R, header: Header) -> Result<Self> {
OctetString::decode_value(reader, header).map(|octet_string| octet_string.inner.into())
}
}
impl EncodeValue for Bytes {
fn value_len(&self) -> Result<Length> {
self.len().try_into()
}
fn encode_value(&self, writer: &mut impl Writer) -> Result<()> {
writer.write(self.as_ref())
}
}
impl FixedTag for Bytes {
const TAG: Tag = Tag::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");
}
}

100
vendor/der/src/asn1/oid.rs vendored Normal file
View File

@@ -0,0 +1,100 @@
//! ASN.1 `OBJECT IDENTIFIER`
use crate::{
asn1::AnyRef, ord::OrdIsValueOrd, DecodeValue, EncodeValue, Error, FixedTag, Header, Length,
Reader, Result, Tag, Tagged, Writer,
};
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];
let slice = buf
.get_mut(..header.length.try_into()?)
.ok_or_else(|| Self::TAG.length_error())?;
let actual_len = reader.read_into(slice)?.len();
debug_assert_eq!(actual_len, header.length.try_into()?);
Ok(Self::from_bytes(slice)?)
}
}
impl EncodeValue for ObjectIdentifier {
fn value_len(&self) -> Result<Length> {
Length::try_from(self.as_bytes().len())
}
fn encode_value(&self, writer: &mut impl Writer) -> Result<()> {
writer.write(self.as_bytes())
}
}
impl FixedTag for ObjectIdentifier {
const TAG: Tag = Tag::ObjectIdentifier;
}
impl OrdIsValueOrd for ObjectIdentifier {}
impl<'a> From<&'a ObjectIdentifier> for AnyRef<'a> {
fn from(oid: &'a ObjectIdentifier) -> AnyRef<'a> {
// Note: ensuring an infallible conversion is possible relies on the
// invariant that `const_oid::MAX_LEN <= Length::max()`.
//
// The `length()` test below ensures this is the case.
let value = oid
.as_bytes()
.try_into()
.expect("OID length invariant violated");
AnyRef::from_tag_and_value(Tag::ObjectIdentifier, value)
}
}
#[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;
fn try_from(any: AnyRef<'_>) -> Result<ObjectIdentifier> {
any.tag().assert_eq(Tag::ObjectIdentifier)?;
Ok(ObjectIdentifier::from_bytes(any.value())?)
}
}
#[cfg(test)]
mod tests {
use super::ObjectIdentifier;
use crate::{Decode, Encode, Length};
const EXAMPLE_OID: ObjectIdentifier = ObjectIdentifier::new_unwrap("1.2.840.113549");
const EXAMPLE_OID_BYTES: &[u8; 8] = &[0x06, 0x06, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d];
#[test]
fn decode() {
let oid = ObjectIdentifier::from_der(EXAMPLE_OID_BYTES).unwrap();
assert_eq!(EXAMPLE_OID, oid);
}
#[test]
fn encode() {
let mut buffer = [0u8; 8];
assert_eq!(
EXAMPLE_OID_BYTES,
EXAMPLE_OID.encode_to_slice(&mut buffer).unwrap()
);
}
#[test]
fn length() {
// Ensure an infallible `From` conversion to `Any` will never panic
assert!(ObjectIdentifier::MAX_SIZE <= Length::MAX.try_into().unwrap());
}
}

66
vendor/der/src/asn1/optional.rs vendored Normal file
View File

@@ -0,0 +1,66 @@
//! ASN.1 `OPTIONAL` as mapped to Rust's `Option` type
use crate::{Choice, Decode, DerOrd, Encode, Length, Reader, Result, Tag, Writer};
use core::cmp::Ordering;
impl<'a, T> Decode<'a> for Option<T>
where
T: Choice<'a>, // NOTE: all `Decode + Tagged` types receive a blanket `Choice` impl
{
fn decode<R: Reader<'a>>(reader: &mut R) -> Result<Option<T>> {
if let Some(byte) = reader.peek_byte() {
if T::can_decode(Tag::try_from(byte)?) {
return T::decode(reader).map(Some);
}
}
Ok(None)
}
}
impl<T> DerOrd for Option<T>
where
T: DerOrd,
{
fn der_cmp(&self, other: &Self) -> Result<Ordering> {
match self {
Some(a) => match other {
Some(b) => a.der_cmp(b),
None => Ok(Ordering::Greater),
},
None => Ok(Ordering::Less),
}
}
}
impl<T> Encode for Option<T>
where
T: Encode,
{
fn encoded_len(&self) -> Result<Length> {
(&self).encoded_len()
}
fn encode(&self, writer: &mut impl Writer) -> Result<()> {
(&self).encode(writer)
}
}
impl<T> Encode for &Option<T>
where
T: Encode,
{
fn encoded_len(&self) -> Result<Length> {
match self {
Some(encodable) => encodable.encoded_len(),
None => Ok(0u8.into()),
}
}
fn encode(&self, encoder: &mut impl Writer) -> Result<()> {
match self {
Some(encodable) => encodable.encode(encoder),
None => Ok(()),
}
}
}

252
vendor/der/src/asn1/printable_string.rs vendored Normal file
View File

@@ -0,0 +1,252 @@
//! ASN.1 `PrintableString` support.
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.
///
/// 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`].
///
/// This is a zero-copy reference type which borrows from the input data.
///
/// # Supported characters
///
/// The following ASCII characters/ranges are supported:
///
/// - `A..Z`
/// - `a..z`
/// - `0..9`
/// - "` `" (i.e. space)
/// - `\`
/// - `(`
/// - `)`
/// - `+`
/// - `,`
/// - `-`
/// - `.`
/// - `/`
/// - `:`
/// - `=`
/// - `?`
#[derive(Copy, Clone, Eq, PartialEq, PartialOrd, Ord)]
pub struct PrintableStringRef<'a> {
/// Inner value
inner: StrRef<'a>,
}
impl<'a> PrintableStringRef<'a> {
/// Create a new ASN.1 `PrintableString`.
pub fn new<T>(input: &'a T) -> Result<Self>
where
T: AsRef<[u8]> + ?Sized,
{
let input = input.as_ref();
// Validate all characters are within PrintableString's allowed set
for &c in input.iter() {
match c {
b'A'..=b'Z'
| b'a'..=b'z'
| b'0'..=b'9'
| b' '
| b'\''
| b'('
| b')'
| b'+'
| b','
| b'-'
| b'.'
| b'/'
| b':'
| b'='
| b'?' => (),
_ => return Err(Self::TAG.value_error()),
}
}
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 = StrRef<'a>;
fn deref(&self) -> &Self::Target {
&self.inner
}
}
impl<'a> From<&PrintableStringRef<'a>> for PrintableStringRef<'a> {
fn from(value: &PrintableStringRef<'a>) -> PrintableStringRef<'a> {
*value
}
}
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())
}
}
#[cfg(feature = "alloc")]
pub use self::allocation::PrintableString;
#[cfg(feature = "alloc")]
mod allocation {
use super::PrintableStringRef;
use crate::{
asn1::AnyRef,
referenced::{OwnedToRef, RefToOwned},
BytesRef, Error, FixedTag, Result, StrOwned, Tag,
};
use alloc::string::String;
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,
}
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_printable_string!(PrintableString);
impl Deref for PrintableString {
type Target = StrOwned;
fn deref(&self) -> &Self::Target {
&self.inner
}
}
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<&'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> RefToOwned<'a> for PrintableStringRef<'a> {
type Owned = PrintableString;
fn ref_to_owned(&self) -> Self::Owned {
PrintableString {
inner: self.inner.ref_to_owned(),
}
}
}
impl OwnedToRef for PrintableString {
type Borrowed<'a> = PrintableStringRef<'a>;
fn owned_to_ref(&self) -> Self::Borrowed<'_> {
PrintableStringRef {
inner: self.inner.owned_to_ref(),
}
}
}
impl TryFrom<String> for PrintableString {
type Error = Error;
fn try_from(input: String) -> Result<Self> {
PrintableStringRef::new(&input)?;
StrOwned::new(input)
.map(|inner| Self { inner })
.map_err(|_| Self::TAG.value_error())
}
}
}
#[cfg(test)]
mod tests {
use super::PrintableStringRef;
use crate::Decode;
#[test]
fn parse_bytes() {
let example_bytes = &[
0x13, 0x0b, 0x54, 0x65, 0x73, 0x74, 0x20, 0x55, 0x73, 0x65, 0x72, 0x20, 0x31,
];
let printable_string = PrintableStringRef::from_der(example_bytes).unwrap();
assert_eq!(printable_string.as_str(), "Test User 1");
}
}

990
vendor/der/src/asn1/real.rs vendored Normal file
View File

@@ -0,0 +1,990 @@
//! ASN.1 `REAL` support.
// TODO(tarcieri): checked arithmetic
#![allow(
clippy::cast_lossless,
clippy::cast_sign_loss,
clippy::integer_arithmetic
)]
use crate::{
BytesRef, DecodeValue, EncodeValue, FixedTag, Header, Length, Reader, Result, StrRef, Tag,
Writer,
};
use super::integer::uint::strip_leading_zeroes;
impl<'a> DecodeValue<'a> for f64 {
fn decode_value<R: Reader<'a>>(reader: &mut R, header: Header) -> Result<Self> {
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 = 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);
if base != 0 {
// Real related error: base is not DER compliant (base encoded in enum)
return Err(Tag::Real.value_error());
}
// Section 8.5.7.3
let scaling_factor = mnth_bits_to_u8::<3, 2>(bytes);
// Section 8.5.7.4
let mantissa_start;
let exponent = match mnth_bits_to_u8::<1, 0>(bytes) {
0 => {
mantissa_start = 2;
let ebytes = (i16::from_be_bytes([0x0, bytes[1]])).to_be_bytes();
u64::from_be_bytes([0x0, 0x0, 0x0, 0x0, 0x0, 0x0, ebytes[0], ebytes[1]])
}
1 => {
mantissa_start = 3;
let ebytes = (i16::from_be_bytes([bytes[1], bytes[2]])).to_be_bytes();
u64::from_be_bytes([0x0, 0x0, 0x0, 0x0, 0x0, 0x0, ebytes[0], ebytes[1]])
}
_ => {
// Real related error: encoded exponent cannot be represented on an IEEE-754 double
return Err(Tag::Real.value_error());
}
};
// Section 8.5.7.5: Read the remaining bytes for the mantissa
let mut n_bytes = [0x0; 8];
for (pos, byte) in bytes[mantissa_start..].iter().rev().enumerate() {
n_bytes[7 - pos] = *byte;
}
let n = u64::from_be_bytes(n_bytes);
// Multiply byt 2^F corresponds to just a left shift
let mantissa = n << scaling_factor;
// Create the f64
Ok(encode_f64(sign, exponent, mantissa))
} else if is_nth_bit_one::<6>(bytes) {
// This either a special value, or it's the value minus zero is encoded, section 8.5.9 applies
match mnth_bits_to_u8::<1, 0>(bytes) {
0 => Ok(f64::INFINITY),
1 => Ok(f64::NEG_INFINITY),
2 => Ok(f64::NAN),
3 => Ok(-0.0_f64),
_ => Err(Tag::Real.value_error()),
}
} else {
let astr = StrRef::from_bytes(&bytes[1..])?;
match astr.inner.parse::<f64>() {
Ok(val) => Ok(val),
// Real related error: encoding not supported or malformed
Err(_) => Err(Tag::Real.value_error()),
}
}
}
}
impl EncodeValue for f64 {
fn value_len(&self) -> Result<Length> {
if self.is_sign_positive() && (*self) < f64::MIN_POSITIVE {
// Zero: positive yet smaller than the minimum positive number
Ok(Length::ZERO)
} else if self.is_nan()
|| self.is_infinite()
|| (self.is_sign_negative() && -self < f64::MIN_POSITIVE)
{
// NaN, infinite (positive or negative), or negative zero (negative but its negative is less than the min positive number)
Ok(Length::ONE)
} else {
// The length is that of the first octets plus those needed for the exponent plus those needed for the mantissa
let (_sign, exponent, mantissa) = decode_f64(*self);
let exponent_len = if exponent == 0 {
// Section 8.5.7.4: there must be at least one octet for exponent encoding
// But, if the exponent is zero, it'll be skipped, so we make sure force it to 1
Length::ONE
} else {
let ebytes = exponent.to_be_bytes();
Length::try_from(strip_leading_zeroes(&ebytes).len())?
};
let mantissa_len = if mantissa == 0 {
Length::ONE
} else {
let mbytes = mantissa.to_be_bytes();
Length::try_from(strip_leading_zeroes(&mbytes).len())?
};
exponent_len + mantissa_len + Length::ONE
}
}
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
if self.is_nan()
|| self.is_infinite()
|| (self.is_sign_negative() && -self < f64::MIN_POSITIVE)
|| (self.is_sign_positive() && (*self) < f64::MIN_POSITIVE)
{
if self.is_sign_positive() && (*self) < f64::MIN_POSITIVE {
// Zero
return Ok(());
} else if self.is_nan() {
// Not a number
writer.write_byte(0b0100_0010)?;
} else if self.is_infinite() {
if self.is_sign_negative() {
// Negative infinity
writer.write_byte(0b0100_0001)?;
} else {
// Plus infinity
writer.write_byte(0b0100_0000)?;
}
} else {
// Minus zero
writer.write_byte(0b0100_0011)?;
}
} else {
// Always use binary encoding, set bit 8 to 1
let mut first_byte = 0b1000_0000;
if self.is_sign_negative() {
// Section 8.5.7.1: set bit 7 to 1 if negative
first_byte |= 0b0100_0000;
}
// Bits 6 and 5 are set to 0 to specify that binary encoding is used
//
// NOTE: the scaling factor is only used to align the implicit point of the mantissa.
// This is unnecessary in DER because the base is 2, and therefore necessarily aligned.
// Therefore, we do not modify the mantissa in anyway after this function call, which
// already adds the implicit one of the IEEE 754 representation.
let (_sign, exponent, mantissa) = decode_f64(*self);
// Encode the exponent as two's complement on 16 bits and remove the bias
let exponent_bytes = exponent.to_be_bytes();
let ebytes = strip_leading_zeroes(&exponent_bytes);
match ebytes.len() {
0 | 1 => {}
2 => first_byte |= 0b0000_0001,
3 => first_byte |= 0b0000_0010,
_ => {
// TODO: support multi octet exponent encoding?
return Err(Tag::Real.value_error());
}
}
writer.write_byte(first_byte)?;
// Encode both bytes or just the last one, handled by encode_bytes directly
// Rust already encodes the data as two's complement, so no further processing is needed
writer.write(ebytes)?;
// Now, encode the mantissa as unsigned binary number
let mantissa_bytes = mantissa.to_be_bytes();
let mbytes = strip_leading_zeroes(&mantissa_bytes);
writer.write(mbytes)?;
}
Ok(())
}
}
impl FixedTag for f64 {
const TAG: Tag = Tag::Real;
}
/// Is the N-th bit 1 in the first octet?
/// NOTE: this function is zero indexed
pub(crate) fn is_nth_bit_one<const N: usize>(bytes: &[u8]) -> bool {
if N < 8 {
bytes
.first()
.map(|byte| byte & (1 << N) != 0)
.unwrap_or(false)
} else {
false
}
}
/// Convert bits M, N into a u8, in the first octet only
pub(crate) fn mnth_bits_to_u8<const M: usize, const N: usize>(bytes: &[u8]) -> u8 {
let bit_m = is_nth_bit_one::<M>(bytes);
let bit_n = is_nth_bit_one::<N>(bytes);
(bit_m as u8) << 1 | bit_n as u8
}
/// Decode an f64 as its sign, exponent, and mantissa in u64 and in that order, using bit shifts and masks.
/// Note: this function **removes** the 1023 bias from the exponent and adds the implicit 1
#[allow(clippy::cast_possible_truncation)]
pub(crate) fn decode_f64(f: f64) -> (u64, u64, u64) {
let bits = f.to_bits();
let sign = bits >> 63;
let exponent = bits >> 52 & 0x7ff;
let exponent_bytes_no_bias = (exponent as i16 - 1023).to_be_bytes();
let exponent_no_bias = u64::from_be_bytes([
0x0,
0x0,
0x0,
0x0,
0x0,
0x0,
exponent_bytes_no_bias[0],
exponent_bytes_no_bias[1],
]);
let mantissa = bits & 0xfffffffffffff;
(sign, exponent_no_bias, mantissa + 1)
}
/// Encode an f64 from its sign, exponent (**without** the 1023 bias), and (mantissa - 1) using bit shifts as received by ASN1
pub(crate) fn encode_f64(sign: u64, exponent: u64, mantissa: u64) -> f64 {
// Add the bias to the exponent
let exponent_with_bias =
(i16::from_be_bytes([exponent.to_be_bytes()[6], exponent.to_be_bytes()[7]]) + 1023) as u64;
let bits = sign << 63 | exponent_with_bias << 52 | (mantissa - 1);
f64::from_bits(bits)
}
#[cfg(test)]
mod tests {
use crate::{Decode, Encode};
#[test]
fn decode_subnormal() {
assert!(f64::from_der(&[0x09, 0x01, 0b0100_0010]).unwrap().is_nan());
let plus_infty = f64::from_der(&[0x09, 0x01, 0b0100_0000]).unwrap();
assert!(plus_infty.is_infinite() && plus_infty.is_sign_positive());
let neg_infty = f64::from_der(&[0x09, 0x01, 0b0100_0001]).unwrap();
assert!(neg_infty.is_infinite() && neg_infty.is_sign_negative());
let neg_zero = f64::from_der(&[0x09, 0x01, 0b0100_0011]).unwrap();
assert!(neg_zero.is_sign_negative() && neg_zero.abs() < f64::EPSILON);
}
#[test]
fn encode_subnormal() {
// All subnormal fit in three bytes
let mut buffer = [0u8; 3];
assert_eq!(
&[0x09, 0x01, 0b0100_0010],
f64::NAN.encode_to_slice(&mut buffer).unwrap()
);
assert_eq!(
&[0x09, 0x01, 0b0100_0000],
f64::INFINITY.encode_to_slice(&mut buffer).unwrap()
);
assert_eq!(
&[0x09, 0x01, 0b0100_0001],
f64::NEG_INFINITY.encode_to_slice(&mut buffer).unwrap()
);
assert_eq!(
&[0x09, 0x01, 0b0100_0011],
(-0.0_f64).encode_to_slice(&mut buffer).unwrap()
);
}
#[test]
fn encdec_normal() {
// The comments correspond to the decoded value from the ASN.1 playground when the bytes are inputed.
{
// rec1value R ::= 0
let val = 0.0;
let expected = &[0x09, 0x0];
let mut buffer = [0u8; 2];
let encoded = val.encode_to_slice(&mut buffer).unwrap();
assert_eq!(
expected, encoded,
"invalid encoding of {}:\ngot {:x?}\nwant: {:x?}",
val, encoded, expected
);
let decoded = f64::from_der(encoded).unwrap();
assert!(
(decoded - val).abs() < f64::EPSILON,
"wanted: {}\tgot: {}",
val,
decoded
);
}
{
// rec1value R ::= { mantissa 1, base 2, exponent 0 }
let val = 1.0;
let expected = &[0x09, 0x03, 0x80, 0x00, 0x01];
let mut buffer = [0u8; 5];
let encoded = val.encode_to_slice(&mut buffer).unwrap();
assert_eq!(
expected, encoded,
"invalid encoding of {}:\ngot {:x?}\nwant: {:x?}",
val, encoded, expected
);
let decoded = f64::from_der(encoded).unwrap();
assert!(
(decoded - val).abs() < f64::EPSILON,
"wanted: {}\tgot: {}",
val,
decoded
);
}
{
// rec1value R ::= { mantissa -1, base 2, exponent 0 }
let val = -1.0;
let expected = &[0x09, 0x03, 0xc0, 0x00, 0x01];
let mut buffer = [0u8; 5];
let encoded = val.encode_to_slice(&mut buffer).unwrap();
assert_eq!(
expected, encoded,
"invalid encoding of {}:\ngot {:x?}\nwant: {:x?}",
val, encoded, expected
);
let decoded = f64::from_der(encoded).unwrap();
assert!(
(decoded - val).abs() < f64::EPSILON,
"wanted: {}\tgot: {}",
val,
decoded
);
}
{
// rec1value R ::= { mantissa -1, base 2, exponent 1 }
let val = -1.0000000000000002;
let expected = &[0x09, 0x03, 0xc0, 0x00, 0x02];
let mut buffer = [0u8; 5];
let encoded = val.encode_to_slice(&mut buffer).unwrap();
assert_eq!(
expected, encoded,
"invalid encoding of {}:\ngot {:x?}\nwant: {:x?}",
val, encoded, expected
);
let decoded = f64::from_der(encoded).unwrap();
assert!(
(decoded - val).abs() < f64::EPSILON,
"wanted: {}\tgot: {}",
val,
decoded
);
}
{
// rec1value R ::= { mantissa 1, base 2, exponent -1022 }
// NOTE: f64::MIN_EXP == -1021 so the exponent decoded by ASN.1 is what we expect
let val = f64::MIN_POSITIVE;
let expected = &[0x09, 0x04, 0x81, 0xfc, 0x02, 0x01];
let mut buffer = [0u8; 7];
let encoded = val.encode_to_slice(&mut buffer).unwrap();
assert_eq!(
expected, encoded,
"invalid encoding of {}:\ngot {:x?}\nwant: {:x?}",
val, encoded, expected
);
let decoded = f64::from_der(encoded).unwrap();
assert!(
(decoded - val).abs() < f64::EPSILON,
"wanted: {}\tgot: {}",
val,
decoded
);
}
{
// rec4value R ::= { mantissa 1, base 2, exponent 3 }
let val = 1.0000000000000016;
let expected = &[0x09, 0x03, 0x80, 0x00, 0x08];
let mut buffer = [0u8; 5];
let encoded = val.encode_to_slice(&mut buffer).unwrap();
assert_eq!(
expected, encoded,
"invalid encoding of {}:\ngot {:x?}\nwant: {:x?}",
val, encoded, expected
);
let decoded = f64::from_der(encoded).unwrap();
assert!(
(decoded - val).abs() < f64::EPSILON,
"wanted: {}\tgot: {}",
val,
decoded
);
}
{
// rec5value R ::= { mantissa 4222124650659841, base 2, exponent 4 }
let val = 31.0;
let expected = &[
0x9, 0x9, 0x80, 0x04, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
];
let mut buffer = [0u8; 11];
let encoded = val.encode_to_slice(&mut buffer).unwrap();
assert_eq!(
expected, encoded,
"invalid encoding of {}:\ngot {:x?}\nwant: {:x?}",
val, encoded, expected
);
let decoded = f64::from_der(encoded).unwrap();
assert!(
(decoded - val).abs() < f64::EPSILON,
"wanted: {}\tgot: {}",
val,
decoded
);
}
}
#[test]
fn encdec_irrationals() {
{
let val = core::f64::consts::PI;
let expected = &[
0x09, 0x09, 0x80, 0x01, 0x09, 0x21, 0xfb, 0x54, 0x44, 0x2d, 0x19,
];
let mut buffer = [0u8; 11];
let encoded = val.encode_to_slice(&mut buffer).unwrap();
assert_eq!(
expected, encoded,
"invalid encoding of {}:\ngot {:x?}\nwant: {:x?}",
val, encoded, expected
);
let decoded = f64::from_der(encoded).unwrap();
assert!(
(decoded - val).abs() < f64::EPSILON,
"wanted: {}\tgot: {}",
val,
decoded
);
}
{
let val = core::f64::consts::E;
let expected = &[
0x09, 0x09, 0x80, 0x01, 0x05, 0xbf, 0x0a, 0x8b, 0x14, 0x57, 0x6a,
];
let mut buffer = [0u8; 12];
let encoded = val.encode_to_slice(&mut buffer).unwrap();
assert_eq!(
expected, encoded,
"invalid encoding of {}:\ngot {:x?}\nwant: {:x?}",
val, encoded, expected
);
let decoded = f64::from_der(encoded).unwrap();
assert!(
(decoded - val).abs() < f64::EPSILON,
"wanted: {}\tgot: {}",
val,
decoded
);
}
{
let val = core::f64::consts::LN_2;
let expected = &[
0x09, 0x0a, 0x81, 0xff, 0xff, 0x6, 0x2e, 0x42, 0xfe, 0xfa, 0x39, 0xf0,
];
let mut buffer = [0u8; 12];
let encoded = val.encode_to_slice(&mut buffer).unwrap();
assert_eq!(
expected, encoded,
"invalid encoding of {}:\ngot {:x?}\nwant: {:x?}",
val, encoded, expected
);
let decoded = f64::from_der(encoded).unwrap();
assert!(
(decoded - val).abs() < f64::EPSILON,
"wanted: {}\tgot: {}",
val,
decoded
);
}
}
#[test]
fn encdec_reasonable_f64() {
// Tests the encoding and decoding of reals with some arbitrary numbers
{
// rec1value R ::= { mantissa 2414341043715239, base 2, exponent 21 }
let val = 3221417.1584163485;
let expected = &[
0x9, 0x9, 0x80, 0x15, 0x8, 0x93, 0xd4, 0x94, 0x46, 0xfc, 0xa7,
];
let mut buffer = [0u8; 11];
let encoded = val.encode_to_slice(&mut buffer).unwrap();
assert_eq!(
expected, encoded,
"invalid encoding of {}:\ngot {:x?}\nwant: {:x?}",
val, encoded, expected
);
let decoded = f64::from_der(encoded).unwrap();
assert!(
(decoded - val).abs() < f64::EPSILON,
"wanted: {}\tgot: {}",
val,
decoded
);
}
{
// rec1value R ::= { mantissa 2671155248072715, base 2, exponent 23 }
let val = 13364022.365665454;
let expected = &[
0x09, 0x09, 0x80, 0x17, 0x09, 0x7d, 0x66, 0xcb, 0xb3, 0x88, 0x0b,
];
let mut buffer = [0u8; 12];
let encoded = val.encode_to_slice(&mut buffer).unwrap();
assert_eq!(
expected, encoded,
"invalid encoding of {}:\ngot {:x?}\nwant: {:x?}",
val, encoded, expected
);
let decoded = f64::from_der(encoded).unwrap();
assert!(
(decoded - val).abs() < f64::EPSILON,
"wanted: {}\tgot: {}",
val,
decoded
);
}
{
// rec1value R ::= { mantissa -4386812962460287, base 2, exponent 14 }
let val = -32343.132588105735;
let expected = &[
0x09, 0x09, 0xc0, 0x0e, 0x0f, 0x95, 0xc8, 0x7c, 0x52, 0xd2, 0x7f,
];
let mut buffer = [0u8; 12];
let encoded = val.encode_to_slice(&mut buffer).unwrap();
assert_eq!(
expected, encoded,
"invalid encoding of {}:\ngot {:x?}\nwant: {:x?}",
val, encoded, expected
);
let decoded = f64::from_der(encoded).unwrap();
assert!(
(decoded - val).abs() < f64::EPSILON,
"wanted: {}\tgot: {}",
val,
decoded
);
}
{
let val = -27084.866751869475;
let expected = &[
0x09, 0x09, 0xc0, 0x0e, 0x0a, 0x73, 0x37, 0x78, 0xdc, 0xd5, 0x4a,
];
let mut buffer = [0u8; 12];
let encoded = val.encode_to_slice(&mut buffer).unwrap();
assert_eq!(
expected, encoded,
"invalid encoding of {}:\ngot {:x?}\nwant: {:x?}",
val, encoded, expected
);
let decoded = f64::from_der(encoded).unwrap();
assert!(
(decoded - val).abs() < f64::EPSILON,
"wanted: {}\tgot: {}",
val,
decoded
);
}
{
// rec1value R ::= { mantissa -4372913134428149, base 2, exponent 7 }
let val = -252.28566647111404;
let expected = &[
0x09, 0x09, 0xc0, 0x07, 0x0f, 0x89, 0x24, 0x2e, 0x02, 0xdf, 0xf5,
];
let mut buffer = [0u8; 12];
let encoded = val.encode_to_slice(&mut buffer).unwrap();
assert_eq!(
expected, encoded,
"invalid encoding of {}:\ngot {:x?}\nwant: {:x?}",
val, encoded, expected
);
let decoded = f64::from_der(encoded).unwrap();
assert!(
(decoded - val).abs() < f64::EPSILON,
"wanted: {}\tgot: {}",
val,
decoded
);
}
{
let val = -14.399709612928548;
let expected = &[
0x09, 0x09, 0xc0, 0x03, 0x0c, 0xcc, 0xa6, 0xbd, 0x06, 0xd9, 0x92,
];
let mut buffer = [0u8; 12];
let encoded = val.encode_to_slice(&mut buffer).unwrap();
assert_eq!(
expected, encoded,
"invalid encoding of {}:\ngot {:x?}\nwant: {:x?}",
val, encoded, expected
);
let decoded = f64::from_der(encoded).unwrap();
assert!(
(decoded - val).abs() < f64::EPSILON,
"wanted: {}\tgot: {}",
val,
decoded
);
}
{
let val = -0.08340570261832964;
let expected = &[
0x09, 0x0a, 0xc1, 0xff, 0xfc, 0x05, 0x5a, 0x13, 0x7d, 0x0b, 0xae, 0x3d,
];
let mut buffer = [0u8; 12];
let encoded = val.encode_to_slice(&mut buffer).unwrap();
assert_eq!(
expected, encoded,
"invalid encoding of {}:\ngot {:x?}\nwant: {:x?}",
val, encoded, expected
);
let decoded = f64::from_der(encoded).unwrap();
assert!(
(decoded - val).abs() < f64::EPSILON,
"wanted: {}\tgot: {}",
val,
decoded
);
}
{
let val = 0.00536851453803701;
let expected = &[
0x09, 0x0a, 0x81, 0xff, 0xf8, 0x05, 0xfd, 0x4b, 0xa5, 0xe7, 0x4c, 0x93,
];
let mut buffer = [0u8; 12];
let encoded = val.encode_to_slice(&mut buffer).unwrap();
assert_eq!(
expected, encoded,
"invalid encoding of {}:\ngot {:x?}\nwant: {:x?}",
val, encoded, expected
);
let decoded = f64::from_der(encoded).unwrap();
assert!(
(decoded - val).abs() < f64::EPSILON,
"wanted: {}\tgot: {}",
val,
decoded
);
}
{
let val = 0.00045183525648866433;
let expected = &[
0x09, 0x0a, 0x81, 0xff, 0xf4, 0x0d, 0x9c, 0x89, 0xa6, 0x59, 0x33, 0x39,
];
let mut buffer = [0u8; 12];
let encoded = val.encode_to_slice(&mut buffer).unwrap();
assert_eq!(
expected, encoded,
"invalid encoding of {}:\ngot {:x?}\nwant: {:x?}",
val, encoded, expected
);
let decoded = f64::from_der(encoded).unwrap();
assert!(
(decoded - val).abs() < f64::EPSILON,
"wanted: {}\tgot: {}",
val,
decoded
);
}
{
let val = 0.000033869092002682955;
let expected = &[
0x09, 0x0a, 0x81, 0xff, 0xf1, 0x01, 0xc1, 0xd5, 0x23, 0xd5, 0x54, 0x7c,
];
let mut buffer = [0u8; 12];
let encoded = val.encode_to_slice(&mut buffer).unwrap();
assert_eq!(
expected, encoded,
"invalid encoding of {}:\ngot {:x?}\nwant: {:x?}",
val, encoded, expected
);
let decoded = f64::from_der(encoded).unwrap();
assert!(
(decoded - val).abs() < f64::EPSILON,
"wanted: {}\tgot: {}",
val,
decoded
);
}
{
let val = 0.0000011770891033600088;
let expected = &[
0x09, 0x0a, 0x81, 0xff, 0xec, 0x03, 0xbf, 0x8f, 0x27, 0xf4, 0x62, 0x56,
];
let mut buffer = [0u8; 12];
let encoded = val.encode_to_slice(&mut buffer).unwrap();
assert_eq!(
expected, encoded,
"invalid encoding of {}:\ngot {:x?}\nwant: {:x?}",
val, encoded, expected
);
let decoded = f64::from_der(encoded).unwrap();
assert!(
(decoded - val).abs() < f64::EPSILON,
"wanted: {}\tgot: {}",
val,
decoded
);
}
{
let val = 0.00000005549514041997082;
let expected = &[
0x09, 0x0a, 0x81, 0xff, 0xe7, 0x0d, 0xcb, 0x31, 0xab, 0x6e, 0xb8, 0xd7,
];
let mut buffer = [0u8; 12];
let encoded = val.encode_to_slice(&mut buffer).unwrap();
assert_eq!(
expected, encoded,
"invalid encoding of {}:\ngot {:x?}\nwant: {:x?}",
val, encoded, expected
);
let decoded = f64::from_der(encoded).unwrap();
assert!(
(decoded - val).abs() < f64::EPSILON,
"wanted: {}\tgot: {}",
val,
decoded
);
}
{
let val = 0.0000000012707044685547803;
let expected = &[
0x09, 0x0a, 0x81, 0xff, 0xe2, 0x05, 0xd4, 0x9e, 0x0a, 0xf2, 0xff, 0x1f,
];
let mut buffer = [0u8; 12];
let encoded = val.encode_to_slice(&mut buffer).unwrap();
assert_eq!(
expected, encoded,
"invalid encoding of {}:\ngot {:x?}\nwant: {:x?}",
val, encoded, expected
);
let decoded = f64::from_der(encoded).unwrap();
assert!(
(decoded - val).abs() < f64::EPSILON,
"wanted: {}\tgot: {}",
val,
decoded
);
}
{
let val = 0.00000000002969611878378562;
let expected = &[
0x09, 0x09, 0x81, 0xff, 0xdd, 0x53, 0x5b, 0x6f, 0x97, 0xee, 0xb6,
];
let mut buffer = [0u8; 11];
let encoded = val.encode_to_slice(&mut buffer).unwrap();
assert_eq!(
expected, encoded,
"invalid encoding of {}:\ngot {:x?}\nwant: {:x?}",
val, encoded, expected
);
let decoded = f64::from_der(encoded).unwrap();
assert!(
(decoded - val).abs() < f64::EPSILON,
"wanted: {}\tgot: {}",
val,
decoded
);
}
}
#[test]
fn reject_non_canonical() {
assert!(f64::from_der(&[0x09, 0x81, 0x00]).is_err());
}
#[test]
fn encdec_f64() {
use super::{decode_f64, encode_f64};
// Test that the extraction and recreation works
for val in [
1.0,
0.1,
-0.1,
-1.0,
0.0,
f64::MIN_POSITIVE,
f64::MAX,
f64::MIN,
3.1415,
951.2357864,
-3.1415,
-951.2357864,
] {
let (s, e, m) = decode_f64(val);
let val2 = encode_f64(s, e, m);
assert!(
(val - val2).abs() < f64::EPSILON,
"fail - want {}\tgot {}",
val,
val2
);
}
}
#[test]
fn validation_cases() {
// Caveat: these test cases are validated on the ASN.1 playground: https://asn1.io/asn1playground/ .
// The test case consists in inputing the bytes in the "decode" field and checking that the decoded
// value corresponds to the one encoded here.
// This tool encodes _all_ values that are non-zero in the ISO 6093 NR3 representation.
// This does not seem to perfectly adhere to the ITU specifications, Special Cases section.
// The implementation of this crate correctly supports decoding such values. It will, however,
// systematically encode REALs in their base 2 form, with a scaling factor where needed to
// ensure that the mantissa is either odd or zero (as per section 11.3.1).
// Positive trivial numbers
{
let expect = 10.0;
let testcase = &[0x09, 0x05, 0x03, 0x31, 0x2E, 0x45, 0x31];
let decoded = f64::from_der(testcase).unwrap();
assert!(
(decoded - expect).abs() < f64::EPSILON,
"wanted: {}\tgot: {}",
expect,
decoded
);
}
{
let expect = 100.0;
let testcase = &[0x09, 0x05, 0x03, 0x31, 0x2E, 0x45, 0x32];
let decoded = f64::from_der(testcase).unwrap();
assert!(
(decoded - expect).abs() < f64::EPSILON,
"wanted: {}\tgot: {}",
expect,
decoded
);
}
{
let expect = 101.0;
let testcase = &[0x09, 0x08, 0x03, 0x31, 0x30, 0x31, 0x2E, 0x45, 0x2B, 0x30];
let decoded = f64::from_der(testcase).unwrap();
assert!(
(decoded - expect).abs() < f64::EPSILON,
"wanted: {}\tgot: {}",
expect,
decoded
);
}
{
let expect = 101.0;
let testcase = &[0x09, 0x08, 0x03, 0x31, 0x30, 0x31, 0x2E, 0x45, 0x2B, 0x30];
let decoded = f64::from_der(testcase).unwrap();
assert!(
(decoded - expect).abs() < f64::EPSILON,
"wanted: {}\tgot: {}",
expect,
decoded
);
}
{
let expect = 0.0;
let testcase = &[0x09, 0x00];
let decoded = f64::from_der(testcase).unwrap();
assert!(
(decoded - expect).abs() < f64::EPSILON,
"wanted: {}\tgot: {}",
expect,
decoded
);
}
{
let expect = 951.2357864;
let testcase = &[
0x09, 0x0F, 0x03, 0x39, 0x35, 0x31, 0x32, 0x33, 0x35, 0x37, 0x38, 0x36, 0x34, 0x2E,
0x45, 0x2D, 0x37,
];
let decoded = f64::from_der(testcase).unwrap();
assert!(
(decoded - expect).abs() < f64::EPSILON,
"wanted: {}\tgot: {}",
expect,
decoded
);
}
// Negative trivial numbers
{
let expect = -10.0;
let testcase = &[0x09, 0x06, 0x03, 0x2D, 0x31, 0x2E, 0x45, 0x31];
let decoded = f64::from_der(testcase).unwrap();
assert!(
(decoded - expect).abs() < f64::EPSILON,
"wanted: {}\tgot: {}",
expect,
decoded
);
}
{
let expect = -100.0;
let testcase = &[0x09, 0x06, 0x03, 0x2D, 0x31, 0x2E, 0x45, 0x32];
let decoded = f64::from_der(testcase).unwrap();
assert!(
(decoded - expect).abs() < f64::EPSILON,
"wanted: {}\tgot: {}",
expect,
decoded
);
}
{
let expect = -101.0;
let testcase = &[
0x09, 0x09, 0x03, 0x2D, 0x31, 0x30, 0x31, 0x2E, 0x45, 0x2B, 0x30,
];
let decoded = f64::from_der(testcase).unwrap();
assert!(
(decoded - expect).abs() < f64::EPSILON,
"wanted: {}\tgot: {}",
expect,
decoded
);
}
{
let expect = -0.5;
let testcase = &[0x09, 0x07, 0x03, 0x2D, 0x35, 0x2E, 0x45, 0x2D, 0x31];
let decoded = f64::from_der(testcase).unwrap();
assert!(
(decoded - expect).abs() < f64::EPSILON,
"wanted: {}\tgot: {}",
expect,
decoded
);
}
{
let expect = -0.0;
let testcase = &[0x09, 0x03, 0x01, 0x2D, 0x30];
let decoded = f64::from_der(testcase).unwrap();
assert!(
(decoded - expect).abs() < f64::EPSILON,
"wanted: {}\tgot: {}",
expect,
decoded
);
}
{
// Test NR3 decoding
let expect = -951.2357864;
let testcase = &[
0x09, 0x10, 0x03, 0x2D, 0x39, 0x35, 0x31, 0x32, 0x33, 0x35, 0x37, 0x38, 0x36, 0x34,
0x2E, 0x45, 0x2D, 0x37,
];
let decoded = f64::from_der(testcase).unwrap();
assert!(
(decoded - expect).abs() < f64::EPSILON,
"wanted: {}\tgot: {}",
expect,
decoded
);
}
}
}

53
vendor/der/src/asn1/sequence.rs vendored Normal file
View File

@@ -0,0 +1,53 @@
//! The [`Sequence`] trait simplifies writing decoders/encoders which map ASN.1
//! `SEQUENCE`s to Rust structs.
use crate::{
BytesRef, DecodeValue, EncodeValue, FixedTag, Header, Length, Reader, Result, Tag, Writer,
};
#[cfg(feature = "alloc")]
use alloc::boxed::Box;
/// Marker trait for ASN.1 `SEQUENCE`s.
///
/// This is mainly used for custom derive.
pub trait Sequence<'a>: DecodeValue<'a> + EncodeValue {}
impl<'a, S> FixedTag for S
where
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: 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: BytesRef::decode_value(reader, header)?,
})
}
}
impl EncodeValue for SequenceRef<'_> {
fn value_len(&self) -> Result<Length> {
Ok(self.body.len())
}
fn encode_value(&self, writer: &mut impl Writer) -> Result<()> {
self.body.encode_value(writer)
}
}
impl<'a> Sequence<'a> for SequenceRef<'a> {}

230
vendor/der/src/asn1/sequence_of.rs vendored Normal file
View File

@@ -0,0 +1,230 @@
//! ASN.1 `SEQUENCE OF` support.
use crate::{
arrayvec, ord::iter_cmp, ArrayVec, Decode, DecodeValue, DerOrd, Encode, EncodeValue, FixedTag,
Header, Length, Reader, Result, Tag, ValueOrd, Writer,
};
use core::cmp::Ordering;
#[cfg(feature = "alloc")]
use alloc::vec::Vec;
/// ASN.1 `SEQUENCE OF` backed by an array.
///
/// This type implements an append-only `SEQUENCE OF` type which is stack-based
/// and does not depend on `alloc` support.
// TODO(tarcieri): use `ArrayVec` when/if it's merged into `core`
// See: https://github.com/rust-lang/rfcs/pull/2990
#[derive(Clone, Debug, Eq, PartialEq)]
pub struct SequenceOf<T, const N: usize> {
inner: ArrayVec<T, N>,
}
impl<T, const N: usize> SequenceOf<T, N> {
/// Create a new [`SequenceOf`].
pub fn new() -> Self {
Self {
inner: ArrayVec::new(),
}
}
/// Add an element to this [`SequenceOf`].
pub fn add(&mut self, element: T) -> Result<()> {
self.inner.push(element)
}
/// Get an element of this [`SequenceOf`].
pub fn get(&self, index: usize) -> Option<&T> {
self.inner.get(index)
}
/// Iterate over the elements in this [`SequenceOf`].
pub fn iter(&self) -> SequenceOfIter<'_, T> {
SequenceOfIter {
inner: self.inner.iter(),
}
}
/// Is this [`SequenceOf`] empty?
pub fn is_empty(&self) -> bool {
self.inner.is_empty()
}
/// Number of elements in this [`SequenceOf`].
pub fn len(&self) -> usize {
self.inner.len()
}
}
impl<T, const N: usize> Default for SequenceOf<T, N> {
fn default() -> Self {
Self::new()
}
}
impl<'a, T, const N: usize> DecodeValue<'a> for SequenceOf<T, N>
where
T: Decode<'a>,
{
fn decode_value<R: Reader<'a>>(reader: &mut R, header: Header) -> Result<Self> {
reader.read_nested(header.length, |reader| {
let mut sequence_of = Self::new();
while !reader.is_finished() {
sequence_of.add(T::decode(reader)?)?;
}
Ok(sequence_of)
})
}
}
impl<T, const N: usize> EncodeValue for SequenceOf<T, N>
where
T: Encode,
{
fn value_len(&self) -> Result<Length> {
self.iter()
.fold(Ok(Length::ZERO), |len, elem| len + elem.encoded_len()?)
}
fn encode_value(&self, writer: &mut impl Writer) -> Result<()> {
for elem in self.iter() {
elem.encode(writer)?;
}
Ok(())
}
}
impl<T, const N: usize> FixedTag for SequenceOf<T, N> {
const TAG: Tag = Tag::Sequence;
}
impl<T, const N: usize> ValueOrd for SequenceOf<T, N>
where
T: DerOrd,
{
fn value_cmp(&self, other: &Self) -> Result<Ordering> {
iter_cmp(self.iter(), other.iter())
}
}
/// Iterator over the elements of an [`SequenceOf`].
#[derive(Clone, Debug)]
pub struct SequenceOfIter<'a, T> {
/// Inner iterator.
inner: arrayvec::Iter<'a, T>,
}
impl<'a, T> Iterator for SequenceOfIter<'a, T> {
type Item = &'a T;
fn next(&mut self) -> Option<&'a T> {
self.inner.next()
}
}
impl<'a, T> ExactSizeIterator for SequenceOfIter<'a, T> {}
impl<'a, T, const N: usize> DecodeValue<'a> for [T; N]
where
T: Decode<'a>,
{
fn decode_value<R: Reader<'a>>(reader: &mut R, header: Header) -> Result<Self> {
let sequence_of = SequenceOf::<T, N>::decode_value(reader, header)?;
// TODO(tarcieri): use `[T; N]::try_map` instead of `expect` when stable
if sequence_of.inner.len() == N {
Ok(sequence_of
.inner
.into_array()
.map(|elem| elem.expect("arrayvec length mismatch")))
} else {
Err(Self::TAG.length_error())
}
}
}
impl<T, const N: usize> EncodeValue for [T; N]
where
T: Encode,
{
fn value_len(&self) -> Result<Length> {
self.iter()
.fold(Ok(Length::ZERO), |len, elem| len + elem.encoded_len()?)
}
fn encode_value(&self, writer: &mut impl Writer) -> Result<()> {
for elem in self {
elem.encode(writer)?;
}
Ok(())
}
}
impl<T, const N: usize> FixedTag for [T; N] {
const TAG: Tag = Tag::Sequence;
}
impl<T, const N: usize> ValueOrd for [T; N]
where
T: DerOrd,
{
fn value_cmp(&self, other: &Self) -> Result<Ordering> {
iter_cmp(self.iter(), other.iter())
}
}
#[cfg(feature = "alloc")]
impl<'a, T> DecodeValue<'a> for Vec<T>
where
T: Decode<'a>,
{
fn decode_value<R: Reader<'a>>(reader: &mut R, header: Header) -> Result<Self> {
reader.read_nested(header.length, |reader| {
let mut sequence_of = Self::new();
while !reader.is_finished() {
sequence_of.push(T::decode(reader)?);
}
Ok(sequence_of)
})
}
}
#[cfg(feature = "alloc")]
impl<T> EncodeValue for Vec<T>
where
T: Encode,
{
fn value_len(&self) -> Result<Length> {
self.iter()
.fold(Ok(Length::ZERO), |len, elem| len + elem.encoded_len()?)
}
fn encode_value(&self, writer: &mut impl Writer) -> Result<()> {
for elem in self {
elem.encode(writer)?;
}
Ok(())
}
}
#[cfg(feature = "alloc")]
impl<T> FixedTag for Vec<T> {
const TAG: Tag = Tag::Sequence;
}
#[cfg(feature = "alloc")]
impl<T> ValueOrd for Vec<T>
where
T: DerOrd,
{
fn value_cmp(&self, other: &Self) -> Result<Ordering> {
iter_cmp(self.iter(), other.iter())
}
}

539
vendor/der/src/asn1/set_of.rs vendored Normal file
View File

@@ -0,0 +1,539 @@
//! ASN.1 `SET OF` support.
//!
//! # Ordering Notes
//!
//! Some DER serializer implementations fail to properly sort elements of a
//! `SET OF`. This is technically non-canonical, but occurs frequently
//! enough that most DER decoders tolerate it. Unfortunately because
//! of that, we must also follow suit.
//!
//! However, all types in this module sort elements of a set at decode-time,
//! ensuring they'll be in the proper order if reserialized.
use crate::{
arrayvec, ord::iter_cmp, ArrayVec, Decode, DecodeValue, DerOrd, Encode, EncodeValue, Error,
ErrorKind, FixedTag, Header, Length, Reader, Result, Tag, ValueOrd, Writer,
};
use core::cmp::Ordering;
#[cfg(feature = "alloc")]
use {alloc::vec::Vec, core::slice};
/// ASN.1 `SET OF` backed by an array.
///
/// This type implements an append-only `SET OF` type which is stack-based
/// and does not depend on `alloc` support.
// TODO(tarcieri): use `ArrayVec` when/if it's merged into `core`
// See: https://github.com/rust-lang/rfcs/pull/2990
#[derive(Clone, Debug, Eq, PartialEq, PartialOrd, Ord)]
pub struct SetOf<T, const N: usize>
where
T: DerOrd,
{
inner: ArrayVec<T, N>,
}
impl<T, const N: usize> SetOf<T, N>
where
T: DerOrd,
{
/// Create a new [`SetOf`].
pub fn new() -> Self {
Self {
inner: ArrayVec::default(),
}
}
/// Add an item to this [`SetOf`].
///
/// Items MUST be added in lexicographical order according to the
/// [`DerOrd`] impl on `T`.
#[deprecated(since = "0.7.6", note = "use `insert` or `insert_ordered` instead")]
pub fn add(&mut self, new_elem: T) -> Result<()> {
self.insert_ordered(new_elem)
}
/// Insert an item into this [`SetOf`].
pub fn insert(&mut self, item: T) -> Result<()> {
self.inner.push(item)?;
der_sort(self.inner.as_mut())
}
/// Insert an item into this [`SetOf`].
///
/// Items MUST be added in lexicographical order according to the
/// [`DerOrd`] impl on `T`.
pub fn insert_ordered(&mut self, item: T) -> Result<()> {
// Ensure set elements are lexicographically ordered
if let Some(last) = self.inner.last() {
check_der_ordering(last, &item)?;
}
self.inner.push(item)
}
/// Get the nth element from this [`SetOf`].
pub fn get(&self, index: usize) -> Option<&T> {
self.inner.get(index)
}
/// Iterate over the elements of this [`SetOf`].
pub fn iter(&self) -> SetOfIter<'_, T> {
SetOfIter {
inner: self.inner.iter(),
}
}
/// Is this [`SetOf`] empty?
pub fn is_empty(&self) -> bool {
self.inner.is_empty()
}
/// Number of elements in this [`SetOf`].
pub fn len(&self) -> usize {
self.inner.len()
}
}
impl<T, const N: usize> Default for SetOf<T, N>
where
T: DerOrd,
{
fn default() -> Self {
Self::new()
}
}
impl<'a, T, const N: usize> DecodeValue<'a> for SetOf<T, N>
where
T: Decode<'a> + DerOrd,
{
fn decode_value<R: Reader<'a>>(reader: &mut R, header: Header) -> Result<Self> {
reader.read_nested(header.length, |reader| {
let mut result = Self::new();
while !reader.is_finished() {
result.inner.push(T::decode(reader)?)?;
}
der_sort(result.inner.as_mut())?;
validate(result.inner.as_ref())?;
Ok(result)
})
}
}
impl<'a, T, const N: usize> EncodeValue for SetOf<T, N>
where
T: 'a + Decode<'a> + Encode + DerOrd,
{
fn value_len(&self) -> Result<Length> {
self.iter()
.fold(Ok(Length::ZERO), |len, elem| len + elem.encoded_len()?)
}
fn encode_value(&self, writer: &mut impl Writer) -> Result<()> {
for elem in self.iter() {
elem.encode(writer)?;
}
Ok(())
}
}
impl<'a, T, const N: usize> FixedTag for SetOf<T, N>
where
T: Decode<'a> + DerOrd,
{
const TAG: Tag = Tag::Set;
}
impl<T, const N: usize> TryFrom<[T; N]> for SetOf<T, N>
where
T: DerOrd,
{
type Error = Error;
fn try_from(mut arr: [T; N]) -> Result<SetOf<T, N>> {
der_sort(&mut arr)?;
let mut result = SetOf::new();
for elem in arr {
result.insert_ordered(elem)?;
}
Ok(result)
}
}
impl<T, const N: usize> ValueOrd for SetOf<T, N>
where
T: DerOrd,
{
fn value_cmp(&self, other: &Self) -> Result<Ordering> {
iter_cmp(self.iter(), other.iter())
}
}
/// Iterator over the elements of an [`SetOf`].
#[derive(Clone, Debug)]
pub struct SetOfIter<'a, T> {
/// Inner iterator.
inner: arrayvec::Iter<'a, T>,
}
impl<'a, T> Iterator for SetOfIter<'a, T> {
type Item = &'a T;
fn next(&mut self) -> Option<&'a T> {
self.inner.next()
}
}
impl<'a, T> ExactSizeIterator for SetOfIter<'a, T> {}
/// ASN.1 `SET OF` backed by a [`Vec`].
///
/// This type implements an append-only `SET OF` type which is heap-backed
/// and depends on `alloc` support.
#[cfg(feature = "alloc")]
#[derive(Clone, Debug, Eq, PartialEq, PartialOrd, Ord)]
pub struct SetOfVec<T>
where
T: DerOrd,
{
inner: Vec<T>,
}
#[cfg(feature = "alloc")]
impl<T: DerOrd> Default for SetOfVec<T> {
fn default() -> Self {
Self {
inner: Default::default(),
}
}
}
#[cfg(feature = "alloc")]
impl<T> SetOfVec<T>
where
T: DerOrd,
{
/// Create a new [`SetOfVec`].
pub fn new() -> Self {
Self {
inner: Vec::default(),
}
}
/// Create a new [`SetOfVec`] from the given iterator.
///
/// Note: this is an inherent method instead of an impl of the
/// [`FromIterator`] trait in order to be fallible.
#[allow(clippy::should_implement_trait)]
pub fn from_iter<I>(iter: I) -> Result<Self>
where
I: IntoIterator<Item = T>,
{
Vec::from_iter(iter).try_into()
}
/// Add an element to this [`SetOfVec`].
///
/// Items MUST be added in lexicographical order according to the
/// [`DerOrd`] impl on `T`.
#[deprecated(since = "0.7.6", note = "use `insert` or `insert_ordered` instead")]
pub fn add(&mut self, item: T) -> Result<()> {
self.insert_ordered(item)
}
/// Extend a [`SetOfVec`] using an iterator.
///
/// Note: this is an inherent method instead of an impl of the
/// [`Extend`] trait in order to be fallible.
pub fn extend<I>(&mut self, iter: I) -> Result<()>
where
I: IntoIterator<Item = T>,
{
self.inner.extend(iter);
der_sort(&mut self.inner)
}
/// Insert an item into this [`SetOfVec`]. Must be unique.
pub fn insert(&mut self, item: T) -> Result<()> {
self.inner.push(item);
der_sort(&mut self.inner)
}
/// Insert an item into this [`SetOfVec`]. Must be unique.
///
/// Items MUST be added in lexicographical order according to the
/// [`DerOrd`] impl on `T`.
pub fn insert_ordered(&mut self, item: T) -> Result<()> {
// Ensure set elements are lexicographically ordered
if let Some(last) = self.inner.last() {
check_der_ordering(last, &item)?;
}
self.inner.push(item);
Ok(())
}
/// Borrow the elements of this [`SetOfVec`] as a slice.
pub fn as_slice(&self) -> &[T] {
self.inner.as_slice()
}
/// Get the nth element from this [`SetOfVec`].
pub fn get(&self, index: usize) -> Option<&T> {
self.inner.get(index)
}
/// Convert this [`SetOfVec`] into the inner [`Vec`].
pub fn into_vec(self) -> Vec<T> {
self.inner
}
/// Iterate over the elements of this [`SetOfVec`].
pub fn iter(&self) -> slice::Iter<'_, T> {
self.inner.iter()
}
/// Is this [`SetOfVec`] empty?
pub fn is_empty(&self) -> bool {
self.inner.is_empty()
}
/// Number of elements in this [`SetOfVec`].
pub fn len(&self) -> usize {
self.inner.len()
}
}
#[cfg(feature = "alloc")]
impl<T> AsRef<[T]> for SetOfVec<T>
where
T: DerOrd,
{
fn as_ref(&self) -> &[T] {
self.as_slice()
}
}
#[cfg(feature = "alloc")]
impl<'a, T> DecodeValue<'a> for SetOfVec<T>
where
T: Decode<'a> + DerOrd,
{
fn decode_value<R: Reader<'a>>(reader: &mut R, header: Header) -> Result<Self> {
reader.read_nested(header.length, |reader| {
let mut inner = Vec::new();
while !reader.is_finished() {
inner.push(T::decode(reader)?);
}
der_sort(inner.as_mut())?;
validate(inner.as_ref())?;
Ok(Self { inner })
})
}
}
#[cfg(feature = "alloc")]
impl<'a, T> EncodeValue for SetOfVec<T>
where
T: 'a + Decode<'a> + Encode + DerOrd,
{
fn value_len(&self) -> Result<Length> {
self.iter()
.fold(Ok(Length::ZERO), |len, elem| len + elem.encoded_len()?)
}
fn encode_value(&self, writer: &mut impl Writer) -> Result<()> {
for elem in self.iter() {
elem.encode(writer)?;
}
Ok(())
}
}
#[cfg(feature = "alloc")]
impl<T> FixedTag for SetOfVec<T>
where
T: DerOrd,
{
const TAG: Tag = Tag::Set;
}
#[cfg(feature = "alloc")]
impl<T> From<SetOfVec<T>> for Vec<T>
where
T: DerOrd,
{
fn from(set: SetOfVec<T>) -> Vec<T> {
set.into_vec()
}
}
#[cfg(feature = "alloc")]
impl<T> TryFrom<Vec<T>> for SetOfVec<T>
where
T: DerOrd,
{
type Error = Error;
fn try_from(mut vec: Vec<T>) -> Result<SetOfVec<T>> {
der_sort(vec.as_mut_slice())?;
Ok(SetOfVec { inner: vec })
}
}
#[cfg(feature = "alloc")]
impl<T, const N: usize> TryFrom<[T; N]> for SetOfVec<T>
where
T: DerOrd,
{
type Error = Error;
fn try_from(arr: [T; N]) -> Result<SetOfVec<T>> {
Vec::from(arr).try_into()
}
}
#[cfg(feature = "alloc")]
impl<T> ValueOrd for SetOfVec<T>
where
T: DerOrd,
{
fn value_cmp(&self, other: &Self) -> Result<Ordering> {
iter_cmp(self.iter(), other.iter())
}
}
// 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)
}
}
/// Ensure set elements are lexicographically ordered using [`DerOrd`].
fn check_der_ordering<T: DerOrd>(a: &T, b: &T) -> Result<()> {
match a.der_cmp(b)? {
Ordering::Less => Ok(()),
Ordering::Equal => Err(ErrorKind::SetDuplicate.into()),
Ordering::Greater => Err(ErrorKind::SetOrdering.into()),
}
}
/// Sort a mut slice according to its [`DerOrd`], returning any errors which
/// might occur during the comparison.
///
/// The algorithm is insertion sort, which should perform well when the input
/// is mostly sorted to begin with.
///
/// This function is used rather than Rust's built-in `[T]::sort_by` in order
/// to support heapless `no_std` targets as well as to enable bubbling up
/// sorting errors.
#[allow(clippy::integer_arithmetic)]
fn der_sort<T: DerOrd>(slice: &mut [T]) -> Result<()> {
for i in 0..slice.len() {
let mut j = i;
while j > 0 {
match slice[j - 1].der_cmp(&slice[j])? {
Ordering::Less => break,
Ordering::Equal => return Err(ErrorKind::SetDuplicate.into()),
Ordering::Greater => {
slice.swap(j - 1, j);
j -= 1;
}
}
}
}
Ok(())
}
/// Validate the elements of a `SET OF`, ensuring that they are all in order
/// and that there are no duplicates.
fn validate<T: DerOrd>(slice: &[T]) -> Result<()> {
if let Some(len) = slice.len().checked_sub(1) {
for i in 0..len {
let j = i.checked_add(1).ok_or(ErrorKind::Overflow)?;
match slice.get(i..=j) {
Some([a, b]) => {
if a.der_cmp(b)? != Ordering::Less {
return Err(ErrorKind::SetOrdering.into());
}
}
_ => return Err(Tag::Set.value_error()),
}
}
}
Ok(())
}
#[cfg(test)]
mod tests {
use super::SetOf;
#[cfg(feature = "alloc")]
use super::SetOfVec;
use crate::ErrorKind;
#[test]
fn setof_tryfrom_array() {
let arr = [3u16, 2, 1, 65535, 0];
let set = SetOf::try_from(arr).unwrap();
assert!(set.iter().copied().eq([0, 1, 2, 3, 65535]));
}
#[test]
fn setof_tryfrom_array_reject_duplicates() {
let arr = [1u16, 1];
let err = SetOf::try_from(arr).err().unwrap();
assert_eq!(err.kind(), ErrorKind::SetDuplicate);
}
#[cfg(feature = "alloc")]
#[test]
fn setofvec_tryfrom_array() {
let arr = [3u16, 2, 1, 65535, 0];
let set = SetOfVec::try_from(arr).unwrap();
assert_eq!(set.as_ref(), &[0, 1, 2, 3, 65535]);
}
#[cfg(feature = "alloc")]
#[test]
fn setofvec_tryfrom_vec() {
let vec = vec![3u16, 2, 1, 65535, 0];
let set = SetOfVec::try_from(vec).unwrap();
assert_eq!(set.as_ref(), &[0, 1, 2, 3, 65535]);
}
#[cfg(feature = "alloc")]
#[test]
fn setofvec_tryfrom_vec_reject_duplicates() {
let vec = vec![1u16, 1];
let err = SetOfVec::try_from(vec).err().unwrap();
assert_eq!(err.kind(), ErrorKind::SetDuplicate);
}
}

217
vendor/der/src/asn1/teletex_string.rs vendored Normal file
View File

@@ -0,0 +1,217 @@
//! 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;
}
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.
///
/// 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`].
///
/// This is a zero-copy reference type which borrows from the input data.
///
/// # 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(Copy, Clone, Eq, PartialEq, PartialOrd, Ord)]
pub struct TeletexStringRef<'a> {
/// Inner value
inner: StrRef<'a>,
}
impl<'a> TeletexStringRef<'a> {
/// Create a new ASN.1 `TeletexString`.
pub fn new<T>(input: &'a T) -> Result<Self>
where
T: AsRef<[u8]> + ?Sized,
{
let input = input.as_ref();
// FIXME: support higher part of the charset
if input.iter().any(|&c| c > 0x7F) {
return Err(Self::TAG.value_error());
}
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 = StrRef<'a>;
fn deref(&self) -> &Self::Target {
&self.inner
}
}
impl<'a> From<&TeletexStringRef<'a>> for TeletexStringRef<'a> {
fn from(value: &TeletexStringRef<'a>) -> TeletexStringRef<'a> {
*value
}
}
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())
}
}
#[cfg(feature = "alloc")]
pub use self::allocation::TeletexString;
#[cfg(feature = "alloc")]
mod allocation {
use super::TeletexStringRef;
use crate::{
asn1::AnyRef,
referenced::{OwnedToRef, RefToOwned},
BytesRef, Error, FixedTag, Result, StrOwned, Tag,
};
use alloc::string::String;
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 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();
TeletexStringRef::new(input)?;
StrOwned::from_bytes(input)
.map(|inner| Self { inner })
.map_err(|_| Self::TAG.value_error())
}
}
impl_teletex_string!(TeletexString);
impl Deref for TeletexString {
type Target = StrOwned;
fn deref(&self) -> &Self::Target {
&self.inner
}
}
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> 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> 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(),
}
}
}
impl TryFrom<String> for TeletexString {
type Error = Error;
fn try_from(input: String) -> Result<Self> {
TeletexStringRef::new(&input)?;
StrOwned::new(input)
.map(|inner| Self { inner })
.map_err(|_| Self::TAG.value_error())
}
}
}
#[cfg(test)]
mod tests {
use super::TeletexStringRef;
use crate::Decode;
use crate::SliceWriter;
#[test]
fn parse_bytes() {
let example_bytes = &[
0x14, 0x0b, 0x54, 0x65, 0x73, 0x74, 0x20, 0x55, 0x73, 0x65, 0x72, 0x20, 0x31,
];
let teletex_string = TeletexStringRef::from_der(example_bytes).unwrap();
assert_eq!(teletex_string.as_str(), "Test User 1");
let mut out = [0_u8; 30];
let mut writer = SliceWriter::new(&mut out);
writer.encode(&teletex_string).unwrap();
let encoded = writer.finish().unwrap();
assert_eq!(encoded, example_bytes);
}
}

242
vendor/der/src/asn1/utc_time.rs vendored Normal file
View File

@@ -0,0 +1,242 @@
//! ASN.1 `UTCTime` support.
use crate::{
datetime::{self, DateTime},
ord::OrdIsValueOrd,
DecodeValue, EncodeValue, Error, ErrorKind, FixedTag, Header, Length, Reader, Result, Tag,
Writer,
};
use core::time::Duration;
#[cfg(feature = "std")]
use std::time::SystemTime;
/// ASN.1 `UTCTime` type.
///
/// This type implements the validity requirements specified in
/// [RFC 5280 Section 4.1.2.5.1][1], namely:
///
/// > For the purposes of this profile, UTCTime values MUST be expressed in
/// > Greenwich Mean Time (Zulu) and MUST include seconds (i.e., times are
/// > `YYMMDDHHMMSSZ`), even where the number of seconds is zero. Conforming
/// > systems MUST interpret the year field (`YY`) as follows:
/// >
/// > - Where `YY` is greater than or equal to 50, the year SHALL be
/// > interpreted as `19YY`; and
/// > - Where `YY` is less than 50, the year SHALL be interpreted as `20YY`.
///
/// Note: Due to common operations working on `UNIX_EPOCH` [`UtcTime`]s are
/// only supported for the years 1970-2049.
///
/// [1]: https://tools.ietf.org/html/rfc5280#section-4.1.2.5.1
#[derive(Copy, Clone, Debug, Eq, PartialEq, PartialOrd, Ord)]
pub struct UtcTime(DateTime);
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() <= UtcTime::MAX_YEAR {
Ok(Self(datetime))
} else {
Err(Self::TAG.value_error())
}
}
/// Convert this [`UtcTime`] into a [`DateTime`].
pub fn to_date_time(&self) -> DateTime {
self.0
}
/// Create a new [`UtcTime`] given a [`Duration`] since `UNIX_EPOCH`
/// (a.k.a. "Unix time")
pub fn from_unix_duration(unix_duration: Duration) -> Result<Self> {
DateTime::from_unix_duration(unix_duration)?.try_into()
}
/// Get the duration of this timestamp since `UNIX_EPOCH`.
pub fn to_unix_duration(&self) -> Duration {
self.0.unix_duration()
}
/// Instantiate from [`SystemTime`].
#[cfg(feature = "std")]
pub fn from_system_time(time: SystemTime) -> Result<Self> {
DateTime::try_from(time)
.map_err(|_| Self::TAG.value_error())?
.try_into()
}
/// Convert to [`SystemTime`].
#[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)? {
return Err(Self::TAG.value_error());
}
let mut bytes = [0u8; Self::LENGTH];
reader.read_into(&mut bytes)?;
match bytes {
// RFC 5280 requires mandatory seconds and Z-normalized time zone
[year1, year2, mon1, mon2, day1, day2, hour1, hour2, min1, min2, sec1, sec2, b'Z'] => {
let year = u16::from(datetime::decode_decimal(Self::TAG, year1, year2)?);
let month = datetime::decode_decimal(Self::TAG, mon1, mon2)?;
let day = datetime::decode_decimal(Self::TAG, day1, day2)?;
let hour = datetime::decode_decimal(Self::TAG, hour1, hour2)?;
let minute = datetime::decode_decimal(Self::TAG, min1, min2)?;
let second = datetime::decode_decimal(Self::TAG, sec1, sec2)?;
// RFC 5280 rules for interpreting the year
let year = if year >= 50 {
year.checked_add(1900)
} else {
year.checked_add(2000)
}
.ok_or(ErrorKind::DateTime)?;
DateTime::new(year, month, day, hour, minute, second)
.map_err(|_| Self::TAG.value_error())
.and_then(|dt| Self::from_unix_duration(dt.unix_duration()))
}
_ => Err(Self::TAG.value_error()),
}
}
}
impl EncodeValue for UtcTime {
fn value_len(&self) -> Result<Length> {
Self::LENGTH.try_into()
}
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),
_ => return Err(Self::TAG.value_error()),
}
.and_then(|y| u8::try_from(y).ok())
.ok_or(ErrorKind::DateTime)?;
datetime::encode_decimal(writer, Self::TAG, year)?;
datetime::encode_decimal(writer, Self::TAG, self.0.month())?;
datetime::encode_decimal(writer, Self::TAG, self.0.day())?;
datetime::encode_decimal(writer, Self::TAG, self.0.hour())?;
datetime::encode_decimal(writer, Self::TAG, self.0.minutes())?;
datetime::encode_decimal(writer, Self::TAG, self.0.seconds())?;
writer.write_byte(b'Z')
}
}
impl FixedTag for UtcTime {
const TAG: Tag = Tag::UtcTime;
}
impl OrdIsValueOrd for UtcTime {}
impl From<&UtcTime> for UtcTime {
fn from(value: &UtcTime) -> UtcTime {
*value
}
}
impl From<UtcTime> for DateTime {
fn from(utc_time: UtcTime) -> DateTime {
utc_time.0
}
}
impl From<&UtcTime> for DateTime {
fn from(utc_time: &UtcTime) -> DateTime {
utc_time.0
}
}
impl TryFrom<DateTime> for UtcTime {
type Error = Error;
fn try_from(datetime: DateTime) -> Result<Self> {
Self::from_date_time(datetime)
}
}
impl TryFrom<&DateTime> for UtcTime {
type Error = Error;
fn try_from(datetime: &DateTime) -> Result<Self> {
Self::from_date_time(*datetime)
}
}
#[cfg(feature = "std")]
impl From<UtcTime> for SystemTime {
fn from(utc_time: UtcTime) -> SystemTime {
utc_time.to_system_time()
}
}
// 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)
}
}
#[cfg(test)]
mod tests {
use super::UtcTime;
use crate::{Decode, Encode, SliceWriter};
use hex_literal::hex;
#[test]
fn round_trip_vector() {
let example_bytes = hex!("17 0d 39 31 30 35 30 36 32 33 34 35 34 30 5a");
let utc_time = UtcTime::from_der(&example_bytes).unwrap();
assert_eq!(utc_time.to_unix_duration().as_secs(), 673573540);
let mut buf = [0u8; 128];
let mut encoder = SliceWriter::new(&mut buf);
utc_time.encode(&mut encoder).unwrap();
assert_eq!(example_bytes, encoder.finish().unwrap());
}
}

164
vendor/der/src/asn1/utf8_string.rs vendored Normal file
View File

@@ -0,0 +1,164 @@
//! ASN.1 `UTF8String` support.
use crate::{
asn1::AnyRef, ord::OrdIsValueOrd, EncodeValue, Error, FixedTag, Length, Result, StrRef, Tag,
Writer,
};
use core::{fmt, ops::Deref, str};
#[cfg(feature = "alloc")]
use {
crate::{DecodeValue, Header, Reader},
alloc::{borrow::ToOwned, string::String},
};
/// ASN.1 `UTF8String` type.
///
/// Supports the full UTF-8 encoding.
///
/// Note that the [`Decode`][`crate::Decode`] and [`Encode`][`crate::Encode`]
/// traits are impl'd for Rust's [`str`][`prim@str`] primitive, which
/// decodes/encodes as a [`Utf8StringRef`].
///
/// You are free to use [`str`][`prim@str`] instead of this type, however it's
/// still provided for explicitness in cases where it might be ambiguous with
/// other ASN.1 string encodings such as
/// [`PrintableStringRef`][`crate::asn1::PrintableStringRef`].
///
/// This is a zero-copy reference type which borrows from the input data.
#[derive(Copy, Clone, Eq, PartialEq, PartialOrd, Ord)]
pub struct Utf8StringRef<'a> {
/// Inner value
inner: StrRef<'a>,
}
impl<'a> Utf8StringRef<'a> {
/// Create a new ASN.1 `UTF8String`.
pub fn new<T>(input: &'a T) -> Result<Self>
where
T: AsRef<[u8]> + ?Sized,
{
StrRef::from_bytes(input.as_ref()).map(|inner| Self { inner })
}
}
impl_string_type!(Utf8StringRef<'a>, 'a);
impl<'a> Deref for Utf8StringRef<'a> {
type Target = StrRef<'a>;
fn deref(&self) -> &Self::Target {
&self.inner
}
}
impl FixedTag for Utf8StringRef<'_> {
const TAG: Tag = Tag::Utf8String;
}
impl<'a> From<&Utf8StringRef<'a>> for Utf8StringRef<'a> {
fn from(value: &Utf8StringRef<'a>) -> Utf8StringRef<'a> {
*value
}
}
impl<'a> From<Utf8StringRef<'a>> for AnyRef<'a> {
fn from(utf_string: Utf8StringRef<'a>) -> AnyRef<'a> {
AnyRef::from_tag_and_value(Tag::Utf8String, utf_string.inner.into())
}
}
impl<'a> fmt::Debug for Utf8StringRef<'a> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "Utf8String({:?})", self.as_str())
}
}
impl<'a> TryFrom<AnyRef<'a>> for &'a str {
type Error = Error;
fn try_from(any: AnyRef<'a>) -> Result<&'a str> {
Utf8StringRef::try_from(any).map(|s| s.as_str())
}
}
impl EncodeValue for str {
fn value_len(&self) -> Result<Length> {
Utf8StringRef::new(self)?.value_len()
}
fn encode_value(&self, writer: &mut impl Writer) -> Result<()> {
Utf8StringRef::new(self)?.encode_value(writer)
}
}
impl FixedTag for str {
const TAG: Tag = Tag::Utf8String;
}
impl OrdIsValueOrd for str {}
#[cfg(feature = "alloc")]
impl<'a> From<Utf8StringRef<'a>> for String {
fn from(s: Utf8StringRef<'a>) -> String {
s.as_str().to_owned()
}
}
#[cfg(feature = "alloc")]
impl<'a> TryFrom<AnyRef<'a>> for String {
type Error = Error;
fn try_from(any: AnyRef<'a>) -> Result<String> {
Utf8StringRef::try_from(any).map(|s| s.as_str().to_owned())
}
}
#[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)?)?)
}
}
#[cfg(feature = "alloc")]
impl EncodeValue for String {
fn value_len(&self) -> Result<Length> {
Utf8StringRef::new(self)?.value_len()
}
fn encode_value(&self, writer: &mut impl Writer) -> Result<()> {
Utf8StringRef::new(self)?.encode_value(writer)
}
}
#[cfg(feature = "alloc")]
impl FixedTag for String {
const TAG: Tag = Tag::Utf8String;
}
#[cfg(feature = "alloc")]
impl OrdIsValueOrd for String {}
#[cfg(test)]
mod tests {
use super::Utf8StringRef;
use crate::Decode;
#[test]
fn parse_ascii_bytes() {
let example_bytes = &[
0x0c, 0x0b, 0x54, 0x65, 0x73, 0x74, 0x20, 0x55, 0x73, 0x65, 0x72, 0x20, 0x31,
];
let utf8_string = Utf8StringRef::from_der(example_bytes).unwrap();
assert_eq!(utf8_string.as_str(), "Test User 1");
}
#[test]
fn parse_utf8_bytes() {
let example_bytes = &[0x0c, 0x06, 0x48, 0x65, 0x6c, 0x6c, 0xc3, 0xb3];
let utf8_string = Utf8StringRef::from_der(example_bytes).unwrap();
assert_eq!(utf8_string.as_str(), "Helló");
}
}

98
vendor/der/src/asn1/videotex_string.rs vendored Normal file
View File

@@ -0,0 +1,98 @@
//! ASN.1 `VideotexString` support.
use crate::{asn1::AnyRef, FixedTag, Result, StrRef, Tag};
use core::{fmt, ops::Deref};
/// ASN.1 `VideotexString` 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`].
///
/// This is a zero-copy reference type which borrows from the input data.
///
/// # Supported characters
///
/// For the practical purposes VideotexString is treated as IA5string, disallowing non-ASCII chars.
///
#[derive(Copy, Clone, Eq, PartialEq, PartialOrd, Ord)]
pub struct VideotexStringRef<'a> {
/// Inner value
inner: StrRef<'a>,
}
impl<'a> VideotexStringRef<'a> {
/// Create a new ASN.1 `VideotexString`.
pub fn new<T>(input: &'a T) -> Result<Self>
where
T: AsRef<[u8]> + ?Sized,
{
let input = input.as_ref();
// Validate all characters are within VideotexString's allowed set
// FIXME: treat as if it were IA5String
if input.iter().any(|&c| c > 0x7F) {
return Err(Self::TAG.value_error());
}
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 = StrRef<'a>;
fn deref(&self) -> &Self::Target {
&self.inner
}
}
impl FixedTag for VideotexStringRef<'_> {
const TAG: Tag = Tag::VideotexString;
}
impl<'a> From<&VideotexStringRef<'a>> for VideotexStringRef<'a> {
fn from(value: &VideotexStringRef<'a>) -> VideotexStringRef<'a> {
*value
}
}
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())
}
}
impl<'a> From<VideotexStringRef<'a>> for &'a [u8] {
fn from(printable_string: VideotexStringRef<'a>) -> &'a [u8] {
printable_string.as_bytes()
}
}
impl<'a> fmt::Debug for VideotexStringRef<'a> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "VideotexString({:?})", self.as_str())
}
}
#[cfg(test)]
mod tests {
use super::VideotexStringRef;
use crate::Decode;
#[test]
fn parse_bytes() {
let example_bytes = &[
0x15, 0x0b, 0x54, 0x65, 0x73, 0x74, 0x20, 0x55, 0x73, 0x65, 0x72, 0x20, 0x31,
];
let printable_string = VideotexStringRef::from_der(example_bytes).unwrap();
assert_eq!(printable_string.as_str(), "Test User 1");
}
}

162
vendor/der/src/bytes_owned.rs vendored Normal file
View File

@@ -0,0 +1,162 @@
//! 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<BytesOwned> for Box<[u8]> {
fn from(bytes: BytesOwned) -> Box<[u8]> {
bytes.inner
}
}
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))
}
}

152
vendor/der/src/bytes_ref.rs vendored Normal file
View File

@@ -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)
}
}
}

447
vendor/der/src/datetime.rs vendored Normal file
View File

@@ -0,0 +1,447 @@
//! Date and time functionality shared between various ASN.1 types
//! (e.g. `GeneralizedTime`, `UTCTime`)
// Adapted from the `humantime` crate.
// Copyright (c) 2016 The humantime Developers
// Released under the MIT OR Apache 2.0 licenses
use crate::{Error, ErrorKind, Result, Tag, Writer};
use core::{fmt, str::FromStr, time::Duration};
#[cfg(feature = "std")]
use std::time::{SystemTime, UNIX_EPOCH};
#[cfg(feature = "time")]
use time::PrimitiveDateTime;
/// Minimum year allowed in [`DateTime`] values.
const MIN_YEAR: u16 = 1970;
/// Maximum duration since `UNIX_EPOCH` which can be represented as a
/// [`DateTime`] (non-inclusive).
///
/// This corresponds to: 9999-12-31T23:59:59Z
const MAX_UNIX_DURATION: Duration = Duration::from_secs(253_402_300_799);
/// Date-and-time type shared by multiple ASN.1 types
/// (e.g. `GeneralizedTime`, `UTCTime`).
///
/// Following conventions from RFC 5280, this type is always Z-normalized
/// (i.e. represents a UTC time). However, it isn't named "UTC time" in order
/// to prevent confusion with ASN.1 `UTCTime`.
#[derive(Copy, Clone, Debug, Eq, PartialEq, PartialOrd, Ord)]
pub struct DateTime {
/// Full year (e.g. 2000).
///
/// Must be >=1970 to permit positive conversions to Unix time.
year: u16,
/// Month (1-12)
month: u8,
/// Day of the month (1-31)
day: u8,
/// Hour (0-23)
hour: u8,
/// Minutes (0-59)
minutes: u8,
/// Seconds (0-59)
seconds: u8,
/// [`Duration`] since the Unix epoch.
unix_duration: Duration,
}
impl DateTime {
/// This is the maximum date represented by the [`DateTime`]
/// This corresponds to: 9999-12-31T23:59:59Z
pub const INFINITY: DateTime = DateTime {
year: 9999,
month: 12,
day: 31,
hour: 23,
minutes: 59,
seconds: 59,
unix_duration: MAX_UNIX_DURATION,
};
/// Create a new [`DateTime`] from the given UTC time components.
// TODO(tarcieri): checked arithmetic
#[allow(clippy::integer_arithmetic)]
pub fn new(year: u16, month: u8, day: u8, hour: u8, minutes: u8, seconds: u8) -> Result<Self> {
// Basic validation of the components.
if year < MIN_YEAR
|| !(1..=12).contains(&month)
|| !(1..=31).contains(&day)
|| !(0..=23).contains(&hour)
|| !(0..=59).contains(&minutes)
|| !(0..=59).contains(&seconds)
{
return Err(ErrorKind::DateTime.into());
}
let leap_years =
((year - 1) - 1968) / 4 - ((year - 1) - 1900) / 100 + ((year - 1) - 1600) / 400;
let is_leap_year = year % 4 == 0 && (year % 100 != 0 || year % 400 == 0);
let (mut ydays, mdays): (u16, u8) = match month {
1 => (0, 31),
2 if is_leap_year => (31, 29),
2 => (31, 28),
3 => (59, 31),
4 => (90, 30),
5 => (120, 31),
6 => (151, 30),
7 => (181, 31),
8 => (212, 31),
9 => (243, 30),
10 => (273, 31),
11 => (304, 30),
12 => (334, 31),
_ => return Err(ErrorKind::DateTime.into()),
};
if day > mdays || day == 0 {
return Err(ErrorKind::DateTime.into());
}
ydays += u16::from(day) - 1;
if is_leap_year && month > 2 {
ydays += 1;
}
let days = u64::from(year - 1970) * 365 + u64::from(leap_years) + u64::from(ydays);
let time = u64::from(seconds) + (u64::from(minutes) * 60) + (u64::from(hour) * 3600);
let unix_duration = Duration::from_secs(time + days * 86400);
if unix_duration > MAX_UNIX_DURATION {
return Err(ErrorKind::DateTime.into());
}
Ok(Self {
year,
month,
day,
hour,
minutes,
seconds,
unix_duration,
})
}
/// Compute a [`DateTime`] from the given [`Duration`] since the `UNIX_EPOCH`.
///
/// Returns `None` if the value is outside the supported date range.
// TODO(tarcieri): checked arithmetic
#[allow(clippy::integer_arithmetic)]
pub fn from_unix_duration(unix_duration: Duration) -> Result<Self> {
if unix_duration > MAX_UNIX_DURATION {
return Err(ErrorKind::DateTime.into());
}
let secs_since_epoch = unix_duration.as_secs();
/// 2000-03-01 (mod 400 year, immediately after Feb 29)
const LEAPOCH: i64 = 11017;
const DAYS_PER_400Y: i64 = 365 * 400 + 97;
const DAYS_PER_100Y: i64 = 365 * 100 + 24;
const DAYS_PER_4Y: i64 = 365 * 4 + 1;
let days = i64::try_from(secs_since_epoch / 86400)? - LEAPOCH;
let secs_of_day = secs_since_epoch % 86400;
let mut qc_cycles = days / DAYS_PER_400Y;
let mut remdays = days % DAYS_PER_400Y;
if remdays < 0 {
remdays += DAYS_PER_400Y;
qc_cycles -= 1;
}
let mut c_cycles = remdays / DAYS_PER_100Y;
if c_cycles == 4 {
c_cycles -= 1;
}
remdays -= c_cycles * DAYS_PER_100Y;
let mut q_cycles = remdays / DAYS_PER_4Y;
if q_cycles == 25 {
q_cycles -= 1;
}
remdays -= q_cycles * DAYS_PER_4Y;
let mut remyears = remdays / 365;
if remyears == 4 {
remyears -= 1;
}
remdays -= remyears * 365;
let mut year = 2000 + remyears + 4 * q_cycles + 100 * c_cycles + 400 * qc_cycles;
let months = [31, 30, 31, 30, 31, 31, 30, 31, 30, 31, 31, 29];
let mut mon = 0;
for mon_len in months.iter() {
mon += 1;
if remdays < *mon_len {
break;
}
remdays -= *mon_len;
}
let mday = remdays + 1;
let mon = if mon + 2 > 12 {
year += 1;
mon - 10
} else {
mon + 2
};
let second = secs_of_day % 60;
let mins_of_day = secs_of_day / 60;
let minute = mins_of_day % 60;
let hour = mins_of_day / 60;
Self::new(
year.try_into()?,
mon,
mday.try_into()?,
hour.try_into()?,
minute.try_into()?,
second.try_into()?,
)
}
/// Get the year.
pub fn year(&self) -> u16 {
self.year
}
/// Get the month.
pub fn month(&self) -> u8 {
self.month
}
/// Get the day.
pub fn day(&self) -> u8 {
self.day
}
/// Get the hour.
pub fn hour(&self) -> u8 {
self.hour
}
/// Get the minutes.
pub fn minutes(&self) -> u8 {
self.minutes
}
/// Get the seconds.
pub fn seconds(&self) -> u8 {
self.seconds
}
/// Compute [`Duration`] since `UNIX_EPOCH` from the given calendar date.
pub fn unix_duration(&self) -> Duration {
self.unix_duration
}
/// Instantiate from [`SystemTime`].
#[cfg(feature = "std")]
pub fn from_system_time(time: SystemTime) -> Result<Self> {
time.duration_since(UNIX_EPOCH)
.map_err(|_| ErrorKind::DateTime.into())
.and_then(Self::from_unix_duration)
}
/// Convert to [`SystemTime`].
#[cfg(feature = "std")]
pub fn to_system_time(&self) -> SystemTime {
UNIX_EPOCH + self.unix_duration()
}
}
impl FromStr for DateTime {
type Err = Error;
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 = 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)?;
let minutes = decode_decimal(tag, min1, min2).map_err(|_| ErrorKind::DateTime)?;
let seconds = decode_decimal(tag, sec1, sec2).map_err(|_| ErrorKind::DateTime)?;
Self::new(year, month, day, hour, minutes, seconds)
}
_ => Err(ErrorKind::DateTime.into()),
}
}
}
impl fmt::Display for DateTime {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(
f,
"{:02}-{:02}-{:02}T{:02}:{:02}:{:02}Z",
self.year, self.month, self.day, self.hour, self.minutes, self.seconds
)
}
}
#[cfg(feature = "std")]
impl From<DateTime> for SystemTime {
fn from(time: DateTime) -> SystemTime {
time.to_system_time()
}
}
#[cfg(feature = "std")]
impl From<&DateTime> for SystemTime {
fn from(time: &DateTime) -> SystemTime {
time.to_system_time()
}
}
#[cfg(feature = "std")]
impl TryFrom<SystemTime> for DateTime {
type Error = Error;
fn try_from(time: SystemTime) -> Result<DateTime> {
DateTime::from_system_time(time)
}
}
#[cfg(feature = "std")]
impl TryFrom<&SystemTime> for DateTime {
type Error = Error;
fn try_from(time: &SystemTime) -> Result<DateTime> {
DateTime::from_system_time(*time)
}
}
#[cfg(feature = "time")]
impl TryFrom<DateTime> for PrimitiveDateTime {
type Error = Error;
fn try_from(time: DateTime) -> Result<PrimitiveDateTime> {
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())?;
Ok(PrimitiveDateTime::new(date, time))
}
}
#[cfg(feature = "time")]
impl TryFrom<PrimitiveDateTime> for DateTime {
type Error = Error;
fn try_from(time: PrimitiveDateTime) -> Result<DateTime> {
DateTime::new(
time.year().try_into().map_err(|_| ErrorKind::DateTime)?,
time.month().into(),
time.day(),
time.hour(),
time.minute(),
time.second(),
)
}
}
// 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 hi.is_ascii_digit() && lo.is_ascii_digit() {
Ok((hi - b'0') * 10 + (lo - b'0'))
} else {
Err(tag.value_error())
}
}
/// Encode 2-digit decimal value
pub(crate) fn encode_decimal<W>(writer: &mut W, tag: Tag, value: u8) -> Result<()>
where
W: Writer + ?Sized,
{
let hi_val = value / 10;
if hi_val >= 10 {
return Err(tag.value_error());
}
writer.write_byte(b'0'.checked_add(hi_val).ok_or(ErrorKind::Overflow)?)?;
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;
/// Ensure a day is OK
fn is_date_valid(year: u16, month: u8, day: u8, hour: u8, minute: u8, second: u8) -> bool {
DateTime::new(year, month, day, hour, minute, second).is_ok()
}
#[test]
fn feb_leap_year_handling() {
assert!(is_date_valid(2000, 2, 29, 0, 0, 0));
assert!(!is_date_valid(2001, 2, 29, 0, 0, 0));
assert!(!is_date_valid(2100, 2, 29, 0, 0, 0));
}
#[test]
fn from_str() {
let datetime = "2001-01-02T12:13:14Z".parse::<DateTime>().unwrap();
assert_eq!(datetime.year(), 2001);
assert_eq!(datetime.month(), 1);
assert_eq!(datetime.day(), 2);
assert_eq!(datetime.hour(), 12);
assert_eq!(datetime.minutes(), 13);
assert_eq!(datetime.seconds(), 14);
}
#[cfg(feature = "alloc")]
#[test]
fn display() {
use alloc::string::ToString;
let datetime = DateTime::new(2001, 01, 02, 12, 13, 14).unwrap();
assert_eq!(&datetime.to_string(), "2001-01-02T12:13:14Z");
}
}

99
vendor/der/src/decode.rs vendored Normal file
View File

@@ -0,0 +1,99 @@
//! Trait definition for [`Decode`].
use crate::{FixedTag, Header, Reader, Result, SliceReader};
use core::marker::PhantomData;
#[cfg(feature = "pem")]
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
/// are based.
pub trait Decode<'a>: Sized {
/// Attempt to decode this message using the provided decoder.
fn decode<R: Reader<'a>>(decoder: &mut R) -> Result<Self>;
/// Parse `Self` from the provided DER-encoded byte slice.
fn from_der(bytes: &'a [u8]) -> Result<Self> {
let mut reader = SliceReader::new(bytes)?;
let result = Self::decode(&mut reader)?;
reader.finish(result)
}
}
impl<'a, T> Decode<'a> for T
where
T: DecodeValue<'a> + FixedTag,
{
fn decode<R: Reader<'a>>(reader: &mut R) -> Result<T> {
let header = Header::decode(reader)?;
header.tag.assert_eq(T::TAG)?;
T::decode_value(reader, header)
}
}
/// Dummy implementation for [`PhantomData`] which allows deriving
/// implementations on structs with phantom fields.
impl<'a, T> Decode<'a> for PhantomData<T>
where
T: ?Sized,
{
fn decode<R: Reader<'a>>(_reader: &mut R) -> Result<PhantomData<T>> {
Ok(PhantomData)
}
}
/// Marker trait for data structures that can be decoded from DER without
/// borrowing any data from the decoder.
///
/// This is primarily useful for trait bounds on functions which require that
/// no data is borrowed from the decoder, for example a PEM decoder which needs
/// to first decode data from Base64.
///
/// This trait is inspired by the [`DeserializeOwned` trait from `serde`](https://docs.rs/serde/latest/serde/de/trait.DeserializeOwned.html).
pub trait DecodeOwned: for<'a> Decode<'a> {}
impl<T> DecodeOwned for T where T: for<'a> Decode<'a> {}
/// PEM decoding trait.
///
/// This trait is automatically impl'd for any type which impls both
/// [`DecodeOwned`] and [`PemLabel`].
#[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")]
impl<T: DecodeOwned + PemLabel> DecodePem for T {
fn from_pem(pem: impl AsRef<[u8]>) -> Result<Self> {
let mut reader = PemReader::new(pem.as_ref())?;
Self::validate_pem_label(reader.type_label())?;
T::decode(&mut reader)
}
}
/// Decode the value part of a Tag-Length-Value encoded field, sans the [`Tag`]
/// and [`Length`].
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)?))
}
}

354
vendor/der/src/document.rs vendored Normal file
View File

@@ -0,0 +1,354 @@
//! ASN.1 DER-encoded documents stored on the heap.
use crate::{Decode, Encode, Error, FixedTag, Length, Reader, Result, SliceReader, Tag, Writer};
use alloc::vec::Vec;
use core::fmt::{self, Debug};
#[cfg(feature = "pem")]
use {crate::pem, alloc::string::String};
#[cfg(feature = "std")]
use std::{fs, path::Path};
#[cfg(all(feature = "pem", feature = "std"))]
use alloc::borrow::ToOwned;
#[cfg(feature = "zeroize")]
use zeroize::{Zeroize, ZeroizeOnDrop, Zeroizing};
/// ASN.1 DER-encoded document.
///
/// This type wraps an encoded ASN.1 DER message. The document checked to
/// ensure it contains a valid DER-encoded `SEQUENCE`.
///
/// It implements common functionality related to encoding/decoding such
/// documents, such as PEM encapsulation as well as reading/writing documents
/// from/to the filesystem.
///
/// The [`SecretDocument`] provides a wrapper for this type with additional
/// hardening applied.
#[derive(Clone, Eq, PartialEq)]
pub struct Document {
/// ASN.1 DER encoded bytes.
der_bytes: Vec<u8>,
/// Length of this document.
length: Length,
}
impl Document {
/// Get the ASN.1 DER-encoded bytes of this document.
pub fn as_bytes(&self) -> &[u8] {
self.der_bytes.as_slice()
}
/// Convert to a [`SecretDocument`].
#[cfg(feature = "zeroize")]
pub fn into_secret(self) -> SecretDocument {
SecretDocument(self)
}
/// Convert to an ASN.1 DER-encoded byte vector.
pub fn into_vec(self) -> Vec<u8> {
self.der_bytes
}
/// Return an ASN.1 DER-encoded byte vector.
pub fn to_vec(&self) -> Vec<u8> {
self.der_bytes.clone()
}
/// Get the length of the encoded ASN.1 DER in bytes.
pub fn len(&self) -> Length {
self.length
}
/// Try to decode the inner ASN.1 DER message contained in this
/// [`Document`] as the given type.
pub fn decode_msg<'a, T: Decode<'a>>(&'a self) -> Result<T> {
T::from_der(self.as_bytes())
}
/// 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_der()?.try_into()
}
/// Decode ASN.1 DER document from PEM.
///
/// Returns the PEM label and decoded [`Document`] on success.
#[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()?))
}
/// Encode ASN.1 DER document as a PEM string with encapsulation boundaries
/// containing the provided PEM type `label` (e.g. `CERTIFICATE`).
#[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")]
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")]
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"))]
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"))]
pub fn write_pem_file(
&self,
path: impl AsRef<Path>,
label: &'static str,
line_ending: pem::LineEnding,
) -> Result<()> {
let pem = self.to_pem(label, line_ending)?;
Ok(fs::write(path, pem.as_bytes())?)
}
}
impl AsRef<[u8]> for Document {
fn as_ref(&self) -> &[u8] {
self.as_bytes()
}
}
impl Debug for Document {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.write_str("Document(")?;
for byte in self.as_bytes() {
write!(f, "{:02X}", byte)?;
}
f.write_str(")")
}
}
impl<'a> Decode<'a> for Document {
fn decode<R: Reader<'a>>(reader: &mut R) -> Result<Document> {
let header = reader.peek_header()?;
let length = (header.encoded_len()? + header.length)?;
let bytes = reader.read_slice(length)?;
Ok(Self {
der_bytes: bytes.into(),
length,
})
}
}
impl Encode for Document {
fn encoded_len(&self) -> Result<Length> {
Ok(self.len())
}
fn encode(&self, writer: &mut impl Writer) -> Result<()> {
writer.write(self.as_bytes())
}
}
impl FixedTag for Document {
const TAG: Tag = Tag::Sequence;
}
impl TryFrom<&[u8]> for Document {
type Error = Error;
fn try_from(der_bytes: &[u8]) -> Result<Self> {
Self::from_der(der_bytes)
}
}
impl TryFrom<Vec<u8>> for Document {
type Error = Error;
fn try_from(der_bytes: Vec<u8>) -> Result<Self> {
let mut decoder = SliceReader::new(&der_bytes)?;
decode_sequence(&mut decoder)?;
decoder.finish(())?;
let length = der_bytes.len().try_into()?;
Ok(Self { der_bytes, length })
}
}
/// Secret [`Document`] type.
///
/// Useful for formats which represent potentially secret data, such as
/// cryptographic keys.
///
/// This type provides additional hardening such as ensuring that the contents
/// are zeroized-on-drop, and also using more restrictive file permissions when
/// writing files to disk.
#[cfg(feature = "zeroize")]
#[derive(Clone)]
pub struct SecretDocument(Document);
#[cfg(feature = "zeroize")]
impl SecretDocument {
/// Borrow the inner serialized bytes of this document.
pub fn as_bytes(&self) -> &[u8] {
self.0.as_bytes()
}
/// Return an allocated ASN.1 DER serialization as a byte vector.
pub fn to_bytes(&self) -> Zeroizing<Vec<u8>> {
Zeroizing::new(self.0.to_vec())
}
/// Get the length of the encoded ASN.1 DER in bytes.
pub fn len(&self) -> Length {
self.0.len()
}
/// Try to decode the inner ASN.1 DER message as the given type.
pub fn decode_msg<'a, T: Decode<'a>>(&'a self) -> Result<T> {
self.0.decode_msg()
}
/// Encode the provided type as ASN.1 DER.
pub fn encode_msg<T: Encode>(msg: &T) -> Result<Self> {
Document::encode_msg(msg).map(Self)
}
/// Decode ASN.1 DER document from PEM.
#[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")]
pub fn to_pem(
&self,
label: &'static str,
line_ending: pem::LineEnding,
) -> Result<Zeroizing<String>> {
self.0.to_pem(label, line_ending).map(Zeroizing::new)
}
/// Read ASN.1 DER document from a file.
#[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")]
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"))]
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"))]
pub fn write_pem_file(
&self,
path: impl AsRef<Path>,
label: &'static str,
line_ending: pem::LineEnding,
) -> Result<()> {
write_secret_file(path, self.to_pem(label, line_ending)?.as_bytes())
}
}
#[cfg(feature = "zeroize")]
impl Debug for SecretDocument {
fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
fmt.debug_struct("SecretDocument").finish_non_exhaustive()
}
}
#[cfg(feature = "zeroize")]
impl Drop for SecretDocument {
fn drop(&mut self) {
self.0.der_bytes.zeroize();
}
}
#[cfg(feature = "zeroize")]
impl From<Document> for SecretDocument {
fn from(doc: Document) -> SecretDocument {
SecretDocument(doc)
}
}
#[cfg(feature = "zeroize")]
impl TryFrom<&[u8]> for SecretDocument {
type Error = Error;
fn try_from(der_bytes: &[u8]) -> Result<Self> {
Document::try_from(der_bytes).map(Self)
}
}
#[cfg(feature = "zeroize")]
impl TryFrom<Vec<u8>> for SecretDocument {
type Error = Error;
fn try_from(der_bytes: Vec<u8>) -> Result<Self> {
Document::try_from(der_bytes).map(Self)
}
}
#[cfg(feature = "zeroize")]
impl ZeroizeOnDrop for SecretDocument {}
/// Attempt to decode a ASN.1 `SEQUENCE` from the given decoder, returning the
/// entire sequence including the header.
fn decode_sequence<'a>(decoder: &mut SliceReader<'a>) -> Result<&'a [u8]> {
let header = decoder.peek_header()?;
header.tag.assert_eq(Tag::Sequence)?;
let len = (header.encoded_len()? + header.length)?;
decoder.read_slice(len)
}
/// Write a file containing secret data to the filesystem, restricting the
/// file permissions so it's only readable by the owner
#[cfg(all(unix, feature = "std", feature = "zeroize"))]
fn write_secret_file(path: impl AsRef<Path>, data: &[u8]) -> Result<()> {
use std::{io::Write, os::unix::fs::OpenOptionsExt};
/// File permissions for secret data
#[cfg(unix)]
const SECRET_FILE_PERMS: u32 = 0o600;
fs::OpenOptions::new()
.create(true)
.write(true)
.truncate(true)
.mode(SECRET_FILE_PERMS)
.open(path)
.and_then(|mut file| file.write_all(data))?;
Ok(())
}
/// Write a file containing secret data to the filesystem
// TODO(tarcieri): permissions hardening on Windows
#[cfg(all(not(unix), feature = "std", feature = "zeroize"))]
fn write_secret_file(path: impl AsRef<Path>, data: &[u8]) -> Result<()> {
fs::write(path, data)?;
Ok(())
}

157
vendor/der/src/encode.rs vendored Normal file
View File

@@ -0,0 +1,157 @@
//! Trait definition for [`Encode`].
use crate::{Header, Length, Result, SliceWriter, Tagged, Writer};
use core::marker::PhantomData;
#[cfg(feature = "alloc")]
use {alloc::boxed::Box, alloc::vec::Vec};
#[cfg(feature = "pem")]
use {
crate::PemWriter,
alloc::string::String,
pem_rfc7468::{self as pem, LineEnding, PemLabel},
};
#[cfg(any(feature = "alloc", feature = "pem"))]
use crate::ErrorKind;
#[cfg(doc)]
use crate::Tag;
/// Encoding trait.
pub trait Encode {
/// Compute the length of this value in bytes when encoded as ASN.1 DER.
fn encoded_len(&self) -> Result<Length>;
/// Encode this value as ASN.1 DER using the provided [`Writer`].
fn encode(&self, encoder: &mut impl Writer) -> Result<()>;
/// Encode this value to the provided byte slice, returning a sub-slice
/// containing the encoded message.
fn encode_to_slice<'a>(&self, buf: &'a mut [u8]) -> Result<&'a [u8]> {
let mut writer = SliceWriter::new(buf);
self.encode(&mut writer)?;
writer.finish()
}
/// Encode this message as ASN.1 DER, appending it to the provided
/// byte vector.
#[cfg(feature = "alloc")]
fn encode_to_vec(&self, buf: &mut Vec<u8>) -> Result<Length> {
let expected_len = usize::try_from(self.encoded_len()?)?;
let initial_len = buf.len();
buf.resize(initial_len + expected_len, 0u8);
let buf_slice = &mut buf[initial_len..];
let actual_len = self.encode_to_slice(buf_slice)?.len();
if expected_len != actual_len {
return Err(ErrorKind::Incomplete {
expected_len: expected_len.try_into()?,
actual_len: actual_len.try_into()?,
}
.into());
}
actual_len.try_into()
}
/// Encode this type as DER, returning a byte vector.
#[cfg(feature = "alloc")]
fn to_der(&self) -> Result<Vec<u8>> {
let mut buf = Vec::new();
self.encode_to_vec(&mut buf)?;
Ok(buf)
}
}
impl<T> Encode for T
where
T: EncodeValue + Tagged,
{
/// Compute the length of this value in bytes when encoded as ASN.1 DER.
fn encoded_len(&self) -> Result<Length> {
self.value_len().and_then(|len| len.for_tlv())
}
/// Encode this value as ASN.1 DER using the provided [`Writer`].
fn encode(&self, writer: &mut impl Writer) -> Result<()> {
self.header()?.encode(writer)?;
self.encode_value(writer)
}
}
/// Dummy implementation for [`PhantomData`] which allows deriving
/// implementations on structs with phantom fields.
impl<T> Encode for PhantomData<T>
where
T: ?Sized,
{
fn encoded_len(&self) -> Result<Length> {
Ok(Length::ZERO)
}
fn encode(&self, _writer: &mut impl Writer) -> Result<()> {
Ok(())
}
}
/// PEM encoding trait.
///
/// This trait is automatically impl'd for any type which impls both
/// [`Encode`] and [`PemLabel`].
#[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")]
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()?)?;
let pem_len = pem::encapsulated_len(Self::PEM_LABEL, line_ending, der_len)?;
let mut buf = vec![0u8; pem_len];
let mut writer = PemWriter::new(Self::PEM_LABEL, line_ending, &mut buf)?;
self.encode(&mut writer)?;
let actual_len = writer.finish()?;
buf.truncate(actual_len);
Ok(String::from_utf8(buf)?)
}
}
/// Encode the value part of a Tag-Length-Value encoded field, sans the [`Tag`]
/// and [`Length`].
pub trait EncodeValue {
/// Get the [`Header`] used to encode this value.
fn header(&self) -> Result<Header>
where
Self: Tagged,
{
Header::new(self.tag(), self.value_len()?)
}
/// Compute the length of this value (sans [`Tag`]+[`Length`] header) when
/// encoded as ASN.1 DER.
fn value_len(&self) -> Result<Length>;
/// Encode value (sans [`Tag`]+[`Length`] header) as ASN.1 DER using the
/// provided [`Writer`].
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)
}
}

71
vendor/der/src/encode_ref.rs vendored Normal file
View File

@@ -0,0 +1,71 @@
//! Wrapper object for encoding reference types.
// TODO(tarcieri): replace with blanket impls of `Encode(Value)` for reference types?
use crate::{Encode, EncodeValue, Length, Result, Tag, Tagged, ValueOrd, Writer};
use core::cmp::Ordering;
/// Reference encoder: wrapper type which impls `Encode` for any reference to a
/// type which impls the same.
pub struct EncodeRef<'a, T>(pub &'a T);
impl<'a, T> AsRef<T> for EncodeRef<'a, T> {
fn as_ref(&self) -> &T {
self.0
}
}
impl<'a, T> Encode for EncodeRef<'a, T>
where
T: Encode,
{
fn encoded_len(&self) -> Result<Length> {
self.0.encoded_len()
}
fn encode(&self, writer: &mut impl Writer) -> Result<()> {
self.0.encode(writer)
}
}
/// Reference value encoder: wrapper type which impls `EncodeValue` and `Tagged`
/// for any reference type which impls the same.
///
/// By virtue of the blanket impl, this type also impls `Encode`.
pub struct EncodeValueRef<'a, T>(pub &'a T);
impl<'a, T> AsRef<T> for EncodeValueRef<'a, T> {
fn as_ref(&self) -> &T {
self.0
}
}
impl<'a, T> EncodeValue for EncodeValueRef<'a, T>
where
T: EncodeValue,
{
fn value_len(&self) -> Result<Length> {
self.0.value_len()
}
fn encode_value(&self, writer: &mut impl Writer) -> Result<()> {
self.0.encode_value(writer)
}
}
impl<'a, T> Tagged for EncodeValueRef<'a, T>
where
T: Tagged,
{
fn tag(&self) -> Tag {
self.0.tag()
}
}
impl<'a, T> ValueOrd for EncodeValueRef<'a, T>
where
T: ValueOrd,
{
fn value_cmp(&self, other: &Self) -> Result<Ordering> {
self.0.value_cmp(other.0)
}
}

369
vendor/der/src/error.rs vendored Normal file
View File

@@ -0,0 +1,369 @@
//! Error types.
pub use core::str::Utf8Error;
use crate::{Length, Tag};
use core::{convert::Infallible, fmt, num::TryFromIntError};
#[cfg(feature = "oid")]
use crate::asn1::ObjectIdentifier;
#[cfg(feature = "pem")]
use crate::pem;
/// Result type.
pub type Result<T> = core::result::Result<T, Error>;
/// Error type.
#[derive(Copy, Clone, Debug, Eq, PartialEq)]
pub struct Error {
/// Kind of error.
kind: ErrorKind,
/// Position inside of message where error occurred.
position: Option<Length>,
}
impl Error {
/// Create a new [`Error`].
pub fn new(kind: ErrorKind, position: Length) -> Error {
Error {
kind,
position: Some(position),
}
}
/// Create a new [`ErrorKind::Incomplete`] for the given length.
///
/// Computes the expected len as being one greater than `actual_len`.
pub fn incomplete(actual_len: Length) -> Self {
match actual_len + Length::ONE {
Ok(expected_len) => ErrorKind::Incomplete {
expected_len,
actual_len,
}
.at(actual_len),
Err(err) => err.kind().at(actual_len),
}
}
/// Get the [`ErrorKind`] which occurred.
pub fn kind(self) -> ErrorKind {
self.kind
}
/// Get the position inside of the message where the error occurred.
pub fn position(self) -> Option<Length> {
self.position
}
/// For errors occurring inside of a nested message, extend the position
/// count by the location where the nested message occurs.
pub(crate) fn nested(self, nested_position: Length) -> Self {
// TODO(tarcieri): better handle length overflows occurring in this calculation?
let position = (nested_position + self.position.unwrap_or_default()).ok();
Self {
kind: self.kind,
position,
}
}
}
#[cfg(feature = "std")]
impl std::error::Error for Error {}
impl fmt::Display for Error {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "{}", self.kind)?;
if let Some(pos) = self.position {
write!(f, " at DER byte {}", pos)?;
}
Ok(())
}
}
impl From<ErrorKind> for Error {
fn from(kind: ErrorKind) -> Error {
Error {
kind,
position: None,
}
}
}
impl From<Infallible> for Error {
fn from(_: Infallible) -> Error {
unreachable!()
}
}
impl From<TryFromIntError> for Error {
fn from(_: TryFromIntError) -> Error {
Error {
kind: ErrorKind::Overflow,
position: None,
}
}
}
impl From<Utf8Error> for Error {
fn from(err: Utf8Error) -> Error {
Error {
kind: ErrorKind::Utf8(err),
position: None,
}
}
}
#[cfg(feature = "alloc")]
impl From<alloc::string::FromUtf8Error> for Error {
fn from(err: alloc::string::FromUtf8Error) -> Error {
ErrorKind::Utf8(err.utf8_error()).into()
}
}
#[cfg(feature = "oid")]
impl From<const_oid::Error> for Error {
fn from(_: const_oid::Error) -> Error {
ErrorKind::OidMalformed.into()
}
}
#[cfg(feature = "pem")]
impl From<pem::Error> for Error {
fn from(err: pem::Error) -> Error {
ErrorKind::Pem(err).into()
}
}
#[cfg(feature = "std")]
impl From<std::io::Error> for Error {
fn from(err: std::io::Error) -> Error {
match err.kind() {
std::io::ErrorKind::NotFound => ErrorKind::FileNotFound,
std::io::ErrorKind::PermissionDenied => ErrorKind::PermissionDenied,
other => ErrorKind::Io(other),
}
.into()
}
}
#[cfg(feature = "time")]
impl From<time::error::ComponentRange> for Error {
fn from(_: time::error::ComponentRange) -> Error {
ErrorKind::DateTime.into()
}
}
/// Error type.
#[derive(Copy, Clone, Debug, Eq, PartialEq)]
#[non_exhaustive]
pub enum ErrorKind {
/// Date-and-time related errors.
DateTime,
/// This error indicates a previous DER parsing operation resulted in
/// an error and tainted the state of a `Decoder` or `Encoder`.
///
/// Once this occurs, the overall operation has failed and cannot be
/// subsequently resumed.
Failed,
/// File not found error.
#[cfg(feature = "std")]
FileNotFound,
/// Message is incomplete and does not contain all of the expected data.
Incomplete {
/// Expected message length.
///
/// Note that this length represents a *minimum* lower bound on how
/// much additional data is needed to continue parsing the message.
///
/// It's possible upon subsequent message parsing that the parser will
/// discover even more data is needed.
expected_len: Length,
/// Actual length of the message buffer currently being processed.
actual_len: Length,
},
/// I/O errors.
#[cfg(feature = "std")]
Io(std::io::ErrorKind),
/// Indefinite length disallowed.
IndefiniteLength,
/// Incorrect length for a given field.
Length {
/// Tag of the value being decoded.
tag: Tag,
},
/// Message is not canonically encoded.
Noncanonical {
/// Tag of the value which is not canonically encoded.
tag: Tag,
},
/// OID is improperly encoded.
OidMalformed,
/// Unknown OID.
///
/// This error is intended to be used by libraries which parse DER-based
/// formats which encounter unknown or unsupported OID libraries.
///
/// It enables passing back the OID value to the caller, which allows them
/// to determine which OID(s) are causing the error (and then potentially
/// contribute upstream support for algorithms they care about).
#[cfg(feature = "oid")]
OidUnknown {
/// OID value that was unrecognized by a parser for a DER-based format.
oid: ObjectIdentifier,
},
/// `SET` cannot contain duplicates.
SetDuplicate,
/// `SET` ordering error: items not in canonical order.
SetOrdering,
/// Integer overflow occurred (library bug!).
Overflow,
/// Message is longer than this library's internal limits support.
Overlength,
/// PEM encoding errors.
#[cfg(feature = "pem")]
Pem(pem::Error),
/// Permission denied reading file.
#[cfg(feature = "std")]
PermissionDenied,
/// Reader does not support the requested operation.
Reader,
/// Unknown tag mode.
TagModeUnknown,
/// Invalid tag number.
///
/// The "tag number" is the lower 5-bits of a tag's octet.
/// This error occurs in the case that all 5-bits are set to `1`,
/// which indicates a multi-byte tag which is unsupported by this library.
TagNumberInvalid,
/// Unexpected tag.
TagUnexpected {
/// Tag the decoder was expecting (if there is a single such tag).
///
/// `None` if multiple tags are expected/allowed, but the `actual` tag
/// does not match any of them.
expected: Option<Tag>,
/// Actual tag encountered in the message.
actual: Tag,
},
/// Unknown/unsupported tag.
TagUnknown {
/// Raw byte value of the tag.
byte: u8,
},
/// Undecoded trailing data at end of message.
TrailingData {
/// Length of the decoded data.
decoded: Length,
/// Total length of the remaining data left in the buffer.
remaining: Length,
},
/// UTF-8 errors.
Utf8(Utf8Error),
/// Unexpected value.
Value {
/// Tag of the unexpected value.
tag: Tag,
},
}
impl ErrorKind {
/// Annotate an [`ErrorKind`] with context about where it occurred,
/// returning an error.
pub fn at(self, position: Length) -> Error {
Error::new(self, position)
}
}
impl fmt::Display for ErrorKind {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
ErrorKind::DateTime => write!(f, "date/time error"),
ErrorKind::Failed => write!(f, "operation failed"),
#[cfg(feature = "std")]
ErrorKind::FileNotFound => write!(f, "file not found"),
ErrorKind::Incomplete {
expected_len,
actual_len,
} => write!(
f,
"ASN.1 DER message is incomplete: expected {}, actual {}",
expected_len, actual_len
),
#[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)
}
ErrorKind::OidMalformed => write!(f, "malformed OID"),
#[cfg(feature = "oid")]
ErrorKind::OidUnknown { oid } => {
write!(f, "unknown/unsupported OID: {}", oid)
}
ErrorKind::SetDuplicate => write!(f, "SET OF contains duplicate"),
ErrorKind::SetOrdering => write!(f, "SET OF ordering error"),
ErrorKind::Overflow => write!(f, "integer overflow"),
ErrorKind::Overlength => write!(f, "ASN.1 DER message is too long"),
#[cfg(feature = "pem")]
ErrorKind::Pem(e) => write!(f, "PEM error: {}", e),
#[cfg(feature = "std")]
ErrorKind::PermissionDenied => write!(f, "permission denied"),
ErrorKind::Reader => write!(f, "reader does not support the requested operation"),
ErrorKind::TagModeUnknown => write!(f, "unknown tag mode"),
ErrorKind::TagNumberInvalid => write!(f, "invalid tag number"),
ErrorKind::TagUnexpected { expected, actual } => {
write!(f, "unexpected ASN.1 DER tag: ")?;
if let Some(tag) = expected {
write!(f, "expected {}, ", tag)?;
}
write!(f, "got {}", actual)
}
ErrorKind::TagUnknown { byte } => {
write!(f, "unknown/unsupported ASN.1 DER tag: 0x{:02x}", byte)
}
ErrorKind::TrailingData { decoded, remaining } => {
write!(
f,
"trailing data at end of DER message: decoded {} bytes, {} bytes remaining",
decoded, remaining
)
}
ErrorKind::Utf8(e) => write!(f, "{}", e),
ErrorKind::Value { tag } => write!(f, "malformed ASN.1 DER value for {}", tag),
}
}
}

60
vendor/der/src/header.rs vendored Normal file
View File

@@ -0,0 +1,60 @@
//! ASN.1 DER headers.
use crate::{Decode, DerOrd, Encode, ErrorKind, Length, Reader, Result, Tag, Writer};
use core::cmp::Ordering;
/// ASN.1 DER headers: tag + length component of TLV-encoded values
#[derive(Copy, Clone, Debug, Eq, PartialEq)]
pub struct Header {
/// Tag representing the type of the encoded value
pub tag: Tag,
/// Length of the encoded value
pub length: Length,
}
impl Header {
/// Create a new [`Header`] from a [`Tag`] and a specified length.
///
/// Returns an error if the length exceeds the limits of [`Length`].
pub fn new(tag: Tag, length: impl TryInto<Length>) -> Result<Self> {
let length = length.try_into().map_err(|_| ErrorKind::Overflow)?;
Ok(Self { tag, length })
}
}
impl<'a> Decode<'a> for Header {
fn decode<R: Reader<'a>>(reader: &mut R) -> Result<Header> {
let tag = Tag::decode(reader)?;
let length = Length::decode(reader).map_err(|e| {
if e.kind() == ErrorKind::Overlength {
ErrorKind::Length { tag }.into()
} else {
e
}
})?;
Ok(Self { tag, length })
}
}
impl Encode for Header {
fn encoded_len(&self) -> Result<Length> {
self.tag.encoded_len()? + self.length.encoded_len()?
}
fn encode(&self, writer: &mut impl Writer) -> Result<()> {
self.tag.encode(writer)?;
self.length.encode(writer)
}
}
impl DerOrd for Header {
fn der_cmp(&self, other: &Self) -> Result<Ordering> {
match self.tag.der_cmp(&other.tag)? {
Ordering::Equal => self.length.der_cmp(&other.length),
ordering => Ok(ordering),
}
}
}

514
vendor/der/src/length.rs vendored Normal file
View File

@@ -0,0 +1,514 @@
//! Length calculations for encoded ASN.1 DER values
use crate::{Decode, DerOrd, Encode, Error, ErrorKind, Reader, Result, SliceWriter, Writer};
use core::{
cmp::Ordering,
fmt,
ops::{Add, Sub},
};
/// Maximum number of octets in a DER encoding of a [`Length`] using the
/// rules implemented by this crate.
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).
#[derive(Copy, Clone, Debug, Default, Eq, PartialEq, PartialOrd, Ord)]
pub struct Length(u32);
impl Length {
/// Length of `0`
pub const ZERO: Self = Self(0);
/// Length of `1`
pub const ONE: Self = Self(1);
/// Maximum length currently supported: 256 MiB
pub const MAX: Self = Self(MAX_U32);
/// Create a new [`Length`] for any value which fits inside of a [`u16`].
///
/// This function is const-safe and therefore useful for [`Length`] constants.
pub const fn new(value: u16) -> Self {
Self(value as u32)
}
/// Is this length equal to zero?
pub fn is_zero(self) -> bool {
self == Self::ZERO
}
/// Get the length of DER Tag-Length-Value (TLV) encoded data if `self`
/// is the length of the inner "value" portion of the message.
pub fn for_tlv(self) -> Result<Self> {
Self::ONE + self.encoded_len()? + self
}
/// Perform saturating addition of two lengths.
pub fn saturating_add(self, rhs: Self) -> Self {
Self(self.0.saturating_add(rhs.0))
}
/// Perform saturating subtraction of two lengths.
pub fn saturating_sub(self, rhs: Self) -> Self {
Self(self.0.saturating_sub(rhs.0))
}
/// Get initial octet of the encoded length (if one is required).
///
/// From X.690 Section 8.1.3.5:
/// > In the long form, the length octets shall consist of an initial octet
/// > and one or more subsequent octets. The initial octet shall be encoded
/// > as follows:
/// >
/// > a) bit 8 shall be one;
/// > b) bits 7 to 1 shall encode the number of subsequent octets in the
/// > length octets, as an unsigned binary integer with bit 7 as the
/// > most significant bit;
/// > c) the value 11111111₂ shall not be used.
fn initial_octet(self) -> Option<u8> {
match self.0 {
0x80..=0xFF => Some(0x81),
0x100..=0xFFFF => Some(0x82),
0x10000..=0xFFFFFF => Some(0x83),
0x1000000..=MAX_U32 => Some(0x84),
_ => None,
}
}
}
impl Add for Length {
type Output = Result<Self>;
fn add(self, other: Self) -> Result<Self> {
self.0
.checked_add(other.0)
.ok_or_else(|| ErrorKind::Overflow.into())
.and_then(TryInto::try_into)
}
}
impl Add<u8> for Length {
type Output = Result<Self>;
fn add(self, other: u8) -> Result<Self> {
self + Length::from(other)
}
}
impl Add<u16> for Length {
type Output = Result<Self>;
fn add(self, other: u16) -> Result<Self> {
self + Length::from(other)
}
}
impl Add<u32> for Length {
type Output = Result<Self>;
fn add(self, other: u32) -> Result<Self> {
self + Length::try_from(other)?
}
}
impl Add<usize> for Length {
type Output = Result<Self>;
fn add(self, other: usize) -> Result<Self> {
self + Length::try_from(other)?
}
}
impl Add<Length> for Result<Length> {
type Output = Self;
fn add(self, other: Length) -> Self {
self? + other
}
}
impl Sub for Length {
type Output = Result<Self>;
fn sub(self, other: Length) -> Result<Self> {
self.0
.checked_sub(other.0)
.ok_or_else(|| ErrorKind::Overflow.into())
.and_then(TryInto::try_into)
}
}
impl Sub<Length> for Result<Length> {
type Output = Self;
fn sub(self, other: Length) -> Self {
self? - other
}
}
impl From<u8> for Length {
fn from(len: u8) -> Length {
Length(len.into())
}
}
impl From<u16> for Length {
fn from(len: u16) -> Length {
Length(len.into())
}
}
impl From<Length> for u32 {
fn from(length: Length) -> u32 {
length.0
}
}
impl TryFrom<u32> for Length {
type Error = Error;
fn try_from(len: u32) -> Result<Length> {
if len <= Self::MAX.0 {
Ok(Length(len))
} else {
Err(ErrorKind::Overflow.into())
}
}
}
impl TryFrom<usize> for Length {
type Error = Error;
fn try_from(len: usize) -> Result<Length> {
u32::try_from(len)
.map_err(|_| ErrorKind::Overflow)?
.try_into()
}
}
impl TryFrom<Length> for usize {
type Error = Error;
fn try_from(len: Length) -> Result<usize> {
len.0.try_into().map_err(|_| ErrorKind::Overflow.into())
}
}
impl<'a> Decode<'a> for Length {
fn decode<R: Reader<'a>>(reader: &mut R) -> Result<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 < 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;
debug_assert!(nbytes <= 4);
let mut decoded_len = 0u32;
for _ in 0..nbytes {
decoded_len = decoded_len.checked_shl(8).ok_or(ErrorKind::Overflow)?
| u32::from(reader.read_byte()?);
}
let length = Length::try_from(decoded_len)?;
// X.690 Section 10.1: DER lengths must be encoded with a minimum
// number of octets
if length.initial_octet() == Some(tag) {
Ok(length)
} else {
Err(ErrorKind::Overlength.into())
}
}
_ => {
// We specialize to a maximum 4-byte length (including initial octet)
Err(ErrorKind::Overlength.into())
}
}
}
}
impl Encode for Length {
fn encoded_len(&self) -> Result<Length> {
match self.0 {
0..=0x7F => Ok(Length(1)),
0x80..=0xFF => Ok(Length(2)),
0x100..=0xFFFF => Ok(Length(3)),
0x10000..=0xFFFFFF => Ok(Length(4)),
0x1000000..=MAX_U32 => Ok(Length(5)),
_ => Err(ErrorKind::Overflow.into()),
}
}
fn encode(&self, writer: &mut impl Writer) -> Result<()> {
match self.initial_octet() {
Some(tag_byte) => {
writer.write_byte(tag_byte)?;
// Strip leading zeroes
match self.0.to_be_bytes() {
[0, 0, 0, byte] => writer.write_byte(byte),
[0, 0, bytes @ ..] => writer.write(&bytes),
[0, bytes @ ..] => writer.write(&bytes),
bytes => writer.write(&bytes),
}
}
#[allow(clippy::cast_possible_truncation)]
None => writer.write_byte(self.0 as u8),
}
}
}
impl DerOrd for Length {
fn der_cmp(&self, other: &Self) -> Result<Ordering> {
let mut buf1 = [0u8; MAX_DER_OCTETS];
let mut buf2 = [0u8; MAX_DER_OCTETS];
let mut encoder1 = SliceWriter::new(&mut buf1);
encoder1.encode(self)?;
let mut encoder2 = SliceWriter::new(&mut buf2);
encoder2.encode(other)?;
Ok(encoder1.finish()?.cmp(encoder2.finish()?))
}
}
impl fmt::Display for Length {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
self.0.fmt(f)
}
}
// 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::{IndefiniteLength, Length};
use crate::{Decode, DerOrd, Encode, ErrorKind};
use core::cmp::Ordering;
#[test]
fn decode() {
assert_eq!(Length::ZERO, Length::from_der(&[0x00]).unwrap());
assert_eq!(Length::from(0x7Fu8), Length::from_der(&[0x7F]).unwrap());
assert_eq!(
Length::from(0x80u8),
Length::from_der(&[0x81, 0x80]).unwrap()
);
assert_eq!(
Length::from(0xFFu8),
Length::from_der(&[0x81, 0xFF]).unwrap()
);
assert_eq!(
Length::from(0x100u16),
Length::from_der(&[0x82, 0x01, 0x00]).unwrap()
);
assert_eq!(
Length::try_from(0x10000u32).unwrap(),
Length::from_der(&[0x83, 0x01, 0x00, 0x00]).unwrap()
);
}
#[test]
fn encode() {
let mut buffer = [0u8; 4];
assert_eq!(&[0x00], Length::ZERO.encode_to_slice(&mut buffer).unwrap());
assert_eq!(
&[0x7F],
Length::from(0x7Fu8).encode_to_slice(&mut buffer).unwrap()
);
assert_eq!(
&[0x81, 0x80],
Length::from(0x80u8).encode_to_slice(&mut buffer).unwrap()
);
assert_eq!(
&[0x81, 0xFF],
Length::from(0xFFu8).encode_to_slice(&mut buffer).unwrap()
);
assert_eq!(
&[0x82, 0x01, 0x00],
Length::from(0x100u16).encode_to_slice(&mut buffer).unwrap()
);
assert_eq!(
&[0x83, 0x01, 0x00, 0x00],
Length::try_from(0x10000u32)
.unwrap()
.encode_to_slice(&mut buffer)
.unwrap()
);
}
#[test]
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]
fn add_overflows_when_max_length_exceeded() {
let result = Length::MAX + Length::ONE;
assert_eq!(
result.err().map(|err| err.kind()),
Some(ErrorKind::Overflow)
);
}
#[test]
fn der_ord() {
assert_eq!(Length::ONE.der_cmp(&Length::MAX).unwrap(), Ordering::Less);
}
}

402
vendor/der/src/lib.rs vendored Normal file
View File

@@ -0,0 +1,402 @@
#![no_std]
#![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",
html_favicon_url = "https://raw.githubusercontent.com/RustCrypto/media/6ee8e381/logo.svg"
)]
#![forbid(unsafe_code)]
#![warn(
clippy::cast_lossless,
clippy::cast_possible_truncation,
clippy::cast_possible_wrap,
clippy::cast_precision_loss,
clippy::cast_sign_loss,
clippy::checked_conversions,
clippy::implicit_saturating_sub,
clippy::integer_arithmetic,
clippy::mod_module_files,
clippy::panic,
clippy::panic_in_result_fn,
clippy::unwrap_used,
missing_docs,
rust_2018_idioms,
unused_lifetimes,
unused_qualifications
)]
//! # Usage
//! ## [`Decode`] and [`Encode`] traits
//! The [`Decode`] and [`Encode`] traits provide the decoding/encoding API
//! respectively, and are designed to work in conjunction with concrete ASN.1
//! types, including all types which impl the [`Sequence`] trait.
//!
//! The traits are impl'd for the following Rust core types:
//! - `()`: ASN.1 `NULL`. See also [`Null`].
//! - [`bool`]: ASN.1 `BOOLEAN`.
//! - [`i8`], [`i16`], [`i32`], [`i64`], [`i128`]: ASN.1 `INTEGER`.
//! - [`u8`], [`u16`], [`u32`], [`u64`], [`u128`]: ASN.1 `INTEGER`.
//! - [`f64`]: ASN.1 `REAL` (gated on `real` crate feature)
//! - [`str`], [`String`][`alloc::string::String`]: ASN.1 `UTF8String`.
//! `String` requires `alloc` feature. See also [`Utf8StringRef`].
//! - [`Option`]: ASN.1 `OPTIONAL`.
//! - [`SystemTime`][`std::time::SystemTime`]: ASN.1 `GeneralizedTime`. Requires `std` feature.
//! - [`Vec`][`alloc::vec::Vec`]: ASN.1 `SEQUENCE OF`. Requires `alloc` feature.
//! - `[T; N]`: ASN.1 `SEQUENCE OF`. See also [`SequenceOf`].
//!
//! The following ASN.1 types provided by this crate also impl these traits:
//! - [`Any`], [`AnyRef`]: ASN.1 `ANY`.
//! - [`BitString`], [`BitStringRef`]: ASN.1 `BIT STRING`
//! - [`GeneralizedTime`]: ASN.1 `GeneralizedTime`.
//! - [`Ia5StringRef`]: ASN.1 `IA5String`.
//! - [`Null`]: ASN.1 `NULL`.
//! - [`ObjectIdentifier`]: ASN.1 `OBJECT IDENTIFIER`.
//! - [`OctetString`], [`OctetStringRef`]: ASN.1 `OCTET STRING`.
//! - [`PrintableStringRef`]: ASN.1 `PrintableString` (ASCII subset).
//! - [`TeletexStringRef`]: ASN.1 `TeletexString`.
//! - [`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.
//! - [`UtcTime`]: ASN.1 `UTCTime`.
//! - [`Utf8StringRef`]: ASN.1 `UTF8String`.
//!
//! Context specific fields can be modeled using these generic types:
//! - [`ContextSpecific`]: decoder/encoder for owned context-specific fields
//! - [`ContextSpecificRef`]: encode-only type for references to context-specific fields
//!
//! ## Example
//! The following example implements X.509's `AlgorithmIdentifier` message type
//! as defined in [RFC 5280 Section 4.1.1.2].
//!
//! The ASN.1 schema for this message type is as follows:
//!
//! ```text
//! AlgorithmIdentifier ::= SEQUENCE {
//! algorithm OBJECT IDENTIFIER,
//! parameters ANY DEFINED BY algorithm OPTIONAL }
//! ```
//!
//! Structured ASN.1 messages are typically encoded as a `SEQUENCE`, which
//! this crate maps to a Rust struct using the [`Sequence`] trait. This
//! trait is bounded on the [`Decode`] trait and provides a blanket impl
//! of the [`Encode`] trait, so any type which impls [`Sequence`] can be
//! used for both decoding and encoding.
//!
//! The following code example shows how to define a struct which maps to the
//! above schema, as well as impl the [`Sequence`] trait for that struct:
//!
//! ```
//! # #[cfg(all(feature = "alloc", feature = "oid"))]
//! # {
//! // Note: the following example does not require the `std` feature at all.
//! // It does leverage the `alloc` feature, but also provides instructions for
//! // "heapless" usage when the `alloc` feature is disabled.
//! use der::{
//! asn1::{AnyRef, ObjectIdentifier},
//! DecodeValue, Decode, SliceReader, Encode, Header, Reader, Sequence
//! };
//!
//! /// X.509 `AlgorithmIdentifier`.
//! #[derive(Copy, Clone, Debug, Eq, PartialEq)]
//! pub struct AlgorithmIdentifier<'a> {
//! /// This field contains an ASN.1 `OBJECT IDENTIFIER`, a.k.a. OID.
//! pub algorithm: ObjectIdentifier,
//!
//! /// This field is `OPTIONAL` and contains the ASN.1 `ANY` type, which
//! /// in this example allows arbitrary algorithm-defined parameters.
//! pub parameters: Option<AnyRef<'a>>
//! }
//!
//! impl<'a> DecodeValue<'a> for AlgorithmIdentifier<'a> {
//! fn decode_value<R: Reader<'a>>(reader: &mut R, _header: Header) -> der::Result<Self> {
//! // The `der::Decoder::Decode` method can be used to decode any
//! // type which impls the `Decode` trait, which is impl'd for
//! // all of the ASN.1 built-in types in the `der` crate.
//! //
//! // Note that if your struct's fields don't contain an ASN.1
//! // built-in type specifically, there are also helper methods
//! // for all of the built-in types supported by this library
//! // which can be used to select a specific type.
//! //
//! // For example, another way of decoding this particular field,
//! // which contains an ASN.1 `OBJECT IDENTIFIER`, is by calling
//! // `decoder.oid()`. Similar methods are defined for other
//! // ASN.1 built-in types.
//! let algorithm = reader.decode()?;
//!
//! // This field contains an ASN.1 `OPTIONAL` type. The `der` crate
//! // maps this directly to Rust's `Option` type and provides
//! // impls of the `Decode` and `Encode` traits for `Option`.
//! // To explicitly request an `OPTIONAL` type be decoded, use the
//! // `decoder.optional()` method.
//! let parameters = reader.decode()?;
//!
//! // The value returned from the provided `FnOnce` will be
//! // returned from the `any.sequence(...)` call above.
//! // Note that the entire sequence body *MUST* be consumed
//! // or an error will be returned.
//! Ok(Self { algorithm, 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();
//!
//! // We need to convert `parameters` into an `Any<'a>` type, which wraps a
//! // `&'a [u8]` byte slice.
//! //
//! // To do that, we need owned DER-encoded data so that we can have
//! // `AnyRef` borrow a reference to it, so we have to serialize the OID.
//! //
//! // When the `alloc` feature of this crate is enabled, any type that impls
//! // the `Encode` trait including all ASN.1 built-in types and any type
//! // which impls `Sequence` can be serialized by calling `Encode::to_der()`.
//! //
//! // 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_der().unwrap();
//!
//! let algorithm_identifier = AlgorithmIdentifier {
//! // OID for `id-ecPublicKey`, if you're curious
//! algorithm: "1.2.840.10045.2.1".parse().unwrap(),
//!
//! // `Any<'a>` impls `TryFrom<&'a [u8]>`, which parses the provided
//! // slice as an ASN.1 DER-encoded message.
//! parameters: Some(der_encoded_parameters.as_slice().try_into().unwrap())
//! };
//!
//! // Serialize the `AlgorithmIdentifier` created above as ASN.1 DER,
//! // allocating a `Vec<u8>` for storage.
//! //
//! // As mentioned earlier, if you don't have the `alloc` feature enabled you
//! // can create a fix-sized array instead, then call `Encoder::new` with a
//! // 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_der().unwrap();
//!
//! // Deserialize the `AlgorithmIdentifier` we just serialized from ASN.1 DER
//! // using `der::Decode::from_bytes`.
//! let decoded_algorithm_identifier = AlgorithmIdentifier::from_der(
//! &der_encoded_algorithm_identifier
//! ).unwrap();
//!
//! // Ensure the original `AlgorithmIdentifier` is the same as the one we just
//! // decoded from ASN.1 DER.
//! assert_eq!(algorithm_identifier, decoded_algorithm_identifier);
//! # }
//! ```
//!
//! ## Custom derive support
//! When the `derive` feature of this crate is enabled, the following custom
//! derive macros are available:
//!
//! - [`Choice`]: derive for `CHOICE` enum (see [`der_derive::Choice`])
//! - [`Enumerated`]: derive for `ENUMERATED` enum (see [`der_derive::Enumerated`])
//! - [`Sequence`]: derive for `SEQUENCE` struct (see [`der_derive::Sequence`])
//!
//! ### Derive [`Sequence`] for struct
//! The following is a code example of how to use the [`Sequence`] custom derive:
//!
//! ```
//! # #[cfg(all(feature = "alloc", feature = "derive", feature = "oid"))]
//! # {
//! use der::{asn1::{AnyRef, ObjectIdentifier}, Encode, Decode, Sequence};
//!
//! /// X.509 `AlgorithmIdentifier` (same as above)
//! #[derive(Copy, Clone, Debug, Eq, PartialEq, Sequence)] // NOTE: added `Sequence`
//! pub struct AlgorithmIdentifier<'a> {
//! /// This field contains an ASN.1 `OBJECT IDENTIFIER`, a.k.a. OID.
//! pub algorithm: ObjectIdentifier,
//!
//! /// This field is `OPTIONAL` and contains the ASN.1 `ANY` type, which
//! /// in this example allows arbitrary algorithm-defined parameters.
//! pub parameters: Option<AnyRef<'a>>
//! }
//!
//! // Example parameters value: OID for the NIST P-256 elliptic curve.
//! let parameters_oid = "1.2.840.10045.3.1.7".parse::<ObjectIdentifier>().unwrap();
//!
//! let algorithm_identifier = AlgorithmIdentifier {
//! // OID for `id-ecPublicKey`, if you're curious
//! algorithm: "1.2.840.10045.2.1".parse().unwrap(),
//!
//! // `Any<'a>` impls `From<&'a ObjectIdentifier>`, allowing OID constants to
//! // be directly converted to an `AnyRef` type for this use case.
//! parameters: Some(AnyRef::from(&parameters_oid))
//! };
//!
//! // Encode
//! let der_encoded_algorithm_identifier = algorithm_identifier.to_der().unwrap();
//!
//! // Decode
//! let decoded_algorithm_identifier = AlgorithmIdentifier::from_der(
//! &der_encoded_algorithm_identifier
//! ).unwrap();
//!
//! assert_eq!(algorithm_identifier, decoded_algorithm_identifier);
//! # }
//! ```
//!
//! For fields which don't directly impl [`Decode`] and [`Encode`],
//! you can add annotations to convert to an intermediate ASN.1 type
//! first, so long as that type impls `TryFrom` and `Into` for the
//! ASN.1 type.
//!
//! For example, structs containing `&'a [u8]` fields may want them encoded
//! as either a `BIT STRING` or `OCTET STRING`. By using the
//! `#[asn1(type = "BIT STRING")]` annotation it's possible to select which
//! ASN.1 type should be used.
//!
//! Building off the above example:
//!
//! ```rust
//! # #[cfg(all(feature = "alloc", feature = "derive", feature = "oid"))]
//! # {
//! # use der::{asn1::{AnyRef, BitStringRef, ObjectIdentifier}, Sequence};
//! #
//! # #[derive(Copy, Clone, Debug, Eq, PartialEq, Sequence)]
//! # pub struct AlgorithmIdentifier<'a> {
//! # pub algorithm: ObjectIdentifier,
//! # pub parameters: Option<AnyRef<'a>>
//! # }
//! /// X.509 `SubjectPublicKeyInfo` (SPKI)
//! #[derive(Copy, Clone, Debug, Eq, PartialEq, Sequence)]
//! pub struct SubjectPublicKeyInfo<'a> {
//! /// X.509 `AlgorithmIdentifier`
//! pub algorithm: AlgorithmIdentifier<'a>,
//!
//! /// Public key data
//! pub subject_public_key: BitStringRef<'a>,
//! }
//! # }
//! ```
//!
//! # See also
//! For more information about ASN.1 DER we recommend the following guides:
//!
//! - [A Layman's Guide to a Subset of ASN.1, BER, and DER] (RSA Laboratories)
//! - [A Warm Welcome to ASN.1 and DER] (Let's Encrypt)
//!
//! [RFC 5280 Section 4.1.1.2]: https://tools.ietf.org/html/rfc5280#section-4.1.1.2
//! [A Layman's Guide to a Subset of ASN.1, BER, and DER]: https://luca.ntop.org/Teaching/Appunti/asn1.html
//! [A Warm Welcome to ASN.1 and DER]: https://letsencrypt.org/docs/a-warm-welcome-to-asn1-and-der/
//!
//! [`Any`]: asn1::Any
//! [`AnyRef`]: asn1::AnyRef
//! [`ContextSpecific`]: asn1::ContextSpecific
//! [`ContextSpecificRef`]: asn1::ContextSpecificRef
//! [`BitString`]: asn1::BitString
//! [`BitStringRef`]: asn1::BitStringRef
//! [`GeneralizedTime`]: asn1::GeneralizedTime
//! [`Ia5StringRef`]: asn1::Ia5StringRef
//! [`Null`]: asn1::Null
//! [`ObjectIdentifier`]: asn1::ObjectIdentifier
//! [`OctetString`]: asn1::OctetString
//! [`OctetStringRef`]: asn1::OctetStringRef
//! [`PrintableStringRef`]: asn1::PrintableStringRef
//! [`TeletexStringRef`]: asn1::TeletexStringRef
//! [`VideotexStringRef`]: asn1::VideotexStringRef
//! [`SequenceOf`]: asn1::SequenceOf
//! [`SetOf`]: asn1::SetOf
//! [`SetOfVec`]: asn1::SetOfVec
//! [`UintRef`]: asn1::UintRef
//! [`UtcTime`]: asn1::UtcTime
//! [`Utf8StringRef`]: asn1::Utf8StringRef
#[cfg(feature = "alloc")]
#[allow(unused_imports)]
#[macro_use]
extern crate alloc;
#[cfg(feature = "std")]
extern crate std;
pub mod asn1;
pub mod referenced;
pub(crate) mod arrayvec;
mod bytes_ref;
mod datetime;
mod decode;
mod encode;
mod encode_ref;
mod error;
mod header;
mod length;
mod ord;
mod reader;
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},
datetime::DateTime,
decode::{Decode, DecodeOwned, DecodeValue},
encode::{Encode, EncodeValue},
encode_ref::{EncodeRef, EncodeValueRef},
error::{Error, ErrorKind, Result},
header::Header,
length::{IndefiniteLength, Length},
ord::{DerOrd, ValueOrd},
reader::{nested::NestedReader, slice::SliceReader, Reader},
tag::{Class, FixedTag, Tag, TagMode, TagNumber, Tagged},
writer::{slice::SliceWriter, Writer},
};
#[cfg(feature = "alloc")]
pub use crate::{asn1::Any, document::Document};
#[cfg(feature = "bigint")]
pub use crypto_bigint as bigint;
#[cfg(feature = "derive")]
pub use der_derive::{Choice, Enumerated, Sequence, ValueOrd};
#[cfg(feature = "flagset")]
pub use flagset;
#[cfg(feature = "oid")]
pub use const_oid as oid;
#[cfg(feature = "pem")]
pub use {
crate::{decode::DecodePem, encode::EncodePem, reader::pem::PemReader, writer::pem::PemWriter},
pem_rfc7468 as pem,
};
#[cfg(feature = "time")]
pub use time;
#[cfg(feature = "zeroize")]
pub use zeroize;
#[cfg(all(feature = "alloc", feature = "zeroize"))]
pub use crate::document::SecretDocument;
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};

85
vendor/der/src/ord.rs vendored Normal file
View File

@@ -0,0 +1,85 @@
//! Ordering trait.
use crate::{EncodeValue, Result, Tagged};
use core::{cmp::Ordering, marker::PhantomData};
/// DER ordering trait.
///
/// Compares the ordering of two values based on their ASN.1 DER
/// serializations.
///
/// This is used by the DER encoding for `SET OF` in order to establish an
/// ordering for the elements of sets.
pub trait DerOrd {
/// Return an [`Ordering`] between `self` and `other` when serialized as
/// ASN.1 DER.
fn der_cmp(&self, other: &Self) -> Result<Ordering>;
}
/// DER value ordering trait.
///
/// Compares the ordering of the value portion of TLV-encoded DER productions.
pub trait ValueOrd {
/// Return an [`Ordering`] between value portion of TLV-encoded `self` and
/// `other` when serialized as ASN.1 DER.
fn value_cmp(&self, other: &Self) -> Result<Ordering>;
}
impl<T> DerOrd for T
where
T: EncodeValue + ValueOrd + Tagged,
{
fn der_cmp(&self, other: &Self) -> Result<Ordering> {
match self.header()?.der_cmp(&other.header()?)? {
Ordering::Equal => self.value_cmp(other),
ordering => Ok(ordering),
}
}
}
/// Marker trait for types whose `Ord` impl can be used as `ValueOrd`.
///
/// This means the `Ord` impl will sort values in the same order as their DER
/// encodings.
pub trait OrdIsValueOrd: Ord {}
impl<T> ValueOrd for T
where
T: OrdIsValueOrd,
{
fn value_cmp(&self, other: &Self) -> Result<Ordering> {
Ok(self.cmp(other))
}
}
/// Compare the order of two iterators using [`DerCmp`] on the values.
pub(crate) fn iter_cmp<'a, I, T: 'a>(a: I, b: I) -> Result<Ordering>
where
I: Iterator<Item = &'a T> + ExactSizeIterator,
T: DerOrd,
{
let length_ord = a.len().cmp(&b.len());
for (value1, value2) in a.zip(b) {
match value1.der_cmp(value2)? {
Ordering::Equal => (),
other => return Ok(other),
}
}
Ok(length_ord)
}
/// Provide a no-op implementation for PhantomData
impl<T> ValueOrd for PhantomData<T> {
fn value_cmp(&self, _other: &Self) -> Result<Ordering> {
Ok(Ordering::Equal)
}
}
/// Provide a no-op implementation for PhantomData
impl<T> DerOrd for PhantomData<T> {
fn der_cmp(&self, _other: &Self) -> Result<Ordering> {
Ok(Ordering::Equal)
}
}

167
vendor/der/src/reader.rs vendored Normal file
View File

@@ -0,0 +1,167 @@
//! Reader trait.
pub(crate) mod nested;
#[cfg(feature = "pem")]
pub(crate) mod pem;
pub(crate) mod slice;
pub(crate) use nested::NestedReader;
use crate::{
asn1::ContextSpecific, Decode, DecodeValue, Encode, Error, ErrorKind, FixedTag, Header, Length,
Result, Tag, TagMode, TagNumber,
};
#[cfg(feature = "alloc")]
use alloc::vec::Vec;
/// Reader trait which reads DER-encoded input.
pub trait Reader<'r>: Sized {
/// Get the length of the input.
fn input_len(&self) -> Length;
/// Peek at the next byte of input without modifying the cursor.
fn peek_byte(&self) -> Option<u8>;
/// Peek forward in the input data, attempting to decode a [`Header`] from
/// the data at the current position in the decoder.
///
/// Does not modify the decoder's state.
fn peek_header(&self) -> Result<Header>;
/// Get the position within the buffer.
fn position(&self) -> Length;
/// Attempt to read data borrowed directly from the input as a slice,
/// updating the internal cursor position.
///
/// # Returns
/// - `Ok(slice)` on success
/// - `Err(ErrorKind::Incomplete)` if there is not enough data
/// - `Err(ErrorKind::Reader)` if the reader can't borrow from the input
fn read_slice(&mut self, len: Length) -> Result<&'r [u8]>;
/// Attempt to decode an ASN.1 `CONTEXT-SPECIFIC` field with the
/// provided [`TagNumber`].
fn context_specific<T>(&mut self, tag_number: TagNumber, tag_mode: TagMode) -> Result<Option<T>>
where
T: DecodeValue<'r> + FixedTag,
{
Ok(match tag_mode {
TagMode::Explicit => ContextSpecific::<T>::decode_explicit(self, tag_number)?,
TagMode::Implicit => ContextSpecific::<T>::decode_implicit(self, tag_number)?,
}
.map(|field| field.value))
}
/// Decode a value which impls the [`Decode`] trait.
fn decode<T: Decode<'r>>(&mut self) -> Result<T> {
T::decode(self).map_err(|e| e.nested(self.position()))
}
/// Return an error with the given [`ErrorKind`], annotating it with
/// context about where the error occurred.
fn error(&mut self, kind: ErrorKind) -> Error {
kind.at(self.position())
}
/// Finish decoding, returning the given value if there is no
/// remaining data, or an error otherwise
fn finish<T>(self, value: T) -> Result<T> {
if !self.is_finished() {
Err(ErrorKind::TrailingData {
decoded: self.position(),
remaining: self.remaining_len(),
}
.at(self.position()))
} else {
Ok(value)
}
}
/// Have we read all of the input data?
fn is_finished(&self) -> bool {
self.remaining_len().is_zero()
}
/// Offset within the original input stream.
///
/// This is used for error reporting, and doesn't need to be overridden
/// by any reader implementations (except for the built-in `NestedReader`,
/// which consumes nested input messages)
fn offset(&self) -> Length {
self.position()
}
/// Peek at the next byte in the decoder and attempt to decode it as a
/// [`Tag`] value.
///
/// Does not modify the decoder's state.
fn peek_tag(&self) -> Result<Tag> {
match self.peek_byte() {
Some(byte) => byte.try_into(),
None => Err(Error::incomplete(self.input_len())),
}
}
/// Read a single byte.
fn read_byte(&mut self) -> Result<u8> {
let mut buf = [0];
self.read_into(&mut buf)?;
Ok(buf[0])
}
/// Attempt to read input data, writing it into the provided buffer, and
/// returning a slice on success.
///
/// # Returns
/// - `Ok(slice)` if there is sufficient data
/// - `Err(ErrorKind::Incomplete)` if there is not enough data
fn read_into<'o>(&mut self, buf: &'o mut [u8]) -> Result<&'o [u8]> {
let input = self.read_slice(buf.len().try_into()?)?;
buf.copy_from_slice(input);
Ok(buf)
}
/// Read nested data of the given length.
fn read_nested<'n, T, F>(&'n mut self, len: Length, f: F) -> Result<T>
where
F: FnOnce(&mut NestedReader<'n, Self>) -> Result<T>,
{
let mut reader = NestedReader::new(self, len)?;
let ret = f(&mut reader)?;
reader.finish(ret)
}
/// Read a byte vector of the given length.
#[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)?;
Ok(bytes)
}
/// Get the number of bytes still remaining in the buffer.
fn remaining_len(&self) -> Length {
debug_assert!(self.position() <= self.input_len());
self.input_len().saturating_sub(self.position())
}
/// Read an ASN.1 `SEQUENCE`, creating a nested [`Reader`] for the body and
/// calling the provided closure with it.
fn sequence<'n, F, T>(&'n mut self, f: F) -> Result<T>
where
F: FnOnce(&mut NestedReader<'n, Self>) -> Result<T>,
{
let header = Header::decode(self)?;
header.tag.assert_eq(Tag::Sequence)?;
self.read_nested(header.length, f)
}
/// Obtain a slice of bytes contain a complete TLV production suitable for parsing later.
fn tlv_bytes(&mut self) -> Result<&'r [u8]> {
let header = self.peek_header()?;
let header_len = header.encoded_len()?;
self.read_slice((header_len + header.length)?)
}
}

96
vendor/der/src/reader/nested.rs vendored Normal file
View File

@@ -0,0 +1,96 @@
//! Reader type for consuming nested TLV records within a DER document.
use crate::{reader::Reader, Error, ErrorKind, Header, Length, Result};
/// Reader type used by [`Reader::read_nested`].
pub struct NestedReader<'i, R> {
/// Inner reader type.
inner: &'i mut R,
/// Nested input length.
input_len: Length,
/// Position within the nested input.
position: Length,
}
impl<'i, 'r, R: Reader<'r>> NestedReader<'i, R> {
/// Create a new nested reader which can read the given [`Length`].
pub(crate) fn new(inner: &'i mut R, len: Length) -> Result<Self> {
if len <= inner.remaining_len() {
Ok(Self {
inner,
input_len: len,
position: Length::ZERO,
})
} else {
Err(ErrorKind::Incomplete {
expected_len: (inner.offset() + len)?,
actual_len: (inner.offset() + inner.remaining_len())?,
}
.at(inner.offset()))
}
}
/// Move the position cursor the given length, returning an error if there
/// isn't enough remaining data in the nested input.
fn advance_position(&mut self, len: Length) -> Result<()> {
let new_position = (self.position + len)?;
if new_position <= self.input_len {
self.position = new_position;
Ok(())
} else {
Err(ErrorKind::Incomplete {
expected_len: (self.inner.offset() + len)?,
actual_len: (self.inner.offset() + self.remaining_len())?,
}
.at(self.inner.offset()))
}
}
}
impl<'i, 'r, R: Reader<'r>> Reader<'r> for NestedReader<'i, R> {
fn input_len(&self) -> Length {
self.input_len
}
fn peek_byte(&self) -> Option<u8> {
if self.is_finished() {
None
} else {
self.inner.peek_byte()
}
}
fn peek_header(&self) -> Result<Header> {
if self.is_finished() {
Err(Error::incomplete(self.offset()))
} else {
// TODO(tarcieri): handle peeking past nested length
self.inner.peek_header()
}
}
fn position(&self) -> Length {
self.position
}
fn read_slice(&mut self, len: Length) -> Result<&'r [u8]> {
self.advance_position(len)?;
self.inner.read_slice(len)
}
fn error(&mut self, kind: ErrorKind) -> Error {
self.inner.error(kind)
}
fn offset(&self) -> Length {
self.inner.offset()
}
fn read_into<'o>(&mut self, out: &'o mut [u8]) -> Result<&'o [u8]> {
self.advance_position(Length::try_from(out.len())?)?;
self.inner.read_into(out)
}
}

206
vendor/der/src/reader/pem.rs vendored Normal file
View File

@@ -0,0 +1,206 @@
//! Streaming PEM reader.
use super::Reader;
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")]
#[derive(Clone)]
pub struct PemReader<'i> {
/// Inner PEM decoder wrapped in a BufReader.
reader: RefCell<utils::BufReader<'i>>,
/// Input length (in bytes after Base64 decoding).
input_len: Length,
/// Position in the input buffer (in bytes after Base64 decoding).
position: Length,
}
#[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 reader = utils::BufReader::new(pem)?;
let input_len = Length::try_from(reader.remaining_len())?;
Ok(Self {
reader: RefCell::new(reader),
input_len,
position: Length::ZERO,
})
}
/// Get the PEM label which will be used in the encapsulation boundaries
/// for this document.
pub fn type_label(&self) -> &'i str {
self.reader.borrow().type_label()
}
}
#[cfg(feature = "pem")]
impl<'i> Reader<'i> for PemReader<'i> {
fn input_len(&self) -> Length {
self.input_len
}
fn peek_byte(&self) -> Option<u8> {
if self.is_finished() {
None
} else {
self.reader.borrow().peek_byte()
}
}
fn peek_header(&self) -> Result<Header> {
if self.is_finished() {
Err(Error::incomplete(self.offset()))
} else {
Header::decode(&mut self.clone())
}
}
fn position(&self) -> Length {
self.position
}
fn read_slice(&mut self, _len: Length) -> Result<&'i [u8]> {
// Can't borrow from PEM because it requires decoding
Err(ErrorKind::Reader.into())
}
fn read_into<'o>(&mut self, buf: &'o mut [u8]) -> Result<&'o [u8]> {
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.reader.borrow().remaining_len())?)?
);
Ok(bytes)
}
}

214
vendor/der/src/reader/slice.rs vendored Normal file
View File

@@ -0,0 +1,214 @@
//! Slice reader.
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: BytesRef<'a>,
/// Did the decoding operation fail?
failed: bool,
/// Position within the decoded slice.
position: Length,
}
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: BytesRef::new(bytes)?,
failed: false,
position: Length::ZERO,
})
}
/// Return an error with the given [`ErrorKind`], annotating it with
/// context about where the error occurred.
pub fn error(&mut self, kind: ErrorKind) -> Error {
self.failed = true;
kind.at(self.position)
}
/// Return an error for an invalid value with the given tag.
pub fn value_error(&mut self, tag: Tag) -> Error {
self.error(tag.value_error().kind())
}
/// Did the decoding operation fail due to an error?
pub fn is_failed(&self) -> bool {
self.failed
}
/// Obtain the remaining bytes in this slice reader from the current cursor
/// position.
fn remaining(&self) -> Result<&'a [u8]> {
if self.is_failed() {
Err(ErrorKind::Failed.at(self.position))
} else {
self.bytes
.as_slice()
.get(self.position.try_into()?..)
.ok_or_else(|| Error::incomplete(self.input_len()))
}
}
}
impl<'a> Reader<'a> for SliceReader<'a> {
fn input_len(&self) -> Length {
self.bytes.len()
}
fn peek_byte(&self) -> Option<u8> {
self.remaining()
.ok()
.and_then(|bytes| bytes.first().cloned())
}
fn peek_header(&self) -> Result<Header> {
Header::decode(&mut self.clone())
}
fn position(&self) -> Length {
self.position
}
fn read_slice(&mut self, len: Length) -> Result<&'a [u8]> {
if self.is_failed() {
return Err(self.error(ErrorKind::Failed));
}
match self.remaining()?.get(..len.try_into()?) {
Some(result) => {
self.position = (self.position + len)?;
Ok(result)
}
None => Err(self.error(ErrorKind::Incomplete {
expected_len: (self.position + len)?,
actual_len: self.input_len(),
})),
}
}
fn decode<T: Decode<'a>>(&mut self) -> Result<T> {
if self.is_failed() {
return Err(self.error(ErrorKind::Failed));
}
T::decode(self).map_err(|e| {
self.failed = true;
e.nested(self.position)
})
}
fn error(&mut self, kind: ErrorKind) -> Error {
self.failed = true;
kind.at(self.position)
}
fn finish<T>(self, value: T) -> Result<T> {
if self.is_failed() {
Err(ErrorKind::Failed.at(self.position))
} else if !self.is_finished() {
Err(ErrorKind::TrailingData {
decoded: self.position,
remaining: self.remaining_len(),
}
.at(self.position))
} else {
Ok(value)
}
}
fn remaining_len(&self) -> Length {
debug_assert!(self.position <= self.input_len());
self.input_len().saturating_sub(self.position)
}
}
#[cfg(test)]
mod tests {
use super::SliceReader;
use crate::{Decode, ErrorKind, Length, Reader, Tag};
use hex_literal::hex;
// INTEGER: 42
const EXAMPLE_MSG: &[u8] = &hex!("02012A00");
#[test]
fn empty_message() {
let mut reader = SliceReader::new(&[]).unwrap();
let err = bool::decode(&mut reader).err().unwrap();
assert_eq!(Some(Length::ZERO), err.position());
match err.kind() {
ErrorKind::Incomplete {
expected_len,
actual_len,
} => {
assert_eq!(actual_len, 0u8.into());
assert_eq!(expected_len, 1u8.into());
}
other => panic!("unexpected error kind: {:?}", other),
}
}
#[test]
fn invalid_field_length() {
const MSG_LEN: usize = 2;
let mut reader = SliceReader::new(&EXAMPLE_MSG[..MSG_LEN]).unwrap();
let err = i8::decode(&mut reader).err().unwrap();
assert_eq!(Some(Length::from(2u8)), err.position());
match err.kind() {
ErrorKind::Incomplete {
expected_len,
actual_len,
} => {
assert_eq!(actual_len, MSG_LEN.try_into().unwrap());
assert_eq!(expected_len, (MSG_LEN + 1).try_into().unwrap());
}
other => panic!("unexpected error kind: {:?}", other),
}
}
#[test]
fn trailing_data() {
let mut reader = SliceReader::new(EXAMPLE_MSG).unwrap();
let x = i8::decode(&mut reader).unwrap();
assert_eq!(42i8, x);
let err = reader.finish(x).err().unwrap();
assert_eq!(Some(Length::from(3u8)), err.position());
assert_eq!(
ErrorKind::TrailingData {
decoded: 3u8.into(),
remaining: 1u8.into()
},
err.kind()
);
}
#[test]
fn peek_tag() {
let reader = SliceReader::new(EXAMPLE_MSG).unwrap();
assert_eq!(reader.position(), Length::ZERO);
assert_eq!(reader.peek_tag().unwrap(), Tag::Integer);
assert_eq!(reader.position(), Length::ZERO); // Position unchanged
}
#[test]
fn peek_header() {
let reader = SliceReader::new(EXAMPLE_MSG).unwrap();
assert_eq!(reader.position(), Length::ZERO);
let header = reader.peek_header().unwrap();
assert_eq!(header.tag, Tag::Integer);
assert_eq!(header.length, Length::ONE);
assert_eq!(reader.position(), Length::ZERO); // Position unchanged
}
}

69
vendor/der/src/referenced.rs vendored Normal file
View File

@@ -0,0 +1,69 @@
//! 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())
}
}
#[cfg(feature = "alloc")]
mod allocating {
use super::{OwnedToRef, RefToOwned};
use alloc::boxed::Box;
impl<'a> RefToOwned<'a> for &'a [u8] {
type Owned = Box<[u8]>;
fn ref_to_owned(&self) -> Self::Owned {
Box::from(*self)
}
}
impl OwnedToRef for Box<[u8]> {
type Borrowed<'a> = &'a [u8];
fn owned_to_ref(&self) -> Self::Borrowed<'_> {
self.as_ref()
}
}
}

104
vendor/der/src/str_owned.rs vendored Normal file
View File

@@ -0,0 +1,104 @@
//! 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: String) -> Result<Self> {
let length = Length::try_from(s.as_bytes().len())?;
Ok(Self { inner: s, length })
}
/// 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(),
}
}
}

92
vendor/der/src/str_ref.rs vendored Normal file
View File

@@ -0,0 +1,92 @@
//! Common handling for types backed by `str` slices with enforcement of a
//! library-level length limitation i.e. `Length::max()`.
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 StrRef<'a> {
/// Inner value
pub(crate) inner: &'a str,
/// Precomputed `Length` (avoids possible panicking conversions)
pub(crate) length: Length,
}
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 {
inner: s,
length: Length::try_from(s.as_bytes().len())?,
})
}
/// Parse a [`StrRef`] from UTF-8 encoded bytes.
pub fn from_bytes(bytes: &'a [u8]) -> Result<Self> {
Self::new(str::from_utf8(bytes)?)
}
/// Borrow the inner `str`
pub fn as_str(&self) -> &'a str {
self.inner
}
/// Borrow the inner byte slice
pub fn as_bytes(&self) -> &'a [u8] {
self.inner.as_bytes()
}
/// Get the [`Length`] of this [`StrRef`]
pub fn len(self) -> Length {
self.length
}
/// Is this [`StrRef`] empty?
pub fn is_empty(self) -> bool {
self.len() == Length::ZERO
}
}
impl AsRef<str> for StrRef<'_> {
fn as_ref(&self) -> &str {
self.as_str()
}
}
impl AsRef<[u8]> for StrRef<'_> {
fn as_ref(&self) -> &[u8] {
self.as_bytes()
}
}
impl<'a> DecodeValue<'a> for StrRef<'a> {
fn decode_value<R: Reader<'a>>(reader: &mut R, header: Header) -> Result<Self> {
Self::from_bytes(BytesRef::decode_value(reader, header)?.as_slice())
}
}
impl<'a> EncodeValue for StrRef<'a> {
fn value_len(&self) -> Result<Length> {
Ok(self.length)
}
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)
}
}
}

460
vendor/der/src/tag.rs vendored Normal file
View File

@@ -0,0 +1,460 @@
//! ASN.1 tags.
#![cfg_attr(feature = "arbitrary", allow(clippy::integer_arithmetic))]
mod class;
mod mode;
mod number;
pub use self::{class::Class, mode::TagMode, number::TagNumber};
use crate::{Decode, DerOrd, Encode, Error, ErrorKind, Length, Reader, Result, Writer};
use core::{cmp::Ordering, fmt};
/// Indicator bit for constructed form encoding (i.e. vs primitive form)
const CONSTRUCTED_FLAG: u8 = 0b100000;
/// Types which have a constant ASN.1 [`Tag`].
pub trait FixedTag {
/// ASN.1 tag
const TAG: Tag;
}
/// Types which have an ASN.1 [`Tag`].
pub trait Tagged {
/// Get the ASN.1 tag that this type is encoded with.
fn tag(&self) -> Tag;
}
/// Types which are [`FixedTag`] always have a known [`Tag`] type.
impl<T: FixedTag> Tagged for T {
fn tag(&self) -> Tag {
T::TAG
}
}
/// ASN.1 tags.
///
/// Tags are the leading identifier octet of the Tag-Length-Value encoding
/// used by ASN.1 DER and identify the type of the subsequent value.
///
/// They are described in X.690 Section 8.1.2: Identifier octets, and
/// structured as follows:
///
/// ```text
/// | Class | P/C | Tag Number |
/// ```
///
/// - 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 {
/// `BOOLEAN` tag: `1`.
Boolean,
/// `INTEGER` tag: `2`.
Integer,
/// `BIT STRING` tag: `3`.
BitString,
/// `OCTET STRING` tag: `4`.
OctetString,
/// `NULL` tag: `5`.
Null,
/// `OBJECT IDENTIFIER` tag: `6`.
ObjectIdentifier,
/// `REAL` tag: `9`.
Real,
/// `ENUMERATED` tag: `10`.
Enumerated,
/// `UTF8String` tag: `12`.
Utf8String,
/// `SEQUENCE` tag: `16`.
Sequence,
/// `SET` and `SET OF` tag: `17`.
Set,
/// `NumericString` tag: `18`.
NumericString,
/// `PrintableString` tag: `19`.
PrintableString,
/// `TeletexString` tag: `20`.
TeletexString,
/// `VideotexString` tag: `21`.
VideotexString,
/// `IA5String` tag: `22`.
Ia5String,
/// `UTCTime` tag: `23`.
UtcTime,
/// `GeneralizedTime` tag: `24`.
GeneralizedTime,
/// `VisibleString` tag: `26`.
VisibleString,
/// `BMPString` tag: `30`.
BmpString,
/// Application tag.
Application {
/// Is this tag constructed? (vs primitive).
constructed: bool,
/// Tag number.
number: TagNumber,
},
/// Context-specific tag.
ContextSpecific {
/// Is this tag constructed? (vs primitive).
constructed: bool,
/// Tag number.
number: TagNumber,
},
/// Private tag number.
Private {
/// Is this tag constructed? (vs primitive).
constructed: bool,
/// Tag number.
number: TagNumber,
},
}
impl Tag {
/// Assert that this [`Tag`] matches the provided expected tag.
///
/// On mismatch, returns an [`Error`] with [`ErrorKind::TagUnexpected`].
pub fn assert_eq(self, expected: Tag) -> Result<Tag> {
if self == expected {
Ok(self)
} else {
Err(self.unexpected_error(Some(expected)))
}
}
/// Get the [`Class`] that corresponds to this [`Tag`].
pub fn class(self) -> Class {
match self {
Tag::Application { .. } => Class::Application,
Tag::ContextSpecific { .. } => Class::ContextSpecific,
Tag::Private { .. } => Class::Private,
_ => Class::Universal,
}
}
/// Get the [`TagNumber`] (lower 6-bits) for this tag.
pub fn number(self) -> TagNumber {
TagNumber(self.octet() & TagNumber::MASK)
}
/// Does this tag represent a constructed (as opposed to primitive) field?
pub fn is_constructed(self) -> bool {
self.octet() & CONSTRUCTED_FLAG != 0
}
/// Is this an application tag?
pub fn is_application(self) -> bool {
self.class() == Class::Application
}
/// Is this a context-specific tag?
pub fn is_context_specific(self) -> bool {
self.class() == Class::ContextSpecific
}
/// Is this a private tag?
pub fn is_private(self) -> bool {
self.class() == Class::Private
}
/// Is this a universal tag?
pub fn is_universal(self) -> bool {
self.class() == Class::Universal
}
/// Get the octet encoding for this [`Tag`].
pub fn octet(self) -> u8 {
match self {
Tag::Boolean => 0x01,
Tag::Integer => 0x02,
Tag::BitString => 0x03,
Tag::OctetString => 0x04,
Tag::Null => 0x05,
Tag::ObjectIdentifier => 0x06,
Tag::Real => 0x09,
Tag::Enumerated => 0x0A,
Tag::Utf8String => 0x0C,
Tag::Sequence => 0x10 | CONSTRUCTED_FLAG,
Tag::Set => 0x11 | CONSTRUCTED_FLAG,
Tag::NumericString => 0x12,
Tag::PrintableString => 0x13,
Tag::TeletexString => 0x14,
Tag::VideotexString => 0x15,
Tag::Ia5String => 0x16,
Tag::UtcTime => 0x17,
Tag::GeneralizedTime => 0x18,
Tag::VisibleString => 0x1A,
Tag::BmpString => 0x1E,
Tag::Application {
constructed,
number,
}
| Tag::ContextSpecific {
constructed,
number,
}
| Tag::Private {
constructed,
number,
} => self.class().octet(constructed, number),
}
}
/// Create an [`Error`] for an invalid [`Length`].
pub fn length_error(self) -> Error {
ErrorKind::Length { tag: self }.into()
}
/// Create an [`Error`] for an non-canonical value with the ASN.1 type
/// identified by this tag.
pub fn non_canonical_error(self) -> Error {
ErrorKind::Noncanonical { tag: self }.into()
}
/// Create an [`Error`] because the current tag was unexpected, with an
/// optional expected tag.
pub fn unexpected_error(self, expected: Option<Self>) -> Error {
ErrorKind::TagUnexpected {
expected,
actual: self,
}
.into()
}
/// Create an [`Error`] for an invalid value with the ASN.1 type identified
/// by this tag.
pub fn value_error(self) -> Error {
ErrorKind::Value { tag: self }.into()
}
}
impl TryFrom<u8> for Tag {
type Error = Error;
fn try_from(byte: u8) -> Result<Tag> {
let constructed = byte & CONSTRUCTED_FLAG != 0;
let number = TagNumber::try_from(byte & TagNumber::MASK)?;
match byte {
0x01 => Ok(Tag::Boolean),
0x02 => Ok(Tag::Integer),
0x03 => Ok(Tag::BitString),
0x04 => Ok(Tag::OctetString),
0x05 => Ok(Tag::Null),
0x06 => Ok(Tag::ObjectIdentifier),
0x09 => Ok(Tag::Real),
0x0A => Ok(Tag::Enumerated),
0x0C => Ok(Tag::Utf8String),
0x12 => Ok(Tag::NumericString),
0x13 => Ok(Tag::PrintableString),
0x14 => Ok(Tag::TeletexString),
0x15 => Ok(Tag::VideotexString),
0x16 => Ok(Tag::Ia5String),
0x17 => Ok(Tag::UtcTime),
0x18 => Ok(Tag::GeneralizedTime),
0x1A => Ok(Tag::VisibleString),
0x1E => Ok(Tag::BmpString),
0x30 => Ok(Tag::Sequence), // constructed
0x31 => Ok(Tag::Set), // constructed
0x40..=0x7E => Ok(Tag::Application {
constructed,
number,
}),
0x80..=0xBE => Ok(Tag::ContextSpecific {
constructed,
number,
}),
0xC0..=0xFE => Ok(Tag::Private {
constructed,
number,
}),
_ => Err(ErrorKind::TagUnknown { byte }.into()),
}
}
}
impl From<Tag> for u8 {
fn from(tag: Tag) -> u8 {
tag.octet()
}
}
impl From<&Tag> for u8 {
fn from(tag: &Tag) -> u8 {
u8::from(*tag)
}
}
impl<'a> Decode<'a> for Tag {
fn decode<R: Reader<'a>>(reader: &mut R) -> Result<Self> {
reader.read_byte().and_then(Self::try_from)
}
}
impl Encode for Tag {
fn encoded_len(&self) -> Result<Length> {
Ok(Length::ONE)
}
fn encode(&self, writer: &mut impl Writer) -> Result<()> {
writer.write_byte(self.into())
}
}
impl DerOrd for Tag {
fn der_cmp(&self, other: &Self) -> Result<Ordering> {
Ok(self.octet().cmp(&other.octet()))
}
}
impl fmt::Display for Tag {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
const FIELD_TYPE: [&str; 2] = ["primitive", "constructed"];
match *self {
Tag::Boolean => f.write_str("BOOLEAN"),
Tag::Integer => f.write_str("INTEGER"),
Tag::BitString => f.write_str("BIT STRING"),
Tag::OctetString => f.write_str("OCTET STRING"),
Tag::Null => f.write_str("NULL"),
Tag::ObjectIdentifier => f.write_str("OBJECT IDENTIFIER"),
Tag::Real => f.write_str("REAL"),
Tag::Enumerated => f.write_str("ENUMERATED"),
Tag::Utf8String => f.write_str("UTF8String"),
Tag::Set => f.write_str("SET"),
Tag::NumericString => f.write_str("NumericString"),
Tag::PrintableString => f.write_str("PrintableString"),
Tag::TeletexString => f.write_str("TeletexString"),
Tag::VideotexString => f.write_str("VideotexString"),
Tag::Ia5String => f.write_str("IA5String"),
Tag::UtcTime => f.write_str("UTCTime"),
Tag::GeneralizedTime => f.write_str("GeneralizedTime"),
Tag::VisibleString => f.write_str("VisibleString"),
Tag::BmpString => f.write_str("BMPString"),
Tag::Sequence => f.write_str("SEQUENCE"),
Tag::Application {
constructed,
number,
} => write!(
f,
"APPLICATION [{}] ({})",
number,
FIELD_TYPE[usize::from(constructed)]
),
Tag::ContextSpecific {
constructed,
number,
} => write!(
f,
"CONTEXT-SPECIFIC [{}] ({})",
number,
FIELD_TYPE[usize::from(constructed)]
),
Tag::Private {
constructed,
number,
} => write!(
f,
"PRIVATE [{}] ({})",
number,
FIELD_TYPE[usize::from(constructed)]
),
}
}
}
impl fmt::Debug for Tag {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "Tag(0x{:02x}: {})", u8::from(*self), self)
}
}
#[cfg(test)]
mod tests {
use super::TagNumber;
use super::{Class, Tag};
#[test]
fn tag_class() {
assert_eq!(Tag::Boolean.class(), Class::Universal);
assert_eq!(Tag::Integer.class(), Class::Universal);
assert_eq!(Tag::BitString.class(), Class::Universal);
assert_eq!(Tag::OctetString.class(), Class::Universal);
assert_eq!(Tag::Null.class(), Class::Universal);
assert_eq!(Tag::ObjectIdentifier.class(), Class::Universal);
assert_eq!(Tag::Real.class(), Class::Universal);
assert_eq!(Tag::Enumerated.class(), Class::Universal);
assert_eq!(Tag::Utf8String.class(), Class::Universal);
assert_eq!(Tag::Set.class(), Class::Universal);
assert_eq!(Tag::NumericString.class(), Class::Universal);
assert_eq!(Tag::PrintableString.class(), Class::Universal);
assert_eq!(Tag::TeletexString.class(), Class::Universal);
assert_eq!(Tag::VideotexString.class(), Class::Universal);
assert_eq!(Tag::Ia5String.class(), Class::Universal);
assert_eq!(Tag::UtcTime.class(), Class::Universal);
assert_eq!(Tag::GeneralizedTime.class(), Class::Universal);
assert_eq!(Tag::Sequence.class(), Class::Universal);
for num in 0..=30 {
for &constructed in &[false, true] {
let number = TagNumber::new(num);
assert_eq!(
Tag::Application {
constructed,
number
}
.class(),
Class::Application
);
assert_eq!(
Tag::ContextSpecific {
constructed,
number
}
.class(),
Class::ContextSpecific
);
assert_eq!(
Tag::Private {
constructed,
number
}
.class(),
Class::Private
);
}
}
}
}

50
vendor/der/src/tag/class.rs vendored Normal file
View File

@@ -0,0 +1,50 @@
//! Class of an ASN.1 tag.
use super::{TagNumber, CONSTRUCTED_FLAG};
use core::fmt;
/// Class of an ASN.1 tag.
#[derive(Copy, Clone, Debug, Eq, PartialEq, PartialOrd, Ord)]
#[repr(u8)]
pub enum Class {
/// `UNIVERSAL`: built-in types whose meaning is the same in all
/// applications.
Universal = 0b00000000,
/// `APPLICATION`: types whose meaning is specific to an application,
///
/// Types in two different applications may have the same
/// application-specific tag and different meanings.
Application = 0b01000000,
/// `CONTEXT-SPECIFIC`: types whose meaning is specific to a given
/// structured type.
///
/// Context-specific tags are used to distinguish between component types
/// with the same underlying tag within the context of a given structured
/// type, and component types in two different structured types may have
/// the same tag and different meanings.
ContextSpecific = 0b10000000,
/// `PRIVATE`: types whose meaning is specific to a given enterprise.
Private = 0b11000000,
}
impl Class {
/// Compute the identifier octet for a tag number of this class.
#[allow(clippy::integer_arithmetic)]
pub(super) fn octet(self, constructed: bool, number: TagNumber) -> u8 {
self as u8 | number.value() | (u8::from(constructed) * CONSTRUCTED_FLAG)
}
}
impl fmt::Display for Class {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.write_str(match self {
Class::Universal => "UNIVERSAL",
Class::Application => "APPLICATION",
Class::ContextSpecific => "CONTEXT-SPECIFIC",
Class::Private => "PRIVATE",
})
}
}

40
vendor/der/src/tag/mode.rs vendored Normal file
View File

@@ -0,0 +1,40 @@
//! Tag modes.
use crate::{Error, ErrorKind, Result};
use core::{fmt, str::FromStr};
/// Tagging modes: `EXPLICIT` versus `IMPLICIT`.
#[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.
///
/// Tag replaces the existing tag of the inner type.
Implicit,
}
impl FromStr for TagMode {
type Err = Error;
fn from_str(s: &str) -> Result<Self> {
match s {
"EXPLICIT" | "explicit" => Ok(TagMode::Explicit),
"IMPLICIT" | "implicit" => Ok(TagMode::Implicit),
_ => Err(ErrorKind::TagModeUnknown.into()),
}
}
}
impl fmt::Display for TagMode {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
TagMode::Explicit => f.write_str("EXPLICIT"),
TagMode::Implicit => f.write_str("IMPLICIT"),
}
}
}

201
vendor/der/src/tag/number.rs vendored Normal file
View File

@@ -0,0 +1,201 @@
//! ASN.1 tag numbers
use super::Tag;
use crate::{Error, ErrorKind, Result};
use core::fmt;
/// ASN.1 tag numbers (i.e. lower 5 bits of a [`Tag`]).
///
/// From X.690 Section 8.1.2.2:
///
/// > bits 5 to 1 shall encode the number of the tag as a binary integer with
/// > bit 5 as the most significant bit.
///
/// This library supports tag numbers ranging from zero to 30 (inclusive),
/// which can be represented as a single identifier octet.
///
/// Section 8.1.2.4 describes how to support multi-byte tag numbers, which are
/// encoded by using a leading tag number of 31 (`0b11111`). This library
/// deliberately does not support this: tag numbers greater than 30 are
/// disallowed.
#[derive(Copy, Clone, Debug, Eq, PartialEq, PartialOrd, Ord)]
pub struct TagNumber(pub(super) u8);
impl TagNumber {
/// Tag number `0`
pub const N0: Self = Self(0);
/// Tag number `1`
pub const N1: Self = Self(1);
/// Tag number `2`
pub const N2: Self = Self(2);
/// Tag number `3`
pub const N3: Self = Self(3);
/// Tag number `4`
pub const N4: Self = Self(4);
/// Tag number `5`
pub const N5: Self = Self(5);
/// Tag number `6`
pub const N6: Self = Self(6);
/// Tag number `7`
pub const N7: Self = Self(7);
/// Tag number `8`
pub const N8: Self = Self(8);
/// Tag number `9`
pub const N9: Self = Self(9);
/// Tag number `10`
pub const N10: Self = Self(10);
/// Tag number `11`
pub const N11: Self = Self(11);
/// Tag number `12`
pub const N12: Self = Self(12);
/// Tag number `13`
pub const N13: Self = Self(13);
/// Tag number `14`
pub const N14: Self = Self(14);
/// Tag number `15`
pub const N15: Self = Self(15);
/// Tag number `16`
pub const N16: Self = Self(16);
/// Tag number `17`
pub const N17: Self = Self(17);
/// Tag number `18`
pub const N18: Self = Self(18);
/// Tag number `19`
pub const N19: Self = Self(19);
/// Tag number `20`
pub const N20: Self = Self(20);
/// Tag number `21`
pub const N21: Self = Self(21);
/// Tag number `22`
pub const N22: Self = Self(22);
/// Tag number `23`
pub const N23: Self = Self(23);
/// Tag number `24`
pub const N24: Self = Self(24);
/// Tag number `25`
pub const N25: Self = Self(25);
/// Tag number `26`
pub const N26: Self = Self(26);
/// Tag number `27`
pub const N27: Self = Self(27);
/// Tag number `28`
pub const N28: Self = Self(28);
/// Tag number `29`
pub const N29: Self = Self(29);
/// Tag number `30`
pub const N30: Self = Self(30);
/// Mask value used to obtain the tag number from a tag octet.
pub(super) const MASK: u8 = 0b11111;
/// Maximum tag number supported (inclusive).
const MAX: u8 = 30;
/// Create a new tag number (const-friendly).
///
/// Panics if the tag number is greater than `30`.
/// For a fallible conversion, use [`TryFrom`] instead.
pub const fn new(byte: u8) -> Self {
#[allow(clippy::panic)]
if byte > Self::MAX {
panic!("tag number out of range");
}
Self(byte)
}
/// Create an `APPLICATION` tag with this tag number.
pub fn application(self, constructed: bool) -> Tag {
Tag::Application {
constructed,
number: self,
}
}
/// Create a `CONTEXT-SPECIFIC` tag with this tag number.
pub fn context_specific(self, constructed: bool) -> Tag {
Tag::ContextSpecific {
constructed,
number: self,
}
}
/// Create a `PRIVATE` tag with this tag number.
pub fn private(self, constructed: bool) -> Tag {
Tag::Private {
constructed,
number: self,
}
}
/// Get the inner value.
pub fn value(self) -> u8 {
self.0
}
}
impl TryFrom<u8> for TagNumber {
type Error = Error;
fn try_from(byte: u8) -> Result<Self> {
match byte {
0..=Self::MAX => Ok(Self(byte)),
_ => Err(ErrorKind::TagNumberInvalid.into()),
}
}
}
impl From<TagNumber> for u8 {
fn from(tag_number: TagNumber) -> u8 {
tag_number.0
}
}
impl fmt::Display for TagNumber {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
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)
}
}

29
vendor/der/src/writer.rs vendored Normal file
View File

@@ -0,0 +1,29 @@
//! Writer trait.
#[cfg(feature = "pem")]
pub(crate) mod pem;
pub(crate) mod slice;
use crate::Result;
#[cfg(feature = "std")]
use std::io;
/// Writer trait which outputs encoded DER.
pub trait Writer {
/// Write the given DER-encoded bytes as output.
fn write(&mut self, slice: &[u8]) -> Result<()>;
/// Write a single byte.
fn write_byte(&mut self, byte: u8) -> Result<()> {
self.write(&[byte])
}
}
#[cfg(feature = "std")]
impl<W: io::Write> Writer for W {
fn write(&mut self, slice: &[u8]) -> Result<()> {
<Self as io::Write>::write(self, slice)?;
Ok(())
}
}

41
vendor/der/src/writer/pem.rs vendored Normal file
View File

@@ -0,0 +1,41 @@
//! Streaming PEM writer.
use super::Writer;
use crate::Result;
use pem_rfc7468::{Encoder, LineEnding};
/// `Writer` type which outputs PEM-encoded data.
pub struct PemWriter<'w>(Encoder<'static, 'w>);
impl<'w> PemWriter<'w> {
/// Create a new PEM writer which outputs into the provided buffer.
///
/// Uses the default 64-character line wrapping.
pub fn new(
type_label: &'static str,
line_ending: LineEnding,
out: &'w mut [u8],
) -> Result<Self> {
Ok(Self(Encoder::new(type_label, line_ending, out)?))
}
/// Get the PEM label which will be used in the encapsulation boundaries
/// for this document.
pub fn type_label(&self) -> &'static str {
self.0.type_label()
}
/// Finish encoding PEM, writing the post-encapsulation boundary.
///
/// On success, returns the total number of bytes written to the output buffer.
pub fn finish(self) -> Result<usize> {
Ok(self.0.finish()?)
}
}
impl Writer for PemWriter<'_> {
fn write(&mut self, slice: &[u8]) -> Result<()> {
self.0.encode(slice)?;
Ok(())
}
}

149
vendor/der/src/writer/slice.rs vendored Normal file
View File

@@ -0,0 +1,149 @@
//! Slice writer.
use crate::{
asn1::*, Encode, EncodeValue, ErrorKind, Header, Length, Result, Tag, TagMode, TagNumber,
Tagged, Writer,
};
/// [`Writer`] which encodes DER into a mutable output byte slice.
#[derive(Debug)]
pub struct SliceWriter<'a> {
/// Buffer into which DER-encoded message is written
bytes: &'a mut [u8],
/// Has the encoding operation failed?
failed: bool,
/// Total number of bytes written to buffer so far
position: Length,
}
impl<'a> SliceWriter<'a> {
/// Create a new encoder with the given byte slice as a backing buffer.
pub fn new(bytes: &'a mut [u8]) -> Self {
Self {
bytes,
failed: false,
position: Length::ZERO,
}
}
/// Encode a value which impls the [`Encode`] trait.
pub fn encode<T: Encode>(&mut self, encodable: &T) -> Result<()> {
if self.is_failed() {
self.error(ErrorKind::Failed)?
}
encodable.encode(self).map_err(|e| {
self.failed = true;
e.nested(self.position)
})
}
/// Return an error with the given [`ErrorKind`], annotating it with
/// context about where the error occurred.
pub fn error<T>(&mut self, kind: ErrorKind) -> Result<T> {
self.failed = true;
Err(kind.at(self.position))
}
/// Did the decoding operation fail due to an error?
pub fn is_failed(&self) -> bool {
self.failed
}
/// Finish encoding to the buffer, returning a slice containing the data
/// written to the buffer.
pub fn finish(self) -> Result<&'a [u8]> {
let position = self.position;
if self.is_failed() {
return Err(ErrorKind::Failed.at(position));
}
self.bytes
.get(..usize::try_from(position)?)
.ok_or_else(|| ErrorKind::Overlength.at(position))
}
/// Encode a `CONTEXT-SPECIFIC` field with the provided tag number and mode.
pub fn context_specific<T>(
&mut self,
tag_number: TagNumber,
tag_mode: TagMode,
value: &T,
) -> Result<()>
where
T: EncodeValue + Tagged,
{
ContextSpecificRef {
tag_number,
tag_mode,
value,
}
.encode(self)
}
/// Encode an ASN.1 `SEQUENCE` of the given length.
///
/// Spawns a nested slice writer which is expected to be exactly the
/// specified length upon completion.
pub fn sequence<F>(&mut self, length: Length, f: F) -> Result<()>
where
F: FnOnce(&mut SliceWriter<'_>) -> Result<()>,
{
Header::new(Tag::Sequence, length).and_then(|header| header.encode(self))?;
let mut nested_encoder = SliceWriter::new(self.reserve(length)?);
f(&mut nested_encoder)?;
if nested_encoder.finish()?.len() == usize::try_from(length)? {
Ok(())
} else {
self.error(ErrorKind::Length { tag: Tag::Sequence })
}
}
/// Reserve a portion of the internal buffer, updating the internal cursor
/// position and returning a mutable slice.
fn reserve(&mut self, len: impl TryInto<Length>) -> Result<&mut [u8]> {
if self.is_failed() {
return Err(ErrorKind::Failed.at(self.position));
}
let len = len
.try_into()
.or_else(|_| self.error(ErrorKind::Overflow))?;
let end = (self.position + len).or_else(|e| self.error(e.kind()))?;
let slice = self
.bytes
.get_mut(self.position.try_into()?..end.try_into()?)
.ok_or_else(|| ErrorKind::Overlength.at(end))?;
self.position = end;
Ok(slice)
}
}
impl<'a> Writer for SliceWriter<'a> {
fn write(&mut self, slice: &[u8]) -> Result<()> {
self.reserve(slice.len())?.copy_from_slice(slice);
Ok(())
}
}
#[cfg(test)]
mod tests {
use super::SliceWriter;
use crate::{Encode, ErrorKind, Length};
#[test]
fn overlength_message() {
let mut buffer = [];
let mut writer = SliceWriter::new(&mut buffer);
let err = false.encode(&mut writer).err().unwrap();
assert_eq!(err.kind(), ErrorKind::Overlength);
assert_eq!(err.position(), Some(Length::ONE));
}
}