Coverage Report

Created: 2026-04-14 06:46

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