s2n_quic_rustls/
certificate.rs1use crate::Error;
5
6macro_rules! cert_type {
7 ($name:ident, $trait:ident, $method:ident, $inner:ty) => {
8 pub struct $name(pub(crate) $inner);
9
10 pub trait $trait {
11 fn $method(self) -> Result<$name, Error>;
12 }
13
14 impl $trait for $name {
15 fn $method(self) -> Result<$name, Error> {
16 Ok(self)
17 }
18 }
19
20 impl $trait for String {
21 fn $method(self) -> Result<$name, Error> {
22 let cert = pem::$method(self.as_bytes())?;
23 Ok($name(cert))
24 }
25 }
26
27 impl $trait for &String {
28 fn $method(self) -> Result<$name, Error> {
29 let cert = pem::$method(self.as_bytes())?;
30 Ok($name(cert))
31 }
32 }
33
34 impl $trait for &str {
35 fn $method(self) -> Result<$name, Error> {
36 let cert = pem::$method(self.as_bytes())?;
37 Ok($name(cert))
38 }
39 }
40
41 impl $trait for Vec<u8> {
42 fn $method(self) -> Result<$name, Error> {
43 let cert = der::$method(self)?;
44 Ok($name(cert))
45 }
46 }
47
48 impl $trait for &[u8] {
49 fn $method(self) -> Result<$name, Error> {
50 self.to_vec().$method()
51 }
52 }
53
54 impl $trait for &std::path::Path {
55 fn $method(self) -> Result<$name, Error> {
56 match self.extension() {
57 Some(ext) if ext == "der" => {
58 let der = std::fs::read(self)?;
59 der.$method()
60 }
61 _ => {
62 let pem = std::fs::read_to_string(self)?;
63 pem.$method()
64 }
65 }
66 }
67 }
68 };
69}
70
71cert_type!(
72 PrivateKey,
73 IntoPrivateKey,
74 into_private_key,
75 rustls::pki_types::PrivateKeyDer<'static>
76);
77cert_type!(
78 Certificate,
79 IntoCertificate,
80 into_certificate,
81 Vec<rustls::pki_types::CertificateDer<'static>>
82);
83
84impl IntoCertificate for Vec<Vec<u8>> {
85 fn into_certificate(self) -> Result<Certificate, Error> {
86 let mut certs = vec![];
87 for der in self {
88 let der = der.into_certificate()?;
89 certs.extend(der.0);
90 }
91 Ok(Certificate(certs))
92 }
93}
94
95mod pem {
96 use rustls::{
97 pki_types::{CertificateDer, PrivateKeyDer},
98 Error,
99 };
100 use rustls_pki_types::pem::PemObject;
101
102 pub fn into_certificate(contents: &[u8]) -> Result<Vec<CertificateDer<'static>>, Error> {
103 let mut cursor = std::io::Cursor::new(contents);
104 rustls_pki_types::CertificateDer::pem_reader_iter(&mut cursor)
105 .map(|cert| cert.map_err(|_| Error::General("Could not read certificate".to_string())))
106 .collect()
107 }
108
109 pub fn into_private_key(contents: &[u8]) -> Result<PrivateKeyDer<'static>, Error> {
110 let mut cursor = std::io::Cursor::new(contents);
111
112 macro_rules! parse_key {
113 ($parser:ident, $key_type:expr) => {
114 cursor.set_position(0);
115
116 let keys: Result<Vec<_>, Error> = $parser(&mut cursor)
117 .map(|key| {
118 key.map_err(|_| {
119 Error::General("Could not load any private keys".to_string())
120 })
121 })
122 .collect();
123 match keys {
124 Err(_) => (),
126 Ok(keys) if keys.is_empty() => (),
128 Ok(mut keys) if keys.len() == 1 => {
129 return Ok($key_type(keys.pop().unwrap()));
130 }
131 Ok(keys) => {
132 return Err(Error::General(format!(
133 "Unexpected number of keys: {} (only 1 supported)",
134 keys.len()
135 )));
136 }
137 }
138 };
139 }
140
141 parse_key!(pkcs8_private_keys, PrivateKeyDer::Pkcs8);
143 parse_key!(rsa_private_keys, PrivateKeyDer::Pkcs1);
145 parse_key!(ec_private_keys, PrivateKeyDer::Sec1);
147
148 Err(Error::General(
149 "could not load any valid private keys".to_string(),
150 ))
151 }
152
153 fn pkcs8_private_keys<R: std::io::Read>(
155 reader: &mut R,
156 ) -> impl Iterator<
157 Item = Result<rustls_pki_types::PrivatePkcs8KeyDer<'static>, rustls_pki_types::pem::Error>,
158 > + '_ {
159 rustls_pki_types::PrivatePkcs8KeyDer::pem_reader_iter(reader)
160 .map(|result| result.map(|key| key.clone_key()))
161 }
162
163 fn rsa_private_keys<R: std::io::Read>(
165 reader: &mut R,
166 ) -> impl Iterator<
167 Item = Result<rustls_pki_types::PrivatePkcs1KeyDer<'static>, rustls_pki_types::pem::Error>,
168 > + '_ {
169 rustls_pki_types::PrivatePkcs1KeyDer::pem_reader_iter(reader)
170 .map(|result| result.map(|key| key.clone_key()))
171 }
172
173 fn ec_private_keys<R: std::io::Read>(
175 reader: &mut R,
176 ) -> impl Iterator<
177 Item = Result<rustls_pki_types::PrivateSec1KeyDer<'static>, rustls_pki_types::pem::Error>,
178 > + '_ {
179 rustls_pki_types::PrivateSec1KeyDer::pem_reader_iter(reader)
180 .map(|result| result.map(|key| key.clone_key()))
181 }
182}
183
184mod der {
185 use rustls::{
186 pki_types::{CertificateDer, PrivateKeyDer},
187 Error,
188 };
189
190 pub fn into_certificate(contents: Vec<u8>) -> Result<Vec<CertificateDer<'static>>, Error> {
191 Ok(vec![CertificateDer::from(contents)])
193 }
194
195 pub fn into_private_key(contents: Vec<u8>) -> Result<PrivateKeyDer<'static>, Error> {
196 Ok(PrivateKeyDer::Pkcs8(contents.into()))
202 }
203}
204
205#[cfg(test)]
206mod tests {
207 use super::*;
208 use s2n_quic_core::crypto::tls::testing::certificates::*;
209
210 #[test]
211 fn load_pem() {
212 let _ = CERT_PEM.into_certificate().unwrap();
213 let _ = CERT_PKCS1_PEM.into_certificate().unwrap();
214 let _ = KEY_PEM.into_private_key().unwrap();
216 let _ = KEY_PKCS1_PEM.into_private_key().unwrap();
218 }
219
220 #[test]
221 fn load_der() {
222 let _ = CERT_DER.into_certificate().unwrap();
223 let _ = KEY_DER.into_private_key().unwrap();
224 }
225}