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