der_parser/
lib.rs

1//! [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](./LICENSE-MIT)
2//! [![Apache License 2.0](https://img.shields.io/badge/License-Apache%202.0-blue.svg)](./LICENSE-APACHE)
3//! [![docs.rs](https://docs.rs/der-parser/badge.svg)](https://docs.rs/der-parser)
4//! [![crates.io](https://img.shields.io/crates/v/der-parser.svg)](https://crates.io/crates/der-parser)
5//! [![Download numbers](https://img.shields.io/crates/d/der-parser.svg)](https://crates.io/crates/der-parser)
6//! [![dependency status](https://deps.rs/crate/der-parser/9.0.0/status.svg)](https://deps.rs/crate/der-parser/9.0.0)
7//! [![Github CI](https://github.com/rusticata/der-parser/workflows/Continuous%20integration/badge.svg)](https://github.com/rusticata/der-parser/actions)
8//! [![Minimum rustc version](https://img.shields.io/badge/rustc-1.63.0+-lightgray.svg)](#rust-version-requirements)
9//!
10//! # BER/DER Parser
11//!
12//! A parser for Basic Encoding Rules (BER [[X.690]]) and Distinguished Encoding Rules(DER
13//! [[X.690]]), implemented with the [nom](https://github.com/Geal/nom) parser combinator
14//! framework.
15//!
16//! It is written in pure Rust, fast, and makes extensive use of zero-copy. A lot of care is taken
17//! to ensure security and safety of this crate, including design (recursion limit, defensive
18//! programming), tests, and fuzzing. It also aims to be panic-free.
19//!
20//! Historically, this parser was intended for DER only, and BER support was added later. This may
21//! still reflect on some naming schemes, but has no other consequence: the `BerObject` and
22//! `DerObject` used in this crate are type aliases, so all functions are compatible.
23//!
24//! DER parsing functions have additional constraints verification, however.
25//!
26//! Serialization has also been added (see [Serialization](#serialization) )
27//!
28//! The code is available on [Github](https://github.com/rusticata/der-parser)
29//! and is part of the [Rusticata](https://github.com/rusticata) project.
30//!
31//! # BER/DER parsers
32//!
33//! BER stands for Basic Encoding Rules, and is defined in [X.690]. It defines a set of rules to
34//! encode and decode ASN.1 objects in binary.
35//!
36//! [X.690] also defines Distinguished Encoding Rules (DER), which is BER with added rules to
37//! ensure canonical and unequivocal binary representation of objects.
38//!
39//! The choice of which one to use is usually guided by the speficication of the data format based
40//! on BER or DER: for example, X.509 uses DER as encoding representation.
41//!
42//! See the related modules for object definitions, functions, and example:
43//! - [`ber`]: Basic Encoding Rules
44//! - [`der`]: Distinguished Encoding Rules
45//!
46//! ## Examples
47//!
48//! Parse two BER integers (see [BER/DER Integers](#berder-integers)):
49//!
50//! ```rust
51//! use der_parser::ber::parse_ber_integer;
52//!
53//! let bytes = [ 0x02, 0x03, 0x01, 0x00, 0x01,
54//!               0x02, 0x03, 0x01, 0x00, 0x00,
55//! ];
56//!
57//! let (rem, obj1) = parse_ber_integer(&bytes).expect("parsing failed");
58//! let (rem, obj2) = parse_ber_integer(&rem).expect("parsing failed");
59//! ```
60//!
61//! Parse a DER sequence of integers:
62//!
63//! ```rust
64//! use der_parser::der::{parse_der_integer, parse_der_sequence_of};
65//!
66//! let bytes = [ 0x30, 0x0a,
67//!               0x02, 0x03, 0x01, 0x00, 0x01,
68//!               0x02, 0x03, 0x01, 0x00, 0x00,
69//! ];
70//!
71//! let (rem, seq) = parse_der_sequence_of(parse_der_integer)(&bytes)
72//!                     .expect("parsing failed");
73//! ```
74//!
75//! Note: all parsing functions return the remaining (unparsed) bytes and the parsed object, or an
76//! error.
77//!
78//! # DER parser design
79//!
80//! Parsing functions are inspired from `nom`, and follow the same interface. The most common
81//! return type is [`BerResult`](error/type.BerResult.html), that stores the remaining bytes and
82//! parsed [`BerObject`](ber/struct.BerObject.html), or an error. Reading the nom documentation may
83//! help understanding how to write parsers and use the output.
84//!
85//! There are two different approaches for parsing DER objects: reading the objects recursively as
86//! long as the tags are known, or specifying a description of the expected objects (generally from
87//! the [ASN.1][X.680] description).
88//!
89//! The first parsing method can be done using the [`parse_ber`](ber/fn.parse_ber.html) and
90//! [`parse_der`](der/fn.parse_der.html) methods.
91//! It is useful when decoding an arbitrary DER object.
92//! However, it cannot fully parse all objects, especially those containing IMPLICIT, OPTIONAL, or
93//! DEFINED BY items.
94//!
95//! ```rust
96//! use der_parser::parse_der;
97//!
98//! let bytes = [ 0x30, 0x0a,
99//!               0x02, 0x03, 0x01, 0x00, 0x01,
100//!               0x02, 0x03, 0x01, 0x00, 0x00,
101//! ];
102//!
103//! let parsed = parse_der(&bytes);
104//! ```
105//!
106//! The second (and preferred) parsing method is to specify the expected objects recursively. The
107//! following functions can be used:
108//! - [`parse_ber_sequence_defined`](ber/fn.parse_ber_sequence_defined.html) and similar functions
109//! for sequences and sets variants
110//! - [`parse_ber_tagged_explicit`](ber/fn.parse_ber_tagged_explicit.html) for tagged explicit
111//! - [`parse_ber_tagged_implicit`](ber/fn.parse_ber_tagged_implicit.html) for tagged implicit
112//! - [`parse_ber_container`](ber/fn.parse_ber_container.html) for generic parsing, etc.
113//! - DER objects use the `_der_` variants
114//!
115//! For example, to read a BER sequence containing two integers:
116//!
117//! ```rust
118//! use der_parser::ber::*;
119//! use der_parser::error::BerResult;
120//!
121//! fn localparse_seq(i:&[u8]) -> BerResult {
122//!     parse_ber_sequence_defined(|data| {
123//!         let (rem, a) = parse_ber_integer(data)?;
124//!         let (rem, b) = parse_ber_integer(rem)?;
125//!         Ok((rem, vec![a, b]))
126//!     })(i)
127//! }
128//!
129//! let bytes = [ 0x30, 0x0a,
130//!               0x02, 0x03, 0x01, 0x00, 0x01,
131//!               0x02, 0x03, 0x01, 0x00, 0x00,
132//! ];
133//!
134//! let (_, parsed) = localparse_seq(&bytes).expect("parsing failed");
135//!
136//! assert_eq!(parsed[0].as_u64(), Ok(65537));
137//! assert_eq!(parsed[1].as_u64(), Ok(65536));
138//! ```
139//!
140//! All functions return a [`BerResult`](error/type.BerResult.html) object: the parsed
141//! [`BerObject`](ber/struct.BerObject.html), an `Incomplete` value, or an error.
142//!
143//! Note that this type is also a `Result`, so usual functions (`map`, `unwrap` etc.) are available.
144//!
145//! # Notes
146//!
147//! ## BER/DER Integers
148//!
149//! DER integers can be of any size, so it is not possible to store them as simple integers (they
150//! are stored as raw bytes).
151//!
152//! Note that, by default, BER/DER integers are signed. Functions are provided to request reading
153//! unsigned values, but they will fail if the integer value is negative.
154//!
155//! To get the integer value for all possible integer sign and size, use
156//! [`BerObject::as_bigint`](ber/struct.BerObject.html#method.as_bigint)) (requires the `bigint` feature).
157//!
158//! To get a simple value expected to be in a known range, use methods like
159//! [`BerObject::as_i32`](ber/struct.BerObject.html#method.as_i32)) and
160//! [`BerObject::as_i64`](ber/struct.BerObject.html#method.as_i64) (or the unsigned versions
161//! [`BerObject::as_u32`](ber/struct.BerObject.html#method.as_u32) and
162//! [`BerObject::as_u64`](ber/struct.BerObject.html#method.as_u64)
163//!),
164//! which will return the value, or an error if the integer is too large (or is negative).
165//!
166//! ```rust
167//! use der_parser::ber::*;
168//!
169//! let data = &[0x02, 0x03, 0x01, 0x00, 0x01];
170//!
171//! let (_, object) = parse_ber_integer(data).expect("parsing failed");
172//! assert_eq!(object.as_u64(), Ok(65537));
173//!
174//! #[cfg(feature = "bigint")]
175//! assert_eq!(object.as_bigint(), Ok(65537.into()))
176//! ```
177//!
178//! Access to the raw value is possible using the `as_slice` method.
179//!
180//! ## Parsers, combinators, macros
181//!
182//! Some parsing tools (for ex for tagged objects) are available in different forms:
183//! - parsers: (regular) functions that takes input and create an object
184//! - combinators: functions that takes parsers (or combinators) as input, and return a function
185//!   (usually, the parser). They are used (combined) as building blocks to create more complex
186//!   parsers.
187//! - macros: these are generally previous (historic) versions of parsers, kept for compatibility.
188//!   They can sometime reduce the amount of code to write, but are hard to debug.
189//!   Parsers should be preferred when possible.
190//!
191//! ## Misc Notes
192//!
193//! - The DER constraints are verified if using `parse_der`.
194//! - `BerObject` and `DerObject` are the same objects (type alias). The only difference is the
195//!   verification of constraints *during parsing*.
196//!
197//! ## Rust version requirements
198//!
199//! The 7.0 series of `der-parser` requires **Rustc version 1.53 or greater**, based on `asn1-rs`
200//! and `nom` 7 dependencies.
201//!
202//! # Serialization
203//!
204//! Support for encoding BER/DER objects is currently being tested and can be used by activating the `serialize` feature.
205//! Note that current status is **experimental**.
206//!
207//! See the `ber_encode_*` functions in the [`ber`](ber/index.html) module, and
208//! [`BerObject::to_vec`](ber/struct.BerObject.html#method.to_vec)
209//!
210//! # References
211//!
212//! - [[X.680]] Abstract Syntax Notation One (ASN.1): Specification of basic notation.
213//! - [[X.690]] ASN.1 encoding rules: Specification of Basic Encoding Rules (BER), Canonical
214//!   Encoding Rules (CER) and Distinguished Encoding Rules (DER).
215//!
216//! [X.680]: http://www.itu.int/rec/T-REC-X.680/en "Abstract Syntax Notation One (ASN.1):
217//!   Specification of basic notation."
218//! [X.690]: https://www.itu.int/rec/T-REC-X.690/en "ASN.1 encoding rules: Specification of
219//!   Basic Encoding Rules (BER), Canonical Encoding Rules (CER) and Distinguished Encoding Rules
220//!   (DER)."
221
222#![deny(/*missing_docs,*/
223        unstable_features,
224        unused_import_braces,
225        unused_qualifications,
226        unreachable_pub)]
227#![forbid(unsafe_code)]
228#![warn(
229    /* missing_docs,
230    rust_2018_idioms,*/
231    missing_debug_implementations,
232)]
233// pragmas for doc
234#![deny(broken_intra_doc_links)]
235#![cfg_attr(docsrs, feature(doc_cfg))]
236#![doc(test(
237    no_crate_inject,
238    attr(deny(warnings/*, rust_2018_idioms*/), allow(dead_code, unused_variables))
239))]
240#![no_std]
241
242#[cfg(any(test, feature = "std"))]
243#[macro_use]
244extern crate std;
245
246extern crate alloc;
247
248#[allow(clippy::module_inception)]
249pub mod ber;
250pub mod der;
251pub mod error;
252pub mod oid;
253
254// compatibility: re-export at crate root
255pub use ber::parse_ber;
256pub use der::parse_der;
257
258pub use asn1_rs;
259pub use nom;
260#[cfg(feature = "bigint")]
261#[cfg_attr(docsrs, doc(cfg(feature = "bigint")))]
262pub use num_bigint;
263pub use rusticata_macros;
264
265// re-exports nom macros, so this crate's macros can be used without importing nom
266pub use nom::IResult;
267
268pub(crate) use asn1_rs::der_constraint_fail_if;
269
270pub use asn1_rs::Oid;
271
272/// Procedural macro to get encoded oids, see the [oid module](oid/index.html).
273#[macro_export]
274macro_rules! oid {
275    ($($args:tt)*) => {{
276        $crate::asn1_rs::oid!($($args)*)
277    }};
278}