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