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