Skip to content

Commit

Permalink
der: add EncodingRules enum
Browse files Browse the repository at this point in the history
Adds an enum with `Ber` and `Der` (default) variants which can be used
to selectively allow a limited number of BER productions when decoding
certain BER-based security-oriented formats, e.g. CMS, PKCS#8.

Currently this doesn't actually do anything, however the goal is to
address #779, where we can't decode CMS generated by Apple tooling.

PR #810 is an example of how the rules could be relaxed to support
`IndefiniteLength`s.
  • Loading branch information
tarcieri committed Jan 9, 2024
1 parent e97d077 commit d84d7e0
Show file tree
Hide file tree
Showing 6 changed files with 50 additions and 7 deletions.
18 changes: 18 additions & 0 deletions der/src/encoding_rules.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
/// ASN.1 encoding rules.
///
/// This enum identifies the specific encoding rules which are applied at the time a given document
/// is decoded from a byte/octet serialization.
///
/// In addition to the Distinguished Encoding Rules (DER), this crate also supports a strict subset
/// of the Basic Encoding Rules (BER) which supports the minimum amount of additional productions
/// beyond DER needed to interoperate with other implementations of cryptography-oriented formats
/// which utilize BER, e.g. CMS, PKCS#8.
#[derive(Clone, Copy, Debug, Default, Eq, PartialEq, PartialOrd, Ord)]
pub enum EncodingRules {
/// Basic Encoding Rules.
Ber,

/// Distinguished Encoding Rules.
#[default]
Der,
}
2 changes: 2 additions & 0 deletions der/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -337,6 +337,7 @@ mod datetime;
mod decode;
mod encode;
mod encode_ref;
mod encoding_rules;
mod error;
mod header;
mod length;
Expand All @@ -359,6 +360,7 @@ pub use crate::{
decode::{Decode, DecodeOwned, DecodeValue},
encode::{Encode, EncodeValue},
encode_ref::{EncodeRef, EncodeValueRef},
encoding_rules::EncodingRules,
error::{Error, ErrorKind, Result},
header::Header,
length::{IndefiniteLength, Length},
Expand Down
7 changes: 5 additions & 2 deletions der/src/reader.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,15 +8,18 @@ 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,
asn1::ContextSpecific, Decode, DecodeValue, Encode, EncodingRules, 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 [`EncodingRules`] which should be applied when decoding the input.
fn encoding_rules(&self) -> EncodingRules;

/// Get the length of the input.
fn input_len(&self) -> Length;

Expand Down
6 changes: 5 additions & 1 deletion der/src/reader/nested.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
//! Reader type for consuming nested TLV records within a DER document.

use crate::{reader::Reader, Error, ErrorKind, Header, Length, Result};
use crate::{reader::Reader, EncodingRules, Error, ErrorKind, Header, Length, Result};

/// Reader type used by [`Reader::read_nested`].
pub struct NestedReader<'i, R> {
Expand Down Expand Up @@ -51,6 +51,10 @@ impl<'i, 'r, R: Reader<'r>> NestedReader<'i, R> {
}

impl<'i, 'r, R: Reader<'r>> Reader<'r> for NestedReader<'i, R> {
fn encoding_rules(&self) -> EncodingRules {
self.inner.encoding_rules()
}

fn input_len(&self) -> Length {
self.input_len
}
Expand Down
12 changes: 9 additions & 3 deletions der/src/reader/pem.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
//! Streaming PEM reader.

use super::Reader;
use crate::{Decode, Error, ErrorKind, Header, Length, Result};
use crate::{Decode, EncodingRules, Error, ErrorKind, Header, Length, Result};
use core::cell::RefCell;

#[allow(clippy::arithmetic_side_effects)]
Expand Down Expand Up @@ -86,9 +86,7 @@ mod utils {
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()
Expand Down Expand Up @@ -130,6 +128,9 @@ pub struct PemReader<'i> {
/// Inner PEM decoder wrapped in a BufReader.
reader: RefCell<utils::BufReader<'i>>,

/// Encoding rules to apply when decoding the input.
encoding_rules: EncodingRules,

/// Input length (in bytes after Base64 decoding).
input_len: Length,

Expand All @@ -148,6 +149,7 @@ impl<'i> PemReader<'i> {

Ok(Self {
reader: RefCell::new(reader),
encoding_rules: EncodingRules::default(),
input_len,
position: Length::ZERO,
})
Expand All @@ -162,6 +164,10 @@ impl<'i> PemReader<'i> {

#[cfg(feature = "pem")]
impl<'i> Reader<'i> for PemReader<'i> {
fn encoding_rules(&self) -> EncodingRules {
self.encoding_rules
}

fn input_len(&self) -> Length {
self.input_len
}
Expand Down
12 changes: 11 additions & 1 deletion der/src/reader/slice.rs
Original file line number Diff line number Diff line change
@@ -1,13 +1,18 @@
//! Slice reader.

use crate::{BytesRef, Decode, Error, ErrorKind, Header, Length, Reader, Result, Tag};
use crate::{
BytesRef, Decode, EncodingRules, 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>,

/// Encoding rules to apply when decoding the input.
encoding_rules: EncodingRules,

/// Did the decoding operation fail?
failed: bool,

Expand All @@ -20,6 +25,7 @@ impl<'a> SliceReader<'a> {
pub fn new(bytes: &'a [u8]) -> Result<Self> {
Ok(Self {
bytes: BytesRef::new(bytes)?,
encoding_rules: EncodingRules::default(),
failed: false,
position: Length::ZERO,
})
Expand Down Expand Up @@ -57,6 +63,10 @@ impl<'a> SliceReader<'a> {
}

impl<'a> Reader<'a> for SliceReader<'a> {
fn encoding_rules(&self) -> EncodingRules {
self.encoding_rules
}

fn input_len(&self) -> Length {
self.bytes.len()
}
Expand Down

0 comments on commit d84d7e0

Please sign in to comment.