Coverage Report

Created: 2025-02-25 06:39

/rust/registry/src/index.crates.io-6f17d22bba15001f/rustls-pemfile-2.2.0/src/lib.rs
Line
Count
Source (jump to first uncovered line)
1
//! # rustls-pemfile
2
//! A basic parser for .pem files containing cryptographic keys and certificates.
3
//!
4
//! The input to this crate is a .pem file containing potentially many sections,
5
//! and the output is those sections as alleged DER-encodings.  This crate does
6
//! not decode the actual DER-encoded keys/certificates.
7
//!
8
//! ## Quick start
9
//! Starting with an `io::BufRead` containing the file to be read:
10
//! - Use `read_all()` to ingest the whole file, then work through the contents in-memory, or,
11
//! - Use `read_one()` to stream through the file, processing the items as found, or,
12
//! - Use `certs()` to extract just the certificates (silently discarding other sections), and
13
//!   similarly for `rsa_private_keys()` and `pkcs8_private_keys()`.
14
//!
15
//! # no-std support
16
//!
17
//! The opt-out "std" Cargo feature can be disabled to put this crate in no-std mode.
18
//!
19
//! In no-std mode, the `read_one_from_slice` API can be used to parse a .pem file that has already
20
//! been loaded into memory.
21
//!
22
//! ## Example code
23
#![cfg_attr(feature = "std", doc = "```")]
24
#![cfg_attr(not(feature = "std"), doc = "```ignore")]
25
//! use std::iter;
26
//! use rustls_pemfile::{Item, read_one};
27
//! # let mut reader = std::io::BufReader::new(&b"junk\n-----BEGIN RSA PRIVATE KEY-----\nqw\n-----END RSA PRIVATE KEY-----\n"[..]);
28
//! // Assume `reader` is any std::io::BufRead implementor
29
//! for item in iter::from_fn(|| read_one(&mut reader).transpose()) {
30
//!     match item.unwrap() {
31
//!         Item::X509Certificate(cert) => println!("certificate {:?}", cert),
32
//!         Item::Crl(crl) => println!("certificate revocation list: {:?}", crl),
33
//!         Item::Csr(csr) => println!("certificate signing request: {:?}", csr),
34
//!         Item::Pkcs1Key(key) => println!("rsa pkcs1 key {:?}", key),
35
//!         Item::Pkcs8Key(key) => println!("pkcs8 key {:?}", key),
36
//!         Item::Sec1Key(key) => println!("sec1 ec key {:?}", key),
37
//!         _ => println!("unhandled item"),
38
//!     }
39
//! }
40
//! ```
41
42
// Require docs for public APIs, deny unsafe code, etc.
43
#![forbid(unsafe_code, unused_must_use, unstable_features)]
44
#![deny(
45
    trivial_casts,
46
    trivial_numeric_casts,
47
    missing_docs,
48
    unused_import_braces,
49
    unused_extern_crates,
50
    unused_qualifications
