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#![cfg_attr(feature = "std", doc = r#"```rust"#)]
105#![cfg_attr(not(feature = "std"), doc = r#"```rust,compile_fail"#)]
106//! use asn1_rs::{Integer, ToDer};
107//!
108//! let mut writer = Vec::new();
109//!
110//! let obj1 = Integer::from_u32(65537);
111//! let obj2 = Integer::from_u32(65536);
112//!
113//! let _ = obj1.write_der(&mut writer).expect("serialization failed");
114//! let _ = obj2.write_der(&mut writer).expect("serialization failed");
115//!
116//! let bytes = &[ 0x02, 0x03, 0x01, 0x00, 0x01,
117//!                0x02, 0x03, 0x01, 0x00, 0x00,
118//! ];
119//! assert_eq!(&writer, bytes);
120//! ```
121//!
122//! Similarly to `FromBer`/`FromDer`, serialization methods are also implemented for primitive types:
123//!
124#![cfg_attr(feature = "std", doc = r#"```rust"#)]
125#![cfg_attr(not(feature = "std"), doc = r#"```rust,compile_fail"#)]
126//! use asn1_rs::ToDer;
127//!
128//! let mut writer = Vec::new();
129//!
130//! let _ = 65537.write_der(&mut writer).expect("serialization failed");
131//! let _ = 65536.write_der(&mut writer).expect("serialization failed");
132//!
133//! let bytes = &[ 0x02, 0x03, 0x01, 0x00, 0x01,
134//!                0x02, 0x03, 0x01, 0x00, 0x00,
135//! ];
136//! assert_eq!(&writer, bytes);
137//! ```
138//!
139//! If the parsing succeeds, but the integer cannot fit into the expected type, the method will return
140//! an `IntegerTooLarge` error.
141//!
142//! ## Changes
143//!
144//! See `CHANGELOG.md`.
145//!
146//! # References
147//!
148//! - [[X.680]] Abstract Syntax Notation One (ASN.1): Specification of basic notation.
149//! - [[X.690]] ASN.1 encoding rules: Specification of Basic Encoding Rules (BER), Canonical
150//!   Encoding Rules (CER) and Distinguished Encoding Rules (DER).
151//!
152//! [X.680]: http://www.itu.int/rec/T-REC-X.680/en "Abstract Syntax Notation One (ASN.1):
153//!   Specification of basic notation."
154//! [X.690]: https://www.itu.int/rec/T-REC-X.690/en "ASN.1 encoding rules: Specification of
155//!   Basic Encoding Rules (BER), Canonical Encoding Rules (CER) and Distinguished Encoding Rules
156//!   (DER)."
157//! [nom]: https://github.com/Geal/nom "Nom parser combinator framework"
158#![deny(/*missing_docs,*/
159    unstable_features,
160    unused_import_braces,
161    unused_qualifications,
162    // unreachable_pub
163)]
164#![forbid(unsafe_code)]
165#![warn(
166/* missing_docs,
167rust_2018_idioms,*/
168missing_debug_implementations,
169)]
170// pragmas for doc
171#![deny(rustdoc::broken_intra_doc_links)]
172#![cfg_attr(docsrs, feature(doc_cfg))]
173#![doc(test(
174no_crate_inject,
175attr(deny(warnings/*, rust_2018_idioms*/), allow(dead_code, unused_variables))
176))]
177#![cfg_attr(not(feature = "std"), no_std)]
178
179#[cfg(feature = "std")]
180extern crate core;
181
182// #[cfg(feature = "alloc")]
183extern crate alloc;
184
185mod asn1_types;
186mod ber;
187mod class;
188mod datetime;
189mod debug;
190mod derive;
191mod error;
192mod header;
193mod length;
194mod tag;
195mod tostatic;
196mod traits;
197
198pub use asn1_types::*;
199pub use class::*;
200pub use datetime::*;
201pub use derive::*;
202pub use error::*;
203pub use header::*;
204pub use length::*;
205pub use tag::*;
206pub use traits::*;
207
208pub use nom;
209pub use nom::{Err, IResult, Needed};
210
211#[doc(hidden)]
212pub mod exports {
213    pub use alloc::borrow;
214    pub use asn1_rs_impl;
215}
216
217#[cfg(doc)]
218pub mod doc;