Coverage Report

Created: 2024-12-17 06:15

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