Skip to main content

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