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}