der_parser/der/parser.rs
1use crate::ber::*;
2use crate::der::*;
3use crate::der_constraint_fail_if;
4use crate::error::*;
5use alloc::borrow::ToOwned;
6use asn1_rs::{Any, FromDer, Tag};
7use nom::bytes::streaming::take;
8use nom::number::streaming::be_u8;
9use nom::{Err, Needed};
10use rusticata_macros::custom_check;
11
12/// Parse DER object recursively
13///
14/// Return a tuple containing the remaining (unparsed) bytes and the DER Object, or an error.
15///
16/// *Note: this is the same as calling `parse_der_recursive` with `MAX_RECURSION`.
17///
18/// ### Example
19///
20/// ```
21/// use der_parser::der::{parse_der, Tag};
22///
23/// let bytes = &[0x02, 0x03, 0x01, 0x00, 0x01];
24/// let (_, obj) = parse_der(bytes).expect("parsing failed");
25///
26/// assert_eq!(obj.header.tag(), Tag::Integer);
27/// ```
28#[inline]
29pub fn parse_der(i: &[u8]) -> DerResult {
30 parse_der_recursive(i, MAX_RECURSION)
31}
32
33/// Parse DER object recursively, specifying the maximum recursion depth
34///
35/// Return a tuple containing the remaining (unparsed) bytes and the DER Object, or an error.
36///
37/// ### Example
38///
39/// ```
40/// use der_parser::der::{parse_der_recursive, Tag};
41///
42/// let bytes = &[0x02, 0x03, 0x01, 0x00, 0x01];
43/// let (_, obj) = parse_der_recursive(bytes, 1).expect("parsing failed");
44///
45/// assert_eq!(obj.header.tag(), Tag::Integer);
46/// ```
47pub fn parse_der_recursive(i: &[u8], max_depth: usize) -> DerResult {
48 let (i, hdr) = der_read_element_header(i)?;
49 // safety check: length cannot be more than 2^32 bytes
50 if let Length::Definite(l) = hdr.length() {
51 custom_check!(i, l > MAX_OBJECT_SIZE, BerError::InvalidLength)?;
52 }
53 der_read_element_content_recursive(i, hdr, max_depth)
54}
55
56/// Parse a DER object, expecting a value with specified tag
57///
58/// The object is parsed recursively, with a maximum depth of `MAX_RECURSION`.
59///
60/// ### Example
61///
62/// ```
63/// use der_parser::der::{parse_der_with_tag, Tag};
64///
65/// let bytes = &[0x02, 0x03, 0x01, 0x00, 0x01];
66/// let (_, obj) = parse_der_with_tag(bytes, Tag::Integer).expect("parsing failed");
67///
68/// assert_eq!(obj.header.tag(), Tag::Integer);
69/// ```
70pub fn parse_der_with_tag<T: Into<Tag>>(i: &[u8], tag: T) -> DerResult {
71 let tag = tag.into();
72 let (i, hdr) = der_read_element_header(i)?;
73 hdr.assert_tag(tag)?;
74 let (i, content) = der_read_element_content_as(
75 i,
76 hdr.tag(),
77 hdr.length(),
78 hdr.is_constructed(),
79 MAX_RECURSION,
80 )?;
81 Ok((i, DerObject::from_header_and_content(hdr, content)))
82}
83
84/// Read end of content marker
85#[inline]
86pub fn parse_der_endofcontent(i: &[u8]) -> DerResult {
87 parse_der_with_tag(i, Tag::EndOfContent)
88}
89
90/// Read a boolean value
91///
92/// The encoding of a boolean value shall be primitive. The contents octets shall consist of a
93/// single octet.
94///
95/// If the boolean value is FALSE, the octet shall be zero.
96/// If the boolean value is TRUE, the octet shall be one byte, and have all bits set to one (0xff).
97#[inline]
98pub fn parse_der_bool(i: &[u8]) -> DerResult {
99 parse_der_with_tag(i, Tag::Boolean)
100}
101
102/// Read an integer value
103///
104/// The encoding of a boolean value shall be primitive. The contents octets shall consist of one or
105/// more octets.
106///
107/// To access the content, use the [`as_u64`](struct.BerObject.html#method.as_u64),
108/// [`as_u32`](struct.BerObject.html#method.as_u32),
109/// [`as_biguint`](struct.BerObject.html#method.as_biguint) or
110/// [`as_bigint`](struct.BerObject.html#method.as_bigint) methods.
111/// Remember that a BER integer has unlimited size, so these methods return `Result` or `Option`
112/// objects.
113///
114/// # Examples
115///
116/// ```rust
117/// # use der_parser::der::{parse_der_integer, DerObject, DerObjectContent};
118/// let empty = &b""[..];
119/// let bytes = [0x02, 0x03, 0x01, 0x00, 0x01];
120/// let expected = DerObject::from_obj(DerObjectContent::Integer(b"\x01\x00\x01"));
121/// assert_eq!(
122/// parse_der_integer(&bytes),
123/// Ok((empty, expected))
124/// );
125/// ```
126#[inline]
127pub fn parse_der_integer(i: &[u8]) -> DerResult {
128 parse_der_with_tag(i, Tag::Integer)
129}
130
131/// Read an bitstring value
132///
133/// To access the content as plain bytes, you will have to
134/// interprete the resulting tuple which will contain in
135/// its first item the number of padding bits left at
136/// the end of the bit string, and in its second item
137/// a `BitStringObject` structure which will, in its sole
138/// structure field called `data`, contain a byte slice
139/// representing the value of the bit string which can
140/// be interpreted as a big-endian value with the padding
141/// bits on the right (as in ASN.1 raw BER or DER encoding).
142///
143/// To access the content as an integer, use the [`as_u64`](struct.BerObject.html#method.as_u64)
144/// or [`as_u32`](struct.BerObject.html#method.as_u32) methods.
145/// Remember that a BER bit string has unlimited size, so these methods return `Result` or `Option`
146/// objects.
147#[inline]
148pub fn parse_der_bitstring(i: &[u8]) -> DerResult {
149 parse_der_with_tag(i, Tag::BitString)
150}
151
152/// Read an octetstring value
153#[inline]
154pub fn parse_der_octetstring(i: &[u8]) -> DerResult {
155 parse_der_with_tag(i, Tag::OctetString)
156}
157
158/// Read a null value
159#[inline]
160pub fn parse_der_null(i: &[u8]) -> DerResult {
161 parse_der_with_tag(i, Tag::Null)
162}
163
164/// Read an object identifier value
165#[inline]
166pub fn parse_der_oid(i: &[u8]) -> DerResult {
167 parse_der_with_tag(i, Tag::Oid)
168}
169
170/// Read an enumerated value
171#[inline]
172pub fn parse_der_enum(i: &[u8]) -> DerResult {
173 parse_der_with_tag(i, Tag::Enumerated)
174}
175
176/// Read a UTF-8 string value. The encoding is checked.
177#[inline]
178pub fn parse_der_utf8string(i: &[u8]) -> DerResult {
179 parse_der_with_tag(i, Tag::Utf8String)
180}
181
182/// Read a relative object identifier value
183#[inline]
184pub fn parse_der_relative_oid(i: &[u8]) -> DerResult {
185 parse_der_with_tag(i, Tag::RelativeOid)
186}
187
188/// Parse a sequence of DER elements
189///
190/// Read a sequence of DER objects, without any constraint on the types.
191/// Sequence is parsed recursively, so if constructed elements are found, they are parsed using the
192/// same function.
193///
194/// To read a specific sequence of objects (giving the expected types), use the
195/// [`parse_der_sequence_defined`](macro.parse_der_sequence_defined.html) macro.
196#[inline]
197pub fn parse_der_sequence(i: &[u8]) -> DerResult {
198 parse_der_with_tag(i, Tag::Sequence)
199}
200
201/// Parse a set of DER elements
202///
203/// Read a set of DER objects, without any constraint on the types.
204/// Set is parsed recursively, so if constructed elements are found, they are parsed using the
205/// same function.
206///
207/// To read a specific set of objects (giving the expected types), use the
208/// [`parse_der_set_defined`](macro.parse_der_set_defined.html) macro.
209#[inline]
210pub fn parse_der_set(i: &[u8]) -> DerResult {
211 parse_der_with_tag(i, Tag::Set)
212}
213
214/// Read a numeric string value. The content is verified to
215/// contain only digits and spaces.
216#[inline]
217pub fn parse_der_numericstring(i: &[u8]) -> DerResult {
218 parse_der_with_tag(i, Tag::NumericString)
219}
220
221/// Read a printable string value. The content is verified to
222/// contain only the allowed characters.
223#[inline]
224pub fn parse_der_visiblestring(i: &[u8]) -> DerResult {
225 parse_der_with_tag(i, Tag::VisibleString)
226}
227
228#[deprecated(since = "8.2.0", note = "Use `parse_der_visiblestring` instead")]
229#[inline]
230pub fn visiblestring(i: &[u8]) -> DerResult {
231 parse_der_visiblestring(i)
232}
233
234/// Read a printable string value. The content is verified to
235/// contain only the allowed characters.
236#[inline]
237pub fn parse_der_printablestring(i: &[u8]) -> DerResult {
238 parse_der_with_tag(i, Tag::PrintableString)
239}
240
241/// Read a T61 string value
242#[inline]
243pub fn parse_der_t61string(i: &[u8]) -> DerResult {
244 parse_der_with_tag(i, Tag::T61String)
245}
246
247/// Read a Videotex string value
248#[inline]
249pub fn parse_der_videotexstring(i: &[u8]) -> DerResult {
250 parse_der_with_tag(i, Tag::VideotexString)
251}
252
253/// Read an IA5 string value. The content is verified to be ASCII.
254#[inline]
255pub fn parse_der_ia5string(i: &[u8]) -> DerResult {
256 parse_der_with_tag(i, Tag::Ia5String)
257}
258
259/// Read an UTC time value
260#[inline]
261pub fn parse_der_utctime(i: &[u8]) -> DerResult {
262 parse_der_with_tag(i, Tag::UtcTime)
263}
264
265/// Read a Generalized time value
266#[inline]
267pub fn parse_der_generalizedtime(i: &[u8]) -> DerResult {
268 parse_der_with_tag(i, Tag::GeneralizedTime)
269}
270
271/// Read a ObjectDescriptor value
272#[inline]
273pub fn parse_der_objectdescriptor(i: &[u8]) -> DerResult {
274 parse_der_with_tag(i, Tag::ObjectDescriptor)
275}
276
277/// Read a GraphicString value
278#[inline]
279pub fn parse_der_graphicstring(i: &[u8]) -> DerResult {
280 parse_der_with_tag(i, Tag::GraphicString)
281}
282
283/// Read a GeneralString value
284#[inline]
285pub fn parse_der_generalstring(i: &[u8]) -> DerResult {
286 parse_der_with_tag(i, Tag::GeneralString)
287}
288
289/// Read a BmpString value
290#[inline]
291pub fn parse_der_bmpstring(i: &[u8]) -> DerResult {
292 parse_der_with_tag(i, Tag::BmpString)
293}
294
295/// Read a UniversalString value
296#[inline]
297pub fn parse_der_universalstring(i: &[u8]) -> DerResult {
298 parse_der_with_tag(i, Tag::UniversalString)
299}
300
301/// Parse an optional tagged object, applying function to get content
302///
303/// This function returns a `DerObject`, trying to read content as generic DER objects.
304/// If parsing failed, return an optional object containing `None`.
305///
306/// To support other return or error types, use
307/// [parse_der_tagged_explicit_g](fn.parse_der_tagged_explicit_g.html)
308///
309/// This function will never fail: if parsing content failed, the BER value `Optional(None)` is
310/// returned.
311#[inline]
312pub fn parse_der_explicit_optional<F>(i: &[u8], tag: Tag, f: F) -> DerResult
313where
314 F: Fn(&[u8]) -> DerResult,
315{
316 parse_ber_explicit_optional(i, tag, f)
317}
318
319/// Parse an implicit tagged object, applying function to read content
320///
321/// Note: unlike explicit tagged functions, the callback must be a *content* parsing function,
322/// often based on the [`parse_der_content`](fn.parse_der_content.html) combinator.
323///
324/// The built object will use the original header (and tag), so the content may not match the tag
325/// value.
326///
327/// For a combinator version, see [parse_der_tagged_implicit](../ber/fn.parse_der_tagged_implicit.html).
328///
329/// For a generic version (different output and error types), see
330/// [parse_der_tagged_implicit_g](../ber/fn.parse_der_tagged_implicit_g.html).
331///
332/// # Examples
333///
334/// The following parses `[3] IMPLICIT INTEGER` into a `DerObject`:
335///
336/// ```rust
337/// # use der_parser::der::*;
338/// # use der_parser::error::DerResult;
339/// #
340/// fn parse_int_implicit(i:&[u8]) -> DerResult {
341/// parse_der_implicit(
342/// i,
343/// 3,
344/// parse_der_content(Tag::Integer),
345/// )
346/// }
347///
348/// # let bytes = &[0x83, 0x03, 0x01, 0x00, 0x01];
349/// let res = parse_int_implicit(bytes);
350/// # match res {
351/// # Ok((rem, content)) => {
352/// # assert!(rem.is_empty());
353/// # assert_eq!(content.as_u32(), Ok(0x10001));
354/// # },
355/// # _ => assert!(false)
356/// # }
357/// ```
358#[inline]
359pub fn parse_der_implicit<'a, T, F>(i: &'a [u8], tag: T, f: F) -> DerResult<'a>
360where
361 F: Fn(&'a [u8], &'_ Header, usize) -> BerResult<'a, DerObjectContent<'a>>,
362 T: Into<Tag>,
363{
364 parse_ber_implicit(i, tag, f)
365}
366
367/// Parse DER object and try to decode it as a 32-bits signed integer
368///
369/// Return `IntegerTooLarge` if object is an integer, but can not be represented in the target
370/// integer type.
371#[inline]
372pub fn parse_der_i32(i: &[u8]) -> BerResult<i32> {
373 <i32>::from_der(i)
374}
375
376/// Parse DER object and try to decode it as a 64-bits signed integer
377///
378/// Return `IntegerTooLarge` if object is an integer, but can not be represented in the target
379/// integer type.
380#[inline]
381pub fn parse_der_i64(i: &[u8]) -> BerResult<i64> {
382 <i64>::from_der(i)
383}
384
385/// Parse DER object and try to decode it as a 32-bits unsigned integer
386///
387/// Return `IntegerTooLarge` if object is an integer, but can not be represented in the target
388/// integer type.
389pub fn parse_der_u32(i: &[u8]) -> BerResult<u32> {
390 <u32>::from_der(i)
391}
392
393/// Parse DER object and try to decode it as a 64-bits unsigned integer
394///
395/// Return `IntegerTooLarge` if object is an integer, but can not be represented in the target
396/// integer type.
397pub fn parse_der_u64(i: &[u8]) -> BerResult<u64> {
398 <u64>::from_der(i)
399}
400
401/// Parse DER object and get content as slice
402#[inline]
403pub fn parse_der_slice<T: Into<Tag>>(i: &[u8], tag: T) -> BerResult<&[u8]> {
404 let tag = tag.into();
405 parse_der_container(move |content, hdr| {
406 hdr.assert_tag(tag)?;
407 Ok((&b""[..], content))
408 })(i)
409}
410
411/// Parse the next bytes as the content of a DER object (combinator, header reference)
412///
413/// Content type is *not* checked to match tag, caller is responsible of providing the correct tag
414///
415/// Caller is also responsible to check if parsing function consumed the expected number of
416/// bytes (`header.len`).
417///
418/// This function differs from [`parse_der_content2`](fn.parse_der_content2.html) because it passes
419/// the BER object header by reference (required for ex. by `parse_der_implicit`).
420///
421/// The arguments of the parse function are: `(input, ber_object_header, max_recursion)`.
422///
423/// Example: manually parsing header and content
424///
425/// ```
426/// # use der_parser::ber::MAX_RECURSION;
427/// # use der_parser::der::*;
428/// #
429/// # let bytes = &[0x02, 0x03, 0x01, 0x00, 0x01];
430/// let (i, header) = der_read_element_header(bytes).expect("parsing failed");
431/// let (rem, content) = parse_der_content(header.tag())(i, &header, MAX_RECURSION)
432/// .expect("parsing failed");
433/// #
434/// # assert_eq!(header.tag(), Tag::Integer);
435/// ```
436pub fn parse_der_content<'a>(
437 tag: Tag,
438) -> impl Fn(&'a [u8], &'_ Header, usize) -> BerResult<'a, DerObjectContent<'a>> {
439 move |i: &[u8], hdr: &Header, max_recursion: usize| {
440 der_read_element_content_as(i, tag, hdr.length(), hdr.is_constructed(), max_recursion)
441 }
442}
443
444/// Parse the next bytes as the content of a DER object (combinator, owned header)
445///
446/// Content type is *not* checked to match tag, caller is responsible of providing the correct tag
447///
448/// Caller is also responsible to check if parsing function consumed the expected number of
449/// bytes (`header.len`).
450///
451/// The arguments of the parse function are: `(input, ber_object_header, max_recursion)`.
452///
453/// This function differs from [`parse_der_content`](fn.parse_der_content.html) because it passes
454/// an owned BER object header (required for ex. by `parse_der_tagged_implicit_g`).
455///
456/// Example: manually parsing header and content
457///
458/// ```
459/// # use der_parser::ber::MAX_RECURSION;
460/// # use der_parser::der::*;
461/// #
462/// # let bytes = &[0x02, 0x03, 0x01, 0x00, 0x01];
463/// let (i, header) = der_read_element_header(bytes).expect("parsing failed");
464/// # assert_eq!(header.tag(), Tag::Integer);
465/// let (rem, content) = parse_der_content2(header.tag())(i, header, MAX_RECURSION)
466/// .expect("parsing failed");
467/// ```
468pub fn parse_der_content2<'a>(
469 tag: Tag,
470) -> impl Fn(&'a [u8], Header<'a>, usize) -> BerResult<'a, DerObjectContent<'a>> {
471 move |i: &[u8], hdr: Header, max_recursion: usize| {
472 der_read_element_content_as(i, tag, hdr.length(), hdr.is_constructed(), max_recursion)
473 }
474}
475
476// --------- end of parse_der_xxx functions ----------
477
478/// Parse the next bytes as the content of a DER object.
479///
480/// Content type is *not* checked, caller is responsible of providing the correct tag
481pub fn der_read_element_content_as(
482 i: &[u8],
483 tag: Tag,
484 length: Length,
485 constructed: bool,
486 max_depth: usize,
487) -> BerResult<DerObjectContent> {
488 // Indefinite lengths are not allowed in DER (X.690 section 10.1)
489 let l = length.definite().map_err(BerError::from)?;
490 if i.len() < l {
491 return Err(Err::Incomplete(Needed::new(l)));
492 }
493 match tag {
494 Tag::Boolean => {
495 custom_check!(i, l != 1, BerError::InvalidLength)?;
496 der_constraint_fail_if!(i, i[0] != 0 && i[0] != 0xff, DerConstraint::InvalidBoolean);
497 }
498 Tag::BitString => {
499 der_constraint_fail_if!(i, constructed, DerConstraint::Constructed);
500 // exception: read and verify padding bits
501 return der_read_content_bitstring(i, l);
502 }
503 Tag::Integer => {
504 // verify leading zeros
505 match i[..l] {
506 [] => {
507 return Err(nom::Err::Error(BerError::DerConstraintFailed(
508 DerConstraint::IntegerEmpty,
509 )))
510 }
511 [0, 0, ..] => {
512 return Err(nom::Err::Error(BerError::DerConstraintFailed(
513 DerConstraint::IntegerLeadingZeroes,
514 )))
515 }
516 [0, byte, ..] if byte < 0x80 => {
517 return Err(nom::Err::Error(BerError::DerConstraintFailed(
518 DerConstraint::IntegerLeadingZeroes,
519 )));
520 }
521 _ => (),
522 }
523 }
524 Tag::NumericString
525 | Tag::VisibleString
526 | Tag::PrintableString
527 | Tag::Ia5String
528 | Tag::Utf8String
529 | Tag::T61String
530 | Tag::VideotexString
531 | Tag::BmpString
532 | Tag::UniversalString
533 | Tag::ObjectDescriptor
534 | Tag::GraphicString
535 | Tag::GeneralString => {
536 der_constraint_fail_if!(i, constructed, DerConstraint::Constructed);
537 }
538 Tag::UtcTime | Tag::GeneralizedTime => {
539 if l == 0 || i.get(l - 1).cloned() != Some(b'Z') {
540 return Err(Err::Error(BerError::DerConstraintFailed(
541 DerConstraint::MissingTimeZone,
542 )));
543 }
544 }
545 _ => (),
546 }
547 ber_read_element_content_as(i, tag, length, constructed, max_depth)
548}
549
550/// Parse DER object content recursively
551///
552/// *Note: an error is raised if recursion depth exceeds `MAX_RECURSION`.
553pub fn der_read_element_content<'a>(i: &'a [u8], hdr: Header<'a>) -> DerResult<'a> {
554 der_read_element_content_recursive(i, hdr, MAX_RECURSION)
555}
556
557fn der_read_element_content_recursive<'a>(
558 i: &'a [u8],
559 hdr: Header<'a>,
560 max_depth: usize,
561) -> DerResult<'a> {
562 match hdr.class() {
563 Class::Universal => (),
564 _ => {
565 let (i, data) = ber_get_object_content(i, &hdr, max_depth)?;
566 let any = Any::new(hdr.clone(), data);
567 let content = DerObjectContent::Unknown(any);
568 let obj = DerObject::from_header_and_content(hdr, content);
569 return Ok((i, obj));
570 }
571 }
572 match der_read_element_content_as(i, hdr.tag(), hdr.length(), hdr.is_constructed(), max_depth) {
573 Ok((rem, content)) => Ok((rem, DerObject::from_header_and_content(hdr, content))),
574 Err(Err::Error(BerError::UnknownTag(_))) => {
575 let (rem, data) = ber_get_object_content(i, &hdr, max_depth)?;
576 let any = Any::new(hdr.clone(), data);
577 let content = DerObjectContent::Unknown(any);
578 let obj = DerObject::from_header_and_content(hdr, content);
579 Ok((rem, obj))
580 }
581 Err(e) => Err(e),
582 }
583}
584
585fn der_read_content_bitstring(i: &[u8], len: usize) -> BerResult<DerObjectContent> {
586 let (i, ignored_bits) = be_u8(i)?;
587 if ignored_bits > 7 {
588 return Err(Err::Error(BerError::invalid_value(
589 Tag::BitString,
590 "More than 7 unused bits".to_owned(),
591 )));
592 }
593 if len == 0 {
594 return Err(Err::Error(BerError::InvalidLength));
595 }
596 let (i, data) = take(len - 1)(i)?;
597 if len > 1 {
598 let mut last_byte = data[len - 2];
599 for _ in 0..ignored_bits as usize {
600 der_constraint_fail_if!(i, last_byte & 1 != 0, DerConstraint::UnusedBitsNotZero);
601 last_byte >>= 1;
602 }
603 }
604 Ok((
605 i,
606 DerObjectContent::BitString(ignored_bits, BitStringObject { data }),
607 ))
608 // do_parse! {
609 // i,
610 // ignored_bits: be_u8 >>
611 // custom_check!(ignored_bits > 7, BerError::DerConstraintFailed) >>
612 // custom_check!(len == 0, BerError::InvalidLength) >>
613 // s: take!(len - 1) >>
614 // call!(|input| {
615 // if len > 1 {
616 // let mut last_byte = s[len-2];
617 // for _ in 0..ignored_bits as usize {
618 // der_constraint_fail_if!(i, last_byte & 1 != 0);
619 // last_byte >>= 1;
620 // }
621 // }
622 // Ok((input,()))
623 // }) >>
624 // ( DerObjectContent::BitString(ignored_bits,BitStringObject{ data:s }) )
625 // }
626}
627
628/// Read an object header (DER)
629#[inline]
630pub fn der_read_element_header(i: &[u8]) -> BerResult<Header> {
631 Header::from_der(i)
632}