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