asn1_rs/
traits.rs

1use crate::error::*;
2use crate::{Any, Class, Explicit, Implicit, Tag, TaggedParser};
3use core::convert::{TryFrom, TryInto};
4#[cfg(feature = "std")]
5use std::io::Write;
6
7/// Phantom type representing a BER parser
8#[doc(hidden)]
9#[derive(Debug)]
10pub enum BerParser {}
11
12/// Phantom type representing a DER parser
13#[doc(hidden)]
14#[derive(Debug)]
15pub enum DerParser {}
16
17#[doc(hidden)]
18pub trait ASN1Parser {}
19
20impl ASN1Parser for BerParser {}
21impl ASN1Parser for DerParser {}
22
23pub trait Tagged {
24    const TAG: Tag;
25}
26
27impl<T> Tagged for &'_ T
28where
29    T: Tagged,
30{
31    const TAG: Tag = T::TAG;
32}
33
34pub trait DynTagged {
35    fn tag(&self) -> Tag;
36}
37
38impl<T> DynTagged for T
39where
40    T: Tagged,
41{
42    fn tag(&self) -> Tag {
43        T::TAG
44    }
45}
46
47/// Base trait for BER object parsers
48///
49/// Library authors should usually not directly implement this trait, but should prefer implementing the
50/// [`TryFrom<Any>`] trait,
51/// which offers greater flexibility and provides an equivalent `FromBer` implementation for free.
52///
53/// # Examples
54///
55/// ```
56/// use asn1_rs::{Any, Result, Tag};
57/// use std::convert::TryFrom;
58///
59/// // The type to be decoded
60/// #[derive(Clone, Copy, Debug, PartialEq, Eq)]
61/// pub struct MyType(pub u32);
62///
63/// impl<'a> TryFrom<Any<'a>> for MyType {
64///     type Error = asn1_rs::Error;
65///
66///     fn try_from(any: Any<'a>) -> Result<MyType> {
67///         any.tag().assert_eq(Tag::Integer)?;
68///         // for this fictive example, the type contains the number of characters
69///         let n = any.data.len() as u32;
70///         Ok(MyType(n))
71///     }
72/// }
73///
74/// // The above code provides a `FromBer` implementation for free.
75///
76/// // Example of parsing code:
77/// use asn1_rs::FromBer;
78///
79/// let input = &[2, 1, 2];
80/// // Objects can be parsed using `from_ber`, which returns the remaining bytes
81/// // and the parsed object:
82/// let (rem, my_type) = MyType::from_ber(input).expect("parsing failed");
83/// ```
84pub trait FromBer<'a, E = Error>: Sized {
85    /// Attempt to parse input bytes into a BER object
86    fn from_ber(bytes: &'a [u8]) -> ParseResult<Self, E>;
87}
88
89impl<'a, T, E> FromBer<'a, E> for T
90where
91    T: TryFrom<Any<'a>, Error = E>,
92    E: From<Error>,
93{
94    fn from_ber(bytes: &'a [u8]) -> ParseResult<T, E> {
95        let (i, any) = Any::from_ber(bytes).map_err(nom::Err::convert)?;
96        let result = any.try_into().map_err(nom::Err::Error)?;
97        Ok((i, result))
98    }
99}
100
101/// Base trait for DER object parsers
102///
103/// Library authors should usually not directly implement this trait, but should prefer implementing the
104/// [`TryFrom<Any>`] + [`CheckDerConstraints`] traits,
105/// which offers greater flexibility and provides an equivalent `FromDer` implementation for free
106/// (in fact, it provides both [`FromBer`] and `FromDer`).
107///
108/// Note: if you already implemented [`TryFrom<Any>`] and [`CheckDerConstraints`],
109/// you can get a free [`FromDer`] implementation by implementing the
110/// [`DerAutoDerive`] trait. This is not automatic, so it is also possible to manually
111/// implement [`FromDer`] if preferred.
112///
113/// # Examples
114///
115/// ```
116/// use asn1_rs::{Any, CheckDerConstraints, DerAutoDerive, Result, Tag};
117/// use std::convert::TryFrom;
118///
119/// // The type to be decoded
120/// #[derive(Clone, Copy, Debug, PartialEq, Eq)]
121/// pub struct MyType(pub u32);
122///
123/// impl<'a> TryFrom<Any<'a>> for MyType {
124///     type Error = asn1_rs::Error;
125///
126///     fn try_from(any: Any<'a>) -> Result<MyType> {
127///         any.tag().assert_eq(Tag::Integer)?;
128///         // for this fictive example, the type contains the number of characters
129///         let n = any.data.len() as u32;
130///         Ok(MyType(n))
131///     }
132/// }
133///
134/// impl CheckDerConstraints for MyType {
135///     fn check_constraints(any: &Any) -> Result<()> {
136///         any.header.assert_primitive()?;
137///         Ok(())
138///     }
139/// }
140///
141/// impl DerAutoDerive for MyType {}
142///
143/// // The above code provides a `FromDer` implementation for free.
144///
145/// // Example of parsing code:
146/// use asn1_rs::FromDer;
147///
148/// let input = &[2, 1, 2];
149/// // Objects can be parsed using `from_der`, which returns the remaining bytes
150/// // and the parsed object:
151/// let (rem, my_type) = MyType::from_der(input).expect("parsing failed");
152/// ```
153pub trait FromDer<'a, E = Error>: Sized {
154    /// Attempt to parse input bytes into a DER object (enforcing constraints)
155    fn from_der(bytes: &'a [u8]) -> ParseResult<Self, E>;
156}
157
158/// Trait to automatically derive `FromDer`
159///
160/// This trait is only a marker to control if a DER parser should be automatically derived. It is
161/// empty.
162///
163/// This trait is used in combination with others:
164/// after implementing [`TryFrom<Any>`] and [`CheckDerConstraints`] for a type,
165/// a free [`FromDer`] implementation is provided by implementing the
166/// [`DerAutoDerive`] trait. This is the most common case.
167///
168/// However, this is not automatic so it is also possible to manually
169/// implement [`FromDer`] if preferred.
170/// Manual implementation is generally only needed for generic containers (for ex. `Vec<T>`),
171/// because the default implementation adds a constraint on `T` to implement also `TryFrom<Any>`
172/// and `CheckDerConstraints`. This is problematic when `T` only provides `FromDer`, and can be
173/// solved by providing a manual implementation of [`FromDer`].
174pub trait DerAutoDerive {}
175
176impl<'a, T, E> FromDer<'a, E> for T
177where
178    T: TryFrom<Any<'a>, Error = E>,
179    T: CheckDerConstraints,
180    T: DerAutoDerive,
181    E: From<Error>,
182{
183    fn from_der(bytes: &'a [u8]) -> ParseResult<T, E> {
184        // Note: Any::from_der checks than length is definite
185        let (i, any) = Any::from_der(bytes).map_err(nom::Err::convert)?;
186        <T as CheckDerConstraints>::check_constraints(&any)
187            .map_err(|e| nom::Err::Error(e.into()))?;
188        let result = any.try_into().map_err(nom::Err::Error)?;
189        Ok((i, result))
190    }
191}
192
193/// Verification of DER constraints
194pub trait CheckDerConstraints {
195    fn check_constraints(any: &Any) -> Result<()>;
196}
197
198/// Common trait for all objects that can be encoded using the DER representation
199///
200/// # Examples
201///
202/// Objects from this crate can be encoded as DER:
203///
204/// ```
205/// use asn1_rs::{Integer, ToDer};
206///
207/// let int = Integer::from(4u32);
208/// let mut writer = Vec::new();
209/// let sz = int.write_der(&mut writer).expect("serialization failed");
210///
211/// assert_eq!(&writer, &[0x02, 0x01, 0x04]);
212/// # assert_eq!(sz, 3);
213/// ```
214///
215/// Many of the primitive types can also directly be encoded as DER:
216///
217/// ```
218/// use asn1_rs::ToDer;
219///
220/// let mut writer = Vec::new();
221/// let sz = 4.write_der(&mut writer).expect("serialization failed");
222///
223/// assert_eq!(&writer, &[0x02, 0x01, 0x04]);
224/// # assert_eq!(sz, 3);
225/// ```
226#[cfg(feature = "std")]
227pub trait ToDer
228where
229    Self: DynTagged,
230{
231    /// Get the length of the object (including the header), when encoded
232    ///
233    // Since we are using DER, length cannot be Indefinite, so we can use `usize`.
234    // XXX can this function fail?
235    fn to_der_len(&self) -> Result<usize>;
236
237    /// Write the DER encoded representation to a newly allocated `Vec<u8>`.
238    fn to_der_vec(&self) -> SerializeResult<Vec<u8>> {
239        let mut v = Vec::new();
240        let _ = self.write_der(&mut v)?;
241        Ok(v)
242    }
243
244    /// Similar to using `to_vec`, but uses provided values without changes.
245    /// This can generate an invalid encoding for a DER object.
246    fn to_der_vec_raw(&self) -> SerializeResult<Vec<u8>> {
247        let mut v = Vec::new();
248        let _ = self.write_der_raw(&mut v)?;
249        Ok(v)
250    }
251
252    /// Attempt to write the DER encoded representation (header and content) into this writer.
253    ///
254    /// # Examples
255    ///
256    /// ```
257    /// use asn1_rs::{Integer, ToDer};
258    ///
259    /// let int = Integer::from(4u32);
260    /// let mut writer = Vec::new();
261    /// let sz = int.write_der(&mut writer).expect("serialization failed");
262    ///
263    /// assert_eq!(&writer, &[0x02, 0x01, 0x04]);
264    /// # assert_eq!(sz, 3);
265    /// ```
266    fn write_der(&self, writer: &mut dyn Write) -> SerializeResult<usize> {
267        let sz = self.write_der_header(writer)?;
268        let sz = sz + self.write_der_content(writer)?;
269        Ok(sz)
270    }
271
272    /// Attempt to write the DER header to this writer.
273    fn write_der_header(&self, writer: &mut dyn Write) -> SerializeResult<usize>;
274
275    /// Attempt to write the DER content (all except header) to this writer.
276    fn write_der_content(&self, writer: &mut dyn Write) -> SerializeResult<usize>;
277
278    /// Similar to using `to_der`, but uses provided values without changes.
279    /// This can generate an invalid encoding for a DER object.
280    fn write_der_raw(&self, writer: &mut dyn Write) -> SerializeResult<usize> {
281        self.write_der(writer)
282    }
283}
284
285#[cfg(feature = "std")]
286impl<'a, T> ToDer for &'a T
287where
288    T: ToDer,
289    &'a T: DynTagged,
290{
291    fn to_der_len(&self) -> Result<usize> {
292        (*self).to_der_len()
293    }
294
295    fn write_der_header(&self, writer: &mut dyn Write) -> SerializeResult<usize> {
296        (*self).write_der_header(writer)
297    }
298
299    fn write_der_content(&self, writer: &mut dyn Write) -> SerializeResult<usize> {
300        (*self).write_der_content(writer)
301    }
302}
303
304/// Helper trait for creating tagged EXPLICIT values
305///
306/// # Examples
307///
308/// ```
309/// use asn1_rs::{AsTaggedExplicit, Class, Error, TaggedParser};
310///
311/// // create a `[1] EXPLICIT INTEGER` value
312/// let tagged: TaggedParser<_, _, Error> = 4u32.explicit(Class::ContextSpecific, 1);
313/// ```
314pub trait AsTaggedExplicit<'a, E = Error>: Sized {
315    fn explicit(self, class: Class, tag: u32) -> TaggedParser<'a, Explicit, Self, E> {
316        TaggedParser::new_explicit(class, tag, self)
317    }
318}
319
320impl<'a, T, E> AsTaggedExplicit<'a, E> for T where T: Sized + 'a {}
321
322/// Helper trait for creating tagged IMPLICIT values
323///
324/// # Examples
325///
326/// ```
327/// use asn1_rs::{AsTaggedImplicit, Class, Error, TaggedParser};
328///
329/// // create a `[1] IMPLICIT INTEGER` value, not constructed
330/// let tagged: TaggedParser<_, _, Error> = 4u32.implicit(Class::ContextSpecific, false, 1);
331/// ```
332pub trait AsTaggedImplicit<'a, E = Error>: Sized {
333    fn implicit(
334        self,
335        class: Class,
336        constructed: bool,
337        tag: u32,
338    ) -> TaggedParser<'a, Implicit, Self, E> {
339        TaggedParser::new_implicit(class, constructed, tag, self)
340    }
341}
342
343impl<'a, T, E> AsTaggedImplicit<'a, E> for T where T: Sized + 'a {}
344
345pub trait ToStatic {
346    type Owned: 'static;
347    fn to_static(&self) -> Self::Owned;
348}