/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 | | ); |