/rust/registry/src/index.crates.io-1949cf8c6b5b557f/der-parser-10.0.0/src/ber/parser.rs
Line | Count | Source |
1 | | use crate::ber::*; |
2 | | use crate::error::*; |
3 | | use asn1_rs::FromBer; |
4 | | use nom::bytes::streaming::take; |
5 | | use nom::{Err, Offset}; |
6 | | |
7 | | /// Default maximum recursion limit |
8 | | pub const MAX_RECURSION: usize = 50; |
9 | | |
10 | | /// Default maximum object size (2^32) |
11 | | pub const MAX_OBJECT_SIZE: usize = 4_294_967_295; |
12 | | |
13 | | /// Skip object content, and return true if object was End-Of-Content |
14 | 0 | pub(crate) fn ber_skip_object_content<'a>( |
15 | 0 | i: &'a [u8], |
16 | 0 | hdr: &Header, |
17 | 0 | max_depth: usize, |
18 | 0 | ) -> BerResult<'a, bool> { |
19 | 0 | if max_depth == 0 { |
20 | 0 | return Err(Err::Error(BerError::BerMaxDepth)); |
21 | 0 | } |
22 | 0 | match hdr.length() { |
23 | 0 | Length::Definite(l) => { |
24 | 0 | if l == 0 && hdr.tag() == Tag::EndOfContent { |
25 | 0 | return Ok((i, true)); |
26 | 0 | } |
27 | 0 | let (i, _) = take(l)(i)?; |
28 | 0 | Ok((i, false)) |
29 | | } |
30 | | Length::Indefinite => { |
31 | 0 | if hdr.is_primitive() { |
32 | 0 | return Err(Err::Error(BerError::ConstructExpected)); |
33 | 0 | } |
34 | | // read objects until EndOfContent (00 00) |
35 | | // this is recursive |
36 | 0 | let mut i = i; |
37 | | loop { |
38 | 0 | let (i2, header2) = ber_read_element_header(i)?; |
39 | 0 | let (i3, eoc) = ber_skip_object_content(i2, &header2, max_depth - 1)?; |
40 | 0 | if eoc { |
41 | | // return false, since top object was not EndOfContent |
42 | 0 | return Ok((i3, false)); |
43 | 0 | } |
44 | 0 | i = i3; |
45 | | } |
46 | | } |
47 | | } |
48 | 0 | } |
49 | | |
50 | | /// Read object raw content (bytes) |
51 | 0 | pub(crate) fn ber_get_object_content<'a>( |
52 | 0 | i: &'a [u8], |
53 | 0 | hdr: &Header, |
54 | 0 | max_depth: usize, |
55 | 0 | ) -> BerResult<'a, &'a [u8]> { |
56 | 0 | let start_i = i; |
57 | 0 | let (i, _) = ber_skip_object_content(i, hdr, max_depth)?; |
58 | 0 | let len = start_i.offset(i); |
59 | 0 | let (content, i) = start_i.split_at(len); |
60 | | // if len is indefinite, there are 2 extra bytes for EOC |
61 | 0 | if hdr.length() == Length::Indefinite { |
62 | 0 | let len = content.len(); |
63 | 0 | assert!(len >= 2); |
64 | 0 | Ok((i, &content[..len - 2])) |
65 | | } else { |
66 | 0 | Ok((i, content)) |
67 | | } |
68 | 0 | } |
69 | | |
70 | | /// Try to parse an input bit string as u64. |
71 | | /// |
72 | | /// Note: this is for the primitive BER/DER encoding only, the |
73 | | /// constructed BER encoding for BIT STRING does not seem to be |
74 | | /// supported at all by the library currently. |
75 | | #[inline] |
76 | 0 | pub(crate) fn bitstring_to_u64( |
77 | 0 | padding_bits: usize, |
78 | 0 | data: &BitStringObject, |
79 | 0 | ) -> Result<u64, BerError> { |
80 | 0 | let raw_bytes = data.data; |
81 | 0 | let bit_size = (raw_bytes.len() * 8) |
82 | 0 | .checked_sub(padding_bits) |
83 | 0 | .ok_or(BerError::InvalidLength)?; |
84 | 0 | if bit_size > 64 { |
85 | 0 | return Err(BerError::IntegerTooLarge); |
86 | 0 | } |
87 | 0 | let padding_bits = padding_bits % 8; |
88 | 0 | let num_bytes = if bit_size % 8 > 0 { |
89 | 0 | (bit_size / 8) + 1 |
90 | | } else { |
91 | 0 | bit_size / 8 |
92 | | }; |
93 | 0 | let mut resulting_integer: u64 = 0; |
94 | 0 | for &c in &raw_bytes[..num_bytes] { |
95 | 0 | resulting_integer <<= 8; |
96 | 0 | resulting_integer |= c as u64; |
97 | 0 | } |
98 | 0 | Ok(resulting_integer >> padding_bits) |
99 | 0 | } |
100 | | |
101 | | /// Read an object header |
102 | | /// |
103 | | /// ### Example |
104 | | /// |
105 | | /// ``` |
106 | | /// # use der_parser::ber::{ber_read_element_header, Class, Length, Tag}; |
107 | | /// # |
108 | | /// let bytes = &[0x02, 0x03, 0x01, 0x00, 0x01]; |
109 | | /// let (i, hdr) = ber_read_element_header(bytes).expect("could not read header"); |
110 | | /// |
111 | | /// assert_eq!(hdr.class(), Class::Universal); |
112 | | /// assert_eq!(hdr.tag(), Tag::Integer); |
113 | | /// assert_eq!(hdr.length(), Length::Definite(3)); |
114 | | /// ``` |
115 | | #[inline] |
116 | 0 | pub fn ber_read_element_header(i: &[u8]) -> BerResult<Header> { |
117 | 0 | Header::from_ber(i) |
118 | 0 | } Unexecuted instantiation: der_parser::ber::parser::ber_read_element_header Unexecuted instantiation: der_parser::ber::parser::ber_read_element_header |
119 | | |
120 | | /// Parse the next bytes as the *content* of a BER object. |
121 | | /// |
122 | | /// Content type is *not* checked to match tag, caller is responsible of providing the correct tag |
123 | | /// |
124 | | /// This function is mostly used when parsing implicit tagged objects, when reading primitive |
125 | | /// types. |
126 | | /// |
127 | | /// `max_depth` is the maximum allowed recursion for objects. |
128 | | /// |
129 | | /// ### Example |
130 | | /// |
131 | | /// ``` |
132 | | /// # use der_parser::ber::{ber_read_element_content_as, ber_read_element_header, Tag}; |
133 | | /// # |
134 | | /// # let bytes = &[0x02, 0x03, 0x01, 0x00, 0x01]; |
135 | | /// let (i, hdr) = ber_read_element_header(bytes).expect("could not read header"); |
136 | | /// let (_, content) = ber_read_element_content_as( |
137 | | /// i, hdr.tag(), hdr.length(), hdr.is_constructed(), 5 |
138 | | /// ).expect("parsing failed"); |
139 | | /// # |
140 | | /// # assert_eq!(hdr.tag(), Tag::Integer); |
141 | | /// # assert_eq!(content.as_u32(), Ok(0x10001)); |
142 | | /// ``` |
143 | | #[inline] |
144 | 0 | pub fn ber_read_element_content_as( |
145 | 0 | i: &[u8], |
146 | 0 | tag: Tag, |
147 | 0 | length: Length, |
148 | 0 | constructed: bool, |
149 | 0 | max_depth: usize, |
150 | 0 | ) -> BerResult<BerObjectContent> { |
151 | 0 | try_read_berobjectcontent_as(i, tag, length, constructed, max_depth) |
152 | 0 | } Unexecuted instantiation: der_parser::ber::parser::ber_read_element_content_as Unexecuted instantiation: der_parser::ber::parser::ber_read_element_content_as |
153 | | |
154 | | /// Parse the next bytes as the content of a BER object (combinator, header reference) |
155 | | /// |
156 | | /// Content type is *not* checked to match tag, caller is responsible of providing the correct tag |
157 | | /// |
158 | | /// Caller is also responsible to check if parsing function consumed the expected number of |
159 | | /// bytes (`header.len`). |
160 | | /// |
161 | | /// The arguments of the parse function are: `(input, ber_object_header, max_recursion)`. |
162 | | /// |
163 | | /// This function differs from [`parse_ber_content2`](fn.parse_ber_content2.html) because it passes |
164 | | /// the BER object header by reference (required for ex. by `parse_ber_implicit`). |
165 | | /// |
166 | | /// Example: manually parsing header and content |
167 | | /// |
168 | | /// ``` |
169 | | /// # use der_parser::ber::*; |
170 | | /// # |
171 | | /// # let bytes = &[0x02, 0x03, 0x01, 0x00, 0x01]; |
172 | | /// let (i, header) = ber_read_element_header(bytes).expect("parsing failed"); |
173 | | /// let (rem, content) = parse_ber_content(header.tag())(i, &header, MAX_RECURSION) |
174 | | /// .expect("parsing failed"); |
175 | | /// # |
176 | | /// # assert_eq!(header.tag(), Tag::Integer); |
177 | | /// ``` |
178 | 0 | pub fn parse_ber_content<'a>( |
179 | 0 | tag: Tag, |
180 | 0 | ) -> impl Fn(&'a [u8], &'_ Header, usize) -> BerResult<'a, BerObjectContent<'a>> { |
181 | 0 | move |i: &[u8], hdr: &Header, max_recursion: usize| { |
182 | 0 | ber_read_element_content_as(i, tag, hdr.length(), hdr.is_constructed(), max_recursion) |
183 | 0 | } |
184 | 0 | } |
185 | | |
186 | | /// Parse the next bytes as the content of a BER object (combinator, owned header) |
187 | | /// |
188 | | /// Content type is *not* checked to match tag, caller is responsible of providing the correct tag |
189 | | /// |
190 | | /// Caller is also responsible to check if parsing function consumed the expected number of |
191 | | /// bytes (`header.len`). |
192 | | /// |
193 | | /// The arguments of the parse function are: `(input, ber_object_header, max_recursion)`. |
194 | | /// |
195 | | /// This function differs from [`parse_ber_content`](fn.parse_ber_content.html) because it passes |
196 | | /// an owned BER object header (required for ex. by `parse_ber_tagged_implicit_g`). |
197 | | /// |
198 | | /// Example: manually parsing header and content |
199 | | /// |
200 | | /// ``` |
201 | | /// # use der_parser::ber::*; |
202 | | /// # |
203 | | /// # let bytes = &[0x02, 0x03, 0x01, 0x00, 0x01]; |
204 | | /// let (i, header) = ber_read_element_header(bytes).expect("parsing failed"); |
205 | | /// let (rem, content) = parse_ber_content(header.tag())(i, &header, MAX_RECURSION) |
206 | | /// .expect("parsing failed"); |
207 | | /// # |
208 | | /// # assert_eq!(header.tag(), Tag::Integer); |
209 | | /// ``` |
210 | 0 | pub fn parse_ber_content2<'a>( |
211 | 0 | tag: Tag, |
212 | 0 | ) -> impl Fn(&'a [u8], Header<'a>, usize) -> BerResult<'a, BerObjectContent<'a>> { |
213 | 0 | move |i: &[u8], hdr: Header, max_recursion: usize| { |
214 | 0 | ber_read_element_content_as(i, tag, hdr.length(), hdr.is_constructed(), max_recursion) |
215 | 0 | } |
216 | 0 | } |
217 | | |
218 | | /// Parse a BER object, expecting a value with specified tag |
219 | | /// |
220 | | /// The object is parsed recursively, with a maximum depth of `MAX_RECURSION`. |
221 | | /// |
222 | | /// ### Example |
223 | | /// |
224 | | /// ``` |
225 | | /// use der_parser::ber::Tag; |
226 | | /// use der_parser::ber::parse_ber_with_tag; |
227 | | /// |
228 | | /// let bytes = &[0x02, 0x03, 0x01, 0x00, 0x01]; |
229 | | /// let (_, obj) = parse_ber_with_tag(bytes, Tag::Integer).expect("parsing failed"); |
230 | | /// |
231 | | /// assert_eq!(obj.header.tag(), Tag::Integer); |
232 | | /// ``` |
233 | 0 | pub fn parse_ber_with_tag<T: Into<Tag>>(i: &[u8], tag: T) -> BerResult { |
234 | 0 | let tag = tag.into(); |
235 | 0 | let (i, hdr) = ber_read_element_header(i)?; |
236 | 0 | hdr.assert_tag(tag)?; |
237 | 0 | let (i, content) = ber_read_element_content_as( |
238 | 0 | i, |
239 | 0 | hdr.tag(), |
240 | 0 | hdr.length(), |
241 | 0 | hdr.is_constructed(), |
242 | | MAX_RECURSION, |
243 | 0 | )?; |
244 | 0 | Ok((i, BerObject::from_header_and_content(hdr, content))) |
245 | 0 | } Unexecuted instantiation: der_parser::ber::parser::parse_ber_with_tag::<asn1_rs::tag::Tag> Unexecuted instantiation: der_parser::ber::parser::parse_ber_with_tag::<_> |
246 | | |
247 | | /// Read end of content marker |
248 | | #[inline] |
249 | 0 | pub fn parse_ber_endofcontent(i: &[u8]) -> BerResult { |
250 | 0 | parse_ber_with_tag(i, Tag::EndOfContent) |
251 | 0 | } |
252 | | |
253 | | /// Read a boolean value |
254 | | /// |
255 | | /// The encoding of a boolean value shall be primitive. The contents octets shall consist of a |
256 | | /// single octet. |
257 | | /// |
258 | | /// If the boolean value is FALSE, the octet shall be zero. |
259 | | /// If the boolean value is TRUE, the octet shall be one byte, and have all bits set to one (0xff). |
260 | | #[inline] |
261 | 0 | pub fn parse_ber_bool(i: &[u8]) -> BerResult { |
262 | 0 | parse_ber_with_tag(i, Tag::Boolean) |
263 | 0 | } Unexecuted instantiation: der_parser::ber::parser::parse_ber_bool Unexecuted instantiation: der_parser::ber::parser::parse_ber_bool |
264 | | |
265 | | /// Read an integer value |
266 | | /// |
267 | | /// The encoding of a boolean value shall be primitive. The contents octets shall consist of one or |
268 | | /// more octets. |
269 | | /// |
270 | | /// To access the content, use the [`as_u64`](struct.BerObject.html#method.as_u64), |
271 | | /// [`as_u32`](struct.BerObject.html#method.as_u32), |
272 | | /// [`as_biguint`](struct.BerObject.html#method.as_biguint) or |
273 | | /// [`as_bigint`](struct.BerObject.html#method.as_bigint) methods. |
274 | | /// Remember that a BER integer has unlimited size, so these methods return `Result` or `Option` |
275 | | /// objects. |
276 | | /// |
277 | | /// # Examples |
278 | | /// |
279 | | /// ```rust |
280 | | /// # extern crate nom; |
281 | | /// # use der_parser::ber::parse_ber_integer; |
282 | | /// # use der_parser::ber::{BerObject,BerObjectContent}; |
283 | | /// let empty = &b""[..]; |
284 | | /// let bytes = [0x02, 0x03, 0x01, 0x00, 0x01]; |
285 | | /// let expected = BerObject::from_obj(BerObjectContent::Integer(b"\x01\x00\x01")); |
286 | | /// assert_eq!( |
287 | | /// parse_ber_integer(&bytes), |
288 | | /// Ok((empty, expected)) |
289 | | /// ); |
290 | | /// ``` |
291 | | #[inline] |
292 | 0 | pub fn parse_ber_integer(i: &[u8]) -> BerResult { |
293 | 0 | parse_ber_with_tag(i, Tag::Integer) |
294 | 0 | } |
295 | | |
296 | | /// Read an bitstring value |
297 | | #[inline] |
298 | 0 | pub fn parse_ber_bitstring(i: &[u8]) -> BerResult { |
299 | 0 | parse_ber_with_tag(i, Tag::BitString) |
300 | 0 | } |
301 | | |
302 | | /// Read an octetstring value |
303 | | #[inline] |
304 | 0 | pub fn parse_ber_octetstring(i: &[u8]) -> BerResult { |
305 | 0 | parse_ber_with_tag(i, Tag::OctetString) |
306 | 0 | } |
307 | | |
308 | | /// Read a null value |
309 | | #[inline] |
310 | 0 | pub fn parse_ber_null(i: &[u8]) -> BerResult { |
311 | 0 | parse_ber_with_tag(i, Tag::Null) |
312 | 0 | } |
313 | | |
314 | | /// Read an object identifier value |
315 | | #[inline] |
316 | 0 | pub fn parse_ber_oid(i: &[u8]) -> BerResult { |
317 | 0 | parse_ber_with_tag(i, Tag::Oid) |
318 | 0 | } |
319 | | |
320 | | /// Read an enumerated value |
321 | | #[inline] |
322 | 0 | pub fn parse_ber_enum(i: &[u8]) -> BerResult { |
323 | 0 | parse_ber_with_tag(i, Tag::Enumerated) |
324 | 0 | } |
325 | | |
326 | | /// Read a UTF-8 string value. The encoding is checked. |
327 | | #[inline] |
328 | 0 | pub fn parse_ber_utf8string(i: &[u8]) -> BerResult { |
329 | 0 | parse_ber_with_tag(i, Tag::Utf8String) |
330 | 0 | } |
331 | | |
332 | | /// Read a relative object identifier value |
333 | | #[inline] |
334 | 0 | pub fn parse_ber_relative_oid(i: &[u8]) -> BerResult { |
335 | 0 | parse_ber_with_tag(i, Tag::RelativeOid) |
336 | 0 | } |
337 | | |
338 | | /// Parse a sequence of BER elements |
339 | | /// |
340 | | /// Read a sequence of BER objects, without any constraint on the types. |
341 | | /// Sequence is parsed recursively, so if constructed elements are found, they are parsed using the |
342 | | /// same function. |
343 | | /// |
344 | | /// To read a specific sequence of objects (giving the expected types), use the |
345 | | /// [`parse_ber_sequence_defined`](macro.parse_ber_sequence_defined.html) macro. |
346 | | #[inline] |
347 | 0 | pub fn parse_ber_sequence(i: &[u8]) -> BerResult { |
348 | 0 | parse_ber_with_tag(i, Tag::Sequence) |
349 | 0 | } |
350 | | |
351 | | /// Parse a set of BER elements |
352 | | /// |
353 | | /// Read a set of BER objects, without any constraint on the types. |
354 | | /// Set is parsed recursively, so if constructed elements are found, they are parsed using the |
355 | | /// same function. |
356 | | /// |
357 | | /// To read a specific set of objects (giving the expected types), use the |
358 | | /// [`parse_ber_set_defined`](macro.parse_ber_set_defined.html) macro. |
359 | | #[inline] |
360 | 0 | pub fn parse_ber_set(i: &[u8]) -> BerResult { |
361 | 0 | parse_ber_with_tag(i, Tag::Set) |
362 | 0 | } |
363 | | |
364 | | /// Read a numeric string value. The content is verified to |
365 | | /// contain only digits and spaces. |
366 | | #[inline] |
367 | 0 | pub fn parse_ber_numericstring(i: &[u8]) -> BerResult { |
368 | 0 | parse_ber_with_tag(i, Tag::NumericString) |
369 | 0 | } |
370 | | |
371 | | /// Read a visible string value. The content is verified to |
372 | | /// contain only the allowed characters. |
373 | | #[inline] |
374 | 0 | pub fn parse_ber_visiblestring(i: &[u8]) -> BerResult { |
375 | 0 | parse_ber_with_tag(i, Tag::VisibleString) |
376 | 0 | } |
377 | | |
378 | | /// Read a printable string value. The content is verified to |
379 | | /// contain only the allowed characters. |
380 | | #[inline] |
381 | 0 | pub fn parse_ber_printablestring(i: &[u8]) -> BerResult { |
382 | 0 | parse_ber_with_tag(i, Tag::PrintableString) |
383 | 0 | } |
384 | | |
385 | | /// Read a T61 string value |
386 | | #[inline] |
387 | 0 | pub fn parse_ber_t61string(i: &[u8]) -> BerResult { |
388 | 0 | parse_ber_with_tag(i, Tag::T61String) |
389 | 0 | } |
390 | | |
391 | | /// Read a Videotex string value |
392 | | #[inline] |
393 | 0 | pub fn parse_ber_videotexstring(i: &[u8]) -> BerResult { |
394 | 0 | parse_ber_with_tag(i, Tag::VideotexString) |
395 | 0 | } |
396 | | |
397 | | /// Read an IA5 string value. The content is verified to be ASCII. |
398 | | #[inline] |
399 | 0 | pub fn parse_ber_ia5string(i: &[u8]) -> BerResult { |
400 | 0 | parse_ber_with_tag(i, Tag::Ia5String) |
401 | 0 | } |
402 | | |
403 | | /// Read an UTC time value |
404 | | #[inline] |
405 | 0 | pub fn parse_ber_utctime(i: &[u8]) -> BerResult { |
406 | 0 | parse_ber_with_tag(i, Tag::UtcTime) |
407 | 0 | } |
408 | | |
409 | | /// Read a Generalized time value |
410 | | #[inline] |
411 | 0 | pub fn parse_ber_generalizedtime(i: &[u8]) -> BerResult { |
412 | 0 | parse_ber_with_tag(i, Tag::GeneralizedTime) |
413 | 0 | } |
414 | | |
415 | | /// Read an ObjectDescriptor value |
416 | | #[inline] |
417 | 0 | pub fn parse_ber_objectdescriptor(i: &[u8]) -> BerResult { |
418 | 0 | parse_ber_with_tag(i, Tag::ObjectDescriptor) |
419 | 0 | } |
420 | | |
421 | | /// Read a GraphicString value |
422 | | #[inline] |
423 | 0 | pub fn parse_ber_graphicstring(i: &[u8]) -> BerResult { |
424 | 0 | parse_ber_with_tag(i, Tag::GraphicString) |
425 | 0 | } |
426 | | |
427 | | /// Read a GeneralString value |
428 | | #[inline] |
429 | 0 | pub fn parse_ber_generalstring(i: &[u8]) -> BerResult { |
430 | 0 | parse_ber_with_tag(i, Tag::GeneralString) |
431 | 0 | } |
432 | | |
433 | | /// Read a BmpString value |
434 | | #[inline] |
435 | 0 | pub fn parse_ber_bmpstring(i: &[u8]) -> BerResult { |
436 | 0 | parse_ber_with_tag(i, Tag::BmpString) |
437 | 0 | } |
438 | | |
439 | | /// Read a UniversalString value |
440 | | #[inline] |
441 | 0 | pub fn parse_ber_universalstring(i: &[u8]) -> BerResult { |
442 | 0 | parse_ber_with_tag(i, Tag::UniversalString) |
443 | 0 | } |
444 | | |
445 | | /// Parse an optional tagged object, applying function to get content |
446 | | /// |
447 | | /// This function returns a `BerObject`, trying to read content as generic BER objects. |
448 | | /// If parsing failed, return an optional object containing `None`. |
449 | | /// |
450 | | /// To support other return or error types, use |
451 | | /// [parse_ber_tagged_explicit_g](fn.parse_ber_tagged_explicit_g.html) |
452 | | /// |
453 | | /// This function will never fail: if parsing content failed, the BER value `Optional(None)` is |
454 | | /// returned. |
455 | 0 | pub fn parse_ber_explicit_optional<F>(i: &[u8], tag: Tag, f: F) -> BerResult |
456 | 0 | where |
457 | 0 | F: Fn(&[u8]) -> BerResult, |
458 | | { |
459 | 0 | parse_ber_optional(parse_ber_tagged_explicit_g(tag, |content, hdr| { |
460 | 0 | let (rem, obj) = f(content)?; |
461 | 0 | let content = BerObjectContent::Tagged(hdr.class(), hdr.tag(), Box::new(obj)); |
462 | 0 | let tagged = BerObject::from_header_and_content(hdr, content); |
463 | 0 | Ok((rem, tagged)) |
464 | 0 | }))(i) |
465 | 0 | } |
466 | | |
467 | | /// Parse an implicit tagged object, applying function to read content |
468 | | /// |
469 | | /// Note: unlike explicit tagged functions, the callback must be a *content* parsing function, |
470 | | /// often based on the [`parse_ber_content`](fn.parse_ber_content.html) combinator. |
471 | | /// |
472 | | /// The built object will use the original header (and tag), so the content may not match the tag |
473 | | /// value. |
474 | | /// |
475 | | /// For a combinator version, see [parse_ber_tagged_implicit](fn.parse_ber_tagged_implicit.html). |
476 | | /// |
477 | | /// For a generic version (different output and error types), see |
478 | | /// [parse_ber_tagged_implicit_g](fn.parse_ber_tagged_implicit_g.html). |
479 | | /// |
480 | | /// # Examples |
481 | | /// |
482 | | /// The following parses `[3] IMPLICIT INTEGER` into a `BerObject`: |
483 | | /// |
484 | | /// ```rust |
485 | | /// # use der_parser::ber::*; |
486 | | /// # use der_parser::error::BerResult; |
487 | | /// # |
488 | | /// fn parse_int_implicit(i:&[u8]) -> BerResult<BerObject> { |
489 | | /// parse_ber_implicit( |
490 | | /// i, |
491 | | /// 3, |
492 | | /// parse_ber_content(Tag::Integer), |
493 | | /// ) |
494 | | /// } |
495 | | /// |
496 | | /// # let bytes = &[0x83, 0x03, 0x01, 0x00, 0x01]; |
497 | | /// let res = parse_int_implicit(bytes); |
498 | | /// # match res { |
499 | | /// # Ok((rem, content)) => { |
500 | | /// # assert!(rem.is_empty()); |
501 | | /// # assert_eq!(content.as_u32(), Ok(0x10001)); |
502 | | /// # }, |
503 | | /// # _ => assert!(false) |
504 | | /// # } |
505 | | /// ``` |
506 | | #[inline] |
507 | 0 | pub fn parse_ber_implicit<'a, T, F>(i: &'a [u8], tag: T, f: F) -> BerResult<'a> |
508 | 0 | where |
509 | 0 | F: Fn(&'a [u8], &'_ Header, usize) -> BerResult<'a, BerObjectContent<'a>>, |
510 | 0 | T: Into<Tag>, |
511 | | { |
512 | 0 | parse_ber_tagged_implicit(tag, f)(i) |
513 | 0 | } Unexecuted instantiation: der_parser::ber::parser::parse_ber_implicit::<u32, der_parser::der::parser::parse_der_content::{closure#0}>Unexecuted instantiation: der_parser::ber::parser::parse_ber_implicit::<_, _> |
514 | | |
515 | | /// Combinator for building optional BER values |
516 | | /// |
517 | | /// To read optional BER values, it is to use the nom `opt()` combinator. However, this results in |
518 | | /// a `Option<BerObject>` and prevents using some functions from this crate (the generic functions |
519 | | /// can still be used). |
520 | | /// |
521 | | /// This combinator is used when parsing BER values, while keeping `BerObject` output only. |
522 | | /// |
523 | | /// This function will never fail: if parsing content failed, the BER value `Optional(None)` is |
524 | | /// returned. |
525 | | /// |
526 | | /// ### Example |
527 | | /// |
528 | | /// ``` |
529 | | /// # use der_parser::ber::*; |
530 | | /// # |
531 | | /// let bytes = &[0x02, 0x03, 0x01, 0x00, 0x01]; |
532 | | /// let mut parser = parse_ber_optional(parse_ber_integer); |
533 | | /// let (_, obj) = parser(bytes).expect("parsing failed"); |
534 | | /// |
535 | | /// assert_eq!(obj.header.tag(), Tag::Integer); |
536 | | /// assert!(obj.as_optional().is_ok()); |
537 | | /// ``` |
538 | 0 | pub fn parse_ber_optional<'a, F>(mut f: F) -> impl FnMut(&'a [u8]) -> BerResult<'a> |
539 | 0 | where |
540 | 0 | F: FnMut(&'a [u8]) -> BerResult<'a>, |
541 | | { |
542 | 0 | move |i: &[u8]| { |
543 | 0 | let res = f(i); |
544 | 0 | match res { |
545 | 0 | Ok((rem, inner)) => { |
546 | 0 | let opt = BerObject::from_header_and_content( |
547 | 0 | inner.header.clone(), |
548 | 0 | BerObjectContent::Optional(Some(Box::new(inner))), |
549 | | ); |
550 | 0 | Ok((rem, opt)) |
551 | | } |
552 | 0 | Err(_) => Ok((i, BerObject::from_obj(BerObjectContent::Optional(None)))), |
553 | | } |
554 | 0 | } |
555 | 0 | } |
556 | | |
557 | | /// Parse BER object and try to decode it as a 32-bits signed integer |
558 | | /// |
559 | | /// Return `IntegerTooLarge` if object is an integer, but can not be represented in the target |
560 | | /// integer type. |
561 | | #[inline] |
562 | 0 | pub fn parse_ber_i32(i: &[u8]) -> BerResult<i32> { |
563 | 0 | <i32>::from_ber(i) |
564 | 0 | } |
565 | | |
566 | | /// Parse BER object and try to decode it as a 64-bits signed integer |
567 | | /// |
568 | | /// Return `IntegerTooLarge` if object is an integer, but can not be represented in the target |
569 | | /// integer type. |
570 | | #[inline] |
571 | 0 | pub fn parse_ber_i64(i: &[u8]) -> BerResult<i64> { |
572 | 0 | <i64>::from_ber(i) |
573 | 0 | } |
574 | | |
575 | | /// Parse BER object and try to decode it as a 32-bits unsigned integer |
576 | | /// |
577 | | /// Return `IntegerTooLarge` if object is an integer, but can not be represented in the target |
578 | | /// integer type. |
579 | | #[inline] |
580 | 0 | pub fn parse_ber_u32(i: &[u8]) -> BerResult<u32> { |
581 | 0 | <u32>::from_ber(i) |
582 | 0 | } |
583 | | |
584 | | /// Parse BER object and try to decode it as a 64-bits unsigned integer |
585 | | /// |
586 | | /// Return `IntegerTooLarge` if object is an integer, but can not be represented in the target |
587 | | /// integer type. |
588 | | #[inline] |
589 | 0 | pub fn parse_ber_u64(i: &[u8]) -> BerResult<u64> { |
590 | 0 | <u64>::from_ber(i) |
591 | 0 | } |
592 | | |
593 | | /// Parse BER object and get content as slice |
594 | | #[inline] |
595 | 0 | pub fn parse_ber_slice<T: Into<Tag>>(i: &[u8], tag: T) -> BerResult<&[u8]> { |
596 | 0 | let tag = tag.into(); |
597 | 0 | parse_ber_container(move |content, hdr| { |
598 | 0 | hdr.assert_tag(tag)?; |
599 | 0 | Ok((&b""[..], content)) |
600 | 0 | })(i) |
601 | 0 | } |
602 | | |
603 | | /// Parse BER object recursively, specifying the maximum recursion depth |
604 | | /// |
605 | | /// Return a tuple containing the remaining (unparsed) bytes and the BER Object, or an error. |
606 | | /// |
607 | | /// ### Example |
608 | | /// |
609 | | /// ``` |
610 | | /// use der_parser::ber::{parse_ber_recursive, Tag}; |
611 | | /// |
612 | | /// let bytes = &[0x02, 0x03, 0x01, 0x00, 0x01]; |
613 | | /// let (_, obj) = parse_ber_recursive(bytes, 1).expect("parsing failed"); |
614 | | /// |
615 | | /// assert_eq!(obj.header.tag(), Tag::Integer); |
616 | | /// ``` |
617 | | #[inline] |
618 | 0 | pub fn parse_ber_recursive(i: &[u8], max_depth: usize) -> BerResult { |
619 | 0 | parse_ber_any_r(i, max_depth) |
620 | 0 | } |
621 | | |
622 | | /// Parse BER object recursively |
623 | | /// |
624 | | /// Return a tuple containing the remaining (unparsed) bytes and the BER Object, or an error. |
625 | | /// |
626 | | /// *Note*: this is the same as calling `parse_ber_recursive` with `MAX_RECURSION`. |
627 | | /// |
628 | | /// ### Example |
629 | | /// |
630 | | /// ``` |
631 | | /// use der_parser::ber::{parse_ber, Tag}; |
632 | | /// |
633 | | /// let bytes = &[0x02, 0x03, 0x01, 0x00, 0x01]; |
634 | | /// let (_, obj) = parse_ber(bytes).expect("parsing failed"); |
635 | | /// |
636 | | /// assert_eq!(obj.header.tag(), Tag::Integer); |
637 | | /// ``` |
638 | | #[inline] |
639 | 0 | pub fn parse_ber(i: &[u8]) -> BerResult { |
640 | 0 | parse_ber_recursive(i, MAX_RECURSION) |
641 | 0 | } |
642 | | |
643 | | #[test] |
644 | | fn test_bitstring_to_u64() { |
645 | | // ignored bits modulo 8 to 0 |
646 | | let data = &hex_literal::hex!("0d 71 82"); |
647 | | let r = bitstring_to_u64(8, &BitStringObject { data }); |
648 | | assert_eq!(r, Ok(0x0d71)); |
649 | | |
650 | | // input too large to fit a 64-bits integer |
651 | | let data = &hex_literal::hex!("0d 71 82 0e 73 72 76 6e 67 6e 62 6c 6e 2d 65 78 30 31"); |
652 | | let r = bitstring_to_u64(0, &BitStringObject { data }); |
653 | | assert!(r.is_err()); |
654 | | |
655 | | // test large number but with many ignored bits |
656 | | let data = &hex_literal::hex!("0d 71 82 0e 73 72 76 6e 67 6e 62 6c 6e 2d 65 78 30 31"); |
657 | | let r = bitstring_to_u64(130, &BitStringObject { data }); |
658 | | // 2 = 130 % 8 |
659 | | assert_eq!(r, Ok(0x0d71 >> 2)); |
660 | | } |