asn1_rs/
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/asn1-rs/badge.svg)](https://docs.rs/asn1-rs)
4//! [![crates.io](https://img.shields.io/crates/v/asn1-rs.svg)](https://crates.io/crates/asn1-rs)
5//! [![Download numbers](https://img.shields.io/crates/d/asn1-rs.svg)](https://crates.io/crates/asn1-rs)
6//! [![Github CI](https://github.com/rusticata/asn1-rs/workflows/Continuous%20integration/badge.svg)](https://github.com/rusticata/asn1-rs/actions)
7//! [![Minimum rustc version](https://img.shields.io/badge/rustc-1.63.0+-lightgray.svg)](#rust-version-requirements)
8//!
9//! # BER/DER Parsers/Encoders
10//!
11//! A set of parsers/encoders for Basic Encoding Rules (BER [[X.690]]) and Distinguished Encoding Rules(DER
12//! [[X.690]]) formats, implemented with the [nom] parser combinator framework.
13//!
14//! It is written in pure Rust, fast, and makes extensive use of zero-copy. A lot of care is taken
15//! to ensure security and safety of this crate, including design (recursion limit, defensive
16//! programming), tests, and fuzzing. It also aims to be panic-free.
17//!
18//! This crate is a rewrite of [der-parser](https://crates.io/crates/der-parser) to propose a more data-oriented API,
19//! and add generalized support for serialization.
20//!
21//! Many ideas were borrowed from the [crypto/utils/der](https://github.com/RustCrypto/utils/tree/master/der) crate (like
22//! the `Any`/`TryFrom`/`FromDer` mechanism), adapted and merged into a generalized BER/DER crate.
23//! Credits (and many thanks) go to Tony Arcieri for writing the original crate.
24//!
25//! # BER/DER parsers
26//!
27//! BER stands for Basic Encoding Rules, and is defined in [[X.690]]. It defines a set of rules to
28//! encode and decode ASN.1 [[X.680]] objects in binary.
29//!
30//! [[X.690]] also defines Distinguished Encoding Rules (DER), which is BER with added rules to
31//! ensure canonical and unequivocal binary representation of objects.
32//!
33//! The choice of which one to use is usually guided by the speficication of the data format based
34//! on BER or DER: for example, X.509 uses DER as encoding representation.
35//!
36//! The main traits for parsing are the [`FromBer`] and [`FromDer`] traits.
37//! These traits provide methods to parse binary input, and return either the remaining (unparsed) bytes
38//! and the parsed object, or an error.
39//!
40//! The parsers follow the interface from [nom], and the [`ParseResult`] object is a specialized version
41//! of `nom::IResult`. This means that most `nom` combinators (`map`, `many0`, etc.) can be used in
42//! combination to objects and methods from this crate. Reading the nom documentation may
43//! help understanding how to write and combine parsers and use the output.
44//!
45//! **Minimum Supported Rust Version**: 1.63.0
46//!
47//! # Recipes
48//!
49//! See [doc::recipes] and [doc::derive] for more examples and recipes.
50//!
51//! See [doc::debug] for advice and tools to debug parsers.
52//!
53//! ## Examples
54//!
55//! Parse 2 BER integers:
56//!
57//! ```rust
58//! use asn1_rs::{Integer, FromBer};
59//!
60//! let bytes = [ 0x02, 0x03, 0x01, 0x00, 0x01,
61//!               0x02, 0x03, 0x01, 0x00, 0x00,
62//! ];
63//!
64//! let (rem, obj1) = Integer::from_ber(&bytes).expect("parsing failed");
65//! let (rem, obj2) = Integer::from_ber(&bytes).expect("parsing failed");
66//!
67//! assert_eq!(obj1, Integer::from_u32(65537));
68//! ```
69//!
70//! In the above example, the generic [`Integer`] type is used. This type can contain integers of any
71//! size, but do not provide a simple API to manipulate the numbers.
72//!
73//! In most cases, the integer either has a limit, or is expected to fit into a primitive type.
74//! To get a simple value, just use the `from_ber`/`from_der` methods on the primitive types:
75//!
76//! ```rust
77//! use asn1_rs::FromBer;
78//!
79//! let bytes = [ 0x02, 0x03, 0x01, 0x00, 0x01,
80//!               0x02, 0x03, 0x01, 0x00, 0x00,
81//! ];
82//!
83//! let (rem, obj1) = u32::from_ber(&bytes).expect("parsing failed");
84//! let (rem, obj2) = u32::from_ber(&rem).expect("parsing failed");
85//!
86//! assert_eq!(obj1, 65537);
87//! assert_eq!(obj2, 65536);
88//! ```
89//!
90//! If the parsing succeeds, but the integer cannot fit into the expected type, the method will return
91//! an `IntegerTooLarge` error.
92//!
93//! # BER/DER encoders
94//!
95//! BER/DER encoding is symmetrical to decoding, using the traits `ToBer` and [`ToDer`] traits.
96//! These traits provide methods to write encoded content to objects with the `io::Write` trait,
97//! or return an allocated `Vec<u8>` with the encoded data.
98//! If the serialization fails, an error is returned.
99//!
100//! ## Examples
101//!
102//! Writing 2 BER integers:
103//!
104//! ```rust
105//! use asn1_rs::{Integer, ToDer};
106//!
107//! let mut writer = Vec::new();
108//!
109//! let obj1 = Integer::from_u32(65537);
110//! let obj2 = Integer::from_u32(65536);
111//!
112//! let _ = obj1.write_der(&mut writer).expect("serialization failed");
113//! let _ = obj2.write_der(&mut writer).expect("serialization failed");
114//!
115//! let bytes = &[ 0x02, 0x03, 0x01, 0x00, 0x01,
116//!                0x02, 0x03, 0x01, 0x00, 0x00,
117//! ];
118//! assert_eq!(&writer, bytes);
119//! ```
120//!
121//! Similarly to `FromBer`/`FromDer`, serialization methods are also implemented for primitive types:
122//!
123//! ```rust
124//! use asn1_rs::ToDer;
125//!
126//! let mut writer = Vec::new();
127//!
128//! let _ = 65537.write_der(&mut writer).expect("serialization failed");
129//! let _ = 65536.write_der(&mut writer).expect("serialization failed");
130//!
131//! let bytes = &[ 0x02, 0x03, 0x01, 0x00, 0x01,
132//!                0x02, 0x03, 0x01, 0x00, 0x00,
133//! ];
134//! assert_eq!(&writer, bytes);
135//! ```
136//!
137//! If the parsing succeeds, but the integer cannot fit into the expected type, the method will return
138//! an `IntegerTooLarge` error.
139//!
140//! ## Changes
141//!
142//! See `CHANGELOG.md`.
143//!
144//! # References
145//!
146//! - [[X.680]] Abstract Syntax Notation One (ASN.1): Specification of basic notation.
147//! - [[X.690]] ASN.1 encoding rules: Specification of Basic Encoding Rules (BER), Canonical
148//!   Encoding Rules (CER) and Distinguished Encoding Rules (DER).
149//!
150//! [X.680]: http://www.itu.int/rec/T-REC-X.680/en "Abstract Syntax Notation One (ASN.1):
151//!   Specification of basic notation."
152//! [X.690]: https://www.itu.int/rec/T-REC-X.690/en "ASN.1 encoding rules: Specification of
153//!   Basic Encoding Rules (BER), Canonical Encoding Rules (CER) and Distinguished Encoding Rules
154//!   (DER)."
155//! [nom]: https://github.com/Geal/nom "Nom parser combinator framework"
156#![deny(/*missing_docs,*/
157    unstable_features,
158    unused_import_braces,
159    unused_qualifications,
160    // unreachable_pub
161)]
162#![forbid(unsafe_code)]
163#![warn(
164/* missing_docs,
165rust_2018_idioms,*/
166missing_debug_implementations,
167)]
168// pragmas for doc
169#![deny(rustdoc::broken_intra_doc_links)]
170#![cfg_attr(docsrs, feature(doc_cfg))]
171#![doc(test(
172no_crate_inject,
173attr(deny(warnings/*, rust_2018_idioms*/), allow(dead_code, unused_variables))
174))]
175#![cfg_attr(not(feature = "std"), no_std)]
176
177#[cfg(feature = "std")]
178extern crate core;
179
180// #[cfg(feature = "alloc")]
181extern crate alloc;
182
183mod asn1_types;
184mod ber;
185mod class;
186mod datetime;
187mod debug;
188mod derive;
189mod error;
190mod header;
191mod length;
192mod tag;
193mod traits;
194
195pub use asn1_types::*;
196pub use class::*;
197pub use datetime::*;
198pub use derive::*;
199pub use error::*;
200pub use header::*;
201pub use length::*;
202pub use tag::*;
203pub use traits::*;
204
205pub use nom;
206pub use nom::{Err, IResult, Needed};
207
208#[doc(hidden)]
209pub mod exports {
210    pub use alloc::borrow;
211    pub use asn1_rs_impl;
212}
213
214#[cfg(doc)]
215pub mod doc;