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/actions/workflows/rust.yml/badge.svg)](https://github.com/rusticata/der-parser/actions/workflows/rust.yml)
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//!
109//! - [`parse_ber_sequence_defined`](ber/fn.parse_ber_sequence_defined.html) and similar functions
110//!
111//! for sequences and sets variants
112//!
113//! - [`parse_ber_tagged_explicit`](ber/fn.parse_ber_tagged_explicit.html) for tagged explicit
114//! - [`parse_ber_tagged_implicit`](ber/fn.parse_ber_tagged_implicit.html) for tagged implicit
115//! - [`parse_ber_container`](ber/fn.parse_ber_container.html) for generic parsing, etc.
116//! - DER objects use the `_der_` variants
117//!
118//! For example, to read a BER sequence containing two integers:
119//!
120//! ```rust
121//! use der_parser::ber::*;
122//! use der_parser::error::BerResult;
123//!
124//! fn localparse_seq(i:&[u8]) -> BerResult {
125//!     parse_ber_sequence_defined(|data| {
126//!         let (rem, a) = parse_ber_integer(data)?;
127//!         let (rem, b) = parse_ber_integer(rem)?;
128//!         Ok((rem, vec![a, b]))
129//!     })(i)
130//! }
131//!
132//! let bytes = [ 0x30, 0x0a,
133//!               0x02, 0x03, 0x01, 0x00, 0x01,
134//!               0x02, 0x03, 0x01, 0x00, 0x00,
135//! ];
136//!
137//! let (_, parsed) = localparse_seq(&bytes).expect("parsing failed");
138//!
139//! assert_eq!(parsed[0].as_u64(), Ok(65537));
140//! assert_eq!(parsed[1].as_u64(), Ok(65536));
141//! ```
142//!
143//! All functions return a [`BerResult`](error/type.BerResult.html) object: the parsed
144//! [`BerObject`](ber/struct.BerObject.html), an `Incomplete` value, or an error.
145//!
146//! Note that this type is also a `Result`, so usual functions (`map`, `unwrap` etc.) are available.
147//!
148//! # Notes
149//!
150//! ## BER/DER Integers
151//!
152//! DER integers can be of any size, so it is not possible to store them as simple integers (they
153//! are stored as raw bytes).
154//!
155//! Note that, by default, BER/DER integers are signed. Functions are provided to request reading
156//! unsigned values, but they will fail if the integer value is negative.
157//!
158//! To get the integer value for all possible integer sign and size, use
159//! [`BerObject::as_bigint`](ber/struct.BerObject.html#method.as_bigint)) (requires the `bigint` feature).
160//!
161//! To get a simple value expected to be in a known range, use methods like
162//! [`BerObject::as_i32`](ber/struct.BerObject.html#method.as_i32)) and
163//! [`BerObject::as_i64`](ber/struct.BerObject.html#method.as_i64) (or the unsigned versions
164//! [`BerObject::as_u32`](ber/struct.BerObject.html#method.as_u32) and
165//! [`BerObject::as_u64`](ber/struct.BerObject.html#method.as_u64)
166//!),
167//! which will return the value, or an error if the integer is too large (or is negative).
168//!
169//! ```rust
170//! use der_parser::ber::*;
171//!
172//! let data = &[0x02, 0x03, 0x01, 0x00, 0x01];
173//!
174//! let (_, object) = parse_ber_integer(data).expect("parsing failed");
175//! assert_eq!(object.as_u64(), Ok(65537));
176//!
177//! #[cfg(feature = "bigint")]
178//! assert_eq!(object.as_bigint(), Ok(65537.into()))
179//! ```
180//!
181//! Access to the raw value is possible using the `as_slice` method.
182//!
183//! ## Parsers, combinators, macros
184//!
185//! Some parsing tools (for ex for tagged objects) are available in different forms:
186//! - parsers: (regular) functions that takes input and create an object
187//! - combinators: functions that takes parsers (or combinators) as input, and return a function
188//!   (usually, the parser). They are used (combined) as building blocks to create more complex
189//!   parsers.
190//! - macros: these are generally previous (historic) versions of parsers, kept for compatibility.
191//!   They can sometime reduce the amount of code to write, but are hard to debug.
192//!   Parsers should be preferred when possible.
193//!
194//! ## Misc Notes
195//!
196//! - The DER constraints are verified if using `parse_der`.
197//! - `BerObject` and `DerObject` are the same objects (type alias). The only difference is the
198//!   verification of constraints *during parsing*.
199//!
200//! ## Rust version requirements
201//!
202//! The 9.0 series of `der-parser` requires **Rustc version 1.63 or greater**, based on `asn1-rs`
203//! and `nom` 7 dependencies.
204//!
205//! # Serialization
206//!
207//! Support for encoding BER/DER objects is currently being tested and can be used by activating the `serialize` feature.
208//! Note that current status is **experimental**.
209//!
210//! See the `ber_encode_*` functions in the [`ber`](ber/index.html) module, and
211//! [`BerObject::to_vec`](ber/struct.BerObject.html#method.to_vec)
212//!
213//! # References
214//!
215//! - [[X.680]] Abstract Syntax Notation One (ASN.1): Specification of basic notation.
216//! - [[X.690]] ASN.1 encoding rules: Specification of Basic Encoding Rules (BER), Canonical
217//!   Encoding Rules (CER) and Distinguished Encoding Rules (DER).
218//!
219//! [X.680]: http://www.itu.int/rec/T-REC-X.680/en "Abstract Syntax Notation One (ASN.1):
220//!   Specification of basic notation."
221//! [X.690]: https://www.itu.int/rec/T-REC-X.690/en "ASN.1 encoding rules: Specification of
222//!   Basic Encoding Rules (BER), Canonical Encoding Rules (CER) and Distinguished Encoding Rules
223//!   (DER)."
224
225#![deny(/*missing_docs,*/
226        unstable_features,
227        unused_import_braces,
228        unused_qualifications,
229        unreachable_pub)]
230#![forbid(unsafe_code)]
231#![warn(
232    /* missing_docs,
233    rust_2018_idioms,*/
234    missing_debug_implementations,
235)]
236// pragmas for doc
237#![deny(rustdoc::broken_intra_doc_links)]
238#![cfg_attr(docsrs, feature(doc_cfg))]
239#![doc(test(
240    no_crate_inject,
241    attr(deny(warnings/*, rust_2018_idioms*/), allow(dead_code, unused_variables))
242))]
243#![no_std]
244
245#[cfg(any(test, feature = "std"))]
246#[macro_use]
247extern crate std;
248
249extern crate alloc;
250
251#[allow(clippy::module_inception)]
252pub mod ber;
253pub mod der;
254pub mod error;
255pub mod oid;
256
257// compatibility: re-export at crate root
258pub use ber::parse_ber;
259pub use der::parse_der;
260
261pub use asn1_rs;
262pub use nom;
263#[cfg(feature = "bigint")]
264#[cfg_attr(docsrs, doc(cfg(feature = "bigint")))]
265pub use num_bigint;
266pub use rusticata_macros;
267
268// re-exports nom macros, so this crate's macros can be used without importing nom
269pub use nom::IResult;
270
271pub(crate) use asn1_rs::der_constraint_fail_if;
272
273pub use asn1_rs::Oid;
274
275/// Procedural macro to get encoded oids, see the [oid module](oid/index.html).
276#[macro_export]
277macro_rules! oid {
278    ($($args:tt)*) => {{
279        $crate::asn1_rs::oid!($($args)*)
280    }};
281}