Coverage Report

Created: 2026-06-07 07:05

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