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