diff --git a/der/src/header.rs b/der/src/header.rs index c3d5ded7b..b069d8569 100644 --- a/der/src/header.rs +++ b/der/src/header.rs @@ -14,6 +14,9 @@ pub struct Header { } impl Header { + /// Maximum number of DER octets a header can be in this crate. + pub(crate) const MAX_SIZE: usize = 1 + Length::MAX_SIZE; + /// Create a new [`Header`] from a [`Tag`] and a specified length. /// /// Returns an error if the length exceeds the limits of [`Length`]. diff --git a/der/src/length.rs b/der/src/length.rs index 726c1c7b7..0a992366b 100644 --- a/der/src/length.rs +++ b/der/src/length.rs @@ -7,10 +7,6 @@ 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; @@ -37,6 +33,10 @@ impl Length { /// Maximum length currently supported: 256 MiB pub const MAX: Self = Self(MAX_U32); + /// Maximum number of octets in a DER encoding of a [`Length`] using the + /// rules implemented by this crate. + pub(crate) const MAX_SIZE: usize = 5; + /// Create a new [`Length`] for any value which fits inside of a [`u16`]. /// /// This function is const-safe and therefore useful for [`Length`] constants. @@ -277,8 +277,8 @@ impl Encode for Length { impl DerOrd for Length { fn der_cmp(&self, other: &Self) -> Result { - let mut buf1 = [0u8; MAX_DER_OCTETS]; - let mut buf2 = [0u8; MAX_DER_OCTETS]; + let mut buf1 = [0u8; Self::MAX_SIZE]; + let mut buf2 = [0u8; Self::MAX_SIZE]; let mut encoder1 = SliceWriter::new(&mut buf1); encoder1.encode(self)?; diff --git a/der/src/reader.rs b/der/src/reader.rs index 1227d7389..0bd565930 100644 --- a/der/src/reader.rs +++ b/der/src/reader.rs @@ -20,14 +20,11 @@ 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; - - /// Peek forward in the input data, attempting to decode a [`Header`] from - /// the data at the current position in the decoder. + /// Peek at the decoded PEM without updating the internal state, writing into the provided + /// output buffer. /// - /// Does not modify the decoder's state. - fn peek_header(&self) -> Result; + /// Attempts to fill the entire buffer, returning an error if there is not enough data. + fn peek_into(&self, buf: &mut [u8]) -> crate::Result<()>; /// Get the position within the buffer. fn position(&self) -> Length; @@ -103,6 +100,31 @@ pub trait Reader<'r>: Sized { self.position() } + /// Peek at the next byte of input without modifying the cursor. + fn peek_byte(&self) -> Option { + let mut byte = [0]; + self.peek_into(&mut byte).ok().map(|_| byte[0]) + } + + /// 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 { + let mut buf = [0u8; Header::MAX_SIZE]; + + for i in 2..Header::MAX_SIZE { + let slice = &mut buf[0..i]; + if self.peek_into(slice).is_ok() { + if let Ok(header) = Header::from_der(slice) { + return Ok(header); + } + } + } + + Header::from_der(&buf) + } + /// Peek at the next byte in the decoder and attempt to decode it as a /// [`Tag`] value. /// diff --git a/der/src/reader/pem.rs b/der/src/reader/pem.rs index d8b0cb111..6a6dfada4 100644 --- a/der/src/reader/pem.rs +++ b/der/src/reader/pem.rs @@ -1,7 +1,7 @@ //! Streaming PEM reader. use super::Reader; -use crate::{Decode, EncodingRules, Error, ErrorKind, Header, Length}; +use crate::{EncodingRules, Error, ErrorKind, Length}; use pem_rfc7468::Decoder; /// `Reader` type which decodes PEM on-the-fly. @@ -45,15 +45,6 @@ impl<'i> PemReader<'i> { pub fn type_label(&self) -> &'i str { self.decoder.type_label() } - - /// Peek at the decoded PEM without updating the internal state, writing into the provided - /// output buffer. - /// - /// Attempts to fill the entire buffer, returning an error if there is not enough data. - pub fn peek_into(&self, buf: &mut [u8]) -> crate::Result<()> { - self.clone().read_into(buf)?; - Ok(()) - } } #[cfg(feature = "pem")] @@ -67,13 +58,9 @@ impl<'i> Reader<'i> for PemReader<'i> { self.input_len } - fn peek_byte(&self) -> Option { - let mut byte = [0]; - self.peek_into(&mut byte).ok().map(|_| byte[0]) - } - - fn peek_header(&self) -> crate::Result
{ - Header::decode(&mut self.clone()) + fn peek_into(&self, buf: &mut [u8]) -> crate::Result<()> { + self.clone().read_into(buf)?; + Ok(()) } fn position(&self) -> Length { diff --git a/der/src/reader/slice.rs b/der/src/reader/slice.rs index 132cb6df3..37ca797f1 100644 --- a/der/src/reader/slice.rs +++ b/der/src/reader/slice.rs @@ -1,6 +1,6 @@ //! Slice reader. -use crate::{BytesRef, Decode, EncodingRules, Error, ErrorKind, Header, Length, Reader, Tag}; +use crate::{BytesRef, Decode, EncodingRules, Error, ErrorKind, Length, Reader, Tag}; /// [`Reader`] which consumes an input byte slice. #[derive(Clone, Debug)] @@ -77,14 +77,9 @@ impl<'a> Reader<'a> for SliceReader<'a> { self.bytes.len() } - fn peek_byte(&self) -> Option { - self.remaining() - .ok() - .and_then(|bytes| bytes.first().cloned()) - } - - fn peek_header(&self) -> Result { - Header::decode(&mut self.clone()) + fn peek_into(&self, buf: &mut [u8]) -> crate::Result<()> { + self.clone().read_into(buf)?; + Ok(()) } fn position(&self) -> Length {