//! [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](./LICENSE-MIT) //! [![Apache License 2.0](https://img.shields.io/badge/License-Apache%202.0-blue.svg)](./LICENSE-APACHE) //! [![docs.rs](https://docs.rs/asn1-rs/badge.svg)](https://docs.rs/asn1-rs) //! [![crates.io](https://img.shields.io/crates/v/asn1-rs.svg)](https://crates.io/crates/asn1-rs) //! [![Download numbers](https://img.shields.io/crates/d/asn1-rs.svg)](https://crates.io/crates/asn1-rs) //! [![Github CI](https://github.com/rusticata/asn1-rs/workflows/Continuous%20integration/badge.svg)](https://github.com/rusticata/asn1-rs/actions) //! [![Minimum rustc version](https://img.shields.io/badge/rustc-1.53.0+-lightgray.svg)](#rust-version-requirements) //! //! # BER/DER Parsers/Encoders //! //! A set of parsers/encoders for Basic Encoding Rules (BER [[X.690]]) and Distinguished Encoding Rules(DER //! [[X.690]]) formats, implemented with the [nom] parser combinator framework. //! //! It is written in pure Rust, fast, and makes extensive use of zero-copy. A lot of care is taken //! to ensure security and safety of this crate, including design (recursion limit, defensive //! programming), tests, and fuzzing. It also aims to be panic-free. //! //! This crate is a rewrite of [der-parser](https://crates.io/crates/der-parser) to propose a more data-oriented API, //! and add generalized support for serialization. //! //! Many ideas were borrowed from the [crypto/utils/der](https://github.com/RustCrypto/utils/tree/master/der) crate (like //! the `Any`/`TryFrom`/`FromDer` mechanism), adapted and merged into a generalized BER/DER crate. //! Credits (and many thanks) go to Tony Arcieri for writing the original crate. //! //! # BER/DER parsers //! //! BER stands for Basic Encoding Rules, and is defined in [[X.690]]. It defines a set of rules to //! encode and decode ASN.1 [[X.680]] objects in binary. //! //! [[X.690]] also defines Distinguished Encoding Rules (DER), which is BER with added rules to //! ensure canonical and unequivocal binary representation of objects. //! //! The choice of which one to use is usually guided by the speficication of the data format based //! on BER or DER: for example, X.509 uses DER as encoding representation. //! //! The main traits for parsing are the [`FromBer`] and [`FromDer`] traits. //! These traits provide methods to parse binary input, and return either the remaining (unparsed) bytes //! and the parsed object, or an error. //! //! The parsers follow the interface from [nom], and the [`ParseResult`] object is a specialized version //! of `nom::IResult`. This means that most `nom` combinators (`map`, `many0`, etc.) can be used in //! combination to objects and methods from this crate. Reading the nom documentation may //! help understanding how to write and combine parsers and use the output. //! //! **Minimum Supported Rust Version**: 1.53.0 //! //! Note: if the `bits` feature is enabled, MSRV is 1.56.0 (due to `bitvec` 1.0) //! //! # Recipes //! //! See [doc::recipes] and [doc::derive] for more examples and recipes. //! //! ## Examples //! //! Parse 2 BER integers: //! //! ```rust //! use asn1_rs::{Integer, FromBer}; //! //! let bytes = [ 0x02, 0x03, 0x01, 0x00, 0x01, //! 0x02, 0x03, 0x01, 0x00, 0x00, //! ]; //! //! let (rem, obj1) = Integer::from_ber(&bytes).expect("parsing failed"); //! let (rem, obj2) = Integer::from_ber(&bytes).expect("parsing failed"); //! //! assert_eq!(obj1, Integer::from_u32(65537)); //! ``` //! //! In the above example, the generic [`Integer`] type is used. This type can contain integers of any //! size, but do not provide a simple API to manipulate the numbers. //! //! In most cases, the integer either has a limit, or is expected to fit into a primitive type. //! To get a simple value, just use the `from_ber`/`from_der` methods on the primitive types: //! //! ```rust //! use asn1_rs::FromBer; //! //! let bytes = [ 0x02, 0x03, 0x01, 0x00, 0x01, //! 0x02, 0x03, 0x01, 0x00, 0x00, //! ]; //! //! let (rem, obj1) = u32::from_ber(&bytes).expect("parsing failed"); //! let (rem, obj2) = u32::from_ber(&rem).expect("parsing failed"); //! //! assert_eq!(obj1, 65537); //! assert_eq!(obj2, 65536); //! ``` //! //! If the parsing succeeds, but the integer cannot fit into the expected type, the method will return //! an `IntegerTooLarge` error. //! //! # BER/DER encoders //! //! BER/DER encoding is symmetrical to decoding, using the traits `ToBer` and [`ToDer`] traits. //! These traits provide methods to write encoded content to objects with the `io::Write` trait, //! or return an allocated `Vec` with the encoded data. //! If the serialization fails, an error is returned. //! //! ## Examples //! //! Writing 2 BER integers: //! //! ```rust //! use asn1_rs::{Integer, ToDer}; //! //! let mut writer = Vec::new(); //! //! let obj1 = Integer::from_u32(65537); //! let obj2 = Integer::from_u32(65536); //! //! let _ = obj1.write_der(&mut writer).expect("serialization failed"); //! let _ = obj2.write_der(&mut writer).expect("serialization failed"); //! //! let bytes = &[ 0x02, 0x03, 0x01, 0x00, 0x01, //! 0x02, 0x03, 0x01, 0x00, 0x00, //! ]; //! assert_eq!(&writer, bytes); //! ``` //! //! Similarly to `FromBer`/`FromDer`, serialization methods are also implemented for primitive types: //! //! ```rust //! use asn1_rs::ToDer; //! //! let mut writer = Vec::new(); //! //! let _ = 65537.write_der(&mut writer).expect("serialization failed"); //! let _ = 65536.write_der(&mut writer).expect("serialization failed"); //! //! let bytes = &[ 0x02, 0x03, 0x01, 0x00, 0x01, //! 0x02, 0x03, 0x01, 0x00, 0x00, //! ]; //! assert_eq!(&writer, bytes); //! ``` //! //! If the parsing succeeds, but the integer cannot fit into the expected type, the method will return //! an `IntegerTooLarge` error. //! //! ## Changes //! //! See `CHANGELOG.md`. //! //! # References //! //! - [[X.680]] Abstract Syntax Notation One (ASN.1): Specification of basic notation. //! - [[X.690]] ASN.1 encoding rules: Specification of Basic Encoding Rules (BER), Canonical //! Encoding Rules (CER) and Distinguished Encoding Rules (DER). //! //! [X.680]: http://www.itu.int/rec/T-REC-X.680/en "Abstract Syntax Notation One (ASN.1): //! Specification of basic notation." //! [X.690]: https://www.itu.int/rec/T-REC-X.690/en "ASN.1 encoding rules: Specification of //! Basic Encoding Rules (BER), Canonical Encoding Rules (CER) and Distinguished Encoding Rules //! (DER)." //! [nom]: https://github.com/Geal/nom "Nom parser combinator framework" #![deny(/*missing_docs,*/ unstable_features, unused_import_braces, unused_qualifications, // unreachable_pub )] #![forbid(unsafe_code)] #![warn( /* missing_docs, rust_2018_idioms,*/ missing_debug_implementations, )] // pragmas for doc #![deny(rustdoc::broken_intra_doc_links)] #![cfg_attr(docsrs, feature(doc_cfg))] #![doc(test( no_crate_inject, attr(deny(warnings/*, rust_2018_idioms*/), allow(dead_code, unused_variables)) ))] #![cfg_attr(not(feature = "std"), no_std)] #[cfg(feature = "std")] extern crate core; // #[cfg(feature = "alloc")] extern crate alloc; mod asn1_types; mod ber; mod class; mod datetime; mod derive; mod error; mod header; mod length; mod tag; mod traits; pub use asn1_types::*; pub use class::*; pub use datetime::*; pub use derive::*; pub use error::*; pub use header::*; pub use length::*; pub use tag::*; pub use traits::*; pub use nom; pub use nom::{Err, IResult, Needed}; #[doc(hidden)] pub mod exports { pub use alloc::borrow; pub use asn1_rs_impl; } #[cfg(doc)] pub mod doc;