asn1_rs/
to_der.rs

1#![cfg(feature = "std")]
2
3use std::io::Write;
4
5use crate::to_ber::*;
6use crate::{Class, Header, Length, SerializeResult, Tag};
7
8/// Common trait for DER encoding functions
9///
10/// The `Encoder` type allows specifying common encoders for objects with similar headers
11/// (for ex. primitive objects) easily.
12///
13/// # Examples
14///
15/// Objects from this crate can be encoded as DER:
16///
17/// ```
18/// use asn1_rs::{Integer, ToDer};
19///
20/// let int = Integer::from(4u32);
21/// let mut writer = Vec::new();
22/// let sz = int.der_encode(&mut writer).expect("serialization failed");
23///
24/// assert_eq!(&writer, &[0x02, 0x01, 0x04]);
25/// # assert_eq!(sz, 3);
26/// ```
27///
28/// Many of the primitive types can also directly be encoded as DER:
29///
30/// ```
31/// use asn1_rs::ToDer;
32///
33/// let mut writer = Vec::new();
34/// let sz = 4.der_encode(&mut writer).expect("serialization failed");
35///
36/// assert_eq!(&writer, &[0x02, 0x01, 0x04]);
37/// # assert_eq!(sz, 3);
38/// ```
39pub trait ToDer {
40    type Encoder: BerEncoder;
41
42    /// Returns the length of the encoded content of the object
43    ///
44    /// The length describes the _content_ only, not the header.
45    fn der_content_len(&self) -> Length;
46
47    /// Returns the total length (including header) of the encoded content of the object
48    fn der_total_len(&self) -> Length {
49        let (_, _, tag) = self.der_tag_info();
50        let content_length = self.der_content_len();
51        ber_total_length(tag, content_length)
52    }
53
54    /// Return the tag information to be encoded in header
55    fn der_tag_info(&self) -> (Class, bool, Tag);
56
57    /// Encode and write the content of the object to the writer `target`
58    ///
59    /// Returns the number of bytes written
60    fn der_write_content<W: Write>(&self, target: &mut W) -> SerializeResult<usize>;
61
62    /// Encode and write the header of the object to the writer `target`
63    ///
64    /// Returns the number of bytes written
65    fn der_write_header<W: Write>(&self, target: &mut W) -> SerializeResult<usize> {
66        let mut encoder = Self::Encoder::new();
67
68        let mut sz = 0;
69        let (class, constructed, tag) = self.der_tag_info();
70        sz += encoder.write_tag_info(class, constructed, tag, target)?;
71
72        // write length
73        let length = self.der_content_len();
74        sz += encoder.write_length(length, target)?;
75
76        Ok(sz)
77    }
78
79    /// Encode and write the object (header + content) to the writer `target`
80    ///
81    /// Returns the number of bytes written
82    fn der_encode<W: Write>(&self, target: &mut W) -> SerializeResult<usize> {
83        let sz = self.der_write_header(target)? + self.der_write_content(target)?;
84
85        Ok(sz)
86    }
87
88    /// Encode and write the object (header + content) as TAGGED EXPLICIT and write it to the writer `target`
89    ///
90    /// Usually, `class` is `Class::ContextSpecific`.
91    ///
92    /// Returns the number of bytes written
93    fn der_encode_tagged_explicit<W: Write>(
94        &self,
95        class: Class,
96        tag_number: u32,
97        target: &mut W,
98    ) -> SerializeResult<usize> {
99        let length = self.der_total_len();
100        let tagged_header = Header::new(class, true, Tag(tag_number), length);
101        let sz = tagged_header.der_write_header(target)?
102            + self.der_write_header(target)?
103            + self.der_write_content(target)?;
104
105        Ok(sz)
106    }
107
108    /// Encode and write the object (header + content) as TAGGED IMPLICIT and write it to the writer `target`
109    ///
110    /// Usually, `class` is `Class::ContextSpecific`.
111    ///
112    /// Returns the number of bytes written
113    fn der_encode_tagged_implicit<W: Write>(
114        &self,
115        class: Class,
116        tag_number: u32,
117        target: &mut W,
118    ) -> SerializeResult<usize> {
119        let length = self.der_content_len();
120        let (_, constructed, _) = self.der_tag_info();
121        let tagged_header = Header::new(class, constructed, Tag(tag_number), length);
122        let sz = tagged_header.der_write_header(target)? + self.der_write_content(target)?;
123
124        Ok(sz)
125    }
126
127    /// Write the DER encoded representation to a newly allocated `Vec<u8>`
128    fn to_der_vec(&self) -> SerializeResult<Vec<u8>> {
129        let mut v = Vec::new();
130        self.der_encode(&mut v)?;
131        Ok(v)
132    }
133
134    /// Encode in DER and write the object (header + content) to the writer `target`
135    ///
136    /// Returns the number of bytes written
137    fn write_der<W: Write>(&self, writer: &mut W) -> SerializeResult<usize> {
138        self.der_encode(writer)
139    }
140
141    //--- DEPRECATED
142
143    /// Get the length of the object (including the header), when encoded
144    ///
145    // Since we are using DER, length cannot be Indefinite
146    #[deprecated(since = "0.8.0", note = "Use `der_total_len()` instead.")]
147    fn to_der_len(&self) -> crate::Result<usize> {
148        match self.der_content_len() {
149            Length::Definite(sz) => Ok(sz),
150            Length::Indefinite => Err(crate::Error::IndefiniteLengthUnexpected),
151        }
152    }
153
154    #[deprecated(since = "0.8.0", note = "Use `to_der_vec()` instead.")]
155    fn to_der_vec_raw(&self) -> SerializeResult<Vec<u8>> {
156        self.to_der_vec()
157    }
158}
159
160//--- blanket impls
161
162impl<E, T: ToDer> ToDer for &'_ T
163where
164    T: ToDer<Encoder = E>,
165    E: BerEncoder,
166{
167    type Encoder = <T as ToDer>::Encoder;
168
169    fn der_content_len(&self) -> Length {
170        (*self).der_content_len()
171    }
172
173    fn der_tag_info(&self) -> (Class, bool, Tag) {
174        (*self).der_tag_info()
175    }
176
177    fn der_write_content<W: Write>(&self, target: &mut W) -> SerializeResult<usize> {
178        (*self).der_write_content(target)
179    }
180}
181
182//--- Macros
183
184/// Helper macro to implement [`ToDer`] for types where implementation is the same as [`ToBer`]
185#[macro_export]
186macro_rules! impl_toder_from_tober {
187    (TY $ty:ty) => {
188        impl $crate::ToDer for $ty
189        where
190            $ty: ToBer,
191        {
192            type Encoder = <$ty as ToBer>::Encoder;
193
194            fn der_content_len(&self) -> Length {
195                <$ty as ToBer>::ber_content_len(self)
196            }
197
198            fn der_tag_info(&self) -> (Class, bool, Tag) {
199                <$ty as ToBer>::ber_tag_info(self)
200            }
201
202            fn der_write_content<W: Write>(&self, target: &mut W) -> SerializeResult<usize> {
203                <$ty as ToBer>::ber_write_content(self, target)
204            }
205        }
206    };
207    (LFT $lft:lifetime, $ty:ty) => {
208        impl<$lft> $crate::ToDer for $ty
209        where
210            $ty: ToBer,
211        {
212            type Encoder = <$ty as ToBer>::Encoder;
213
214            fn der_content_len(&self) -> Length {
215                <$ty as ToBer>::ber_content_len(self)
216            }
217
218            fn der_tag_info(&self) -> (Class, bool, Tag) {
219                <$ty as ToBer>::ber_tag_info(self)
220            }
221
222            fn der_write_content<W: Write>(&self, target: &mut W) -> SerializeResult<usize> {
223                <$ty as ToBer>::ber_write_content(self, target)
224            }
225        }
226    };
227}
228
229//--- Helper functions
230
231/// Return the length (in bytes) required for a set of objects (DER)
232///
233/// Compute the length by iterating through all items, and add lengths for their header+content.
234///
235/// Note: if one of the objects has an undefinite length, then the resulting length
236/// will be indefinite.
237pub fn der_length_constructed_items<'a, T, IT>(iter: IT) -> Length
238where
239    T: ToDer + 'a,
240    IT: Iterator<Item = &'a T>,
241{
242    iter.map(|t| t.der_total_len()).sum()
243}