blob: eea4cb98d7f9704c84b297268f6ea581c4e3ab56 [file] [log] [blame]
use crate::error::*;
use crate::{Any, Class, Explicit, Implicit, Tag, TaggedParser};
use core::convert::{TryFrom, TryInto};
#[cfg(feature = "std")]
use std::io::Write;
/// Phantom type representing a BER parser
#[doc(hidden)]
#[derive(Debug)]
pub enum BerParser {}
/// Phantom type representing a DER parser
#[doc(hidden)]
#[derive(Debug)]
pub enum DerParser {}
#[doc(hidden)]
pub trait ASN1Parser {}
impl ASN1Parser for BerParser {}
impl ASN1Parser for DerParser {}
pub trait Tagged {
const TAG: Tag;
}
impl<T> Tagged for &'_ T
where
T: Tagged,
{
const TAG: Tag = T::TAG;
}
pub trait DynTagged {
fn tag(&self) -> Tag;
}
impl<T> DynTagged for T
where
T: Tagged,
{
fn tag(&self) -> Tag {
T::TAG
}
}
/// Base trait for BER object parsers
///
/// Library authors should usually not directly implement this trait, but should prefer implementing the
/// [`TryFrom<Any>`] trait,
/// which offers greater flexibility and provides an equivalent `FromBer` implementation for free.
///
/// # Examples
///
/// ```
/// use asn1_rs::{Any, Result, Tag};
/// use std::convert::TryFrom;
///
/// // The type to be decoded
/// #[derive(Clone, Copy, Debug, PartialEq, Eq)]
/// pub struct MyType(pub u32);
///
/// impl<'a> TryFrom<Any<'a>> for MyType {
/// type Error = asn1_rs::Error;
///
/// fn try_from(any: Any<'a>) -> Result<MyType> {
/// any.tag().assert_eq(Tag::Integer)?;
/// // for this fictive example, the type contains the number of characters
/// let n = any.data.len() as u32;
/// Ok(MyType(n))
/// }
/// }
///
/// // The above code provides a `FromBer` implementation for free.
///
/// // Example of parsing code:
/// use asn1_rs::FromBer;
///
/// let input = &[2, 1, 2];
/// // Objects can be parsed using `from_ber`, which returns the remaining bytes
/// // and the parsed object:
/// let (rem, my_type) = MyType::from_ber(input).expect("parsing failed");
/// ```
pub trait FromBer<'a, E = Error>: Sized {
/// Attempt to parse input bytes into a BER object
fn from_ber(bytes: &'a [u8]) -> ParseResult<Self, E>;
}
impl<'a, T, E> FromBer<'a, E> for T
where
T: TryFrom<Any<'a>, Error = E>,
E: From<Error>,
{
fn from_ber(bytes: &'a [u8]) -> ParseResult<T, E> {
let (i, any) = Any::from_ber(bytes).map_err(nom::Err::convert)?;
let result = any.try_into().map_err(nom::Err::Error)?;
Ok((i, result))
}
}
/// Base trait for DER object parsers
///
/// Library authors should usually not directly implement this trait, but should prefer implementing the
/// [`TryFrom<Any>`] + [`CheckDerConstraints`] traits,
/// which offers greater flexibility and provides an equivalent `FromDer` implementation for free
/// (in fact, it provides both [`FromBer`] and `FromDer`).
///
/// Note: if you already implemented [`TryFrom<Any>`] and [`CheckDerConstraints`],
/// you can get a free [`FromDer`] implementation by implementing the
/// [`DerAutoDerive`] trait. This is not automatic, so it is also possible to manually
/// implement [`FromDer`] if preferred.
///
/// # Examples
///
/// ```
/// use asn1_rs::{Any, CheckDerConstraints, DerAutoDerive, Result, Tag};
/// use std::convert::TryFrom;
///
/// // The type to be decoded
/// #[derive(Clone, Copy, Debug, PartialEq, Eq)]
/// pub struct MyType(pub u32);
///
/// impl<'a> TryFrom<Any<'a>> for MyType {
/// type Error = asn1_rs::Error;
///
/// fn try_from(any: Any<'a>) -> Result<MyType> {
/// any.tag().assert_eq(Tag::Integer)?;
/// // for this fictive example, the type contains the number of characters
/// let n = any.data.len() as u32;
/// Ok(MyType(n))
/// }
/// }
///
/// impl CheckDerConstraints for MyType {
/// fn check_constraints(any: &Any) -> Result<()> {
/// any.header.assert_primitive()?;
/// Ok(())
/// }
/// }
///
/// impl DerAutoDerive for MyType {}
///
/// // The above code provides a `FromDer` implementation for free.
///
/// // Example of parsing code:
/// use asn1_rs::FromDer;
///
/// let input = &[2, 1, 2];
/// // Objects can be parsed using `from_der`, which returns the remaining bytes
/// // and the parsed object:
/// let (rem, my_type) = MyType::from_der(input).expect("parsing failed");
/// ```
pub trait FromDer<'a, E = Error>: Sized {
/// Attempt to parse input bytes into a DER object (enforcing constraints)
fn from_der(bytes: &'a [u8]) -> ParseResult<Self, E>;
}
/// Trait to automatically derive `FromDer`
///
/// This trait is only a marker to control if a DER parser should be automatically derived. It is
/// empty.
///
/// This trait is used in combination with others:
/// after implementing [`TryFrom<Any>`] and [`CheckDerConstraints`] for a type,
/// a free [`FromDer`] implementation is provided by implementing the
/// [`DerAutoDerive`] trait. This is the most common case.
///
/// However, this is not automatic so it is also possible to manually
/// implement [`FromDer`] if preferred.
/// Manual implementation is generally only needed for generic containers (for ex. `Vec<T>`),
/// because the default implementation adds a constraint on `T` to implement also `TryFrom<Any>`
/// and `CheckDerConstraints`. This is problematic when `T` only provides `FromDer`, and can be
/// solved by providing a manual implementation of [`FromDer`].
pub trait DerAutoDerive {}
impl<'a, T, E> FromDer<'a, E> for T
where
T: TryFrom<Any<'a>, Error = E>,
T: CheckDerConstraints,
T: DerAutoDerive,
E: From<Error>,
{
fn from_der(bytes: &'a [u8]) -> ParseResult<T, E> {
// Note: Any::from_der checks than length is definite
let (i, any) = Any::from_der(bytes).map_err(nom::Err::convert)?;
<T as CheckDerConstraints>::check_constraints(&any)
.map_err(|e| nom::Err::Error(e.into()))?;
let result = any.try_into().map_err(nom::Err::Error)?;
Ok((i, result))
}
}
/// Verification of DER constraints
pub trait CheckDerConstraints {
fn check_constraints(any: &Any) -> Result<()>;
}
/// Common trait for all objects that can be encoded using the DER representation
///
/// # Examples
///
/// Objects from this crate can be encoded as DER:
///
/// ```
/// use asn1_rs::{Integer, ToDer};
///
/// let int = Integer::from(4u32);
/// let mut writer = Vec::new();
/// let sz = int.write_der(&mut writer).expect("serialization failed");
///
/// assert_eq!(&writer, &[0x02, 0x01, 0x04]);
/// # assert_eq!(sz, 3);
/// ```
///
/// Many of the primitive types can also directly be encoded as DER:
///
/// ```
/// use asn1_rs::ToDer;
///
/// let mut writer = Vec::new();
/// let sz = 4.write_der(&mut writer).expect("serialization failed");
///
/// assert_eq!(&writer, &[0x02, 0x01, 0x04]);
/// # assert_eq!(sz, 3);
/// ```
#[cfg(feature = "std")]
pub trait ToDer
where
Self: DynTagged,
{
/// Get the length of the object (including the header), when encoded
///
// Since we are using DER, length cannot be Indefinite, so we can use `usize`.
// XXX can this function fail?
fn to_der_len(&self) -> Result<usize>;
/// Write the DER encoded representation to a newly allocated `Vec<u8>`.
fn to_der_vec(&self) -> SerializeResult<Vec<u8>> {
let mut v = Vec::new();
let _ = self.write_der(&mut v)?;
Ok(v)
}
/// Similar to using `to_vec`, but uses provided values without changes.
/// This can generate an invalid encoding for a DER object.
fn to_der_vec_raw(&self) -> SerializeResult<Vec<u8>> {
let mut v = Vec::new();
let _ = self.write_der_raw(&mut v)?;
Ok(v)
}
/// Attempt to write the DER encoded representation (header and content) into this writer.
///
/// # Examples
///
/// ```
/// use asn1_rs::{Integer, ToDer};
///
/// let int = Integer::from(4u32);
/// let mut writer = Vec::new();
/// let sz = int.write_der(&mut writer).expect("serialization failed");
///
/// assert_eq!(&writer, &[0x02, 0x01, 0x04]);
/// # assert_eq!(sz, 3);
/// ```
fn write_der(&self, writer: &mut dyn Write) -> SerializeResult<usize> {
let sz = self.write_der_header(writer)?;
let sz = sz + self.write_der_content(writer)?;
Ok(sz)
}
/// Attempt to write the DER header to this writer.
fn write_der_header(&self, writer: &mut dyn Write) -> SerializeResult<usize>;
/// Attempt to write the DER content (all except header) to this writer.
fn write_der_content(&self, writer: &mut dyn Write) -> SerializeResult<usize>;
/// Similar to using `to_der`, but uses provided values without changes.
/// This can generate an invalid encoding for a DER object.
fn write_der_raw(&self, writer: &mut dyn Write) -> SerializeResult<usize> {
self.write_der(writer)
}
}
#[cfg(feature = "std")]
impl<'a, T> ToDer for &'a T
where
T: ToDer,
&'a T: DynTagged,
{
fn to_der_len(&self) -> Result<usize> {
(*self).to_der_len()
}
fn write_der_header(&self, writer: &mut dyn Write) -> SerializeResult<usize> {
(*self).write_der_header(writer)
}
fn write_der_content(&self, writer: &mut dyn Write) -> SerializeResult<usize> {
(*self).write_der_content(writer)
}
}
/// Helper trait for creating tagged EXPLICIT values
///
/// # Examples
///
/// ```
/// use asn1_rs::{AsTaggedExplicit, Class, Error, TaggedParser};
///
/// // create a `[1] EXPLICIT INTEGER` value
/// let tagged: TaggedParser<_, _, Error> = 4u32.explicit(Class::ContextSpecific, 1);
/// ```
pub trait AsTaggedExplicit<'a, E = Error>: Sized {
fn explicit(self, class: Class, tag: u32) -> TaggedParser<'a, Explicit, Self, E> {
TaggedParser::new_explicit(class, tag, self)
}
}
impl<'a, T, E> AsTaggedExplicit<'a, E> for T where T: Sized + 'a {}
/// Helper trait for creating tagged IMPLICIT values
///
/// # Examples
///
/// ```
/// use asn1_rs::{AsTaggedImplicit, Class, Error, TaggedParser};
///
/// // create a `[1] IMPLICIT INTEGER` value, not constructed
/// let tagged: TaggedParser<_, _, Error> = 4u32.implicit(Class::ContextSpecific, false, 1);
/// ```
pub trait AsTaggedImplicit<'a, E = Error>: Sized {
fn implicit(
self,
class: Class,
constructed: bool,
tag: u32,
) -> TaggedParser<'a, Implicit, Self, E> {
TaggedParser::new_implicit(class, constructed, tag, self)
}
}
impl<'a, T, E> AsTaggedImplicit<'a, E> for T where T: Sized + 'a {}
pub trait ToStatic {
type Owned: 'static;
fn to_static(&self) -> Self::Owned;
}