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(¶meters_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