diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-19 17:39:49 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-19 17:39:49 +0000 |
commit | a0aa2307322cd47bbf416810ac0292925e03be87 (patch) | |
tree | 37076262a026c4b48c8a0e84f44ff9187556ca35 /rust/vendor/der-parser-6.0.1/src/der | |
parent | Initial commit. (diff) | |
download | suricata-a0aa2307322cd47bbf416810ac0292925e03be87.tar.xz suricata-a0aa2307322cd47bbf416810ac0292925e03be87.zip |
Adding upstream version 1:7.0.3.upstream/1%7.0.3
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'rust/vendor/der-parser-6.0.1/src/der')
-rw-r--r-- | rust/vendor/der-parser-6.0.1/src/der/mod.rs | 88 | ||||
-rw-r--r-- | rust/vendor/der-parser-6.0.1/src/der/multi.rs | 535 | ||||
-rw-r--r-- | rust/vendor/der-parser-6.0.1/src/der/parser.rs | 668 | ||||
-rw-r--r-- | rust/vendor/der-parser-6.0.1/src/der/tagged.rs | 263 |
4 files changed, 1554 insertions, 0 deletions
diff --git a/rust/vendor/der-parser-6.0.1/src/der/mod.rs b/rust/vendor/der-parser-6.0.1/src/der/mod.rs new file mode 100644 index 0000000..bad3f23 --- /dev/null +++ b/rust/vendor/der-parser-6.0.1/src/der/mod.rs @@ -0,0 +1,88 @@ +//! Distinguished Encoding Rules (DER) objects and parser +//! +//! All functions in this crate use BER parsing functions (see the `ber` module) +//! internally, adding constraints verification where needed. +//! +//! The objects [`BerObject`] and [`DerObject`] are the same (type alias): all BER functions, +//! combinators and macros can be used, and provide additional tools for DER parsing. +//! However, DER parsing functions enforce DER constraints in addition of their BER counterparts. +//! +//! # DER Objects +//! +//! The main object of this crate is [`DerObject`]. It contains a header (ber tag, class, and size) +//! and content. +//! +//! To parse primitive objects (for ex. integers or strings), use the `parse_der_` set of +//! functions. +//! +//! Constructed objects (like sequences, sets or tagged objects) require to use a combinator. This +//! combinator takes a function or closure as input, and returns a new, specialized parser. +//! See the [nom](https://github.com/geal/nom) parser combinator library for more details on +//! combinators. +//! +//! # Examples +//! +//! Parse two DER integers: +//! +//! ```rust +//! use der_parser::der::parse_der_integer; +//! +//! let bytes = [ 0x02, 0x03, 0x01, 0x00, 0x01, +//! 0x02, 0x03, 0x01, 0x00, 0x00, +//! ]; +//! +//! let (rem, obj1) = parse_der_integer(&bytes).expect("parsing failed"); +//! let (rem, obj2) = parse_der_integer(&bytes).expect("parsing failed"); +//! ``` +//! +//! Parse a BER sequence containing one integer and an octetstring: +//! +//! ```rust +//! use der_parser::der::*; +//! +//! let bytes = [ 0x30, 0x0a, +//! 0x02, 0x03, 0x01, 0x00, 0x01, +//! 0x04, 0x03, 0x62, 0x61, 0x64, +//! ]; +//! +//! let (rem, seq) = parse_der_sequence_defined(|content| { +//! let (rem, obj1) = parse_der_integer(content)?; +//! let (rem, obj2) = parse_der_octetstring(rem)?; +//! Ok((rem, vec![obj1, obj2])) +//! })(&bytes) +//! .expect("parsing failed"); +//! ``` + +use crate::ber::{BerClass, BerObject, BerObjectContent, BerObjectHeader, BerTag}; + +mod multi; +mod parser; +mod tagged; +pub use crate::der::multi::*; +pub use crate::der::parser::*; +pub use crate::der::tagged::*; + +use alloc::boxed::Box; +use alloc::vec::Vec; +use core::convert::{Into, TryFrom}; + +/// DER Object class of tag (same as `BerClass`) +pub type DerClass = BerClass; + +/// DER tag (same as BER tag) +pub type DerTag = BerTag; + +/// Representation of a DER-encoded (X.690) object +/// +/// Note that a DER object is just a BER object, with additional constraints. +pub type DerObject<'a> = BerObject<'a>; + +/// DER object header (identifier and length) +/// +/// This is the same object as `BerObjectHeader`. +pub type DerObjectHeader<'a> = BerObjectHeader<'a>; + +/// BER object content +/// +/// This is the same object as `BerObjectContent`. +pub type DerObjectContent<'a> = BerObjectContent<'a>; diff --git a/rust/vendor/der-parser-6.0.1/src/der/multi.rs b/rust/vendor/der-parser-6.0.1/src/der/multi.rs new file mode 100644 index 0000000..f4f22fa --- /dev/null +++ b/rust/vendor/der-parser-6.0.1/src/der/multi.rs @@ -0,0 +1,535 @@ +use crate::ber::BerSize; +use crate::der::*; +use crate::error::*; +use nom::bytes::streaming::take; +use nom::combinator::{all_consuming, complete, cut, map}; +use nom::error::ParseError; +use nom::multi::many0; +use nom::{Err, IResult}; + +/// Parse a SEQUENCE OF object +/// +/// Given a subparser for a DER type, parse a sequence of identical objects. +/// +/// ```rust +/// # use der_parser::der::{parse_der_integer, parse_der_sequence_of, DerObject}; +/// # use der_parser::error::BerResult; +/// # +/// /// Read a SEQUENCE OF INTEGER +/// fn parser(i:&[u8]) -> BerResult<DerObject> { +/// parse_der_sequence_of(parse_der_integer)(i) +/// } +/// +/// # let empty = &b""[..]; +/// # let bytes = [ 0x30, 0x0a, +/// # 0x02, 0x03, 0x01, 0x00, 0x01, +/// # 0x02, 0x03, 0x01, 0x00, 0x00, +/// # ]; +/// # let expected = DerObject::from_seq(vec![ +/// # DerObject::from_int_slice(b"\x01\x00\x01"), +/// # DerObject::from_int_slice(b"\x01\x00\x00"), +/// # ]); +/// # assert_eq!(parser(&bytes), Ok((empty, expected))); +/// let (rem, v) = parser(&bytes).expect("parsing failed"); +/// ``` +pub fn parse_der_sequence_of<'a, F>(f: F) -> impl FnMut(&'a [u8]) -> BerResult +where + F: Fn(&'a [u8]) -> BerResult, +{ + map(parse_der_sequence_of_v(f), DerObject::from_seq) +} + +/// Parse a SEQUENCE OF object (returning a vec) +/// +/// Given a subparser for a DER type, parse a sequence of identical objects. +/// +/// This differs from `parse_der_sequence_of` in the parse function and return type. +/// +/// ```rust +/// # use der_parser::der::{parse_der_integer, parse_der_sequence_of_v, DerObject}; +/// # use der_parser::error::BerResult; +/// # +/// /// Read a SEQUENCE OF INTEGER +/// fn parser(i:&[u8]) -> BerResult<Vec<DerObject>> { +/// parse_der_sequence_of_v(parse_der_integer)(i) +/// } +/// +/// # let empty = &b""[..]; +/// # let bytes = [ 0x30, 0x0a, +/// # 0x02, 0x03, 0x01, 0x00, 0x01, +/// # 0x02, 0x03, 0x01, 0x00, 0x00, +/// # ]; +/// # let expected = vec![ +/// # DerObject::from_int_slice(b"\x01\x00\x01"), +/// # DerObject::from_int_slice(b"\x01\x00\x00"), +/// # ]; +/// let (rem, v) = parser(&bytes).expect("parsing failed"); +/// # assert_eq!(v, expected); +/// ``` +pub fn parse_der_sequence_of_v<'a, T, F, E>( + f: F, +) -> impl FnMut(&'a [u8]) -> IResult<&'a [u8], Vec<T>, E> +where + F: FnMut(&'a [u8]) -> IResult<&'a [u8], T, E>, + E: ParseError<&'a [u8]> + From<BerError>, +{ + let mut subparser = all_consuming(many0(complete(cut(f)))); + parse_der_sequence_defined_g(move |data, _| subparser(data)) +} + +/// Parse a defined sequence of DER elements (function version) +/// +/// Given a list of expected parsers, apply them to build a DER sequence and +/// return the remaining bytes and the built object. +/// +/// The remaining bytes point *after* the sequence: any bytes that are part of the sequence but not +/// parsed are ignored. +/// +/// The object header is not available to the parsing function, and the returned type is always a +/// `DerObject`. +/// For a generic version, see +/// [`parse_der_sequence_defined_g`](fn.parse_der_sequence_defined_g.html). +/// +/// # Examples +/// +/// Parsing a sequence of identical types (same as `parse_der_sequence_of`): +/// +/// ```rust +/// # use der_parser::der::{parse_der_integer, parse_der_sequence_defined, DerObject}; +/// # use der_parser::error::BerResult; +/// use nom::combinator::complete; +/// use nom::multi::many1; +/// +/// fn localparse_seq(i:&[u8]) -> BerResult { +/// parse_der_sequence_defined( +/// many1(complete(parse_der_integer)) +/// )(i) +/// } +/// +/// # let empty = &b""[..]; +/// # let bytes = [ 0x30, 0x0a, +/// # 0x02, 0x03, 0x01, 0x00, 0x01, +/// # 0x02, 0x03, 0x01, 0x00, 0x00, +/// # ]; +/// # let expected = DerObject::from_seq(vec![ +/// # DerObject::from_int_slice(b"\x01\x00\x01"), +/// # DerObject::from_int_slice(b"\x01\x00\x00"), +/// # ]); +/// # assert_eq!(localparse_seq(&bytes), Ok((empty, expected))); +/// let (rem, v) = localparse_seq(&bytes).expect("parsing failed"); +/// ``` +/// +/// Parsing a defined sequence with different types: +/// +/// ```rust +/// # use der_parser::der::*; +/// # use der_parser::error::BerResult; +/// use nom::combinator::map; +/// use nom::sequence::tuple; +/// +/// /// Read a DER-encoded object: +/// /// SEQUENCE { +/// /// a INTEGER, +/// /// b OCTETSTRING +/// /// } +/// fn localparse_seq(i:&[u8]) -> BerResult { +/// parse_der_sequence_defined( +/// // the nom `tuple` combinator returns a tuple, so we have to map it +/// // to a list +/// map( +/// tuple((parse_der_integer, parse_der_octetstring)), +/// |(a, b)| vec![a, b] +/// ) +/// )(i) +/// } +/// +/// # let empty = &b""[..]; +/// # let bytes = [ 0x30, 0x0a, +/// # 0x02, 0x03, 0x01, 0x00, 0x01, +/// # 0x04, 0x03, 0x01, 0x00, 0x00, +/// # ]; +/// # let expected = DerObject::from_seq(vec![ +/// # DerObject::from_int_slice(b"\x01\x00\x01"), +/// # DerObject::from_obj(DerObjectContent::OctetString(b"\x01\x00\x00")), +/// # ]); +/// # assert_eq!(localparse_seq(&bytes), Ok((empty, expected))); +/// let (rem, v) = localparse_seq(&bytes).expect("parsing failed"); +/// ``` +pub fn parse_der_sequence_defined<'a, F>(mut f: F) -> impl FnMut(&'a [u8]) -> BerResult +where + F: FnMut(&'a [u8]) -> BerResult<Vec<DerObject>>, +{ + map( + parse_der_sequence_defined_g(move |data, _| f(data)), + DerObject::from_seq, + ) +} + +/// Parse a defined SEQUENCE object (generic function) +/// +/// Given a parser for sequence content, apply it to build a DER sequence and +/// return the remaining bytes and the built object. +/// +/// The remaining bytes point *after* the sequence: any bytes that are part of the sequence but not +/// parsed are ignored. +/// +/// Unlike `parse_der_sequence_defined`, this function allows returning any object or error type, +/// and also passes the object header to the callback. +/// +/// # Examples +/// +/// Parsing a defined sequence with different types: +/// +/// ```rust +/// # use der_parser::der::*; +/// # use der_parser::error::BerResult; +/// # +/// # #[derive(Debug, PartialEq)] +/// pub struct MyObject<'a> { +/// a: u32, +/// b: &'a [u8], +/// } +/// +/// /// Read a DER-encoded object: +/// /// SEQUENCE { +/// /// a INTEGER (0..4294967295), +/// /// b OCTETSTRING +/// /// } +/// fn parse_myobject(i: &[u8]) -> BerResult<MyObject> { +/// parse_der_sequence_defined_g( +/// |i:&[u8], _| { +/// let (i, a) = parse_der_u32(i)?; +/// let (i, obj) = parse_der_octetstring(i)?; +/// let b = obj.as_slice().unwrap(); +/// Ok((i, MyObject{ a, b })) +/// } +/// )(i) +/// } +/// +/// # let empty = &b""[..]; +/// # let bytes = [ 0x30, 0x0a, +/// # 0x02, 0x03, 0x01, 0x00, 0x01, +/// # 0x04, 0x03, 0x01, 0x00, 0x00, +/// # ]; +/// # let expected = MyObject { +/// # a: 0x010001, +/// # b: &[01, 00, 00] +/// # }; +/// # assert_eq!(parse_myobject(&bytes), Ok((empty, expected))); +/// let (rem, v) = parse_myobject(&bytes).expect("parsing failed"); +/// ``` +pub fn parse_der_sequence_defined_g<'a, O, F, E>( + mut f: F, +) -> impl FnMut(&'a [u8]) -> IResult<&'a [u8], O, E> +where + F: FnMut(&'a [u8], DerObjectHeader<'a>) -> IResult<&'a [u8], O, E>, + E: ParseError<&'a [u8]> + From<BerError>, +{ + parse_der_container(move |i, hdr| { + if hdr.tag != DerTag::Sequence { + return Err(Err::Error(BerError::InvalidTag.into())); + } + f(i, hdr) + }) +} + +/// Parse a SET OF object +/// +/// Given a subparser for a DER type, parse a set of identical objects. +/// +/// ```rust +/// # use der_parser::der::{parse_der_integer, parse_der_set_of, DerObject}; +/// # use der_parser::error::BerResult; +/// # +/// /// Read a SET OF INTEGER +/// fn parser(i:&[u8]) -> BerResult<DerObject> { +/// parse_der_set_of(parse_der_integer)(i) +/// } +/// +/// # let empty = &b""[..]; +/// # let bytes = [ 0x31, 0x0a, +/// # 0x02, 0x03, 0x01, 0x00, 0x01, +/// # 0x02, 0x03, 0x01, 0x00, 0x00, +/// # ]; +/// # let expected = DerObject::from_set(vec![ +/// # DerObject::from_int_slice(b"\x01\x00\x01"), +/// # DerObject::from_int_slice(b"\x01\x00\x00"), +/// # ]); +/// # assert_eq!(parser(&bytes), Ok((empty, expected))); +/// let (rem, v) = parser(&bytes).expect("parsing failed"); +/// ``` +pub fn parse_der_set_of<'a, F>(f: F) -> impl FnMut(&'a [u8]) -> BerResult +where + F: Fn(&'a [u8]) -> BerResult, +{ + map(parse_der_set_of_v(f), DerObject::from_set) +} + +/// Parse a SET OF object (returning a vec) +/// +/// Given a subparser for a DER type, parse a set of identical objects. +/// +/// This differs from `parse_der_set_of` in the parse function and return type. +/// +/// ```rust +/// # use der_parser::der::{parse_der_integer, parse_der_set_of_v, DerObject}; +/// # use der_parser::error::BerResult; +/// # +/// /// Read a SET OF INTEGER +/// fn parser(i:&[u8]) -> BerResult<Vec<DerObject>> { +/// parse_der_set_of_v(parse_der_integer)(i) +/// } +/// +/// # let empty = &b""[..]; +/// # let bytes = [ 0x31, 0x0a, +/// # 0x02, 0x03, 0x01, 0x00, 0x01, +/// # 0x02, 0x03, 0x01, 0x00, 0x00, +/// # ]; +/// # let expected = vec![ +/// # DerObject::from_int_slice(b"\x01\x00\x01"), +/// # DerObject::from_int_slice(b"\x01\x00\x00"), +/// # ]; +/// let (rem, v) = parser(&bytes).expect("parsing failed"); +/// # assert_eq!(v, expected); +/// ``` +pub fn parse_der_set_of_v<'a, T, F, E>(f: F) -> impl FnMut(&'a [u8]) -> IResult<&'a [u8], Vec<T>, E> +where + F: FnMut(&'a [u8]) -> IResult<&'a [u8], T, E>, + E: ParseError<&'a [u8]> + From<BerError>, +{ + let mut subparser = all_consuming(many0(complete(cut(f)))); + parse_der_set_defined_g(move |data, _| subparser(data)) +} + +/// Parse a defined set of DER elements (function version) +/// +/// Given a list of expected parsers, apply them to build a DER set and +/// return the remaining bytes and the built object. +/// +/// The remaining bytes point *after* the set: any bytes that are part of the sequence but not +/// parsed are ignored. +/// The nom combinator `all_consuming` can be used to ensure all the content is parsed. +/// +/// The object header is not available to the parsing function, and the returned type is always a +/// `DerObject`. +/// For a generic version, see [`parse_der_set_defined_g`](fn.parse_der_set_defined_g.html). +/// +/// # Examples +/// +/// Parsing a set of identical types (same as `parse_der_set_of`): +/// +/// ```rust +/// # use der_parser::der::{parse_der_integer, parse_der_set_defined, DerObject}; +/// # use der_parser::error::BerResult; +/// use nom::combinator::complete; +/// use nom::multi::many1; +/// +/// fn localparse_seq(i:&[u8]) -> BerResult { +/// parse_der_set_defined( +/// many1(complete(parse_der_integer)) +/// )(i) +/// } +/// +/// # let empty = &b""[..]; +/// # let bytes = [ 0x31, 0x0a, +/// # 0x02, 0x03, 0x01, 0x00, 0x01, +/// # 0x02, 0x03, 0x01, 0x00, 0x00, +/// # ]; +/// # let expected = DerObject::from_set(vec![ +/// # DerObject::from_int_slice(b"\x01\x00\x01"), +/// # DerObject::from_int_slice(b"\x01\x00\x00"), +/// # ]); +/// # assert_eq!(localparse_seq(&bytes), Ok((empty, expected))); +/// let (rem, v) = localparse_seq(&bytes).expect("parsing failed"); +/// ``` +/// +/// Parsing a defined set with different types: +/// +/// ```rust +/// # use der_parser::der::*; +/// # use der_parser::error::BerResult; +/// use nom::combinator::map; +/// use nom::sequence::tuple; +/// +/// /// Read a DER-encoded object: +/// /// SET { +/// /// a INTEGER, +/// /// b OCTETSTRING +/// /// } +/// fn localparse_set(i:&[u8]) -> BerResult { +/// parse_der_set_defined( +/// // the nom `tuple` combinator returns a tuple, so we have to map it +/// // to a list +/// map( +/// tuple((parse_der_integer, parse_der_octetstring)), +/// |(a, b)| vec![a, b] +/// ) +/// )(i) +/// } +/// +/// # let empty = &b""[..]; +/// # let bytes = [ 0x31, 0x0a, +/// # 0x02, 0x03, 0x01, 0x00, 0x01, +/// # 0x04, 0x03, 0x01, 0x00, 0x00, +/// # ]; +/// # let expected = DerObject::from_set(vec![ +/// # DerObject::from_int_slice(b"\x01\x00\x01"), +/// # DerObject::from_obj(DerObjectContent::OctetString(b"\x01\x00\x00")), +/// # ]); +/// # assert_eq!(localparse_set(&bytes), Ok((empty, expected))); +/// let (rem, v) = localparse_set(&bytes).expect("parsing failed"); +/// ``` +pub fn parse_der_set_defined<'a, F>(mut f: F) -> impl FnMut(&'a [u8]) -> BerResult +where + F: FnMut(&'a [u8]) -> BerResult<Vec<DerObject>>, +{ + map( + parse_der_set_defined_g(move |data, _| f(data)), + DerObject::from_set, + ) +} + +/// Parse a defined SET object (generic version) +/// +/// Given a parser for set content, apply it to build a DER set and +/// return the remaining bytes and the built object. +/// +/// The remaining bytes point *after* the set: any bytes that are part of the sequence but not +/// parsed are ignored. +/// The nom combinator `all_consuming` can be used to ensure all the content is parsed. +/// +/// Unlike `parse_der_set_defined`, this function allows returning any object or error type, +/// and also passes the object header to the callback. +/// +/// # Examples +/// +/// Parsing a defined set with different types: +/// +/// ```rust +/// # use der_parser::der::*; +/// # use der_parser::error::BerResult; +/// # +/// # #[derive(Debug, PartialEq)] +/// pub struct MyObject<'a> { +/// a: u32, +/// b: &'a [u8], +/// } +/// +/// /// Read a DER-encoded object: +/// /// SET { +/// /// a INTEGER (0..4294967295), +/// /// b OCTETSTRING +/// /// } +/// fn parse_myobject(i: &[u8]) -> BerResult<MyObject> { +/// parse_der_set_defined_g( +/// |i:&[u8], _| { +/// let (i, a) = parse_der_u32(i)?; +/// let (i, obj) = parse_der_octetstring(i)?; +/// let b = obj.as_slice().unwrap(); +/// Ok((i, MyObject{ a, b })) +/// } +/// )(i) +/// } +/// +/// # let empty = &b""[..]; +/// # let bytes = [ 0x31, 0x0a, +/// # 0x02, 0x03, 0x01, 0x00, 0x01, +/// # 0x04, 0x03, 0x01, 0x00, 0x00, +/// # ]; +/// # let expected = MyObject { +/// # a: 0x010001, +/// # b: &[01, 00, 00] +/// # }; +/// # assert_eq!(parse_myobject(&bytes), Ok((empty, expected))); +/// let (rem, v) = parse_myobject(&bytes).expect("parsing failed"); +/// ``` +pub fn parse_der_set_defined_g<'a, O, F, E>( + mut f: F, +) -> impl FnMut(&'a [u8]) -> IResult<&'a [u8], O, E> +where + F: FnMut(&'a [u8], DerObjectHeader<'a>) -> IResult<&'a [u8], O, E>, + E: ParseError<&'a [u8]> + From<BerError>, +{ + parse_der_container(move |i, hdr| { + if hdr.tag != DerTag::Set { + return Err(Err::Error(BerError::InvalidTag.into())); + } + f(i, hdr) + }) +} + +/// Parse a DER object and apply provided function to content +/// +/// Given a parser for content, read DER object header and apply parser to +/// return the remaining bytes and the parser result. +/// +/// The remaining bytes point *after* the content: any bytes that are part of the content but not +/// parsed are ignored. +/// The nom combinator `all_consuming` can be used to ensure all the content is parsed. +/// +/// This function is mostly intended for structured objects, but can be used for any valid DER +/// object. +/// +/// # Examples +/// +/// Parsing a defined sequence with different types: +/// +/// ```rust +/// # use der_parser::der::*; +/// # use der_parser::error::{BerError, BerResult}; +/// # +/// # #[derive(Debug, PartialEq)] +/// pub struct MyObject<'a> { +/// a: u32, +/// b: &'a [u8], +/// } +/// +/// /// Read a DER-encoded object: +/// /// SEQUENCE { +/// /// a INTEGER (0..4294967295), +/// /// b OCTETSTRING +/// /// } +/// fn parse_myobject(i: &[u8]) -> BerResult<MyObject> { +/// parse_der_container( +/// |i: &[u8], hdr: DerObjectHeader| { +/// if hdr.tag != DerTag::Sequence { +/// return Err(nom::Err::Error(BerError::BerTypeError.into())); +/// } +/// let (i, a) = parse_der_u32(i)?; +/// let (i, obj) = parse_der_octetstring(i)?; +/// let b = obj.as_slice().unwrap(); +/// Ok((i, MyObject{ a, b })) +/// } +/// )(i) +/// } +/// +/// # let empty = &b""[..]; +/// # let bytes = [ 0x30, 0x0a, +/// # 0x02, 0x03, 0x01, 0x00, 0x01, +/// # 0x04, 0x03, 0x01, 0x00, 0x00, +/// # ]; +/// # let expected = MyObject { +/// # a: 0x010001, +/// # b: &[01, 00, 00] +/// # }; +/// # assert_eq!(parse_myobject(&bytes), Ok((empty, expected))); +/// let (rem, v) = parse_myobject(&bytes).expect("parsing failed"); +/// ``` +pub fn parse_der_container<'a, O, F, E>(mut f: F) -> impl FnMut(&'a [u8]) -> IResult<&'a [u8], O, E> +where + F: FnMut(&'a [u8], DerObjectHeader<'a>) -> IResult<&'a [u8], O, E>, + E: ParseError<&'a [u8]> + From<BerError>, +{ + move |i: &[u8]| { + let (i, hdr) = der_read_element_header(i).map_err(nom::Err::convert)?; + // X.690 10.1: the definitive form of length encoding shall be used + let (i, data) = match hdr.len { + BerSize::Definite(len) => take(len)(i)?, + BerSize::Indefinite => { + return Err(Err::Error(BerError::DerConstraintFailed.into())); + } + }; + let (_rest, v) = f(data, hdr)?; + Ok((i, v)) + } +} diff --git a/rust/vendor/der-parser-6.0.1/src/der/parser.rs b/rust/vendor/der-parser-6.0.1/src/der/parser.rs new file mode 100644 index 0000000..04b4b23 --- /dev/null +++ b/rust/vendor/der-parser-6.0.1/src/der/parser.rs @@ -0,0 +1,668 @@ +use crate::ber::*; +use crate::der::*; +use crate::error::*; +use nom::bytes::streaming::take; +use nom::number::streaming::be_u8; +use nom::{Err, Needed}; +use rusticata_macros::custom_check; + +/// Parse DER object recursively +/// +/// Return a tuple containing the remaining (unparsed) bytes and the DER Object, or an error. +/// +/// *Note: this is the same as calling `parse_der_recursive` with `MAX_RECURSION`. +/// +/// ### Example +/// +/// ``` +/// use der_parser::der::{parse_der, DerTag}; +/// +/// let bytes = &[0x02, 0x03, 0x01, 0x00, 0x01]; +/// let (_, obj) = parse_der(bytes).expect("parsing failed"); +/// +/// assert_eq!(obj.header.tag, DerTag::Integer); +/// ``` +#[inline] +pub fn parse_der(i: &[u8]) -> DerResult { + parse_der_recursive(i, MAX_RECURSION) +} + +/// Parse DER object recursively, specifying the maximum recursion depth +/// +/// Return a tuple containing the remaining (unparsed) bytes and the DER Object, or an error. +/// +/// ### Example +/// +/// ``` +/// use der_parser::der::{parse_der_recursive, DerTag}; +/// +/// let bytes = &[0x02, 0x03, 0x01, 0x00, 0x01]; +/// let (_, obj) = parse_der_recursive(bytes, 1).expect("parsing failed"); +/// +/// assert_eq!(obj.header.tag, DerTag::Integer); +/// ``` +pub fn parse_der_recursive(i: &[u8], max_depth: usize) -> DerResult { + let (i, hdr) = der_read_element_header(i)?; + // safety check: length cannot be more than 2^32 bytes + if let BerSize::Definite(l) = hdr.len { + custom_check!(i, l > MAX_OBJECT_SIZE, BerError::InvalidLength)?; + } + der_read_element_content_recursive(i, hdr, max_depth) +} + +#[doc(hidden)] +#[macro_export] +macro_rules! der_constraint_fail_if( + ($slice:expr, $cond:expr) => ( + { + if $cond { + return Err(::nom::Err::Error(BerError::DerConstraintFailed)); + } + } + ); +); + +/// Parse a DER object, expecting a value with specified tag +/// +/// The object is parsed recursively, with a maximum depth of `MAX_RECURSION`. +/// +/// ### Example +/// +/// ``` +/// use der_parser::der::{parse_der_with_tag, DerTag}; +/// +/// let bytes = &[0x02, 0x03, 0x01, 0x00, 0x01]; +/// let (_, obj) = parse_der_with_tag(bytes, DerTag::Integer).expect("parsing failed"); +/// +/// assert_eq!(obj.header.tag, DerTag::Integer); +/// ``` +pub fn parse_der_with_tag<Tag: Into<DerTag>>(i: &[u8], tag: Tag) -> DerResult { + let tag = tag.into(); + let (i, hdr) = der_read_element_header(i)?; + if hdr.tag != tag { + return Err(nom::Err::Error(BerError::InvalidTag)); + } + let (i, content) = + der_read_element_content_as(i, hdr.tag, hdr.len, hdr.is_constructed(), MAX_RECURSION)?; + Ok((i, DerObject::from_header_and_content(hdr, content))) +} + +/// Read end of content marker +#[inline] +pub fn parse_der_endofcontent(i: &[u8]) -> DerResult { + parse_der_with_tag(i, DerTag::EndOfContent) +} + +/// Read a boolean value +/// +/// The encoding of a boolean value shall be primitive. The contents octets shall consist of a +/// single octet. +/// +/// If the boolean value is FALSE, the octet shall be zero. +/// If the boolean value is TRUE, the octet shall be one byte, and have all bits set to one (0xff). +#[inline] +pub fn parse_der_bool(i: &[u8]) -> DerResult { + parse_der_with_tag(i, DerTag::Boolean) +} + +/// Read an integer value +/// +/// The encoding of a boolean value shall be primitive. The contents octets shall consist of one or +/// more octets. +/// +/// To access the content, use the [`as_u64`](struct.BerObject.html#method.as_u64), +/// [`as_u32`](struct.BerObject.html#method.as_u32), +/// [`as_biguint`](struct.BerObject.html#method.as_biguint) or +/// [`as_bigint`](struct.BerObject.html#method.as_bigint) methods. +/// Remember that a BER integer has unlimited size, so these methods return `Result` or `Option` +/// objects. +/// +/// # Examples +/// +/// ```rust +/// # use der_parser::der::{parse_der_integer, DerObject, DerObjectContent}; +/// let empty = &b""[..]; +/// let bytes = [0x02, 0x03, 0x01, 0x00, 0x01]; +/// let expected = DerObject::from_obj(DerObjectContent::Integer(b"\x01\x00\x01")); +/// assert_eq!( +/// parse_der_integer(&bytes), +/// Ok((empty, expected)) +/// ); +/// ``` +#[inline] +pub fn parse_der_integer(i: &[u8]) -> DerResult { + parse_der_with_tag(i, DerTag::Integer) +} + +/// Read an bitstring value +/// +/// To access the content as plain bytes, you will have to +/// interprete the resulting tuple which will contain in +/// its first item the number of padding bits left at +/// the end of the bit string, and in its second item +/// a `BitStringObject` structure which will, in its sole +/// structure field called `data`, contain a byte slice +/// representing the value of the bit string which can +/// be interpreted as a big-endian value with the padding +/// bits on the right (as in ASN.1 raw BER or DER encoding). +/// +/// To access the content as an integer, use the [`as_u64`](struct.BerObject.html#method.as_u64) +/// or [`as_u32`](struct.BerObject.html#method.as_u32) methods. +/// Remember that a BER bit string has unlimited size, so these methods return `Result` or `Option` +/// objects. +#[inline] +pub fn parse_der_bitstring(i: &[u8]) -> DerResult { + parse_der_with_tag(i, DerTag::BitString) +} + +/// Read an octetstring value +#[inline] +pub fn parse_der_octetstring(i: &[u8]) -> DerResult { + parse_der_with_tag(i, DerTag::OctetString) +} + +/// Read a null value +#[inline] +pub fn parse_der_null(i: &[u8]) -> DerResult { + parse_der_with_tag(i, DerTag::Null) +} + +/// Read an object identifier value +#[inline] +pub fn parse_der_oid(i: &[u8]) -> DerResult { + parse_der_with_tag(i, DerTag::Oid) +} + +/// Read an enumerated value +#[inline] +pub fn parse_der_enum(i: &[u8]) -> DerResult { + parse_der_with_tag(i, DerTag::Enumerated) +} + +/// Read a UTF-8 string value. The encoding is checked. +#[inline] +pub fn parse_der_utf8string(i: &[u8]) -> DerResult { + parse_der_with_tag(i, DerTag::Utf8String) +} + +/// Read a relative object identifier value +#[inline] +pub fn parse_der_relative_oid(i: &[u8]) -> DerResult { + parse_der_with_tag(i, DerTag::RelativeOid) +} + +/// Parse a sequence of DER elements +/// +/// Read a sequence of DER objects, without any constraint on the types. +/// Sequence is parsed recursively, so if structured elements are found, they are parsed using the +/// same function. +/// +/// To read a specific sequence of objects (giving the expected types), use the +/// [`parse_der_sequence_defined`](macro.parse_der_sequence_defined.html) macro. +#[inline] +pub fn parse_der_sequence(i: &[u8]) -> DerResult { + parse_der_with_tag(i, DerTag::Sequence) +} + +/// Parse a set of DER elements +/// +/// Read a set of DER objects, without any constraint on the types. +/// Set is parsed recursively, so if structured elements are found, they are parsed using the +/// same function. +/// +/// To read a specific set of objects (giving the expected types), use the +/// [`parse_der_set_defined`](macro.parse_der_set_defined.html) macro. +#[inline] +pub fn parse_der_set(i: &[u8]) -> DerResult { + parse_der_with_tag(i, DerTag::Set) +} + +/// Read a numeric string value. The content is verified to +/// contain only digits and spaces. +#[inline] +pub fn parse_der_numericstring(i: &[u8]) -> DerResult { + parse_der_with_tag(i, DerTag::NumericString) +} + +/// Read a printable string value. The content is verified to +/// contain only the allowed characters. +#[inline] +pub fn visiblestring(i: &[u8]) -> DerResult { + parse_der_with_tag(i, DerTag::VisibleString) +} + +/// Read a printable string value. The content is verified to +/// contain only the allowed characters. +#[inline] +pub fn parse_der_printablestring(i: &[u8]) -> DerResult { + parse_der_with_tag(i, DerTag::PrintableString) +} + +/// Read a T61 string value +#[inline] +pub fn parse_der_t61string(i: &[u8]) -> DerResult { + parse_der_with_tag(i, DerTag::T61String) +} + +/// Read a Videotex string value +#[inline] +pub fn parse_der_videotexstring(i: &[u8]) -> DerResult { + parse_der_with_tag(i, DerTag::VideotexString) +} + +/// Read an IA5 string value. The content is verified to be ASCII. +#[inline] +pub fn parse_der_ia5string(i: &[u8]) -> DerResult { + parse_der_with_tag(i, DerTag::Ia5String) +} + +/// Read an UTC time value +#[inline] +pub fn parse_der_utctime(i: &[u8]) -> DerResult { + parse_der_with_tag(i, DerTag::UtcTime) +} + +/// Read a Generalized time value +#[inline] +pub fn parse_der_generalizedtime(i: &[u8]) -> DerResult { + parse_der_with_tag(i, DerTag::GeneralizedTime) +} + +/// Read a ObjectDescriptor value +#[inline] +pub fn parse_der_objectdescriptor(i: &[u8]) -> DerResult { + parse_der_with_tag(i, DerTag::ObjDescriptor) +} + +/// Read a GraphicString value +#[inline] +pub fn parse_der_graphicstring(i: &[u8]) -> DerResult { + parse_der_with_tag(i, DerTag::GraphicString) +} + +/// Read a GeneralString value +#[inline] +pub fn parse_der_generalstring(i: &[u8]) -> DerResult { + parse_der_with_tag(i, DerTag::GeneralString) +} + +/// Read a BmpString value +#[inline] +pub fn parse_der_bmpstring(i: &[u8]) -> DerResult { + parse_der_with_tag(i, DerTag::BmpString) +} + +/// Read a UniversalString value +#[inline] +pub fn parse_der_universalstring(i: &[u8]) -> DerResult { + parse_der_with_tag(i, DerTag::UniversalString) +} + +/// Parse an optional tagged object, applying function to get content +/// +/// This function returns a `DerObject`, trying to read content as generic DER objects. +/// If parsing failed, return an optional object containing `None`. +/// +/// To support other return or error types, use +/// [parse_der_tagged_explicit_g](fn.parse_der_tagged_explicit_g.html) +/// +/// This function will never fail: if parsing content failed, the BER value `Optional(None)` is +/// returned. +#[inline] +pub fn parse_der_explicit_optional<F>(i: &[u8], tag: DerTag, f: F) -> DerResult +where + F: Fn(&[u8]) -> DerResult, +{ + parse_ber_explicit_optional(i, tag, f) +} + +/// Parse an implicit tagged object, applying function to read content +/// +/// Note: unlike explicit tagged functions, the callback must be a *content* parsing function, +/// often based on the [`parse_der_content`](fn.parse_der_content.html) combinator. +/// +/// The built object will use the original header (and tag), so the content may not match the tag +/// value. +/// +/// For a combinator version, see [parse_der_tagged_implicit](../ber/fn.parse_der_tagged_implicit.html). +/// +/// For a generic version (different output and error types), see +/// [parse_der_tagged_implicit_g](../ber/fn.parse_der_tagged_implicit_g.html). +/// +/// # Examples +/// +/// The following parses `[3] IMPLICIT INTEGER` into a `DerObject`: +/// +/// ```rust +/// # use der_parser::der::*; +/// # use der_parser::error::DerResult; +/// # +/// fn parse_int_implicit(i:&[u8]) -> DerResult { +/// parse_der_implicit( +/// i, +/// 3, +/// parse_der_content(DerTag::Integer), +/// ) +/// } +/// +/// # let bytes = &[0x83, 0x03, 0x01, 0x00, 0x01]; +/// let res = parse_int_implicit(bytes); +/// # match res { +/// # Ok((rem, content)) => { +/// # assert!(rem.is_empty()); +/// # assert_eq!(content.as_u32(), Ok(0x10001)); +/// # }, +/// # _ => assert!(false) +/// # } +/// ``` +#[inline] +pub fn parse_der_implicit<'a, Tag, F>(i: &'a [u8], tag: Tag, f: F) -> DerResult<'a> +where + F: Fn(&'a [u8], &'_ DerObjectHeader, usize) -> BerResult<'a, DerObjectContent<'a>>, + Tag: Into<DerTag>, +{ + parse_ber_implicit(i, tag, f) +} + +/// Parse DER object and try to decode it as a 32-bits signed integer +/// +/// Return `IntegerTooLarge` if object is an integer, but can not be represented in the target +/// integer type. +#[inline] +pub fn parse_der_i32(i: &[u8]) -> BerResult<i32> { + let (rem, der) = parse_der_integer(i)?; + let int = der.as_i32().map_err(nom::Err::Error)?; + Ok((rem, int)) +} + +/// Parse DER object and try to decode it as a 64-bits signed integer +/// +/// Return `IntegerTooLarge` if object is an integer, but can not be represented in the target +/// integer type. +#[inline] +pub fn parse_der_i64(i: &[u8]) -> BerResult<i64> { + let (rem, der) = parse_der_integer(i)?; + let int = der.as_i64().map_err(nom::Err::Error)?; + Ok((rem, int)) +} + +/// Parse DER object and try to decode it as a 32-bits unsigned integer +/// +/// Return `IntegerTooLarge` if object is an integer, but can not be represented in the target +/// integer type. +pub fn parse_der_u32(i: &[u8]) -> BerResult<u32> { + let (rem, der) = parse_der_integer(i)?; + let int = der.as_u32().map_err(nom::Err::Error)?; + Ok((rem, int)) +} + +/// Parse DER object and try to decode it as a 64-bits unsigned integer +/// +/// Return `IntegerTooLarge` if object is an integer, but can not be represented in the target +/// integer type. +pub fn parse_der_u64(i: &[u8]) -> BerResult<u64> { + let (rem, der) = parse_der_integer(i)?; + let int = der.as_u64().map_err(nom::Err::Error)?; + Ok((rem, int)) +} + +/// Parse DER object and get content as slice +#[inline] +pub fn parse_der_slice<Tag: Into<DerTag>>(i: &[u8], tag: Tag) -> BerResult<&[u8]> { + let tag = tag.into(); + parse_der_container(move |content, hdr| { + if hdr.tag != tag { + return Err(Err::Error(BerError::InvalidTag)); + } + Ok((&b""[..], content)) + })(i) +} + +/// Parse the next bytes as the content of a DER object (combinator, header reference) +/// +/// Content type is *not* checked to match tag, caller is responsible of providing the correct tag +/// +/// Caller is also responsible to check if parsing function consumed the expected number of +/// bytes (`header.len`). +/// +/// This function differs from [`parse_der_content2`](fn.parse_der_content2.html) because it passes +/// the BER object header by reference (required for ex. by `parse_der_implicit`). +/// +/// The arguments of the parse function are: `(input, ber_object_header, max_recursion)`. +/// +/// Example: manually parsing header and content +/// +/// ``` +/// # use der_parser::ber::MAX_RECURSION; +/// # use der_parser::der::*; +/// # +/// # let bytes = &[0x02, 0x03, 0x01, 0x00, 0x01]; +/// let (i, header) = der_read_element_header(bytes).expect("parsing failed"); +/// let (rem, content) = parse_der_content(header.tag)(i, &header, MAX_RECURSION) +/// .expect("parsing failed"); +/// # +/// # assert_eq!(header.tag, DerTag::Integer); +/// ``` +pub fn parse_der_content<'a>( + tag: DerTag, +) -> impl Fn(&'a [u8], &'_ DerObjectHeader, usize) -> BerResult<'a, DerObjectContent<'a>> { + move |i: &[u8], hdr: &DerObjectHeader, max_recursion: usize| { + der_read_element_content_as(i, tag, hdr.len, hdr.is_constructed(), max_recursion) + } +} + +/// Parse the next bytes as the content of a DER object (combinator, owned header) +/// +/// Content type is *not* checked to match tag, caller is responsible of providing the correct tag +/// +/// Caller is also responsible to check if parsing function consumed the expected number of +/// bytes (`header.len`). +/// +/// The arguments of the parse function are: `(input, ber_object_header, max_recursion)`. +/// +/// This function differs from [`parse_der_content`](fn.parse_der_content.html) because it passes +/// an owned BER object header (required for ex. by `parse_der_tagged_implicit_g`). +/// +/// Example: manually parsing header and content +/// +/// ``` +/// # use der_parser::ber::MAX_RECURSION; +/// # use der_parser::der::*; +/// # +/// # let bytes = &[0x02, 0x03, 0x01, 0x00, 0x01]; +/// let (i, header) = der_read_element_header(bytes).expect("parsing failed"); +/// # assert_eq!(header.tag, DerTag::Integer); +/// let (rem, content) = parse_der_content2(header.tag)(i, header, MAX_RECURSION) +/// .expect("parsing failed"); +/// ``` +pub fn parse_der_content2<'a>( + tag: DerTag, +) -> impl Fn(&'a [u8], DerObjectHeader<'a>, usize) -> BerResult<'a, DerObjectContent<'a>> { + move |i: &[u8], hdr: DerObjectHeader, max_recursion: usize| { + der_read_element_content_as(i, tag, hdr.len, hdr.is_constructed(), max_recursion) + } +} + +// --------- end of parse_der_xxx functions ---------- + +/// Parse the next bytes as the content of a DER object. +/// +/// Content type is *not* checked, caller is responsible of providing the correct tag +pub fn der_read_element_content_as( + i: &[u8], + tag: DerTag, + len: BerSize, + constructed: bool, + max_depth: usize, +) -> BerResult<DerObjectContent> { + // Indefinite lengths are not allowed in DER (X.690 section 10.1) + let l = len.primitive()?; + if i.len() < l { + return Err(Err::Incomplete(Needed::new(l))); + } + match tag { + DerTag::Boolean => { + custom_check!(i, l != 1, BerError::InvalidLength)?; + der_constraint_fail_if!(i, i[0] != 0 && i[0] != 0xff); + } + DerTag::BitString => { + der_constraint_fail_if!(i, constructed); + // exception: read and verify padding bits + return der_read_content_bitstring(i, l); + } + DerTag::Integer => { + // verify leading zeros + match i[..l] { + [] => return Err(nom::Err::Error(BerError::DerConstraintFailed)), + [0, 0, ..] => return Err(nom::Err::Error(BerError::DerConstraintFailed)), + [0, byte, ..] if byte < 0x80 => { + return Err(nom::Err::Error(BerError::DerConstraintFailed)); + } + _ => (), + } + } + DerTag::NumericString + | DerTag::VisibleString + | DerTag::PrintableString + | DerTag::Ia5String + | DerTag::Utf8String + | DerTag::T61String + | DerTag::VideotexString + | DerTag::BmpString + | DerTag::UniversalString + | DerTag::ObjDescriptor + | DerTag::GraphicString + | DerTag::GeneralString => { + der_constraint_fail_if!(i, constructed); + } + DerTag::UtcTime | DerTag::GeneralizedTime => { + if l == 0 || i.get(l - 1).cloned() != Some(b'Z') { + return Err(Err::Error(BerError::DerConstraintFailed)); + } + } + _ => (), + } + ber_read_element_content_as(i, tag, len, constructed, max_depth) +} + +/// Parse DER object content recursively +/// +/// *Note: an error is raised if recursion depth exceeds `MAX_RECURSION`. +pub fn der_read_element_content<'a>(i: &'a [u8], hdr: DerObjectHeader<'a>) -> DerResult<'a> { + der_read_element_content_recursive(i, hdr, MAX_RECURSION) +} + +fn der_read_element_content_recursive<'a>( + i: &'a [u8], + hdr: DerObjectHeader<'a>, + max_depth: usize, +) -> DerResult<'a> { + match hdr.class { + BerClass::Universal => (), + BerClass::Private => { + let (rem, content) = ber_get_object_content(i, &hdr, max_depth)?; + let content = BerObjectContent::Private(hdr.clone(), content); + let obj = BerObject::from_header_and_content(hdr, content); + return Ok((rem, obj)); + } + _ => { + let (i, content) = ber_get_object_content(i, &hdr, max_depth)?; + let content = DerObjectContent::Unknown(hdr.class, hdr.tag, content); + let obj = DerObject::from_header_and_content(hdr, content); + return Ok((i, obj)); + } + } + match der_read_element_content_as(i, hdr.tag, hdr.len, hdr.is_constructed(), max_depth) { + Ok((rem, content)) => Ok((rem, DerObject::from_header_and_content(hdr, content))), + Err(Err::Error(BerError::UnknownTag)) => { + let (rem, content) = ber_get_object_content(i, &hdr, max_depth)?; + let content = DerObjectContent::Unknown(hdr.class, hdr.tag, content); + let obj = DerObject::from_header_and_content(hdr, content); + Ok((rem, obj)) + } + Err(e) => Err(e), + } +} + +fn der_read_content_bitstring(i: &[u8], len: usize) -> BerResult<DerObjectContent> { + let (i, ignored_bits) = be_u8(i)?; + if ignored_bits > 7 { + return Err(Err::Error(BerError::DerConstraintFailed)); + } + if len == 0 { + return Err(Err::Error(BerError::InvalidLength)); + } + let (i, data) = take(len - 1)(i)?; + if len > 1 { + let mut last_byte = data[len - 2]; + for _ in 0..ignored_bits as usize { + der_constraint_fail_if!(i, last_byte & 1 != 0); + last_byte >>= 1; + } + } + Ok(( + i, + DerObjectContent::BitString(ignored_bits, BitStringObject { data }), + )) + // do_parse! { + // i, + // ignored_bits: be_u8 >> + // custom_check!(ignored_bits > 7, BerError::DerConstraintFailed) >> + // custom_check!(len == 0, BerError::InvalidLength) >> + // s: take!(len - 1) >> + // call!(|input| { + // if len > 1 { + // let mut last_byte = s[len-2]; + // for _ in 0..ignored_bits as usize { + // der_constraint_fail_if!(i, last_byte & 1 != 0); + // last_byte >>= 1; + // } + // } + // Ok((input,())) + // }) >> + // ( DerObjectContent::BitString(ignored_bits,BitStringObject{ data:s }) ) + // } +} + +/// Read an object header (DER) +pub fn der_read_element_header(i: &[u8]) -> BerResult<DerObjectHeader> { + let (i1, el) = parse_identifier(i)?; + let class = match DerClass::try_from(el.0) { + Ok(c) => c, + Err(_) => unreachable!(), // Cannot fail, we have read exactly 2 bits + }; + let (i2, len) = parse_ber_length_byte(i1)?; + let (i3, len) = match (len.0, len.1) { + (0, l1) => { + // Short form: MSB is 0, the rest encodes the length (which can be 0) (8.1.3.4) + (i2, BerSize::Definite(usize::from(l1))) + } + (_, 0) => { + // Indefinite form is not allowed in DER (10.1) + return Err(::nom::Err::Error(BerError::DerConstraintFailed)); + } + (_, l1) => { + // if len is 0xff -> error (8.1.3.5) + if l1 == 0b0111_1111 { + return Err(::nom::Err::Error(BerError::InvalidTag)); + } + // DER(9.1) if len is 0 (indefinite form), obj must be constructed + der_constraint_fail_if!(&i[1..], len.1 == 0 && el.1 != 1); + let (i3, llen) = take(l1)(i2)?; + match bytes_to_u64(llen) { + Ok(l) => { + // DER: should have been encoded in short form (< 127) + der_constraint_fail_if!(i, l < 127); + let l = + usize::try_from(l).or(Err(::nom::Err::Error(BerError::InvalidLength)))?; + (i3, BerSize::Definite(l)) + } + Err(_) => { + return Err(::nom::Err::Error(BerError::InvalidTag)); + } + } + } + }; + let hdr = DerObjectHeader::new(class, el.1, BerTag(el.2), len).with_raw_tag(Some(el.3)); + Ok((i3, hdr)) +} diff --git a/rust/vendor/der-parser-6.0.1/src/der/tagged.rs b/rust/vendor/der-parser-6.0.1/src/der/tagged.rs new file mode 100644 index 0000000..c7d0fec --- /dev/null +++ b/rust/vendor/der-parser-6.0.1/src/der/tagged.rs @@ -0,0 +1,263 @@ +use crate::ber::MAX_RECURSION; +use crate::der::*; +use crate::error::*; +use nom::error::ParseError; +use nom::{Err, IResult}; + +/// Read a TAGGED EXPLICIT value (combinator) +/// +/// The built object will use the outer header (and tag), and contains a `Tagged` object +/// with class, value and content. +/// +/// For a generic version (different output and error types), see +/// [parse_der_tagged_explicit_g](fn.parse_der_tagged_explicit_g.html). +/// +/// The following parses `[2] EXPLICIT INTEGER`: +/// +/// ```rust +/// # use der_parser::der::*; +/// # use der_parser::error::BerResult; +/// use nom::combinator::map_res; +/// # +/// fn parse_int_explicit(i:&[u8]) -> BerResult<u32> { +/// map_res( +/// parse_der_tagged_explicit(2, parse_der_integer), +/// |x: DerObject| x.as_tagged()?.2.as_u32() +/// )(i) +/// } +/// +/// # let bytes = &[0xa2, 0x05, 0x02, 0x03, 0x01, 0x00, 0x01]; +/// let res = parse_int_explicit(bytes); +/// # match res { +/// # Ok((rem,val)) => { +/// # assert!(rem.is_empty()); +/// # assert_eq!(val, 0x10001); +/// # }, +/// # _ => assert!(false) +/// # } +/// ``` +pub fn parse_der_tagged_explicit<'a, Tag, F>(tag: Tag, f: F) -> impl FnMut(&'a [u8]) -> BerResult +where + F: Fn(&'a [u8]) -> BerResult<DerObject>, + Tag: Into<DerTag>, +{ + let tag = tag.into(); + parse_der_tagged_explicit_g(tag, move |content, hdr| { + let (rem, obj) = f(content)?; + let class = hdr.class; + let obj2 = DerObject::from_header_and_content( + hdr, + DerObjectContent::Tagged(class, tag, Box::new(obj)), + ); + Ok((rem, obj2)) + }) +} + +/// Read a TAGGED EXPLICIT value (generic version) +/// +/// The following parses `[2] EXPLICIT INTEGER`: +/// +/// ```rust +/// # use der_parser::der::*; +/// # use der_parser::error::BerResult; +/// # +/// fn parse_int_explicit(i:&[u8]) -> BerResult<u32> { +/// parse_der_tagged_explicit_g(2, move |content, hdr| { +/// let (rem, obj) = parse_der_integer(content)?; +/// let value = obj.as_u32()?; +/// Ok((rem, value)) +/// })(i) +/// } +/// +/// # let bytes = &[0xa2, 0x05, 0x02, 0x03, 0x01, 0x00, 0x01]; +/// let res = parse_int_explicit(bytes); +/// # match res { +/// # Ok((rem,val)) => { +/// # assert!(rem.is_empty()); +/// # assert_eq!(val, 0x10001); +/// # }, +/// # _ => assert!(false) +/// # } +/// ``` +pub fn parse_der_tagged_explicit_g<'a, Tag, Output, F, E>( + tag: Tag, + f: F, +) -> impl FnMut(&'a [u8]) -> IResult<&'a [u8], Output, E> +where + F: Fn(&'a [u8], DerObjectHeader<'a>) -> IResult<&'a [u8], Output, E>, + E: ParseError<&'a [u8]> + From<BerError>, + Tag: Into<DerTag>, +{ + let tag = tag.into(); + parse_der_container(move |i, hdr| { + if hdr.class == DerClass::Universal { + return Err(Err::Error(BerError::InvalidClass.into())); + } + if hdr.tag != tag { + return Err(Err::Error(BerError::InvalidTag.into())); + } + // X.690 8.14.2: if implicit tagging was not used, the encoding shall be constructed + if !hdr.is_constructed() { + return Err(Err::Error(BerError::ConstructExpected.into())); + } + f(i, hdr) + // trailing bytes are ignored + }) +} + +/// Read a TAGGED IMPLICIT value (combinator) +/// +/// Parse a TAGGED IMPLICIT value, given the expected tag, and the content parsing function. +/// +/// The built object will use the original header (and tag), so the content may not match the tag +/// value. +/// +/// For a generic version (different output and error types), see +/// [parse_der_tagged_implicit_g](fn.parse_der_tagged_implicit_g.html). +/// +/// # Examples +/// +/// The following parses `[2] IMPLICIT INTEGER` into a `DerObject`: +/// +/// ```rust +/// # use der_parser::der::*; +/// # use der_parser::error::BerResult; +/// # +/// fn parse_int_implicit(i:&[u8]) -> BerResult<DerObject> { +/// parse_der_tagged_implicit( +/// 2, +/// parse_der_content(DerTag::Integer), +/// )(i) +/// } +/// +/// # let bytes = &[0x82, 0x03, 0x01, 0x00, 0x01]; +/// let res = parse_int_implicit(bytes); +/// # match res { +/// # Ok((rem, content)) => { +/// # assert!(rem.is_empty()); +/// # assert_eq!(content.as_u32(), Ok(0x10001)); +/// # }, +/// # _ => assert!(false) +/// # } +/// ``` +/// +/// The following parses `[2] IMPLICIT INTEGER` into an `u32`, raising an error if the integer is +/// too large: +/// +/// ```rust +/// # use der_parser::der::*; +/// # use der_parser::error::BerResult; +/// use nom::combinator::map_res; +/// # +/// fn parse_int_implicit(i:&[u8]) -> BerResult<u32> { +/// map_res( +/// parse_der_tagged_implicit( +/// 2, +/// parse_der_content(DerTag::Integer), +/// ), +/// |x: DerObject| x.as_u32() +/// )(i) +/// } +/// +/// # let bytes = &[0x82, 0x03, 0x01, 0x00, 0x01]; +/// let res = parse_int_implicit(bytes); +/// # match res { +/// # Ok((rem, val)) => { +/// # assert!(rem.is_empty()); +/// # assert_eq!(val, 0x10001); +/// # }, +/// # _ => assert!(false) +/// # } +/// ``` +pub fn parse_der_tagged_implicit<'a, Tag, F>(tag: Tag, f: F) -> impl FnMut(&'a [u8]) -> BerResult +where + F: Fn(&'a [u8], &'_ DerObjectHeader, usize) -> BerResult<'a, DerObjectContent<'a>>, + Tag: Into<DerTag>, +{ + let tag = tag.into(); + parse_der_tagged_implicit_g(tag, move |i, hdr, depth| { + let (rem, content) = f(i, &hdr, depth)?; + // trailing bytes are ignored + let obj = DerObject::from_header_and_content(hdr, content); + Ok((rem, obj)) + }) +} + +/// Read a TAGGED IMPLICIT value (generic version) +/// +/// Parse a TAGGED IMPLICIT value, given the expected tag, and the content parsing function. +/// +/// # Examples +/// +/// The following parses `[1] IMPLICIT OCTETSTRING`, returning a `DerObject`: +/// +/// ```rust +/// # use der_parser::der::*; +/// # use der_parser::error::BerResult; +/// # +/// fn parse_implicit_0_octetstring(i:&[u8]) -> BerResult<DerObjectContent> { +/// parse_der_tagged_implicit_g( +/// 2, +/// parse_der_content2(DerTag::OctetString) +/// )(i) +/// } +/// +/// # let bytes = &[0x02, 0x05, 0x68, 0x65, 0x6c, 0x6c, 0x6f]; +/// let res = parse_implicit_0_octetstring(bytes); +/// # match res { +/// # Ok((rem, val)) => { +/// # assert!(rem.is_empty()); +/// # let s = val.as_slice().unwrap(); +/// # assert_eq!(s, b"hello"); +/// # }, +/// # _ => assert!(false) +/// # } +/// ``` +/// +/// The following parses `[2] IMPLICIT INTEGER` into an `u32`, raising an error if the integer is +/// too large: +/// +/// ```rust +/// # use der_parser::der::*; +/// # use der_parser::error::BerResult; +/// # +/// fn parse_int_implicit(i:&[u8]) -> BerResult<u32> { +/// parse_der_tagged_implicit_g( +/// 2, +/// |content, hdr, depth| { +/// let (rem, obj_content) = parse_der_content(DerTag::Integer)(content, &hdr, depth)?; +/// let value = obj_content.as_u32()?; +/// Ok((rem, value)) +/// } +/// )(i) +/// } +/// +/// # let bytes = &[0x82, 0x03, 0x01, 0x00, 0x01]; +/// let res = parse_int_implicit(bytes); +/// # match res { +/// # Ok((rem, val)) => { +/// # assert!(rem.is_empty()); +/// # assert_eq!(val, 0x10001); +/// # }, +/// # _ => assert!(false) +/// # } +/// ``` +pub fn parse_der_tagged_implicit_g<'a, Tag, Output, F, E>( + tag: Tag, + f: F, +) -> impl FnMut(&'a [u8]) -> IResult<&[u8], Output, E> +where + F: Fn(&'a [u8], DerObjectHeader<'a>, usize) -> IResult<&'a [u8], Output, E>, + E: ParseError<&'a [u8]> + From<BerError>, + Tag: Into<DerTag>, +{ + let tag = tag.into(); + parse_der_container(move |i, hdr| { + if hdr.tag != tag { + return Err(Err::Error(BerError::InvalidTag.into())); + } + // XXX MAX_RECURSION should not be used, it resets the depth counter + f(i, hdr, MAX_RECURSION) + // trailing bytes are ignored + }) +} |