der/
lib.rs

1#![doc = include_str!("../README.md")]
2
3//! # Usage
4//! ## [`Decodable`] and [`Encodable`] traits
5//! The [`Decodable`] and [`Encodable`] traits are the core abstractions on
6//! which this crate is built and control what types can be (de)serialized
7//! as ASN.1 DER.
8//!
9//! The traits are impl'd for the following Rust core types:
10//! - `()`: ASN.1 `NULL`. See also [`Null`].
11//! - [`bool`]: ASN.1 `BOOLEAN`.
12//! - [`i8`], [`i16`], [`i32`], [`i64`], [`i128`]: ASN.1 `INTEGER`.
13//! - [`u8`], [`u16`], [`u32`], [`u64`], [`u128`]: ASN.1 `INTEGER`.
14//! - [`str`], [`String`][`alloc::string::String`]: ASN.1 `UTF8String`.
15//!   `String` requires `alloc` feature. See also [`Utf8String`].
16//!   Requires `alloc` feature. See also [`SetOf`].
17//! - [`Option`]: ASN.1 `OPTIONAL`.
18//! - [`SystemTime`][`std::time::SystemTime`]: ASN.1 `GeneralizedTime`. Requires `std` feature.
19//! - [`Vec`][`alloc::vec::Vec`]: ASN.1 `SEQUENCE OF`. Requires `alloc` feature.
20//! - `[T; N]`: ASN.1 `SEQUENCE OF`. See also [`SequenceOf`].
21//!
22//! The following ASN.1 types provided by this crate also impl these traits:
23//! - [`Any`]: ASN.1 `ANY`
24//! - [`BitString`]: ASN.1 `BIT STRING`
25//! - [`GeneralizedTime`]: ASN.1 `GeneralizedTime`
26//! - [`Ia5String`]: ASN.1 `IA5String`
27//! - [`Null`]: ASN.1 `NULL`
28//! - [`ObjectIdentifier`]: ASN.1 `OBJECT IDENTIFIER`
29//! - [`OctetString`]: ASN.1 `OCTET STRING`
30//! - [`PrintableString`]: ASN.1 `PrintableString` (ASCII subset)
31//! - [`SequenceOf`]: ASN.1 `SEQUENCE OF`
32//! - [`SetOf`], [`SetOfVec`]: ASN.1 `SET OF`
33//! - [`UIntBytes`]: ASN.1 unsigned `INTEGER` with raw access to encoded bytes
34//! - [`UtcTime`]: ASN.1 `UTCTime`
35//! - [`Utf8String`]: ASN.1 `UTF8String`
36//!
37//! Context specific fields can be modeled using these generic types:
38//! - [`ContextSpecific`]: decoder/encoder for owned context-specific fields
39//! - [`ContextSpecificRef`]: encode-only type for references to context-specific fields
40//!
41//! ## Example
42//! The following example implements X.509's `AlgorithmIdentifier` message type
43//! as defined in [RFC 5280 Section 4.1.1.2].
44//!
45//! The ASN.1 schema for this message type is as follows:
46//!
47//! ```text
48//! AlgorithmIdentifier  ::=  SEQUENCE  {
49//!      algorithm               OBJECT IDENTIFIER,
50//!      parameters              ANY DEFINED BY algorithm OPTIONAL  }
51//! ```
52//!
53//! Structured ASN.1 messages are typically encoded as a `SEQUENCE`, which
54//! this crate maps to a Rust struct using the [`Sequence`] trait. This
55//! trait is bounded on the [`Decodable`] trait and provides a blanket impl
56//! of the [`Encodable`] trait, so any type which impls [`Sequence`] can be
57//! used for both decoding and encoding.
58//!
59//! The [`Decoder`] and [`Encoder`] types provide the decoding/encoding API
60//! respectively, and are designed to work in conjunction with concrete ASN.1
61//! types which impl the [`Decodable`] and [`Encodable`] traits, including
62//! all types which impl the [`Sequence`] trait.
63//!
64//! The following code example shows how to define a struct which maps to the
65//! above schema, as well as impl the [`Sequence`] trait for that struct:
66//!
67//! ```
68//! # #[cfg(all(feature = "alloc", feature = "oid"))]
69//! # {
70//! // Note: the following example does not require the `std` feature at all.
71//! // It does leverage the `alloc` feature, but also provides instructions for
72//! // "heapless" usage when the `alloc` feature is disabled.
73//! use der::{
74//!     asn1::{Any, ObjectIdentifier},
75//!     Decodable, Decoder, Encodable, Sequence
76//! };
77//!
78//! /// X.509 `AlgorithmIdentifier`.
79//! #[derive(Copy, Clone, Debug, Eq, PartialEq)]
80//! pub struct AlgorithmIdentifier<'a> {
81//!     /// This field contains an ASN.1 `OBJECT IDENTIFIER`, a.k.a. OID.
82//!     pub algorithm: ObjectIdentifier,
83//!
84//!     /// This field is `OPTIONAL` and contains the ASN.1 `ANY` type, which
85//!     /// in this example allows arbitrary algorithm-defined parameters.
86//!     pub parameters: Option<Any<'a>>
87//! }
88//!
89//! impl<'a> Decodable<'a> for AlgorithmIdentifier<'a> {
90//!     fn decode(decoder: &mut Decoder<'a>) -> der::Result<Self> {
91//!         // The `Decoder::sequence` method decodes an ASN.1 `SEQUENCE` tag
92//!         // and length then calls the provided `FnOnce` with a nested
93//!         // `der::Decoder` which can be used to decode it.
94//!         decoder.sequence(|decoder| {
95//!             // The `der::Decoder::Decode` method can be used to decode any
96//!             // type which impls the `Decodable` trait, which is impl'd for
97//!             // all of the ASN.1 built-in types in the `der` crate.
98//!             //
99//!             // Note that if your struct's fields don't contain an ASN.1
100//!             // built-in type specifically, there are also helper methods
101//!             // for all of the built-in types supported by this library
102//!             // which can be used to select a specific type.
103//!             //
104//!             // For example, another way of decoding this particular field,
105//!             // which contains an ASN.1 `OBJECT IDENTIFIER`, is by calling
106//!             // `decoder.oid()`. Similar methods are defined for other
107//!             // ASN.1 built-in types.
108//!             let algorithm = decoder.decode()?;
109//!
110//!             // This field contains an ASN.1 `OPTIONAL` type. The `der` crate
111//!             // maps this directly to Rust's `Option` type and provides
112//!             // impls of the `Decodable` and `Encodable` traits for `Option`.
113//!             // To explicitly request an `OPTIONAL` type be decoded, use the
114//!             // `decoder.optional()` method.
115//!             let parameters = decoder.decode()?;
116//!
117//!             // The value returned from the provided `FnOnce` will be
118//!             // returned from the `any.sequence(...)` call above.
119//!             // Note that the entire sequence body *MUST* be consumed
120//!             // or an error will be returned.
121//!             Ok(Self { algorithm, parameters })
122//!         })
123//!     }
124//! }
125//!
126//! impl<'a> Sequence<'a> for AlgorithmIdentifier<'a> {
127//!     // The `Sequence::fields` method is used for encoding and functions as
128//!     // a visitor for all of the fields in a message.
129//!     //
130//!     // To implement it, you must define a slice containing `Encodable`
131//!     // trait objects, then pass it to the provided `field_encoder`
132//!     // function, which is implemented by the `der` crate and handles
133//!     // message serialization.
134//!     //
135//!     // Trait objects are used because they allow for slices containing
136//!     // heterogeneous field types, and a callback is used to allow for the
137//!     // construction of temporary field encoder types. The latter means
138//!     // that the fields of your Rust struct don't necessarily need to
139//!     // impl the `Encodable` trait, but if they don't you must construct
140//!     // a temporary wrapper value which does.
141//!     //
142//!     // Types which impl the `Sequence` trait receive blanket impls of both
143//!     // the `Encodable` and `Tagged` traits (where the latter is impl'd as
144//!     // `Tagged::TAG = der::Tag::Sequence`.
145//!     fn fields<F, T>(&self, field_encoder: F) -> der::Result<T>
146//!     where
147//!         F: FnOnce(&[&dyn Encodable]) -> der::Result<T>,
148//!     {
149//!         field_encoder(&[&self.algorithm, &self.parameters])
150//!     }
151//! }
152//!
153//! // Example parameters value: OID for the NIST P-256 elliptic curve.
154//! let parameters = "1.2.840.10045.3.1.7".parse::<ObjectIdentifier>().unwrap();
155//!
156//! // We need to convert `parameters` into an `Any<'a>` type, which wraps a
157//! // `&'a [u8]` byte slice.
158//! //
159//! // To do that, we need owned DER-encoded data so that we can have
160//! // `Any` borrow a reference to it, so we have to serialize the OID.
161//! //
162//! // When the `alloc` feature of this crate is enabled, any type that impls
163//! // the `Encodable` trait including all ASN.1 built-in types and any type
164//! // which impls `Sequence` can be serialized by calling `Encodable::to_vec()`.
165//! //
166//! // If you would prefer to avoid allocations, you can create a byte array
167//! // as backing storage instead, pass that to `der::Encoder::new`, and then
168//! // encode the `parameters` value using `encoder.encode(parameters)`.
169//! let der_encoded_parameters = parameters.to_vec().unwrap();
170//!
171//! let algorithm_identifier = AlgorithmIdentifier {
172//!     // OID for `id-ecPublicKey`, if you're curious
173//!     algorithm: "1.2.840.10045.2.1".parse().unwrap(),
174//!
175//!     // `Any<'a>` impls `TryFrom<&'a [u8]>`, which parses the provided
176//!     // slice as an ASN.1 DER-encoded message.
177//!     parameters: Some(der_encoded_parameters.as_slice().try_into().unwrap())
178//! };
179//!
180//! // Serialize the `AlgorithmIdentifier` created above as ASN.1 DER,
181//! // allocating a `Vec<u8>` for storage.
182//! //
183//! // As mentioned earlier, if you don't have the `alloc` feature enabled you
184//! // can create a fix-sized array instead, then call `Encoder::new` with a
185//! // reference to it, then encode the message using
186//! // `encoder.encode(algorithm_identifier)`, then finally `encoder.finish()`
187//! // to obtain a byte slice containing the encoded message.
188//! let der_encoded_algorithm_identifier = algorithm_identifier.to_vec().unwrap();
189//!
190//! // Deserialize the `AlgorithmIdentifier` we just serialized from ASN.1 DER
191//! // using `der::Decodable::from_bytes`.
192//! let decoded_algorithm_identifier = AlgorithmIdentifier::from_der(
193//!     &der_encoded_algorithm_identifier
194//! ).unwrap();
195//!
196//! // Ensure the original `AlgorithmIdentifier` is the same as the one we just
197//! // decoded from ASN.1 DER.
198//! assert_eq!(algorithm_identifier, decoded_algorithm_identifier);
199//! # }
200//! ```
201//!
202//! ## Custom derive support
203//! When the `derive` feature of this crate is enabled, the following custom
204//! derive macros are available:
205//!
206//! - [`Choice`]: derive for `CHOICE` enum (see [`der_derive::Choice`])
207//! - [`Enumerated`]: derive for `ENUMERATED` enum (see [`der_derive::Enumerated`])
208//! - [`Sequence`]: derive for `SEQUENCE` struct (see [`der_derive::Sequence`])
209//!
210//! ### Derive [`Sequence`] for struct
211//! The following is a code example of how to use the [`Sequence`] custom derive:
212//!
213//! ```
214//! # #[cfg(all(feature = "alloc", feature = "derive", feature = "oid"))]
215//! # {
216//! use der::{asn1::{Any, ObjectIdentifier}, Encodable, Decodable, Sequence};
217//!
218//! /// X.509 `AlgorithmIdentifier` (same as above)
219//! #[derive(Copy, Clone, Debug, Eq, PartialEq, Sequence)] // NOTE: added `Sequence`
220//! pub struct AlgorithmIdentifier<'a> {
221//!     /// This field contains an ASN.1 `OBJECT IDENTIFIER`, a.k.a. OID.
222//!     pub algorithm: ObjectIdentifier,
223//!
224//!     /// This field is `OPTIONAL` and contains the ASN.1 `ANY` type, which
225//!     /// in this example allows arbitrary algorithm-defined parameters.
226//!     pub parameters: Option<Any<'a>>
227//! }
228//!
229//! // Example parameters value: OID for the NIST P-256 elliptic curve.
230//! let parameters_oid = "1.2.840.10045.3.1.7".parse::<ObjectIdentifier>().unwrap();
231//!
232//! let algorithm_identifier = AlgorithmIdentifier {
233//!     // OID for `id-ecPublicKey`, if you're curious
234//!     algorithm: "1.2.840.10045.2.1".parse().unwrap(),
235//!
236//!     // `Any<'a>` impls `From<&'a ObjectIdentifier>`, allowing OID constants to
237//!     // be directly converted to an `Any` type for this use case.
238//!     parameters: Some(Any::from(&parameters_oid))
239//! };
240//!
241//! // Encode
242//! let der_encoded_algorithm_identifier = algorithm_identifier.to_vec().unwrap();
243//!
244//! // Decode
245//! let decoded_algorithm_identifier = AlgorithmIdentifier::from_der(
246//!     &der_encoded_algorithm_identifier
247//! ).unwrap();
248//!
249//! assert_eq!(algorithm_identifier, decoded_algorithm_identifier);
250//! # }
251//! ```
252//!
253//! For fields which don't directly impl [`Decodable`] and [`Encodable`],
254//! you can add annotations to convert to an intermediate ASN.1 type
255//! first, so long as that type impls `TryFrom` and `Into` for the
256//! ASN.1 type.
257//!
258//! For example, structs containing `&'a [u8]` fields may want them encoded
259//! as either a `BIT STRING` or `OCTET STRING`. By using the
260//! `#[asn1(type = "BIT STRING")]` annotation it's possible to select which
261//! ASN.1 type should be used.
262//!
263//! Building off the above example:
264//!
265//! ```rust
266//! # #[cfg(all(feature = "alloc", feature = "derive", feature = "oid"))]
267//! # {
268//! # use der::{asn1::{Any, BitString, ObjectIdentifier}, Sequence};
269//! #
270//! # #[derive(Copy, Clone, Debug, Eq, PartialEq, Sequence)]
271//! # pub struct AlgorithmIdentifier<'a> {
272//! #     pub algorithm: ObjectIdentifier,
273//! #     pub parameters: Option<Any<'a>>
274//! # }
275//! /// X.509 `SubjectPublicKeyInfo` (SPKI)
276//! #[derive(Copy, Clone, Debug, Eq, PartialEq, Sequence)]
277//! pub struct SubjectPublicKeyInfo<'a> {
278//!     /// X.509 `AlgorithmIdentifier`
279//!     pub algorithm: AlgorithmIdentifier<'a>,
280//!
281//!     /// Public key data
282//!     pub subject_public_key: BitString<'a>,
283//! }
284//! # }
285//! ```
286//!
287//! # See also
288//! For more information about ASN.1 DER we recommend the following guides:
289//!
290//! - [A Layman's Guide to a Subset of ASN.1, BER, and DER] (RSA Laboratories)
291//! - [A Warm Welcome to ASN.1 and DER] (Let's Encrypt)
292//!
293//! [RFC 5280 Section 4.1.1.2]: https://tools.ietf.org/html/rfc5280#section-4.1.1.2
294//! [A Layman's Guide to a Subset of ASN.1, BER, and DER]: https://luca.ntop.org/Teaching/Appunti/asn1.html
295//! [A Warm Welcome to ASN.1 and DER]: https://letsencrypt.org/docs/a-warm-welcome-to-asn1-and-der/
296//!
297//! [`Any`]: asn1::Any
298//! [`ContextSpecific`]: asn1::ContextSpecific
299//! [`ContextSpecificRef`]: asn1::ContextSpecificRef
300//! [`BitString`]: asn1::BitString
301//! [`GeneralizedTime`]: asn1::GeneralizedTime
302//! [`Ia5String`]: asn1::Ia5String
303//! [`Null`]: asn1::Null
304//! [`ObjectIdentifier`]: asn1::ObjectIdentifier
305//! [`OctetString`]: asn1::OctetString
306//! [`PrintableString`]: asn1::PrintableString
307//! [`SequenceOf`]: asn1::SequenceOf
308//! [`SetOf`]: asn1::SetOf
309//! [`SetOfVec`]: asn1::SetOfVec
310//! [`UIntBytes`]: asn1::UIntBytes
311//! [`UtcTime`]: asn1::UtcTime
312//! [`Utf8String`]: asn1::Utf8String
313
314#![no_std]
315#![cfg_attr(docsrs, feature(doc_cfg))]
316#![doc(
317    html_logo_url = "https://raw.githubusercontent.com/RustCrypto/meta/master/logo.svg",
318    html_favicon_url = "https://raw.githubusercontent.com/RustCrypto/meta/master/logo.svg",
319    html_root_url = "https://docs.rs/der/0.5.1"
320)]
321#![forbid(unsafe_code, clippy::unwrap_used)]
322#![warn(
323    missing_docs,
324    rust_2018_idioms,
325    unused_lifetimes,
326    unused_qualifications
327)]
328
329#[cfg(feature = "alloc")]
330extern crate alloc;
331#[cfg(feature = "std")]
332extern crate std;
333
334pub mod asn1;
335
336pub(crate) mod arrayvec;
337mod byte_slice;
338mod datetime;
339mod decodable;
340mod decoder;
341mod encodable;
342mod encoder;
343mod error;
344mod header;
345mod length;
346mod ord;
347mod str_slice;
348mod tag;
349mod value;
350
351#[cfg(feature = "alloc")]
352mod document;
353
354pub use crate::{
355    asn1::{Any, Choice, Sequence},
356    datetime::DateTime,
357    decodable::Decodable,
358    decoder::Decoder,
359    encodable::Encodable,
360    encoder::Encoder,
361    error::{Error, ErrorKind, Result},
362    header::Header,
363    length::Length,
364    ord::{DerOrd, OrdIsValueOrd, ValueOrd},
365    tag::{Class, FixedTag, Tag, TagMode, TagNumber, Tagged},
366    value::{DecodeValue, EncodeValue},
367};
368
369#[cfg(feature = "alloc")]
370pub use document::Document;
371
372#[cfg(feature = "bigint")]
373#[cfg_attr(docsrs, doc(cfg(feature = "bigint")))]
374pub use crypto_bigint as bigint;
375
376#[cfg(feature = "derive")]
377#[cfg_attr(docsrs, doc(cfg(feature = "derive")))]
378pub use der_derive::{Choice, Enumerated, Sequence, ValueOrd};
379
380#[cfg(feature = "pem")]
381#[cfg_attr(docsrs, doc(cfg(feature = "pem")))]
382pub use pem_rfc7468 as pem;
383
384#[cfg(feature = "time")]
385#[cfg_attr(docsrs, doc(cfg(feature = "time")))]
386pub use time;
387
388pub(crate) use crate::{arrayvec::ArrayVec, byte_slice::ByteSlice, str_slice::StrSlice};