diff --git a/der/derive/src/choice.rs b/der/derive/src/choice.rs index 362145de6..51c44163d 100644 --- a/der/derive/src/choice.rs +++ b/der/derive/src/choice.rs @@ -109,7 +109,7 @@ impl DeriveChoice { } impl<#lt_params> ::der::EncodeValue for #ident<#lt_params> { - fn encode_value(&self, encoder: &mut ::der::Encoder<'_>) -> ::der::Result<()> { + fn encode_value(&self, encoder: &mut dyn ::der::Writer) -> ::der::Result<()> { match self { #(#encode_body)* } diff --git a/der/derive/src/enumerated.rs b/der/derive/src/enumerated.rs index 602c5b689..a6db802fe 100644 --- a/der/derive/src/enumerated.rs +++ b/der/derive/src/enumerated.rs @@ -129,7 +129,7 @@ impl DeriveEnumerated { ::der::EncodeValue::value_len(&(*self as #repr)) } - fn encode_value(&self, encoder: &mut ::der::Encoder<'_>) -> ::der::Result<()> { + fn encode_value(&self, encoder: &mut dyn ::der::Writer) -> ::der::Result<()> { ::der::EncodeValue::encode_value(&(*self as #repr), encoder) } } diff --git a/der/derive/src/newtype.rs b/der/derive/src/newtype.rs index 921ee7137..3f5beab51 100644 --- a/der/derive/src/newtype.rs +++ b/der/derive/src/newtype.rs @@ -103,7 +103,7 @@ impl DeriveNewtype { } #limpl ::der::EncodeValue for #ltype { - fn encode_value(&self, encoder: &mut ::der::Encoder<'_>) -> ::der::Result<()> { + fn encode_value(&self, encoder: &mut dyn ::der::Writer) -> ::der::Result<()> { self.0.encode_value(encoder) } diff --git a/der/src/asn1/any.rs b/der/src/asn1/any.rs index 61836ddcb..491cd84cf 100644 --- a/der/src/asn1/any.rs +++ b/der/src/asn1/any.rs @@ -1,7 +1,7 @@ //! ASN.1 `ANY` type. use crate::{ - asn1::*, ByteSlice, Choice, Decode, DecodeValue, Decoder, DerOrd, EncodeValue, Encoder, Error, + asn1::*, ByteSlice, Choice, Decode, DecodeValue, Decoder, DerOrd, EncodeValue, Error, ErrorKind, FixedTag, Header, Length, Result, Tag, Tagged, ValueOrd, Writer, }; use core::cmp::Ordering; @@ -167,8 +167,8 @@ impl EncodeValue for Any<'_> { Ok(self.value.len()) } - fn encode_value(&self, encoder: &mut Encoder<'_>) -> Result<()> { - encoder.write(self.value()) + fn encode_value(&self, writer: &mut dyn Writer) -> Result<()> { + writer.write(self.value()) } } diff --git a/der/src/asn1/bit_string.rs b/der/src/asn1/bit_string.rs index d514ce7c4..b8372ddb6 100644 --- a/der/src/asn1/bit_string.rs +++ b/der/src/asn1/bit_string.rs @@ -1,8 +1,8 @@ //! ASN.1 `BIT STRING` support. use crate::{ - asn1::Any, ByteSlice, DecodeValue, Decoder, DerOrd, EncodeValue, Encoder, Error, ErrorKind, - FixedTag, Header, Length, Reader, Result, Tag, ValueOrd, Writer, + asn1::Any, ByteSlice, DecodeValue, Decoder, DerOrd, EncodeValue, Error, ErrorKind, FixedTag, + Header, Length, Reader, Result, Tag, ValueOrd, Writer, }; use core::{cmp::Ordering, iter::FusedIterator}; @@ -133,9 +133,9 @@ impl EncodeValue for BitString<'_> { self.byte_len() + Length::ONE } - fn encode_value(&self, encoder: &mut Encoder<'_>) -> Result<()> { - encoder.write_byte(self.unused_bits)?; - encoder.write(self.raw_bytes()) + fn encode_value(&self, writer: &mut dyn Writer) -> Result<()> { + writer.write_byte(self.unused_bits)?; + writer.write(self.raw_bytes()) } } @@ -290,10 +290,10 @@ where BitString::new((lead % 8) as u8, buff)?.value_len() } - fn encode_value(&self, encoder: &mut Encoder<'_>) -> Result<()> { + fn encode_value(&self, writer: &mut dyn Writer) -> Result<()> { let (lead, buff) = encode_flagset(self); let buff = &buff[..buff.len() - lead / 8]; - BitString::new((lead % 8) as u8, buff)?.encode_value(encoder) + BitString::new((lead % 8) as u8, buff)?.encode_value(writer) } } diff --git a/der/src/asn1/boolean.rs b/der/src/asn1/boolean.rs index a1a52cbc0..0bc16a53f 100644 --- a/der/src/asn1/boolean.rs +++ b/der/src/asn1/boolean.rs @@ -1,8 +1,8 @@ //! ASN.1 `BOOLEAN` support. use crate::{ - asn1::Any, ord::OrdIsValueOrd, ByteSlice, DecodeValue, Decoder, EncodeValue, Encoder, Error, - ErrorKind, FixedTag, Header, Length, Reader, Result, Tag, Writer, + asn1::Any, ord::OrdIsValueOrd, ByteSlice, DecodeValue, Decoder, EncodeValue, Error, ErrorKind, + FixedTag, Header, Length, Reader, Result, Tag, Writer, }; /// Byte used to encode `true` in ASN.1 DER. From X.690 Section 11.1: @@ -33,8 +33,8 @@ impl EncodeValue for bool { Ok(Length::ONE) } - fn encode_value(&self, encoder: &mut Encoder<'_>) -> Result<()> { - encoder.write_byte(if *self { TRUE_OCTET } else { FALSE_OCTET }) + fn encode_value(&self, writer: &mut dyn Writer) -> Result<()> { + writer.write_byte(if *self { TRUE_OCTET } else { FALSE_OCTET }) } } diff --git a/der/src/asn1/context_specific.rs b/der/src/asn1/context_specific.rs index fa78b68f3..dbc08045b 100644 --- a/der/src/asn1/context_specific.rs +++ b/der/src/asn1/context_specific.rs @@ -2,7 +2,7 @@ use crate::{ asn1::Any, Choice, Decode, DecodeValue, Decoder, DerOrd, Encode, EncodeValue, EncodeValueRef, - Encoder, Error, Header, Length, Reader, Result, Tag, TagMode, TagNumber, Tagged, ValueOrd, + Error, Header, Length, Reader, Result, Tag, TagMode, TagNumber, Tagged, ValueOrd, Writer, }; use core::cmp::Ordering; @@ -141,10 +141,10 @@ where } } - fn encode_value(&self, encoder: &mut Encoder<'_>) -> Result<()> { + fn encode_value(&self, writer: &mut dyn Writer) -> Result<()> { match self.tag_mode { - TagMode::Explicit => self.value.encode(encoder), - TagMode::Implicit => self.value.encode_value(encoder), + TagMode::Explicit => self.value.encode(writer), + TagMode::Implicit => self.value.encode_value(writer), } } } @@ -235,8 +235,8 @@ where self.encoder().value_len() } - fn encode_value(&self, encoder: &mut Encoder<'_>) -> Result<()> { - self.encoder().encode_value(encoder) + fn encode_value(&self, writer: &mut dyn Writer) -> Result<()> { + self.encoder().encode_value(writer) } } diff --git a/der/src/asn1/generalized_time.rs b/der/src/asn1/generalized_time.rs index 2ef8b8670..f436113e7 100644 --- a/der/src/asn1/generalized_time.rs +++ b/der/src/asn1/generalized_time.rs @@ -4,8 +4,8 @@ use crate::{ asn1::Any, datetime::{self, DateTime}, ord::OrdIsValueOrd, - ByteSlice, DecodeValue, Decoder, EncodeValue, Encoder, Error, ErrorKind, FixedTag, Header, - Length, Result, Tag, Writer, + ByteSlice, DecodeValue, Decoder, EncodeValue, Error, ErrorKind, FixedTag, Header, Length, + Result, Tag, Writer, }; use core::time::Duration; @@ -104,18 +104,18 @@ impl EncodeValue for GeneralizedTime { Ok(Self::LENGTH) } - fn encode_value(&self, encoder: &mut Encoder<'_>) -> Result<()> { + fn encode_value(&self, writer: &mut dyn 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(encoder, Self::TAG, year_hi)?; - datetime::encode_decimal(encoder, Self::TAG, year_lo)?; - datetime::encode_decimal(encoder, Self::TAG, self.0.month())?; - datetime::encode_decimal(encoder, Self::TAG, self.0.day())?; - datetime::encode_decimal(encoder, Self::TAG, self.0.hour())?; - datetime::encode_decimal(encoder, Self::TAG, self.0.minutes())?; - datetime::encode_decimal(encoder, Self::TAG, self.0.seconds())?; - encoder.write_byte(b'Z') + 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') } } @@ -174,8 +174,8 @@ impl EncodeValue for DateTime { GeneralizedTime::from(self).value_len() } - fn encode_value(&self, encoder: &mut Encoder<'_>) -> Result<()> { - GeneralizedTime::from(self).encode_value(encoder) + fn encode_value(&self, writer: &mut dyn Writer) -> Result<()> { + GeneralizedTime::from(self).encode_value(writer) } } @@ -200,8 +200,8 @@ impl EncodeValue for SystemTime { GeneralizedTime::try_from(self)?.value_len() } - fn encode_value(&self, encoder: &mut Encoder<'_>) -> Result<()> { - GeneralizedTime::try_from(self)?.encode_value(encoder) + fn encode_value(&self, writer: &mut dyn Writer) -> Result<()> { + GeneralizedTime::try_from(self)?.encode_value(writer) } } @@ -276,8 +276,8 @@ impl EncodeValue for PrimitiveDateTime { GeneralizedTime::try_from(self)?.value_len() } - fn encode_value(&self, encoder: &mut Encoder<'_>) -> Result<()> { - GeneralizedTime::try_from(self)?.encode_value(encoder) + fn encode_value(&self, writer: &mut dyn Writer) -> Result<()> { + GeneralizedTime::try_from(self)?.encode_value(writer) } } diff --git a/der/src/asn1/ia5_string.rs b/der/src/asn1/ia5_string.rs index ba5ff805a..fa8ccd015 100644 --- a/der/src/asn1/ia5_string.rs +++ b/der/src/asn1/ia5_string.rs @@ -1,8 +1,8 @@ //! ASN.1 `IA5String` support. use crate::{ - asn1::Any, ord::OrdIsValueOrd, ByteSlice, DecodeValue, Decoder, EncodeValue, Encoder, Error, - FixedTag, Header, Length, Result, StrSlice, Tag, + asn1::Any, ord::OrdIsValueOrd, ByteSlice, DecodeValue, Decoder, EncodeValue, Error, FixedTag, + Header, Length, Result, StrSlice, Tag, Writer, }; use core::{fmt, str}; @@ -84,8 +84,8 @@ impl EncodeValue for Ia5String<'_> { self.inner.value_len() } - fn encode_value(&self, encoder: &mut Encoder<'_>) -> Result<()> { - self.inner.encode_value(encoder) + fn encode_value(&self, writer: &mut dyn Writer) -> Result<()> { + self.inner.encode_value(writer) } } diff --git a/der/src/asn1/integer.rs b/der/src/asn1/integer.rs index 190d87d4d..2d0dcd51e 100644 --- a/der/src/asn1/integer.rs +++ b/der/src/asn1/integer.rs @@ -6,7 +6,7 @@ pub(super) mod uint; use crate::{ asn1::Any, ByteSlice, DecodeValue, Decoder, EncodeValue, Encoder, Error, FixedTag, Header, - Length, Result, Tag, ValueOrd, + Length, Result, Tag, ValueOrd, Writer, }; use core::{cmp::Ordering, mem}; @@ -41,11 +41,11 @@ macro_rules! impl_int_encoding { } } - fn encode_value(&self, encoder: &mut Encoder<'_>) -> Result<()> { + fn encode_value(&self, writer: &mut dyn Writer) -> Result<()> { if *self < 0 { - int::encode_bytes(encoder, &(*self as $uint).to_be_bytes()) + int::encode_bytes(writer, &(*self as $uint).to_be_bytes()) } else { - uint::encode_bytes(encoder, &self.to_be_bytes()) + uint::encode_bytes(writer, &self.to_be_bytes()) } } } @@ -93,8 +93,8 @@ macro_rules! impl_uint_encoding { uint::encoded_len(&self.to_be_bytes()) } - fn encode_value(&self, encoder: &mut Encoder<'_>) -> Result<()> { - uint::encode_bytes(encoder, &self.to_be_bytes()) + fn encode_value(&self, writer: &mut dyn Writer) -> Result<()> { + uint::encode_bytes(writer, &self.to_be_bytes()) } } diff --git a/der/src/asn1/integer/bigint.rs b/der/src/asn1/integer/bigint.rs index 22ecfb5f6..9fa81e2a1 100644 --- a/der/src/asn1/integer/bigint.rs +++ b/der/src/asn1/integer/bigint.rs @@ -2,8 +2,8 @@ use super::uint; use crate::{ - asn1::Any, ByteSlice, DecodeValue, Decoder, EncodeValue, Encoder, Error, ErrorKind, FixedTag, - Header, Length, Result, Tag, Writer, + asn1::Any, ByteSlice, DecodeValue, Decoder, EncodeValue, Error, ErrorKind, FixedTag, Header, + Length, Result, Tag, Writer, }; /// "Big" unsigned ASN.1 `INTEGER` type. @@ -64,13 +64,13 @@ impl<'a> EncodeValue for UIntBytes<'a> { uint::encoded_len(self.inner.as_slice()) } - fn encode_value(&self, encoder: &mut Encoder<'_>) -> Result<()> { + fn encode_value(&self, writer: &mut dyn Writer) -> Result<()> { // Add leading `0x00` byte if required if self.value_len()? > self.len() { - encoder.write_byte(0)?; + writer.write_byte(0)?; } - encoder.write(self.as_bytes()) + writer.write(self.as_bytes()) } } diff --git a/der/src/asn1/integer/int.rs b/der/src/asn1/integer/int.rs index bc6489bb7..a9fe43890 100644 --- a/der/src/asn1/integer/int.rs +++ b/der/src/asn1/integer/int.rs @@ -1,7 +1,7 @@ //! Support for encoding negative integers use super::is_highest_bit_set; -use crate::{Encoder, ErrorKind, Length, Result, Writer}; +use crate::{ErrorKind, Length, Result, Writer}; /// Decode an unsigned integer of the specified size. /// @@ -27,8 +27,11 @@ pub(super) fn decode_to_array(bytes: &[u8]) -> Result<[u8; N]> { } /// Encode the given big endian bytes representing an integer as ASN.1 DER. -pub(super) fn encode_bytes(encoder: &mut Encoder<'_>, bytes: &[u8]) -> Result<()> { - encoder.write(strip_leading_ones(bytes)) +pub(super) fn encode_bytes(writer: &mut W, bytes: &[u8]) -> Result<()> +where + W: Writer + ?Sized, +{ + writer.write(strip_leading_ones(bytes)) } /// Get the encoded length for the given unsigned integer serialized as bytes. diff --git a/der/src/asn1/integer/uint.rs b/der/src/asn1/integer/uint.rs index a6e0d221e..e45a72f2a 100644 --- a/der/src/asn1/integer/uint.rs +++ b/der/src/asn1/integer/uint.rs @@ -1,6 +1,6 @@ //! Unsigned integer decoders/encoders. -use crate::{Encoder, Length, Result, Tag, Writer}; +use crate::{Length, Result, Tag, Writer}; /// Decode an unsigned integer into a big endian byte slice with all leading /// zeroes removed. @@ -40,7 +40,10 @@ pub(super) fn decode_to_array(bytes: &[u8]) -> Result<[u8; N]> { } /// Encode the given big endian bytes representing an integer as ASN.1 DER. -pub(crate) fn encode_bytes(encoder: &mut Encoder<'_>, bytes: &[u8]) -> Result<()> { +pub(crate) fn encode_bytes(encoder: &mut W, bytes: &[u8]) -> Result<()> +where + W: Writer + ?Sized, +{ let bytes = strip_leading_zeroes(bytes); if needs_leading_zero(bytes) { diff --git a/der/src/asn1/null.rs b/der/src/asn1/null.rs index 65f1f7dc4..41fd3473e 100644 --- a/der/src/asn1/null.rs +++ b/der/src/asn1/null.rs @@ -1,8 +1,8 @@ //! ASN.1 `NULL` support. use crate::{ - asn1::Any, ord::OrdIsValueOrd, ByteSlice, DecodeValue, Decoder, Encode, EncodeValue, Encoder, - Error, ErrorKind, FixedTag, Header, Length, Result, Tag, + asn1::Any, ord::OrdIsValueOrd, ByteSlice, DecodeValue, Decoder, EncodeValue, Error, ErrorKind, + FixedTag, Header, Length, Result, Tag, Writer, }; /// ASN.1 `NULL` type. @@ -24,7 +24,7 @@ impl EncodeValue for Null { Ok(Length::ZERO) } - fn encode_value(&self, _encoder: &mut Encoder<'_>) -> Result<()> { + fn encode_value(&self, _writer: &mut dyn Writer) -> Result<()> { Ok(()) } } @@ -70,13 +70,13 @@ impl DecodeValue<'_> for () { } } -impl Encode for () { - fn encoded_len(&self) -> Result { - Null.encoded_len() +impl EncodeValue for () { + fn value_len(&self) -> Result { + Ok(Length::ZERO) } - fn encode(&self, encoder: &mut Encoder<'_>) -> Result<()> { - Null.encode(encoder) + fn encode_value(&self, _writer: &mut dyn Writer) -> Result<()> { + Ok(()) } } diff --git a/der/src/asn1/octet_string.rs b/der/src/asn1/octet_string.rs index 00b15bbda..670e0a19b 100644 --- a/der/src/asn1/octet_string.rs +++ b/der/src/asn1/octet_string.rs @@ -1,8 +1,8 @@ //! ASN.1 `OCTET STRING` support. use crate::{ - asn1::Any, ord::OrdIsValueOrd, ByteSlice, DecodeValue, Decoder, EncodeValue, Encoder, Error, - ErrorKind, FixedTag, Header, Length, Result, Tag, + asn1::Any, ord::OrdIsValueOrd, ByteSlice, DecodeValue, Decoder, EncodeValue, Error, ErrorKind, + FixedTag, Header, Length, Result, Tag, Writer, }; /// ASN.1 `OCTET STRING` type. @@ -54,8 +54,8 @@ impl EncodeValue for OctetString<'_> { self.inner.value_len() } - fn encode_value(&self, encoder: &mut Encoder<'_>) -> Result<()> { - self.inner.encode_value(encoder) + fn encode_value(&self, writer: &mut dyn Writer) -> Result<()> { + self.inner.encode_value(writer) } } diff --git a/der/src/asn1/oid.rs b/der/src/asn1/oid.rs index cd48442ad..d17fd2bbd 100644 --- a/der/src/asn1/oid.rs +++ b/der/src/asn1/oid.rs @@ -1,8 +1,8 @@ //! ASN.1 `OBJECT IDENTIFIER` use crate::{ - asn1::Any, ord::OrdIsValueOrd, ByteSlice, DecodeValue, Decoder, EncodeValue, Encoder, Error, - FixedTag, Header, Length, Result, Tag, Tagged, Writer, + asn1::Any, ord::OrdIsValueOrd, ByteSlice, DecodeValue, Decoder, EncodeValue, Error, FixedTag, + Header, Length, Result, Tag, Tagged, Writer, }; use const_oid::ObjectIdentifier; @@ -18,8 +18,8 @@ impl EncodeValue for ObjectIdentifier { Length::try_from(self.as_bytes().len()) } - fn encode_value(&self, encoder: &mut Encoder<'_>) -> Result<()> { - encoder.write(self.as_bytes()) + fn encode_value(&self, writer: &mut dyn Writer) -> Result<()> { + writer.write(self.as_bytes()) } } diff --git a/der/src/asn1/optional.rs b/der/src/asn1/optional.rs index 08334b354..e114a4f6a 100644 --- a/der/src/asn1/optional.rs +++ b/der/src/asn1/optional.rs @@ -1,6 +1,6 @@ //! ASN.1 `OPTIONAL` as mapped to Rust's `Option` type -use crate::{Choice, Decode, Decoder, DerOrd, Encode, Encoder, Length, Reader, Result, Tag}; +use crate::{Choice, Decode, Decoder, DerOrd, Encode, Length, Reader, Result, Tag, Writer}; use core::cmp::Ordering; impl<'a, T> Decode<'a> for Option @@ -23,14 +23,12 @@ where T: DerOrd, { fn der_cmp(&self, other: &Self) -> Result { - if let Some(a) = self { - if let Some(b) = other { - a.der_cmp(b) - } else { - Ok(Ordering::Greater) - } - } else { - Ok(Ordering::Less) + match self { + Some(a) => match other { + Some(b) => a.der_cmp(b), + None => Ok(Ordering::Greater), + }, + None => Ok(Ordering::Less), } } } @@ -43,8 +41,8 @@ where (&self).encoded_len() } - fn encode(&self, encoder: &mut Encoder<'_>) -> Result<()> { - (&self).encode(encoder) + fn encode(&self, writer: &mut dyn Writer) -> Result<()> { + (&self).encode(writer) } } @@ -53,18 +51,16 @@ where T: Encode, { fn encoded_len(&self) -> Result { - if let Some(encodable) = self { - encodable.encoded_len() - } else { - Ok(0u8.into()) + match self { + Some(encodable) => encodable.encoded_len(), + None => Ok(0u8.into()), } } - fn encode(&self, encoder: &mut Encoder<'_>) -> Result<()> { - if let Some(encodable) = self { - encodable.encode(encoder) - } else { - Ok(()) + fn encode(&self, encoder: &mut dyn Writer) -> Result<()> { + match self { + Some(encodable) => encodable.encode(encoder), + None => Ok(()), } } } diff --git a/der/src/asn1/printable_string.rs b/der/src/asn1/printable_string.rs index aa283ffdf..5e74c8b69 100644 --- a/der/src/asn1/printable_string.rs +++ b/der/src/asn1/printable_string.rs @@ -1,8 +1,8 @@ //! ASN.1 `PrintableString` support. use crate::{ - asn1::Any, ord::OrdIsValueOrd, ByteSlice, DecodeValue, Decoder, EncodeValue, Encoder, Error, - FixedTag, Header, Length, Result, StrSlice, Tag, + asn1::Any, ord::OrdIsValueOrd, ByteSlice, DecodeValue, Decoder, EncodeValue, Error, FixedTag, + Header, Length, Result, StrSlice, Tag, Writer, }; use core::{fmt, str}; @@ -117,8 +117,8 @@ impl<'a> EncodeValue for PrintableString<'a> { self.inner.value_len() } - fn encode_value(&self, encoder: &mut Encoder<'_>) -> Result<()> { - self.inner.encode_value(encoder) + fn encode_value(&self, writer: &mut dyn Writer) -> Result<()> { + self.inner.encode_value(writer) } } diff --git a/der/src/asn1/real.rs b/der/src/asn1/real.rs index 0064e7e81..63e51fe1a 100644 --- a/der/src/asn1/real.rs +++ b/der/src/asn1/real.rs @@ -8,8 +8,8 @@ )] use crate::{ - str_slice::StrSlice, ByteSlice, DecodeValue, Decoder, EncodeValue, Encoder, FixedTag, Header, - Length, Result, Tag, Writer, + str_slice::StrSlice, ByteSlice, DecodeValue, Decoder, EncodeValue, FixedTag, Header, Length, + Result, Tag, Writer, }; use super::integer::uint::strip_leading_zeroes; @@ -122,7 +122,7 @@ impl EncodeValue for f64 { } } - fn encode_value(&self, encoder: &mut Encoder<'_>) -> Result<()> { + fn encode_value(&self, writer: &mut dyn Writer) -> Result<()> { // Check if special value // Encode zero first, if it's zero // Special value from section 8.5.9 if non zero @@ -136,28 +136,30 @@ impl EncodeValue for f64 { return Ok(()); } else if self.is_nan() { // Not a number - encoder.write_byte(0b0100_0010)?; + writer.write_byte(0b0100_0010)?; } else if self.is_infinite() { if self.is_sign_negative() { // Negative infinity - encoder.write_byte(0b0100_0001)?; + writer.write_byte(0b0100_0001)?; } else { // Plus infinity - encoder.write_byte(0b0100_0000)?; + writer.write_byte(0b0100_0000)?; } } else { // Minus zero - encoder.write_byte(0b0100_0011)?; + 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 + // 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 @@ -178,17 +180,18 @@ impl EncodeValue for f64 { } } - encoder.write_byte(first_byte)?; + 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 - encoder.write(ebytes)?; + 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); - encoder.write(mbytes)?; + writer.write(mbytes)?; } + Ok(()) } } diff --git a/der/src/asn1/sequence.rs b/der/src/asn1/sequence.rs index ed364573f..8146a7e2d 100644 --- a/der/src/asn1/sequence.rs +++ b/der/src/asn1/sequence.rs @@ -2,8 +2,8 @@ //! `SEQUENCE`s to Rust structs. use crate::{ - ByteSlice, Decode, DecodeValue, Decoder, Encode, EncodeValue, Encoder, FixedTag, Header, - Length, Reader, Result, Tag, + ByteSlice, Decode, DecodeValue, Decoder, Encode, EncodeValue, FixedTag, Header, Length, Reader, + Result, Tag, Writer, }; /// ASN.1 `SEQUENCE` trait. @@ -34,10 +34,10 @@ where }) } - fn encode_value(&self, encoder: &mut Encoder<'_>) -> Result<()> { + fn encode_value(&self, writer: &mut dyn Writer) -> Result<()> { self.fields(|fields| { for &field in fields { - field.encode(encoder)?; + field.encode(writer)?; } Ok(()) @@ -87,8 +87,8 @@ impl EncodeValue for SequenceRef<'_> { Ok(self.body.len()) } - fn encode_value(&self, encoder: &mut Encoder<'_>) -> Result<()> { - self.body.encode_value(encoder) + fn encode_value(&self, writer: &mut dyn Writer) -> Result<()> { + self.body.encode_value(writer) } } diff --git a/der/src/asn1/sequence_of.rs b/der/src/asn1/sequence_of.rs index c1f5d563b..ee330ae0e 100644 --- a/der/src/asn1/sequence_of.rs +++ b/der/src/asn1/sequence_of.rs @@ -2,7 +2,7 @@ use crate::{ arrayvec, ord::iter_cmp, ArrayVec, Decode, DecodeValue, Decoder, DerOrd, Encode, EncodeValue, - Encoder, ErrorKind, FixedTag, Header, Length, Reader, Result, Tag, ValueOrd, + ErrorKind, FixedTag, Header, Length, Reader, Result, Tag, ValueOrd, Writer, }; use core::cmp::Ordering; @@ -91,9 +91,9 @@ where .fold(Ok(Length::ZERO), |len, elem| len + elem.encoded_len()?) } - fn encode_value(&self, encoder: &mut Encoder<'_>) -> Result<()> { + fn encode_value(&self, writer: &mut dyn Writer) -> Result<()> { for elem in self.iter() { - elem.encode(encoder)?; + elem.encode(writer)?; } Ok(()) @@ -150,9 +150,9 @@ where .fold(Ok(Length::ZERO), |len, elem| len + elem.encoded_len()?) } - fn encode_value(&self, encoder: &mut Encoder<'_>) -> Result<()> { + fn encode_value(&self, writer: &mut dyn Writer) -> Result<()> { for elem in self { - elem.encode(encoder)?; + elem.encode(writer)?; } Ok(()) @@ -205,9 +205,9 @@ where .fold(Ok(Length::ZERO), |len, elem| len + elem.encoded_len()?) } - fn encode_value(&self, encoder: &mut Encoder<'_>) -> Result<()> { + fn encode_value(&self, writer: &mut dyn Writer) -> Result<()> { for elem in self { - elem.encode(encoder)?; + elem.encode(writer)?; } Ok(()) diff --git a/der/src/asn1/set_of.rs b/der/src/asn1/set_of.rs index cfcae3edc..00b88cc68 100644 --- a/der/src/asn1/set_of.rs +++ b/der/src/asn1/set_of.rs @@ -2,7 +2,7 @@ use crate::{ arrayvec, ord::iter_cmp, ArrayVec, Decode, DecodeValue, Decoder, DerOrd, Encode, EncodeValue, - Encoder, Error, ErrorKind, FixedTag, Header, Length, Reader, Result, Tag, ValueOrd, + Error, ErrorKind, FixedTag, Header, Length, Reader, Result, Tag, ValueOrd, Writer, }; use core::cmp::Ordering; @@ -110,9 +110,9 @@ where .fold(Ok(Length::ZERO), |len, elem| len + elem.encoded_len()?) } - fn encode_value(&self, encoder: &mut Encoder<'_>) -> Result<()> { + fn encode_value(&self, writer: &mut dyn Writer) -> Result<()> { for elem in self.iter() { - elem.encode(encoder)?; + elem.encode(writer)?; } Ok(()) @@ -299,9 +299,9 @@ where .fold(Ok(Length::ZERO), |len, elem| len + elem.encoded_len()?) } - fn encode_value(&self, encoder: &mut Encoder<'_>) -> Result<()> { + fn encode_value(&self, writer: &mut dyn Writer) -> Result<()> { for elem in self.iter() { - elem.encode(encoder)?; + elem.encode(writer)?; } Ok(()) diff --git a/der/src/asn1/utc_time.rs b/der/src/asn1/utc_time.rs index 4938d415d..d1572b50f 100644 --- a/der/src/asn1/utc_time.rs +++ b/der/src/asn1/utc_time.rs @@ -4,8 +4,8 @@ use crate::{ asn1::Any, datetime::{self, DateTime}, ord::OrdIsValueOrd, - ByteSlice, DecodeValue, Decoder, EncodeValue, Encoder, Error, ErrorKind, FixedTag, Header, - Length, Result, Tag, Writer, + ByteSlice, DecodeValue, Decoder, EncodeValue, Error, ErrorKind, FixedTag, Header, Length, + Result, Tag, Writer, }; use core::time::Duration; @@ -113,7 +113,7 @@ impl EncodeValue for UtcTime { Ok(Self::LENGTH) } - fn encode_value(&self, encoder: &mut Encoder<'_>) -> Result<()> { + fn encode_value(&self, writer: &mut dyn Writer) -> Result<()> { let year = match self.0.year() { y @ 1950..=1999 => y.checked_sub(1900), y @ 2000..=2049 => y.checked_sub(2000), @@ -122,13 +122,13 @@ impl EncodeValue for UtcTime { .and_then(|y| u8::try_from(y).ok()) .ok_or(ErrorKind::DateTime)?; - datetime::encode_decimal(encoder, Self::TAG, year)?; - datetime::encode_decimal(encoder, Self::TAG, self.0.month())?; - datetime::encode_decimal(encoder, Self::TAG, self.0.day())?; - datetime::encode_decimal(encoder, Self::TAG, self.0.hour())?; - datetime::encode_decimal(encoder, Self::TAG, self.0.minutes())?; - datetime::encode_decimal(encoder, Self::TAG, self.0.seconds())?; - encoder.write_byte(b'Z') + 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') } } diff --git a/der/src/asn1/utf8_string.rs b/der/src/asn1/utf8_string.rs index f3d40a2c0..b800a8d4e 100644 --- a/der/src/asn1/utf8_string.rs +++ b/der/src/asn1/utf8_string.rs @@ -1,8 +1,8 @@ //! ASN.1 `UTF8String` support. use crate::{ - asn1::Any, ord::OrdIsValueOrd, ByteSlice, DecodeValue, Decoder, EncodeValue, Encoder, Error, - FixedTag, Header, Length, Result, StrSlice, Tag, + asn1::Any, ord::OrdIsValueOrd, ByteSlice, DecodeValue, Decoder, EncodeValue, Error, FixedTag, + Header, Length, Result, StrSlice, Tag, Writer, }; use core::{fmt, str}; @@ -80,8 +80,8 @@ impl EncodeValue for Utf8String<'_> { self.inner.value_len() } - fn encode_value(&self, encoder: &mut Encoder<'_>) -> Result<()> { - self.inner.encode_value(encoder) + fn encode_value(&self, writer: &mut dyn Writer) -> Result<()> { + self.inner.encode_value(writer) } } @@ -142,8 +142,8 @@ impl EncodeValue for str { Utf8String::new(self)?.value_len() } - fn encode_value(&self, encoder: &mut Encoder<'_>) -> Result<()> { - Utf8String::new(self)?.encode_value(encoder) + fn encode_value(&self, writer: &mut dyn Writer) -> Result<()> { + Utf8String::new(self)?.encode_value(writer) } } @@ -178,8 +178,8 @@ impl EncodeValue for String { Utf8String::new(self)?.value_len() } - fn encode_value(&self, encoder: &mut Encoder<'_>) -> Result<()> { - Utf8String::new(self)?.encode_value(encoder) + fn encode_value(&self, writer: &mut dyn Writer) -> Result<()> { + Utf8String::new(self)?.encode_value(writer) } } diff --git a/der/src/byte_slice.rs b/der/src/byte_slice.rs index cf802863b..976401d7d 100644 --- a/der/src/byte_slice.rs +++ b/der/src/byte_slice.rs @@ -2,8 +2,8 @@ //! library-level length limitation i.e. `Length::max()`. use crate::{ - str_slice::StrSlice, DecodeValue, Decoder, DerOrd, EncodeValue, Encoder, Error, Header, Length, - Reader, Result, Writer, + str_slice::StrSlice, DecodeValue, Decoder, DerOrd, EncodeValue, Error, Header, Length, Reader, + Result, Writer, }; use core::cmp::Ordering; @@ -66,8 +66,8 @@ impl EncodeValue for ByteSlice<'_> { Ok(self.length) } - fn encode_value(&self, encoder: &mut Encoder<'_>) -> Result<()> { - encoder.write(self.as_ref()) + fn encode_value(&self, writer: &mut dyn Writer) -> Result<()> { + writer.write(self.as_ref()) } } diff --git a/der/src/datetime.rs b/der/src/datetime.rs index 2c2b2549b..2b4c504bf 100644 --- a/der/src/datetime.rs +++ b/der/src/datetime.rs @@ -5,7 +5,7 @@ // Copyright (c) 2016 The humantime Developers // Released under the MIT OR Apache 2.0 licenses -use crate::{Encoder, Error, ErrorKind, Result, Tag, Writer}; +use crate::{Error, ErrorKind, Result, Tag, Writer}; use core::{fmt, str::FromStr, time::Duration}; #[cfg(feature = "std")] @@ -372,15 +372,18 @@ pub(crate) fn decode_decimal(tag: Tag, hi: u8, lo: u8) -> Result { } /// Encode 2-digit decimal value -pub(crate) fn encode_decimal(encoder: &mut Encoder<'_>, tag: Tag, value: u8) -> Result<()> { +pub(crate) fn encode_decimal(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()); } - encoder.write_byte(b'0'.checked_add(hi_val).ok_or(ErrorKind::Overflow)?)?; - encoder.write_byte(b'0'.checked_add(value % 10).ok_or(ErrorKind::Overflow)?) + 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)?) } #[cfg(test)] diff --git a/der/src/document.rs b/der/src/document.rs index 5cc67462e..a3cd4c9c2 100644 --- a/der/src/document.rs +++ b/der/src/document.rs @@ -1,8 +1,6 @@ //! ASN.1 DER-encoded documents stored on the heap. -use crate::{ - Decode, Decoder, Encode, Encoder, Error, FixedTag, Length, Reader, Result, Tag, Writer, -}; +use crate::{Decode, Decoder, Encode, Error, FixedTag, Length, Reader, Result, Tag, Writer}; use alloc::vec::Vec; use core::fmt::{self, Debug}; @@ -167,8 +165,8 @@ impl Encode for Document { Ok(self.len()) } - fn encode(&self, encoder: &mut Encoder<'_>) -> Result<()> { - encoder.write(self.as_bytes()) + fn encode(&self, writer: &mut dyn Writer) -> Result<()> { + writer.write(self.as_bytes()) } } diff --git a/der/src/encode.rs b/der/src/encode.rs index 7b4532b0b..1de1cb371 100644 --- a/der/src/encode.rs +++ b/der/src/encode.rs @@ -1,6 +1,6 @@ //! Trait definition for [`Encode`]. -use crate::{Encoder, Header, Length, Result, Tagged}; +use crate::{Encoder, Header, Length, Result, Tagged, Writer}; #[cfg(feature = "alloc")] use {crate::ErrorKind, alloc::vec::Vec, core::iter}; @@ -21,7 +21,7 @@ pub trait Encode { fn encoded_len(&self) -> Result; /// Encode this value as ASN.1 DER using the provided [`Encoder`]. - fn encode(&self, encoder: &mut Encoder<'_>) -> Result<()>; + fn encode(&self, encoder: &mut dyn Writer) -> Result<()>; /// Encode this value to the provided byte slice, returning a sub-slice /// containing the encoded message. @@ -75,9 +75,9 @@ where } /// Encode this value as ASN.1 DER using the provided [`Encoder`]. - fn encode(&self, encoder: &mut Encoder<'_>) -> Result<()> { - self.header()?.encode(encoder)?; - self.encode_value(encoder) + fn encode(&self, writer: &mut dyn Writer) -> Result<()> { + self.header()?.encode(writer)?; + self.encode_value(writer) } } @@ -119,5 +119,5 @@ pub trait EncodeValue { /// Encode value (sans [`Tag`]+[`Length`] header) as ASN.1 DER using the /// provided [`Encoder`]. - fn encode_value(&self, encoder: &mut Encoder<'_>) -> Result<()>; + fn encode_value(&self, encoder: &mut dyn Writer) -> Result<()>; } diff --git a/der/src/encode_ref.rs b/der/src/encode_ref.rs index 8855b4743..c1e4f03f4 100644 --- a/der/src/encode_ref.rs +++ b/der/src/encode_ref.rs @@ -1,7 +1,7 @@ //! Wrapper object for encoding reference types. // TODO(tarcieri): replace with blanket impls of `Encode(Value)` for reference types? -use crate::{Encode, EncodeValue, Encoder, Length, Result, Tag, Tagged, ValueOrd}; +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 @@ -22,8 +22,8 @@ where self.0.encoded_len() } - fn encode(&self, encoder: &mut Encoder<'_>) -> Result<()> { - self.0.encode(encoder) + fn encode(&self, writer: &mut dyn Writer) -> Result<()> { + self.0.encode(writer) } } @@ -47,8 +47,8 @@ where self.0.value_len() } - fn encode_value(&self, encoder: &mut Encoder<'_>) -> Result<()> { - self.0.encode_value(encoder) + fn encode_value(&self, writer: &mut dyn Writer) -> Result<()> { + self.0.encode_value(writer) } } diff --git a/der/src/encoder.rs b/der/src/encoder.rs index d39a0ed45..d3bf9f1ca 100644 --- a/der/src/encoder.rs +++ b/der/src/encoder.rs @@ -1,8 +1,8 @@ //! DER encoder. use crate::{ - asn1::*, Encode, EncodeRef, EncodeValue, Error, ErrorKind, Header, Length, Result, Tag, - TagMode, TagNumber, Tagged, Writer, + asn1::*, Encode, EncodeValue, Error, ErrorKind, Header, Length, Result, Tag, TagMode, + TagNumber, Tagged, Writer, }; /// DER encoder. @@ -74,14 +74,6 @@ impl<'a> Encoder<'a> { .ok_or_else(|| ErrorKind::Overlength.at(position)) } - /// Encode the provided value as an ASN.1 `BIT STRING`. - pub fn bit_string(&mut self, value: impl TryInto>) -> Result<()> { - value - .try_into() - .map_err(|_| self.value_error(Tag::BitString)) - .and_then(|value| self.encode(&value)) - } - /// Encode a `CONTEXT-SPECIFIC` field with the provided tag number and mode. pub fn context_specific( &mut self, @@ -100,58 +92,6 @@ impl<'a> Encoder<'a> { .encode(self) } - /// Encode the provided value as an ASN.1 `GeneralizedTime`. - pub fn generalized_time(&mut self, value: impl TryInto) -> Result<()> { - value - .try_into() - .map_err(|_| self.value_error(Tag::GeneralizedTime)) - .and_then(|value| self.encode(&value)) - } - - /// Encode the provided value as an ASN.1 `IA5String`. - pub fn ia5_string(&mut self, value: impl TryInto>) -> Result<()> { - value - .try_into() - .map_err(|_| self.value_error(Tag::Ia5String)) - .and_then(|value| self.encode(&value)) - } - - /// Encode an ASN.1 `NULL` value. - pub fn null(&mut self) -> Result<()> { - self.encode(&Null) - } - - /// Encode the provided value as an ASN.1 `OCTET STRING` - pub fn octet_string(&mut self, value: impl TryInto>) -> Result<()> { - value - .try_into() - .map_err(|_| self.value_error(Tag::OctetString)) - .and_then(|value| self.encode(&value)) - } - - /// Encode an ASN.1 [`ObjectIdentifier`] - #[cfg(feature = "oid")] - #[cfg_attr(docsrs, doc(cfg(feature = "oid")))] - pub fn oid(&mut self, value: impl TryInto) -> Result<()> { - value - .try_into() - .map_err(|_| self.value_error(Tag::ObjectIdentifier)) - .and_then(|value| self.encode(&value)) - } - - /// Encode an ASN.1 `OPTIONAL` for the given option reference. - pub fn optional(&mut self, value: Option<&T>) -> Result<()> { - value.map(EncodeRef).encode(self) - } - - /// Encode the provided value as an ASN.1 `PrintableString` - pub fn printable_string(&mut self, value: impl TryInto>) -> Result<()> { - value - .try_into() - .map_err(|_| self.value_error(Tag::PrintableString)) - .and_then(|value| self.encode(&value)) - } - /// Encode an ASN.1 `SEQUENCE` of the given length. /// /// Spawns a nested [`Encoder`] which is expected to be exactly the @@ -172,22 +112,6 @@ impl<'a> Encoder<'a> { } } - /// Encode the provided value as an ASN.1 `UTCTime` - pub fn utc_time(&mut self, value: impl TryInto) -> Result<()> { - value - .try_into() - .map_err(|_| self.value_error(Tag::UtcTime)) - .and_then(|value| self.encode(&value)) - } - - /// Encode the provided value as an ASN.1 `Utf8String` - pub fn utf8_string(&mut self, value: impl TryInto>) -> Result<()> { - value - .try_into() - .map_err(|_| self.value_error(Tag::Utf8String)) - .and_then(|value| self.encode(&value)) - } - /// Reserve a portion of the internal buffer, updating the internal cursor /// position and returning a mutable slice. fn reserve(&mut self, len: impl TryInto) -> Result<&mut [u8]> { @@ -200,10 +124,9 @@ impl<'a> Encoder<'a> { .or_else(|_| self.error(ErrorKind::Overflow))?; let end = (self.position + len).or_else(|e| self.error(e.kind()))?; - let range = self.position.try_into()?..end.try_into()?; let slice = self .bytes - .get_mut(range) + .get_mut(self.position.try_into()?..end.try_into()?) .ok_or_else(|| ErrorKind::Overlength.at(end))?; self.position = end; @@ -221,8 +144,7 @@ impl<'a> Writer for Encoder<'a> { #[cfg(test)] mod tests { use super::Encoder; - use crate::{asn1::BitString, Encode, ErrorKind, Length, TagMode, TagNumber}; - use hex_literal::hex; + use crate::{Encode, ErrorKind, Length}; #[test] fn overlength_message() { @@ -232,27 +154,4 @@ mod tests { assert_eq!(err.kind(), ErrorKind::Overlength); assert_eq!(err.position(), Some(Length::ONE)); } - - #[test] - fn context_specific_with_implicit_field() { - // From 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 - const EXPECTED_BYTES: &[u8] = - &hex!("81210019BF44096984CDFE8541BAC167DC3B96C85086AA30B6B6CB0C5C38AD703166E1"); - - let tag_number = TagNumber::new(1); - let bit_string = BitString::from_bytes(&EXPECTED_BYTES[3..]).unwrap(); - - let mut buf = [0u8; EXPECTED_BYTES.len()]; - let mut encoder = Encoder::new(&mut buf); - encoder - .context_specific(tag_number, TagMode::Implicit, &bit_string) - .unwrap(); - - assert_eq!(EXPECTED_BYTES, encoder.finish().unwrap()); - } } diff --git a/der/src/header.rs b/der/src/header.rs index 757855d5f..48a551dfc 100644 --- a/der/src/header.rs +++ b/der/src/header.rs @@ -1,6 +1,6 @@ //! ASN.1 DER headers. -use crate::{Decode, Decoder, DerOrd, Encode, Encoder, ErrorKind, Length, Result, Tag}; +use crate::{Decode, Decoder, DerOrd, Encode, ErrorKind, Length, Result, Tag, Writer}; use core::cmp::Ordering; /// ASN.1 DER headers: tag + length component of TLV-encoded values @@ -44,9 +44,9 @@ impl Encode for Header { self.tag.encoded_len()? + self.length.encoded_len()? } - fn encode(&self, encoder: &mut Encoder<'_>) -> Result<()> { - self.tag.encode(encoder)?; - self.length.encode(encoder) + fn encode(&self, writer: &mut dyn Writer) -> Result<()> { + self.tag.encode(writer)?; + self.length.encode(writer) } } diff --git a/der/src/length.rs b/der/src/length.rs index dde9000ea..f9533b280 100644 --- a/der/src/length.rs +++ b/der/src/length.rs @@ -7,6 +7,10 @@ use core::{ 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; @@ -248,28 +252,29 @@ impl Encode for Length { } } - #[allow(clippy::cast_possible_truncation)] - fn encode(&self, encoder: &mut Encoder<'_>) -> Result<()> { - if let Some(tag_byte) = self.initial_octet() { - encoder.write_byte(tag_byte)?; - - // Strip leading zeroes - match self.0.to_be_bytes() { - [0, 0, 0, byte] => encoder.write_byte(byte), - [0, 0, bytes @ ..] => encoder.write(&bytes), - [0, bytes @ ..] => encoder.write(&bytes), - bytes => encoder.write(&bytes), + fn encode(&self, writer: &mut dyn 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), + } } - } else { - encoder.write_byte(self.0 as u8) + #[allow(clippy::cast_possible_truncation)] + None => writer.write_byte(self.0 as u8), } } } impl DerOrd for Length { fn der_cmp(&self, other: &Self) -> Result { - let mut buf1 = [0u8; 5]; - let mut buf2 = [0u8; 5]; + let mut buf1 = [0u8; MAX_DER_OCTETS]; + let mut buf2 = [0u8; MAX_DER_OCTETS]; let mut encoder1 = Encoder::new(&mut buf1); encoder1.encode(self)?; diff --git a/der/src/str_slice.rs b/der/src/str_slice.rs index 8246b276b..4e911be43 100644 --- a/der/src/str_slice.rs +++ b/der/src/str_slice.rs @@ -1,9 +1,7 @@ //! Common handling for types backed by `str` slices with enforcement of a //! library-level length limitation i.e. `Length::max()`. -use crate::{ - ByteSlice, DecodeValue, Decoder, EncodeValue, Encoder, Header, Length, Result, Writer, -}; +use crate::{ByteSlice, DecodeValue, Decoder, EncodeValue, Header, Length, Result, Writer}; use core::str; /// String slice newtype which respects the [`Length::max`] limit. @@ -75,7 +73,7 @@ impl<'a> EncodeValue for StrSlice<'a> { Ok(self.length) } - fn encode_value(&self, encoder: &mut Encoder<'_>) -> Result<()> { - encoder.write(self.as_ref()) + fn encode_value(&self, writer: &mut dyn Writer) -> Result<()> { + writer.write(self.as_ref()) } } diff --git a/der/src/tag.rs b/der/src/tag.rs index fc3fc7df5..f590b929f 100644 --- a/der/src/tag.rs +++ b/der/src/tag.rs @@ -6,9 +6,7 @@ mod number; pub use self::{class::Class, mode::TagMode, number::TagNumber}; -use crate::{ - Decode, Decoder, DerOrd, Encode, Encoder, Error, ErrorKind, Length, Reader, Result, Writer, -}; +use crate::{Decode, Decoder, DerOrd, Encode, Error, ErrorKind, Length, Reader, Result, Writer}; use core::{cmp::Ordering, fmt}; /// Indicator bit for constructed form encoding (i.e. vs primitive form) @@ -315,8 +313,8 @@ impl Encode for Tag { Ok(Length::ONE) } - fn encode(&self, encoder: &mut Encoder<'_>) -> Result<()> { - encoder.write_byte(self.into()) + fn encode(&self, writer: &mut dyn Writer) -> Result<()> { + writer.write_byte(self.into()) } } diff --git a/der/src/writer.rs b/der/src/writer.rs index de2e35349..b5e31327d 100644 --- a/der/src/writer.rs +++ b/der/src/writer.rs @@ -3,7 +3,7 @@ use crate::Result; /// Writer trait which outputs encoded DER. -pub trait Writer: Sized { +pub trait Writer { /// Write the given DER-encoded bytes as output. fn write(&mut self, slice: &[u8]) -> Result<()>; diff --git a/pkcs1/src/version.rs b/pkcs1/src/version.rs index 2d9b111f8..585ebccde 100644 --- a/pkcs1/src/version.rs +++ b/pkcs1/src/version.rs @@ -1,7 +1,7 @@ //! PKCS#1 version identifier. use crate::Error; -use der::{Decode, Decoder, Encode, Encoder, FixedTag, Tag}; +use der::{Decode, Decoder, Encode, FixedTag, Tag, Writer}; /// Version identifier for PKCS#1 documents as defined in /// [RFC 8017 Appendix 1.2]. @@ -62,8 +62,8 @@ impl Encode for Version { der::Length::ONE.for_tlv() } - fn encode(&self, encoder: &mut Encoder<'_>) -> der::Result<()> { - u8::from(*self).encode(encoder) + fn encode(&self, writer: &mut dyn Writer) -> der::Result<()> { + u8::from(*self).encode(writer) } } diff --git a/pkcs5/src/lib.rs b/pkcs5/src/lib.rs index 9368c2022..582874687 100644 --- a/pkcs5/src/lib.rs +++ b/pkcs5/src/lib.rs @@ -29,7 +29,7 @@ pub use crate::error::{Error, Result}; pub use der::{self, asn1::ObjectIdentifier}; pub use spki::AlgorithmIdentifier; -use der::{Decode, Decoder, Encode, Encoder, Length, Tag}; +use der::{Decode, Decoder, Encode, Sequence, Tag}; #[cfg(all(feature = "alloc", feature = "pbes2"))] use alloc::vec::Vec; @@ -42,7 +42,7 @@ pub enum EncryptionScheme<'a> { /// Password-Based Encryption Scheme 1 as defined in [RFC 8018 Section 6.1]. /// /// [RFC 8018 Section 6.1]: https://tools.ietf.org/html/rfc8018#section-6.1 - Pbes1(pbes1::Parameters), + Pbes1(pbes1::Algorithm), /// Password-Based Encryption Scheme 2 as defined in [RFC 8018 Section 6.2]. /// @@ -119,9 +119,9 @@ impl<'a> EncryptionScheme<'a> { } /// Get [`pbes1::Parameters`] if it is the selected algorithm. - pub fn pbes1(&self) -> Option<&pbes1::Parameters> { + pub fn pbes1(&self) -> Option<&pbes1::Algorithm> { match self { - Self::Pbes1(params) => Some(params), + Self::Pbes1(alg) => Some(alg), _ => None, } } @@ -141,33 +141,21 @@ impl<'a> Decode<'a> for EncryptionScheme<'a> { } } -impl<'a> Encode for EncryptionScheme<'a> { - fn encoded_len(&self) -> der::Result { +impl<'a> Sequence<'a> for EncryptionScheme<'a> { + fn fields(&self, f: F) -> der::Result + where + F: FnOnce(&[&dyn Encode]) -> der::Result, + { match self { - Self::Pbes1(pbes1) => pbes1.encoded_len(), - Self::Pbes2(pbes2) => { - (pbes2::PBES2_OID.encoded_len()? + pbes2.encoded_len()?)?.for_tlv() - } - } - } - - fn encode(&self, encoder: &mut Encoder<'_>) -> der::Result<()> { - match self { - Self::Pbes1(pbes1) => pbes1.encode(encoder), - Self::Pbes2(pbes2) => { - let seq_len = (pbes2::PBES2_OID.encoded_len()? + pbes2.encoded_len()?)?; - encoder.sequence(seq_len, |seq| { - seq.encode(&pbes2::PBES2_OID)?; - seq.encode(pbes2) - }) - } + Self::Pbes1(pbes1) => f(&[&pbes1.oid(), &pbes1.parameters]), + Self::Pbes2(pbes2) => f(&[&pbes2::PBES2_OID, pbes2]), } } } -impl<'a> From for EncryptionScheme<'a> { - fn from(params: pbes1::Parameters) -> EncryptionScheme<'a> { - Self::Pbes1(params) +impl<'a> From for EncryptionScheme<'a> { + fn from(alg: pbes1::Algorithm) -> EncryptionScheme<'a> { + Self::Pbes1(alg) } } @@ -182,13 +170,12 @@ impl<'a> TryFrom> for EncryptionScheme<'a> { fn try_from(alg: AlgorithmIdentifier<'a>) -> der::Result> { if alg.oid == pbes2::PBES2_OID { - if let Some(params) = alg.parameters { - pbes2::Parameters::try_from(params).map(Into::into) - } else { - Err(Tag::OctetString.value_error()) + match alg.parameters { + Some(params) => pbes2::Parameters::try_from(params).map(Into::into), + None => Err(Tag::OctetString.value_error()), } } else { - pbes1::Parameters::try_from(alg).map(Into::into) + pbes1::Algorithm::try_from(alg).map(Into::into) } } } diff --git a/pkcs5/src/pbes1.rs b/pkcs5/src/pbes1.rs index 47dff4471..c12a6131b 100644 --- a/pkcs5/src/pbes1.rs +++ b/pkcs5/src/pbes1.rs @@ -4,8 +4,8 @@ use crate::AlgorithmIdentifier; use der::{ - asn1::{ObjectIdentifier, OctetString}, - Decode, Decoder, Encode, Encoder, ErrorKind, FixedTag, Length, Tag, + asn1::{Any, ObjectIdentifier, OctetString}, + Decode, Decoder, Encode, ErrorKind, Length, Sequence, Tag, Writer, }; /// `pbeWithMD2AndDES-CBC` Object Identifier (OID). @@ -35,111 +35,125 @@ pub const PBE_WITH_SHA1_AND_RC2_CBC_OID: ObjectIdentifier = /// Length of a PBES1 salt (as defined in the `PBEParameter` ASN.1 message). pub const SALT_LENGTH: usize = 8; -/// Password-Based Encryption Scheme 1 parameters as defined in [RFC 8018 Appendix A.3]. +/// Password-Based Encryption Scheme 1 algorithms as defined in [RFC 8018 Appendix A.C]. /// /// ```text -/// PBEParameter ::= SEQUENCE { -/// salt OCTET STRING (SIZE(8)), -/// iterationCount INTEGER } +/// PBES1Algorithms ALGORITHM-IDENTIFIER ::= { +/// {PBEParameter IDENTIFIED BY pbeWithMD2AndDES-CBC} | +/// {PBEParameter IDENTIFIED BY pbeWithMD2AndRC2-CBC} | +/// {PBEParameter IDENTIFIED BY pbeWithMD5AndDES-CBC} | +/// {PBEParameter IDENTIFIED BY pbeWithMD5AndRC2-CBC} | +/// {PBEParameter IDENTIFIED BY pbeWithSHA1AndDES-CBC} | +/// {PBEParameter IDENTIFIED BY pbeWithSHA1AndRC2-CBC}, +/// ... +/// } /// ``` /// -/// Note that this struct additionally stores an [`EncryptionScheme`] parameter -/// parsed from the [`ObjectIdentifier`]. -/// -/// [RFC 8018 Appendix A.3]: https://tools.ietf.org/html/rfc8018#appendix-A.3 +/// [RFC 8018 Appendix A.C]: https://datatracker.ietf.org/doc/html/rfc8018#appendix-C #[derive(Clone, Debug, Eq, PartialEq)] -pub struct Parameters { - /// Encryption scheme +pub struct Algorithm { + /// Encryption scheme. pub encryption: EncryptionScheme, - /// Salt value - pub salt: [u8; SALT_LENGTH], - - /// Iteration count - pub iteration_count: u16, + /// Scheme parameters. + pub parameters: Parameters, } -impl Parameters { +impl Algorithm { /// Get the [`ObjectIdentifier`] (a.k.a OID) for this algorithm. pub fn oid(&self) -> ObjectIdentifier { self.encryption.oid() } +} - /// Get the inner length of the encoded sequence - fn inner_len(&self) -> der::Result { - let oid_len = self.encryption.oid().encoded_len()?; - let params_len = (self.salt_string()?.encoded_len()? - + self.iteration_count.encoded_len()?)? - .for_tlv()?; - oid_len + params_len +impl Decode<'_> for Algorithm { + fn decode(decoder: &mut Decoder<'_>) -> der::Result { + AlgorithmIdentifier::decode(decoder)?.try_into() } +} - /// Get an [`OctetString`] wrapper for the salt - fn salt_string(&self) -> der::Result> { - OctetString::new(&self.salt) +impl Sequence<'_> for Algorithm { + fn fields(&self, f: F) -> der::Result + where + F: FnOnce(&[&dyn Encode]) -> der::Result, + { + f(&[&self.encryption, &self.parameters]) } } -impl Decode<'_> for Parameters { - fn decode(decoder: &mut Decoder<'_>) -> der::Result { - AlgorithmIdentifier::decode(decoder)?.try_into() +impl<'a> TryFrom> for Algorithm { + type Error = der::Error; + + fn try_from(alg: AlgorithmIdentifier<'a>) -> der::Result { + // Ensure that we have a supported PBES1 algorithm identifier + let encryption = EncryptionScheme::try_from(alg.oid) + .map_err(|_| der::Tag::ObjectIdentifier.value_error())?; + + match alg.parameters { + Some(any) => Ok(Self { + encryption, + parameters: any.try_into()?, + }), + None => Err(Tag::OctetString.value_error()), + } } } -impl Encode for Parameters { - fn encoded_len(&self) -> der::Result { - self.inner_len()?.for_tlv() - } +/// Password-Based Encryption Scheme 1 parameters as defined in [RFC 8018 Appendix A.3]. +/// +/// ```text +/// PBEParameter ::= SEQUENCE { +/// salt OCTET STRING (SIZE(8)), +/// iterationCount INTEGER } +/// ``` +/// +/// [RFC 8018 Appendix A.3]: https://tools.ietf.org/html/rfc8018#appendix-A.3 +#[derive(Clone, Debug, Eq, PartialEq)] +pub struct Parameters { + /// Salt value + pub salt: [u8; SALT_LENGTH], - fn encode(&self, encoder: &mut Encoder<'_>) -> der::Result<()> { - encoder.sequence(self.inner_len()?, |encoder| { - encoder.oid(self.encryption.oid())?; + /// Iteration count + pub iteration_count: u16, +} - let salt_string = self.salt_string()?; - let seq_len = (salt_string.encoded_len()? + self.iteration_count.encoded_len()?)?; - encoder.sequence(seq_len, |seq| { - seq.encode(&salt_string)?; - seq.encode(&self.iteration_count) - }) - }) +impl Decode<'_> for Parameters { + fn decode(decoder: &mut Decoder<'_>) -> der::Result { + Any::decode(decoder)?.try_into() } } -impl FixedTag for Parameters { - const TAG: Tag = Tag::Sequence; +impl Sequence<'_> for Parameters { + fn fields(&self, f: F) -> der::Result + where + F: FnOnce(&[&dyn Encode]) -> der::Result, + { + f(&[&OctetString::new(&self.salt)?, &self.iteration_count]) + } } -impl<'a> TryFrom> for Parameters { +impl TryFrom> for Parameters { type Error = der::Error; - fn try_from(alg: AlgorithmIdentifier<'a>) -> der::Result { - // Ensure that we have a supported PBES1 algorithm identifier - let encryption = EncryptionScheme::try_from(alg.oid) - .map_err(|_| der::Tag::ObjectIdentifier.value_error())?; + fn try_from(any: Any<'_>) -> der::Result { + any.sequence(|params| { + let salt = params + .octet_string()? + .as_bytes() + .try_into() + .map_err(|_| der::Tag::OctetString.value_error())?; - if let Some(any) = alg.parameters { - any.sequence(|params| { - let salt = params - .octet_string()? - .as_bytes() - .try_into() - .map_err(|_| der::Tag::OctetString.value_error())?; - - let iteration_count = params.decode()?; - - Ok(Self { - encryption, - salt, - iteration_count, - }) + let iteration_count = params.decode()?; + + Ok(Parameters { + salt, + iteration_count, }) - } else { - Err(Tag::OctetString.value_error()) - } + }) } } -/// Password-Based Encryption Scheme 1 algorithms as defined in [RFC 8018 Appendix A.3]. +/// Password-Based Encryption Scheme 1 ciphersuites as defined in [RFC 8018 Appendix A.3]. /// /// [RFC 8018 Appendix A.3]: https://tools.ietf.org/html/rfc8018#appendix-A.3 #[derive(Copy, Clone, Debug, Eq, PartialEq)] @@ -222,8 +236,8 @@ impl Encode for EncryptionScheme { self.oid().encoded_len() } - fn encode(&self, encoder: &mut Encoder<'_>) -> der::Result<()> { - self.oid().encode(encoder) + fn encode(&self, writer: &mut dyn Writer) -> der::Result<()> { + self.oid().encode(writer) } } diff --git a/pkcs5/src/pbes2.rs b/pkcs5/src/pbes2.rs index 9775fbcb2..3a397051f 100644 --- a/pkcs5/src/pbes2.rs +++ b/pkcs5/src/pbes2.rs @@ -15,7 +15,7 @@ pub use self::kdf::{ use crate::{AlgorithmIdentifier, Error, Result}; use der::{ asn1::{Any, ObjectIdentifier, OctetString}, - Decode, Decoder, Encode, Encoder, ErrorKind, Length, Sequence, Tag, + Decode, Decoder, Encode, ErrorKind, Length, Sequence, Tag, Writer, }; #[cfg(all(feature = "alloc", feature = "pbes2"))] @@ -378,7 +378,7 @@ impl<'a> Encode for EncryptionScheme<'a> { AlgorithmIdentifier::try_from(*self)?.encoded_len() } - fn encode(&self, encoder: &mut Encoder<'_>) -> der::Result<()> { - AlgorithmIdentifier::try_from(*self)?.encode(encoder) + fn encode(&self, writer: &mut dyn Writer) -> der::Result<()> { + AlgorithmIdentifier::try_from(*self)?.encode(writer) } } diff --git a/pkcs5/src/pbes2/kdf.rs b/pkcs5/src/pbes2/kdf.rs index 30a699ade..8e2410e24 100644 --- a/pkcs5/src/pbes2/kdf.rs +++ b/pkcs5/src/pbes2/kdf.rs @@ -3,7 +3,7 @@ use crate::{AlgorithmIdentifier, Error, Result}; use der::{ asn1::{Any, ObjectIdentifier, OctetString}, - Decode, Decoder, Encode, Encoder, ErrorKind, Length, Sequence, Tag, Tagged, + Decode, Decoder, Encode, ErrorKind, Length, Sequence, Tag, Tagged, Writer, }; /// Password-Based Key Derivation Function (PBKDF2) OID. @@ -342,8 +342,8 @@ impl Encode for Pbkdf2Prf { AlgorithmIdentifier::try_from(*self)?.encoded_len() } - fn encode(&self, encoder: &mut Encoder<'_>) -> der::Result<()> { - AlgorithmIdentifier::try_from(*self)?.encode(encoder) + fn encode(&self, writer: &mut dyn Writer) -> der::Result<()> { + AlgorithmIdentifier::try_from(*self)?.encode(writer) } } diff --git a/pkcs7/src/content_info.rs b/pkcs7/src/content_info.rs index bb7fe4322..7edfab324 100644 --- a/pkcs7/src/content_info.rs +++ b/pkcs7/src/content_info.rs @@ -132,7 +132,7 @@ mod tests { let mut encoder = Encoder::new(&mut in_buf); encoder.sequence(crate::PKCS_7_DATA_OID.encoded_len()?, |encoder| { - encoder.oid(crate::PKCS_7_DATA_OID) + crate::PKCS_7_DATA_OID.encode(encoder) })?; let encoded_der = encoder.finish().expect("encoding success"); @@ -156,7 +156,7 @@ mod tests { let mut encoder = Encoder::new(&mut in_buf); encoder.sequence(crate::PKCS_7_ENCRYPTED_DATA_OID.encoded_len()?, |encoder| { - encoder.oid(crate::PKCS_7_ENCRYPTED_DATA_OID) + (crate::PKCS_7_ENCRYPTED_DATA_OID).encode(encoder) })?; let encoded_der = encoder.finish().expect("encoding success"); @@ -195,7 +195,7 @@ mod tests { let mut encoder = Encoder::new(&mut in_buf); encoder.sequence(inner_len, |encoder| { - encoder.oid(crate::PKCS_7_DATA_OID)?; + crate::PKCS_7_DATA_OID.encode(encoder)?; encoder.context_specific( TagNumber::new(0), TagMode::Explicit, diff --git a/pkcs7/src/content_type.rs b/pkcs7/src/content_type.rs index b4d3ea155..bf6f29226 100644 --- a/pkcs7/src/content_type.rs +++ b/pkcs7/src/content_type.rs @@ -1,5 +1,5 @@ use der::asn1::ObjectIdentifier; -use der::{DecodeValue, Decoder, EncodeValue, Encoder, ErrorKind, FixedTag, Header, Length, Tag}; +use der::{DecodeValue, Decoder, EncodeValue, ErrorKind, FixedTag, Header, Length, Tag, Writer}; /// Indicates the type of content. #[derive(Copy, Clone, Debug, Eq, PartialEq)] @@ -57,8 +57,8 @@ impl EncodeValue for ContentType { self.to_oid().value_len() } - fn encode_value(&self, encoder: &mut Encoder<'_>) -> der::Result<()> { - self.to_oid().encode_value(encoder) + fn encode_value(&self, writer: &mut dyn Writer) -> der::Result<()> { + self.to_oid().encode_value(writer) } } diff --git a/pkcs7/src/data_content.rs b/pkcs7/src/data_content.rs index bd949f13e..d6e98e5b6 100644 --- a/pkcs7/src/data_content.rs +++ b/pkcs7/src/data_content.rs @@ -2,7 +2,7 @@ use core::convert::{From, TryFrom}; use der::{ - asn1::OctetString, DecodeValue, Decoder, EncodeValue, Encoder, FixedTag, Header, Length, Tag, + asn1::OctetString, DecodeValue, Decoder, EncodeValue, FixedTag, Header, Length, Tag, Writer, }; /// The content that is just an octet string. @@ -43,8 +43,8 @@ impl<'a> EncodeValue for DataContent<'a> { Length::try_from(self.content.len()) } - fn encode_value(&self, encoder: &mut Encoder<'_>) -> der::Result<()> { - OctetString::new(self.content)?.encode_value(encoder) + fn encode_value(&self, writer: &mut dyn Writer) -> der::Result<()> { + OctetString::new(self.content)?.encode_value(writer) } } diff --git a/pkcs7/src/encrypted_data_content.rs b/pkcs7/src/encrypted_data_content.rs index 315bf4379..557a8a865 100644 --- a/pkcs7/src/encrypted_data_content.rs +++ b/pkcs7/src/encrypted_data_content.rs @@ -2,8 +2,8 @@ use crate::enveloped_data_content::EncryptedContentInfo; use der::{ - Decode, DecodeValue, Decoder, Encode, EncodeValue, Encoder, FixedTag, Header, Length, Sequence, - Tag, + Decode, DecodeValue, Decoder, Encode, EncodeValue, FixedTag, Header, Length, Sequence, Tag, + Writer, }; /// Syntax version of the `encrypted-data` content type. @@ -51,8 +51,8 @@ impl EncodeValue for Version { u8::from(*self).value_len() } - fn encode_value(&self, encoder: &mut Encoder<'_>) -> der::Result<()> { - u8::from(*self).encode_value(encoder) + fn encode_value(&self, writer: &mut dyn Writer) -> der::Result<()> { + u8::from(*self).encode_value(writer) } } diff --git a/pkcs8/src/version.rs b/pkcs8/src/version.rs index f9f65981a..09684782b 100644 --- a/pkcs8/src/version.rs +++ b/pkcs8/src/version.rs @@ -1,7 +1,7 @@ //! PKCS#8 version identifier. use crate::Error; -use der::{Decode, Decoder, Encode, Encoder, FixedTag, Tag}; +use der::{Decode, Decoder, Encode, FixedTag, Tag, Writer}; /// Version identifier for PKCS#8 documents. /// @@ -36,8 +36,8 @@ impl Encode for Version { der::Length::from(1u8).for_tlv() } - fn encode(&self, encoder: &mut Encoder<'_>) -> der::Result<()> { - u8::from(*self).encode(encoder) + fn encode(&self, writer: &mut dyn Writer) -> der::Result<()> { + u8::from(*self).encode(writer) } } diff --git a/sec1/src/parameters.rs b/sec1/src/parameters.rs index 249f16b84..623cec3f0 100644 --- a/sec1/src/parameters.rs +++ b/sec1/src/parameters.rs @@ -1,6 +1,6 @@ use der::{ asn1::{Any, ObjectIdentifier}, - DecodeValue, Decoder, EncodeValue, Encoder, FixedTag, Header, Length, Tag, + DecodeValue, Decoder, EncodeValue, FixedTag, Header, Length, Tag, Writer, }; /// Elliptic curve parameters as described in @@ -41,9 +41,9 @@ impl EncodeValue for EcParameters { } } - fn encode_value(&self, encoder: &mut Encoder<'_>) -> der::Result<()> { + fn encode_value(&self, writer: &mut dyn Writer) -> der::Result<()> { match self { - Self::NamedCurve(oid) => oid.encode_value(encoder), + Self::NamedCurve(oid) => oid.encode_value(writer), } } }