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