/rust/registry/src/index.crates.io-1949cf8c6b5b557f/der-parser-6.0.1/src/der/parser.rs
Line | Count | Source |
1 | | use crate::ber::*; |
2 | | use crate::der::*; |
3 | | use crate::error::*; |
4 | | use nom::bytes::streaming::take; |
5 | | use nom::number::streaming::be_u8; |
6 | | use nom::{Err, Needed}; |
7 | | use rusticata_macros::custom_check; |
8 | | |
9 | | /// Parse DER object recursively |
10 | | /// |
11 | | /// Return a tuple containing the remaining (unparsed) bytes and the DER Object, or an error. |
12 | | /// |
13 | | /// *Note: this is the same as calling `parse_der_recursive` with `MAX_RECURSION`. |
14 | | /// |
15 | | /// ### Example |
16 | | /// |
17 | | /// ``` |
18 | | /// use der_parser::der::{parse_der, DerTag}; |
19 | | /// |
20 | | /// let bytes = &[0x02, 0x03, 0x01, 0x00, 0x01]; |
21 | | /// let (_, obj) = parse_der(bytes).expect("parsing failed"); |
22 | | /// |
23 | | /// assert_eq!(obj.header.tag, DerTag::Integer); |
24 | | /// ``` |
25 | | #[inline] |
26 | 286k | pub fn parse_der(i: &[u8]) -> DerResult { |
27 | 286k | parse_der_recursive(i, MAX_RECURSION) |
28 | 286k | } |
29 | | |
30 | | /// Parse DER object recursively, specifying the maximum recursion depth |
31 | | /// |
32 | | /// Return a tuple containing the remaining (unparsed) bytes and the DER Object, or an error. |
33 | | /// |
34 | | /// ### Example |
35 | | /// |
36 | | /// ``` |
37 | | /// use der_parser::der::{parse_der_recursive, DerTag}; |
38 | | /// |
39 | | /// let bytes = &[0x02, 0x03, 0x01, 0x00, 0x01]; |
40 | | /// let (_, obj) = parse_der_recursive(bytes, 1).expect("parsing failed"); |
41 | | /// |
42 | | /// assert_eq!(obj.header.tag, DerTag::Integer); |
43 | | /// ``` |
44 | 286k | pub fn parse_der_recursive(i: &[u8], max_depth: usize) -> DerResult { |
45 | 286k | let (i, hdr) = der_read_element_header(i)?; |
46 | | // safety check: length cannot be more than 2^32 bytes |
47 | 240k | if let BerSize::Definite(l) = hdr.len { |
48 | 240k | custom_check!(i, l > MAX_OBJECT_SIZE, BerError::InvalidLength)?; |
49 | 0 | } |
50 | 238k | der_read_element_content_recursive(i, hdr, max_depth) |
51 | 286k | } |
52 | | |
53 | | #[doc(hidden)] |
54 | | #[macro_export] |
55 | | macro_rules! der_constraint_fail_if( |
56 | | ($slice:expr, $cond:expr) => ( |
57 | | { |
58 | | if $cond { |
59 | | return Err(::nom::Err::Error(BerError::DerConstraintFailed)); |
60 | | } |
61 | | } |
62 | | ); |
63 | | ); |
64 | | |
65 | | /// Parse a DER object, expecting a value with specified tag |
66 | | /// |
67 | | /// The object is parsed recursively, with a maximum depth of `MAX_RECURSION`. |
68 | | /// |
69 | | /// ### Example |
70 | | /// |
71 | | /// ``` |
72 | | /// use der_parser::der::{parse_der_with_tag, DerTag}; |
73 | | /// |
74 | | /// let bytes = &[0x02, 0x03, 0x01, 0x00, 0x01]; |
75 | | /// let (_, obj) = parse_der_with_tag(bytes, DerTag::Integer).expect("parsing failed"); |
76 | | /// |
77 | | /// assert_eq!(obj.header.tag, DerTag::Integer); |
78 | | /// ``` |
79 | 818k | pub fn parse_der_with_tag<Tag: Into<DerTag>>(i: &[u8], tag: Tag) -> DerResult { |
80 | 818k | let tag = tag.into(); |
81 | 818k | let (i, hdr) = der_read_element_header(i)?; |
82 | 730k | if hdr.tag != tag { |
83 | 28.7k | return Err(nom::Err::Error(BerError::InvalidTag)); |
84 | 702k | } |
85 | 688k | let (i, content) = |
86 | 702k | der_read_element_content_as(i, hdr.tag, hdr.len, hdr.is_constructed(), MAX_RECURSION)?; |
87 | 688k | Ok((i, DerObject::from_header_and_content(hdr, content))) |
88 | 818k | } der_parser::der::parser::parse_der_with_tag::<der_parser::ber::ber::BerTag> Line | Count | Source | 79 | 78.1k | pub fn parse_der_with_tag<Tag: Into<DerTag>>(i: &[u8], tag: Tag) -> DerResult { | 80 | 78.1k | let tag = tag.into(); | 81 | 78.1k | let (i, hdr) = der_read_element_header(i)?; | 82 | 55.4k | if hdr.tag != tag { | 83 | 23.7k | return Err(nom::Err::Error(BerError::InvalidTag)); | 84 | 31.7k | } | 85 | 29.1k | let (i, content) = | 86 | 31.7k | der_read_element_content_as(i, hdr.tag, hdr.len, hdr.is_constructed(), MAX_RECURSION)?; | 87 | 29.1k | Ok((i, DerObject::from_header_and_content(hdr, content))) | 88 | 78.1k | } |
der_parser::der::parser::parse_der_with_tag::<der_parser::ber::ber::BerTag> Line | Count | Source | 79 | 341k | pub fn parse_der_with_tag<Tag: Into<DerTag>>(i: &[u8], tag: Tag) -> DerResult { | 80 | 341k | let tag = tag.into(); | 81 | 341k | let (i, hdr) = der_read_element_header(i)?; | 82 | 281k | if hdr.tag != tag { | 83 | 3.53k | return Err(nom::Err::Error(BerError::InvalidTag)); | 84 | 277k | } | 85 | 272k | let (i, content) = | 86 | 277k | der_read_element_content_as(i, hdr.tag, hdr.len, hdr.is_constructed(), MAX_RECURSION)?; | 87 | 272k | Ok((i, DerObject::from_header_and_content(hdr, content))) | 88 | 341k | } |
der_parser::der::parser::parse_der_with_tag::<der_parser::ber::ber::BerTag> Line | Count | Source | 79 | 399k | pub fn parse_der_with_tag<Tag: Into<DerTag>>(i: &[u8], tag: Tag) -> DerResult { | 80 | 399k | let tag = tag.into(); | 81 | 399k | let (i, hdr) = der_read_element_header(i)?; | 82 | 394k | if hdr.tag != tag { | 83 | 1.44k | return Err(nom::Err::Error(BerError::InvalidTag)); | 84 | 392k | } | 85 | 386k | let (i, content) = | 86 | 392k | der_read_element_content_as(i, hdr.tag, hdr.len, hdr.is_constructed(), MAX_RECURSION)?; | 87 | 386k | Ok((i, DerObject::from_header_and_content(hdr, content))) | 88 | 399k | } |
|
89 | | |
90 | | /// Read end of content marker |
91 | | #[inline] |
92 | 0 | pub fn parse_der_endofcontent(i: &[u8]) -> DerResult { |
93 | 0 | parse_der_with_tag(i, DerTag::EndOfContent) |
94 | 0 | } |
95 | | |
96 | | /// Read a boolean value |
97 | | /// |
98 | | /// The encoding of a boolean value shall be primitive. The contents octets shall consist of a |
99 | | /// single octet. |
100 | | /// |
101 | | /// If the boolean value is FALSE, the octet shall be zero. |
102 | | /// If the boolean value is TRUE, the octet shall be one byte, and have all bits set to one (0xff). |
103 | | #[inline] |
104 | 0 | pub fn parse_der_bool(i: &[u8]) -> DerResult { |
105 | 0 | parse_der_with_tag(i, DerTag::Boolean) |
106 | 0 | } |
107 | | |
108 | | /// Read an integer value |
109 | | /// |
110 | | /// The encoding of a boolean value shall be primitive. The contents octets shall consist of one or |
111 | | /// more octets. |
112 | | /// |
113 | | /// To access the content, use the [`as_u64`](struct.BerObject.html#method.as_u64), |
114 | | /// [`as_u32`](struct.BerObject.html#method.as_u32), |
115 | | /// [`as_biguint`](struct.BerObject.html#method.as_biguint) or |
116 | | /// [`as_bigint`](struct.BerObject.html#method.as_bigint) methods. |
117 | | /// Remember that a BER integer has unlimited size, so these methods return `Result` or `Option` |
118 | | /// objects. |
119 | | /// |
120 | | /// # Examples |
121 | | /// |
122 | | /// ```rust |
123 | | /// # use der_parser::der::{parse_der_integer, DerObject, DerObjectContent}; |
124 | | /// let empty = &b""[..]; |
125 | | /// let bytes = [0x02, 0x03, 0x01, 0x00, 0x01]; |
126 | | /// let expected = DerObject::from_obj(DerObjectContent::Integer(b"\x01\x00\x01")); |
127 | | /// assert_eq!( |
128 | | /// parse_der_integer(&bytes), |
129 | | /// Ok((empty, expected)) |
130 | | /// ); |
131 | | /// ``` |
132 | | #[inline] |
133 | 501k | pub fn parse_der_integer(i: &[u8]) -> DerResult { |
134 | 501k | parse_der_with_tag(i, DerTag::Integer) |
135 | 501k | } |
136 | | |
137 | | /// Read an bitstring value |
138 | | /// |
139 | | /// To access the content as plain bytes, you will have to |
140 | | /// interprete the resulting tuple which will contain in |
141 | | /// its first item the number of padding bits left at |
142 | | /// the end of the bit string, and in its second item |
143 | | /// a `BitStringObject` structure which will, in its sole |
144 | | /// structure field called `data`, contain a byte slice |
145 | | /// representing the value of the bit string which can |
146 | | /// be interpreted as a big-endian value with the padding |
147 | | /// bits on the right (as in ASN.1 raw BER or DER encoding). |
148 | | /// |
149 | | /// To access the content as an integer, use the [`as_u64`](struct.BerObject.html#method.as_u64) |
150 | | /// or [`as_u32`](struct.BerObject.html#method.as_u32) methods. |
151 | | /// Remember that a BER bit string has unlimited size, so these methods return `Result` or `Option` |
152 | | /// objects. |
153 | | #[inline] |
154 | 68.2k | pub fn parse_der_bitstring(i: &[u8]) -> DerResult { |
155 | 68.2k | parse_der_with_tag(i, DerTag::BitString) |
156 | 68.2k | } |
157 | | |
158 | | /// Read an octetstring value |
159 | | #[inline] |
160 | 1.29k | pub fn parse_der_octetstring(i: &[u8]) -> DerResult { |
161 | 1.29k | parse_der_with_tag(i, DerTag::OctetString) |
162 | 1.29k | } |
163 | | |
164 | | /// Read a null value |
165 | | #[inline] |
166 | 0 | pub fn parse_der_null(i: &[u8]) -> DerResult { |
167 | 0 | parse_der_with_tag(i, DerTag::Null) |
168 | 0 | } |
169 | | |
170 | | /// Read an object identifier value |
171 | | #[inline] |
172 | 76.5k | pub fn parse_der_oid(i: &[u8]) -> DerResult { |
173 | 76.5k | parse_der_with_tag(i, DerTag::Oid) |
174 | 76.5k | } |
175 | | |
176 | | /// Read an enumerated value |
177 | | #[inline] |
178 | 0 | pub fn parse_der_enum(i: &[u8]) -> DerResult { |
179 | 0 | parse_der_with_tag(i, DerTag::Enumerated) |
180 | 0 | } |
181 | | |
182 | | /// Read a UTF-8 string value. The encoding is checked. |
183 | | #[inline] |
184 | 0 | pub fn parse_der_utf8string(i: &[u8]) -> DerResult { |
185 | 0 | parse_der_with_tag(i, DerTag::Utf8String) |
186 | 0 | } |
187 | | |
188 | | /// Read a relative object identifier value |
189 | | #[inline] |
190 | 0 | pub fn parse_der_relative_oid(i: &[u8]) -> DerResult { |
191 | 0 | parse_der_with_tag(i, DerTag::RelativeOid) |
192 | 0 | } |
193 | | |
194 | | /// Parse a sequence of DER elements |
195 | | /// |
196 | | /// Read a sequence of DER objects, without any constraint on the types. |
197 | | /// Sequence is parsed recursively, so if structured elements are found, they are parsed using the |
198 | | /// same function. |
199 | | /// |
200 | | /// To read a specific sequence of objects (giving the expected types), use the |
201 | | /// [`parse_der_sequence_defined`](macro.parse_der_sequence_defined.html) macro. |
202 | | #[inline] |
203 | 1.62k | pub fn parse_der_sequence(i: &[u8]) -> DerResult { |
204 | 1.62k | parse_der_with_tag(i, DerTag::Sequence) |
205 | 1.62k | } |
206 | | |
207 | | /// Parse a set of DER elements |
208 | | /// |
209 | | /// Read a set of DER objects, without any constraint on the types. |
210 | | /// Set is parsed recursively, so if structured elements are found, they are parsed using the |
211 | | /// same function. |
212 | | /// |
213 | | /// To read a specific set of objects (giving the expected types), use the |
214 | | /// [`parse_der_set_defined`](macro.parse_der_set_defined.html) macro. |
215 | | #[inline] |
216 | 0 | pub fn parse_der_set(i: &[u8]) -> DerResult { |
217 | 0 | parse_der_with_tag(i, DerTag::Set) |
218 | 0 | } |
219 | | |
220 | | /// Read a numeric string value. The content is verified to |
221 | | /// contain only digits and spaces. |
222 | | #[inline] |
223 | 0 | pub fn parse_der_numericstring(i: &[u8]) -> DerResult { |
224 | 0 | parse_der_with_tag(i, DerTag::NumericString) |
225 | 0 | } |
226 | | |
227 | | /// Read a printable string value. The content is verified to |
228 | | /// contain only the allowed characters. |
229 | | #[inline] |
230 | 0 | pub fn visiblestring(i: &[u8]) -> DerResult { |
231 | 0 | parse_der_with_tag(i, DerTag::VisibleString) |
232 | 0 | } |
233 | | |
234 | | /// Read a printable string value. The content is verified to |
235 | | /// contain only the allowed characters. |
236 | | #[inline] |
237 | 0 | pub fn parse_der_printablestring(i: &[u8]) -> DerResult { |
238 | 0 | parse_der_with_tag(i, DerTag::PrintableString) |
239 | 0 | } |
240 | | |
241 | | /// Read a T61 string value |
242 | | #[inline] |
243 | 0 | pub fn parse_der_t61string(i: &[u8]) -> DerResult { |
244 | 0 | parse_der_with_tag(i, DerTag::T61String) |
245 | 0 | } |
246 | | |
247 | | /// Read a Videotex string value |
248 | | #[inline] |
249 | 0 | pub fn parse_der_videotexstring(i: &[u8]) -> DerResult { |
250 | 0 | parse_der_with_tag(i, DerTag::VideotexString) |
251 | 0 | } |
252 | | |
253 | | /// Read an IA5 string value. The content is verified to be ASCII. |
254 | | #[inline] |
255 | 0 | pub fn parse_der_ia5string(i: &[u8]) -> DerResult { |
256 | 0 | parse_der_with_tag(i, DerTag::Ia5String) |
257 | 0 | } |
258 | | |
259 | | /// Read an UTC time value |
260 | | #[inline] |
261 | 0 | pub fn parse_der_utctime(i: &[u8]) -> DerResult { |
262 | 0 | parse_der_with_tag(i, DerTag::UtcTime) |
263 | 0 | } |
264 | | |
265 | | /// Read a Generalized time value |
266 | | #[inline] |
267 | 72.1k | pub fn parse_der_generalizedtime(i: &[u8]) -> DerResult { |
268 | 72.1k | parse_der_with_tag(i, DerTag::GeneralizedTime) |
269 | 72.1k | } |
270 | | |
271 | | /// Read a ObjectDescriptor value |
272 | | #[inline] |
273 | 0 | pub fn parse_der_objectdescriptor(i: &[u8]) -> DerResult { |
274 | 0 | parse_der_with_tag(i, DerTag::ObjDescriptor) |
275 | 0 | } |
276 | | |
277 | | /// Read a GraphicString value |
278 | | #[inline] |
279 | 0 | pub fn parse_der_graphicstring(i: &[u8]) -> DerResult { |
280 | 0 | parse_der_with_tag(i, DerTag::GraphicString) |
281 | 0 | } |
282 | | |
283 | | /// Read a GeneralString value |
284 | | #[inline] |
285 | 97.5k | pub fn parse_der_generalstring(i: &[u8]) -> DerResult { |
286 | 97.5k | parse_der_with_tag(i, DerTag::GeneralString) |
287 | 97.5k | } |
288 | | |
289 | | /// Read a BmpString value |
290 | | #[inline] |
291 | 0 | pub fn parse_der_bmpstring(i: &[u8]) -> DerResult { |
292 | 0 | parse_der_with_tag(i, DerTag::BmpString) |
293 | 0 | } |
294 | | |
295 | | /// Read a UniversalString value |
296 | | #[inline] |
297 | 0 | pub fn parse_der_universalstring(i: &[u8]) -> DerResult { |
298 | 0 | parse_der_with_tag(i, DerTag::UniversalString) |
299 | 0 | } |
300 | | |
301 | | /// Parse an optional tagged object, applying function to get content |
302 | | /// |
303 | | /// This function returns a `DerObject`, trying to read content as generic DER objects. |
304 | | /// If parsing failed, return an optional object containing `None`. |
305 | | /// |
306 | | /// To support other return or error types, use |
307 | | /// [parse_der_tagged_explicit_g](fn.parse_der_tagged_explicit_g.html) |
308 | | /// |
309 | | /// This function will never fail: if parsing content failed, the BER value `Optional(None)` is |
310 | | /// returned. |
311 | | #[inline] |
312 | 0 | pub fn parse_der_explicit_optional<F>(i: &[u8], tag: DerTag, f: F) -> DerResult |
313 | 0 | where |
314 | 0 | F: Fn(&[u8]) -> DerResult, |
315 | | { |
316 | 0 | parse_ber_explicit_optional(i, tag, f) |
317 | 0 | } |
318 | | |
319 | | /// Parse an implicit tagged object, applying function to read content |
320 | | /// |
321 | | /// Note: unlike explicit tagged functions, the callback must be a *content* parsing function, |
322 | | /// often based on the [`parse_der_content`](fn.parse_der_content.html) combinator. |
323 | | /// |
324 | | /// The built object will use the original header (and tag), so the content may not match the tag |
325 | | /// value. |
326 | | /// |
327 | | /// For a combinator version, see [parse_der_tagged_implicit](../ber/fn.parse_der_tagged_implicit.html). |
328 | | /// |
329 | | /// For a generic version (different output and error types), see |
330 | | /// [parse_der_tagged_implicit_g](../ber/fn.parse_der_tagged_implicit_g.html). |
331 | | /// |
332 | | /// # Examples |
333 | | /// |
334 | | /// The following parses `[3] IMPLICIT INTEGER` into a `DerObject`: |
335 | | /// |
336 | | /// ```rust |
337 | | /// # use der_parser::der::*; |
338 | | /// # use der_parser::error::DerResult; |
339 | | /// # |
340 | | /// fn parse_int_implicit(i:&[u8]) -> DerResult { |
341 | | /// parse_der_implicit( |
342 | | /// i, |
343 | | /// 3, |
344 | | /// parse_der_content(DerTag::Integer), |
345 | | /// ) |
346 | | /// } |
347 | | /// |
348 | | /// # let bytes = &[0x83, 0x03, 0x01, 0x00, 0x01]; |
349 | | /// let res = parse_int_implicit(bytes); |
350 | | /// # match res { |
351 | | /// # Ok((rem, content)) => { |
352 | | /// # assert!(rem.is_empty()); |
353 | | /// # assert_eq!(content.as_u32(), Ok(0x10001)); |
354 | | /// # }, |
355 | | /// # _ => assert!(false) |
356 | | /// # } |
357 | | /// ``` |
358 | | #[inline] |
359 | 0 | pub fn parse_der_implicit<'a, Tag, F>(i: &'a [u8], tag: Tag, f: F) -> DerResult<'a> |
360 | 0 | where |
361 | 0 | F: Fn(&'a [u8], &'_ DerObjectHeader, usize) -> BerResult<'a, DerObjectContent<'a>>, |
362 | 0 | Tag: Into<DerTag>, |
363 | | { |
364 | 0 | parse_ber_implicit(i, tag, f) |
365 | 0 | } |
366 | | |
367 | | /// Parse DER object and try to decode it as a 32-bits signed integer |
368 | | /// |
369 | | /// Return `IntegerTooLarge` if object is an integer, but can not be represented in the target |
370 | | /// integer type. |
371 | | #[inline] |
372 | 0 | pub fn parse_der_i32(i: &[u8]) -> BerResult<i32> { |
373 | 0 | let (rem, der) = parse_der_integer(i)?; |
374 | 0 | let int = der.as_i32().map_err(nom::Err::Error)?; |
375 | 0 | Ok((rem, int)) |
376 | 0 | } |
377 | | |
378 | | /// Parse DER object and try to decode it as a 64-bits signed integer |
379 | | /// |
380 | | /// Return `IntegerTooLarge` if object is an integer, but can not be represented in the target |
381 | | /// integer type. |
382 | | #[inline] |
383 | 0 | pub fn parse_der_i64(i: &[u8]) -> BerResult<i64> { |
384 | 0 | let (rem, der) = parse_der_integer(i)?; |
385 | 0 | let int = der.as_i64().map_err(nom::Err::Error)?; |
386 | 0 | Ok((rem, int)) |
387 | 0 | } |
388 | | |
389 | | /// Parse DER object and try to decode it as a 32-bits unsigned integer |
390 | | /// |
391 | | /// Return `IntegerTooLarge` if object is an integer, but can not be represented in the target |
392 | | /// integer type. |
393 | 399k | pub fn parse_der_u32(i: &[u8]) -> BerResult<u32> { |
394 | 399k | let (rem, der) = parse_der_integer(i)?; |
395 | 386k | let int = der.as_u32().map_err(nom::Err::Error)?; |
396 | 382k | Ok((rem, int)) |
397 | 399k | } |
398 | | |
399 | | /// Parse DER object and try to decode it as a 64-bits unsigned integer |
400 | | /// |
401 | | /// Return `IntegerTooLarge` if object is an integer, but can not be represented in the target |
402 | | /// integer type. |
403 | 0 | pub fn parse_der_u64(i: &[u8]) -> BerResult<u64> { |
404 | 0 | let (rem, der) = parse_der_integer(i)?; |
405 | 0 | let int = der.as_u64().map_err(nom::Err::Error)?; |
406 | 0 | Ok((rem, int)) |
407 | 0 | } |
408 | | |
409 | | /// Parse DER object and get content as slice |
410 | | #[inline] |
411 | 0 | pub fn parse_der_slice<Tag: Into<DerTag>>(i: &[u8], tag: Tag) -> BerResult<&[u8]> { |
412 | 0 | let tag = tag.into(); |
413 | 0 | parse_der_container(move |content, hdr| { |
414 | 0 | if hdr.tag != tag { |
415 | 0 | return Err(Err::Error(BerError::InvalidTag)); |
416 | 0 | } |
417 | 0 | Ok((&b""[..], content)) |
418 | 0 | })(i) |
419 | 0 | } |
420 | | |
421 | | /// Parse the next bytes as the content of a DER object (combinator, header reference) |
422 | | /// |
423 | | /// Content type is *not* checked to match tag, caller is responsible of providing the correct tag |
424 | | /// |
425 | | /// Caller is also responsible to check if parsing function consumed the expected number of |
426 | | /// bytes (`header.len`). |
427 | | /// |
428 | | /// This function differs from [`parse_der_content2`](fn.parse_der_content2.html) because it passes |
429 | | /// the BER object header by reference (required for ex. by `parse_der_implicit`). |
430 | | /// |
431 | | /// The arguments of the parse function are: `(input, ber_object_header, max_recursion)`. |
432 | | /// |
433 | | /// Example: manually parsing header and content |
434 | | /// |
435 | | /// ``` |
436 | | /// # use der_parser::ber::MAX_RECURSION; |
437 | | /// # use der_parser::der::*; |
438 | | /// # |
439 | | /// # let bytes = &[0x02, 0x03, 0x01, 0x00, 0x01]; |
440 | | /// let (i, header) = der_read_element_header(bytes).expect("parsing failed"); |
441 | | /// let (rem, content) = parse_der_content(header.tag)(i, &header, MAX_RECURSION) |
442 | | /// .expect("parsing failed"); |
443 | | /// # |
444 | | /// # assert_eq!(header.tag, DerTag::Integer); |
445 | | /// ``` |
446 | 0 | pub fn parse_der_content<'a>( |
447 | 0 | tag: DerTag, |
448 | 0 | ) -> impl Fn(&'a [u8], &'_ DerObjectHeader, usize) -> BerResult<'a, DerObjectContent<'a>> { |
449 | 0 | move |i: &[u8], hdr: &DerObjectHeader, max_recursion: usize| { |
450 | 0 | der_read_element_content_as(i, tag, hdr.len, hdr.is_constructed(), max_recursion) |
451 | 0 | } |
452 | 0 | } |
453 | | |
454 | | /// Parse the next bytes as the content of a DER object (combinator, owned header) |
455 | | /// |
456 | | /// Content type is *not* checked to match tag, caller is responsible of providing the correct tag |
457 | | /// |
458 | | /// Caller is also responsible to check if parsing function consumed the expected number of |
459 | | /// bytes (`header.len`). |
460 | | /// |
461 | | /// The arguments of the parse function are: `(input, ber_object_header, max_recursion)`. |
462 | | /// |
463 | | /// This function differs from [`parse_der_content`](fn.parse_der_content.html) because it passes |
464 | | /// an owned BER object header (required for ex. by `parse_der_tagged_implicit_g`). |
465 | | /// |
466 | | /// Example: manually parsing header and content |
467 | | /// |
468 | | /// ``` |
469 | | /// # use der_parser::ber::MAX_RECURSION; |
470 | | /// # use der_parser::der::*; |
471 | | /// # |
472 | | /// # let bytes = &[0x02, 0x03, 0x01, 0x00, 0x01]; |
473 | | /// let (i, header) = der_read_element_header(bytes).expect("parsing failed"); |
474 | | /// # assert_eq!(header.tag, DerTag::Integer); |
475 | | /// let (rem, content) = parse_der_content2(header.tag)(i, header, MAX_RECURSION) |
476 | | /// .expect("parsing failed"); |
477 | | /// ``` |
478 | 0 | pub fn parse_der_content2<'a>( |
479 | 0 | tag: DerTag, |
480 | 0 | ) -> impl Fn(&'a [u8], DerObjectHeader<'a>, usize) -> BerResult<'a, DerObjectContent<'a>> { |
481 | 0 | move |i: &[u8], hdr: DerObjectHeader, max_recursion: usize| { |
482 | 0 | der_read_element_content_as(i, tag, hdr.len, hdr.is_constructed(), max_recursion) |
483 | 0 | } |
484 | 0 | } |
485 | | |
486 | | // --------- end of parse_der_xxx functions ---------- |
487 | | |
488 | | /// Parse the next bytes as the content of a DER object. |
489 | | /// |
490 | | /// Content type is *not* checked, caller is responsible of providing the correct tag |
491 | 885k | pub fn der_read_element_content_as( |
492 | 885k | i: &[u8], |
493 | 885k | tag: DerTag, |
494 | 885k | len: BerSize, |
495 | 885k | constructed: bool, |
496 | 885k | max_depth: usize, |
497 | 885k | ) -> BerResult<DerObjectContent> { |
498 | | // Indefinite lengths are not allowed in DER (X.690 section 10.1) |
499 | 885k | let l = len.primitive()?; |
500 | 885k | if i.len() < l { |
501 | 7.61k | return Err(Err::Incomplete(Needed::new(l))); |
502 | 878k | } |
503 | 878k | match tag { |
504 | | DerTag::Boolean => { |
505 | 7.20k | custom_check!(i, l != 1, BerError::InvalidLength)?; |
506 | 3.95k | der_constraint_fail_if!(i, i[0] != 0 && i[0] != 0xff); |
507 | | } |
508 | | DerTag::BitString => { |
509 | 85.8k | der_constraint_fail_if!(i, constructed); |
510 | | // exception: read and verify padding bits |
511 | 85.1k | return der_read_content_bitstring(i, l); |
512 | | } |
513 | | DerTag::Integer => { |
514 | | // verify leading zeros |
515 | 454k | match i[..l] { |
516 | 454k | [] => return Err(nom::Err::Error(BerError::DerConstraintFailed)), |
517 | 452k | [0, 0, ..] => return Err(nom::Err::Error(BerError::DerConstraintFailed)), |
518 | 20.5k | [0, byte, ..] if byte < 0x80 => { |
519 | 1.73k | return Err(nom::Err::Error(BerError::DerConstraintFailed)); |
520 | | } |
521 | 447k | _ => (), |
522 | | } |
523 | | } |
524 | | DerTag::NumericString |
525 | | | DerTag::VisibleString |
526 | | | DerTag::PrintableString |
527 | | | DerTag::Ia5String |
528 | | | DerTag::Utf8String |
529 | | | DerTag::T61String |
530 | | | DerTag::VideotexString |
531 | | | DerTag::BmpString |
532 | | | DerTag::UniversalString |
533 | | | DerTag::ObjDescriptor |
534 | | | DerTag::GraphicString |
535 | | | DerTag::GeneralString => { |
536 | 123k | der_constraint_fail_if!(i, constructed); |
537 | | } |
538 | | DerTag::UtcTime | DerTag::GeneralizedTime => { |
539 | 75.8k | if l == 0 || i.get(l - 1).cloned() != Some(b'Z') { |
540 | 3.66k | return Err(Err::Error(BerError::DerConstraintFailed)); |
541 | 72.1k | } |
542 | | } |
543 | 131k | _ => (), |
544 | | } |
545 | 773k | ber_read_element_content_as(i, tag, len, constructed, max_depth) |
546 | 885k | } |
547 | | |
548 | | /// Parse DER object content recursively |
549 | | /// |
550 | | /// *Note: an error is raised if recursion depth exceeds `MAX_RECURSION`. |
551 | 0 | pub fn der_read_element_content<'a>(i: &'a [u8], hdr: DerObjectHeader<'a>) -> DerResult<'a> { |
552 | 0 | der_read_element_content_recursive(i, hdr, MAX_RECURSION) |
553 | 0 | } |
554 | | |
555 | 238k | fn der_read_element_content_recursive<'a>( |
556 | 238k | i: &'a [u8], |
557 | 238k | hdr: DerObjectHeader<'a>, |
558 | 238k | max_depth: usize, |
559 | 238k | ) -> DerResult<'a> { |
560 | 238k | match hdr.class { |
561 | 183k | BerClass::Universal => (), |
562 | | BerClass::Private => { |
563 | 6.57k | let (rem, content) = ber_get_object_content(i, &hdr, max_depth)?; |
564 | 4.34k | let content = BerObjectContent::Private(hdr.clone(), content); |
565 | 4.34k | let obj = BerObject::from_header_and_content(hdr, content); |
566 | 4.34k | return Ok((rem, obj)); |
567 | | } |
568 | | _ => { |
569 | 48.3k | let (i, content) = ber_get_object_content(i, &hdr, max_depth)?; |
570 | 38.3k | let content = DerObjectContent::Unknown(hdr.class, hdr.tag, content); |
571 | 38.3k | let obj = DerObject::from_header_and_content(hdr, content); |
572 | 38.3k | return Ok((i, obj)); |
573 | | } |
574 | | } |
575 | 183k | match der_read_element_content_as(i, hdr.tag, hdr.len, hdr.is_constructed(), max_depth) { |
576 | 124k | Ok((rem, content)) => Ok((rem, DerObject::from_header_and_content(hdr, content))), |
577 | | Err(Err::Error(BerError::UnknownTag)) => { |
578 | 2.93k | let (rem, content) = ber_get_object_content(i, &hdr, max_depth)?; |
579 | 2.93k | let content = DerObjectContent::Unknown(hdr.class, hdr.tag, content); |
580 | 2.93k | let obj = DerObject::from_header_and_content(hdr, content); |
581 | 2.93k | Ok((rem, obj)) |
582 | | } |
583 | 56.1k | Err(e) => Err(e), |
584 | | } |
585 | 238k | } |
586 | | |
587 | 85.1k | fn der_read_content_bitstring(i: &[u8], len: usize) -> BerResult<DerObjectContent> { |
588 | 85.1k | let (i, ignored_bits) = be_u8(i)?; |
589 | 83.6k | if ignored_bits > 7 { |
590 | 1.84k | return Err(Err::Error(BerError::DerConstraintFailed)); |
591 | 81.8k | } |
592 | 81.8k | if len == 0 { |
593 | 1.81k | return Err(Err::Error(BerError::InvalidLength)); |
594 | 79.9k | } |
595 | 79.9k | let (i, data) = take(len - 1)(i)?; |
596 | 79.9k | if len > 1 { |
597 | 77.7k | let mut last_byte = data[len - 2]; |
598 | 77.7k | for _ in 0..ignored_bits as usize { |
599 | 105k | der_constraint_fail_if!(i, last_byte & 1 != 0); |
600 | 96.5k | last_byte >>= 1; |
601 | | } |
602 | 2.19k | } |
603 | 71.0k | Ok(( |
604 | 71.0k | i, |
605 | 71.0k | DerObjectContent::BitString(ignored_bits, BitStringObject { data }), |
606 | 71.0k | )) |
607 | | // do_parse! { |
608 | | // i, |
609 | | // ignored_bits: be_u8 >> |
610 | | // custom_check!(ignored_bits > 7, BerError::DerConstraintFailed) >> |
611 | | // custom_check!(len == 0, BerError::InvalidLength) >> |
612 | | // s: take!(len - 1) >> |
613 | | // call!(|input| { |
614 | | // if len > 1 { |
615 | | // let mut last_byte = s[len-2]; |
616 | | // for _ in 0..ignored_bits as usize { |
617 | | // der_constraint_fail_if!(i, last_byte & 1 != 0); |
618 | | // last_byte >>= 1; |
619 | | // } |
620 | | // } |
621 | | // Ok((input,())) |
622 | | // }) >> |
623 | | // ( DerObjectContent::BitString(ignored_bits,BitStringObject{ data:s }) ) |
624 | | // } |
625 | 85.1k | } |
626 | | |
627 | | /// Read an object header (DER) |
628 | 1.10M | pub fn der_read_element_header(i: &[u8]) -> BerResult<DerObjectHeader> { |
629 | 1.10M | let (i1, el) = parse_identifier(i)?; |
630 | 994k | let class = match DerClass::try_from(el.0) { |
631 | 994k | Ok(c) => c, |
632 | 0 | Err(_) => unreachable!(), // Cannot fail, we have read exactly 2 bits |
633 | | }; |
634 | 994k | let (i2, len) = parse_ber_length_byte(i1)?; |
635 | 988k | let (i3, len) = match (len.0, len.1) { |
636 | 963k | (0, l1) => { |
637 | | // Short form: MSB is 0, the rest encodes the length (which can be 0) (8.1.3.4) |
638 | 963k | (i2, BerSize::Definite(usize::from(l1))) |
639 | | } |
640 | | (_, 0) => { |
641 | | // Indefinite form is not allowed in DER (10.1) |
642 | 1.33k | return Err(::nom::Err::Error(BerError::DerConstraintFailed)); |
643 | | } |
644 | 24.4k | (_, l1) => { |
645 | | // if len is 0xff -> error (8.1.3.5) |
646 | 24.4k | if l1 == 0b0111_1111 { |
647 | 5.12k | return Err(::nom::Err::Error(BerError::InvalidTag)); |
648 | 19.3k | } |
649 | | // DER(9.1) if len is 0 (indefinite form), obj must be constructed |
650 | 19.3k | der_constraint_fail_if!(&i[1..], len.1 == 0 && el.1 != 1); |
651 | 19.3k | let (i3, llen) = take(l1)(i2)?; |
652 | 13.7k | match bytes_to_u64(llen) { |
653 | 9.44k | Ok(l) => { |
654 | | // DER: should have been encoded in short form (< 127) |
655 | 9.44k | der_constraint_fail_if!(i, l < 127); |
656 | 8.34k | let l = |
657 | 8.34k | usize::try_from(l).or(Err(::nom::Err::Error(BerError::InvalidLength)))?; |
658 | 8.34k | (i3, BerSize::Definite(l)) |
659 | | } |
660 | | Err(_) => { |
661 | 4.30k | return Err(::nom::Err::Error(BerError::InvalidTag)); |
662 | | } |
663 | | } |
664 | | } |
665 | | }; |
666 | 971k | let hdr = DerObjectHeader::new(class, el.1, BerTag(el.2), len).with_raw_tag(Some(el.3)); |
667 | 971k | Ok((i3, hdr)) |
668 | 1.10M | } |