1 use crate::ber::*;
2 use crate::error::*;
3 use crate::oid::*;
4 use nom::bytes::streaming::take;
5 use nom::combinator::{map, map_res};
6 use nom::error::ErrorKind;
7 use nom::number::streaming::be_u8;
8 use nom::{Err, Needed};
9 
10 /// Maximum recursion limit
11 pub const MAX_RECURSION: usize = 50;
12 
13 /// Try to parse input bytes as u64
14 #[inline]
bytes_to_u64(s: &[u8]) -> Result<u64, BerError>15 pub(crate) fn bytes_to_u64(s: &[u8]) -> Result<u64, BerError> {
16     let mut u: u64 = 0;
17     for &c in s {
18         if u & 0xff00_0000_0000_0000 != 0 {
19             return Err(BerError::IntegerTooLarge);
20         }
21         u <<= 8;
22         u |= u64::from(c);
23     }
24     Ok(u)
25 }
26 
parse_identifier(i: &[u8]) -> BerResult<(u8, u8, u32)>27 pub(crate) fn parse_identifier(i: &[u8]) -> BerResult<(u8, u8, u32)> {
28     if i.is_empty() {
29         Err(Err::Incomplete(Needed::Size(1)))
30     } else {
31         let a = i[0] >> 6;
32         let b = if i[0] & 0b0010_0000 != 0 { 1 } else { 0 };
33         let mut c = u32::from(i[0] & 0b0001_1111);
34 
35         let mut tag_byte_count = 1;
36 
37         if c == 0x1f {
38             c = 0;
39             loop {
40                 // Make sure we don't read past the end of our data.
41                 custom_check!(i, tag_byte_count >= i.len(), BerError::InvalidTag)?;
42 
43                 // With tag defined as u32 the most we can fit in is four tag bytes.
44                 // (X.690 doesn't actually specify maximum tag width.)
45                 custom_check!(i, tag_byte_count > 5, BerError::InvalidTag)?;
46 
47                 c = (c << 7) | (u32::from(i[tag_byte_count]) & 0x7f);
48                 let done = i[tag_byte_count] & 0x80 == 0;
49                 tag_byte_count += 1;
50                 if done {
51                     break;
52                 }
53             }
54         }
55 
56         Ok((&i[tag_byte_count..], (a, b, c)))
57     }
58 }
59 
parse_ber_length_byte(i: &[u8]) -> BerResult<(u8, u8)>60 pub(crate) fn parse_ber_length_byte(i: &[u8]) -> BerResult<(u8, u8)> {
61     if i.is_empty() {
62         Err(Err::Incomplete(Needed::Size(1)))
63     } else {
64         let a = i[0] >> 7;
65         let b = i[0] & 0b0111_1111;
66         Ok((&i[1..], (a, b)))
67     }
68 }
69 
ber_read_relative_oid(i: &[u8]) -> Result<Vec<u64>, u64>70 fn ber_read_relative_oid(i: &[u8]) -> Result<Vec<u64>, u64> {
71     let mut oid = Vec::new();
72     let mut acc: u64;
73 
74     if i.is_empty() {
75         return Ok(oid);
76     };
77 
78     acc = 0;
79     for &c in &i[0..] {
80         acc = (acc << 7) | u64::from(c & 0b0111_1111);
81         if (c & (1 << 7)) == 0 {
82             oid.push(acc);
83             acc = 0;
84         }
85     }
86 
87     match acc {
88         0 => Ok(oid),
89         _ => Err(acc),
90     }
91 }
92 
ber_read_oid(i: &[u8]) -> Result<Vec<u64>, u64>93 fn ber_read_oid(i: &[u8]) -> Result<Vec<u64>, u64> {
94     let mut oid = Vec::new();
95     let mut index = 0;
96 
97     if i.is_empty() {
98         return Err(0);
99     };
100 
101     /* first element = X*40 + Y (See 8.19.4) */
102     let acc = u64::from(i[0]);
103     if acc < 128 {
104         oid.push(acc / 40);
105         oid.push(acc % 40);
106         index = 1;
107     }
108 
109     let rel_oid = ber_read_relative_oid(&i[index..])?;
110     oid.extend(&rel_oid);
111     Ok(oid)
112 }
113 
114 /// Read an object header
ber_read_element_header(i: &[u8]) -> BerResult<BerObjectHeader>115 pub fn ber_read_element_header(i: &[u8]) -> BerResult<BerObjectHeader> {
116     do_parse! {
117         i,
118         el:   parse_identifier >>
119         len:  parse_ber_length_byte >>
120         llen: cond!(len.0 == 1, take!(len.1)) >>
121         ( {
122             let len : u64 = match len.0 {
123                 0 => u64::from(len.1),
124                 _ => {
125                     // if len is 0xff -> error (8.1.3.5)
126                     if len.1 == 0b0111_1111 {
127                         return Err(::nom::Err::Error(BerError::InvalidTag));
128                     }
129                     // XXX llen: test if 0 (indefinite form), if len is 0xff -> error
130                     match bytes_to_u64(llen.unwrap()) {
131                         Ok(l)  => l,
132                         Err(_) => { return Err(::nom::Err::Error(BerError::InvalidTag)); },
133                     }
134                 },
135             };
136             BerObjectHeader {
137                 class: el.0,
138                 structured: el.1,
139                 tag: BerTag(el.2),
140                 len,
141             }
142         } )
143     }
144 }
145 
146 #[inline]
ber_read_content_eoc(i: &[u8]) -> BerResult<BerObjectContent>147 pub(crate) fn ber_read_content_eoc(i: &[u8]) -> BerResult<BerObjectContent> {
148     Ok((i, BerObjectContent::EndOfContent))
149 }
150 
151 #[inline]
ber_read_content_bool(i: &[u8]) -> BerResult<BerObjectContent>152 pub(crate) fn ber_read_content_bool(i: &[u8]) -> BerResult<BerObjectContent> {
153     match be_u8(i) {
154         Ok((rem, 0)) => Ok((rem, BerObjectContent::Boolean(false))),
155         Ok((rem, _)) => Ok((rem, BerObjectContent::Boolean(true))),
156         Err(e) => Err(e),
157     }
158 }
159 
160 #[inline]
ber_read_content_integer(i: &[u8], len: usize) -> BerResult<BerObjectContent>161 pub(crate) fn ber_read_content_integer(i: &[u8], len: usize) -> BerResult<BerObjectContent> {
162     map(take(len), BerObjectContent::Integer)(i)
163 }
164 
165 // XXX check if constructed (8.6.3)
166 #[inline]
ber_read_content_bitstring(i: &[u8], len: usize) -> BerResult<BerObjectContent>167 pub(crate) fn ber_read_content_bitstring(i: &[u8], len: usize) -> BerResult<BerObjectContent> {
168     do_parse! {
169         i,
170         ignored_bits: be_u8 >>
171                       custom_check!(len == 0, BerError::InvalidLength) >>
172         s:            take!(len - 1) >>
173         ( BerObjectContent::BitString(ignored_bits,BitStringObject{ data:s }) )
174     }
175 }
176 
177 // XXX check if constructed (8.7)
178 #[inline]
ber_read_content_octetstring(i: &[u8], len: usize) -> BerResult<BerObjectContent>179 pub(crate) fn ber_read_content_octetstring(i: &[u8], len: usize) -> BerResult<BerObjectContent> {
180     map(take(len), BerObjectContent::OctetString)(i)
181 }
182 
183 #[inline]
ber_read_content_null(i: &[u8]) -> BerResult<BerObjectContent>184 pub(crate) fn ber_read_content_null(i: &[u8]) -> BerResult<BerObjectContent> {
185     Ok((i, BerObjectContent::Null))
186 }
187 
188 // XXX check if primitive (8.19.1)
189 #[inline]
ber_read_content_oid(i: &[u8], len: usize) -> BerResult<BerObjectContent>190 pub(crate) fn ber_read_content_oid(i: &[u8], len: usize) -> BerResult<BerObjectContent> {
191     do_parse! {
192         i,
193              error_if!(len == 0, ErrorKind::LengthValue) >>
194         oid: map_res!(take!(len),ber_read_oid) >>
195         ( BerObjectContent::OID(Oid::from(&oid)) )
196     }
197 }
198 
199 // XXX check if primitive (8.4)
200 #[inline]
ber_read_content_enum(i: &[u8], len: usize) -> BerResult<BerObjectContent>201 pub(crate) fn ber_read_content_enum(i: &[u8], len: usize) -> BerResult<BerObjectContent> {
202     parse_hex_to_u64!(i, len).map(|(rem, i)| (rem, BerObjectContent::Enum(i)))
203 }
204 
205 // XXX check if constructed, or indefinite length (8.21)
206 #[inline]
ber_read_content_utf8string(i: &[u8], len: usize) -> BerResult<BerObjectContent>207 pub(crate) fn ber_read_content_utf8string(i: &[u8], len: usize) -> BerResult<BerObjectContent> {
208     map!(i, take!(len), |s| BerObjectContent::UTF8String(s))
209 }
210 
211 #[inline]
ber_read_content_relativeoid(i: &[u8], len: usize) -> BerResult<BerObjectContent>212 pub(crate) fn ber_read_content_relativeoid(i: &[u8], len: usize) -> BerResult<BerObjectContent> {
213     do_parse! {
214         i,
215              custom_check!(len == 0, BerError::InvalidLength) >>
216         oid: map_res!(take!(len), ber_read_relative_oid) >>
217         ( BerObjectContent::RelativeOID(Oid::from(&oid)) )
218     }
219 }
220 
221 #[inline]
ber_read_content_sequence( i: &[u8], len: usize, depth: usize, ) -> BerResult<BerObjectContent>222 pub(crate) fn ber_read_content_sequence(
223     i: &[u8],
224     len: usize,
225     depth: usize,
226 ) -> BerResult<BerObjectContent> {
227     if len == 0 {
228         // indefinite form
229         // read until end-of-content
230         map!(
231             i,
232             many_till!(
233                 call!(parse_ber_recursive, depth + 1),
234                 parse_ber_endofcontent
235             ),
236             |(l, _)| { BerObjectContent::Sequence(l) }
237         )
238     } else {
239         map!(
240             i,
241             flat_take!(
242                 len,
243                 many0!(complete!(call!(parse_ber_recursive, depth + 1)))
244             ),
245             |l| { BerObjectContent::Sequence(l) }
246         )
247     }
248 }
249 
250 #[inline]
ber_read_content_set( i: &[u8], len: usize, depth: usize, ) -> BerResult<BerObjectContent>251 pub(crate) fn ber_read_content_set(
252     i: &[u8],
253     len: usize,
254     depth: usize,
255 ) -> BerResult<BerObjectContent> {
256     if len == 0 {
257         // indefinite form
258         // read until end-of-content
259         map!(
260             i,
261             many_till!(
262                 call!(parse_ber_recursive, depth + 1),
263                 parse_ber_endofcontent
264             ),
265             |(l, _)| { BerObjectContent::Set(l) }
266         )
267     } else {
268         map!(
269             i,
270             flat_take!(
271                 len,
272                 many0!(complete!(call!(parse_ber_recursive, depth + 1)))
273             ),
274             |l| { BerObjectContent::Set(l) }
275         )
276     }
277 }
278 
279 // XXX check if constructed, or indefinite length (8.21)
280 #[inline]
ber_read_content_numericstring(i: &[u8], len: usize) -> BerResult<BerObjectContent>281 pub(crate) fn ber_read_content_numericstring(i: &[u8], len: usize) -> BerResult<BerObjectContent> {
282     map!(i, take!(len), |s| BerObjectContent::NumericString(s))
283 }
284 
285 // XXX check if constructed, or indefinite length (8.21)
286 #[inline]
ber_read_content_printablestring( i: &[u8], len: usize, ) -> BerResult<BerObjectContent>287 pub(crate) fn ber_read_content_printablestring(
288     i: &[u8],
289     len: usize,
290 ) -> BerResult<BerObjectContent> {
291     map!(i, take!(len), |s| BerObjectContent::PrintableString(s))
292 }
293 
294 // XXX check if constructed, or indefinite length (8.21)
295 #[inline]
ber_read_content_t61string(i: &[u8], len: usize) -> BerResult<BerObjectContent>296 pub(crate) fn ber_read_content_t61string(i: &[u8], len: usize) -> BerResult<BerObjectContent> {
297     map(take(len), BerObjectContent::T61String)(i)
298 }
299 
300 // XXX check if constructed, or indefinite length (8.21)
301 #[inline]
ber_read_content_ia5string(i: &[u8], len: usize) -> BerResult<BerObjectContent>302 pub(crate) fn ber_read_content_ia5string(i: &[u8], len: usize) -> BerResult<BerObjectContent> {
303     map!(i, take!(len), |s| BerObjectContent::IA5String(s))
304 }
305 
306 #[inline]
ber_read_content_utctime(i: &[u8], len: usize) -> BerResult<BerObjectContent>307 pub(crate) fn ber_read_content_utctime(i: &[u8], len: usize) -> BerResult<BerObjectContent> {
308     map(take(len), BerObjectContent::UTCTime)(i)
309 }
310 
311 #[inline]
ber_read_content_generalizedtime( i: &[u8], len: usize, ) -> BerResult<BerObjectContent>312 pub(crate) fn ber_read_content_generalizedtime(
313     i: &[u8],
314     len: usize,
315 ) -> BerResult<BerObjectContent> {
316     map(take(len), BerObjectContent::GeneralizedTime)(i)
317 }
318 
319 // XXX check if constructed, or indefinite length (8.21)
320 #[inline]
ber_read_content_generalstring(i: &[u8], len: usize) -> BerResult<BerObjectContent>321 pub(crate) fn ber_read_content_generalstring(i: &[u8], len: usize) -> BerResult<BerObjectContent> {
322     map(take(len), BerObjectContent::GeneralString)(i)
323 }
324 
325 // XXX check if constructed, or indefinite length (8.21)
326 #[inline]
ber_read_content_bmpstring(i: &[u8], len: usize) -> BerResult<BerObjectContent>327 pub(crate) fn ber_read_content_bmpstring(i: &[u8], len: usize) -> BerResult<BerObjectContent> {
328     map(take(len), BerObjectContent::BmpString)(i)
329 }
330 
331 /// Parse the next bytes as the content of a BER object.
332 ///
333 /// Content type is *not* checked, caller is reponsible of providing the correct tag
ber_read_element_content_as( i: &[u8], tag: BerTag, len: usize, constructed: bool, depth: usize, ) -> BerResult<BerObjectContent>334 pub fn ber_read_element_content_as(
335     i: &[u8],
336     tag: BerTag,
337     len: usize,
338     constructed: bool,
339     depth: usize,
340 ) -> BerResult<BerObjectContent> {
341     if i.len() < len {
342         return Err(Err::Incomplete(Needed::Size(len)));
343     }
344     match tag {
345         // 0x00 end-of-content
346         BerTag::EndOfContent => {
347             custom_check!(i, len != 0, BerError::InvalidLength)?;
348             ber_read_content_eoc(i)
349         }
350         // 0x01 bool
351         BerTag::Boolean => {
352             custom_check!(i, len != 1, BerError::InvalidLength)?;
353             ber_read_content_bool(i)
354         }
355         // 0x02
356         BerTag::Integer => {
357             custom_check!(i, constructed, BerError::ConstructUnexpected)?;
358             ber_read_content_integer(i, len)
359         }
360         // 0x03: bitstring
361         BerTag::BitString => {
362             custom_check!(i, constructed, BerError::Unsupported)?; // XXX valid in BER
363             ber_read_content_bitstring(i, len)
364         }
365         // 0x04: octetstring
366         BerTag::OctetString => {
367             custom_check!(i, constructed, BerError::Unsupported)?; // XXX valid in BER
368             ber_read_content_octetstring(i, len)
369         }
370         // 0x05: null
371         BerTag::Null => {
372             custom_check!(i, constructed, BerError::ConstructUnexpected)?;
373             custom_check!(i, len != 0, BerError::InvalidLength)?;
374             ber_read_content_null(i)
375         }
376         // 0x06: object identified
377         BerTag::Oid => {
378             custom_check!(i, constructed, BerError::ConstructUnexpected)?;
379             ber_read_content_oid(i, len)
380         }
381         // 0x0a: enumerated
382         BerTag::Enumerated => {
383             custom_check!(i, constructed, BerError::ConstructUnexpected)?;
384             ber_read_content_enum(i, len)
385         }
386         // 0x0c: UTF8String
387         BerTag::Utf8String => {
388             custom_check!(i, constructed, BerError::Unsupported)?; // XXX valid in BER
389             ber_read_content_utf8string(i, len)
390         }
391         // 0x0d: relative object identified
392         BerTag::RelativeOid => {
393             custom_check!(i, constructed, BerError::ConstructUnexpected)?;
394             ber_read_content_relativeoid(i, len)
395         }
396         // 0x10: sequence
397         BerTag::Sequence => {
398             custom_check!(i, !constructed, BerError::ConstructExpected)?;
399             ber_read_content_sequence(i, len, depth)
400         }
401         // 0x11: set
402         BerTag::Set => {
403             custom_check!(i, !constructed, BerError::ConstructExpected)?;
404             ber_read_content_set(i, len, depth)
405         }
406         // 0x12: numericstring
407         BerTag::NumericString => {
408             custom_check!(i, constructed, BerError::Unsupported)?; // XXX valid in BER
409             ber_read_content_numericstring(i, len)
410         }
411         // 0x13: printablestring
412         BerTag::PrintableString => {
413             custom_check!(i, constructed, BerError::Unsupported)?; // XXX valid in BER
414             ber_read_content_printablestring(i, len)
415         }
416         // 0x14: t61string
417         BerTag::T61String => {
418             custom_check!(i, constructed, BerError::Unsupported)?; // XXX valid in BER
419             ber_read_content_t61string(i, len)
420         }
421         // 0x16: ia5string
422         BerTag::Ia5String => {
423             custom_check!(i, constructed, BerError::Unsupported)?; // XXX valid in BER
424             ber_read_content_ia5string(i, len)
425         }
426         // 0x17: utctime
427         BerTag::UtcTime => ber_read_content_utctime(i, len),
428         // 0x18: generalizedtime
429         BerTag::GeneralizedTime => ber_read_content_generalizedtime(i, len),
430         // 0x1b: generalstring
431         BerTag::GeneralString => {
432             custom_check!(i, constructed, BerError::Unsupported)?; // XXX valid in BER
433             ber_read_content_generalstring(i, len)
434         }
435         // 0x1e: bmpstring
436         BerTag::BmpString => {
437             custom_check!(i, constructed, BerError::Unsupported)?; // XXX valid in BER
438             ber_read_content_bmpstring(i, len)
439         }
440         // all unknown values
441         _ => Err(Err::Error(BerError::UnknownTag)),
442     }
443 }
444 //
445 /// Parse a BER object, expecting a value with specificed tag
parse_ber_with_tag(i: &[u8], tag: BerTag) -> BerResult446 pub fn parse_ber_with_tag(i: &[u8], tag: BerTag) -> BerResult {
447     do_parse! {
448         i,
449         hdr: ber_read_element_header >>
450              custom_check!(hdr.tag != tag, BerError::InvalidTag) >>
451         o:   call!(ber_read_element_content_as, hdr.tag, hdr.len as usize, hdr.is_constructed(), 0) >>
452         ( BerObject::from_header_and_content(hdr, o) )
453     }
454 }
455 
456 /// Read end of content marker
457 #[inline]
parse_ber_endofcontent(i: &[u8]) -> BerResult458 pub fn parse_ber_endofcontent(i: &[u8]) -> BerResult {
459     parse_ber_with_tag(i, BerTag::EndOfContent)
460 }
461 
462 /// Read a boolean value
463 ///
464 /// The encoding of a boolean value shall be primitive. The contents octets shall consist of a
465 /// single octet.
466 ///
467 /// If the boolean value is FALSE, the octet shall be zero.
468 /// If the boolean value is TRUE, the octet shall be one byte, and have all bits set to one (0xff).
469 #[inline]
parse_ber_bool(i: &[u8]) -> BerResult470 pub fn parse_ber_bool(i: &[u8]) -> BerResult {
471     parse_ber_with_tag(i, BerTag::Boolean)
472 }
473 
474 /// Read an integer value
475 ///
476 /// The encoding of a boolean value shall be primitive. The contents octets shall consist of one or
477 /// more octets.
478 ///
479 /// To access the content, use the [`as_u64`](struct.BerObject.html#method.as_u64),
480 /// [`as_u32`](struct.BerObject.html#method.as_u32),
481 /// [`as_biguint`](struct.BerObject.html#method.as_biguint) or
482 /// [`as_bigint`](struct.BerObject.html#method.as_bigint) methods.
483 /// Remember that a BER integer has unlimited size, so these methods return `Result` or `Option`
484 /// objects.
485 ///
486 /// # Examples
487 ///
488 /// ```rust
489 /// # #[macro_use] extern crate der_parser;
490 /// # extern crate nom;
491 /// # use der_parser::ber::parse_ber_integer;
492 /// # use der_parser::ber::{BerObject,BerObjectContent};
493 /// let empty = &b""[..];
494 /// let bytes = [0x02, 0x03, 0x01, 0x00, 0x01];
495 /// let expected  = BerObject::from_obj(BerObjectContent::Integer(b"\x01\x00\x01"));
496 /// assert_eq!(
497 ///     parse_ber_integer(&bytes),
498 ///     Ok((empty, expected))
499 /// );
500 /// ```
501 #[inline]
parse_ber_integer(i: &[u8]) -> BerResult502 pub fn parse_ber_integer(i: &[u8]) -> BerResult {
503     parse_ber_with_tag(i, BerTag::Integer)
504 }
505 
506 /// Read an bitstring value
507 #[inline]
parse_ber_bitstring(i: &[u8]) -> BerResult508 pub fn parse_ber_bitstring(i: &[u8]) -> BerResult {
509     parse_ber_with_tag(i, BerTag::BitString)
510 }
511 
512 /// Read an octetstring value
513 #[inline]
parse_ber_octetstring(i: &[u8]) -> BerResult514 pub fn parse_ber_octetstring(i: &[u8]) -> BerResult {
515     parse_ber_with_tag(i, BerTag::OctetString)
516 }
517 
518 /// Read a null value
519 #[inline]
parse_ber_null(i: &[u8]) -> BerResult520 pub fn parse_ber_null(i: &[u8]) -> BerResult {
521     parse_ber_with_tag(i, BerTag::Null)
522 }
523 
524 /// Read an object identifier value
525 #[inline]
parse_ber_oid(i: &[u8]) -> BerResult526 pub fn parse_ber_oid(i: &[u8]) -> BerResult {
527     parse_ber_with_tag(i, BerTag::Oid)
528 }
529 
530 /// Read an enumerated value
531 #[inline]
parse_ber_enum(i: &[u8]) -> BerResult532 pub fn parse_ber_enum(i: &[u8]) -> BerResult {
533     parse_ber_with_tag(i, BerTag::Enumerated)
534 }
535 
536 /// Read a UTF-8 string value
537 #[inline]
parse_ber_utf8string(i: &[u8]) -> BerResult538 pub fn parse_ber_utf8string(i: &[u8]) -> BerResult {
539     parse_ber_with_tag(i, BerTag::Utf8String)
540 }
541 
542 /// Read a relative object identifier value
543 #[inline]
parse_ber_relative_oid(i: &[u8]) -> BerResult544 pub fn parse_ber_relative_oid(i: &[u8]) -> BerResult {
545     parse_ber_with_tag(i, BerTag::RelativeOid)
546 }
547 
548 /// Parse a sequence of BER elements
549 ///
550 /// Read a sequence of BER objects, without any constraint on the types.
551 /// Sequence is parsed recursively, so if structured elements are found, they are parsed using the
552 /// same function.
553 ///
554 /// To read a specific sequence of objects (giving the expected types), use the
555 /// [`parse_ber_sequence_defined`](macro.parse_ber_sequence_defined.html) macro.
556 #[inline]
parse_ber_sequence(i: &[u8]) -> BerResult557 pub fn parse_ber_sequence(i: &[u8]) -> BerResult {
558     parse_ber_with_tag(i, BerTag::Sequence)
559 }
560 
561 /// Parse a set of BER elements
562 ///
563 /// Read a set of BER objects, without any constraint on the types.
564 /// Set is parsed recursively, so if structured elements are found, they are parsed using the
565 /// same function.
566 ///
567 /// To read a specific set of objects (giving the expected types), use the
568 /// [`parse_ber_set_defined`](macro.parse_ber_set_defined.html) macro.
569 #[inline]
parse_ber_set(i: &[u8]) -> BerResult570 pub fn parse_ber_set(i: &[u8]) -> BerResult {
571     parse_ber_with_tag(i, BerTag::Set)
572 }
573 
574 /// Read a numeric string value
575 #[inline]
parse_ber_numericstring(i: &[u8]) -> BerResult576 pub fn parse_ber_numericstring(i: &[u8]) -> BerResult {
577     parse_ber_with_tag(i, BerTag::NumericString)
578 }
579 
580 /// Read a printable string value
581 #[inline]
parse_ber_printablestring(i: &[u8]) -> BerResult582 pub fn parse_ber_printablestring(i: &[u8]) -> BerResult {
583     parse_ber_with_tag(i, BerTag::PrintableString)
584 }
585 
586 /// Read a T61 string value
587 #[inline]
parse_ber_t61string(i: &[u8]) -> BerResult588 pub fn parse_ber_t61string(i: &[u8]) -> BerResult {
589     parse_ber_with_tag(i, BerTag::T61String)
590 }
591 
592 /// Read an IA5 string value
593 #[inline]
parse_ber_ia5string(i: &[u8]) -> BerResult594 pub fn parse_ber_ia5string(i: &[u8]) -> BerResult {
595     parse_ber_with_tag(i, BerTag::Ia5String)
596 }
597 
598 /// Read an UTC time value
599 #[inline]
parse_ber_utctime(i: &[u8]) -> BerResult600 pub fn parse_ber_utctime(i: &[u8]) -> BerResult {
601     parse_ber_with_tag(i, BerTag::UtcTime)
602 }
603 
604 /// Read a Generalized time value
605 #[inline]
parse_ber_generalizedtime(i: &[u8]) -> BerResult606 pub fn parse_ber_generalizedtime(i: &[u8]) -> BerResult {
607     parse_ber_with_tag(i, BerTag::GeneralizedTime)
608 }
609 
610 /// Read a GeneralString value
611 #[inline]
parse_ber_generalstring(i: &[u8]) -> BerResult612 pub fn parse_ber_generalstring(i: &[u8]) -> BerResult {
613     parse_ber_with_tag(i, BerTag::GeneralString)
614 }
615 
616 /// Read a BmpString value
617 #[inline]
parse_ber_bmpstring(i: &[u8]) -> BerResult618 pub fn parse_ber_bmpstring(i: &[u8]) -> BerResult {
619     parse_ber_with_tag(i, BerTag::BmpString)
620 }
621 
parse_ber_explicit_failed(i: &[u8], tag: BerTag) -> BerResult622 pub fn parse_ber_explicit_failed(i: &[u8], tag: BerTag) -> BerResult {
623     Ok((
624         i,
625         BerObject::from_obj(BerObjectContent::ContextSpecific(tag, None)),
626     ))
627 }
628 
parse_ber_explicit<F>(i: &[u8], tag: BerTag, f: F) -> BerResult where F: Fn(&[u8]) -> BerResult,629 pub fn parse_ber_explicit<F>(i: &[u8], tag: BerTag, f: F) -> BerResult
630 where
631     F: Fn(&[u8]) -> BerResult,
632 {
633     alt! {
634         i,
635         complete!(do_parse!(
636             hdr:     ber_read_element_header >>
637                      custom_check!(hdr.tag != tag, BerError::InvalidTag) >>
638             content: f >>
639             (
640                 BerObject::from_header_and_content(
641                     hdr,
642                     BerObjectContent::ContextSpecific(tag,Some(Box::new(content)))
643                 )
644             )
645         )) |
646         complete!(call!(parse_ber_explicit_failed, tag))
647     }
648 }
649 
650 /// call der *content* parsing function
parse_ber_implicit<F>(i: &[u8], tag: BerTag, f: F) -> BerResult where F: Fn(&[u8], BerTag, usize) -> BerResult<BerObjectContent>,651 pub fn parse_ber_implicit<F>(i: &[u8], tag: BerTag, f: F) -> BerResult
652 where
653     F: Fn(&[u8], BerTag, usize) -> BerResult<BerObjectContent>,
654 {
655     alt! {
656         i,
657         complete!(do_parse!(
658             hdr:     ber_read_element_header >>
659                      custom_check!(hdr.tag != tag, BerError::InvalidTag) >>
660             content: call!(f, tag, hdr.len as usize) >>
661             (
662                 BerObject::from_header_and_content(
663                     hdr,
664                     BerObjectContent::ContextSpecific(tag,Some(Box::new(BerObject::from_obj(content))))
665                 )
666             )
667         )) |
668         complete!(call!(parse_ber_explicit_failed, tag))
669     }
670 }
671 
672 /// Parse BER object and try to decode it as a 32-bits unsigned integer
673 #[inline]
parse_ber_u32(i: &[u8]) -> BerResult<u32>674 pub fn parse_ber_u32(i: &[u8]) -> BerResult<u32> {
675     map_res(parse_ber_integer, |o| o.as_u32())(i)
676 }
677 
678 /// Parse BER object and try to decode it as a 64-bits unsigned integer
679 #[inline]
parse_ber_u64(i: &[u8]) -> BerResult<u64>680 pub fn parse_ber_u64(i: &[u8]) -> BerResult<u64> {
681     map_res(parse_ber_integer, |o| o.as_u64())(i)
682 }
683 
parse_ber_recursive(i: &[u8], depth: usize) -> BerResult684 fn parse_ber_recursive(i: &[u8], depth: usize) -> BerResult {
685     custom_check!(i, depth > MAX_RECURSION, BerError::BerMaxDepth)?;
686     let (rem, hdr) = ber_read_element_header(i)?;
687     custom_check!(
688         i,
689         hdr.len as usize > i.len() || hdr.len > u64::from(::std::u32::MAX),
690         BerError::InvalidLength
691     )?;
692     match hdr.class {
693         // universal
694         0b00 |
695         // private
696         0b11 => (),
697         // application
698         0b01 |
699         // context-specific
700         0b10 => return map!(
701             rem,
702             take!(hdr.len),
703             |b| { BerObject::from_header_and_content(hdr,BerObjectContent::Unknown(hdr.tag, b)) }
704         ),
705         _    => { return Err(Err::Error(BerError::InvalidClass)); },
706     }
707     match ber_read_element_content_as(rem, hdr.tag, hdr.len as usize, hdr.is_constructed(), depth) {
708         Ok((rem, content)) => Ok((rem, BerObject::from_header_and_content(hdr, content))),
709         Err(Err::Error(BerError::UnknownTag)) => map!(rem, take!(hdr.len), |b| {
710             BerObject::from_header_and_content(hdr, BerObjectContent::Unknown(hdr.tag, b))
711         }),
712         Err(e) => Err(e),
713     }
714 }
715 
716 /// Parse BER object
717 #[inline]
parse_ber(i: &[u8]) -> BerResult718 pub fn parse_ber(i: &[u8]) -> BerResult {
719     parse_ber_recursive(i, 0)
720 }
721