/rust/registry/src/index.crates.io-1949cf8c6b5b557f/der-parser-6.0.1/src/ber/parser.rs
Line | Count | Source |
1 | | use crate::ber::*; |
2 | | use crate::error::*; |
3 | | use crate::oid::*; |
4 | | use nom::bytes::streaming::take; |
5 | | use nom::combinator::{complete, map, verify}; |
6 | | use nom::multi::{many0, many_till}; |
7 | | use nom::number::streaming::be_u8; |
8 | | use nom::{Err, Needed, Offset}; |
9 | | use rusticata_macros::{combinator::parse_hex_to_u64, custom_check}; |
10 | | |
11 | | /// Default maximum recursion limit |
12 | | pub const MAX_RECURSION: usize = 50; |
13 | | |
14 | | /// Default maximum object size (2^32) |
15 | | pub const MAX_OBJECT_SIZE: usize = 4_294_967_295; |
16 | | |
17 | | /// Skip object content, and return true if object was End-Of-Content |
18 | 334k | pub(crate) fn ber_skip_object_content<'a>( |
19 | 334k | i: &'a [u8], |
20 | 334k | hdr: &BerObjectHeader, |
21 | 334k | max_depth: usize, |
22 | 334k | ) -> BerResult<'a, bool> { |
23 | 334k | if max_depth == 0 { |
24 | 410 | return Err(Err::Error(BerError::BerMaxDepth)); |
25 | 333k | } |
26 | 333k | match hdr.len { |
27 | 215k | BerSize::Definite(l) => { |
28 | 215k | if l == 0 && hdr.tag == BerTag::EndOfContent { |
29 | 45.0k | return Ok((i, true)); |
30 | 170k | } |
31 | 170k | let (i, _) = take(l)(i)?; |
32 | 140k | Ok((i, false)) |
33 | | } |
34 | | BerSize::Indefinite => { |
35 | 118k | if hdr.is_primitive() { |
36 | 0 | return Err(Err::Error(BerError::ConstructExpected)); |
37 | 118k | } |
38 | | // read objects until EndOfContent (00 00) |
39 | | // this is recursive |
40 | 118k | let mut i = i; |
41 | | loop { |
42 | 163k | let (i2, header2) = ber_read_element_header(i)?; |
43 | 120k | let (i3, eoc) = ber_skip_object_content(i2, &header2, max_depth - 1)?; |
44 | 87.7k | if eoc { |
45 | | // return false, since top object was not EndOfContent |
46 | 43.1k | return Ok((i3, false)); |
47 | 44.6k | } |
48 | 44.6k | i = i3; |
49 | | } |
50 | | } |
51 | | } |
52 | 334k | } |
53 | | |
54 | | /// Read object raw content (bytes) |
55 | 213k | pub(crate) fn ber_get_object_content<'a>( |
56 | 213k | i: &'a [u8], |
57 | 213k | hdr: &BerObjectHeader, |
58 | 213k | max_depth: usize, |
59 | 213k | ) -> BerResult<'a, &'a [u8]> { |
60 | 213k | let start_i = i; |
61 | 213k | let (i, _) = ber_skip_object_content(i, hdr, max_depth)?; |
62 | 140k | let len = start_i.offset(i); |
63 | 140k | let (content, i) = start_i.split_at(len); |
64 | | // if len is indefinite, there are 2 extra bytes for EOC |
65 | 140k | if hdr.len == BerSize::Indefinite { |
66 | 34.3k | let len = content.len(); |
67 | 34.3k | assert!(len >= 2); |
68 | 34.3k | Ok((i, &content[..len - 2])) |
69 | | } else { |
70 | 106k | Ok((i, content)) |
71 | | } |
72 | 213k | } |
73 | | |
74 | | /// Try to parse input bytes as u64 |
75 | | #[inline] |
76 | 63.7k | pub(crate) fn bytes_to_u64(s: &[u8]) -> Result<u64, BerError> { |
77 | 63.7k | let mut u: u64 = 0; |
78 | 311k | for &c in s { |
79 | 257k | if u & 0xff00_0000_0000_0000 != 0 { |
80 | 10.1k | return Err(BerError::IntegerTooLarge); |
81 | 247k | } |
82 | 247k | u <<= 8; |
83 | 247k | u |= u64::from(c); |
84 | | } |
85 | 53.6k | Ok(u) |
86 | 63.7k | } |
87 | | |
88 | | /// Try to parse an input bit string as u64. |
89 | | /// |
90 | | /// Note: this is for the primitive BER/DER encoding only, the |
91 | | /// constructed BER encoding for BIT STRING does not seem to be |
92 | | /// supported at all by the library currently. |
93 | | #[inline] |
94 | 0 | pub(crate) fn bitstring_to_u64( |
95 | 0 | padding_bits: usize, |
96 | 0 | data: &BitStringObject, |
97 | 0 | ) -> Result<u64, BerError> { |
98 | 0 | let raw_bytes = data.data; |
99 | 0 | let bit_size = (raw_bytes.len() * 8) |
100 | 0 | .checked_sub(padding_bits) |
101 | 0 | .ok_or(BerError::InvalidLength)?; |
102 | 0 | if bit_size > 64 { |
103 | 0 | return Err(BerError::IntegerTooLarge); |
104 | 0 | } |
105 | 0 | let padding_bits = padding_bits % 8; |
106 | 0 | let num_bytes = if bit_size % 8 > 0 { |
107 | 0 | (bit_size / 8) + 1 |
108 | | } else { |
109 | 0 | bit_size / 8 |
110 | | }; |
111 | 0 | let mut resulting_integer: u64 = 0; |
112 | 0 | for &c in &raw_bytes[..num_bytes] { |
113 | 0 | resulting_integer <<= 8; |
114 | 0 | resulting_integer |= c as u64; |
115 | 0 | } |
116 | 0 | Ok(resulting_integer >> padding_bits) |
117 | 0 | } |
118 | | |
119 | 5.64M | pub(crate) fn parse_identifier(i: &[u8]) -> BerResult<(u8, u8, u32, &[u8])> { |
120 | 5.64M | if i.is_empty() { |
121 | 197k | Err(Err::Incomplete(Needed::new(1))) |
122 | | } else { |
123 | 5.45M | let a = i[0] >> 6; |
124 | 5.45M | let b = if i[0] & 0b0010_0000 != 0 { 1 } else { 0 }; |
125 | 5.45M | let mut c = u32::from(i[0] & 0b0001_1111); |
126 | | |
127 | 5.45M | let mut tag_byte_count = 1; |
128 | | |
129 | 5.45M | if c == 0x1f { |
130 | 556k | c = 0; |
131 | | loop { |
132 | | // Make sure we don't read past the end of our data. |
133 | 798k | custom_check!(i, tag_byte_count >= i.len(), BerError::InvalidTag)?; |
134 | | |
135 | | // With tag defined as u32 the most we can fit in is four tag bytes. |
136 | | // (X.690 doesn't actually specify maximum tag width.) |
137 | 773k | custom_check!(i, tag_byte_count > 5, BerError::InvalidTag)?; |
138 | | |
139 | 764k | c = (c << 7) | (u32::from(i[tag_byte_count]) & 0x7f); |
140 | 764k | let done = i[tag_byte_count] & 0x80 == 0; |
141 | 764k | tag_byte_count += 1; |
142 | 764k | if done { |
143 | 522k | break; |
144 | 241k | } |
145 | | } |
146 | 4.89M | } |
147 | | |
148 | 5.41M | let (raw_tag, rem) = i.split_at(tag_byte_count); |
149 | | |
150 | 5.41M | Ok((rem, (a, b, c, raw_tag))) |
151 | | } |
152 | 5.64M | } |
153 | | |
154 | | /// Return the MSB and the rest of the first byte, or an error |
155 | 5.41M | pub(crate) fn parse_ber_length_byte(i: &[u8]) -> BerResult<(u8, u8)> { |
156 | 5.41M | if i.is_empty() { |
157 | 25.4k | Err(Err::Incomplete(Needed::new(1))) |
158 | | } else { |
159 | 5.39M | let a = i[0] >> 7; |
160 | 5.39M | let b = i[0] & 0b0111_1111; |
161 | 5.39M | Ok((&i[1..], (a, b))) |
162 | | } |
163 | 5.41M | } |
164 | | |
165 | | /// Read an object header |
166 | | /// |
167 | | /// ### Example |
168 | | /// |
169 | | /// ``` |
170 | | /// # use der_parser::ber::{ber_read_element_header, BerClass, BerSize, BerTag}; |
171 | | /// # |
172 | | /// let bytes = &[0x02, 0x03, 0x01, 0x00, 0x01]; |
173 | | /// let (i, hdr) = ber_read_element_header(bytes).expect("could not read header"); |
174 | | /// |
175 | | /// assert_eq!(hdr.class, BerClass::Universal); |
176 | | /// assert_eq!(hdr.tag, BerTag::Integer); |
177 | | /// assert_eq!(hdr.len, BerSize::Definite(3)); |
178 | | /// ``` |
179 | 4.22M | pub fn ber_read_element_header(i: &[u8]) -> BerResult<BerObjectHeader> { |
180 | 4.22M | let (i1, el) = parse_identifier(i)?; |
181 | 4.12M | let class = match BerClass::try_from(el.0) { |
182 | 4.12M | Ok(c) => c, |
183 | 0 | Err(_) => unreachable!(), // Cannot fail, we have read exactly 2 bits |
184 | | }; |
185 | 4.12M | let (i2, len) = parse_ber_length_byte(i1)?; |
186 | 4.10M | let (i3, len) = match (len.0, len.1) { |
187 | 3.71M | (0, l1) => { |
188 | | // Short form: MSB is 0, the rest encodes the length (which can be 0) (8.1.3.4) |
189 | 3.71M | (i2, BerSize::Definite(usize::from(l1))) |
190 | | } |
191 | | (_, 0) => { |
192 | | // Indefinite form: MSB is 1, the rest is 0 (8.1.3.6) |
193 | | // If encoding is primitive, definite form shall be used (8.1.3.2) |
194 | 247k | if el.1 == 0 { |
195 | 6.55k | return Err(Err::Error(BerError::ConstructExpected)); |
196 | 241k | } |
197 | 241k | (i2, BerSize::Indefinite) |
198 | | } |
199 | 140k | (_, l1) => { |
200 | | // if len is 0xff -> error (8.1.3.5) |
201 | 140k | if l1 == 0b0111_1111 { |
202 | 28.3k | return Err(::nom::Err::Error(BerError::InvalidTag)); |
203 | 112k | } |
204 | 112k | let (i3, llen) = take(l1)(i2)?; |
205 | 49.1k | match bytes_to_u64(llen) { |
206 | 44.0k | Ok(l) => { |
207 | 44.0k | let l = |
208 | 44.0k | usize::try_from(l).or(Err(::nom::Err::Error(BerError::InvalidLength)))?; |
209 | 44.0k | (i3, BerSize::Definite(l)) |
210 | | } |
211 | | Err(_) => { |
212 | 5.07k | return Err(::nom::Err::Error(BerError::InvalidTag)); |
213 | | } |
214 | | } |
215 | | } |
216 | | }; |
217 | 4.00M | let hdr = BerObjectHeader::new(class, el.1, BerTag(el.2), len).with_raw_tag(Some(el.3)); |
218 | 4.00M | Ok((i3, hdr)) |
219 | 4.22M | } |
220 | | |
221 | | #[allow(clippy::unnecessary_wraps)] |
222 | | #[inline] |
223 | 101k | fn ber_read_content_eoc(i: &[u8]) -> BerResult<BerObjectContent> { |
224 | 101k | Ok((i, BerObjectContent::EndOfContent)) |
225 | 101k | } |
226 | | |
227 | | #[inline] |
228 | 12.4k | fn ber_read_content_bool(i: &[u8]) -> BerResult<BerObjectContent> { |
229 | 12.4k | match be_u8(i) { |
230 | 4.66k | Ok((rem, 0)) => Ok((rem, BerObjectContent::Boolean(false))), |
231 | 7.80k | Ok((rem, _)) => Ok((rem, BerObjectContent::Boolean(true))), |
232 | 0 | Err(e) => Err(e), |
233 | | } |
234 | 12.4k | } |
235 | | |
236 | | #[inline] |
237 | 645k | fn ber_read_content_integer(i: &[u8], len: usize) -> BerResult<BerObjectContent> { |
238 | 645k | map(take(len), BerObjectContent::Integer)(i) |
239 | 645k | } |
240 | | |
241 | | #[inline] |
242 | 3.12k | fn ber_read_content_bitstring(i: &[u8], len: usize) -> BerResult<BerObjectContent> { |
243 | 3.12k | custom_check!(i, len == 0, BerError::InvalidLength)?; |
244 | | |
245 | 2.01k | let (i, ignored_bits) = be_u8(i)?; |
246 | 2.01k | let (i, data) = take(len - 1)(i)?; |
247 | 2.01k | Ok(( |
248 | 2.01k | i, |
249 | 2.01k | BerObjectContent::BitString(ignored_bits, BitStringObject { data }), |
250 | 2.01k | )) |
251 | 3.12k | } |
252 | | |
253 | | #[inline] |
254 | 8.37k | fn ber_read_content_octetstring(i: &[u8], len: usize) -> BerResult<BerObjectContent> { |
255 | 8.37k | map(take(len), BerObjectContent::OctetString)(i) |
256 | 8.37k | } |
257 | | |
258 | | #[allow(clippy::unnecessary_wraps)] |
259 | | #[inline] |
260 | 1.55k | fn ber_read_content_null(i: &[u8]) -> BerResult<BerObjectContent> { |
261 | 1.55k | Ok((i, BerObjectContent::Null)) |
262 | 1.55k | } |
263 | | |
264 | 37.9k | fn ber_read_content_oid(i: &[u8], len: usize) -> BerResult<BerObjectContent> { |
265 | 37.9k | custom_check!(i, len == 0, BerError::InvalidLength)?; |
266 | | |
267 | 36.3k | let (i1, oid) = verify(take(len), |os: &[u8]| os.last().unwrap() >> 7 == 0u8)(i)?; |
268 | | |
269 | 35.1k | let obj = BerObjectContent::OID(Oid::new(Cow::Borrowed(oid))); |
270 | 35.1k | Ok((i1, obj)) |
271 | 37.9k | } |
272 | | |
273 | | #[inline] |
274 | 11.8k | fn ber_read_content_enum(i: &[u8], len: usize) -> BerResult<BerObjectContent> { |
275 | 11.8k | let (rem, num) = parse_hex_to_u64(i, len).map_err(|_| BerError::BerValueError)?; |
276 | 10.6k | Ok((rem, BerObjectContent::Enum(num))) |
277 | 11.8k | } |
278 | | |
279 | 3.15k | fn ber_read_content_utf8string(i: &[u8], len: usize) -> BerResult<BerObjectContent> { |
280 | 3.15k | let (i, bytes) = take(len)(i)?; |
281 | 3.15k | let s = core::str::from_utf8(bytes) |
282 | 3.15k | .map_err(|_| Err::Error(BerError::StringInvalidCharset)) |
283 | 3.15k | .map(BerObjectContent::UTF8String)?; |
284 | 2.00k | Ok((i, s)) |
285 | 3.15k | } |
286 | | |
287 | 6.62k | fn ber_read_content_relativeoid(i: &[u8], len: usize) -> BerResult<BerObjectContent> { |
288 | 6.62k | custom_check!(i, len == 0, BerError::InvalidLength)?; |
289 | | |
290 | 5.88k | let (i1, oid) = verify(take(len), |os: &[u8]| os.last().unwrap() >> 7 == 0u8)(i)?; |
291 | | |
292 | 3.22k | let obj = BerObjectContent::RelativeOID(Oid::new_relative(Cow::Borrowed(oid))); |
293 | 3.22k | Ok((i1, obj)) |
294 | 6.62k | } |
295 | | |
296 | 111k | fn ber_read_content_sequence( |
297 | 111k | i: &[u8], |
298 | 111k | len: BerSize, |
299 | 111k | max_depth: usize, |
300 | 111k | ) -> BerResult<BerObjectContent> { |
301 | 111k | custom_check!(i, max_depth == 0, BerError::BerMaxDepth)?; |
302 | 111k | match len { |
303 | 74.7k | BerSize::Definite(len) => { |
304 | 74.7k | let (i, data) = take(len)(i)?; |
305 | 74.7k | let (_, l) = many0(complete(r_parse_ber(max_depth - 1)))(data)?; |
306 | | // trailing bytes are ignored |
307 | 74.7k | Ok((i, BerObjectContent::Sequence(l))) |
308 | | } |
309 | | BerSize::Indefinite => { |
310 | | // indefinite form |
311 | | // read until end-of-content |
312 | 36.5k | let (rem, (l, _)) = many_till(r_parse_ber(max_depth - 1), parse_ber_endofcontent)(i)?; |
313 | 10.7k | Ok((rem, BerObjectContent::Sequence(l))) |
314 | | } |
315 | | } |
316 | 111k | } |
317 | | |
318 | 75.4k | fn ber_read_content_set(i: &[u8], len: BerSize, max_depth: usize) -> BerResult<BerObjectContent> { |
319 | 75.4k | custom_check!(i, max_depth == 0, BerError::BerMaxDepth)?; |
320 | 75.4k | match len { |
321 | 38.5k | BerSize::Definite(len) => { |
322 | 38.5k | let (i, data) = take(len)(i)?; |
323 | 38.5k | let (_, l) = many0(complete(r_parse_ber(max_depth - 1)))(data)?; |
324 | | // trailing bytes are ignored |
325 | 38.5k | Ok((i, BerObjectContent::Set(l))) |
326 | | } |
327 | | BerSize::Indefinite => { |
328 | | // indefinite form |
329 | | // read until end-of-content |
330 | 36.8k | let (rem, (l, _)) = many_till(r_parse_ber(max_depth - 1), parse_ber_endofcontent)(i)?; |
331 | 6.38k | Ok((rem, BerObjectContent::Set(l))) |
332 | | } |
333 | | } |
334 | 75.4k | } |
335 | | |
336 | 8.27k | fn ber_read_content_numericstring<'a>(i: &'a [u8], len: usize) -> BerResult<BerObjectContent<'a>> { |
337 | | // Argument must be a reference, because of the .iter().all(F) call below |
338 | | #[allow(clippy::trivially_copy_pass_by_ref)] |
339 | 4.07k | fn is_numeric(b: &u8) -> bool { |
340 | 4.07k | matches!(*b, b'0'..=b'9' | b' ') |
341 | 4.07k | } |
342 | 8.27k | let (i, bytes) = take(len)(i)?; |
343 | 8.27k | if !bytes.iter().all(is_numeric) { |
344 | 1.78k | return Err(Err::Error(BerError::StringInvalidCharset)); |
345 | 6.48k | } |
346 | 6.48k | let s = core::str::from_utf8(bytes) |
347 | 6.48k | .map_err(|_| Err::Error(BerError::StringInvalidCharset)) |
348 | 6.48k | .map(BerObjectContent::NumericString)?; |
349 | 6.48k | Ok((i, s)) |
350 | 8.27k | } |
351 | | |
352 | 3.98k | fn ber_read_content_visiblestring<'a>(i: &'a [u8], len: usize) -> BerResult<BerObjectContent<'a>> { |
353 | | // Argument must be a reference, because of the .iter().all(F) call below |
354 | | #[allow(clippy::trivially_copy_pass_by_ref)] |
355 | 15.1k | fn is_visible(b: &u8) -> bool { |
356 | 15.1k | 0x20 <= *b && *b <= 0x7f |
357 | 15.1k | } |
358 | 3.98k | let (i, bytes) = take(len)(i)?; |
359 | 3.98k | if !bytes.iter().all(is_visible) { |
360 | 2.25k | return Err(Err::Error(BerError::StringInvalidCharset)); |
361 | 1.73k | } |
362 | 1.73k | let s = core::str::from_utf8(bytes) |
363 | 1.73k | .map_err(|_| Err::Error(BerError::StringInvalidCharset)) |
364 | 1.73k | .map(BerObjectContent::VisibleString)?; |
365 | 1.73k | Ok((i, s)) |
366 | 3.98k | } |
367 | | |
368 | 6.30k | fn ber_read_content_printablestring<'a>( |
369 | 6.30k | i: &'a [u8], |
370 | 6.30k | len: usize, |
371 | 6.30k | ) -> BerResult<BerObjectContent<'a>> { |
372 | | // Argument must be a reference, because of the .iter().all(F) call below |
373 | | #[allow(clippy::trivially_copy_pass_by_ref)] |
374 | 107k | fn is_printable(b: &u8) -> bool { |
375 | 107k | matches!(*b, |
376 | 51.1k | b'a'..=b'z' |
377 | 14.7k | | b'A'..=b'Z' |
378 | 10.7k | | b'0'..=b'9' |
379 | | | b' ' |
380 | | | b'\'' |
381 | | | b'(' |
382 | | | b')' |
383 | | | b'+' |
384 | | | b',' |
385 | | | b'-' |
386 | | | b'.' |
387 | | | b'/' |
388 | | | b':' |
389 | | | b'=' |
390 | | | b'?') |
391 | 107k | } |
392 | 6.30k | let (i, bytes) = take(len)(i)?; |
393 | 6.30k | if !bytes.iter().all(is_printable) { |
394 | 2.55k | return Err(Err::Error(BerError::StringInvalidCharset)); |
395 | 3.75k | } |
396 | 3.75k | let s = core::str::from_utf8(bytes) |
397 | 3.75k | .map_err(|_| Err::Error(BerError::StringInvalidCharset)) |
398 | 3.75k | .map(BerObjectContent::PrintableString)?; |
399 | 3.75k | Ok((i, s)) |
400 | 6.30k | } |
401 | | |
402 | | #[inline] |
403 | 4.05k | fn ber_read_content_t61string(i: &[u8], len: usize) -> BerResult<BerObjectContent> { |
404 | 4.05k | map(take(len), BerObjectContent::T61String)(i) |
405 | 4.05k | } |
406 | | |
407 | | #[inline] |
408 | 7.06k | fn ber_read_content_videotexstring(i: &[u8], len: usize) -> BerResult<BerObjectContent> { |
409 | 7.06k | map(take(len), BerObjectContent::VideotexString)(i) |
410 | 7.06k | } |
411 | | |
412 | 7.74k | fn ber_read_content_ia5string<'a>(i: &'a [u8], len: usize) -> BerResult<BerObjectContent<'a>> { |
413 | 7.74k | let (i, bytes) = take(len)(i)?; |
414 | 7.74k | if !bytes.iter().all(u8::is_ascii) { |
415 | 3.28k | return Err(Err::Error(BerError::StringInvalidCharset)); |
416 | 4.45k | } |
417 | 4.45k | let s = core::str::from_utf8(bytes) |
418 | 4.45k | .map_err(|_| Err::Error(BerError::StringInvalidCharset)) |
419 | 4.45k | .map(BerObjectContent::IA5String)?; |
420 | 4.45k | Ok((i, s)) |
421 | 7.74k | } |
422 | | |
423 | 3.82k | fn ber_read_content_utctime<'a>(i: &'a [u8], len: usize) -> BerResult<BerObjectContent<'a>> { |
424 | | // Argument must be a reference, because of the .iter().all(F) call below |
425 | | #[allow(clippy::trivially_copy_pass_by_ref)] |
426 | 20.0k | fn is_visible(b: &u8) -> bool { |
427 | 20.0k | 0x20 <= *b && *b <= 0x7f |
428 | 20.0k | } |
429 | 3.82k | let (i, bytes) = take(len)(i)?; |
430 | 3.82k | if !bytes.iter().all(is_visible) { |
431 | 1.30k | return Err(Err::Error(BerError::StringInvalidCharset)); |
432 | 2.51k | } |
433 | 2.51k | let s = core::str::from_utf8(bytes) |
434 | 2.51k | .map_err(|_| Err::Error(BerError::StringInvalidCharset)) |
435 | 2.51k | .map(BerObjectContent::UTCTime)?; |
436 | 2.51k | Ok((i, s)) |
437 | 3.82k | } |
438 | | |
439 | 109k | fn ber_read_content_generalizedtime<'a>( |
440 | 109k | i: &'a [u8], |
441 | 109k | len: usize, |
442 | 109k | ) -> BerResult<BerObjectContent<'a>> { |
443 | | // Argument must be a reference, because of the .iter().all(F) call below |
444 | | #[allow(clippy::trivially_copy_pass_by_ref)] |
445 | 183k | fn is_visible(b: &u8) -> bool { |
446 | 183k | 0x20 <= *b && *b <= 0x7f |
447 | 183k | } |
448 | 109k | let (i, bytes) = take(len)(i)?; |
449 | 109k | if !bytes.iter().all(is_visible) { |
450 | 1.78k | return Err(Err::Error(BerError::StringInvalidCharset)); |
451 | 107k | } |
452 | 107k | let s = core::str::from_utf8(bytes) |
453 | 107k | .map_err(|_| Err::Error(BerError::StringInvalidCharset)) |
454 | 107k | .map(BerObjectContent::GeneralizedTime)?; |
455 | 107k | Ok((i, s)) |
456 | 109k | } |
457 | | |
458 | | #[inline] |
459 | 2.45k | fn ber_read_content_objectdescriptor(i: &[u8], len: usize) -> BerResult<BerObjectContent> { |
460 | 2.45k | map(take(len), BerObjectContent::ObjectDescriptor)(i) |
461 | 2.45k | } |
462 | | |
463 | | #[inline] |
464 | 1.01k | fn ber_read_content_graphicstring(i: &[u8], len: usize) -> BerResult<BerObjectContent> { |
465 | 1.01k | map(take(len), BerObjectContent::GraphicString)(i) |
466 | 1.01k | } |
467 | | |
468 | | #[inline] |
469 | 134k | fn ber_read_content_generalstring(i: &[u8], len: usize) -> BerResult<BerObjectContent> { |
470 | 134k | map(take(len), BerObjectContent::GeneralString)(i) |
471 | 134k | } |
472 | | |
473 | | #[inline] |
474 | 5.89k | fn ber_read_content_bmpstring(i: &[u8], len: usize) -> BerResult<BerObjectContent> { |
475 | 5.89k | map(take(len), BerObjectContent::BmpString)(i) |
476 | 5.89k | } |
477 | | |
478 | | #[inline] |
479 | 1.57k | fn ber_read_content_universalstring(i: &[u8], len: usize) -> BerResult<BerObjectContent> { |
480 | 1.57k | map(take(len), BerObjectContent::UniversalString)(i) |
481 | 1.57k | } |
482 | | |
483 | | /// Parse the next bytes as the *content* of a BER object. |
484 | | /// |
485 | | /// Content type is *not* checked to match tag, caller is responsible of providing the correct tag |
486 | | /// |
487 | | /// This function is mostly used when parsing implicit tagged objects, when reading primitive |
488 | | /// types. |
489 | | /// |
490 | | /// `max_depth` is the maximum allowed recursion for objects. |
491 | | /// |
492 | | /// ### Example |
493 | | /// |
494 | | /// ``` |
495 | | /// # use der_parser::ber::{ber_read_element_content_as, ber_read_element_header, BerTag}; |
496 | | /// # |
497 | | /// # let bytes = &[0x02, 0x03, 0x01, 0x00, 0x01]; |
498 | | /// let (i, hdr) = ber_read_element_header(bytes).expect("could not read header"); |
499 | | /// let (_, content) = ber_read_element_content_as( |
500 | | /// i, hdr.tag, hdr.len, hdr.is_constructed(), 5 |
501 | | /// ).expect("parsing failed"); |
502 | | /// # |
503 | | /// # assert_eq!(hdr.tag, BerTag::Integer); |
504 | | /// # assert_eq!(content.as_u32(), Ok(0x10001)); |
505 | | /// ``` |
506 | 1.38M | pub fn ber_read_element_content_as( |
507 | 1.38M | i: &[u8], |
508 | 1.38M | tag: BerTag, |
509 | 1.38M | len: BerSize, |
510 | 1.38M | constructed: bool, |
511 | 1.38M | max_depth: usize, |
512 | 1.38M | ) -> BerResult<BerObjectContent> { |
513 | 1.38M | if let BerSize::Definite(l) = len { |
514 | 1.30M | custom_check!(i, l > MAX_OBJECT_SIZE, BerError::InvalidLength)?; |
515 | 1.30M | if i.len() < l { |
516 | 11.3k | return Err(Err::Incomplete(Needed::new(l))); |
517 | 1.29M | } |
518 | 81.2k | } |
519 | 1.37M | match tag { |
520 | | // 0x00 end-of-content |
521 | | BerTag::EndOfContent => { |
522 | 110k | custom_check!(i, len != BerSize::Definite(0), BerError::InvalidLength)?; |
523 | 101k | ber_read_content_eoc(i) |
524 | | } |
525 | | // 0x01 bool |
526 | | BerTag::Boolean => { |
527 | 14.9k | let len = len.primitive()?; |
528 | 14.2k | custom_check!(i, len != 1, BerError::InvalidLength)?; |
529 | 12.4k | ber_read_content_bool(i) |
530 | | } |
531 | | // 0x02 |
532 | | BerTag::Integer => { |
533 | 648k | custom_check!(i, constructed, BerError::ConstructUnexpected)?; |
534 | 645k | let len = len.primitive()?; |
535 | 645k | ber_read_content_integer(i, len) |
536 | | } |
537 | | // 0x03: bitstring |
538 | | BerTag::BitString => { |
539 | 4.76k | custom_check!(i, constructed, BerError::Unsupported)?; // XXX valid in BER (8.6.3) |
540 | 3.12k | let len = len.primitive()?; |
541 | 3.12k | ber_read_content_bitstring(i, len) |
542 | | } |
543 | | // 0x04: octetstring |
544 | | BerTag::OctetString => { |
545 | 9.85k | custom_check!(i, constructed, BerError::Unsupported)?; // XXX valid in BER (8.7.1) |
546 | 8.37k | let len = len.primitive()?; |
547 | 8.37k | ber_read_content_octetstring(i, len) |
548 | | } |
549 | | // 0x05: null |
550 | | BerTag::Null => { |
551 | 3.39k | custom_check!(i, constructed, BerError::ConstructUnexpected)?; |
552 | 2.26k | let len = len.primitive()?; |
553 | 2.26k | custom_check!(i, len != 0, BerError::InvalidLength)?; |
554 | 1.55k | ber_read_content_null(i) |
555 | | } |
556 | | // 0x06: object identifier |
557 | | BerTag::Oid => { |
558 | 39.2k | custom_check!(i, constructed, BerError::ConstructUnexpected)?; // forbidden in 8.19.1 |
559 | 37.9k | let len = len.primitive()?; |
560 | 37.9k | ber_read_content_oid(i, len) |
561 | | } |
562 | | // 0x07: object descriptor - Alias for GraphicString with a different |
563 | | // implicit tag, see below |
564 | | BerTag::ObjDescriptor => { |
565 | 3.26k | custom_check!(i, constructed, BerError::Unsupported)?; // XXX valid in BER (8.21) |
566 | 2.45k | let len = len.primitive()?; |
567 | 2.45k | ber_read_content_objectdescriptor(i, len) |
568 | | } |
569 | | // 0x0a: enumerated |
570 | | BerTag::Enumerated => { |
571 | 12.5k | custom_check!(i, constructed, BerError::ConstructUnexpected)?; // forbidden in 8.4 |
572 | 11.8k | let len = len.primitive()?; |
573 | 11.8k | ber_read_content_enum(i, len) |
574 | | } |
575 | | // 0x0c: UTF8String - Unicode encoded with the UTF-8 charset (ISO/IEC |
576 | | // 10646-1, Annex D) |
577 | | BerTag::Utf8String => { |
578 | 4.95k | custom_check!(i, constructed, BerError::Unsupported)?; // XXX valid in BER (8.21) |
579 | 3.15k | let len = len.primitive()?; |
580 | 3.15k | ber_read_content_utf8string(i, len) |
581 | | } |
582 | | // 0x0d: relative object identified |
583 | | BerTag::RelativeOid => { |
584 | 7.48k | custom_check!(i, constructed, BerError::ConstructUnexpected)?; |
585 | 6.62k | let len = len.primitive()?; |
586 | 6.62k | ber_read_content_relativeoid(i, len) |
587 | | } |
588 | | // 0x10: sequence |
589 | | BerTag::Sequence => { |
590 | 112k | custom_check!(i, !constructed, BerError::ConstructExpected)?; |
591 | 111k | ber_read_content_sequence(i, len, max_depth) |
592 | | } |
593 | | // 0x11: set |
594 | | BerTag::Set => { |
595 | 76.8k | custom_check!(i, !constructed, BerError::ConstructExpected)?; |
596 | 75.4k | ber_read_content_set(i, len, max_depth) |
597 | | } |
598 | | // 0x12: numericstring - ASCII string with digits an spaces only |
599 | | BerTag::NumericString => { |
600 | 9.28k | custom_check!(i, constructed, BerError::Unsupported)?; // XXX valid in BER (8.21) |
601 | 8.27k | let len = len.primitive()?; |
602 | 8.27k | ber_read_content_numericstring(i, len) |
603 | | } |
604 | | // 0x13: printablestring - ASCII string with certain printable |
605 | | // characters only (specified in Table 10 of X.680) |
606 | | BerTag::PrintableString => { |
607 | 7.65k | custom_check!(i, constructed, BerError::Unsupported)?; // XXX valid in BER (8.21) |
608 | 6.30k | let len = len.primitive()?; |
609 | 6.30k | ber_read_content_printablestring(i, len) |
610 | | } |
611 | | // 0x14: t61string - ISO 2022 string with a Teletex (T.61) charset, |
612 | | // ASCII is possible but only when explicit escaped, as by default |
613 | | // the G0 character range (0x20-0x7f) will match the graphic character |
614 | | // set. https://en.wikipedia.org/wiki/ITU_T.61 |
615 | | BerTag::T61String => { |
616 | 5.42k | custom_check!(i, constructed, BerError::Unsupported)?; // XXX valid in BER (8.21) |
617 | 4.05k | let len = len.primitive()?; |
618 | 4.05k | ber_read_content_t61string(i, len) |
619 | | } |
620 | | // 0x15: videotexstring - ISO 2022 string with a Videotex (T.100/T.101) |
621 | | // charset, excluding ASCII. https://en.wikipedia.org/wiki/Videotex_character_set |
622 | | BerTag::VideotexString => { |
623 | 8.08k | custom_check!(i, constructed, BerError::Unsupported)?; // XXX valid in BER (8.21) |
624 | 7.06k | let len = len.primitive()?; |
625 | 7.06k | ber_read_content_videotexstring(i, len) |
626 | | } |
627 | | // 0x16: ia5string - ASCII string |
628 | | BerTag::Ia5String => { |
629 | 9.54k | custom_check!(i, constructed, BerError::Unsupported)?; // XXX valid in BER (8.21) |
630 | 7.74k | let len = len.primitive()?; |
631 | 7.74k | ber_read_content_ia5string(i, len) |
632 | | } |
633 | | // 0x17: utctime - Alias for a VisibleString with a different implicit |
634 | | // tag, see below |
635 | | BerTag::UtcTime => { |
636 | 4.42k | let len = len.primitive()?; |
637 | 3.82k | ber_read_content_utctime(i, len) |
638 | | } |
639 | | // 0x18: generalizedtime - Alias for a VisibleString with a different |
640 | | // implicit tag, see below |
641 | | BerTag::GeneralizedTime => { |
642 | 110k | let len = len.primitive()?; |
643 | 109k | ber_read_content_generalizedtime(i, len) |
644 | | } |
645 | | // 0x19: graphicstring - Generic ISO 2022 container with explicit |
646 | | // escape sequences, without control characters |
647 | | BerTag::GraphicString => { |
648 | 2.04k | custom_check!(i, constructed, BerError::Unsupported)?; // XXX valid in BER (8.21) |
649 | 1.01k | let len = len.primitive()?; |
650 | 1.01k | ber_read_content_graphicstring(i, len) |
651 | | } |
652 | | // 0x1a: visiblestring - ASCII string with no control characters except |
653 | | // SPACE |
654 | | BerTag::VisibleString => { |
655 | 4.54k | custom_check!(i, constructed, BerError::Unsupported)?; // XXX valid in BER (8.21) |
656 | 3.98k | let len = len.primitive()?; |
657 | 3.98k | ber_read_content_visiblestring(i, len) |
658 | | } |
659 | | // 0x1b: generalstring - Generic ISO 2022 container with explicit |
660 | | // escape sequences |
661 | | BerTag::GeneralString => { |
662 | 135k | custom_check!(i, constructed, BerError::Unsupported)?; // XXX valid in BER (8.21) |
663 | 134k | let len = len.primitive()?; |
664 | 134k | ber_read_content_generalstring(i, len) |
665 | | } |
666 | | // 0x1e: bmpstring - Unicode encoded with the UCS-2 big-endian charset |
667 | | // (ISO/IEC 10646-1, section 13.1), restricted to the BMP (Basic |
668 | | // Multilingual Plane) except certain control cahracters |
669 | | BerTag::BmpString => { |
670 | 6.79k | custom_check!(i, constructed, BerError::Unsupported)?; // XXX valid in BER (8.21) |
671 | 5.89k | let len = len.primitive()?; |
672 | 5.89k | ber_read_content_bmpstring(i, len) |
673 | | } |
674 | | // 0x1c: universalstring - Unicode encoded with the UCS-4 big-endian |
675 | | // charset (ISO/IEC 10646-1, section 13.2) |
676 | | BerTag::UniversalString => { |
677 | 2.28k | custom_check!(i, constructed, BerError::Unsupported)?; // XXX valid in BER (8.21) |
678 | 1.57k | let len = len.primitive()?; |
679 | 1.57k | ber_read_content_universalstring(i, len) |
680 | | } |
681 | | // all unknown values |
682 | 19.7k | _ => Err(Err::Error(BerError::UnknownTag)), |
683 | | } |
684 | 1.38M | } |
685 | | |
686 | | /// Parse the next bytes as the content of a BER object (combinator, header reference) |
687 | | /// |
688 | | /// Content type is *not* checked to match tag, caller is responsible of providing the correct tag |
689 | | /// |
690 | | /// Caller is also responsible to check if parsing function consumed the expected number of |
691 | | /// bytes (`header.len`). |
692 | | /// |
693 | | /// The arguments of the parse function are: `(input, ber_object_header, max_recursion)`. |
694 | | /// |
695 | | /// This function differs from [`parse_ber_content2`](fn.parse_ber_content2.html) because it passes |
696 | | /// the BER object header by reference (required for ex. by `parse_ber_implicit`). |
697 | | /// |
698 | | /// Example: manually parsing header and content |
699 | | /// |
700 | | /// ``` |
701 | | /// # use der_parser::ber::*; |
702 | | /// # |
703 | | /// # let bytes = &[0x02, 0x03, 0x01, 0x00, 0x01]; |
704 | | /// let (i, header) = ber_read_element_header(bytes).expect("parsing failed"); |
705 | | /// let (rem, content) = parse_ber_content(header.tag)(i, &header, MAX_RECURSION) |
706 | | /// .expect("parsing failed"); |
707 | | /// # |
708 | | /// # assert_eq!(header.tag, BerTag::Integer); |
709 | | /// ``` |
710 | 0 | pub fn parse_ber_content<'a>( |
711 | 0 | tag: BerTag, |
712 | 0 | ) -> impl Fn(&'a [u8], &'_ BerObjectHeader, usize) -> BerResult<'a, BerObjectContent<'a>> { |
713 | 0 | move |i: &[u8], hdr: &BerObjectHeader, max_recursion: usize| { |
714 | 0 | ber_read_element_content_as(i, tag, hdr.len, hdr.is_constructed(), max_recursion) |
715 | 0 | } |
716 | 0 | } |
717 | | |
718 | | /// Parse the next bytes as the content of a BER object (combinator, owned header) |
719 | | /// |
720 | | /// Content type is *not* checked to match tag, caller is responsible of providing the correct tag |
721 | | /// |
722 | | /// Caller is also responsible to check if parsing function consumed the expected number of |
723 | | /// bytes (`header.len`). |
724 | | /// |
725 | | /// The arguments of the parse function are: `(input, ber_object_header, max_recursion)`. |
726 | | /// |
727 | | /// This function differs from [`parse_ber_content`](fn.parse_ber_content.html) because it passes |
728 | | /// an owned BER object header (required for ex. by `parse_ber_tagged_implicit_g`). |
729 | | /// |
730 | | /// Example: manually parsing header and content |
731 | | /// |
732 | | /// ``` |
733 | | /// # use der_parser::ber::*; |
734 | | /// # |
735 | | /// # let bytes = &[0x02, 0x03, 0x01, 0x00, 0x01]; |
736 | | /// let (i, header) = ber_read_element_header(bytes).expect("parsing failed"); |
737 | | /// let (rem, content) = parse_ber_content(header.tag)(i, &header, MAX_RECURSION) |
738 | | /// .expect("parsing failed"); |
739 | | /// # |
740 | | /// # assert_eq!(header.tag, BerTag::Integer); |
741 | | /// ``` |
742 | 0 | pub fn parse_ber_content2<'a>( |
743 | 0 | tag: BerTag, |
744 | 0 | ) -> impl Fn(&'a [u8], BerObjectHeader<'a>, usize) -> BerResult<'a, BerObjectContent<'a>> { |
745 | 0 | move |i: &[u8], hdr: BerObjectHeader, max_recursion: usize| { |
746 | 0 | ber_read_element_content_as(i, tag, hdr.len, hdr.is_constructed(), max_recursion) |
747 | 0 | } |
748 | 0 | } |
749 | | |
750 | | /// Parse a BER object, expecting a value with specified tag |
751 | | /// |
752 | | /// The object is parsed recursively, with a maximum depth of `MAX_RECURSION`. |
753 | | /// |
754 | | /// ### Example |
755 | | /// |
756 | | /// ``` |
757 | | /// use der_parser::ber::BerTag; |
758 | | /// use der_parser::ber::parse_ber_with_tag; |
759 | | /// |
760 | | /// let bytes = &[0x02, 0x03, 0x01, 0x00, 0x01]; |
761 | | /// let (_, obj) = parse_ber_with_tag(bytes, BerTag::Integer).expect("parsing failed"); |
762 | | /// |
763 | | /// assert_eq!(obj.header.tag, BerTag::Integer); |
764 | | /// ``` |
765 | 157k | pub fn parse_ber_with_tag<Tag: Into<BerTag>>(i: &[u8], tag: Tag) -> BerResult { |
766 | 157k | let tag = tag.into(); |
767 | 157k | let (i, hdr) = ber_read_element_header(i)?; |
768 | 149k | if hdr.tag != tag { |
769 | 126k | return Err(nom::Err::Error(BerError::InvalidTag)); |
770 | 22.9k | } |
771 | 17.1k | let (i, content) = |
772 | 22.9k | ber_read_element_content_as(i, hdr.tag, hdr.len, hdr.is_constructed(), MAX_RECURSION)?; |
773 | 17.1k | Ok((i, BerObject::from_header_and_content(hdr, content))) |
774 | 157k | } der_parser::ber::parser::parse_ber_with_tag::<der_parser::ber::ber::BerTag> Line | Count | Source | 765 | 206 | pub fn parse_ber_with_tag<Tag: Into<BerTag>>(i: &[u8], tag: Tag) -> BerResult { | 766 | 206 | let tag = tag.into(); | 767 | 206 | let (i, hdr) = ber_read_element_header(i)?; | 768 | 12 | if hdr.tag != tag { | 769 | 0 | return Err(nom::Err::Error(BerError::InvalidTag)); | 770 | 12 | } | 771 | 12 | let (i, content) = | 772 | 12 | ber_read_element_content_as(i, hdr.tag, hdr.len, hdr.is_constructed(), MAX_RECURSION)?; | 773 | 12 | Ok((i, BerObject::from_header_and_content(hdr, content))) | 774 | 206 | } |
der_parser::ber::parser::parse_ber_with_tag::<der_parser::ber::ber::BerTag> Line | Count | Source | 765 | 157k | pub fn parse_ber_with_tag<Tag: Into<BerTag>>(i: &[u8], tag: Tag) -> BerResult { | 766 | 157k | let tag = tag.into(); | 767 | 157k | let (i, hdr) = ber_read_element_header(i)?; | 768 | 149k | if hdr.tag != tag { | 769 | 126k | return Err(nom::Err::Error(BerError::InvalidTag)); | 770 | 22.9k | } | 771 | 17.1k | let (i, content) = | 772 | 22.9k | ber_read_element_content_as(i, hdr.tag, hdr.len, hdr.is_constructed(), MAX_RECURSION)?; | 773 | 17.1k | Ok((i, BerObject::from_header_and_content(hdr, content))) | 774 | 157k | } |
|
775 | | |
776 | | /// Read end of content marker |
777 | | #[inline] |
778 | 157k | pub fn parse_ber_endofcontent(i: &[u8]) -> BerResult { |
779 | 157k | parse_ber_with_tag(i, BerTag::EndOfContent) |
780 | 157k | } |
781 | | |
782 | | /// Read a boolean value |
783 | | /// |
784 | | /// The encoding of a boolean value shall be primitive. The contents octets shall consist of a |
785 | | /// single octet. |
786 | | /// |
787 | | /// If the boolean value is FALSE, the octet shall be zero. |
788 | | /// If the boolean value is TRUE, the octet shall be one byte, and have all bits set to one (0xff). |
789 | | #[inline] |
790 | 0 | pub fn parse_ber_bool(i: &[u8]) -> BerResult { |
791 | 0 | parse_ber_with_tag(i, BerTag::Boolean) |
792 | 0 | } |
793 | | |
794 | | /// Read an integer value |
795 | | /// |
796 | | /// The encoding of a boolean value shall be primitive. The contents octets shall consist of one or |
797 | | /// more octets. |
798 | | /// |
799 | | /// To access the content, use the [`as_u64`](struct.BerObject.html#method.as_u64), |
800 | | /// [`as_u32`](struct.BerObject.html#method.as_u32), |
801 | | /// [`as_biguint`](struct.BerObject.html#method.as_biguint) or |
802 | | /// [`as_bigint`](struct.BerObject.html#method.as_bigint) methods. |
803 | | /// Remember that a BER integer has unlimited size, so these methods return `Result` or `Option` |
804 | | /// objects. |
805 | | /// |
806 | | /// # Examples |
807 | | /// |
808 | | /// ```rust |
809 | | /// # extern crate nom; |
810 | | /// # use der_parser::ber::parse_ber_integer; |
811 | | /// # use der_parser::ber::{BerObject,BerObjectContent}; |
812 | | /// let empty = &b""[..]; |
813 | | /// let bytes = [0x02, 0x03, 0x01, 0x00, 0x01]; |
814 | | /// let expected = BerObject::from_obj(BerObjectContent::Integer(b"\x01\x00\x01")); |
815 | | /// assert_eq!( |
816 | | /// parse_ber_integer(&bytes), |
817 | | /// Ok((empty, expected)) |
818 | | /// ); |
819 | | /// ``` |
820 | | #[inline] |
821 | 0 | pub fn parse_ber_integer(i: &[u8]) -> BerResult { |
822 | 0 | parse_ber_with_tag(i, BerTag::Integer) |
823 | 0 | } |
824 | | |
825 | | /// Read an bitstring value |
826 | | #[inline] |
827 | 0 | pub fn parse_ber_bitstring(i: &[u8]) -> BerResult { |
828 | 0 | parse_ber_with_tag(i, BerTag::BitString) |
829 | 0 | } |
830 | | |
831 | | /// Read an octetstring value |
832 | | #[inline] |
833 | 206 | pub fn parse_ber_octetstring(i: &[u8]) -> BerResult { |
834 | 206 | parse_ber_with_tag(i, BerTag::OctetString) |
835 | 206 | } |
836 | | |
837 | | /// Read a null value |
838 | | #[inline] |
839 | 0 | pub fn parse_ber_null(i: &[u8]) -> BerResult { |
840 | 0 | parse_ber_with_tag(i, BerTag::Null) |
841 | 0 | } |
842 | | |
843 | | /// Read an object identifier value |
844 | | #[inline] |
845 | 0 | pub fn parse_ber_oid(i: &[u8]) -> BerResult { |
846 | 0 | parse_ber_with_tag(i, BerTag::Oid) |
847 | 0 | } |
848 | | |
849 | | /// Read an enumerated value |
850 | | #[inline] |
851 | 0 | pub fn parse_ber_enum(i: &[u8]) -> BerResult { |
852 | 0 | parse_ber_with_tag(i, BerTag::Enumerated) |
853 | 0 | } |
854 | | |
855 | | /// Read a UTF-8 string value. The encoding is checked. |
856 | | #[inline] |
857 | 0 | pub fn parse_ber_utf8string(i: &[u8]) -> BerResult { |
858 | 0 | parse_ber_with_tag(i, BerTag::Utf8String) |
859 | 0 | } |
860 | | |
861 | | /// Read a relative object identifier value |
862 | | #[inline] |
863 | 0 | pub fn parse_ber_relative_oid(i: &[u8]) -> BerResult { |
864 | 0 | parse_ber_with_tag(i, BerTag::RelativeOid) |
865 | 0 | } |
866 | | |
867 | | /// Parse a sequence of BER elements |
868 | | /// |
869 | | /// Read a sequence of BER objects, without any constraint on the types. |
870 | | /// Sequence is parsed recursively, so if structured elements are found, they are parsed using the |
871 | | /// same function. |
872 | | /// |
873 | | /// To read a specific sequence of objects (giving the expected types), use the |
874 | | /// [`parse_ber_sequence_defined`](macro.parse_ber_sequence_defined.html) macro. |
875 | | #[inline] |
876 | 0 | pub fn parse_ber_sequence(i: &[u8]) -> BerResult { |
877 | 0 | parse_ber_with_tag(i, BerTag::Sequence) |
878 | 0 | } |
879 | | |
880 | | /// Parse a set of BER elements |
881 | | /// |
882 | | /// Read a set of BER objects, without any constraint on the types. |
883 | | /// Set is parsed recursively, so if structured elements are found, they are parsed using the |
884 | | /// same function. |
885 | | /// |
886 | | /// To read a specific set of objects (giving the expected types), use the |
887 | | /// [`parse_ber_set_defined`](macro.parse_ber_set_defined.html) macro. |
888 | | #[inline] |
889 | 0 | pub fn parse_ber_set(i: &[u8]) -> BerResult { |
890 | 0 | parse_ber_with_tag(i, BerTag::Set) |
891 | 0 | } |
892 | | |
893 | | /// Read a numeric string value. The content is verified to |
894 | | /// contain only digits and spaces. |
895 | | #[inline] |
896 | 0 | pub fn parse_ber_numericstring(i: &[u8]) -> BerResult { |
897 | 0 | parse_ber_with_tag(i, BerTag::NumericString) |
898 | 0 | } |
899 | | |
900 | | /// Read a visible string value. The content is verified to |
901 | | /// contain only the allowed characters. |
902 | | #[inline] |
903 | 0 | pub fn parse_ber_visiblestring(i: &[u8]) -> BerResult { |
904 | 0 | parse_ber_with_tag(i, BerTag::VisibleString) |
905 | 0 | } |
906 | | |
907 | | /// Read a printable string value. The content is verified to |
908 | | /// contain only the allowed characters. |
909 | | #[inline] |
910 | 0 | pub fn parse_ber_printablestring(i: &[u8]) -> BerResult { |
911 | 0 | parse_ber_with_tag(i, BerTag::PrintableString) |
912 | 0 | } |
913 | | |
914 | | /// Read a T61 string value |
915 | | #[inline] |
916 | 0 | pub fn parse_ber_t61string(i: &[u8]) -> BerResult { |
917 | 0 | parse_ber_with_tag(i, BerTag::T61String) |
918 | 0 | } |
919 | | |
920 | | /// Read a Videotex string value |
921 | | #[inline] |
922 | 0 | pub fn parse_ber_videotexstring(i: &[u8]) -> BerResult { |
923 | 0 | parse_ber_with_tag(i, BerTag::VideotexString) |
924 | 0 | } |
925 | | |
926 | | /// Read an IA5 string value. The content is verified to be ASCII. |
927 | | #[inline] |
928 | 0 | pub fn parse_ber_ia5string(i: &[u8]) -> BerResult { |
929 | 0 | parse_ber_with_tag(i, BerTag::Ia5String) |
930 | 0 | } |
931 | | |
932 | | /// Read an UTC time value |
933 | | #[inline] |
934 | 0 | pub fn parse_ber_utctime(i: &[u8]) -> BerResult { |
935 | 0 | parse_ber_with_tag(i, BerTag::UtcTime) |
936 | 0 | } |
937 | | |
938 | | /// Read a Generalized time value |
939 | | #[inline] |
940 | 0 | pub fn parse_ber_generalizedtime(i: &[u8]) -> BerResult { |
941 | 0 | parse_ber_with_tag(i, BerTag::GeneralizedTime) |
942 | 0 | } |
943 | | |
944 | | /// Read an ObjectDescriptor value |
945 | | #[inline] |
946 | 0 | pub fn parse_ber_objectdescriptor(i: &[u8]) -> BerResult { |
947 | 0 | parse_ber_with_tag(i, BerTag::ObjDescriptor) |
948 | 0 | } |
949 | | |
950 | | /// Read a GraphicString value |
951 | | #[inline] |
952 | 0 | pub fn parse_ber_graphicstring(i: &[u8]) -> BerResult { |
953 | 0 | parse_ber_with_tag(i, BerTag::GraphicString) |
954 | 0 | } |
955 | | |
956 | | /// Read a GeneralString value |
957 | | #[inline] |
958 | 0 | pub fn parse_ber_generalstring(i: &[u8]) -> BerResult { |
959 | 0 | parse_ber_with_tag(i, BerTag::GeneralString) |
960 | 0 | } |
961 | | |
962 | | /// Read a BmpString value |
963 | | #[inline] |
964 | 0 | pub fn parse_ber_bmpstring(i: &[u8]) -> BerResult { |
965 | 0 | parse_ber_with_tag(i, BerTag::BmpString) |
966 | 0 | } |
967 | | |
968 | | /// Read a UniversalString value |
969 | | #[inline] |
970 | 0 | pub fn parse_ber_universalstring(i: &[u8]) -> BerResult { |
971 | 0 | parse_ber_with_tag(i, BerTag::UniversalString) |
972 | 0 | } |
973 | | |
974 | | /// Parse an optional tagged object, applying function to get content |
975 | | /// |
976 | | /// This function returns a `BerObject`, trying to read content as generic BER objects. |
977 | | /// If parsing failed, return an optional object containing `None`. |
978 | | /// |
979 | | /// To support other return or error types, use |
980 | | /// [parse_ber_tagged_explicit_g](fn.parse_ber_tagged_explicit_g.html) |
981 | | /// |
982 | | /// This function will never fail: if parsing content failed, the BER value `Optional(None)` is |
983 | | /// returned. |
984 | 0 | pub fn parse_ber_explicit_optional<F>(i: &[u8], tag: BerTag, f: F) -> BerResult |
985 | 0 | where |
986 | 0 | F: Fn(&[u8]) -> BerResult, |
987 | | { |
988 | 0 | parse_ber_optional(parse_ber_tagged_explicit_g(tag, |content, hdr| { |
989 | 0 | let (rem, obj) = f(content)?; |
990 | 0 | let content = BerObjectContent::Tagged(hdr.class, hdr.tag, Box::new(obj)); |
991 | 0 | let tagged = BerObject::from_header_and_content(hdr, content); |
992 | 0 | Ok((rem, tagged)) |
993 | 0 | }))(i) |
994 | 0 | } |
995 | | |
996 | | /// Parse an implicit tagged object, applying function to read content |
997 | | /// |
998 | | /// Note: unlike explicit tagged functions, the callback must be a *content* parsing function, |
999 | | /// often based on the [`parse_ber_content`](fn.parse_ber_content.html) combinator. |
1000 | | /// |
1001 | | /// The built object will use the original header (and tag), so the content may not match the tag |
1002 | | /// value. |
1003 | | /// |
1004 | | /// For a combinator version, see [parse_ber_tagged_implicit](fn.parse_ber_tagged_implicit.html). |
1005 | | /// |
1006 | | /// For a generic version (different output and error types), see |
1007 | | /// [parse_ber_tagged_implicit_g](fn.parse_ber_tagged_implicit_g.html). |
1008 | | /// |
1009 | | /// # Examples |
1010 | | /// |
1011 | | /// The following parses `[3] IMPLICIT INTEGER` into a `BerObject`: |
1012 | | /// |
1013 | | /// ```rust |
1014 | | /// # use der_parser::ber::*; |
1015 | | /// # use der_parser::error::BerResult; |
1016 | | /// # |
1017 | | /// fn parse_int_implicit(i:&[u8]) -> BerResult<BerObject> { |
1018 | | /// parse_ber_implicit( |
1019 | | /// i, |
1020 | | /// 3, |
1021 | | /// parse_ber_content(BerTag::Integer), |
1022 | | /// ) |
1023 | | /// } |
1024 | | /// |
1025 | | /// # let bytes = &[0x83, 0x03, 0x01, 0x00, 0x01]; |
1026 | | /// let res = parse_int_implicit(bytes); |
1027 | | /// # match res { |
1028 | | /// # Ok((rem, content)) => { |
1029 | | /// # assert!(rem.is_empty()); |
1030 | | /// # assert_eq!(content.as_u32(), Ok(0x10001)); |
1031 | | /// # }, |
1032 | | /// # _ => assert!(false) |
1033 | | /// # } |
1034 | | /// ``` |
1035 | | #[inline] |
1036 | 0 | pub fn parse_ber_implicit<'a, Tag, F>(i: &'a [u8], tag: Tag, f: F) -> BerResult<'a> |
1037 | 0 | where |
1038 | 0 | F: Fn(&'a [u8], &'_ BerObjectHeader, usize) -> BerResult<'a, BerObjectContent<'a>>, |
1039 | 0 | Tag: Into<BerTag>, |
1040 | | { |
1041 | 0 | parse_ber_tagged_implicit(tag, f)(i) |
1042 | 0 | } |
1043 | | |
1044 | | /// Combinator for building optional BER values |
1045 | | /// |
1046 | | /// To read optional BER values, it is to use the nom `opt()` combinator. However, this results in |
1047 | | /// a `Option<BerObject>` and prevents using some functions from this crate (the generic functions |
1048 | | /// can still be used). |
1049 | | /// |
1050 | | /// This combinator is used when parsing BER values, while keeping `BerObject` output only. |
1051 | | /// |
1052 | | /// This function will never fail: if parsing content failed, the BER value `Optional(None)` is |
1053 | | /// returned. |
1054 | | /// |
1055 | | /// ### Example |
1056 | | /// |
1057 | | /// ``` |
1058 | | /// # use der_parser::ber::*; |
1059 | | /// # |
1060 | | /// let bytes = &[0x02, 0x03, 0x01, 0x00, 0x01]; |
1061 | | /// let mut parser = parse_ber_optional(parse_ber_integer); |
1062 | | /// let (_, obj) = parser(bytes).expect("parsing failed"); |
1063 | | /// |
1064 | | /// assert_eq!(obj.header.tag, BerTag::Integer); |
1065 | | /// assert!(obj.as_optional().is_ok()); |
1066 | | /// ``` |
1067 | 0 | pub fn parse_ber_optional<'a, F>(mut f: F) -> impl FnMut(&'a [u8]) -> BerResult<'a> |
1068 | 0 | where |
1069 | 0 | F: FnMut(&'a [u8]) -> BerResult<'a>, |
1070 | | { |
1071 | 0 | move |i: &[u8]| { |
1072 | 0 | let res = f(i); |
1073 | 0 | match res { |
1074 | 0 | Ok((rem, inner)) => { |
1075 | 0 | let opt = BerObject::from_header_and_content( |
1076 | 0 | inner.header.clone(), |
1077 | 0 | BerObjectContent::Optional(Some(Box::new(inner))), |
1078 | | ); |
1079 | 0 | Ok((rem, opt)) |
1080 | | } |
1081 | 0 | Err(_) => Ok((i, BerObject::from_obj(BerObjectContent::Optional(None)))), |
1082 | | } |
1083 | 0 | } |
1084 | 0 | } |
1085 | | |
1086 | | /// Parse BER object and try to decode it as a 32-bits signed integer |
1087 | | /// |
1088 | | /// Return `IntegerTooLarge` if object is an integer, but can not be represented in the target |
1089 | | /// integer type. |
1090 | | #[inline] |
1091 | 0 | pub fn parse_ber_i32(i: &[u8]) -> BerResult<i32> { |
1092 | 0 | let (rem, ber) = parse_ber_integer(i)?; |
1093 | 0 | let int = ber.as_i32().map_err(nom::Err::Error)?; |
1094 | 0 | Ok((rem, int)) |
1095 | 0 | } |
1096 | | |
1097 | | /// Parse BER object and try to decode it as a 64-bits signed integer |
1098 | | /// |
1099 | | /// Return `IntegerTooLarge` if object is an integer, but can not be represented in the target |
1100 | | /// integer type. |
1101 | | #[inline] |
1102 | 0 | pub fn parse_ber_i64(i: &[u8]) -> BerResult<i64> { |
1103 | 0 | let (rem, ber) = parse_ber_integer(i)?; |
1104 | 0 | let int = ber.as_i64().map_err(nom::Err::Error)?; |
1105 | 0 | Ok((rem, int)) |
1106 | 0 | } |
1107 | | |
1108 | | /// Parse BER object and try to decode it as a 32-bits unsigned integer |
1109 | | /// |
1110 | | /// Return `IntegerTooLarge` if object is an integer, but can not be represented in the target |
1111 | | /// integer type. |
1112 | | #[inline] |
1113 | 0 | pub fn parse_ber_u32(i: &[u8]) -> BerResult<u32> { |
1114 | 0 | let (rem, ber) = parse_ber_integer(i)?; |
1115 | 0 | let int = ber.as_u32().map_err(nom::Err::Error)?; |
1116 | 0 | Ok((rem, int)) |
1117 | 0 | } |
1118 | | |
1119 | | /// Parse BER object and try to decode it as a 64-bits unsigned integer |
1120 | | /// |
1121 | | /// Return `IntegerTooLarge` if object is an integer, but can not be represented in the target |
1122 | | /// integer type. |
1123 | | #[inline] |
1124 | 0 | pub fn parse_ber_u64(i: &[u8]) -> BerResult<u64> { |
1125 | 0 | let (rem, ber) = parse_ber_integer(i)?; |
1126 | 0 | let int = ber.as_u64().map_err(nom::Err::Error)?; |
1127 | 0 | Ok((rem, int)) |
1128 | 0 | } |
1129 | | |
1130 | | /// Parse BER object and get content as slice |
1131 | | #[inline] |
1132 | 0 | pub fn parse_ber_slice<Tag: Into<BerTag>>(i: &[u8], tag: Tag) -> BerResult<&[u8]> { |
1133 | 0 | let tag = tag.into(); |
1134 | 0 | parse_ber_container(move |content, hdr| { |
1135 | 0 | if hdr.tag != tag { |
1136 | 0 | return Err(Err::Error(BerError::InvalidTag)); |
1137 | 0 | } |
1138 | 0 | Ok((&b""[..], content)) |
1139 | 0 | })(i) |
1140 | 0 | } |
1141 | | |
1142 | | /// Helper combinator, to create a parser with a maximum parsing depth |
1143 | | #[inline] |
1144 | 186k | pub(crate) fn r_parse_ber(max_depth: usize) -> impl Fn(&[u8]) -> BerResult { |
1145 | 461k | move |i: &[u8]| parse_ber_recursive(i, max_depth) |
1146 | 186k | } |
1147 | | |
1148 | | /// Parse BER object recursively, specifying the maximum recursion depth |
1149 | | /// |
1150 | | /// Return a tuple containing the remaining (unparsed) bytes and the BER Object, or an error. |
1151 | | /// |
1152 | | /// ### Example |
1153 | | /// |
1154 | | /// ``` |
1155 | | /// use der_parser::ber::{parse_ber_recursive, BerTag}; |
1156 | | /// |
1157 | | /// let bytes = &[0x02, 0x03, 0x01, 0x00, 0x01]; |
1158 | | /// let (_, obj) = parse_ber_recursive(bytes, 1).expect("parsing failed"); |
1159 | | /// |
1160 | | /// assert_eq!(obj.header.tag, BerTag::Integer); |
1161 | | /// ``` |
1162 | 461k | pub fn parse_ber_recursive(i: &[u8], max_depth: usize) -> BerResult { |
1163 | 461k | custom_check!(i, max_depth == 0, BerError::BerMaxDepth)?; |
1164 | 461k | let (rem, hdr) = ber_read_element_header(i)?; |
1165 | 411k | if let BerSize::Definite(l) = hdr.len { |
1166 | 327k | custom_check!(i, l > MAX_OBJECT_SIZE, BerError::InvalidLength)?; |
1167 | 83.9k | } |
1168 | 410k | match hdr.class { |
1169 | 350k | BerClass::Universal => (), |
1170 | | BerClass::Private => { |
1171 | 25.2k | let (rem, content) = ber_get_object_content(rem, &hdr, max_depth)?; |
1172 | 22.4k | let content = BerObjectContent::Private(hdr.clone(), content); |
1173 | 22.4k | let obj = BerObject::from_header_and_content(hdr, content); |
1174 | 22.4k | return Ok((rem, obj)); |
1175 | | } |
1176 | | _ => { |
1177 | 34.6k | let (rem, content) = ber_get_object_content(rem, &hdr, max_depth)?; |
1178 | 28.4k | let content = BerObjectContent::Unknown(hdr.class, hdr.tag, content); |
1179 | 28.4k | let obj = BerObject::from_header_and_content(hdr, content); |
1180 | 28.4k | return Ok((rem, obj)); |
1181 | | } |
1182 | | } |
1183 | 350k | match ber_read_element_content_as(rem, hdr.tag, hdr.len, hdr.is_constructed(), max_depth) { |
1184 | 232k | Ok((rem, content)) => Ok((rem, BerObject::from_header_and_content(hdr, content))), |
1185 | | Err(Err::Error(BerError::UnknownTag)) => { |
1186 | 16.5k | let (rem, content) = ber_get_object_content(rem, &hdr, max_depth)?; |
1187 | 14.8k | let content = BerObjectContent::Unknown(hdr.class, hdr.tag, content); |
1188 | 14.8k | let obj = BerObject::from_header_and_content(hdr, content); |
1189 | 14.8k | Ok((rem, obj)) |
1190 | | } |
1191 | 101k | Err(e) => Err(e), |
1192 | | } |
1193 | 461k | } |
1194 | | |
1195 | | /// Parse BER object recursively |
1196 | | /// |
1197 | | /// Return a tuple containing the remaining (unparsed) bytes and the BER Object, or an error. |
1198 | | /// |
1199 | | /// *Note*: this is the same as calling `parse_ber_recursive` with `MAX_RECURSION`. |
1200 | | /// |
1201 | | /// ### Example |
1202 | | /// |
1203 | | /// ``` |
1204 | | /// use der_parser::ber::{parse_ber, BerTag}; |
1205 | | /// |
1206 | | /// let bytes = &[0x02, 0x03, 0x01, 0x00, 0x01]; |
1207 | | /// let (_, obj) = parse_ber(bytes).expect("parsing failed"); |
1208 | | /// |
1209 | | /// assert_eq!(obj.header.tag, BerTag::Integer); |
1210 | | /// ``` |
1211 | | #[inline] |
1212 | 0 | pub fn parse_ber(i: &[u8]) -> BerResult { |
1213 | 0 | parse_ber_recursive(i, MAX_RECURSION) |
1214 | 0 | } |
1215 | | |
1216 | | #[test] |
1217 | | fn test_numericstring() { |
1218 | | assert_eq!( |
1219 | | ber_read_content_numericstring(b" 0123 4495768 ", 15), |
1220 | | Ok(( |
1221 | | [].as_ref(), |
1222 | | BerObjectContent::NumericString(" 0123 4495768 ") |
1223 | | )), |
1224 | | ); |
1225 | | assert_eq!( |
1226 | | ber_read_content_numericstring(b"", 0), |
1227 | | Ok(([].as_ref(), BerObjectContent::NumericString(""))), |
1228 | | ); |
1229 | | assert!(ber_read_content_numericstring(b"123a", 4).is_err()); |
1230 | | } |
1231 | | |
1232 | | #[test] |
1233 | | fn text_visiblestring() { |
1234 | | assert_eq!( |
1235 | | ber_read_content_visiblestring(b"AZaz]09 '()+,-./:=?", 19), |
1236 | | Ok(( |
1237 | | [].as_ref(), |
1238 | | BerObjectContent::VisibleString("AZaz]09 '()+,-./:=?") |
1239 | | )), |
1240 | | ); |
1241 | | assert_eq!( |
1242 | | ber_read_content_visiblestring(b"", 0), |
1243 | | Ok(([].as_ref(), BerObjectContent::VisibleString(""))), |
1244 | | ); |
1245 | | assert!(ber_read_content_visiblestring(b"\n", 1).is_err()); |
1246 | | } |
1247 | | |
1248 | | #[test] |
1249 | | fn test_printablestring() { |
1250 | | assert_eq!( |
1251 | | ber_read_content_printablestring(b"AZaz09 '()+,-./:=?", 18), |
1252 | | Ok(( |
1253 | | [].as_ref(), |
1254 | | BerObjectContent::PrintableString("AZaz09 '()+,-./:=?") |
1255 | | )), |
1256 | | ); |
1257 | | assert_eq!( |
1258 | | ber_read_content_printablestring(b"", 0), |
1259 | | Ok(([].as_ref(), BerObjectContent::PrintableString(""))), |
1260 | | ); |
1261 | | assert!(ber_read_content_printablestring(b"]\n", 2).is_err()); |
1262 | | } |
1263 | | |
1264 | | #[test] |
1265 | | fn test_ia5string() { |
1266 | | assert_eq!( |
1267 | | ber_read_content_ia5string(b"AZaz\n09 '()+,-./:=?[]{}\0\n", 25), |
1268 | | Ok(( |
1269 | | [].as_ref(), |
1270 | | BerObjectContent::IA5String("AZaz\n09 '()+,-./:=?[]{}\0\n") |
1271 | | )), |
1272 | | ); |
1273 | | assert_eq!( |
1274 | | ber_read_content_ia5string(b"", 0), |
1275 | | Ok(([].as_ref(), BerObjectContent::IA5String(""))), |
1276 | | ); |
1277 | | assert!(ber_read_content_ia5string(b"\xFF", 1).is_err()); |
1278 | | } |
1279 | | |
1280 | | #[test] |
1281 | | fn test_utf8string() { |
1282 | | assert_eq!( |
1283 | | ber_read_content_utf8string("AZaz09 '()+,-./:=?[]{}\0\nüÜ".as_ref(), 28), |
1284 | | Ok(( |
1285 | | [].as_ref(), |
1286 | | BerObjectContent::UTF8String("AZaz09 '()+,-./:=?[]{}\0\nüÜ") |
1287 | | )), |
1288 | | ); |
1289 | | assert_eq!( |
1290 | | ber_read_content_utf8string(b"", 0), |
1291 | | Ok(([].as_ref(), BerObjectContent::UTF8String(""))), |
1292 | | ); |
1293 | | assert!(ber_read_content_utf8string(b"\xe2\x28\xa1", 3).is_err()); |
1294 | | } |
1295 | | |
1296 | | #[test] |
1297 | | fn test_bitstring_to_u64() { |
1298 | | // ignored bits modulo 8 to 0 |
1299 | | let data = &hex_literal::hex!("0d 71 82"); |
1300 | | let r = bitstring_to_u64(8, &BitStringObject { data }); |
1301 | | assert_eq!(r, Ok(0x0d71)); |
1302 | | |
1303 | | // input too large to fit a 64-bits integer |
1304 | | let data = &hex_literal::hex!("0d 71 82 0e 73 72 76 6e 67 6e 62 6c 6e 2d 65 78 30 31"); |
1305 | | let r = bitstring_to_u64(0, &BitStringObject { data }); |
1306 | | assert!(r.is_err()); |
1307 | | |
1308 | | // test large number but with many ignored bits |
1309 | | let data = &hex_literal::hex!("0d 71 82 0e 73 72 76 6e 67 6e 62 6c 6e 2d 65 78 30 31"); |
1310 | | let r = bitstring_to_u64(130, &BitStringObject { data }); |
1311 | | // 2 = 130 % 8 |
1312 | | assert_eq!(r, Ok(0x0d71 >> 2)); |
1313 | | } |