asn1_rs/
from_der.rs

1use core::convert::{TryFrom, TryInto};
2use core::fmt::{Debug, Display};
3
4use nom::bytes::streaming::take;
5use nom::error::ParseError;
6use nom::{Err, IResult, Input as _};
7
8use crate::debug::{trace_generic, trace_input};
9use crate::{
10    parse_der_any, wrap_ber_parser, Any, BerError, DerMode, DynTagged, Error, GetObjectContent,
11    Header, Input, ParseResult, Result, MAX_RECURSION,
12};
13
14/// Base trait for DER object parsers
15///
16/// # Notes
17///
18/// *This trait might become deprecated soon! Instead of this one, implement trait [`DerParser`].*
19///
20/// Library authors should usually not directly implement this trait, but should prefer implementing the
21/// [`TryFrom<Any>`] + [`CheckDerConstraints`] traits,
22/// which offers greater flexibility and provides an equivalent `FromDer` implementation for free
23/// (in fact, it provides both [`FromBer`](crate::FromBer) and [`FromDer`]).
24///
25/// Note: if you already implemented [`TryFrom<Any>`] and [`CheckDerConstraints`],
26/// you can get a free [`FromDer`] implementation by implementing the
27/// [`DerAutoDerive`] trait. This is not automatic, so it is also possible to manually
28/// implement [`FromDer`] if preferred.
29///
30/// # Examples
31///
32/// ```
33/// use asn1_rs::{Any, CheckDerConstraints, DerAutoDerive, Result, Tag};
34/// use std::convert::TryFrom;
35///
36/// // The type to be decoded
37/// #[derive(Clone, Copy, Debug, PartialEq, Eq)]
38/// pub struct MyType(pub u32);
39///
40/// impl<'a> TryFrom<Any<'a>> for MyType {
41///     type Error = asn1_rs::Error;
42///
43///     fn try_from(any: Any<'a>) -> Result<MyType> {
44///         any.tag().assert_eq(Tag::Integer)?;
45///         // for this fictive example, the type contains the number of characters
46///         let n = any.data.len() as u32;
47///         Ok(MyType(n))
48///     }
49/// }
50///
51/// impl CheckDerConstraints for MyType {
52///     fn check_constraints(any: &Any) -> Result<()> {
53///         any.header.assert_primitive()?;
54///         Ok(())
55///     }
56/// }
57///
58/// impl DerAutoDerive for MyType {}
59///
60/// // The above code provides a `FromDer` implementation for free.
61///
62/// // Example of parsing code:
63/// use asn1_rs::FromDer;
64///
65/// let input = &[2, 1, 2];
66/// // Objects can be parsed using `from_der`, which returns the remaining bytes
67/// // and the parsed object:
68/// let (rem, my_type) = MyType::from_der(input).expect("parsing failed");
69/// ```
70pub trait FromDer<'a, E = Error>: Sized {
71    /// Attempt to parse input bytes into a DER object (enforcing constraints)
72    fn from_der(bytes: &'a [u8]) -> ParseResult<'a, Self, E>;
73}
74
75/// Trait to automatically derive `FromDer`
76///
77/// This trait is only a marker to control if a DER parser should be automatically derived. It is
78/// empty.
79///
80/// This trait is used in combination with others:
81/// after implementing [`TryFrom<Any>`] and [`CheckDerConstraints`] for a type,
82/// a free [`FromDer`] implementation is provided by implementing the
83/// [`DerAutoDerive`] trait. This is the most common case.
84///
85/// However, this is not automatic so it is also possible to manually
86/// implement [`FromDer`] if preferred.
87/// Manual implementation is generally only needed for generic containers (for ex. `Vec<T>`),
88/// because the default implementation adds a constraint on `T` to implement also `TryFrom<Any>`
89/// and `CheckDerConstraints`. This is problematic when `T` only provides `FromDer`, and can be
90/// solved by providing a manual implementation of [`FromDer`].
91pub trait DerAutoDerive {}
92
93impl<'a, T, E> FromDer<'a, E> for T
94where
95    T: TryFrom<Any<'a>, Error = E>,
96    T: CheckDerConstraints,
97    T: DerAutoDerive,
98    E: From<Error> + Display + Debug,
99{
100    fn from_der(bytes: &'a [u8]) -> ParseResult<'a, T, E> {
101        trace_generic(
102            core::any::type_name::<T>(),
103            "T::from_der",
104            |bytes| {
105                let (i, any) = wrap_ber_parser(parse_der_any)(bytes).map_err(Err::convert)?;
106                <T as CheckDerConstraints>::check_constraints(&any)
107                    .map_err(|e| Err::Error(e.into()))?;
108                let result = any.try_into().map_err(Err::Error)?;
109                Ok((i, result))
110            },
111            bytes,
112        )
113    }
114}
115
116/// Verification of DER constraints
117pub trait CheckDerConstraints {
118    fn check_constraints(any: &Any) -> Result<()>;
119}
120
121/// Base trait for DER object parsers
122///
123/// Implementers should provide a definition for the following:
124/// - method [`from_der_content`](DerParser::from_der_content): Parse DER content, given a header and data
125/// - trait [`DynTagged`]
126///
127/// This trait can be automatically derived from a `struct` using the [`DerParserSequence`](crate::DerParserSequence)
128/// or [`DerParserSet`](crate::DerParserSet) custom derive attributes.
129pub trait DerParser<'i>
130where
131    Self: Sized,
132    Self: DynTagged,
133{
134    /// The Error type for parsing errors.
135    type Error: Display + ParseError<Input<'i>> + From<BerError<Input<'i>>>;
136
137    /// Attempt to parse a new DER object from data.
138    ///
139    /// Header tag must match expected tag, and length must be definite.
140    fn parse_der(input: Input<'i>) -> IResult<Input<'i>, Self, Self::Error> {
141        trace_input("DerParser::parse_der", |input| {
142            let (rem, header) = Header::parse_der(input.clone()).map_err(Err::convert)?;
143            // get length, rejecting indefinite (invalid for DER)
144            let length = header
145                .length
146                .definite_inner()
147                .map_err(BerError::convert_into(input.clone()))?;
148            if !Self::accept_tag(header.tag) {
149                return Err(Err::Error(
150                    // TODO: expected Tag is `None`, so the error will not be helpful
151                    BerError::unexpected_tag(input, None, header.tag).into(),
152                ));
153            }
154            let (rem, data) = take(length)(rem)?;
155            let (_, obj) = trace_input("DerParser::from_der_content", |i| {
156                // wrap from_der_content function to display better errors, if any
157                Self::from_der_content(&header, i)
158            })(data)
159            .map_err(Err::convert)?;
160            Ok((rem, obj))
161        })(input)
162    }
163
164    /// Parse a new DER object from header and data.
165    ///
166    /// `input` length is (supposed to be) guaranteed to match `header` length (definite)
167    ///
168    /// This function also checks DER-related constraints.
169    /// Relevant sections in specifications:
170    /// - Canonical encoding rules (X.690: 9)
171    /// - Distinguished encoding rules (X.690: 10)
172    /// - Restrictions on BER employed by both CER and DER (X.690: 11)
173    ///
174    /// Note: in this method, implementers should *not* check header tag (which can be
175    /// different from the usual object tag when using IMPLICIT tagging, for ex.).
176    fn from_der_content(
177        header: &'_ Header<'i>,
178        input: Input<'i>,
179    ) -> IResult<Input<'i>, Self, Self::Error>;
180
181    fn parse_der_optional(input: Input<'i>) -> IResult<Input<'i>, Option<Self>, Self::Error> {
182        if input.input_len() == 0 {
183            return Ok((input, None));
184        }
185        let (rem, header) = Header::parse_der(input.clone()).map_err(Err::convert)?;
186        if !Self::accept_tag(header.tag) {
187            return Ok((input, None));
188        }
189        // get length, rejecting indefinite (invalid for DER)
190        let length = header
191            .length
192            .definite_inner()
193            .map_err(BerError::convert_into(input.clone()))?;
194        let (rem, data) = take(length)(rem)?;
195        let (_, obj) = Self::from_der_content(&header, data).map_err(Err::convert)?;
196        Ok((rem, Some(obj)))
197    }
198
199    /// Parse object header (validating tag) and return header and content as `Input`
200    fn parse_der_as_input(
201        input: Input<'i>,
202    ) -> IResult<Input<'i>, (Header<'i>, Input<'i>), Self::Error> {
203        trace_input("DerParser::parse_der_as_input", |input| {
204            let (rem, header) = Header::parse_der(input.clone()).map_err(Err::convert)?;
205            if !Self::accept_tag(header.tag) {
206                return Err(Err::Error(
207                    // FIXME: expected Tag is `None`, so the error will not be helpful
208                    BerError::unexpected_tag(input, None, header.tag).into(),
209                ));
210            }
211            let (rem, data) =
212                DerMode::get_object_content(&header, rem, MAX_RECURSION).map_err(Err::convert)?;
213
214            Ok((rem, (header, data)))
215        })(input)
216    }
217}