rustls/
pemfile.rs

1use crate::key;
2use base64;
3use std::io;
4
5/// Extract and decode all PEM sections from `rd`, which begin with `start_mark`
6/// and end with `end_mark`.  Apply the functor `f` to each decoded buffer,
7/// and return a Vec of `f`'s return values.
8fn extract<A>(
9    rd: &mut dyn io::BufRead,
10    start_mark: &str,
11    end_mark: &str,
12    f: &dyn Fn(Vec<u8>) -> A,
13) -> Result<Vec<A>, ()> {
14    let mut ders = Vec::new();
15    let mut b64buf = String::new();
16    let mut take_base64 = false;
17
18    let mut raw_line = Vec::<u8>::new();
19    loop {
20        raw_line.clear();
21        let len = rd
22            .read_until(b'\n', &mut raw_line)
23            .map_err(|_| ())?;
24
25        if len == 0 {
26            return Ok(ders);
27        }
28        let line = String::from_utf8_lossy(&raw_line);
29
30        if line.starts_with(start_mark) {
31            take_base64 = true;
32            continue;
33        }
34
35        if line.starts_with(end_mark) {
36            take_base64 = false;
37            let der = base64::decode(&b64buf).map_err(|_| ())?;
38            ders.push(f(der));
39            b64buf = String::new();
40            continue;
41        }
42
43        if take_base64 {
44            b64buf.push_str(line.trim());
45        }
46    }
47}
48
49/// Extract all the certificates from rd, and return a vec of `key::Certificate`s
50/// containing the der-format contents.
51pub fn certs(rd: &mut dyn io::BufRead) -> Result<Vec<key::Certificate>, ()> {
52    extract(
53        rd,
54        "-----BEGIN CERTIFICATE-----",
55        "-----END CERTIFICATE-----",
56        &|v| key::Certificate(v),
57    )
58}
59
60/// Extract all RSA private keys from rd, and return a vec of `key::PrivateKey`s
61/// containing the der-format contents.
62pub fn rsa_private_keys(rd: &mut dyn io::BufRead) -> Result<Vec<key::PrivateKey>, ()> {
63    extract(
64        rd,
65        "-----BEGIN RSA PRIVATE KEY-----",
66        "-----END RSA PRIVATE KEY-----",
67        &|v| key::PrivateKey(v),
68    )
69}
70
71/// Extract all PKCS8-encoded private keys from rd, and return a vec of
72/// `key::PrivateKey`s containing the der-format contents.
73pub fn pkcs8_private_keys(rd: &mut dyn io::BufRead) -> Result<Vec<key::PrivateKey>, ()> {
74    extract(
75        rd,
76        "-----BEGIN PRIVATE KEY-----",
77        "-----END PRIVATE KEY-----",
78        &|v| key::PrivateKey(v),
79    )
80}