rustls_pki_types/
lib.rs

1//! This crate provides types for representing X.509 certificates, keys and other types as
2//! commonly used in the rustls ecosystem. It is intended to be used by crates that need to work
3//! with such X.509 types, such as [rustls](https://crates.io/crates/rustls),
4//! [rustls-webpki](https://crates.io/crates/rustls-webpki),
5//! [rustls-pemfile](https://crates.io/crates/rustls-pemfile), and others.
6//!
7//! Some of these crates used to define their own trivial wrappers around DER-encoded bytes.
8//! However, in order to avoid inconvenient dependency edges, these were all disconnected. By
9//! using a common low-level crate of types with long-term stable API, we hope to avoid the
10//! downsides of unnecessary dependency edges while providing good interoperability between crates.
11//!
12//! ## DER and PEM
13//!
14//! Many of the types defined in this crate represent DER-encoded data. DER is a binary encoding of
15//! the ASN.1 format commonly used in web PKI specifications. It is a binary encoding, so it is
16//! relatively compact when stored in memory. However, as a binary format, it is not very easy to
17//! work with for humans and in contexts where binary data is inconvenient. For this reason,
18//! many tools and protocols use a ASCII-based encoding of DER, called PEM. In addition to the
19//! base64-encoded DER, PEM objects are delimited by header and footer lines which indicate the type
20//! of object contained in the PEM blob.
21//!
22//! Types here can be created from:
23//!
24//! - DER using (for example) [`PrivatePkcs8KeyDer::from()`].
25//! - PEM using (for example) [`pem::PemObject::from_pem_slice()`].
26//!
27//! The [`pem::PemObject`] trait contains the full selection of ways to construct
28//! these types from PEM encodings.  That includes ways to open and read from a file,
29//! from a slice, or from an `std::io` stream.
30//!
31//! There is also a lower-level API that allows a given PEM file to be fully consumed
32//! in one pass, even if it contains different data types: see the implementation of
33//! the [`pem::PemObject`] trait on the `(pem::SectionKind, Vec<u8>)` tuple.
34//!
35//! ## Creating new certificates and keys
36//!
37//! This crate does not provide any functionality for creating new certificates or keys. However,
38//! the [rcgen](https://docs.rs/rcgen) crate can be used to create new certificates and keys.
39//!
40//! ## Cloning private keys
41//!
42//! This crate intentionally **does not** implement `Clone` on private key types in
43//! order to minimize the exposure of private key data in memory.
44//!
45//! If you want to extend the lifetime of a `PrivateKeyDer<'_>`, consider [`PrivateKeyDer::clone_key()`].
46//! Alternatively  since these types are immutable, consider wrapping the `PrivateKeyDer<'_>` in a [`Rc`]
47//! or an [`Arc`].
48//!
49//! [`Rc`]: https://doc.rust-lang.org/std/rc/struct.Rc.html
50//! [`Arc`]: https://doc.rust-lang.org/std/sync/struct.Arc.html
51//! [`PrivateKeyDer::clone_key()`]: https://docs.rs/rustls-pki-types/latest/rustls_pki_types/enum.PrivateKeyDer.html#method.clone_key
52//!
53//! ## Target `wasm32-unknown-unknown` with the `web` feature
54//!
55//! [`std::time::SystemTime`](https://doc.rust-lang.org/std/time/struct.SystemTime.html)
56//! is unavailable in `wasm32-unknown-unknown` targets, so calls to
57//! [`UnixTime::now()`](https://docs.rs/rustls-pki-types/latest/rustls_pki_types/struct.UnixTime.html#method.now),
58//! otherwise enabled by the [`std`](https://docs.rs/crate/rustls-pki-types/latest/features#std) feature,
59//! require building instead with the [`web`](https://docs.rs/crate/rustls-pki-types/latest/features#web)
60//! feature. It gets time by calling [`Date.now()`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Date/now)
61//! in the browser.
62
63#![cfg_attr(not(feature = "std"), no_std)]
64#![warn(
65    missing_docs,
66    clippy::exhaustive_enums,
67    clippy::exhaustive_structs,
68    clippy::use_self
69)]
70#![cfg_attr(rustls_pki_types_docsrs, feature(doc_cfg))]
71
72#[cfg(feature = "alloc")]
73extern crate alloc;
74
75#[cfg(feature = "alloc")]
76use alloc::vec::Vec;
77use core::fmt;
78use core::ops::Deref;
79use core::time::Duration;
80#[cfg(feature = "alloc")]
81use pem::{PemObject, PemObjectFilter, SectionKind};
82#[cfg(all(
83    feature = "std",
84    not(all(target_family = "wasm", target_os = "unknown"))
85))]
86use std::time::SystemTime;
87#[cfg(all(target_family = "wasm", target_os = "unknown", feature = "web"))]
88use web_time::SystemTime;
89
90pub mod alg_id;
91mod base64;
92mod server_name;
93
94/// Low-level PEM decoding APIs.
95///
96/// These APIs allow decoding PEM format in an iterator, which means you
97/// can load multiple different types of PEM section from a file in a single
98/// pass.
99#[cfg(feature = "alloc")]
100pub mod pem;
101
102pub use alg_id::AlgorithmIdentifier;
103pub use server_name::{
104    AddrParseError, DnsName, InvalidDnsNameError, IpAddr, Ipv4Addr, Ipv6Addr, ServerName,
105};
106
107/// A DER-encoded X.509 private key, in one of several formats
108///
109/// See variant inner types for more detailed information.
110///
111/// This can load several types of PEM-encoded private key, and then reveal
112/// which types were found:
113///
114/// ```rust
115/// # #[cfg(all(feature = "alloc", feature = "std"))] {
116/// use rustls_pki_types::{PrivateKeyDer, pem::PemObject};
117///
118/// // load from a PEM file
119/// let pkcs8 = PrivateKeyDer::from_pem_file("tests/data/nistp256key.pkcs8.pem").unwrap();
120/// let pkcs1 = PrivateKeyDer::from_pem_file("tests/data/rsa1024.pkcs1.pem").unwrap();
121/// let sec1 = PrivateKeyDer::from_pem_file("tests/data/nistp256key.pem").unwrap();
122/// assert!(matches!(pkcs8, PrivateKeyDer::Pkcs8(_)));
123/// assert!(matches!(pkcs1, PrivateKeyDer::Pkcs1(_)));
124/// assert!(matches!(sec1, PrivateKeyDer::Sec1(_)));
125/// # }
126/// ```
127#[non_exhaustive]
128#[derive(Debug, PartialEq, Eq)]
129pub enum PrivateKeyDer<'a> {
130    /// An RSA private key
131    Pkcs1(PrivatePkcs1KeyDer<'a>),
132    /// A Sec1 private key
133    Sec1(PrivateSec1KeyDer<'a>),
134    /// A PKCS#8 private key
135    Pkcs8(PrivatePkcs8KeyDer<'a>),
136}
137
138#[cfg(feature = "alloc")]
139impl zeroize::Zeroize for PrivateKeyDer<'static> {
140    fn zeroize(&mut self) {
141        match self {
142            Self::Pkcs1(key) => key.zeroize(),
143            Self::Sec1(key) => key.zeroize(),
144            Self::Pkcs8(key) => key.zeroize(),
145        }
146    }
147}
148
149impl PrivateKeyDer<'_> {
150    /// Clone the private key to a `'static` value
151    #[cfg(feature = "alloc")]
152    pub fn clone_key(&self) -> PrivateKeyDer<'static> {
153        use PrivateKeyDer::*;
154        match self {
155            Pkcs1(key) => Pkcs1(key.clone_key()),
156            Sec1(key) => Sec1(key.clone_key()),
157            Pkcs8(key) => Pkcs8(key.clone_key()),
158        }
159    }
160
161    /// Yield the DER-encoded bytes of the private key
162    pub fn secret_der(&self) -> &[u8] {
163        match self {
164            PrivateKeyDer::Pkcs1(key) => key.secret_pkcs1_der(),
165            PrivateKeyDer::Sec1(key) => key.secret_sec1_der(),
166            PrivateKeyDer::Pkcs8(key) => key.secret_pkcs8_der(),
167        }
168    }
169}
170
171#[cfg(feature = "alloc")]
172impl PemObject for PrivateKeyDer<'static> {
173    fn from_pem(kind: SectionKind, value: Vec<u8>) -> Option<Self> {
174        match kind {
175            SectionKind::RsaPrivateKey => Some(Self::Pkcs1(value.into())),
176            SectionKind::EcPrivateKey => Some(Self::Sec1(value.into())),
177            SectionKind::PrivateKey => Some(Self::Pkcs8(value.into())),
178            _ => None,
179        }
180    }
181}
182
183impl<'a> From<PrivatePkcs1KeyDer<'a>> for PrivateKeyDer<'a> {
184    fn from(key: PrivatePkcs1KeyDer<'a>) -> Self {
185        Self::Pkcs1(key)
186    }
187}
188
189impl<'a> From<PrivateSec1KeyDer<'a>> for PrivateKeyDer<'a> {
190    fn from(key: PrivateSec1KeyDer<'a>) -> Self {
191        Self::Sec1(key)
192    }
193}
194
195impl<'a> From<PrivatePkcs8KeyDer<'a>> for PrivateKeyDer<'a> {
196    fn from(key: PrivatePkcs8KeyDer<'a>) -> Self {
197        Self::Pkcs8(key)
198    }
199}
200
201impl<'a> TryFrom<&'a [u8]> for PrivateKeyDer<'a> {
202    type Error = &'static str;
203
204    fn try_from(key: &'a [u8]) -> Result<Self, Self::Error> {
205        const SHORT_FORM_LEN_MAX: u8 = 128;
206        const TAG_SEQUENCE: u8 = 0x30;
207        const TAG_INTEGER: u8 = 0x02;
208
209        // We expect all key formats to begin with a SEQUENCE, which requires at least 2 bytes
210        // in the short length encoding.
211        if key.first() != Some(&TAG_SEQUENCE) || key.len() < 2 {
212            return Err(INVALID_KEY_DER_ERR);
213        }
214
215        // The length of the SEQUENCE is encoded in the second byte. We must skip this many bytes.
216        let skip_len = match key[1] >= SHORT_FORM_LEN_MAX {
217            // 1 byte for SEQUENCE tag, 1 byte for short-form len
218            false => 2,
219            // 1 byte for SEQUENCE tag, 1 byte for start of len, remaining bytes encoded
220            // in key[1].
221            true => 2 + (key[1] - SHORT_FORM_LEN_MAX) as usize,
222        };
223        let key_bytes = key.get(skip_len..).ok_or(INVALID_KEY_DER_ERR)?;
224
225        // PKCS#8 (https://www.rfc-editor.org/rfc/rfc5208) describes the PrivateKeyInfo
226        // structure as:
227        //   PrivateKeyInfo ::= SEQUENCE {
228        //      version Version,
229        //      privateKeyAlgorithm AlgorithmIdentifier {{PrivateKeyAlgorithms}},
230        //      privateKey PrivateKey,
231        //      attributes [0] Attributes OPTIONAL
232        //   }
233        // PKCS#5 (https://www.rfc-editor.org/rfc/rfc8018) describes the AlgorithmIdentifier
234        // as a SEQUENCE.
235        //
236        // Therefore, we consider the outer SEQUENCE, a version number, and the start of
237        // an AlgorithmIdentifier to be enough to identify a PKCS#8 key. If it were PKCS#1 or SEC1
238        // the version would not be followed by a SEQUENCE.
239        if matches!(key_bytes, [TAG_INTEGER, 0x01, _, TAG_SEQUENCE, ..]) {
240            return Ok(Self::Pkcs8(key.into()));
241        }
242
243        // PKCS#1 (https://www.rfc-editor.org/rfc/rfc8017) describes the RSAPrivateKey structure
244        // as:
245        //  RSAPrivateKey ::= SEQUENCE {
246        //              version           Version,
247        //              modulus           INTEGER,  -- n
248        //              publicExponent    INTEGER,  -- e
249        //              privateExponent   INTEGER,  -- d
250        //              prime1            INTEGER,  -- p
251        //              prime2            INTEGER,  -- q
252        //              exponent1         INTEGER,  -- d mod (p-1)
253        //              exponent2         INTEGER,  -- d mod (q-1)
254        //              coefficient       INTEGER,  -- (inverse of q) mod p
255        //              otherPrimeInfos   OtherPrimeInfos OPTIONAL
256        //          }
257        //
258        // Therefore, we consider the outer SEQUENCE and a Version of 0 to be enough to identify
259        // a PKCS#1 key. If it were PKCS#8, the version would be followed by a SEQUENCE. If it
260        // were SEC1, the VERSION would have been 1.
261        if key_bytes.starts_with(&[TAG_INTEGER, 0x01, 0x00]) {
262            return Ok(Self::Pkcs1(key.into()));
263        }
264
265        // SEC1 (https://www.rfc-editor.org/rfc/rfc5915) describes the ECPrivateKey structure as:
266        //   ECPrivateKey ::= SEQUENCE {
267        //      version        INTEGER { ecPrivkeyVer1(1) } (ecPrivkeyVer1),
268        //      privateKey     OCTET STRING,
269        //      parameters [0] ECParameters {{ NamedCurve }} OPTIONAL,
270        //      publicKey  [1] BIT STRING OPTIONAL
271        //   }
272        //
273        // Therefore, we consider the outer SEQUENCE and an INTEGER of 1 to be enough to
274        // identify a SEC1 key. If it were PKCS#8 or PKCS#1, the version would have been 0.
275        if key_bytes.starts_with(&[TAG_INTEGER, 0x01, 0x01]) {
276            return Ok(Self::Sec1(key.into()));
277        }
278
279        Err(INVALID_KEY_DER_ERR)
280    }
281}
282
283static INVALID_KEY_DER_ERR: &str = "unknown or invalid key format";
284
285#[cfg(feature = "alloc")]
286impl TryFrom<Vec<u8>> for PrivateKeyDer<'_> {
287    type Error = &'static str;
288
289    fn try_from(key: Vec<u8>) -> Result<Self, Self::Error> {
290        Ok(match PrivateKeyDer::try_from(&key[..])? {
291            PrivateKeyDer::Pkcs1(_) => Self::Pkcs1(key.into()),
292            PrivateKeyDer::Sec1(_) => Self::Sec1(key.into()),
293            PrivateKeyDer::Pkcs8(_) => Self::Pkcs8(key.into()),
294        })
295    }
296}
297
298/// A DER-encoded plaintext RSA private key; as specified in PKCS#1/RFC 3447
299///
300/// RSA private keys are identified in PEM context as `RSA PRIVATE KEY` and when stored in a
301/// file usually use a `.pem` or `.key` extension.
302///
303/// ```rust
304/// # #[cfg(all(feature = "alloc", feature = "std"))] {
305/// use rustls_pki_types::{PrivatePkcs1KeyDer, pem::PemObject};
306///
307/// // load from a PEM file
308/// PrivatePkcs1KeyDer::from_pem_file("tests/data/rsa1024.pkcs1.pem").unwrap();
309///
310/// // or from a PEM byte slice...
311/// # let byte_slice = include_bytes!("../tests/data/rsa1024.pkcs1.pem");
312/// PrivatePkcs1KeyDer::from_pem_slice(byte_slice).unwrap();
313/// # }
314/// ```
315#[derive(PartialEq, Eq)]
316pub struct PrivatePkcs1KeyDer<'a>(Der<'a>);
317
318impl PrivatePkcs1KeyDer<'_> {
319    /// Clone the private key to a `'static` value
320    #[cfg(feature = "alloc")]
321    pub fn clone_key(&self) -> PrivatePkcs1KeyDer<'static> {
322        PrivatePkcs1KeyDer::from(self.0.as_ref().to_vec())
323    }
324
325    /// Yield the DER-encoded bytes of the private key
326    pub fn secret_pkcs1_der(&self) -> &[u8] {
327        self.0.as_ref()
328    }
329}
330
331#[cfg(feature = "alloc")]
332impl zeroize::Zeroize for PrivatePkcs1KeyDer<'static> {
333    fn zeroize(&mut self) {
334        self.0.0.zeroize()
335    }
336}
337
338#[cfg(feature = "alloc")]
339impl PemObjectFilter for PrivatePkcs1KeyDer<'static> {
340    const KIND: SectionKind = SectionKind::RsaPrivateKey;
341}
342
343impl<'a> From<&'a [u8]> for PrivatePkcs1KeyDer<'a> {
344    fn from(slice: &'a [u8]) -> Self {
345        Self(Der(BytesInner::Borrowed(slice)))
346    }
347}
348
349#[cfg(feature = "alloc")]
350impl From<Vec<u8>> for PrivatePkcs1KeyDer<'_> {
351    fn from(vec: Vec<u8>) -> Self {
352        Self(Der(BytesInner::Owned(vec)))
353    }
354}
355
356impl fmt::Debug for PrivatePkcs1KeyDer<'_> {
357    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
358        f.debug_tuple("PrivatePkcs1KeyDer")
359            .field(&"[secret key elided]")
360            .finish()
361    }
362}
363
364/// A Sec1-encoded plaintext private key; as specified in RFC 5915
365///
366/// Sec1 private keys are identified in PEM context as `EC PRIVATE KEY` and when stored in a
367/// file usually use a `.pem` or `.key` extension. For more on PEM files, refer to the crate
368/// documentation.
369///
370/// ```rust
371/// # #[cfg(all(feature = "alloc", feature = "std"))] {
372/// use rustls_pki_types::{PrivateSec1KeyDer, pem::PemObject};
373///
374/// // load from a PEM file
375/// PrivateSec1KeyDer::from_pem_file("tests/data/nistp256key.pem").unwrap();
376///
377/// // or from a PEM byte slice...
378/// # let byte_slice = include_bytes!("../tests/data/nistp256key.pem");
379/// PrivateSec1KeyDer::from_pem_slice(byte_slice).unwrap();
380/// # }
381/// ```
382#[derive(PartialEq, Eq)]
383pub struct PrivateSec1KeyDer<'a>(Der<'a>);
384
385impl PrivateSec1KeyDer<'_> {
386    /// Clone the private key to a `'static` value
387    #[cfg(feature = "alloc")]
388    pub fn clone_key(&self) -> PrivateSec1KeyDer<'static> {
389        PrivateSec1KeyDer::from(self.0.as_ref().to_vec())
390    }
391
392    /// Yield the DER-encoded bytes of the private key
393    pub fn secret_sec1_der(&self) -> &[u8] {
394        self.0.as_ref()
395    }
396}
397
398#[cfg(feature = "alloc")]
399impl zeroize::Zeroize for PrivateSec1KeyDer<'static> {
400    fn zeroize(&mut self) {
401        self.0.0.zeroize()
402    }
403}
404
405#[cfg(feature = "alloc")]
406impl PemObjectFilter for PrivateSec1KeyDer<'static> {
407    const KIND: SectionKind = SectionKind::EcPrivateKey;
408}
409
410impl<'a> From<&'a [u8]> for PrivateSec1KeyDer<'a> {
411    fn from(slice: &'a [u8]) -> Self {
412        Self(Der(BytesInner::Borrowed(slice)))
413    }
414}
415
416#[cfg(feature = "alloc")]
417impl From<Vec<u8>> for PrivateSec1KeyDer<'_> {
418    fn from(vec: Vec<u8>) -> Self {
419        Self(Der(BytesInner::Owned(vec)))
420    }
421}
422
423impl fmt::Debug for PrivateSec1KeyDer<'_> {
424    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
425        f.debug_tuple("PrivateSec1KeyDer")
426            .field(&"[secret key elided]")
427            .finish()
428    }
429}
430
431/// A DER-encoded plaintext private key; as specified in PKCS#8/RFC 5958
432///
433/// PKCS#8 private keys are identified in PEM context as `PRIVATE KEY` and when stored in a
434/// file usually use a `.pem` or `.key` extension. For more on PEM files, refer to the crate
435/// documentation.
436///
437/// ```rust
438/// # #[cfg(all(feature = "alloc", feature = "std"))] {
439/// use rustls_pki_types::{PrivatePkcs8KeyDer, pem::PemObject};
440///
441/// // load from a PEM file
442/// PrivatePkcs8KeyDer::from_pem_file("tests/data/nistp256key.pkcs8.pem").unwrap();
443/// PrivatePkcs8KeyDer::from_pem_file("tests/data/rsa1024.pkcs8.pem").unwrap();
444///
445/// // or from a PEM byte slice...
446/// # let byte_slice = include_bytes!("../tests/data/nistp256key.pkcs8.pem");
447/// PrivatePkcs8KeyDer::from_pem_slice(byte_slice).unwrap();
448/// # }
449/// ```
450#[derive(PartialEq, Eq)]
451pub struct PrivatePkcs8KeyDer<'a>(Der<'a>);
452
453impl PrivatePkcs8KeyDer<'_> {
454    /// Clone the private key to a `'static` value
455    #[cfg(feature = "alloc")]
456    pub fn clone_key(&self) -> PrivatePkcs8KeyDer<'static> {
457        PrivatePkcs8KeyDer::from(self.0.as_ref().to_vec())
458    }
459
460    /// Yield the DER-encoded bytes of the private key
461    pub fn secret_pkcs8_der(&self) -> &[u8] {
462        self.0.as_ref()
463    }
464}
465
466#[cfg(feature = "alloc")]
467impl zeroize::Zeroize for PrivatePkcs8KeyDer<'static> {
468    fn zeroize(&mut self) {
469        self.0.0.zeroize()
470    }
471}
472
473#[cfg(feature = "alloc")]
474impl PemObjectFilter for PrivatePkcs8KeyDer<'static> {
475    const KIND: SectionKind = SectionKind::PrivateKey;
476}
477
478impl<'a> From<&'a [u8]> for PrivatePkcs8KeyDer<'a> {
479    fn from(slice: &'a [u8]) -> Self {
480        Self(Der(BytesInner::Borrowed(slice)))
481    }
482}
483
484#[cfg(feature = "alloc")]
485impl From<Vec<u8>> for PrivatePkcs8KeyDer<'_> {
486    fn from(vec: Vec<u8>) -> Self {
487        Self(Der(BytesInner::Owned(vec)))
488    }
489}
490
491impl fmt::Debug for PrivatePkcs8KeyDer<'_> {
492    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
493        f.debug_tuple("PrivatePkcs8KeyDer")
494            .field(&"[secret key elided]")
495            .finish()
496    }
497}
498
499/// A trust anchor (a.k.a. root CA)
500///
501/// Traditionally, certificate verification libraries have represented trust anchors as full X.509
502/// root certificates. However, those certificates contain a lot more data than is needed for
503/// verifying certificates. The [`TrustAnchor`] representation allows an application to store
504/// just the essential elements of trust anchors.
505///
506/// The most common way to get one of these is to call [`rustls_webpki::anchor_from_trusted_cert()`].
507///
508/// [`rustls_webpki::anchor_from_trusted_cert()`]: https://docs.rs/rustls-webpki/latest/webpki/fn.anchor_from_trusted_cert.html
509#[allow(clippy::exhaustive_structs)]
510#[derive(Clone, Debug, Hash, PartialEq, Eq)]
511pub struct TrustAnchor<'a> {
512    /// Value of the `subject` field of the trust anchor
513    pub subject: Der<'a>,
514    /// Value of the `subjectPublicKeyInfo` field of the trust anchor
515    pub subject_public_key_info: Der<'a>,
516    /// Value of DER-encoded `NameConstraints`, containing name constraints to the trust anchor, if any
517    pub name_constraints: Option<Der<'a>>,
518}
519
520impl TrustAnchor<'_> {
521    /// Yield a `'static` lifetime of the `TrustAnchor` by allocating owned `Der` variants
522    #[cfg(feature = "alloc")]
523    pub fn to_owned(&self) -> TrustAnchor<'static> {
524        #[cfg(not(feature = "std"))]
525        use alloc::borrow::ToOwned;
526        TrustAnchor {
527            subject: self.subject.as_ref().to_owned().into(),
528            subject_public_key_info: self.subject_public_key_info.as_ref().to_owned().into(),
529            name_constraints: self
530                .name_constraints
531                .as_ref()
532                .map(|nc| nc.as_ref().to_owned().into()),
533        }
534    }
535}
536
537/// A Certificate Revocation List; as specified in RFC 5280
538///
539/// Certificate revocation lists are identified in PEM context as `X509 CRL` and when stored in a
540/// file usually use a `.crl` extension. For more on PEM files, refer to the crate documentation.
541///
542/// ```rust
543/// # #[cfg(all(feature = "alloc", feature = "std"))] {
544/// use rustls_pki_types::{CertificateRevocationListDer, pem::PemObject};
545///
546/// // load several from a PEM file
547/// let crls: Vec<_> = CertificateRevocationListDer::pem_file_iter("tests/data/crl.pem")
548///     .unwrap()
549///     .collect();
550/// assert!(crls.len() >= 1);
551///
552/// // or one from a PEM byte slice...
553/// # let byte_slice = include_bytes!("../tests/data/crl.pem");
554/// CertificateRevocationListDer::from_pem_slice(byte_slice).unwrap();
555///
556/// // or several from a PEM byte slice
557/// let crls: Vec<_> = CertificateRevocationListDer::pem_slice_iter(byte_slice)
558///     .collect();
559/// assert!(crls.len() >= 1);
560/// # }
561/// ```
562
563#[derive(Clone, Debug, Hash, PartialEq, Eq)]
564pub struct CertificateRevocationListDer<'a>(Der<'a>);
565
566#[cfg(feature = "alloc")]
567impl PemObjectFilter for CertificateRevocationListDer<'static> {
568    const KIND: SectionKind = SectionKind::Crl;
569}
570
571impl AsRef<[u8]> for CertificateRevocationListDer<'_> {
572    fn as_ref(&self) -> &[u8] {
573        self.0.as_ref()
574    }
575}
576
577impl Deref for CertificateRevocationListDer<'_> {
578    type Target = [u8];
579
580    fn deref(&self) -> &Self::Target {
581        self.as_ref()
582    }
583}
584
585impl<'a> From<&'a [u8]> for CertificateRevocationListDer<'a> {
586    fn from(slice: &'a [u8]) -> Self {
587        Self(Der::from(slice))
588    }
589}
590
591#[cfg(feature = "alloc")]
592impl From<Vec<u8>> for CertificateRevocationListDer<'_> {
593    fn from(vec: Vec<u8>) -> Self {
594        Self(Der::from(vec))
595    }
596}
597
598/// A Certificate Signing Request; as specified in RFC 2986
599///
600/// Certificate signing requests are identified in PEM context as `CERTIFICATE REQUEST` and when stored in a
601/// file usually use a `.csr` extension. For more on PEM files, refer to the crate documentation.
602///
603/// ```rust
604/// # #[cfg(all(feature = "alloc", feature = "std"))] {
605/// use rustls_pki_types::{CertificateSigningRequestDer, pem::PemObject};
606///
607/// // load from a PEM file
608/// CertificateSigningRequestDer::from_pem_file("tests/data/csr.pem").unwrap();
609///
610/// // or from a PEM byte slice...
611/// # let byte_slice = include_bytes!("../tests/data/csr.pem");
612/// CertificateSigningRequestDer::from_pem_slice(byte_slice).unwrap();
613/// # }
614/// ```
615#[derive(Clone, Debug, Hash, PartialEq, Eq)]
616pub struct CertificateSigningRequestDer<'a>(Der<'a>);
617
618#[cfg(feature = "alloc")]
619impl PemObjectFilter for CertificateSigningRequestDer<'static> {
620    const KIND: SectionKind = SectionKind::Csr;
621}
622
623impl AsRef<[u8]> for CertificateSigningRequestDer<'_> {
624    fn as_ref(&self) -> &[u8] {
625        self.0.as_ref()
626    }
627}
628
629impl Deref for CertificateSigningRequestDer<'_> {
630    type Target = [u8];
631
632    fn deref(&self) -> &Self::Target {
633        self.as_ref()
634    }
635}
636
637impl<'a> From<&'a [u8]> for CertificateSigningRequestDer<'a> {
638    fn from(slice: &'a [u8]) -> Self {
639        Self(Der::from(slice))
640    }
641}
642
643#[cfg(feature = "alloc")]
644impl From<Vec<u8>> for CertificateSigningRequestDer<'_> {
645    fn from(vec: Vec<u8>) -> Self {
646        Self(Der::from(vec))
647    }
648}
649
650/// A DER-encoded X.509 certificate; as specified in RFC 5280
651///
652/// Certificates are identified in PEM context as `CERTIFICATE` and when stored in a
653/// file usually use a `.pem`, `.cer` or `.crt` extension. For more on PEM files, refer to the
654/// crate documentation.
655///
656/// ```rust
657/// # #[cfg(all(feature = "alloc", feature = "std"))] {
658/// use rustls_pki_types::{CertificateDer, pem::PemObject};
659///
660/// // load several from a PEM file
661/// let certs: Vec<_> = CertificateDer::pem_file_iter("tests/data/certificate.chain.pem")
662///     .unwrap()
663///     .collect();
664/// assert_eq!(certs.len(), 3);
665///
666/// // or one from a PEM byte slice...
667/// # let byte_slice = include_bytes!("../tests/data/certificate.chain.pem");
668/// CertificateDer::from_pem_slice(byte_slice).unwrap();
669///
670/// // or several from a PEM byte slice
671/// let certs: Vec<_> = CertificateDer::pem_slice_iter(byte_slice)
672///     .collect();
673/// assert_eq!(certs.len(), 3);
674/// # }
675/// ```
676#[derive(Clone, Debug, Hash, PartialEq, Eq)]
677pub struct CertificateDer<'a>(Der<'a>);
678
679impl<'a> CertificateDer<'a> {
680    /// A const constructor to create a `CertificateDer` from a slice of DER.
681    pub const fn from_slice(bytes: &'a [u8]) -> Self {
682        Self(Der::from_slice(bytes))
683    }
684}
685
686#[cfg(feature = "alloc")]
687impl PemObjectFilter for CertificateDer<'static> {
688    const KIND: SectionKind = SectionKind::Certificate;
689}
690
691impl AsRef<[u8]> for CertificateDer<'_> {
692    fn as_ref(&self) -> &[u8] {
693        self.0.as_ref()
694    }
695}
696
697impl Deref for CertificateDer<'_> {
698    type Target = [u8];
699
700    fn deref(&self) -> &Self::Target {
701        self.as_ref()
702    }
703}
704
705impl<'a> From<&'a [u8]> for CertificateDer<'a> {
706    fn from(slice: &'a [u8]) -> Self {
707        Self(Der::from(slice))
708    }
709}
710
711#[cfg(feature = "alloc")]
712impl From<Vec<u8>> for CertificateDer<'_> {
713    fn from(vec: Vec<u8>) -> Self {
714        Self(Der::from(vec))
715    }
716}
717
718impl CertificateDer<'_> {
719    /// Converts this certificate into its owned variant, unfreezing borrowed content (if any)
720    #[cfg(feature = "alloc")]
721    pub fn into_owned(self) -> CertificateDer<'static> {
722        CertificateDer(Der(self.0.0.into_owned()))
723    }
724}
725
726/// A DER-encoded SubjectPublicKeyInfo (SPKI), as specified in RFC 5280.
727#[deprecated(since = "1.7.0", note = "Prefer `SubjectPublicKeyInfoDer` instead")]
728pub type SubjectPublicKeyInfo<'a> = SubjectPublicKeyInfoDer<'a>;
729
730/// A DER-encoded SubjectPublicKeyInfo (SPKI), as specified in RFC 5280.
731///
732/// Public keys are identified in PEM context as a `PUBLIC KEY`.
733///
734/// ```rust
735/// # #[cfg(all(feature = "alloc", feature = "std"))] {
736/// use rustls_pki_types::{SubjectPublicKeyInfoDer, pem::PemObject};
737///
738/// // load from a PEM file
739/// SubjectPublicKeyInfoDer::from_pem_file("tests/data/spki.pem").unwrap();
740///
741/// // or from a PEM byte slice...
742/// # let byte_slice = include_bytes!("../tests/data/spki.pem");
743/// SubjectPublicKeyInfoDer::from_pem_slice(byte_slice).unwrap();
744/// # }
745/// ```
746#[derive(Clone, Debug, Hash, PartialEq, Eq)]
747pub struct SubjectPublicKeyInfoDer<'a>(Der<'a>);
748
749#[cfg(feature = "alloc")]
750impl PemObjectFilter for SubjectPublicKeyInfoDer<'static> {
751    const KIND: SectionKind = SectionKind::PublicKey;
752}
753
754impl AsRef<[u8]> for SubjectPublicKeyInfoDer<'_> {
755    fn as_ref(&self) -> &[u8] {
756        self.0.as_ref()
757    }
758}
759
760impl Deref for SubjectPublicKeyInfoDer<'_> {
761    type Target = [u8];
762
763    fn deref(&self) -> &Self::Target {
764        self.as_ref()
765    }
766}
767
768impl<'a> From<&'a [u8]> for SubjectPublicKeyInfoDer<'a> {
769    fn from(slice: &'a [u8]) -> Self {
770        Self(Der::from(slice))
771    }
772}
773
774#[cfg(feature = "alloc")]
775impl From<Vec<u8>> for SubjectPublicKeyInfoDer<'_> {
776    fn from(vec: Vec<u8>) -> Self {
777        Self(Der::from(vec))
778    }
779}
780
781impl SubjectPublicKeyInfoDer<'_> {
782    /// Converts this SubjectPublicKeyInfo into its owned variant, unfreezing borrowed content (if any)
783    #[cfg(feature = "alloc")]
784    pub fn into_owned(self) -> SubjectPublicKeyInfoDer<'static> {
785        SubjectPublicKeyInfoDer(Der(self.0.0.into_owned()))
786    }
787}
788
789/// A TLS-encoded Encrypted Client Hello (ECH) configuration list (`ECHConfigList`); as specified in
790/// [draft-ietf-tls-esni-18 ยง4](https://datatracker.ietf.org/doc/html/draft-ietf-tls-esni-18#section-4)
791#[derive(Clone, Eq, Hash, PartialEq)]
792pub struct EchConfigListBytes<'a>(BytesInner<'a>);
793
794impl EchConfigListBytes<'_> {
795    /// Converts this config into its owned variant, unfreezing borrowed content (if any)
796    #[cfg(feature = "alloc")]
797    pub fn into_owned(self) -> EchConfigListBytes<'static> {
798        EchConfigListBytes(self.0.into_owned())
799    }
800}
801
802#[cfg(feature = "alloc")]
803impl EchConfigListBytes<'static> {
804    /// Convert an iterator over PEM items into an `EchConfigListBytes` and private key.
805    ///
806    /// This handles the "ECHConfig file" format specified in
807    /// <https://www.ietf.org/archive/id/draft-farrell-tls-pemesni-05.html#name-echconfig-file>
808    ///
809    /// Use it like:
810    ///
811    /// ```rust
812    /// # #[cfg(all(feature = "alloc", feature = "std"))] {
813    /// # use rustls_pki_types::{EchConfigListBytes, pem::PemObject};
814    /// let (config, key) = EchConfigListBytes::config_and_key_from_iter(
815    ///     PemObject::pem_file_iter("tests/data/ech.pem").unwrap()
816    /// ).unwrap();
817    /// # }
818    /// ```
819    pub fn config_and_key_from_iter(
820        iter: impl Iterator<Item = Result<(SectionKind, Vec<u8>), pem::Error>>,
821    ) -> Result<(Self, PrivatePkcs8KeyDer<'static>), pem::Error> {
822        let mut key = None;
823        let mut config = None;
824
825        for item in iter {
826            let (kind, data) = item?;
827            match kind {
828                SectionKind::PrivateKey => {
829                    key = PrivatePkcs8KeyDer::from_pem(kind, data);
830                }
831                SectionKind::EchConfigList => {
832                    config = Self::from_pem(kind, data);
833                }
834                _ => continue,
835            };
836
837            if let (Some(_key), Some(_config)) = (&key, &config) {
838                return Ok((config.take().unwrap(), key.take().unwrap()));
839            }
840        }
841
842        Err(pem::Error::NoItemsFound)
843    }
844}
845
846#[cfg(feature = "alloc")]
847impl PemObjectFilter for EchConfigListBytes<'static> {
848    const KIND: SectionKind = SectionKind::EchConfigList;
849}
850
851impl fmt::Debug for EchConfigListBytes<'_> {
852    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
853        hex(f, self.as_ref())
854    }
855}
856
857impl AsRef<[u8]> for EchConfigListBytes<'_> {
858    fn as_ref(&self) -> &[u8] {
859        self.0.as_ref()
860    }
861}
862
863impl Deref for EchConfigListBytes<'_> {
864    type Target = [u8];
865
866    fn deref(&self) -> &Self::Target {
867        self.as_ref()
868    }
869}
870
871impl<'a> From<&'a [u8]> for EchConfigListBytes<'a> {
872    fn from(slice: &'a [u8]) -> Self {
873        Self(BytesInner::Borrowed(slice))
874    }
875}
876
877#[cfg(feature = "alloc")]
878impl From<Vec<u8>> for EchConfigListBytes<'_> {
879    fn from(vec: Vec<u8>) -> Self {
880        Self(BytesInner::Owned(vec))
881    }
882}
883
884/// An abstract signature verification algorithm.
885///
886/// One of these is needed per supported pair of public key type (identified
887/// with `public_key_alg_id()`) and `signatureAlgorithm` (identified with
888/// `signature_alg_id()`).  Note that both of these `AlgorithmIdentifier`s include
889/// the parameters encoding, so separate `SignatureVerificationAlgorithm`s are needed
890/// for each possible public key or signature parameters.
891///
892/// Debug implementations should list the public key algorithm identifier and
893/// signature algorithm identifier in human friendly form (i.e. not encoded bytes),
894/// along with the name of the implementing library (to distinguish different
895/// implementations of the same algorithms).
896pub trait SignatureVerificationAlgorithm: Send + Sync + fmt::Debug {
897    /// Verify a signature.
898    ///
899    /// `public_key` is the `subjectPublicKey` value from a `SubjectPublicKeyInfo` encoding
900    /// and is untrusted.  The key's `subjectPublicKeyInfo` matches the [`AlgorithmIdentifier`]
901    /// returned by `public_key_alg_id()`.
902    ///
903    /// `message` is the data over which the signature was allegedly computed.
904    /// It is not hashed; implementations of this trait function must do hashing
905    /// if that is required by the algorithm they implement.
906    ///
907    /// `signature` is the signature allegedly over `message`.
908    ///
909    /// Return `Ok(())` only if `signature` is a valid signature on `message`.
910    ///
911    /// Return `Err(InvalidSignature)` if the signature is invalid, including if the `public_key`
912    /// encoding is invalid.  There is no need or opportunity to produce errors
913    /// that are more specific than this.
914    fn verify_signature(
915        &self,
916        public_key: &[u8],
917        message: &[u8],
918        signature: &[u8],
919    ) -> Result<(), InvalidSignature>;
920
921    /// Return the `AlgorithmIdentifier` that must equal a public key's
922    /// `subjectPublicKeyInfo` value for this `SignatureVerificationAlgorithm`
923    /// to be used for signature verification.
924    fn public_key_alg_id(&self) -> AlgorithmIdentifier;
925
926    /// Return the `AlgorithmIdentifier` that must equal the `signatureAlgorithm` value
927    /// on the data to be verified for this `SignatureVerificationAlgorithm` to be used
928    /// for signature verification.
929    fn signature_alg_id(&self) -> AlgorithmIdentifier;
930
931    /// Return the FIPS status of this algorithm or implementation.
932    fn fips_status(&self) -> FipsStatus {
933        match self.fips() {
934            true => FipsStatus::Pending,
935            false => FipsStatus::Unvalidated,
936        }
937    }
938
939    /// Return `true` if this is backed by a FIPS-approved implementation.
940    fn fips(&self) -> bool {
941        false
942    }
943}
944
945/// A detail-less error when a signature is not valid.
946#[allow(clippy::exhaustive_structs)]
947#[derive(Debug, Copy, Clone)]
948pub struct InvalidSignature;
949
950/// A timestamp, tracking the number of non-leap seconds since the Unix epoch.
951///
952/// The Unix epoch is defined January 1, 1970 00:00:00 UTC.
953#[derive(Debug, Clone, Copy, Hash, PartialEq, Eq, PartialOrd, Ord)]
954pub struct UnixTime(u64);
955
956impl UnixTime {
957    /// The current time, as a `UnixTime`
958    #[cfg(any(
959        all(
960            feature = "std",
961            not(all(target_family = "wasm", target_os = "unknown"))
962        ),
963        all(target_family = "wasm", target_os = "unknown", feature = "web")
964    ))]
965    pub fn now() -> Self {
966        Self::since_unix_epoch(
967            SystemTime::now()
968                .duration_since(SystemTime::UNIX_EPOCH)
969                .unwrap(), // Safe: this code did not exist before 1970.
970        )
971    }
972
973    /// Convert a `Duration` since the start of 1970 to a `UnixTime`
974    ///
975    /// The `duration` must be relative to the Unix epoch.
976    pub const fn since_unix_epoch(duration: Duration) -> Self {
977        Self(duration.as_secs())
978    }
979
980    /// Number of seconds since the Unix epoch
981    pub const fn as_secs(&self) -> u64 {
982        self.0
983    }
984}
985
986/// DER-encoded data, either owned or borrowed
987///
988/// This wrapper type is used to represent DER-encoded data in a way that is agnostic to whether
989/// the data is owned (by a `Vec<u8>`) or borrowed (by a `&[u8]`). Support for the owned
990/// variant is only available when the `alloc` feature is enabled.
991#[derive(Clone, Eq, Hash, PartialEq)]
992pub struct Der<'a>(BytesInner<'a>);
993
994impl<'a> Der<'a> {
995    /// A const constructor to create a `Der` from a borrowed slice
996    pub const fn from_slice(der: &'a [u8]) -> Self {
997        Self(BytesInner::Borrowed(der))
998    }
999}
1000
1001impl AsRef<[u8]> for Der<'_> {
1002    fn as_ref(&self) -> &[u8] {
1003        self.0.as_ref()
1004    }
1005}
1006
1007impl Deref for Der<'_> {
1008    type Target = [u8];
1009
1010    fn deref(&self) -> &Self::Target {
1011        self.as_ref()
1012    }
1013}
1014
1015impl<'a> From<&'a [u8]> for Der<'a> {
1016    fn from(slice: &'a [u8]) -> Self {
1017        Self(BytesInner::Borrowed(slice))
1018    }
1019}
1020
1021#[cfg(feature = "alloc")]
1022impl From<Vec<u8>> for Der<'static> {
1023    fn from(vec: Vec<u8>) -> Self {
1024        Self(BytesInner::Owned(vec))
1025    }
1026}
1027
1028impl fmt::Debug for Der<'_> {
1029    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1030        hex(f, self.as_ref())
1031    }
1032}
1033
1034#[derive(Debug, Clone)]
1035enum BytesInner<'a> {
1036    #[cfg(feature = "alloc")]
1037    Owned(Vec<u8>),
1038    Borrowed(&'a [u8]),
1039}
1040
1041#[cfg(feature = "alloc")]
1042impl BytesInner<'_> {
1043    fn into_owned(self) -> BytesInner<'static> {
1044        BytesInner::Owned(match self {
1045            Self::Owned(vec) => vec,
1046            Self::Borrowed(slice) => slice.to_vec(),
1047        })
1048    }
1049}
1050
1051#[cfg(feature = "alloc")]
1052impl zeroize::Zeroize for BytesInner<'static> {
1053    fn zeroize(&mut self) {
1054        match self {
1055            BytesInner::Owned(vec) => vec.zeroize(),
1056            BytesInner::Borrowed(_) => (),
1057        }
1058    }
1059}
1060
1061impl AsRef<[u8]> for BytesInner<'_> {
1062    fn as_ref(&self) -> &[u8] {
1063        match &self {
1064            #[cfg(feature = "alloc")]
1065            BytesInner::Owned(vec) => vec.as_ref(),
1066            BytesInner::Borrowed(slice) => slice,
1067        }
1068    }
1069}
1070
1071impl core::hash::Hash for BytesInner<'_> {
1072    fn hash<H: core::hash::Hasher>(&self, state: &mut H) {
1073        state.write(self.as_ref());
1074    }
1075}
1076
1077impl PartialEq for BytesInner<'_> {
1078    fn eq(&self, other: &Self) -> bool {
1079        self.as_ref() == other.as_ref()
1080    }
1081}
1082
1083impl Eq for BytesInner<'_> {}
1084
1085/// FIPS validation status of an algorithm or implementation.
1086#[allow(clippy::exhaustive_enums)]
1087#[derive(Clone, Copy, Debug, Eq, Ord, PartialEq, PartialOrd)]
1088pub enum FipsStatus {
1089    /// Not FIPS tested, or unapproved algorithm.
1090    Unvalidated,
1091    /// In queue for FIPS validation.
1092    Pending,
1093    /// FIPS certified, with named certificate.
1094    #[non_exhaustive]
1095    Certified {
1096        /// A name, number or URL referencing the FIPS certificate.
1097        certificate: &'static str,
1098    },
1099}
1100
1101// Format an iterator of u8 into a hex string
1102fn hex<'a>(f: &mut fmt::Formatter<'_>, payload: impl IntoIterator<Item = &'a u8>) -> fmt::Result {
1103    for (i, b) in payload.into_iter().enumerate() {
1104        if i == 0 {
1105            write!(f, "0x")?;
1106        }
1107        write!(f, "{b:02x}")?;
1108    }
1109    Ok(())
1110}
1111
1112#[cfg(all(test, feature = "std"))]
1113mod tests {
1114    use super::*;
1115
1116    #[test]
1117    fn der_debug() {
1118        let der = Der::from_slice(&[0x01, 0x02, 0x03]);
1119        assert_eq!(format!("{der:?}"), "0x010203");
1120    }
1121
1122    #[test]
1123    fn alg_id_debug() {
1124        let alg_id = AlgorithmIdentifier::from_slice(&[0x01, 0x02, 0x03]);
1125        assert_eq!(format!("{alg_id:?}"), "0x010203");
1126    }
1127
1128    #[test]
1129    fn bytes_inner_equality() {
1130        let owned_a = BytesInner::Owned(vec![1, 2, 3]);
1131        let owned_b = BytesInner::Owned(vec![4, 5]);
1132        let borrowed_a = BytesInner::Borrowed(&[1, 2, 3]);
1133        let borrowed_b = BytesInner::Borrowed(&[99]);
1134
1135        // Self-equality.
1136        assert_eq!(owned_a, owned_a);
1137        assert_eq!(owned_b, owned_b);
1138        assert_eq!(borrowed_a, borrowed_a);
1139        assert_eq!(borrowed_b, borrowed_b);
1140
1141        // Borrowed vs Owned equality
1142        assert_eq!(owned_a, borrowed_a);
1143        assert_eq!(borrowed_a, owned_a);
1144
1145        // Owned inequality
1146        assert_ne!(owned_a, owned_b);
1147        assert_ne!(owned_b, owned_a);
1148
1149        // Borrowed inequality
1150        assert_ne!(borrowed_a, borrowed_b);
1151        assert_ne!(borrowed_b, borrowed_a);
1152
1153        // Borrowed vs Owned inequality
1154        assert_ne!(owned_a, borrowed_b);
1155        assert_ne!(borrowed_b, owned_a);
1156    }
1157}