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.5.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
7.17M
    fn get_object_content<'a>(
27
7.17M
        i: &'a [u8],
28
7.17M
        hdr: &'_ Header,
29
7.17M
        max_depth: usize,
30
7.17M
    ) -> ParseResult<'a, &'a [u8]> {
31
7.17M
        let start_i = i;
32
7.17M
        let (i, _) = ber_skip_object_content(i, hdr, max_depth)?;
33
7.15M
        let len = start_i.offset(i);
34
7.15M
        let (content, i) = start_i.split_at(len);
35
        // if len is indefinite, there are 2 extra bytes for EOC
36
7.15M
        if hdr.length == Length::Indefinite {
37
28.7k
            let len = content.len();
38
28.7k
            assert!(len >= 2);
39
28.7k
            Ok((i, &content[..len - 2]))
40
        } else {
41
7.12M
            Ok((i, content))
42
        }
43
7.17M
    }
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
243k
    fn get_object_content<'a>(
51
243k
        i: &'a [u8],
52
243k
        hdr: &'_ Header,
53
243k
        _max_depth: usize,
54
243k
    ) -> ParseResult<'a, &'a [u8]> {
55
243k
        match hdr.length {
56
243k
            Length::Definite(l) => take(l)(i),
57
0
            Length::Indefinite => Err(Err::Error(Error::DerConstraintFailed(
58
0
                DerConstraint::IndefiniteLength,
59
0
            ))),
60
        }
61
243k
    }
62
}
63
64
/// Skip object content, and return true if object was End-Of-Content
65
13.6M
fn ber_skip_object_content<'a>(
66
13.6M
    i: &'a [u8],
67
13.6M
    hdr: &Header,
68
13.6M
    max_depth: usize,
69
13.6M
) -> ParseResult<'a, bool> {
70
13.6M
    if max_depth == 0 {
71
326
        return Err(Err::Error(Error::BerMaxDepth));
72
13.6M
    }
73
13.6M
    match hdr.length {
74
13.4M
        Length::Definite(l) => {
75
13.4M
            if l == 0 && hdr.tag == Tag::EndOfContent {
76
2.43M
                return Ok((i, true));
77
11.0M
            }
78
11.0M
            let (i, _) = take(l)(i)?;
79
11.0M
            Ok((i, false))
80
        }
81
        Length::Indefinite => {
82
129k
            hdr.assert_constructed()?;
83
            // read objects until EndOfContent (00 00)
84
            // this is recursive
85
129k
            let mut i = i;
86
            loop {
87
6.45M
                let (i2, header2) = Header::from_ber(i)?;
88
6.44M
                let (i3, eoc) = ber_skip_object_content(i2, &header2, max_depth - 1)?;
89
6.43M
                if eoc {
90
                    // return false, since top object was not EndOfContent
91
109k
                    return Ok((i3, false));
92
6.32M
                }
93
6.32M
                i = i3;
94
            }
95
        }
96
    }
97
13.6M
}
98
99
/// Try to parse input bytes as u64
100
#[inline]
101
78.2k
pub(crate) fn bytes_to_u64(s: &[u8]) -> core::result::Result<u64, Error> {
102
78.2k
    let mut u: u64 = 0;
103
257k
    for &c in s {
104
180k
        if u & 0xff00_0000_0000_0000 != 0 {
105
1.59k
            return Err(Error::IntegerTooLarge);
106
179k
        }
107
179k
        u <<= 8;
108
179k
        u |= u64::from(c);
109
    }
110
76.6k
    Ok(u)
111
78.2k
}
112
113
15.8M
pub(crate) fn parse_identifier(i: &[u8]) -> ParseResult<(u8, u8, u32, &[u8])> {
114
15.8M
    if i.is_empty() {
115
94.5k
        Err(Err::Incomplete(Needed::new(1)))
116
    } else {
117
15.7M
        let a = i[0] >> 6;
118
15.7M
        let b = u8::from(i[0] & 0b0010_0000 != 0);
119
15.7M
        let mut c = u32::from(i[0] & 0b0001_1111);
120
121
15.7M
        let mut tag_byte_count = 1;
122
123
15.7M
        if c == 0x1f {
124
61.6k
            c = 0;
125
            loop {
126
                // Make sure we don't read past the end of our data.
127
134k
                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
127k
                custom_check!(i, tag_byte_count > 5, Error::InvalidTag)?;
132
133
125k
                c = (c << 7) | (u32::from(i[tag_byte_count]) & 0x7f);
134
125k
                let done = i[tag_byte_count] & 0x80 == 0;
135
125k
                tag_byte_count += 1;
136
125k
                if done {
137
52.6k
                    break;
138
72.8k
                }
139
            }
140
15.6M
        }
141
142
15.7M
        let (raw_tag, rem) = i.split_at(tag_byte_count);
143
144
15.7M
        Ok((rem, (a, b, c, raw_tag)))
145
    }
146
15.8M
}
147
148
/// Return the MSB and the rest of the first byte, or an error
149
15.7M
pub(crate) fn parse_ber_length_byte(i: &[u8]) -> ParseResult<(u8, u8)> {
150
15.7M
    if i.is_empty() {
151
7.51k
        Err(Err::Incomplete(Needed::new(1)))
152
    } else {
153
15.7M
        let a = i[0] >> 7;
154
15.7M
        let b = i[0] & 0b0111_1111;
155
15.7M
        Ok((&i[1..], (a, b)))
156
    }
157
15.7M
}
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
);