Coverage Report

Created: 2026-06-30 07:20

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/rust/registry/src/index.crates.io-1949cf8c6b5b557f/asn1-rs-0.6.2/src/ber/parser.rs
Line
Count
Source
1
use crate::error::*;
2
use crate::header::*;
3
use crate::{BerParser, DerParser, FromBer, Length, Tag};
4
use nom::bytes::streaming::take;
5
use nom::{Err, Needed, Offset};
6
use rusticata_macros::custom_check;
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
pub trait GetObjectContent {
15
    /// Return the raw content (bytes) of the next ASN.1 encoded object
16
    ///
17
    /// Note: if using BER and length is indefinite, terminating End-Of-Content is NOT included
18
    fn get_object_content<'a>(
19
        i: &'a [u8],
20
        hdr: &'_ Header,
21
        max_depth: usize,
22
    ) -> ParseResult<'a, &'a [u8]>;
23
}
24
25
impl GetObjectContent for BerParser {
26
8.03M
    fn get_object_content<'a>(
27
8.03M
        i: &'a [u8],
28
8.03M
        hdr: &'_ Header,
29
8.03M
        max_depth: usize,
30
8.03M
    ) -> ParseResult<'a, &'a [u8]> {
31
8.03M
        let start_i = i;
32
8.03M
        let (i, _) = ber_skip_object_content(i, hdr, max_depth)?;
33
8.00M
        let len = start_i.offset(i);
34
8.00M
        let (content, i) = start_i.split_at(len);
35
        // if len is indefinite, there are 2 extra bytes for EOC
36
8.00M
        if hdr.length == Length::Indefinite {
37
58.5k
            let len = content.len();
38
58.5k
            assert!(len >= 2);
39
58.5k
            Ok((i, &content[..len - 2]))
40
        } else {
41
7.94M
            Ok((i, content))
42
        }
43
8.03M
    }
44
}
45
46
impl GetObjectContent for DerParser {
47
    /// Skip object content, accepting only DER
48
    ///
49
    /// This this function is for DER only, it cannot go into recursion (no indefinite length)
50
1.45M
    fn get_object_content<'a>(
51
1.45M
        i: &'a [u8],
52
1.45M
        hdr: &'_ Header,
53
1.45M
        _max_depth: usize,
54
1.45M
    ) -> ParseResult<'a, &'a [u8]> {
55
1.45M
        match hdr.length {
56
1.45M
            Length::Definite(l) => take(l)(i),
57
0
            Length::Indefinite => Err(Err::Error(Error::DerConstraintFailed(
58
0
                DerConstraint::IndefiniteLength,
59
0
            ))),
60
        }
61
1.45M
    }
62
}
63
64
/// Skip object content, and return true if object was End-Of-Content
65
16.8M
fn ber_skip_object_content<'a>(
66
16.8M
    i: &'a [u8],
67
16.8M
    hdr: &Header,
68
16.8M
    max_depth: usize,
69
16.8M
) -> ParseResult<'a, bool> {
70
16.8M
    if max_depth == 0 {
71
398
        return Err(Err::Error(Error::BerMaxDepth));
72
16.8M
    }
73
16.8M
    match hdr.length {
74
16.3M
        Length::Definite(l) => {
75
16.3M
            if l == 0 && hdr.tag == Tag::EndOfContent {
76
2.03M
                return Ok((i, true));
77
14.3M
            }
78
14.3M
            let (i, _) = take(l)(i)?;
79
14.3M
            Ok((i, false))
80
        }
81
        Length::Indefinite => {
82
407k
            hdr.assert_constructed()?;
83
            // read objects until EndOfContent (00 00)
84
            // this is recursive
85
407k
            let mut i = i;
86
            loop {
87
8.77M
                let (i2, header2) = Header::from_ber(i)?;
88
8.76M
                let (i3, eoc) = ber_skip_object_content(i2, &header2, max_depth - 1)?;
89
8.73M
                if eoc {
90
                    // return false, since top object was not EndOfContent
91
371k
                    return Ok((i3, false));
92
8.36M
                }
93
8.36M
                i = i3;
94
            }
95
        }
96
    }
97
16.8M
}
98
99
/// Try to parse input bytes as u64
100
#[inline]
101
531k
pub(crate) fn bytes_to_u64(s: &[u8]) -> core::result::Result<u64, Error> {
102
531k
    let mut u: u64 = 0;
103
1.23M
    for &c in s {
104
710k
        if u & 0xff00_0000_0000_0000 != 0 {
105
9.72k
            return Err(Error::IntegerTooLarge);
106
700k
        }
107
700k
        u <<= 8;
108
700k
        u |= u64::from(c);
109
    }
110
521k
    Ok(u)
111
531k
}
112
113
20.7M
pub(crate) fn parse_identifier(i: &[u8]) -> ParseResult<(u8, u8, u32, &[u8])> {
114
20.7M
    if i.is_empty() {
115
170k
        Err(Err::Incomplete(Needed::new(1)))
116
    } else {
117
20.6M
        let a = i[0] >> 6;
118
20.6M
        let b = u8::from(i[0] & 0b0010_0000 != 0);
119
20.6M
        let mut c = u32::from(i[0] & 0b0001_1111);
120
121
20.6M
        let mut tag_byte_count = 1;
122
123
20.6M
        if c == 0x1f {
124
119k
            c = 0;
125
            loop {
126
                // Make sure we don't read past the end of our data.
127
315k
                custom_check!(i, tag_byte_count >= i.len(), Error::InvalidTag)?;
128
129
                // With tag defined as u32 the most we can fit in is four tag bytes.
130
                // (X.690 doesn't actually specify maximum tag width.)
131
299k
                custom_check!(i, tag_byte_count > 5, Error::InvalidTag)?;
132
133
292k
                c = (c << 7) | (u32::from(i[tag_byte_count]) & 0x7f);
134
292k
                let done = i[tag_byte_count] & 0x80 == 0;
135
292k
                tag_byte_count += 1;
136
292k
                if done {
137
96.9k
                    break;
138
195k
                }
139
            }
140
20.5M
        }
141
142
20.6M
        let (raw_tag, rem) = i.split_at(tag_byte_count);
143
144
20.6M
        Ok((rem, (a, b, c, raw_tag)))
145
    }
146
20.7M
}
147
148
/// Return the MSB and the rest of the first byte, or an error
149
20.6M
pub(crate) fn parse_ber_length_byte(i: &[u8]) -> ParseResult<(u8, u8)> {
150
20.6M
    if i.is_empty() {
151
17.4k
        Err(Err::Incomplete(Needed::new(1)))
152
    } else {
153
20.5M
        let a = i[0] >> 7;
154
20.5M
        let b = i[0] & 0b0111_1111;
155
20.5M
        Ok((&i[1..], (a, b)))
156
    }
157
20.6M
}
158
159
#[doc(hidden)]
160
#[macro_export]
161
macro_rules! der_constraint_fail_if(
162
    ($slice:expr, $cond:expr, $constraint:expr) => (
163
        {
164
            if $cond {
165
                return Err(::nom::Err::Error(Error::DerConstraintFailed($constraint)));
166
            }
167
        }
168
    );
169
);