tls_helpers/
lib.rs

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
use base64::engine::general_purpose::STANDARD as base64_engine;
use base64::Engine;
use pki_types::{CertificateDer, PrivateKeyDer};
use rustls::{Certificate, PrivateKey};
use rustls_pemfile::{certs, pkcs8_private_keys};
use std::io::{self, Cursor};
use std::sync::Arc;
use tokio_rustls::rustls::ServerConfig;
use tokio_rustls::rustls::{ClientConfig, RootCertStore};
use tokio_rustls::{TlsAcceptor, TlsConnector};

pub fn from_base64_raw(pem: &str) -> io::Result<Vec<u8>> {
    let cert_bytes = base64_engine
        .decode(pem)
        .map_err(|e| io::Error::new(io::ErrorKind::InvalidData, e.to_string()));

    return cert_bytes;
}

pub fn certs_from_base64(cert_base64: &str) -> io::Result<Vec<Certificate>> {
    let cert_bytes = from_base64_raw(cert_base64)?;
    let mut cursor = Cursor::new(cert_bytes);
    certs(&mut cursor)
        .map(|result| result.map(|der| Certificate(der.to_vec())))
        .collect()
}

pub fn privkey_from_base64(privkey_base64: &str) -> io::Result<PrivateKey> {
    let key_bytes = from_base64_raw(privkey_base64)?;
    let mut cursor = Cursor::new(key_bytes);
    let keys = pkcs8_private_keys(&mut cursor)
        .collect::<Result<Vec<_>, _>>()
        .map_err(|_| io::Error::new(io::ErrorKind::InvalidData, "Failed to read private keys"))?;
    let key = keys
        .into_iter()
        .next()
        .ok_or_else(|| io::Error::new(io::ErrorKind::NotFound, "No private key found"))?;
    Ok(PrivateKey(key.secret_pkcs8_der().to_vec()))
}

pub fn tls_connector_from_base64(
    ca_cert_base64: &str,
) -> Result<TlsConnector, Box<dyn std::error::Error>> {
    let mut root_store = RootCertStore::empty();
    let certs = load_certs_from_base64(ca_cert_base64)?;
    for cert in certs {
        root_store.add(cert)?;
    }
    let config = ClientConfig::builder()
        .with_root_certificates(root_store)
        .with_no_client_auth();
    Ok(TlsConnector::from(Arc::new(config)))
}

pub fn tls_acceptor_from_base64(
    cert_base64: &str,
    privkey_base64: &str,
    h1: bool,
    h2: bool,
) -> Result<TlsAcceptor, Box<dyn std::error::Error + Send + Sync>> {
    let certs = load_certs_from_base64(cert_base64)?;
    let key = load_keys_from_base64(privkey_base64)?;

    let mut server_config = ServerConfig::builder()
        .with_no_client_auth()
        .with_single_cert(certs, key)?;

    let mut protos = Vec::new();

    if h2 {
        protos.push(b"h2".to_vec());
    }

    if h1 {
        protos.push(b"http/1.1".to_vec());
        protos.push(b"http/1.0".to_vec());
    }

    server_config.alpn_protocols = protos;

    let tls_acceptor = TlsAcceptor::from(Arc::new(server_config));

    Ok(tls_acceptor)
}

pub fn load_certs_from_base64(cert_base64: &str) -> io::Result<Vec<CertificateDer<'static>>> {
    let cert_bytes = from_base64_raw(cert_base64)?;
    let mut cursor = Cursor::new(cert_bytes);
    certs(&mut cursor).collect()
}

pub fn load_keys_from_base64(privkey_base64: &str) -> io::Result<PrivateKeyDer<'static>> {
    let key_bytes = from_base64_raw(privkey_base64)?;
    let mut cursor = Cursor::new(key_bytes);

    let keys = pkcs8_private_keys(&mut cursor)
        .collect::<Result<Vec<_>, _>>() // This collects results and returns Result<Vec<T>, E>
        .map_err(|_| io::Error::new(io::ErrorKind::InvalidData, "Failed to read private keys"))?;

    let key = keys
        .into_iter()
        .next()
        .ok_or_else(|| io::Error::new(io::ErrorKind::NotFound, "No private key found"))?;

    Ok(PrivateKeyDer::from(key))
}