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
ber_skip_object_content<'a>( i: &'a [u8], hdr: &BerObjectHeader, max_depth: usize, ) -> BerResult<'a, bool>18 pub(crate) fn ber_skip_object_content<'a>(
19 i: &'a [u8],
20 hdr: &BerObjectHeader,
21 max_depth: usize,
22 ) -> BerResult<'a, bool> {
23 if max_depth == 0 {
24 return Err(Err::Error(BerError::BerMaxDepth));
25 }
26 match hdr.len {
27 BerSize::Definite(l) => {
28 if l == 0 && hdr.tag == BerTag::EndOfContent {
29 return Ok((i, true));
30 }
31 let (i, _) = take(l)(i)?;
32 Ok((i, false))
33 }
34 BerSize::Indefinite => {
35 if hdr.is_primitive() {
36 return Err(Err::Error(BerError::ConstructExpected));
37 }
38 // read objects until EndOfContent (00 00)
39 // this is recursive
40 let mut i = i;
41 loop {
42 let (i2, header2) = ber_read_element_header(i)?;
43 let (i3, eoc) = ber_skip_object_content(i2, &header2, max_depth - 1)?;
44 if eoc {
45 // return false, since top object was not EndOfContent
46 return Ok((i3, false));
47 }
48 i = i3;
49 }
50 }
51 }
52 }
53
54 /// Read object raw content (bytes)
ber_get_object_content<'a>( i: &'a [u8], hdr: &BerObjectHeader, max_depth: usize, ) -> BerResult<'a, &'a [u8]>55 pub(crate) fn ber_get_object_content<'a>(
56 i: &'a [u8],
57 hdr: &BerObjectHeader,
58 max_depth: usize,
59 ) -> BerResult<'a, &'a [u8]> {
60 let start_i = i;
61 let (i, _) = ber_skip_object_content(i, hdr, max_depth)?;
62 let len = start_i.offset(i);
63 let (content, i) = start_i.split_at(len);
64 // if len is indefinite, there are 2 extra bytes for EOC
65 if hdr.len == BerSize::Indefinite {
66 let len = content.len();
67 assert!(len >= 2);
68 Ok((i, &content[..len - 2]))
69 } else {
70 Ok((i, content))
71 }
72 }
73
74 /// Try to parse input bytes as u64
75 #[inline]
bytes_to_u64(s: &[u8]) -> Result<u64, BerError>76 pub(crate) fn bytes_to_u64(s: &[u8]) -> Result<u64, BerError> {
77 let mut u: u64 = 0;
78 for &c in s {
79 if u & 0xff00_0000_0000_0000 != 0 {
80 return Err(BerError::IntegerTooLarge);
81 }
82 u <<= 8;
83 u |= u64::from(c);
84 }
85 Ok(u)
86 }
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]
bitstring_to_u64( padding_bits: usize, data: &BitStringObject, ) -> Result<u64, BerError>94 pub(crate) fn bitstring_to_u64(
95 padding_bits: usize,
96 data: &BitStringObject,
97 ) -> Result<u64, BerError> {
98 let raw_bytes = data.data;
99 let bit_size = (raw_bytes.len() * 8)
100 .checked_sub(padding_bits)
101 .ok_or(BerError::InvalidLength)?;
102 if bit_size > 64 {
103 return Err(BerError::IntegerTooLarge);
104 }
105 let padding_bits = padding_bits % 8;
106 let num_bytes = if bit_size % 8 > 0 {
107 (bit_size / 8) + 1
108 } else {
109 bit_size / 8
110 };
111 let mut resulting_integer: u64 = 0;
112 for &c in &raw_bytes[..num_bytes] {
113 resulting_integer <<= 8;
114 resulting_integer |= c as u64;
115 }
116 Ok(resulting_integer >> padding_bits)
117 }
118
parse_identifier(i: &[u8]) -> BerResult<(u8, u8, u32, &[u8])>119 pub(crate) fn parse_identifier(i: &[u8]) -> BerResult<(u8, u8, u32, &[u8])> {
120 if i.is_empty() {
121 Err(Err::Incomplete(Needed::new(1)))
122 } else {
123 let a = i[0] >> 6;
124 let b = if i[0] & 0b0010_0000 != 0 { 1 } else { 0 };
125 let mut c = u32::from(i[0] & 0b0001_1111);
126
127 let mut tag_byte_count = 1;
128
129 if c == 0x1f {
130 c = 0;
131 loop {
132 // Make sure we don't read past the end of our data.
133 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 custom_check!(i, tag_byte_count > 5, BerError::InvalidTag)?;
138
139 c = (c << 7) | (u32::from(i[tag_byte_count]) & 0x7f);
140 let done = i[tag_byte_count] & 0x80 == 0;
141 tag_byte_count += 1;
142 if done {
143 break;
144 }
145 }
146 }
147
148 let (raw_tag, rem) = i.split_at(tag_byte_count);
149
150 Ok((rem, (a, b, c, raw_tag)))
151 }
152 }
153
154 /// Return the MSB and the rest of the first byte, or an error
parse_ber_length_byte(i: &[u8]) -> BerResult<(u8, u8)>155 pub(crate) fn parse_ber_length_byte(i: &[u8]) -> BerResult<(u8, u8)> {
156 if i.is_empty() {
157 Err(Err::Incomplete(Needed::new(1)))
158 } else {
159 let a = i[0] >> 7;
160 let b = i[0] & 0b0111_1111;
161 Ok((&i[1..], (a, b)))
162 }
163 }
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 /// ```
ber_read_element_header(i: &[u8]) -> BerResult<BerObjectHeader>179 pub fn ber_read_element_header(i: &[u8]) -> BerResult<BerObjectHeader> {
180 let (i1, el) = parse_identifier(i)?;
181 let class = match BerClass::try_from(el.0) {
182 Ok(c) => c,
183 Err(_) => unreachable!(), // Cannot fail, we have read exactly 2 bits
184 };
185 let (i2, len) = parse_ber_length_byte(i1)?;
186 let (i3, len) = match (len.0, len.1) {
187 (0, l1) => {
188 // Short form: MSB is 0, the rest encodes the length (which can be 0) (8.1.3.4)
189 (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 if el.1 == 0 {
195 return Err(Err::Error(BerError::ConstructExpected));
196 }
197 (i2, BerSize::Indefinite)
198 }
199 (_, l1) => {
200 // if len is 0xff -> error (8.1.3.5)
201 if l1 == 0b0111_1111 {
202 return Err(::nom::Err::Error(BerError::InvalidTag));
203 }
204 let (i3, llen) = take(l1)(i2)?;
205 match bytes_to_u64(llen) {
206 Ok(l) => {
207 let l =
208 usize::try_from(l).or(Err(::nom::Err::Error(BerError::InvalidLength)))?;
209 (i3, BerSize::Definite(l))
210 }
211 Err(_) => {
212 return Err(::nom::Err::Error(BerError::InvalidTag));
213 }
214 }
215 }
216 };
217 let hdr = BerObjectHeader::new(class, el.1, BerTag(el.2), len).with_raw_tag(Some(el.3));
218 Ok((i3, hdr))
219 }
220
221 #[allow(clippy::unnecessary_wraps)]
222 #[inline]
ber_read_content_eoc(i: &[u8]) -> BerResult<BerObjectContent>223 fn ber_read_content_eoc(i: &[u8]) -> BerResult<BerObjectContent> {
224 Ok((i, BerObjectContent::EndOfContent))
225 }
226
227 #[inline]
ber_read_content_bool(i: &[u8]) -> BerResult<BerObjectContent>228 fn ber_read_content_bool(i: &[u8]) -> BerResult<BerObjectContent> {
229 match be_u8(i) {
230 Ok((rem, 0)) => Ok((rem, BerObjectContent::Boolean(false))),
231 Ok((rem, _)) => Ok((rem, BerObjectContent::Boolean(true))),
232 Err(e) => Err(e),
233 }
234 }
235
236 #[inline]
ber_read_content_integer(i: &[u8], len: usize) -> BerResult<BerObjectContent>237 fn ber_read_content_integer(i: &[u8], len: usize) -> BerResult<BerObjectContent> {
238 map(take(len), BerObjectContent::Integer)(i)
239 }
240
241 #[inline]
ber_read_content_bitstring(i: &[u8], len: usize) -> BerResult<BerObjectContent>242 fn ber_read_content_bitstring(i: &[u8], len: usize) -> BerResult<BerObjectContent> {
243 custom_check!(i, len == 0, BerError::InvalidLength)?;
244
245 let (i, ignored_bits) = be_u8(i)?;
246 let (i, data) = take(len - 1)(i)?;
247 Ok((
248 i,
249 BerObjectContent::BitString(ignored_bits, BitStringObject { data }),
250 ))
251 }
252
253 #[inline]
ber_read_content_octetstring(i: &[u8], len: usize) -> BerResult<BerObjectContent>254 fn ber_read_content_octetstring(i: &[u8], len: usize) -> BerResult<BerObjectContent> {
255 map(take(len), BerObjectContent::OctetString)(i)
256 }
257
258 #[allow(clippy::unnecessary_wraps)]
259 #[inline]
ber_read_content_null(i: &[u8]) -> BerResult<BerObjectContent>260 fn ber_read_content_null(i: &[u8]) -> BerResult<BerObjectContent> {
261 Ok((i, BerObjectContent::Null))
262 }
263
ber_read_content_oid(i: &[u8], len: usize) -> BerResult<BerObjectContent>264 fn ber_read_content_oid(i: &[u8], len: usize) -> BerResult<BerObjectContent> {
265 custom_check!(i, len == 0, BerError::InvalidLength)?;
266
267 let (i1, oid) = verify(take(len), |os: &[u8]| os.last().unwrap() >> 7 == 0u8)(i)?;
268
269 let obj = BerObjectContent::OID(Oid::new(Cow::Borrowed(oid)));
270 Ok((i1, obj))
271 }
272
273 #[inline]
ber_read_content_enum(i: &[u8], len: usize) -> BerResult<BerObjectContent>274 fn ber_read_content_enum(i: &[u8], len: usize) -> BerResult<BerObjectContent> {
275 let (rem, num) = parse_hex_to_u64(i, len).map_err(|_| BerError::BerValueError)?;
276 Ok((rem, BerObjectContent::Enum(num)))
277 }
278
ber_read_content_utf8string(i: &[u8], len: usize) -> BerResult<BerObjectContent>279 fn ber_read_content_utf8string(i: &[u8], len: usize) -> BerResult<BerObjectContent> {
280 let (i, bytes) = take(len)(i)?;
281 let s = core::str::from_utf8(bytes)
282 .map_err(|_| Err::Error(BerError::StringInvalidCharset))
283 .map(|s| BerObjectContent::UTF8String(s))?;
284 Ok((i, s))
285 }
286
ber_read_content_relativeoid(i: &[u8], len: usize) -> BerResult<BerObjectContent>287 fn ber_read_content_relativeoid(i: &[u8], len: usize) -> BerResult<BerObjectContent> {
288 custom_check!(i, len == 0, BerError::InvalidLength)?;
289
290 let (i1, oid) = verify(take(len), |os: &[u8]| os.last().unwrap() >> 7 == 0u8)(i)?;
291
292 let obj = BerObjectContent::RelativeOID(Oid::new_relative(Cow::Borrowed(oid)));
293 Ok((i1, obj))
294 }
295
ber_read_content_sequence( i: &[u8], len: BerSize, max_depth: usize, ) -> BerResult<BerObjectContent>296 fn ber_read_content_sequence(
297 i: &[u8],
298 len: BerSize,
299 max_depth: usize,
300 ) -> BerResult<BerObjectContent> {
301 custom_check!(i, max_depth == 0, BerError::BerMaxDepth)?;
302 match len {
303 BerSize::Definite(len) => {
304 let (i, data) = take(len)(i)?;
305 let (_, l) = many0(complete(r_parse_ber(max_depth - 1)))(data)?;
306 // trailing bytes are ignored
307 Ok((i, BerObjectContent::Sequence(l)))
308 }
309 BerSize::Indefinite => {
310 // indefinite form
311 // read until end-of-content
312 let (rem, (l, _)) = many_till(r_parse_ber(max_depth - 1), parse_ber_endofcontent)(i)?;
313 Ok((rem, BerObjectContent::Sequence(l)))
314 }
315 }
316 }
317
ber_read_content_set(i: &[u8], len: BerSize, max_depth: usize) -> BerResult<BerObjectContent>318 fn ber_read_content_set(i: &[u8], len: BerSize, max_depth: usize) -> BerResult<BerObjectContent> {
319 custom_check!(i, max_depth == 0, BerError::BerMaxDepth)?;
320 match len {
321 BerSize::Definite(len) => {
322 let (i, data) = take(len)(i)?;
323 let (_, l) = many0(complete(r_parse_ber(max_depth - 1)))(data)?;
324 // trailing bytes are ignored
325 Ok((i, BerObjectContent::Set(l)))
326 }
327 BerSize::Indefinite => {
328 // indefinite form
329 // read until end-of-content
330 let (rem, (l, _)) = many_till(r_parse_ber(max_depth - 1), parse_ber_endofcontent)(i)?;
331 Ok((rem, BerObjectContent::Set(l)))
332 }
333 }
334 }
335
ber_read_content_numericstring<'a>(i: &'a [u8], len: usize) -> BerResult<BerObjectContent<'a>>336 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 fn is_numeric(b: &u8) -> bool {
340 matches!(*b, b'0'..=b'9' | b' ')
341 }
342 let (i, bytes) = take(len)(i)?;
343 if !bytes.iter().all(is_numeric) {
344 return Err(Err::Error(BerError::StringInvalidCharset));
345 }
346 let s = core::str::from_utf8(bytes)
347 .map_err(|_| Err::Error(BerError::StringInvalidCharset))
348 .map(|s| BerObjectContent::NumericString(s))?;
349 Ok((i, s))
350 }
351
ber_read_content_visiblestring<'a>(i: &'a [u8], len: usize) -> BerResult<BerObjectContent<'a>>352 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 fn is_visible(b: &u8) -> bool {
356 0x20 <= *b && *b <= 0x7f
357 }
358 let (i, bytes) = take(len)(i)?;
359 if !bytes.iter().all(is_visible) {
360 return Err(Err::Error(BerError::StringInvalidCharset));
361 }
362 let s = core::str::from_utf8(bytes)
363 .map_err(|_| Err::Error(BerError::StringInvalidCharset))
364 .map(|s| BerObjectContent::VisibleString(s))?;
365 Ok((i, s))
366 }
367
ber_read_content_printablestring<'a>( i: &'a [u8], len: usize, ) -> BerResult<BerObjectContent<'a>>368 fn ber_read_content_printablestring<'a>(
369 i: &'a [u8],
370 len: usize,
371 ) -> 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 fn is_printable(b: &u8) -> bool {
375 matches!(*b,
376 b'a'..=b'z'
377 | b'A'..=b'Z'
378 | 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 }
392 let (i, bytes) = take(len)(i)?;
393 if !bytes.iter().all(is_printable) {
394 return Err(Err::Error(BerError::StringInvalidCharset));
395 }
396 let s = core::str::from_utf8(bytes)
397 .map_err(|_| Err::Error(BerError::StringInvalidCharset))
398 .map(|s| BerObjectContent::PrintableString(s))?;
399 Ok((i, s))
400 }
401
402 #[inline]
ber_read_content_t61string(i: &[u8], len: usize) -> BerResult<BerObjectContent>403 fn ber_read_content_t61string(i: &[u8], len: usize) -> BerResult<BerObjectContent> {
404 map(take(len), BerObjectContent::T61String)(i)
405 }
406
407 #[inline]
ber_read_content_videotexstring(i: &[u8], len: usize) -> BerResult<BerObjectContent>408 fn ber_read_content_videotexstring(i: &[u8], len: usize) -> BerResult<BerObjectContent> {
409 map(take(len), BerObjectContent::VideotexString)(i)
410 }
411
ber_read_content_ia5string<'a>(i: &'a [u8], len: usize) -> BerResult<BerObjectContent<'a>>412 fn ber_read_content_ia5string<'a>(i: &'a [u8], len: usize) -> BerResult<BerObjectContent<'a>> {
413 let (i, bytes) = take(len)(i)?;
414 if !bytes.iter().all(u8::is_ascii) {
415 return Err(Err::Error(BerError::StringInvalidCharset));
416 }
417 let s = core::str::from_utf8(bytes)
418 .map_err(|_| Err::Error(BerError::StringInvalidCharset))
419 .map(|s| BerObjectContent::IA5String(s))?;
420 Ok((i, s))
421 }
422
ber_read_content_utctime<'a>(i: &'a [u8], len: usize) -> BerResult<BerObjectContent<'a>>423 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 fn is_visible(b: &u8) -> bool {
427 0x20 <= *b && *b <= 0x7f
428 }
429 let (i, bytes) = take(len)(i)?;
430 if !bytes.iter().all(is_visible) {
431 return Err(Err::Error(BerError::StringInvalidCharset));
432 }
433 let s = core::str::from_utf8(bytes)
434 .map_err(|_| Err::Error(BerError::StringInvalidCharset))
435 .map(|s| BerObjectContent::UTCTime(s))?;
436 Ok((i, s))
437 }
438
ber_read_content_generalizedtime<'a>( i: &'a [u8], len: usize, ) -> BerResult<BerObjectContent<'a>>439 fn ber_read_content_generalizedtime<'a>(
440 i: &'a [u8],
441 len: usize,
442 ) -> 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 fn is_visible(b: &u8) -> bool {
446 0x20 <= *b && *b <= 0x7f
447 }
448 let (i, bytes) = take(len)(i)?;
449 if !bytes.iter().all(is_visible) {
450 return Err(Err::Error(BerError::StringInvalidCharset));
451 }
452 let s = core::str::from_utf8(bytes)
453 .map_err(|_| Err::Error(BerError::StringInvalidCharset))
454 .map(|s| BerObjectContent::GeneralizedTime(s))?;
455 Ok((i, s))
456 }
457
458 #[inline]
ber_read_content_objectdescriptor(i: &[u8], len: usize) -> BerResult<BerObjectContent>459 fn ber_read_content_objectdescriptor(i: &[u8], len: usize) -> BerResult<BerObjectContent> {
460 map(take(len), BerObjectContent::ObjectDescriptor)(i)
461 }
462
463 #[inline]
ber_read_content_graphicstring(i: &[u8], len: usize) -> BerResult<BerObjectContent>464 fn ber_read_content_graphicstring(i: &[u8], len: usize) -> BerResult<BerObjectContent> {
465 map(take(len), BerObjectContent::GraphicString)(i)
466 }
467
468 #[inline]
ber_read_content_generalstring(i: &[u8], len: usize) -> BerResult<BerObjectContent>469 fn ber_read_content_generalstring(i: &[u8], len: usize) -> BerResult<BerObjectContent> {
470 map(take(len), BerObjectContent::GeneralString)(i)
471 }
472
473 #[inline]
ber_read_content_bmpstring(i: &[u8], len: usize) -> BerResult<BerObjectContent>474 fn ber_read_content_bmpstring(i: &[u8], len: usize) -> BerResult<BerObjectContent> {
475 map(take(len), BerObjectContent::BmpString)(i)
476 }
477
478 #[inline]
ber_read_content_universalstring(i: &[u8], len: usize) -> BerResult<BerObjectContent>479 fn ber_read_content_universalstring(i: &[u8], len: usize) -> BerResult<BerObjectContent> {
480 map(take(len), BerObjectContent::UniversalString)(i)
481 }
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 /// ```
ber_read_element_content_as( i: &[u8], tag: BerTag, len: BerSize, constructed: bool, max_depth: usize, ) -> BerResult<BerObjectContent>506 pub fn ber_read_element_content_as(
507 i: &[u8],
508 tag: BerTag,
509 len: BerSize,
510 constructed: bool,
511 max_depth: usize,
512 ) -> BerResult<BerObjectContent> {
513 if let BerSize::Definite(l) = len {
514 custom_check!(i, l > MAX_OBJECT_SIZE, BerError::InvalidLength)?;
515 if i.len() < l {
516 return Err(Err::Incomplete(Needed::new(l)));
517 }
518 }
519 match tag {
520 // 0x00 end-of-content
521 BerTag::EndOfContent => {
522 custom_check!(i, len != BerSize::Definite(0), BerError::InvalidLength)?;
523 ber_read_content_eoc(i)
524 }
525 // 0x01 bool
526 BerTag::Boolean => {
527 let len = len.primitive()?;
528 custom_check!(i, len != 1, BerError::InvalidLength)?;
529 ber_read_content_bool(i)
530 }
531 // 0x02
532 BerTag::Integer => {
533 custom_check!(i, constructed, BerError::ConstructUnexpected)?;
534 let len = len.primitive()?;
535 ber_read_content_integer(i, len)
536 }
537 // 0x03: bitstring
538 BerTag::BitString => {
539 custom_check!(i, constructed, BerError::Unsupported)?; // XXX valid in BER (8.6.3)
540 let len = len.primitive()?;
541 ber_read_content_bitstring(i, len)
542 }
543 // 0x04: octetstring
544 BerTag::OctetString => {
545 custom_check!(i, constructed, BerError::Unsupported)?; // XXX valid in BER (8.7.1)
546 let len = len.primitive()?;
547 ber_read_content_octetstring(i, len)
548 }
549 // 0x05: null
550 BerTag::Null => {
551 custom_check!(i, constructed, BerError::ConstructUnexpected)?;
552 let len = len.primitive()?;
553 custom_check!(i, len != 0, BerError::InvalidLength)?;
554 ber_read_content_null(i)
555 }
556 // 0x06: object identifier
557 BerTag::Oid => {
558 custom_check!(i, constructed, BerError::ConstructUnexpected)?; // forbidden in 8.19.1
559 let len = len.primitive()?;
560 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 custom_check!(i, constructed, BerError::Unsupported)?; // XXX valid in BER (8.21)
566 let len = len.primitive()?;
567 ber_read_content_objectdescriptor(i, len)
568 }
569 // 0x0a: enumerated
570 BerTag::Enumerated => {
571 custom_check!(i, constructed, BerError::ConstructUnexpected)?; // forbidden in 8.4
572 let len = len.primitive()?;
573 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 custom_check!(i, constructed, BerError::Unsupported)?; // XXX valid in BER (8.21)
579 let len = len.primitive()?;
580 ber_read_content_utf8string(i, len)
581 }
582 // 0x0d: relative object identified
583 BerTag::RelativeOid => {
584 custom_check!(i, constructed, BerError::ConstructUnexpected)?;
585 let len = len.primitive()?;
586 ber_read_content_relativeoid(i, len)
587 }
588 // 0x10: sequence
589 BerTag::Sequence => {
590 custom_check!(i, !constructed, BerError::ConstructExpected)?;
591 ber_read_content_sequence(i, len, max_depth)
592 }
593 // 0x11: set
594 BerTag::Set => {
595 custom_check!(i, !constructed, BerError::ConstructExpected)?;
596 ber_read_content_set(i, len, max_depth)
597 }
598 // 0x12: numericstring - ASCII string with digits an spaces only
599 BerTag::NumericString => {
600 custom_check!(i, constructed, BerError::Unsupported)?; // XXX valid in BER (8.21)
601 let len = len.primitive()?;
602 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 custom_check!(i, constructed, BerError::Unsupported)?; // XXX valid in BER (8.21)
608 let len = len.primitive()?;
609 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 custom_check!(i, constructed, BerError::Unsupported)?; // XXX valid in BER (8.21)
617 let len = len.primitive()?;
618 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 custom_check!(i, constructed, BerError::Unsupported)?; // XXX valid in BER (8.21)
624 let len = len.primitive()?;
625 ber_read_content_videotexstring(i, len)
626 }
627 // 0x16: ia5string - ASCII string
628 BerTag::Ia5String => {
629 custom_check!(i, constructed, BerError::Unsupported)?; // XXX valid in BER (8.21)
630 let len = len.primitive()?;
631 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 let len = len.primitive()?;
637 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 let len = len.primitive()?;
643 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 custom_check!(i, constructed, BerError::Unsupported)?; // XXX valid in BER (8.21)
649 let len = len.primitive()?;
650 ber_read_content_graphicstring(i, len)
651 }
652 // 0x1a: visiblestring - ASCII string with no control characters except
653 // SPACE
654 BerTag::VisibleString => {
655 custom_check!(i, constructed, BerError::Unsupported)?; // XXX valid in BER (8.21)
656 let len = len.primitive()?;
657 ber_read_content_visiblestring(i, len)
658 }
659 // 0x1b: generalstring - Generic ISO 2022 container with explicit
660 // escape sequences
661 BerTag::GeneralString => {
662 custom_check!(i, constructed, BerError::Unsupported)?; // XXX valid in BER (8.21)
663 let len = len.primitive()?;
664 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 custom_check!(i, constructed, BerError::Unsupported)?; // XXX valid in BER (8.21)
671 let len = len.primitive()?;
672 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 custom_check!(i, constructed, BerError::Unsupported)?; // XXX valid in BER (8.21)
678 let len = len.primitive()?;
679 ber_read_content_universalstring(i, len)
680 }
681 // all unknown values
682 _ => Err(Err::Error(BerError::UnknownTag)),
683 }
684 }
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 /// ```
parse_ber_content<'a>( tag: BerTag, ) -> impl Fn(&'a [u8], &'_ BerObjectHeader, usize) -> BerResult<'a, BerObjectContent<'a>>710 pub fn parse_ber_content<'a>(
711 tag: BerTag,
712 ) -> impl Fn(&'a [u8], &'_ BerObjectHeader, usize) -> BerResult<'a, BerObjectContent<'a>> {
713 move |i: &[u8], hdr: &BerObjectHeader, max_recursion: usize| {
714 ber_read_element_content_as(i, tag, hdr.len, hdr.is_constructed(), max_recursion)
715 }
716 }
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 /// ```
parse_ber_content2<'a>( tag: BerTag, ) -> impl Fn(&'a [u8], BerObjectHeader<'a>, usize) -> BerResult<'a, BerObjectContent<'a>>742 pub fn parse_ber_content2<'a>(
743 tag: BerTag,
744 ) -> impl Fn(&'a [u8], BerObjectHeader<'a>, usize) -> BerResult<'a, BerObjectContent<'a>> {
745 move |i: &[u8], hdr: BerObjectHeader, max_recursion: usize| {
746 ber_read_element_content_as(i, tag, hdr.len, hdr.is_constructed(), max_recursion)
747 }
748 }
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 /// ```
parse_ber_with_tag<Tag: Into<BerTag>>(i: &[u8], tag: Tag) -> BerResult765 pub fn parse_ber_with_tag<Tag: Into<BerTag>>(i: &[u8], tag: Tag) -> BerResult {
766 let tag = tag.into();
767 let (i, hdr) = ber_read_element_header(i)?;
768 if hdr.tag != tag {
769 return Err(nom::Err::Error(BerError::InvalidTag));
770 }
771 let (i, content) =
772 ber_read_element_content_as(i, hdr.tag, hdr.len, hdr.is_constructed(), MAX_RECURSION)?;
773 Ok((i, BerObject::from_header_and_content(hdr, content)))
774 }
775
776 /// Read end of content marker
777 #[inline]
parse_ber_endofcontent(i: &[u8]) -> BerResult778 pub fn parse_ber_endofcontent(i: &[u8]) -> BerResult {
779 parse_ber_with_tag(i, BerTag::EndOfContent)
780 }
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]
parse_ber_bool(i: &[u8]) -> BerResult790 pub fn parse_ber_bool(i: &[u8]) -> BerResult {
791 parse_ber_with_tag(i, BerTag::Boolean)
792 }
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]
parse_ber_integer(i: &[u8]) -> BerResult821 pub fn parse_ber_integer(i: &[u8]) -> BerResult {
822 parse_ber_with_tag(i, BerTag::Integer)
823 }
824
825 /// Read an bitstring value
826 #[inline]
parse_ber_bitstring(i: &[u8]) -> BerResult827 pub fn parse_ber_bitstring(i: &[u8]) -> BerResult {
828 parse_ber_with_tag(i, BerTag::BitString)
829 }
830
831 /// Read an octetstring value
832 #[inline]
parse_ber_octetstring(i: &[u8]) -> BerResult833 pub fn parse_ber_octetstring(i: &[u8]) -> BerResult {
834 parse_ber_with_tag(i, BerTag::OctetString)
835 }
836
837 /// Read a null value
838 #[inline]
parse_ber_null(i: &[u8]) -> BerResult839 pub fn parse_ber_null(i: &[u8]) -> BerResult {
840 parse_ber_with_tag(i, BerTag::Null)
841 }
842
843 /// Read an object identifier value
844 #[inline]
parse_ber_oid(i: &[u8]) -> BerResult845 pub fn parse_ber_oid(i: &[u8]) -> BerResult {
846 parse_ber_with_tag(i, BerTag::Oid)
847 }
848
849 /// Read an enumerated value
850 #[inline]
parse_ber_enum(i: &[u8]) -> BerResult851 pub fn parse_ber_enum(i: &[u8]) -> BerResult {
852 parse_ber_with_tag(i, BerTag::Enumerated)
853 }
854
855 /// Read a UTF-8 string value. The encoding is checked.
856 #[inline]
parse_ber_utf8string(i: &[u8]) -> BerResult857 pub fn parse_ber_utf8string(i: &[u8]) -> BerResult {
858 parse_ber_with_tag(i, BerTag::Utf8String)
859 }
860
861 /// Read a relative object identifier value
862 #[inline]
parse_ber_relative_oid(i: &[u8]) -> BerResult863 pub fn parse_ber_relative_oid(i: &[u8]) -> BerResult {
864 parse_ber_with_tag(i, BerTag::RelativeOid)
865 }
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]
parse_ber_sequence(i: &[u8]) -> BerResult876 pub fn parse_ber_sequence(i: &[u8]) -> BerResult {
877 parse_ber_with_tag(i, BerTag::Sequence)
878 }
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]
parse_ber_set(i: &[u8]) -> BerResult889 pub fn parse_ber_set(i: &[u8]) -> BerResult {
890 parse_ber_with_tag(i, BerTag::Set)
891 }
892
893 /// Read a numeric string value. The content is verified to
894 /// contain only digits and spaces.
895 #[inline]
parse_ber_numericstring(i: &[u8]) -> BerResult896 pub fn parse_ber_numericstring(i: &[u8]) -> BerResult {
897 parse_ber_with_tag(i, BerTag::NumericString)
898 }
899
900 /// Read a visible string value. The content is verified to
901 /// contain only the allowed characters.
902 #[inline]
parse_ber_visiblestring(i: &[u8]) -> BerResult903 pub fn parse_ber_visiblestring(i: &[u8]) -> BerResult {
904 parse_ber_with_tag(i, BerTag::VisibleString)
905 }
906
907 /// Read a printable string value. The content is verified to
908 /// contain only the allowed characters.
909 #[inline]
parse_ber_printablestring(i: &[u8]) -> BerResult910 pub fn parse_ber_printablestring(i: &[u8]) -> BerResult {
911 parse_ber_with_tag(i, BerTag::PrintableString)
912 }
913
914 /// Read a T61 string value
915 #[inline]
parse_ber_t61string(i: &[u8]) -> BerResult916 pub fn parse_ber_t61string(i: &[u8]) -> BerResult {
917 parse_ber_with_tag(i, BerTag::T61String)
918 }
919
920 /// Read a Videotex string value
921 #[inline]
parse_ber_videotexstring(i: &[u8]) -> BerResult922 pub fn parse_ber_videotexstring(i: &[u8]) -> BerResult {
923 parse_ber_with_tag(i, BerTag::VideotexString)
924 }
925
926 /// Read an IA5 string value. The content is verified to be ASCII.
927 #[inline]
parse_ber_ia5string(i: &[u8]) -> BerResult928 pub fn parse_ber_ia5string(i: &[u8]) -> BerResult {
929 parse_ber_with_tag(i, BerTag::Ia5String)
930 }
931
932 /// Read an UTC time value
933 #[inline]
parse_ber_utctime(i: &[u8]) -> BerResult934 pub fn parse_ber_utctime(i: &[u8]) -> BerResult {
935 parse_ber_with_tag(i, BerTag::UtcTime)
936 }
937
938 /// Read a Generalized time value
939 #[inline]
parse_ber_generalizedtime(i: &[u8]) -> BerResult940 pub fn parse_ber_generalizedtime(i: &[u8]) -> BerResult {
941 parse_ber_with_tag(i, BerTag::GeneralizedTime)
942 }
943
944 /// Read an ObjectDescriptor value
945 #[inline]
parse_ber_objectdescriptor(i: &[u8]) -> BerResult946 pub fn parse_ber_objectdescriptor(i: &[u8]) -> BerResult {
947 parse_ber_with_tag(i, BerTag::ObjDescriptor)
948 }
949
950 /// Read a GraphicString value
951 #[inline]
parse_ber_graphicstring(i: &[u8]) -> BerResult952 pub fn parse_ber_graphicstring(i: &[u8]) -> BerResult {
953 parse_ber_with_tag(i, BerTag::GraphicString)
954 }
955
956 /// Read a GeneralString value
957 #[inline]
parse_ber_generalstring(i: &[u8]) -> BerResult958 pub fn parse_ber_generalstring(i: &[u8]) -> BerResult {
959 parse_ber_with_tag(i, BerTag::GeneralString)
960 }
961
962 /// Read a BmpString value
963 #[inline]
parse_ber_bmpstring(i: &[u8]) -> BerResult964 pub fn parse_ber_bmpstring(i: &[u8]) -> BerResult {
965 parse_ber_with_tag(i, BerTag::BmpString)
966 }
967
968 /// Read a UniversalString value
969 #[inline]
parse_ber_universalstring(i: &[u8]) -> BerResult970 pub fn parse_ber_universalstring(i: &[u8]) -> BerResult {
971 parse_ber_with_tag(i, BerTag::UniversalString)
972 }
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.
parse_ber_explicit_optional<F>(i: &[u8], tag: BerTag, f: F) -> BerResult where F: Fn(&[u8]) -> BerResult,984 pub fn parse_ber_explicit_optional<F>(i: &[u8], tag: BerTag, f: F) -> BerResult
985 where
986 F: Fn(&[u8]) -> BerResult,
987 {
988 parse_ber_optional(parse_ber_tagged_explicit_g(tag, |content, hdr| {
989 let (rem, obj) = f(content)?;
990 let content = BerObjectContent::Tagged(hdr.class, hdr.tag, Box::new(obj));
991 let tagged = BerObject::from_header_and_content(hdr, content);
992 Ok((rem, tagged))
993 }))(i)
994 }
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]
parse_ber_implicit<'a, Tag, F>(i: &'a [u8], tag: Tag, f: F) -> BerResult<'a> where F: Fn(&'a [u8], &'_ BerObjectHeader, usize) -> BerResult<'a, BerObjectContent<'a>>, Tag: Into<BerTag>,1036 pub fn parse_ber_implicit<'a, Tag, F>(i: &'a [u8], tag: Tag, f: F) -> BerResult<'a>
1037 where
1038 F: Fn(&'a [u8], &'_ BerObjectHeader, usize) -> BerResult<'a, BerObjectContent<'a>>,
1039 Tag: Into<BerTag>,
1040 {
1041 parse_ber_tagged_implicit(tag, f)(i)
1042 }
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 /// ```
parse_ber_optional<'a, F>(mut f: F) -> impl FnMut(&'a [u8]) -> BerResult<'a> where F: FnMut(&'a [u8]) -> BerResult<'a>,1067 pub fn parse_ber_optional<'a, F>(mut f: F) -> impl FnMut(&'a [u8]) -> BerResult<'a>
1068 where
1069 F: FnMut(&'a [u8]) -> BerResult<'a>,
1070 {
1071 move |i: &[u8]| {
1072 let res = f(i);
1073 match res {
1074 Ok((rem, inner)) => {
1075 let opt = BerObject::from_header_and_content(
1076 inner.header.clone(),
1077 BerObjectContent::Optional(Some(Box::new(inner))),
1078 );
1079 Ok((rem, opt))
1080 }
1081 Err(_) => Ok((i, BerObject::from_obj(BerObjectContent::Optional(None)))),
1082 }
1083 }
1084 }
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]
parse_ber_i32(i: &[u8]) -> BerResult<i32>1091 pub fn parse_ber_i32(i: &[u8]) -> BerResult<i32> {
1092 let (rem, ber) = parse_ber_integer(i)?;
1093 let int = ber.as_i32().map_err(nom::Err::Error)?;
1094 Ok((rem, int))
1095 }
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]
parse_ber_i64(i: &[u8]) -> BerResult<i64>1102 pub fn parse_ber_i64(i: &[u8]) -> BerResult<i64> {
1103 let (rem, ber) = parse_ber_integer(i)?;
1104 let int = ber.as_i64().map_err(nom::Err::Error)?;
1105 Ok((rem, int))
1106 }
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]
parse_ber_u32(i: &[u8]) -> BerResult<u32>1113 pub fn parse_ber_u32(i: &[u8]) -> BerResult<u32> {
1114 let (rem, ber) = parse_ber_integer(i)?;
1115 let int = ber.as_u32().map_err(nom::Err::Error)?;
1116 Ok((rem, int))
1117 }
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]
parse_ber_u64(i: &[u8]) -> BerResult<u64>1124 pub fn parse_ber_u64(i: &[u8]) -> BerResult<u64> {
1125 let (rem, ber) = parse_ber_integer(i)?;
1126 let int = ber.as_u64().map_err(nom::Err::Error)?;
1127 Ok((rem, int))
1128 }
1129
1130 /// Parse BER object and get content as slice
1131 #[inline]
parse_ber_slice<Tag: Into<BerTag>>(i: &[u8], tag: Tag) -> BerResult<&[u8]>1132 pub fn parse_ber_slice<Tag: Into<BerTag>>(i: &[u8], tag: Tag) -> BerResult<&[u8]> {
1133 let tag = tag.into();
1134 parse_ber_container(move |content, hdr| {
1135 if hdr.tag != tag {
1136 return Err(Err::Error(BerError::InvalidTag));
1137 }
1138 Ok((&b""[..], content))
1139 })(i)
1140 }
1141
1142 /// Helper combinator, to create a parser with a maximum parsing depth
1143 #[inline]
r_parse_ber(max_depth: usize) -> impl Fn(&[u8]) -> BerResult1144 pub(crate) fn r_parse_ber(max_depth: usize) -> impl Fn(&[u8]) -> BerResult {
1145 move |i: &[u8]| parse_ber_recursive(i, max_depth)
1146 }
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 /// ```
parse_ber_recursive(i: &[u8], max_depth: usize) -> BerResult1162 pub fn parse_ber_recursive(i: &[u8], max_depth: usize) -> BerResult {
1163 custom_check!(i, max_depth == 0, BerError::BerMaxDepth)?;
1164 let (rem, hdr) = ber_read_element_header(i)?;
1165 if let BerSize::Definite(l) = hdr.len {
1166 custom_check!(i, l > MAX_OBJECT_SIZE, BerError::InvalidLength)?;
1167 }
1168 match hdr.class {
1169 BerClass::Universal => (),
1170 BerClass::Private => {
1171 let (rem, content) = ber_get_object_content(rem, &hdr, max_depth)?;
1172 let content = BerObjectContent::Private(hdr.clone(), content);
1173 let obj = BerObject::from_header_and_content(hdr, content);
1174 return Ok((rem, obj));
1175 }
1176 _ => {
1177 let (rem, content) = ber_get_object_content(rem, &hdr, max_depth)?;
1178 let content = BerObjectContent::Unknown(hdr.class, hdr.tag, content);
1179 let obj = BerObject::from_header_and_content(hdr, content);
1180 return Ok((rem, obj));
1181 }
1182 }
1183 match ber_read_element_content_as(rem, hdr.tag, hdr.len, hdr.is_constructed(), max_depth) {
1184 Ok((rem, content)) => Ok((rem, BerObject::from_header_and_content(hdr, content))),
1185 Err(Err::Error(BerError::UnknownTag)) => {
1186 let (rem, content) = ber_get_object_content(rem, &hdr, max_depth)?;
1187 let content = BerObjectContent::Unknown(hdr.class, hdr.tag, content);
1188 let obj = BerObject::from_header_and_content(hdr, content);
1189 Ok((rem, obj))
1190 }
1191 Err(e) => Err(e),
1192 }
1193 }
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]
parse_ber(i: &[u8]) -> BerResult1212 pub fn parse_ber(i: &[u8]) -> BerResult {
1213 parse_ber_recursive(i, MAX_RECURSION)
1214 }
1215
1216 #[test]
test_numericstring()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]
text_visiblestring()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]
test_printablestring()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]
test_ia5string()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]
test_utf8string()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]
test_bitstring_to_u64()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 }
1314