| 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; |
| } |