1use base64::engine::general_purpose::STANDARD as base64_engine;
2use base64::Engine;
3use pki_types::{CertificateDer, PrivateKeyDer};
4use rustls::{Certificate, PrivateKey};
5use rustls_pemfile::{certs, pkcs8_private_keys};
6use std::io::{self, Cursor};
7use std::sync::Arc;
8use tokio_rustls::rustls::ServerConfig;
9use tokio_rustls::rustls::{ClientConfig, RootCertStore};
10use tokio_rustls::{TlsAcceptor, TlsConnector};
11
12pub fn from_base64_raw(pem: &str) -> io::Result<Vec<u8>> {
13 let cert_bytes = base64_engine
14 .decode(pem)
15 .map_err(|e| io::Error::new(io::ErrorKind::InvalidData, e.to_string()));
16
17 return cert_bytes;
18}
19
20pub fn certs_from_base64(cert_base64: &str) -> io::Result<Vec<Certificate>> {
21 let cert_bytes = from_base64_raw(cert_base64)?;
22 let mut cursor = Cursor::new(cert_bytes);
23 certs(&mut cursor)
24 .map(|result| result.map(|der| Certificate(der.to_vec())))
25 .collect()
26}
27
28pub fn privkey_from_base64(privkey_base64: &str) -> io::Result<PrivateKey> {
29 let key_bytes = from_base64_raw(privkey_base64)?;
30 let mut cursor = Cursor::new(key_bytes);
31 let keys = pkcs8_private_keys(&mut cursor)
32 .collect::<Result<Vec<_>, _>>()
33 .map_err(|_| io::Error::new(io::ErrorKind::InvalidData, "Failed to read private keys"))?;
34 let key = keys
35 .into_iter()
36 .next()
37 .ok_or_else(|| io::Error::new(io::ErrorKind::NotFound, "No private key found"))?;
38 Ok(PrivateKey(key.secret_pkcs8_der().to_vec()))
39}
40
41pub fn tls_connector_from_base64(
42 ca_cert_base64: &str,
43) -> Result<TlsConnector, Box<dyn std::error::Error>> {
44 let mut root_store = RootCertStore::empty();
45 let certs = load_certs_from_base64(ca_cert_base64)?;
46 for cert in certs {
47 root_store.add(cert)?;
48 }
49 let config = ClientConfig::builder()
50 .with_root_certificates(root_store)
51 .with_no_client_auth();
52 Ok(TlsConnector::from(Arc::new(config)))
53}
54
55pub fn tls_acceptor_from_base64(
56 cert_base64: &str,
57 privkey_base64: &str,
58 h1: bool,
59 h2: bool,
60) -> Result<TlsAcceptor, Box<dyn std::error::Error + Send + Sync>> {
61 let certs = load_certs_from_base64(cert_base64)?;
62 let key = load_keys_from_base64(privkey_base64)?;
63
64 let mut server_config = ServerConfig::builder()
65 .with_no_client_auth()
66 .with_single_cert(certs, key)?;
67
68 let mut protos = Vec::new();
69
70 if h2 {
71 protos.push(b"h2".to_vec());
72 }
73
74 if h1 {
75 protos.push(b"http/1.1".to_vec());
76 protos.push(b"http/1.0".to_vec());
77 }
78
79 server_config.alpn_protocols = protos;
80
81 let tls_acceptor = TlsAcceptor::from(Arc::new(server_config));
82
83 Ok(tls_acceptor)
84}
85
86pub fn load_certs_from_base64(cert_base64: &str) -> io::Result<Vec<CertificateDer<'static>>> {
87 let cert_bytes = from_base64_raw(cert_base64)?;
88 let mut cursor = Cursor::new(cert_bytes);
89 certs(&mut cursor).collect()
90}
91
92pub fn load_keys_from_base64(privkey_base64: &str) -> io::Result<PrivateKeyDer<'static>> {
93 let key_bytes = from_base64_raw(privkey_base64)?;
94 let mut cursor = Cursor::new(key_bytes);
95
96 let ec_keys = rustls_pemfile::ec_private_keys(&mut cursor)
98 .collect::<Result<Vec<_>, _>>()
99 .map_err(|_| {
100 io::Error::new(io::ErrorKind::InvalidData, "Failed to read EC private keys")
101 })?;
102
103 if let Some(key) = ec_keys.into_iter().next() {
104 return Ok(PrivateKeyDer::from(key));
105 }
106
107 cursor.set_position(0);
109 let pkcs8_keys = pkcs8_private_keys(&mut cursor)
110 .collect::<Result<Vec<_>, _>>()
111 .map_err(|_| {
112 io::Error::new(
113 io::ErrorKind::InvalidData,
114 "Failed to read PKCS8 private keys",
115 )
116 })?;
117
118 pkcs8_keys
119 .into_iter()
120 .next()
121 .map(PrivateKeyDer::from)
122 .ok_or_else(|| io::Error::new(io::ErrorKind::NotFound, "No private key found"))
123}