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
8pub const MAX_RECURSION: usize = 50;
10
11pub trait GetObjectContent {
15 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 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 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
64fn 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 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 Ok((i3, false));
92 }
93 i = i3;
94 }
95 }
96 }
97}
98
99#[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 custom_check!(i, tag_byte_count >= i.len(), Error::InvalidTag)?;
128
129 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
148pub(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);