• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 use crate::ber::*;
2 use crate::error::*;
3 use crate::oid::*;
4 use nom::bytes::streaming::take;
5 use nom::combinator::{complete, map, verify};
6 use nom::multi::{many0, many_till};
7 use nom::number::streaming::be_u8;
8 use nom::{Err, Needed, Offset};
9 use rusticata_macros::{combinator::parse_hex_to_u64, custom_check};
10 
11 /// Default maximum recursion limit
12 pub const MAX_RECURSION: usize = 50;
13 
14 /// Default maximum object size (2^32)
15 pub const MAX_OBJECT_SIZE: usize = 4_294_967_295;
16 
17 /// Skip object content, and return true if object was End-Of-Content
ber_skip_object_content<'a>( i: &'a [u8], hdr: &BerObjectHeader, max_depth: usize, ) -> BerResult<'a, bool>18 pub(crate) fn ber_skip_object_content<'a>(
19     i: &'a [u8],
20     hdr: &BerObjectHeader,
21     max_depth: usize,
22 ) -> BerResult<'a, bool> {
23     if max_depth == 0 {
24         return Err(Err::Error(BerError::BerMaxDepth));
25     }
26     match hdr.len {
27         BerSize::Definite(l) => {
28             if l == 0 && hdr.tag == BerTag::EndOfContent {
29                 return Ok((i, true));
30             }
31             let (i, _) = take(l)(i)?;
32             Ok((i, false))
33         }
34         BerSize::Indefinite => {
35             if hdr.is_primitive() {
36                 return Err(Err::Error(BerError::ConstructExpected));
37             }
38             // read objects until EndOfContent (00 00)
39             // this is recursive
40             let mut i = i;
41             loop {
42                 let (i2, header2) = ber_read_element_header(i)?;
43                 let (i3, eoc) = ber_skip_object_content(i2, &header2, max_depth - 1)?;
44                 if eoc {
45                     // return false, since top object was not EndOfContent
46                     return Ok((i3, false));
47                 }
48                 i = i3;
49             }
50         }
51     }
52 }
53 
54 /// Read object raw content (bytes)
ber_get_object_content<'a>( i: &'a [u8], hdr: &BerObjectHeader, max_depth: usize, ) -> BerResult<'a, &'a [u8]>55 pub(crate) fn ber_get_object_content<'a>(
56     i: &'a [u8],
57     hdr: &BerObjectHeader,
58     max_depth: usize,
59 ) -> BerResult<'a, &'a [u8]> {
60     let start_i = i;
61     let (i, _) = ber_skip_object_content(i, hdr, max_depth)?;
62     let len = start_i.offset(i);
63     let (content, i) = start_i.split_at(len);
64     // if len is indefinite, there are 2 extra bytes for EOC
65     if hdr.len == BerSize::Indefinite {
66         let len = content.len();
67         assert!(len >= 2);
68         Ok((i, &content[..len - 2]))
69     } else {
70         Ok((i, content))
71     }
72 }
73 
74 /// Try to parse input bytes as u64
75 #[inline]
bytes_to_u64(s: &[u8]) -> Result<u64, BerError>76 pub(crate) fn bytes_to_u64(s: &[u8]) -> Result<u64, BerError> {
77     let mut u: u64 = 0;
78     for &c in s {
79         if u & 0xff00_0000_0000_0000 != 0 {
80             return Err(BerError::IntegerTooLarge);
81         }
82         u <<= 8;
83         u |= u64::from(c);
84     }
85     Ok(u)
86 }
87 
88 /// Try to parse an input bit string as u64.
89 ///
90 /// Note: this is for the primitive BER/DER encoding only, the
91 /// constructed BER encoding for BIT STRING does not seem to be
92 /// supported at all by the library currently.
93 #[inline]
bitstring_to_u64( padding_bits: usize, data: &BitStringObject, ) -> Result<u64, BerError>94 pub(crate) fn bitstring_to_u64(
95     padding_bits: usize,
96     data: &BitStringObject,
97 ) -> Result<u64, BerError> {
98     let raw_bytes = data.data;
99     let bit_size = (raw_bytes.len() * 8)
100         .checked_sub(padding_bits)
101         .ok_or(BerError::InvalidLength)?;
102     if bit_size > 64 {
103         return Err(BerError::IntegerTooLarge);
104     }
105     let padding_bits = padding_bits % 8;
106     let num_bytes = if bit_size % 8 > 0 {
107         (bit_size / 8) + 1
108     } else {
109         bit_size / 8
110     };
111     let mut resulting_integer: u64 = 0;
112     for &c in &raw_bytes[..num_bytes] {
113         resulting_integer <<= 8;
114         resulting_integer |= c as u64;
115     }
116     Ok(resulting_integer >> padding_bits)
117 }
118 
parse_identifier(i: &[u8]) -> BerResult<(u8, u8, u32, &[u8])>119 pub(crate) fn parse_identifier(i: &[u8]) -> BerResult<(u8, u8, u32, &[u8])> {
120     if i.is_empty() {
121         Err(Err::Incomplete(Needed::new(1)))
122     } else {
123         let a = i[0] >> 6;
124         let b = if i[0] & 0b0010_0000 != 0 { 1 } else { 0 };
125         let mut c = u32::from(i[0] & 0b0001_1111);
126 
127         let mut tag_byte_count = 1;
128 
129         if c == 0x1f {
130             c = 0;
131             loop {
132                 // Make sure we don't read past the end of our data.
133                 custom_check!(i, tag_byte_count >= i.len(), BerError::InvalidTag)?;
134 
135                 // With tag defined as u32 the most we can fit in is four tag bytes.
136                 // (X.690 doesn't actually specify maximum tag width.)
137                 custom_check!(i, tag_byte_count > 5, BerError::InvalidTag)?;
138 
139                 c = (c << 7) | (u32::from(i[tag_byte_count]) & 0x7f);
140                 let done = i[tag_byte_count] & 0x80 == 0;
141                 tag_byte_count += 1;
142                 if done {
143                     break;
144                 }
145             }
146         }
147 
148         let (raw_tag, rem) = i.split_at(tag_byte_count);
149 
150         Ok((rem, (a, b, c, raw_tag)))
151     }
152 }
153 
154 /// Return the MSB and the rest of the first byte, or an error
parse_ber_length_byte(i: &[u8]) -> BerResult<(u8, u8)>155 pub(crate) fn parse_ber_length_byte(i: &[u8]) -> BerResult<(u8, u8)> {
156     if i.is_empty() {
157         Err(Err::Incomplete(Needed::new(1)))
158     } else {
159         let a = i[0] >> 7;
160         let b = i[0] & 0b0111_1111;
161         Ok((&i[1..], (a, b)))
162     }
163 }
164 
165 /// Read an object header
166 ///
167 /// ### Example
168 ///
169 /// ```
170 /// # use der_parser::ber::{ber_read_element_header, BerClass, BerSize, BerTag};
171 /// #
172 /// let bytes = &[0x02, 0x03, 0x01, 0x00, 0x01];
173 /// let (i, hdr) = ber_read_element_header(bytes).expect("could not read header");
174 ///
175 /// assert_eq!(hdr.class, BerClass::Universal);
176 /// assert_eq!(hdr.tag, BerTag::Integer);
177 /// assert_eq!(hdr.len, BerSize::Definite(3));
178 /// ```
ber_read_element_header(i: &[u8]) -> BerResult<BerObjectHeader>179 pub fn ber_read_element_header(i: &[u8]) -> BerResult<BerObjectHeader> {
180     let (i1, el) = parse_identifier(i)?;
181     let class = match BerClass::try_from(el.0) {
182         Ok(c) => c,
183         Err(_) => unreachable!(), // Cannot fail, we have read exactly 2 bits
184     };
185     let (i2, len) = parse_ber_length_byte(i1)?;
186     let (i3, len) = match (len.0, len.1) {
187         (0, l1) => {
188             // Short form: MSB is 0, the rest encodes the length (which can be 0) (8.1.3.4)
189             (i2, BerSize::Definite(usize::from(l1)))
190         }
191         (_, 0) => {
192             // Indefinite form: MSB is 1, the rest is 0 (8.1.3.6)
193             // If encoding is primitive, definite form shall be used (8.1.3.2)
194             if el.1 == 0 {
195                 return Err(Err::Error(BerError::ConstructExpected));
196             }
197             (i2, BerSize::Indefinite)
198         }
199         (_, l1) => {
200             // if len is 0xff -> error (8.1.3.5)
201             if l1 == 0b0111_1111 {
202                 return Err(::nom::Err::Error(BerError::InvalidTag));
203             }
204             let (i3, llen) = take(l1)(i2)?;
205             match bytes_to_u64(llen) {
206                 Ok(l) => {
207                     let l =
208                         usize::try_from(l).or(Err(::nom::Err::Error(BerError::InvalidLength)))?;
209                     (i3, BerSize::Definite(l))
210                 }
211                 Err(_) => {
212                     return Err(::nom::Err::Error(BerError::InvalidTag));
213                 }
214             }
215         }
216     };
217     let hdr = BerObjectHeader::new(class, el.1, BerTag(el.2), len).with_raw_tag(Some(el.3));
218     Ok((i3, hdr))
219 }
220 
221 #[allow(clippy::unnecessary_wraps)]
222 #[inline]
ber_read_content_eoc(i: &[u8]) -> BerResult<BerObjectContent>223 fn ber_read_content_eoc(i: &[u8]) -> BerResult<BerObjectContent> {
224     Ok((i, BerObjectContent::EndOfContent))
225 }
226 
227 #[inline]
ber_read_content_bool(i: &[u8]) -> BerResult<BerObjectContent>228 fn ber_read_content_bool(i: &[u8]) -> BerResult<BerObjectContent> {
229     match be_u8(i) {
230         Ok((rem, 0)) => Ok((rem, BerObjectContent::Boolean(false))),
231         Ok((rem, _)) => Ok((rem, BerObjectContent::Boolean(true))),
232         Err(e) => Err(e),
233     }
234 }
235 
236 #[inline]
ber_read_content_integer(i: &[u8], len: usize) -> BerResult<BerObjectContent>237 fn ber_read_content_integer(i: &[u8], len: usize) -> BerResult<BerObjectContent> {
238     map(take(len), BerObjectContent::Integer)(i)
239 }
240 
241 #[inline]
ber_read_content_bitstring(i: &[u8], len: usize) -> BerResult<BerObjectContent>242 fn ber_read_content_bitstring(i: &[u8], len: usize) -> BerResult<BerObjectContent> {
243     custom_check!(i, len == 0, BerError::InvalidLength)?;
244 
245     let (i, ignored_bits) = be_u8(i)?;
246     let (i, data) = take(len - 1)(i)?;
247     Ok((
248         i,
249         BerObjectContent::BitString(ignored_bits, BitStringObject { data }),
250     ))
251 }
252 
253 #[inline]
ber_read_content_octetstring(i: &[u8], len: usize) -> BerResult<BerObjectContent>254 fn ber_read_content_octetstring(i: &[u8], len: usize) -> BerResult<BerObjectContent> {
255     map(take(len), BerObjectContent::OctetString)(i)
256 }
257 
258 #[allow(clippy::unnecessary_wraps)]
259 #[inline]
ber_read_content_null(i: &[u8]) -> BerResult<BerObjectContent>260 fn ber_read_content_null(i: &[u8]) -> BerResult<BerObjectContent> {
261     Ok((i, BerObjectContent::Null))
262 }
263 
ber_read_content_oid(i: &[u8], len: usize) -> BerResult<BerObjectContent>264 fn ber_read_content_oid(i: &[u8], len: usize) -> BerResult<BerObjectContent> {
265     custom_check!(i, len == 0, BerError::InvalidLength)?;
266 
267     let (i1, oid) = verify(take(len), |os: &[u8]| os.last().unwrap() >> 7 == 0u8)(i)?;
268 
269     let obj = BerObjectContent::OID(Oid::new(Cow::Borrowed(oid)));
270     Ok((i1, obj))
271 }
272 
273 #[inline]
ber_read_content_enum(i: &[u8], len: usize) -> BerResult<BerObjectContent>274 fn ber_read_content_enum(i: &[u8], len: usize) -> BerResult<BerObjectContent> {
275     let (rem, num) = parse_hex_to_u64(i, len).map_err(|_| BerError::BerValueError)?;
276     Ok((rem, BerObjectContent::Enum(num)))
277 }
278 
ber_read_content_utf8string(i: &[u8], len: usize) -> BerResult<BerObjectContent>279 fn ber_read_content_utf8string(i: &[u8], len: usize) -> BerResult<BerObjectContent> {
280     let (i, bytes) = take(len)(i)?;
281     let s = core::str::from_utf8(bytes)
282         .map_err(|_| Err::Error(BerError::StringInvalidCharset))
283         .map(|s| BerObjectContent::UTF8String(s))?;
284     Ok((i, s))
285 }
286 
ber_read_content_relativeoid(i: &[u8], len: usize) -> BerResult<BerObjectContent>287 fn ber_read_content_relativeoid(i: &[u8], len: usize) -> BerResult<BerObjectContent> {
288     custom_check!(i, len == 0, BerError::InvalidLength)?;
289 
290     let (i1, oid) = verify(take(len), |os: &[u8]| os.last().unwrap() >> 7 == 0u8)(i)?;
291 
292     let obj = BerObjectContent::RelativeOID(Oid::new_relative(Cow::Borrowed(oid)));
293     Ok((i1, obj))
294 }
295 
ber_read_content_sequence( i: &[u8], len: BerSize, max_depth: usize, ) -> BerResult<BerObjectContent>296 fn ber_read_content_sequence(
297     i: &[u8],
298     len: BerSize,
299     max_depth: usize,
300 ) -> BerResult<BerObjectContent> {
301     custom_check!(i, max_depth == 0, BerError::BerMaxDepth)?;
302     match len {
303         BerSize::Definite(len) => {
304             let (i, data) = take(len)(i)?;
305             let (_, l) = many0(complete(r_parse_ber(max_depth - 1)))(data)?;
306             // trailing bytes are ignored
307             Ok((i, BerObjectContent::Sequence(l)))
308         }
309         BerSize::Indefinite => {
310             // indefinite form
311             // read until end-of-content
312             let (rem, (l, _)) = many_till(r_parse_ber(max_depth - 1), parse_ber_endofcontent)(i)?;
313             Ok((rem, BerObjectContent::Sequence(l)))
314         }
315     }
316 }
317 
ber_read_content_set(i: &[u8], len: BerSize, max_depth: usize) -> BerResult<BerObjectContent>318 fn ber_read_content_set(i: &[u8], len: BerSize, max_depth: usize) -> BerResult<BerObjectContent> {
319     custom_check!(i, max_depth == 0, BerError::BerMaxDepth)?;
320     match len {
321         BerSize::Definite(len) => {
322             let (i, data) = take(len)(i)?;
323             let (_, l) = many0(complete(r_parse_ber(max_depth - 1)))(data)?;
324             // trailing bytes are ignored
325             Ok((i, BerObjectContent::Set(l)))
326         }
327         BerSize::Indefinite => {
328             // indefinite form
329             // read until end-of-content
330             let (rem, (l, _)) = many_till(r_parse_ber(max_depth - 1), parse_ber_endofcontent)(i)?;
331             Ok((rem, BerObjectContent::Set(l)))
332         }
333     }
334 }
335 
ber_read_content_numericstring<'a>(i: &'a [u8], len: usize) -> BerResult<BerObjectContent<'a>>336 fn ber_read_content_numericstring<'a>(i: &'a [u8], len: usize) -> BerResult<BerObjectContent<'a>> {
337     // Argument must be a reference, because of the .iter().all(F) call below
338     #[allow(clippy::trivially_copy_pass_by_ref)]
339     fn is_numeric(b: &u8) -> bool {
340         matches!(*b, b'0'..=b'9' | b' ')
341     }
342     let (i, bytes) = take(len)(i)?;
343     if !bytes.iter().all(is_numeric) {
344         return Err(Err::Error(BerError::StringInvalidCharset));
345     }
346     let s = core::str::from_utf8(bytes)
347         .map_err(|_| Err::Error(BerError::StringInvalidCharset))
348         .map(|s| BerObjectContent::NumericString(s))?;
349     Ok((i, s))
350 }
351 
ber_read_content_visiblestring<'a>(i: &'a [u8], len: usize) -> BerResult<BerObjectContent<'a>>352 fn ber_read_content_visiblestring<'a>(i: &'a [u8], len: usize) -> BerResult<BerObjectContent<'a>> {
353     // Argument must be a reference, because of the .iter().all(F) call below
354     #[allow(clippy::trivially_copy_pass_by_ref)]
355     fn is_visible(b: &u8) -> bool {
356         0x20 <= *b && *b <= 0x7f
357     }
358     let (i, bytes) = take(len)(i)?;
359     if !bytes.iter().all(is_visible) {
360         return Err(Err::Error(BerError::StringInvalidCharset));
361     }
362     let s = core::str::from_utf8(bytes)
363         .map_err(|_| Err::Error(BerError::StringInvalidCharset))
364         .map(|s| BerObjectContent::VisibleString(s))?;
365     Ok((i, s))
366 }
367 
ber_read_content_printablestring<'a>( i: &'a [u8], len: usize, ) -> BerResult<BerObjectContent<'a>>368 fn ber_read_content_printablestring<'a>(
369     i: &'a [u8],
370     len: usize,
371 ) -> BerResult<BerObjectContent<'a>> {
372     // Argument must be a reference, because of the .iter().all(F) call below
373     #[allow(clippy::trivially_copy_pass_by_ref)]
374     fn is_printable(b: &u8) -> bool {
375         matches!(*b,
376             b'a'..=b'z'
377             | b'A'..=b'Z'
378             | b'0'..=b'9'
379             | b' '
380             | b'\''
381             | b'('
382             | b')'
383             | b'+'
384             | b','
385             | b'-'
386             | b'.'
387             | b'/'
388             | b':'
389             | b'='
390             | b'?')
391     }
392     let (i, bytes) = take(len)(i)?;
393     if !bytes.iter().all(is_printable) {
394         return Err(Err::Error(BerError::StringInvalidCharset));
395     }
396     let s = core::str::from_utf8(bytes)
397         .map_err(|_| Err::Error(BerError::StringInvalidCharset))
398         .map(|s| BerObjectContent::PrintableString(s))?;
399     Ok((i, s))
400 }
401 
402 #[inline]
ber_read_content_t61string(i: &[u8], len: usize) -> BerResult<BerObjectContent>403 fn ber_read_content_t61string(i: &[u8], len: usize) -> BerResult<BerObjectContent> {
404     map(take(len), BerObjectContent::T61String)(i)
405 }
406 
407 #[inline]
ber_read_content_videotexstring(i: &[u8], len: usize) -> BerResult<BerObjectContent>408 fn ber_read_content_videotexstring(i: &[u8], len: usize) -> BerResult<BerObjectContent> {
409     map(take(len), BerObjectContent::VideotexString)(i)
410 }
411 
ber_read_content_ia5string<'a>(i: &'a [u8], len: usize) -> BerResult<BerObjectContent<'a>>412 fn ber_read_content_ia5string<'a>(i: &'a [u8], len: usize) -> BerResult<BerObjectContent<'a>> {
413     let (i, bytes) = take(len)(i)?;
414     if !bytes.iter().all(u8::is_ascii) {
415         return Err(Err::Error(BerError::StringInvalidCharset));
416     }
417     let s = core::str::from_utf8(bytes)
418         .map_err(|_| Err::Error(BerError::StringInvalidCharset))
419         .map(|s| BerObjectContent::IA5String(s))?;
420     Ok((i, s))
421 }
422 
ber_read_content_utctime<'a>(i: &'a [u8], len: usize) -> BerResult<BerObjectContent<'a>>423 fn ber_read_content_utctime<'a>(i: &'a [u8], len: usize) -> BerResult<BerObjectContent<'a>> {
424     // Argument must be a reference, because of the .iter().all(F) call below
425     #[allow(clippy::trivially_copy_pass_by_ref)]
426     fn is_visible(b: &u8) -> bool {
427         0x20 <= *b && *b <= 0x7f
428     }
429     let (i, bytes) = take(len)(i)?;
430     if !bytes.iter().all(is_visible) {
431         return Err(Err::Error(BerError::StringInvalidCharset));
432     }
433     let s = core::str::from_utf8(bytes)
434         .map_err(|_| Err::Error(BerError::StringInvalidCharset))
435         .map(|s| BerObjectContent::UTCTime(s))?;
436     Ok((i, s))
437 }
438 
ber_read_content_generalizedtime<'a>( i: &'a [u8], len: usize, ) -> BerResult<BerObjectContent<'a>>439 fn ber_read_content_generalizedtime<'a>(
440     i: &'a [u8],
441     len: usize,
442 ) -> BerResult<BerObjectContent<'a>> {
443     // Argument must be a reference, because of the .iter().all(F) call below
444     #[allow(clippy::trivially_copy_pass_by_ref)]
445     fn is_visible(b: &u8) -> bool {
446         0x20 <= *b && *b <= 0x7f
447     }
448     let (i, bytes) = take(len)(i)?;
449     if !bytes.iter().all(is_visible) {
450         return Err(Err::Error(BerError::StringInvalidCharset));
451     }
452     let s = core::str::from_utf8(bytes)
453         .map_err(|_| Err::Error(BerError::StringInvalidCharset))
454         .map(|s| BerObjectContent::GeneralizedTime(s))?;
455     Ok((i, s))
456 }
457 
458 #[inline]
ber_read_content_objectdescriptor(i: &[u8], len: usize) -> BerResult<BerObjectContent>459 fn ber_read_content_objectdescriptor(i: &[u8], len: usize) -> BerResult<BerObjectContent> {
460     map(take(len), BerObjectContent::ObjectDescriptor)(i)
461 }
462 
463 #[inline]
ber_read_content_graphicstring(i: &[u8], len: usize) -> BerResult<BerObjectContent>464 fn ber_read_content_graphicstring(i: &[u8], len: usize) -> BerResult<BerObjectContent> {
465     map(take(len), BerObjectContent::GraphicString)(i)
466 }
467 
468 #[inline]
ber_read_content_generalstring(i: &[u8], len: usize) -> BerResult<BerObjectContent>469 fn ber_read_content_generalstring(i: &[u8], len: usize) -> BerResult<BerObjectContent> {
470     map(take(len), BerObjectContent::GeneralString)(i)
471 }
472 
473 #[inline]
ber_read_content_bmpstring(i: &[u8], len: usize) -> BerResult<BerObjectContent>474 fn ber_read_content_bmpstring(i: &[u8], len: usize) -> BerResult<BerObjectContent> {
475     map(take(len), BerObjectContent::BmpString)(i)
476 }
477 
478 #[inline]
ber_read_content_universalstring(i: &[u8], len: usize) -> BerResult<BerObjectContent>479 fn ber_read_content_universalstring(i: &[u8], len: usize) -> BerResult<BerObjectContent> {
480     map(take(len), BerObjectContent::UniversalString)(i)
481 }
482 
483 /// Parse the next bytes as the *content* of a BER object.
484 ///
485 /// Content type is *not* checked to match tag, caller is responsible of providing the correct tag
486 ///
487 /// This function is mostly used when parsing implicit tagged objects, when reading primitive
488 /// types.
489 ///
490 /// `max_depth` is the maximum allowed recursion for objects.
491 ///
492 /// ### Example
493 ///
494 /// ```
495 /// # use der_parser::ber::{ber_read_element_content_as, ber_read_element_header, BerTag};
496 /// #
497 /// # let bytes = &[0x02, 0x03, 0x01, 0x00, 0x01];
498 /// let (i, hdr) = ber_read_element_header(bytes).expect("could not read header");
499 /// let (_, content) = ber_read_element_content_as(
500 ///     i, hdr.tag, hdr.len, hdr.is_constructed(), 5
501 /// ).expect("parsing failed");
502 /// #
503 /// # assert_eq!(hdr.tag, BerTag::Integer);
504 /// # assert_eq!(content.as_u32(), Ok(0x10001));
505 /// ```
ber_read_element_content_as( i: &[u8], tag: BerTag, len: BerSize, constructed: bool, max_depth: usize, ) -> BerResult<BerObjectContent>506 pub fn ber_read_element_content_as(
507     i: &[u8],
508     tag: BerTag,
509     len: BerSize,
510     constructed: bool,
511     max_depth: usize,
512 ) -> BerResult<BerObjectContent> {
513     if let BerSize::Definite(l) = len {
514         custom_check!(i, l > MAX_OBJECT_SIZE, BerError::InvalidLength)?;
515         if i.len() < l {
516             return Err(Err::Incomplete(Needed::new(l)));
517         }
518     }
519     match tag {
520         // 0x00 end-of-content
521         BerTag::EndOfContent => {
522             custom_check!(i, len != BerSize::Definite(0), BerError::InvalidLength)?;
523             ber_read_content_eoc(i)
524         }
525         // 0x01 bool
526         BerTag::Boolean => {
527             let len = len.primitive()?;
528             custom_check!(i, len != 1, BerError::InvalidLength)?;
529             ber_read_content_bool(i)
530         }
531         // 0x02
532         BerTag::Integer => {
533             custom_check!(i, constructed, BerError::ConstructUnexpected)?;
534             let len = len.primitive()?;
535             ber_read_content_integer(i, len)
536         }
537         // 0x03: bitstring
538         BerTag::BitString => {
539             custom_check!(i, constructed, BerError::Unsupported)?; // XXX valid in BER (8.6.3)
540             let len = len.primitive()?;
541             ber_read_content_bitstring(i, len)
542         }
543         // 0x04: octetstring
544         BerTag::OctetString => {
545             custom_check!(i, constructed, BerError::Unsupported)?; // XXX valid in BER (8.7.1)
546             let len = len.primitive()?;
547             ber_read_content_octetstring(i, len)
548         }
549         // 0x05: null
550         BerTag::Null => {
551             custom_check!(i, constructed, BerError::ConstructUnexpected)?;
552             let len = len.primitive()?;
553             custom_check!(i, len != 0, BerError::InvalidLength)?;
554             ber_read_content_null(i)
555         }
556         // 0x06: object identifier
557         BerTag::Oid => {
558             custom_check!(i, constructed, BerError::ConstructUnexpected)?; // forbidden in 8.19.1
559             let len = len.primitive()?;
560             ber_read_content_oid(i, len)
561         }
562         // 0x07: object descriptor - Alias for GraphicString with a different
563         // implicit tag, see below
564         BerTag::ObjDescriptor => {
565             custom_check!(i, constructed, BerError::Unsupported)?; // XXX valid in BER (8.21)
566             let len = len.primitive()?;
567             ber_read_content_objectdescriptor(i, len)
568         }
569         // 0x0a: enumerated
570         BerTag::Enumerated => {
571             custom_check!(i, constructed, BerError::ConstructUnexpected)?; // forbidden in 8.4
572             let len = len.primitive()?;
573             ber_read_content_enum(i, len)
574         }
575         // 0x0c: UTF8String - Unicode encoded with the UTF-8 charset (ISO/IEC
576         // 10646-1, Annex D)
577         BerTag::Utf8String => {
578             custom_check!(i, constructed, BerError::Unsupported)?; // XXX valid in BER (8.21)
579             let len = len.primitive()?;
580             ber_read_content_utf8string(i, len)
581         }
582         // 0x0d: relative object identified
583         BerTag::RelativeOid => {
584             custom_check!(i, constructed, BerError::ConstructUnexpected)?;
585             let len = len.primitive()?;
586             ber_read_content_relativeoid(i, len)
587         }
588         // 0x10: sequence
589         BerTag::Sequence => {
590             custom_check!(i, !constructed, BerError::ConstructExpected)?;
591             ber_read_content_sequence(i, len, max_depth)
592         }
593         // 0x11: set
594         BerTag::Set => {
595             custom_check!(i, !constructed, BerError::ConstructExpected)?;
596             ber_read_content_set(i, len, max_depth)
597         }
598         // 0x12: numericstring - ASCII string with digits an spaces only
599         BerTag::NumericString => {
600             custom_check!(i, constructed, BerError::Unsupported)?; // XXX valid in BER (8.21)
601             let len = len.primitive()?;
602             ber_read_content_numericstring(i, len)
603         }
604         // 0x13: printablestring - ASCII string with certain printable
605         // characters only (specified in Table 10 of X.680)
606         BerTag::PrintableString => {
607             custom_check!(i, constructed, BerError::Unsupported)?; // XXX valid in BER (8.21)
608             let len = len.primitive()?;
609             ber_read_content_printablestring(i, len)
610         }
611         // 0x14: t61string - ISO 2022 string with a Teletex (T.61) charset,
612         // ASCII is possible but only when explicit escaped, as by default
613         // the G0 character range (0x20-0x7f) will match the graphic character
614         // set. https://en.wikipedia.org/wiki/ITU_T.61
615         BerTag::T61String => {
616             custom_check!(i, constructed, BerError::Unsupported)?; // XXX valid in BER (8.21)
617             let len = len.primitive()?;
618             ber_read_content_t61string(i, len)
619         }
620         // 0x15: videotexstring - ISO 2022 string with a Videotex (T.100/T.101)
621         // charset, excluding ASCII. https://en.wikipedia.org/wiki/Videotex_character_set
622         BerTag::VideotexString => {
623             custom_check!(i, constructed, BerError::Unsupported)?; // XXX valid in BER (8.21)
624             let len = len.primitive()?;
625             ber_read_content_videotexstring(i, len)
626         }
627         // 0x16: ia5string - ASCII string
628         BerTag::Ia5String => {
629             custom_check!(i, constructed, BerError::Unsupported)?; // XXX valid in BER (8.21)
630             let len = len.primitive()?;
631             ber_read_content_ia5string(i, len)
632         }
633         // 0x17: utctime - Alias for a VisibleString with a different implicit
634         // tag, see below
635         BerTag::UtcTime => {
636             let len = len.primitive()?;
637             ber_read_content_utctime(i, len)
638         }
639         // 0x18: generalizedtime - Alias for a VisibleString with a different
640         // implicit tag, see below
641         BerTag::GeneralizedTime => {
642             let len = len.primitive()?;
643             ber_read_content_generalizedtime(i, len)
644         }
645         // 0x19: graphicstring - Generic ISO 2022 container with explicit
646         // escape sequences, without control characters
647         BerTag::GraphicString => {
648             custom_check!(i, constructed, BerError::Unsupported)?; // XXX valid in BER (8.21)
649             let len = len.primitive()?;
650             ber_read_content_graphicstring(i, len)
651         }
652         // 0x1a: visiblestring - ASCII string with no control characters except
653         // SPACE
654         BerTag::VisibleString => {
655             custom_check!(i, constructed, BerError::Unsupported)?; // XXX valid in BER (8.21)
656             let len = len.primitive()?;
657             ber_read_content_visiblestring(i, len)
658         }
659         // 0x1b: generalstring - Generic ISO 2022 container with explicit
660         // escape sequences
661         BerTag::GeneralString => {
662             custom_check!(i, constructed, BerError::Unsupported)?; // XXX valid in BER (8.21)
663             let len = len.primitive()?;
664             ber_read_content_generalstring(i, len)
665         }
666         // 0x1e: bmpstring - Unicode encoded with the UCS-2 big-endian charset
667         // (ISO/IEC 10646-1, section 13.1), restricted to the BMP (Basic
668         // Multilingual Plane) except certain control cahracters
669         BerTag::BmpString => {
670             custom_check!(i, constructed, BerError::Unsupported)?; // XXX valid in BER (8.21)
671             let len = len.primitive()?;
672             ber_read_content_bmpstring(i, len)
673         }
674         // 0x1c: universalstring - Unicode encoded with the UCS-4 big-endian
675         // charset (ISO/IEC 10646-1, section 13.2)
676         BerTag::UniversalString => {
677             custom_check!(i, constructed, BerError::Unsupported)?; // XXX valid in BER (8.21)
678             let len = len.primitive()?;
679             ber_read_content_universalstring(i, len)
680         }
681         // all unknown values
682         _ => Err(Err::Error(BerError::UnknownTag)),
683     }
684 }
685 
686 /// Parse the next bytes as the content of a BER object (combinator, header reference)
687 ///
688 /// Content type is *not* checked to match tag, caller is responsible of providing the correct tag
689 ///
690 /// Caller is also responsible to check if parsing function consumed the expected number of
691 /// bytes (`header.len`).
692 ///
693 /// The arguments of the parse function are: `(input, ber_object_header, max_recursion)`.
694 ///
695 /// This function differs from [`parse_ber_content2`](fn.parse_ber_content2.html) because it passes
696 /// the BER object header by reference (required for ex. by `parse_ber_implicit`).
697 ///
698 /// Example: manually parsing header and content
699 ///
700 /// ```
701 /// # use der_parser::ber::*;
702 /// #
703 /// # let bytes = &[0x02, 0x03, 0x01, 0x00, 0x01];
704 /// let (i, header) = ber_read_element_header(bytes).expect("parsing failed");
705 /// let (rem, content) = parse_ber_content(header.tag)(i, &header, MAX_RECURSION)
706 ///     .expect("parsing failed");
707 /// #
708 /// # assert_eq!(header.tag, BerTag::Integer);
709 /// ```
parse_ber_content<'a>( tag: BerTag, ) -> impl Fn(&'a [u8], &'_ BerObjectHeader, usize) -> BerResult<'a, BerObjectContent<'a>>710 pub fn parse_ber_content<'a>(
711     tag: BerTag,
712 ) -> impl Fn(&'a [u8], &'_ BerObjectHeader, usize) -> BerResult<'a, BerObjectContent<'a>> {
713     move |i: &[u8], hdr: &BerObjectHeader, max_recursion: usize| {
714         ber_read_element_content_as(i, tag, hdr.len, hdr.is_constructed(), max_recursion)
715     }
716 }
717 
718 /// Parse the next bytes as the content of a BER object (combinator, owned header)
719 ///
720 /// Content type is *not* checked to match tag, caller is responsible of providing the correct tag
721 ///
722 /// Caller is also responsible to check if parsing function consumed the expected number of
723 /// bytes (`header.len`).
724 ///
725 /// The arguments of the parse function are: `(input, ber_object_header, max_recursion)`.
726 ///
727 /// This function differs from [`parse_ber_content`](fn.parse_ber_content.html) because it passes
728 /// an owned BER object header (required for ex. by `parse_ber_tagged_implicit_g`).
729 ///
730 /// Example: manually parsing header and content
731 ///
732 /// ```
733 /// # use der_parser::ber::*;
734 /// #
735 /// # let bytes = &[0x02, 0x03, 0x01, 0x00, 0x01];
736 /// let (i, header) = ber_read_element_header(bytes).expect("parsing failed");
737 /// let (rem, content) = parse_ber_content(header.tag)(i, &header, MAX_RECURSION)
738 ///     .expect("parsing failed");
739 /// #
740 /// # assert_eq!(header.tag, BerTag::Integer);
741 /// ```
parse_ber_content2<'a>( tag: BerTag, ) -> impl Fn(&'a [u8], BerObjectHeader<'a>, usize) -> BerResult<'a, BerObjectContent<'a>>742 pub fn parse_ber_content2<'a>(
743     tag: BerTag,
744 ) -> impl Fn(&'a [u8], BerObjectHeader<'a>, usize) -> BerResult<'a, BerObjectContent<'a>> {
745     move |i: &[u8], hdr: BerObjectHeader, max_recursion: usize| {
746         ber_read_element_content_as(i, tag, hdr.len, hdr.is_constructed(), max_recursion)
747     }
748 }
749 
750 /// Parse a BER object, expecting a value with specified tag
751 ///
752 /// The object is parsed recursively, with a maximum depth of `MAX_RECURSION`.
753 ///
754 /// ### Example
755 ///
756 /// ```
757 /// use der_parser::ber::BerTag;
758 /// use der_parser::ber::parse_ber_with_tag;
759 ///
760 /// let bytes = &[0x02, 0x03, 0x01, 0x00, 0x01];
761 /// let (_, obj) = parse_ber_with_tag(bytes, BerTag::Integer).expect("parsing failed");
762 ///
763 /// assert_eq!(obj.header.tag, BerTag::Integer);
764 /// ```
parse_ber_with_tag<Tag: Into<BerTag>>(i: &[u8], tag: Tag) -> BerResult765 pub fn parse_ber_with_tag<Tag: Into<BerTag>>(i: &[u8], tag: Tag) -> BerResult {
766     let tag = tag.into();
767     let (i, hdr) = ber_read_element_header(i)?;
768     if hdr.tag != tag {
769         return Err(nom::Err::Error(BerError::InvalidTag));
770     }
771     let (i, content) =
772         ber_read_element_content_as(i, hdr.tag, hdr.len, hdr.is_constructed(), MAX_RECURSION)?;
773     Ok((i, BerObject::from_header_and_content(hdr, content)))
774 }
775 
776 /// Read end of content marker
777 #[inline]
parse_ber_endofcontent(i: &[u8]) -> BerResult778 pub fn parse_ber_endofcontent(i: &[u8]) -> BerResult {
779     parse_ber_with_tag(i, BerTag::EndOfContent)
780 }
781 
782 /// Read a boolean value
783 ///
784 /// The encoding of a boolean value shall be primitive. The contents octets shall consist of a
785 /// single octet.
786 ///
787 /// If the boolean value is FALSE, the octet shall be zero.
788 /// If the boolean value is TRUE, the octet shall be one byte, and have all bits set to one (0xff).
789 #[inline]
parse_ber_bool(i: &[u8]) -> BerResult790 pub fn parse_ber_bool(i: &[u8]) -> BerResult {
791     parse_ber_with_tag(i, BerTag::Boolean)
792 }
793 
794 /// Read an integer value
795 ///
796 /// The encoding of a boolean value shall be primitive. The contents octets shall consist of one or
797 /// more octets.
798 ///
799 /// To access the content, use the [`as_u64`](struct.BerObject.html#method.as_u64),
800 /// [`as_u32`](struct.BerObject.html#method.as_u32),
801 /// [`as_biguint`](struct.BerObject.html#method.as_biguint) or
802 /// [`as_bigint`](struct.BerObject.html#method.as_bigint) methods.
803 /// Remember that a BER integer has unlimited size, so these methods return `Result` or `Option`
804 /// objects.
805 ///
806 /// # Examples
807 ///
808 /// ```rust
809 /// # extern crate nom;
810 /// # use der_parser::ber::parse_ber_integer;
811 /// # use der_parser::ber::{BerObject,BerObjectContent};
812 /// let empty = &b""[..];
813 /// let bytes = [0x02, 0x03, 0x01, 0x00, 0x01];
814 /// let expected  = BerObject::from_obj(BerObjectContent::Integer(b"\x01\x00\x01"));
815 /// assert_eq!(
816 ///     parse_ber_integer(&bytes),
817 ///     Ok((empty, expected))
818 /// );
819 /// ```
820 #[inline]
parse_ber_integer(i: &[u8]) -> BerResult821 pub fn parse_ber_integer(i: &[u8]) -> BerResult {
822     parse_ber_with_tag(i, BerTag::Integer)
823 }
824 
825 /// Read an bitstring value
826 #[inline]
parse_ber_bitstring(i: &[u8]) -> BerResult827 pub fn parse_ber_bitstring(i: &[u8]) -> BerResult {
828     parse_ber_with_tag(i, BerTag::BitString)
829 }
830 
831 /// Read an octetstring value
832 #[inline]
parse_ber_octetstring(i: &[u8]) -> BerResult833 pub fn parse_ber_octetstring(i: &[u8]) -> BerResult {
834     parse_ber_with_tag(i, BerTag::OctetString)
835 }
836 
837 /// Read a null value
838 #[inline]
parse_ber_null(i: &[u8]) -> BerResult839 pub fn parse_ber_null(i: &[u8]) -> BerResult {
840     parse_ber_with_tag(i, BerTag::Null)
841 }
842 
843 /// Read an object identifier value
844 #[inline]
parse_ber_oid(i: &[u8]) -> BerResult845 pub fn parse_ber_oid(i: &[u8]) -> BerResult {
846     parse_ber_with_tag(i, BerTag::Oid)
847 }
848 
849 /// Read an enumerated value
850 #[inline]
parse_ber_enum(i: &[u8]) -> BerResult851 pub fn parse_ber_enum(i: &[u8]) -> BerResult {
852     parse_ber_with_tag(i, BerTag::Enumerated)
853 }
854 
855 /// Read a UTF-8 string value. The encoding is checked.
856 #[inline]
parse_ber_utf8string(i: &[u8]) -> BerResult857 pub fn parse_ber_utf8string(i: &[u8]) -> BerResult {
858     parse_ber_with_tag(i, BerTag::Utf8String)
859 }
860 
861 /// Read a relative object identifier value
862 #[inline]
parse_ber_relative_oid(i: &[u8]) -> BerResult863 pub fn parse_ber_relative_oid(i: &[u8]) -> BerResult {
864     parse_ber_with_tag(i, BerTag::RelativeOid)
865 }
866 
867 /// Parse a sequence of BER elements
868 ///
869 /// Read a sequence of BER objects, without any constraint on the types.
870 /// Sequence is parsed recursively, so if structured elements are found, they are parsed using the
871 /// same function.
872 ///
873 /// To read a specific sequence of objects (giving the expected types), use the
874 /// [`parse_ber_sequence_defined`](macro.parse_ber_sequence_defined.html) macro.
875 #[inline]
parse_ber_sequence(i: &[u8]) -> BerResult876 pub fn parse_ber_sequence(i: &[u8]) -> BerResult {
877     parse_ber_with_tag(i, BerTag::Sequence)
878 }
879 
880 /// Parse a set of BER elements
881 ///
882 /// Read a set of BER objects, without any constraint on the types.
883 /// Set is parsed recursively, so if structured elements are found, they are parsed using the
884 /// same function.
885 ///
886 /// To read a specific set of objects (giving the expected types), use the
887 /// [`parse_ber_set_defined`](macro.parse_ber_set_defined.html) macro.
888 #[inline]
parse_ber_set(i: &[u8]) -> BerResult889 pub fn parse_ber_set(i: &[u8]) -> BerResult {
890     parse_ber_with_tag(i, BerTag::Set)
891 }
892 
893 /// Read a numeric string value. The content is verified to
894 /// contain only digits and spaces.
895 #[inline]
parse_ber_numericstring(i: &[u8]) -> BerResult896 pub fn parse_ber_numericstring(i: &[u8]) -> BerResult {
897     parse_ber_with_tag(i, BerTag::NumericString)
898 }
899 
900 /// Read a visible string value. The content is verified to
901 /// contain only the allowed characters.
902 #[inline]
parse_ber_visiblestring(i: &[u8]) -> BerResult903 pub fn parse_ber_visiblestring(i: &[u8]) -> BerResult {
904     parse_ber_with_tag(i, BerTag::VisibleString)
905 }
906 
907 /// Read a printable string value. The content is verified to
908 /// contain only the allowed characters.
909 #[inline]
parse_ber_printablestring(i: &[u8]) -> BerResult910 pub fn parse_ber_printablestring(i: &[u8]) -> BerResult {
911     parse_ber_with_tag(i, BerTag::PrintableString)
912 }
913 
914 /// Read a T61 string value
915 #[inline]
parse_ber_t61string(i: &[u8]) -> BerResult916 pub fn parse_ber_t61string(i: &[u8]) -> BerResult {
917     parse_ber_with_tag(i, BerTag::T61String)
918 }
919 
920 /// Read a Videotex string value
921 #[inline]
parse_ber_videotexstring(i: &[u8]) -> BerResult922 pub fn parse_ber_videotexstring(i: &[u8]) -> BerResult {
923     parse_ber_with_tag(i, BerTag::VideotexString)
924 }
925 
926 /// Read an IA5 string value. The content is verified to be ASCII.
927 #[inline]
parse_ber_ia5string(i: &[u8]) -> BerResult928 pub fn parse_ber_ia5string(i: &[u8]) -> BerResult {
929     parse_ber_with_tag(i, BerTag::Ia5String)
930 }
931 
932 /// Read an UTC time value
933 #[inline]
parse_ber_utctime(i: &[u8]) -> BerResult934 pub fn parse_ber_utctime(i: &[u8]) -> BerResult {
935     parse_ber_with_tag(i, BerTag::UtcTime)
936 }
937 
938 /// Read a Generalized time value
939 #[inline]
parse_ber_generalizedtime(i: &[u8]) -> BerResult940 pub fn parse_ber_generalizedtime(i: &[u8]) -> BerResult {
941     parse_ber_with_tag(i, BerTag::GeneralizedTime)
942 }
943 
944 /// Read an ObjectDescriptor value
945 #[inline]
parse_ber_objectdescriptor(i: &[u8]) -> BerResult946 pub fn parse_ber_objectdescriptor(i: &[u8]) -> BerResult {
947     parse_ber_with_tag(i, BerTag::ObjDescriptor)
948 }
949 
950 /// Read a GraphicString value
951 #[inline]
parse_ber_graphicstring(i: &[u8]) -> BerResult952 pub fn parse_ber_graphicstring(i: &[u8]) -> BerResult {
953     parse_ber_with_tag(i, BerTag::GraphicString)
954 }
955 
956 /// Read a GeneralString value
957 #[inline]
parse_ber_generalstring(i: &[u8]) -> BerResult958 pub fn parse_ber_generalstring(i: &[u8]) -> BerResult {
959     parse_ber_with_tag(i, BerTag::GeneralString)
960 }
961 
962 /// Read a BmpString value
963 #[inline]
parse_ber_bmpstring(i: &[u8]) -> BerResult964 pub fn parse_ber_bmpstring(i: &[u8]) -> BerResult {
965     parse_ber_with_tag(i, BerTag::BmpString)
966 }
967 
968 /// Read a UniversalString value
969 #[inline]
parse_ber_universalstring(i: &[u8]) -> BerResult970 pub fn parse_ber_universalstring(i: &[u8]) -> BerResult {
971     parse_ber_with_tag(i, BerTag::UniversalString)
972 }
973 
974 /// Parse an optional tagged object, applying function to get content
975 ///
976 /// This function returns a `BerObject`, trying to read content as generic BER objects.
977 /// If parsing failed, return an optional object containing `None`.
978 ///
979 /// To support other return or error types, use
980 /// [parse_ber_tagged_explicit_g](fn.parse_ber_tagged_explicit_g.html)
981 ///
982 /// This function will never fail: if parsing content failed, the BER value `Optional(None)` is
983 /// returned.
parse_ber_explicit_optional<F>(i: &[u8], tag: BerTag, f: F) -> BerResult where F: Fn(&[u8]) -> BerResult,984 pub fn parse_ber_explicit_optional<F>(i: &[u8], tag: BerTag, f: F) -> BerResult
985 where
986     F: Fn(&[u8]) -> BerResult,
987 {
988     parse_ber_optional(parse_ber_tagged_explicit_g(tag, |content, hdr| {
989         let (rem, obj) = f(content)?;
990         let content = BerObjectContent::Tagged(hdr.class, hdr.tag, Box::new(obj));
991         let tagged = BerObject::from_header_and_content(hdr, content);
992         Ok((rem, tagged))
993     }))(i)
994 }
995 
996 /// Parse an implicit tagged object, applying function to read content
997 ///
998 /// Note: unlike explicit tagged functions, the callback must be a *content* parsing function,
999 /// often based on the [`parse_ber_content`](fn.parse_ber_content.html) combinator.
1000 ///
1001 /// The built object will use the original header (and tag), so the content may not match the tag
1002 /// value.
1003 ///
1004 /// For a combinator version, see [parse_ber_tagged_implicit](fn.parse_ber_tagged_implicit.html).
1005 ///
1006 /// For a generic version (different output and error types), see
1007 /// [parse_ber_tagged_implicit_g](fn.parse_ber_tagged_implicit_g.html).
1008 ///
1009 /// # Examples
1010 ///
1011 /// The following parses `[3] IMPLICIT INTEGER` into a `BerObject`:
1012 ///
1013 /// ```rust
1014 /// # use der_parser::ber::*;
1015 /// # use der_parser::error::BerResult;
1016 /// #
1017 /// fn parse_int_implicit(i:&[u8]) -> BerResult<BerObject> {
1018 ///     parse_ber_implicit(
1019 ///         i,
1020 ///         3,
1021 ///         parse_ber_content(BerTag::Integer),
1022 ///     )
1023 /// }
1024 ///
1025 /// # let bytes = &[0x83, 0x03, 0x01, 0x00, 0x01];
1026 /// let res = parse_int_implicit(bytes);
1027 /// # match res {
1028 /// #     Ok((rem, content)) => {
1029 /// #         assert!(rem.is_empty());
1030 /// #         assert_eq!(content.as_u32(), Ok(0x10001));
1031 /// #     },
1032 /// #     _ => assert!(false)
1033 /// # }
1034 /// ```
1035 #[inline]
parse_ber_implicit<'a, Tag, F>(i: &'a [u8], tag: Tag, f: F) -> BerResult<'a> where F: Fn(&'a [u8], &'_ BerObjectHeader, usize) -> BerResult<'a, BerObjectContent<'a>>, Tag: Into<BerTag>,1036 pub fn parse_ber_implicit<'a, Tag, F>(i: &'a [u8], tag: Tag, f: F) -> BerResult<'a>
1037 where
1038     F: Fn(&'a [u8], &'_ BerObjectHeader, usize) -> BerResult<'a, BerObjectContent<'a>>,
1039     Tag: Into<BerTag>,
1040 {
1041     parse_ber_tagged_implicit(tag, f)(i)
1042 }
1043 
1044 /// Combinator for building optional BER values
1045 ///
1046 /// To read optional BER values, it is to use the nom `opt()` combinator. However, this results in
1047 /// a `Option<BerObject>` and prevents using some functions from this crate (the generic functions
1048 /// can still be used).
1049 ///
1050 /// This combinator is used when parsing BER values, while keeping `BerObject` output only.
1051 ///
1052 /// This function will never fail: if parsing content failed, the BER value `Optional(None)` is
1053 /// returned.
1054 ///
1055 /// ### Example
1056 ///
1057 /// ```
1058 /// # use der_parser::ber::*;
1059 /// #
1060 /// let bytes = &[0x02, 0x03, 0x01, 0x00, 0x01];
1061 /// let mut parser = parse_ber_optional(parse_ber_integer);
1062 /// let (_, obj) = parser(bytes).expect("parsing failed");
1063 ///
1064 /// assert_eq!(obj.header.tag, BerTag::Integer);
1065 /// assert!(obj.as_optional().is_ok());
1066 /// ```
parse_ber_optional<'a, F>(mut f: F) -> impl FnMut(&'a [u8]) -> BerResult<'a> where F: FnMut(&'a [u8]) -> BerResult<'a>,1067 pub fn parse_ber_optional<'a, F>(mut f: F) -> impl FnMut(&'a [u8]) -> BerResult<'a>
1068 where
1069     F: FnMut(&'a [u8]) -> BerResult<'a>,
1070 {
1071     move |i: &[u8]| {
1072         let res = f(i);
1073         match res {
1074             Ok((rem, inner)) => {
1075                 let opt = BerObject::from_header_and_content(
1076                     inner.header.clone(),
1077                     BerObjectContent::Optional(Some(Box::new(inner))),
1078                 );
1079                 Ok((rem, opt))
1080             }
1081             Err(_) => Ok((i, BerObject::from_obj(BerObjectContent::Optional(None)))),
1082         }
1083     }
1084 }
1085 
1086 /// Parse BER object and try to decode it as a 32-bits signed integer
1087 ///
1088 /// Return `IntegerTooLarge` if object is an integer, but can not be represented in the target
1089 /// integer type.
1090 #[inline]
parse_ber_i32(i: &[u8]) -> BerResult<i32>1091 pub fn parse_ber_i32(i: &[u8]) -> BerResult<i32> {
1092     let (rem, ber) = parse_ber_integer(i)?;
1093     let int = ber.as_i32().map_err(nom::Err::Error)?;
1094     Ok((rem, int))
1095 }
1096 
1097 /// Parse BER object and try to decode it as a 64-bits signed integer
1098 ///
1099 /// Return `IntegerTooLarge` if object is an integer, but can not be represented in the target
1100 /// integer type.
1101 #[inline]
parse_ber_i64(i: &[u8]) -> BerResult<i64>1102 pub fn parse_ber_i64(i: &[u8]) -> BerResult<i64> {
1103     let (rem, ber) = parse_ber_integer(i)?;
1104     let int = ber.as_i64().map_err(nom::Err::Error)?;
1105     Ok((rem, int))
1106 }
1107 
1108 /// Parse BER object and try to decode it as a 32-bits unsigned integer
1109 ///
1110 /// Return `IntegerTooLarge` if object is an integer, but can not be represented in the target
1111 /// integer type.
1112 #[inline]
parse_ber_u32(i: &[u8]) -> BerResult<u32>1113 pub fn parse_ber_u32(i: &[u8]) -> BerResult<u32> {
1114     let (rem, ber) = parse_ber_integer(i)?;
1115     let int = ber.as_u32().map_err(nom::Err::Error)?;
1116     Ok((rem, int))
1117 }
1118 
1119 /// Parse BER object and try to decode it as a 64-bits unsigned integer
1120 ///
1121 /// Return `IntegerTooLarge` if object is an integer, but can not be represented in the target
1122 /// integer type.
1123 #[inline]
parse_ber_u64(i: &[u8]) -> BerResult<u64>1124 pub fn parse_ber_u64(i: &[u8]) -> BerResult<u64> {
1125     let (rem, ber) = parse_ber_integer(i)?;
1126     let int = ber.as_u64().map_err(nom::Err::Error)?;
1127     Ok((rem, int))
1128 }
1129 
1130 /// Parse BER object and get content as slice
1131 #[inline]
parse_ber_slice<Tag: Into<BerTag>>(i: &[u8], tag: Tag) -> BerResult<&[u8]>1132 pub fn parse_ber_slice<Tag: Into<BerTag>>(i: &[u8], tag: Tag) -> BerResult<&[u8]> {
1133     let tag = tag.into();
1134     parse_ber_container(move |content, hdr| {
1135         if hdr.tag != tag {
1136             return Err(Err::Error(BerError::InvalidTag));
1137         }
1138         Ok((&b""[..], content))
1139     })(i)
1140 }
1141 
1142 /// Helper combinator, to create a parser with a maximum parsing depth
1143 #[inline]
r_parse_ber(max_depth: usize) -> impl Fn(&[u8]) -> BerResult1144 pub(crate) fn r_parse_ber(max_depth: usize) -> impl Fn(&[u8]) -> BerResult {
1145     move |i: &[u8]| parse_ber_recursive(i, max_depth)
1146 }
1147 
1148 /// Parse BER object recursively, specifying the maximum recursion depth
1149 ///
1150 /// Return a tuple containing the remaining (unparsed) bytes and the BER Object, or an error.
1151 ///
1152 /// ### Example
1153 ///
1154 /// ```
1155 /// use der_parser::ber::{parse_ber_recursive, BerTag};
1156 ///
1157 /// let bytes = &[0x02, 0x03, 0x01, 0x00, 0x01];
1158 /// let (_, obj) = parse_ber_recursive(bytes, 1).expect("parsing failed");
1159 ///
1160 /// assert_eq!(obj.header.tag, BerTag::Integer);
1161 /// ```
parse_ber_recursive(i: &[u8], max_depth: usize) -> BerResult1162 pub fn parse_ber_recursive(i: &[u8], max_depth: usize) -> BerResult {
1163     custom_check!(i, max_depth == 0, BerError::BerMaxDepth)?;
1164     let (rem, hdr) = ber_read_element_header(i)?;
1165     if let BerSize::Definite(l) = hdr.len {
1166         custom_check!(i, l > MAX_OBJECT_SIZE, BerError::InvalidLength)?;
1167     }
1168     match hdr.class {
1169         BerClass::Universal => (),
1170         BerClass::Private => {
1171             let (rem, content) = ber_get_object_content(rem, &hdr, max_depth)?;
1172             let content = BerObjectContent::Private(hdr.clone(), content);
1173             let obj = BerObject::from_header_and_content(hdr, content);
1174             return Ok((rem, obj));
1175         }
1176         _ => {
1177             let (rem, content) = ber_get_object_content(rem, &hdr, max_depth)?;
1178             let content = BerObjectContent::Unknown(hdr.class, hdr.tag, content);
1179             let obj = BerObject::from_header_and_content(hdr, content);
1180             return Ok((rem, obj));
1181         }
1182     }
1183     match ber_read_element_content_as(rem, hdr.tag, hdr.len, hdr.is_constructed(), max_depth) {
1184         Ok((rem, content)) => Ok((rem, BerObject::from_header_and_content(hdr, content))),
1185         Err(Err::Error(BerError::UnknownTag)) => {
1186             let (rem, content) = ber_get_object_content(rem, &hdr, max_depth)?;
1187             let content = BerObjectContent::Unknown(hdr.class, hdr.tag, content);
1188             let obj = BerObject::from_header_and_content(hdr, content);
1189             Ok((rem, obj))
1190         }
1191         Err(e) => Err(e),
1192     }
1193 }
1194 
1195 /// Parse BER object recursively
1196 ///
1197 /// Return a tuple containing the remaining (unparsed) bytes and the BER Object, or an error.
1198 ///
1199 /// *Note*: this is the same as calling `parse_ber_recursive` with `MAX_RECURSION`.
1200 ///
1201 /// ### Example
1202 ///
1203 /// ```
1204 /// use der_parser::ber::{parse_ber, BerTag};
1205 ///
1206 /// let bytes = &[0x02, 0x03, 0x01, 0x00, 0x01];
1207 /// let (_, obj) = parse_ber(bytes).expect("parsing failed");
1208 ///
1209 /// assert_eq!(obj.header.tag, BerTag::Integer);
1210 /// ```
1211 #[inline]
parse_ber(i: &[u8]) -> BerResult1212 pub fn parse_ber(i: &[u8]) -> BerResult {
1213     parse_ber_recursive(i, MAX_RECURSION)
1214 }
1215 
1216 #[test]
test_numericstring()1217 fn test_numericstring() {
1218     assert_eq!(
1219         ber_read_content_numericstring(b" 0123  4495768 ", 15),
1220         Ok((
1221             [].as_ref(),
1222             BerObjectContent::NumericString(" 0123  4495768 ")
1223         )),
1224     );
1225     assert_eq!(
1226         ber_read_content_numericstring(b"", 0),
1227         Ok(([].as_ref(), BerObjectContent::NumericString(""))),
1228     );
1229     assert!(ber_read_content_numericstring(b"123a", 4).is_err());
1230 }
1231 
1232 #[test]
text_visiblestring()1233 fn text_visiblestring() {
1234     assert_eq!(
1235         ber_read_content_visiblestring(b"AZaz]09 '()+,-./:=?", 19),
1236         Ok((
1237             [].as_ref(),
1238             BerObjectContent::VisibleString("AZaz]09 '()+,-./:=?")
1239         )),
1240     );
1241     assert_eq!(
1242         ber_read_content_visiblestring(b"", 0),
1243         Ok(([].as_ref(), BerObjectContent::VisibleString(""))),
1244     );
1245     assert!(ber_read_content_visiblestring(b"\n", 1).is_err());
1246 }
1247 
1248 #[test]
test_printablestring()1249 fn test_printablestring() {
1250     assert_eq!(
1251         ber_read_content_printablestring(b"AZaz09 '()+,-./:=?", 18),
1252         Ok((
1253             [].as_ref(),
1254             BerObjectContent::PrintableString("AZaz09 '()+,-./:=?")
1255         )),
1256     );
1257     assert_eq!(
1258         ber_read_content_printablestring(b"", 0),
1259         Ok(([].as_ref(), BerObjectContent::PrintableString(""))),
1260     );
1261     assert!(ber_read_content_printablestring(b"]\n", 2).is_err());
1262 }
1263 
1264 #[test]
test_ia5string()1265 fn test_ia5string() {
1266     assert_eq!(
1267         ber_read_content_ia5string(b"AZaz\n09 '()+,-./:=?[]{}\0\n", 25),
1268         Ok((
1269             [].as_ref(),
1270             BerObjectContent::IA5String("AZaz\n09 '()+,-./:=?[]{}\0\n")
1271         )),
1272     );
1273     assert_eq!(
1274         ber_read_content_ia5string(b"", 0),
1275         Ok(([].as_ref(), BerObjectContent::IA5String(""))),
1276     );
1277     assert!(ber_read_content_ia5string(b"\xFF", 1).is_err());
1278 }
1279 
1280 #[test]
test_utf8string()1281 fn test_utf8string() {
1282     assert_eq!(
1283         ber_read_content_utf8string("AZaz09 '()+,-./:=?[]{}\0\nüÜ".as_ref(), 28),
1284         Ok((
1285             [].as_ref(),
1286             BerObjectContent::UTF8String("AZaz09 '()+,-./:=?[]{}\0\nüÜ")
1287         )),
1288     );
1289     assert_eq!(
1290         ber_read_content_utf8string(b"", 0),
1291         Ok(([].as_ref(), BerObjectContent::UTF8String(""))),
1292     );
1293     assert!(ber_read_content_utf8string(b"\xe2\x28\xa1", 3).is_err());
1294 }
1295 
1296 #[test]
test_bitstring_to_u64()1297 fn test_bitstring_to_u64() {
1298     // ignored bits modulo 8 to 0
1299     let data = &hex_literal::hex!("0d 71 82");
1300     let r = bitstring_to_u64(8, &BitStringObject { data });
1301     assert_eq!(r, Ok(0x0d71));
1302 
1303     // input too large to fit a 64-bits integer
1304     let data = &hex_literal::hex!("0d 71 82 0e 73 72 76 6e 67 6e 62 6c 6e 2d 65 78 30 31");
1305     let r = bitstring_to_u64(0, &BitStringObject { data });
1306     assert!(r.is_err());
1307 
1308     // test large number but with many ignored bits
1309     let data = &hex_literal::hex!("0d 71 82 0e 73 72 76 6e 67 6e 62 6c 6e 2d 65 78 30 31");
1310     let r = bitstring_to_u64(130, &BitStringObject { data });
1311     // 2 = 130 % 8
1312     assert_eq!(r, Ok(0x0d71 >> 2));
1313 }
1314