51
)]
52
#![no_std]
53
54
extern crate alloc;
55
#[cfg(any(feature = "std", test))]
56
extern crate std;
57
58
#[cfg(test)]
59
#[cfg(feature = "std")]
60
mod tests;
61
62
mod pemfile;
63
#[cfg(feature = "std")]
64
use core::iter;
65
/// --- Legacy APIs:
66
#[cfg(feature = "std")]
67
use std::io;
68
69
#[cfg(feature = "std")]
70
pub use pemfile::{read_all, read_one};
71
pub use pemfile::{read_one_from_slice, Error, Item};
72
#[cfg(feature = "std")]
73
use pki_types::PrivateKeyDer;
74
#[cfg(feature = "std")]
75
use pki_types::{
76
    CertificateDer, CertificateRevocationListDer, CertificateSigningRequestDer, PrivatePkcs1KeyDer,
77
    PrivatePkcs8KeyDer, PrivateSec1KeyDer, SubjectPublicKeyInfoDer,
78
};
79
80
/// Return an iterator over certificates from `rd`.
81
///
82
/// Filters out any PEM sections that are not certificates and yields errors if a problem
83
/// occurs while trying to extract a certificate.
84
#[cfg(feature = "std")]
85
0
pub fn certs(
86
0
    rd: &mut dyn io::BufRead,
87
0
) -> impl Iterator<Item = Result<CertificateDer<'static>, io::Error>> + '_ {
88
0
    iter::from_fn(move || read_one(rd).transpose()).filter_map(|item| match item {
Unexecuted instantiation: rustls_pemfile::certs::{closure#0}
Unexecuted instantiation: rustls_pemfile::certs::{closure#0}
89
0
        Ok(Item::X509Certificate(cert)) => Some(Ok(cert)),
90
0
        Err(err) => Some(Err(err)),
91
0
        _ => None,
92
0
    })
Unexecuted instantiation: rustls_pemfile::certs::{closure#1}
Unexecuted instantiation: rustls_pemfile::certs::{closure#1}
93
0
}
94
95
/// Return the first private key found in `rd`.
96
///
97
/// Yields the first PEM section describing a private key (of any type), or an error if a
98
/// problem occurs while trying to read PEM sections.
99
#[cfg(feature = "std")]
100
0
pub fn private_key(rd: &mut dyn io::BufRead) -> Result<Option<PrivateKeyDer<'static>>, io::Error> {
101
0
    for result in iter::from_fn(move || read_one(rd).transpose()) {
102
0
        match result? {
103
0
            Item::Pkcs1Key(key) => return Ok(Some(key.into())),
104
0
            Item::Pkcs8Key(key) => return Ok(Some(key.into())),
105
0
            Item::Sec1Key(key) => return Ok(Some(key.into())),
106
            Item::X509Certificate(_)
107
            | Item::SubjectPublicKeyInfo(_)
108
            | Item::Crl(_)
109
0
            | Item::Csr(_) => continue,
110
        }
111
    }
112
113
0
    Ok(None)
114
0
}
115
116
/// Return the first certificate signing request (CSR) found in `rd`.
117
///
118
/// Yields the first PEM section describing a certificate signing request, or an error if a
119
/// problem occurs while trying to read PEM sections.
120
#[cfg(feature = "std")]
121
0
pub fn csr(
122
0
    rd: &mut dyn io::BufRead,
123
0
) -> Result<Option<CertificateSigningRequestDer<'static>>, io::Error> {
124
0
    for result in iter::from_fn(move || read_one(rd).transpose()) {
125
0
        match result? {
126
0
            Item::Csr(csr) => return Ok(Some(csr)),
127
            Item::Pkcs1Key(_)
128
            | Item::Pkcs8Key(_)
129
            | Item::Sec1Key(_)
130
            | Item::X509Certificate(_)
131
            | Item::SubjectPublicKeyInfo(_)
132
0
            | Item::Crl(_) => continue,
133
        }
134
    }
135
136
0
    Ok(None)
137
0
}
138
139
/// Return an iterator certificate revocation lists (CRLs) from `rd`.
140
///
141
/// Filters out any PEM sections that are not CRLs and yields errors if a problem occurs
142
/// while trying to extract a CRL.
143
#[cfg(feature = "std")]
144
0
pub fn crls(
145
0
    rd: &mut dyn io::BufRead,
146
0
) -> impl Iterator<Item = Result<CertificateRevocationListDer<'static>, io::Error>> + '_ {
147
0
    iter::from_fn(move || read_one(rd).transpose()).filter_map(|item| match item {
148
0
        Ok(Item::Crl(crl)) => Some(Ok(crl)),
149
0
        Err(err) => Some(Err(err)),
150
0
        _ => None,
151
0
    })
152
0
}
153
154
/// Return an iterator over RSA private keys from `rd`.
155
///
156
/// Filters out any PEM sections that are not RSA private keys and yields errors if a problem
157
/// occurs while trying to extract an RSA private key.
158
#[cfg(feature = "std")]
159
0
pub fn rsa_private_keys(
160
0
    rd: &mut dyn io::BufRead,
161
0
) -> impl Iterator<Item = Result<PrivatePkcs1KeyDer<'static>, io::Error>> + '_ {
162
0
    iter::from_fn(move || read_one(rd).transpose()).filter_map(|item| match item {
163
0
        Ok(Item::Pkcs1Key(key)) => Some(Ok(key)),
164
0
        Err(err) => Some(Err(err)),
165
0
        _ => None,
166
0
    })
167
0
}
168
169
/// Return an iterator over PKCS8-encoded private keys from `rd`.
170
///
171
/// Filters out any PEM sections that are not PKCS8-encoded private keys and yields errors if a
172
/// problem occurs while trying to extract an RSA private key.
173
#[cfg(feature = "std")]
174
0
pub fn pkcs8_private_keys(
175
0
    rd: &mut dyn io::BufRead,
176
0
) -> impl Iterator<Item = Result<PrivatePkcs8KeyDer<'static>, io::Error>> + '_ {
177
0
    iter::from_fn(move || read_one(rd).transpose()).filter_map(|item| match item {
178
0
        Ok(Item::Pkcs8Key(key)) => Some(Ok(key)),
179
0
        Err(err) => Some(Err(err)),
180
0
        _ => None,
181
0
    })
182
0
}
183
184
/// Return an iterator over SEC1-encoded EC private keys from `rd`.
185
///
186
/// Filters out any PEM sections that are not SEC1-encoded EC private keys and yields errors if a
187
/// problem occurs while trying to extract a SEC1-encoded EC private key.
188
#[cfg(feature = "std")]
189
0
pub fn ec_private_keys(
190
0
    rd: &mut dyn io::BufRead,
191
0
) -> impl Iterator<Item = Result<PrivateSec1KeyDer<'static>, io::Error>> + '_ {
192
0
    iter::from_fn(move || read_one(rd).transpose()).filter_map(|item| match item {
193
0
        Ok(Item::Sec1Key(key)) => Some(Ok(key)),
194
0
        Err(err) => Some(Err(err)),
195
0
        _ => None,
196
0
    })
197
0
}
198
199
/// Return an iterator over SPKI-encoded keys from `rd`.
200
///
201
/// Filters out any PEM sections that are not SPKI-encoded public keys and yields errors if a
202
/// problem occurs while trying to extract a SPKI-encoded public key.
203
#[cfg(feature = "std")]
204
0
pub fn public_keys(
205
0
    rd: &mut dyn io::BufRead,
206
0
) -> impl Iterator<Item = Result<SubjectPublicKeyInfoDer<'static>, io::Error>> + '_ {
207
0
    iter::from_fn(move || read_one(rd).transpose()).filter_map(|item| match item {
208
0
        Ok(Item::SubjectPublicKeyInfo(key)) => Some(Ok(key)),
209
0
        Err(err) => Some(Err(err)),
210
0
        _ => None,
211
0
    })
212
0
}