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}