asn1_rs/ber/
parser.rs

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