Coverage Report

Created: 2025-11-16 07:09

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