rustls_cert_file_reader/
pem.rs1use std::io::ErrorKind;
4
5pub fn parse_certs(
7 rd: &mut dyn std::io::BufRead,
8) -> Result<Vec<rustls_pki_types::CertificateDer<'static>>, std::io::Error> {
9 let mut certs = Vec::new();
10
11 loop {
12 let Some(item) = read_one(rd)? else {
13 return Ok(certs);
14 };
15 if let Some(cert) = cert_from_pemfile_item(item) {
16 certs.push(cert);
17 }
18 }
19}
20
21pub fn parse_key(
23 rd: &mut dyn std::io::BufRead,
24) -> Result<rustls_pki_types::PrivateKeyDer<'static>, std::io::Error> {
25 let key = loop {
26 let Some(item) = read_one(rd)? else {
27 return Err(std::io::Error::new(
28 ErrorKind::NotFound,
29 "no key found in the given data".to_string(),
30 ));
31 };
32 if let Some(key) = private_key_from_pemfile_item(item) {
33 break key;
34 }
35 };
36
37 loop {
39 let Some(item) = read_one(rd)? else {
40 break;
41 };
42
43 if private_key_from_pemfile_item(item).is_some() {
44 return Err(std::io::Error::new(
45 ErrorKind::InvalidInput,
46 "more than one key".to_string(),
47 ));
48 }
49 }
50
51 Ok(key)
52}
53
54type PemObjectTuple = (rustls_pki_types::pem::SectionKind, Vec<u8>);
56
57fn read_one(rd: &mut dyn std::io::BufRead) -> Result<Option<PemObjectTuple>, std::io::Error> {
59 match rustls_pki_types::pem::from_buf(rd) {
60 Ok(item) => Ok(item),
61 Err(rustls_pki_types::pem::Error::Io(error)) => Err(error),
62 Err(error) => Err(std::io::Error::other(error)),
64 }
65}
66
67fn private_key_from_pemfile_item(
70 (kind, der): PemObjectTuple,
71) -> Option<rustls_pki_types::PrivateKeyDer<'static>> {
72 <rustls_pki_types::PrivateKeyDer<'static> as rustls_pki_types::pem::PemObject>::from_pem(
73 kind, der,
74 )
75}
76
77fn cert_from_pemfile_item(
80 (kind, der): PemObjectTuple,
81) -> Option<rustls_pki_types::CertificateDer<'static>> {
82 <rustls_pki_types::CertificateDer<'static> as rustls_pki_types::pem::PemObject>::from_pem(
83 kind, der,
84 )
85}