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