/rust/registry/src/index.crates.io-1949cf8c6b5b557f/der-parser-10.0.0/src/der/parser.rs
Line | Count | Source |
1 | | use crate::ber::*; |
2 | | use crate::der::*; |
3 | | use crate::der_constraint_fail_if; |
4 | | use crate::error::*; |
5 | | use alloc::borrow::ToOwned; |
6 | | use asn1_rs::{Any, FromDer}; |
7 | | use nom::bytes::streaming::take; |
8 | | use nom::number::streaming::be_u8; |
9 | | use nom::{Err, Needed}; |
10 | | use rusticata_macros::custom_check; |
11 | | |
12 | | /// Parse DER object recursively |
13 | | /// |
14 | | /// Return a tuple containing the remaining (unparsed) bytes and the DER Object, or an error. |
15 | | /// |
16 | | /// *Note: this is the same as calling `parse_der_recursive` with `MAX_RECURSION`. |
17 | | /// |
18 | | /// ### Example |
19 | | /// |
20 | | /// ``` |
21 | | /// use der_parser::der::{parse_der, Tag}; |
22 | | /// |
23 | | /// let bytes = &[0x02, 0x03, 0x01, 0x00, 0x01]; |
24 | | /// let (_, obj) = parse_der(bytes).expect("parsing failed"); |
25 | | /// |
26 | | /// assert_eq!(obj.header.tag(), Tag::Integer); |
27 | | /// ``` |
28 | | #[inline] |
29 | 0 | pub fn parse_der(i: &[u8]) -> DerResult { |
30 | 0 | parse_der_recursive(i, MAX_RECURSION) |
31 | 0 | } |
32 | | |
33 | | /// Parse DER object recursively, specifying the maximum recursion depth |
34 | | /// |
35 | | /// Return a tuple containing the remaining (unparsed) bytes and the DER Object, or an error. |
36 | | /// |
37 | | /// ### Example |
38 | | /// |
39 | | /// ``` |
40 | | /// use der_parser::der::{parse_der_recursive, Tag}; |
41 | | /// |
42 | | /// let bytes = &[0x02, 0x03, 0x01, 0x00, 0x01]; |
43 | | /// let (_, obj) = parse_der_recursive(bytes, 1).expect("parsing failed"); |
44 | | /// |
45 | | /// assert_eq!(obj.header.tag(), Tag::Integer); |
46 | | /// ``` |
47 | 0 | pub fn parse_der_recursive(i: &[u8], max_depth: usize) -> DerResult { |
48 | 0 | let (i, hdr) = der_read_element_header(i)?; |
49 | | // safety check: length cannot be more than 2^32 bytes |
50 | 0 | if let Length::Definite(l) = hdr.length() { |
51 | 0 | custom_check!(i, l > MAX_OBJECT_SIZE, BerError::InvalidLength)?; |
52 | 0 | } |
53 | 0 | der_read_element_content_recursive(i, hdr, max_depth) |
54 | 0 | } |
55 | | |
56 | | /// Parse a DER object, expecting a value with specified tag |
57 | | /// |
58 | | /// The object is parsed recursively, with a maximum depth of `MAX_RECURSION`. |
59 | | /// |
60 | | /// ### Example |
61 | | /// |
62 | | /// ``` |
63 | | /// use der_parser::der::{parse_der_with_tag, Tag}; |
64 | | /// |
65 | | /// let bytes = &[0x02, 0x03, 0x01, 0x00, 0x01]; |
66 | | /// let (_, obj) = parse_der_with_tag(bytes, Tag::Integer).expect("parsing failed"); |
67 | | /// |
68 | | /// assert_eq!(obj.header.tag(), Tag::Integer); |
69 | | /// ``` |
70 | 0 | pub fn parse_der_with_tag<T: Into<Tag>>(i: &[u8], tag: T) -> DerResult { |
71 | 0 | let tag = tag.into(); |
72 | 0 | let (i, hdr) = der_read_element_header(i)?; |
73 | 0 | hdr.assert_tag(tag)?; |
74 | 0 | let (i, content) = der_read_element_content_as( |
75 | 0 | i, |
76 | 0 | hdr.tag(), |
77 | 0 | hdr.length(), |
78 | 0 | hdr.is_constructed(), |
79 | | MAX_RECURSION, |
80 | 0 | )?; |
81 | 0 | Ok((i, DerObject::from_header_and_content(hdr, content))) |
82 | 0 | } Unexecuted instantiation: der_parser::der::parser::parse_der_with_tag::<asn1_rs::tag::Tag> Unexecuted instantiation: der_parser::der::parser::parse_der_with_tag::<_> |
83 | | |
84 | | /// Read end of content marker |
85 | | #[inline] |
86 | 0 | pub fn parse_der_endofcontent(i: &[u8]) -> DerResult { |
87 | 0 | parse_der_with_tag(i, Tag::EndOfContent) |
88 | 0 | } |
89 | | |
90 | | /// Read a boolean value |
91 | | /// |
92 | | /// The encoding of a boolean value shall be primitive. The contents octets shall consist of a |
93 | | /// single octet. |
94 | | /// |
95 | | /// If the boolean value is FALSE, the octet shall be zero. |
96 | | /// If the boolean value is TRUE, the octet shall be one byte, and have all bits set to one (0xff). |
97 | | #[inline] |
98 | 0 | pub fn parse_der_bool(i: &[u8]) -> DerResult { |
99 | 0 | parse_der_with_tag(i, Tag::Boolean) |
100 | 0 | } |
101 | | |
102 | | /// Read an integer value |
103 | | /// |
104 | | /// The encoding of a boolean value shall be primitive. The contents octets shall consist of one or |
105 | | /// more octets. |
106 | | /// |
107 | | /// To access the content, use the [`as_u64`](struct.BerObject.html#method.as_u64), |
108 | | /// [`as_u32`](struct.BerObject.html#method.as_u32), |
109 | | /// [`as_biguint`](struct.BerObject.html#method.as_biguint) or |
110 | | /// [`as_bigint`](struct.BerObject.html#method.as_bigint) methods. |
111 | | /// Remember that a BER integer has unlimited size, so these methods return `Result` or `Option` |
112 | | /// objects. |
113 | | /// |
114 | | /// # Examples |
115 | | /// |
116 | | /// ```rust |
117 | | /// # use der_parser::der::{parse_der_integer, DerObject, DerObjectContent}; |
118 | | /// let empty = &b""[..]; |
119 | | /// let bytes = [0x02, 0x03, 0x01, 0x00, 0x01]; |
120 | | /// let expected = DerObject::from_obj(DerObjectContent::Integer(b"\x01\x00\x01")); |
121 | | /// assert_eq!( |
122 | | /// parse_der_integer(&bytes), |
123 | | /// Ok((empty, expected)) |
124 | | /// ); |
125 | | /// ``` |
126 | | #[inline] |
127 | 0 | pub fn parse_der_integer(i: &[u8]) -> DerResult { |
128 | 0 | parse_der_with_tag(i, Tag::Integer) |
129 | 0 | } Unexecuted instantiation: der_parser::der::parser::parse_der_integer Unexecuted instantiation: der_parser::der::parser::parse_der_integer |
130 | | |
131 | | /// Read an bitstring value |
132 | | /// |
133 | | /// To access the content as plain bytes, you will have to |
134 | | /// interprete the resulting tuple which will contain in |
135 | | /// its first item the number of padding bits left at |
136 | | /// the end of the bit string, and in its second item |
137 | | /// a `BitStringObject` structure which will, in its sole |
138 | | /// structure field called `data`, contain a byte slice |
139 | | /// representing the value of the bit string which can |
140 | | /// be interpreted as a big-endian value with the padding |
141 | | /// bits on the right (as in ASN.1 raw BER or DER encoding). |
142 | | /// |
143 | | /// To access the content as an integer, use the [`as_u64`](struct.BerObject.html#method.as_u64) |
144 | | /// or [`as_u32`](struct.BerObject.html#method.as_u32) methods. |
145 | | /// Remember that a BER bit string has unlimited size, so these methods return `Result` or `Option` |
146 | | /// objects. |
147 | | #[inline] |
148 | 0 | pub fn parse_der_bitstring(i: &[u8]) -> DerResult { |
149 | 0 | parse_der_with_tag(i, Tag::BitString) |
150 | 0 | } Unexecuted instantiation: der_parser::der::parser::parse_der_bitstring Unexecuted instantiation: der_parser::der::parser::parse_der_bitstring |
151 | | |
152 | | /// Read an octetstring value |
153 | | #[inline] |
154 | 0 | pub fn parse_der_octetstring(i: &[u8]) -> DerResult { |
155 | 0 | parse_der_with_tag(i, Tag::OctetString) |
156 | 0 | } |
157 | | |
158 | | /// Read a null value |
159 | | #[inline] |
160 | 0 | pub fn parse_der_null(i: &[u8]) -> DerResult { |
161 | 0 | parse_der_with_tag(i, Tag::Null) |
162 | 0 | } |
163 | | |
164 | | /// Read an object identifier value |
165 | | #[inline] |
166 | 0 | pub fn parse_der_oid(i: &[u8]) -> DerResult { |
167 | 0 | parse_der_with_tag(i, Tag::Oid) |
168 | 0 | } |
169 | | |
170 | | /// Read an enumerated value |
171 | | #[inline] |
172 | 0 | pub fn parse_der_enum(i: &[u8]) -> DerResult { |
173 | 0 | parse_der_with_tag(i, Tag::Enumerated) |
174 | 0 | } Unexecuted instantiation: der_parser::der::parser::parse_der_enum Unexecuted instantiation: der_parser::der::parser::parse_der_enum |
175 | | |
176 | | /// Read a UTF-8 string value. The encoding is checked. |
177 | | #[inline] |
178 | 0 | pub fn parse_der_utf8string(i: &[u8]) -> DerResult { |
179 | 0 | parse_der_with_tag(i, Tag::Utf8String) |
180 | 0 | } Unexecuted instantiation: der_parser::der::parser::parse_der_utf8string Unexecuted instantiation: der_parser::der::parser::parse_der_utf8string |
181 | | |
182 | | /// Read a relative object identifier value |
183 | | #[inline] |
184 | 0 | pub fn parse_der_relative_oid(i: &[u8]) -> DerResult { |
185 | 0 | parse_der_with_tag(i, Tag::RelativeOid) |
186 | 0 | } |
187 | | |
188 | | /// Parse a sequence of DER elements |
189 | | /// |
190 | | /// Read a sequence of DER objects, without any constraint on the types. |
191 | | /// Sequence is parsed recursively, so if constructed elements are found, they are parsed using the |
192 | | /// same function. |
193 | | /// |
194 | | /// To read a specific sequence of objects (giving the expected types), use the |
195 | | /// [`parse_der_sequence_defined`](macro.parse_der_sequence_defined.html) macro. |
196 | | #[inline] |
197 | 0 | pub fn parse_der_sequence(i: &[u8]) -> DerResult { |
198 | 0 | parse_der_with_tag(i, Tag::Sequence) |
199 | 0 | } Unexecuted instantiation: der_parser::der::parser::parse_der_sequence Unexecuted instantiation: der_parser::der::parser::parse_der_sequence |
200 | | |
201 | | /// Parse a set of DER elements |
202 | | /// |
203 | | /// Read a set of DER objects, without any constraint on the types. |
204 | | /// Set is parsed recursively, so if constructed elements are found, they are parsed using the |
205 | | /// same function. |
206 | | /// |
207 | | /// To read a specific set of objects (giving the expected types), use the |
208 | | /// [`parse_der_set_defined`](macro.parse_der_set_defined.html) macro. |
209 | | #[inline] |
210 | 0 | pub fn parse_der_set(i: &[u8]) -> DerResult { |
211 | 0 | parse_der_with_tag(i, Tag::Set) |
212 | 0 | } |
213 | | |
214 | | /// Read a numeric string value. The content is verified to |
215 | | /// contain only digits and spaces. |
216 | | #[inline] |
217 | 0 | pub fn parse_der_numericstring(i: &[u8]) -> DerResult { |
218 | 0 | parse_der_with_tag(i, Tag::NumericString) |
219 | 0 | } |
220 | | |
221 | | /// Read a printable string value. The content is verified to |
222 | | /// contain only the allowed characters. |
223 | | #[inline] |
224 | 0 | pub fn parse_der_visiblestring(i: &[u8]) -> DerResult { |
225 | 0 | parse_der_with_tag(i, Tag::VisibleString) |
226 | 0 | } |
227 | | |
228 | | #[deprecated(since = "8.2.0", note = "Use `parse_der_visiblestring` instead")] |
229 | | #[inline] |
230 | 0 | pub fn visiblestring(i: &[u8]) -> DerResult { |
231 | 0 | parse_der_visiblestring(i) |
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, Tag::PrintableString) |
239 | 0 | } Unexecuted instantiation: der_parser::der::parser::parse_der_printablestring Unexecuted instantiation: der_parser::der::parser::parse_der_printablestring |
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, Tag::T61String) |
245 | 0 | } Unexecuted instantiation: der_parser::der::parser::parse_der_t61string Unexecuted instantiation: der_parser::der::parser::parse_der_t61string |
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, Tag::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, Tag::Ia5String) |
257 | 0 | } Unexecuted instantiation: der_parser::der::parser::parse_der_ia5string Unexecuted instantiation: der_parser::der::parser::parse_der_ia5string |
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, Tag::UtcTime) |
263 | 0 | } |
264 | | |
265 | | /// Read a Generalized time value |
266 | | #[inline] |
267 | 0 | pub fn parse_der_generalizedtime(i: &[u8]) -> DerResult { |
268 | 0 | parse_der_with_tag(i, Tag::GeneralizedTime) |
269 | 0 | } |
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, Tag::ObjectDescriptor) |
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, Tag::GraphicString) |
281 | 0 | } |
282 | | |
283 | | /// Read a GeneralString value |
284 | | #[inline] |
285 | 0 | pub fn parse_der_generalstring(i: &[u8]) -> DerResult { |
286 | 0 | parse_der_with_tag(i, Tag::GeneralString) |
287 | 0 | } |
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, Tag::BmpString) |
293 | 0 | } Unexecuted instantiation: der_parser::der::parser::parse_der_bmpstring Unexecuted instantiation: der_parser::der::parser::parse_der_bmpstring |
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, Tag::UniversalString) |
299 | 0 | } Unexecuted instantiation: der_parser::der::parser::parse_der_universalstring Unexecuted instantiation: der_parser::der::parser::parse_der_universalstring |
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: Tag, 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(Tag::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, T, F>(i: &'a [u8], tag: T, f: F) -> DerResult<'a> |
360 | 0 | where |
361 | 0 | F: Fn(&'a [u8], &'_ Header, usize) -> BerResult<'a, DerObjectContent<'a>>, |
362 | 0 | T: Into<Tag>, |
363 | | { |
364 | 0 | parse_ber_implicit(i, tag, f) |
365 | 0 | } Unexecuted instantiation: der_parser::der::parser::parse_der_implicit::<u32, der_parser::der::parser::parse_der_content::{closure#0}>Unexecuted instantiation: der_parser::der::parser::parse_der_implicit::<_, _> |
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 | <i32>::from_der(i) |
374 | 0 | } |
375 | | |
376 | | /// Parse DER object and try to decode it as a 64-bits signed integer |
377 | | /// |
378 | | /// Return `IntegerTooLarge` if object is an integer, but can not be represented in the target |
379 | | /// integer type. |
380 | | #[inline] |
381 | 0 | pub fn parse_der_i64(i: &[u8]) -> BerResult<i64> { |
382 | 0 | <i64>::from_der(i) |
383 | 0 | } |
384 | | |
385 | | /// Parse DER object and try to decode it as a 32-bits unsigned integer |
386 | | /// |
387 | | /// Return `IntegerTooLarge` if object is an integer, but can not be represented in the target |
388 | | /// integer type. |
389 | 0 | pub fn parse_der_u32(i: &[u8]) -> BerResult<u32> { |
390 | 0 | <u32>::from_der(i) |
391 | 0 | } |
392 | | |
393 | | /// Parse DER object and try to decode it as a 64-bits unsigned integer |
394 | | /// |
395 | | /// Return `IntegerTooLarge` if object is an integer, but can not be represented in the target |
396 | | /// integer type. |
397 | 0 | pub fn parse_der_u64(i: &[u8]) -> BerResult<u64> { |
398 | 0 | <u64>::from_der(i) |
399 | 0 | } |
400 | | |
401 | | /// Parse DER object and get content as slice |
402 | | #[inline] |
403 | 0 | pub fn parse_der_slice<T: Into<Tag>>(i: &[u8], tag: T) -> BerResult<&[u8]> { |
404 | 0 | let tag = tag.into(); |
405 | 0 | parse_der_container(move |content, hdr| { |
406 | 0 | hdr.assert_tag(tag)?; |
407 | 0 | Ok((&b""[..], content)) |
408 | 0 | })(i) |
409 | 0 | } |
410 | | |
411 | | /// Parse the next bytes as the content of a DER object (combinator, header reference) |
412 | | /// |
413 | | /// Content type is *not* checked to match tag, caller is responsible of providing the correct tag |
414 | | /// |
415 | | /// Caller is also responsible to check if parsing function consumed the expected number of |
416 | | /// bytes (`header.len`). |
417 | | /// |
418 | | /// This function differs from [`parse_der_content2`](fn.parse_der_content2.html) because it passes |
419 | | /// the BER object header by reference (required for ex. by `parse_der_implicit`). |
420 | | /// |
421 | | /// The arguments of the parse function are: `(input, ber_object_header, max_recursion)`. |
422 | | /// |
423 | | /// Example: manually parsing header and content |
424 | | /// |
425 | | /// ``` |
426 | | /// # use der_parser::ber::MAX_RECURSION; |
427 | | /// # use der_parser::der::*; |
428 | | /// # |
429 | | /// # let bytes = &[0x02, 0x03, 0x01, 0x00, 0x01]; |
430 | | /// let (i, header) = der_read_element_header(bytes).expect("parsing failed"); |
431 | | /// let (rem, content) = parse_der_content(header.tag())(i, &header, MAX_RECURSION) |
432 | | /// .expect("parsing failed"); |
433 | | /// # |
434 | | /// # assert_eq!(header.tag(), Tag::Integer); |
435 | | /// ``` |
436 | 0 | pub fn parse_der_content<'a>( |
437 | 0 | tag: Tag, |
438 | 0 | ) -> impl Fn(&'a [u8], &'_ Header, usize) -> BerResult<'a, DerObjectContent<'a>> { |
439 | 0 | move |i: &[u8], hdr: &Header, max_recursion: usize| { |
440 | 0 | der_read_element_content_as(i, tag, hdr.length(), hdr.is_constructed(), max_recursion) |
441 | 0 | } Unexecuted instantiation: der_parser::der::parser::parse_der_content::{closure#0}Unexecuted instantiation: der_parser::der::parser::parse_der_content::{closure#0} |
442 | 0 | } |
443 | | |
444 | | /// Parse the next bytes as the content of a DER object (combinator, owned header) |
445 | | /// |
446 | | /// Content type is *not* checked to match tag, caller is responsible of providing the correct tag |
447 | | /// |
448 | | /// Caller is also responsible to check if parsing function consumed the expected number of |
449 | | /// bytes (`header.len`). |
450 | | /// |
451 | | /// The arguments of the parse function are: `(input, ber_object_header, max_recursion)`. |
452 | | /// |
453 | | /// This function differs from [`parse_der_content`](fn.parse_der_content.html) because it passes |
454 | | /// an owned BER object header (required for ex. by `parse_der_tagged_implicit_g`). |
455 | | /// |
456 | | /// Example: manually parsing header and content |
457 | | /// |
458 | | /// ``` |
459 | | /// # use der_parser::ber::MAX_RECURSION; |
460 | | /// # use der_parser::der::*; |
461 | | /// # |
462 | | /// # let bytes = &[0x02, 0x03, 0x01, 0x00, 0x01]; |
463 | | /// let (i, header) = der_read_element_header(bytes).expect("parsing failed"); |
464 | | /// # assert_eq!(header.tag(), Tag::Integer); |
465 | | /// let (rem, content) = parse_der_content2(header.tag())(i, header, MAX_RECURSION) |
466 | | /// .expect("parsing failed"); |
467 | | /// ``` |
468 | 0 | pub fn parse_der_content2<'a>( |
469 | 0 | tag: Tag, |
470 | 0 | ) -> impl Fn(&'a [u8], Header<'a>, usize) -> BerResult<'a, DerObjectContent<'a>> { |
471 | 0 | move |i: &[u8], hdr: Header, max_recursion: usize| { |
472 | 0 | der_read_element_content_as(i, tag, hdr.length(), hdr.is_constructed(), max_recursion) |
473 | 0 | } |
474 | 0 | } |
475 | | |
476 | | // --------- end of parse_der_xxx functions ---------- |
477 | | |
478 | | /// Parse the next bytes as the content of a DER object. |
479 | | /// |
480 | | /// Content type is *not* checked, caller is responsible of providing the correct tag |
481 | 0 | pub fn der_read_element_content_as( |
482 | 0 | i: &[u8], |
483 | 0 | tag: Tag, |
484 | 0 | length: Length, |
485 | 0 | constructed: bool, |
486 | 0 | max_depth: usize, |
487 | 0 | ) -> BerResult<DerObjectContent> { |
488 | | // Indefinite lengths are not allowed in DER (X.690 section 10.1) |
489 | 0 | let l = length.definite()?; |
490 | 0 | if i.len() < l { |
491 | 0 | return Err(Err::Incomplete(Needed::new(l))); |
492 | 0 | } |
493 | 0 | match tag { |
494 | | Tag::Boolean => { |
495 | 0 | custom_check!(i, l != 1, BerError::InvalidLength)?; |
496 | 0 | der_constraint_fail_if!(i, i[0] != 0 && i[0] != 0xff, DerConstraint::InvalidBoolean); |
497 | | } |
498 | | Tag::BitString => { |
499 | 0 | der_constraint_fail_if!(i, constructed, DerConstraint::Constructed); |
500 | | // exception: read and verify padding bits |
501 | 0 | return der_read_content_bitstring(i, l); |
502 | | } |
503 | | Tag::Integer => { |
504 | | // verify leading zeros |
505 | 0 | match i[..l] { |
506 | 0 | [] => { |
507 | 0 | return Err(Err::Error(BerError::DerConstraintFailed( |
508 | 0 | DerConstraint::IntegerEmpty, |
509 | 0 | ))) |
510 | | } |
511 | 0 | [0, 0, ..] => { |
512 | 0 | return Err(Err::Error(BerError::DerConstraintFailed( |
513 | 0 | DerConstraint::IntegerLeadingZeroes, |
514 | 0 | ))) |
515 | | } |
516 | 0 | [0, byte, ..] if byte < 0x80 => { |
517 | 0 | return Err(Err::Error(BerError::DerConstraintFailed( |
518 | 0 | DerConstraint::IntegerLeadingZeroes, |
519 | 0 | ))); |
520 | | } |
521 | 0 | _ => (), |
522 | | } |
523 | | } |
524 | | Tag::NumericString |
525 | | | Tag::VisibleString |
526 | | | Tag::PrintableString |
527 | | | Tag::Ia5String |
528 | | | Tag::Utf8String |
529 | | | Tag::T61String |
530 | | | Tag::VideotexString |
531 | | | Tag::BmpString |
532 | | | Tag::UniversalString |
533 | | | Tag::ObjectDescriptor |
534 | | | Tag::GraphicString |
535 | | | Tag::GeneralString => { |
536 | 0 | der_constraint_fail_if!(i, constructed, DerConstraint::Constructed); |
537 | | } |
538 | | Tag::UtcTime | Tag::GeneralizedTime => { |
539 | 0 | if l == 0 || i.get(l - 1).cloned() != Some(b'Z') { |
540 | 0 | return Err(Err::Error(BerError::DerConstraintFailed( |
541 | 0 | DerConstraint::MissingTimeZone, |
542 | 0 | ))); |
543 | 0 | } |
544 | | } |
545 | 0 | _ => (), |
546 | | } |
547 | 0 | ber_read_element_content_as(i, tag, length, constructed, max_depth) |
548 | 0 | } |
549 | | |
550 | | /// Parse DER object content recursively |
551 | | /// |
552 | | /// *Note: an error is raised if recursion depth exceeds `MAX_RECURSION`. |
553 | 0 | pub fn der_read_element_content<'a>(i: &'a [u8], hdr: Header<'a>) -> DerResult<'a> { |
554 | 0 | der_read_element_content_recursive(i, hdr, MAX_RECURSION) |
555 | 0 | } |
556 | | |
557 | 0 | fn der_read_element_content_recursive<'a>( |
558 | 0 | i: &'a [u8], |
559 | 0 | hdr: Header<'a>, |
560 | 0 | max_depth: usize, |
561 | 0 | ) -> DerResult<'a> { |
562 | 0 | match hdr.class() { |
563 | 0 | Class::Universal => (), |
564 | | _ => { |
565 | 0 | let (i, data) = ber_get_object_content(i, &hdr, max_depth)?; |
566 | 0 | let any = Any::new(hdr.clone(), data); |
567 | 0 | let content = DerObjectContent::Unknown(any); |
568 | 0 | let obj = DerObject::from_header_and_content(hdr, content); |
569 | 0 | return Ok((i, obj)); |
570 | | } |
571 | | } |
572 | 0 | match der_read_element_content_as(i, hdr.tag(), hdr.length(), hdr.is_constructed(), max_depth) { |
573 | 0 | Ok((rem, content)) => Ok((rem, DerObject::from_header_and_content(hdr, content))), |
574 | | Err(Err::Error(BerError::UnknownTag(_))) => { |
575 | 0 | let (rem, data) = ber_get_object_content(i, &hdr, max_depth)?; |
576 | 0 | let any = Any::new(hdr.clone(), data); |
577 | 0 | let content = DerObjectContent::Unknown(any); |
578 | 0 | let obj = DerObject::from_header_and_content(hdr, content); |
579 | 0 | Ok((rem, obj)) |
580 | | } |
581 | 0 | Err(e) => Err(e), |
582 | | } |
583 | 0 | } |
584 | | |
585 | 0 | fn der_read_content_bitstring(i: &[u8], len: usize) -> BerResult<DerObjectContent> { |
586 | 0 | let (i, ignored_bits) = be_u8(i)?; |
587 | 0 | if ignored_bits > 7 { |
588 | 0 | return Err(Err::Error(BerError::invalid_value( |
589 | 0 | Tag::BitString, |
590 | 0 | "More than 7 unused bits".to_owned(), |
591 | 0 | ))); |
592 | 0 | } |
593 | 0 | if len == 0 { |
594 | 0 | return Err(Err::Error(BerError::InvalidLength)); |
595 | 0 | } |
596 | 0 | let (i, data) = take(len - 1)(i)?; |
597 | 0 | if len > 1 { |
598 | 0 | let mut last_byte = data[len - 2]; |
599 | 0 | for _ in 0..ignored_bits as usize { |
600 | 0 | der_constraint_fail_if!(i, last_byte & 1 != 0, DerConstraint::UnusedBitsNotZero); |
601 | 0 | last_byte >>= 1; |
602 | | } |
603 | 0 | } |
604 | 0 | Ok(( |
605 | 0 | i, |
606 | 0 | DerObjectContent::BitString(ignored_bits, BitStringObject { data }), |
607 | 0 | )) |
608 | | // do_parse! { |
609 | | // i, |
610 | | // ignored_bits: be_u8 >> |
611 | | // custom_check!(ignored_bits > 7, BerError::DerConstraintFailed) >> |
612 | | // custom_check!(len == 0, BerError::InvalidLength) >> |
613 | | // s: take!(len - 1) >> |
614 | | // call!(|input| { |
615 | | // if len > 1 { |
616 | | // let mut last_byte = s[len-2]; |
617 | | // for _ in 0..ignored_bits as usize { |
618 | | // der_constraint_fail_if!(i, last_byte & 1 != 0); |
619 | | // last_byte >>= 1; |
620 | | // } |
621 | | // } |
622 | | // Ok((input,())) |
623 | | // }) >> |
624 | | // ( DerObjectContent::BitString(ignored_bits,BitStringObject{ data:s }) ) |
625 | | // } |
626 | 0 | } |
627 | | |
628 | | /// Read an object header (DER) |
629 | | #[inline] |
630 | 0 | pub fn der_read_element_header(i: &[u8]) -> BerResult<Header> { |
631 | 0 | Header::from_der(i) |
632 | 0 | } Unexecuted instantiation: der_parser::der::parser::der_read_element_header Unexecuted instantiation: der_parser::der::parser::der_read_element_header |