tls-helpers 0.2.0

helpers for creating tls tcp connections
Documentation
use base64::engine::general_purpose::STANDARD as base64_engine;
use base64::Engine;
use pki_types::{CertificateDer, PrivateKeyDer};
use rustls_pemfile::{certs, private_key};
use std::io::{self, Cursor};
use std::sync::Arc;
use tokio_rustls::rustls::crypto::ring;
use tokio_rustls::rustls::{ClientConfig, RootCertStore, ServerConfig};
use tokio_rustls::{TlsAcceptor, TlsConnector};

fn install_provider() {
    let _ = ring::default_provider().install_default();
}

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<CertificateDer<'static>>> {
    let cert_bytes = from_base64_raw(cert_base64)?;
    let mut cursor = Cursor::new(cert_bytes);
    certs(&mut cursor).collect()
}

pub fn privkey_from_base64(privkey_base64: &str) -> io::Result<PrivateKeyDer<'static>> {
    let key_bytes = from_base64_raw(privkey_base64)?;
    let mut cursor = Cursor::new(key_bytes);
    private_key(&mut cursor)?
        .ok_or_else(|| io::Error::new(io::ErrorKind::NotFound, "No private key found"))
}

pub fn tls_connector_from_base64(
    ca_cert_base64: &str,
) -> Result<TlsConnector, Box<dyn std::error::Error>> {
    install_provider();
    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>> {
    install_provider();
    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>>> {
    install_provider();
    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>> {
    install_provider();
    let key_bytes = from_base64_raw(privkey_base64)?;
    let mut cursor = Cursor::new(key_bytes);
    private_key(&mut cursor)?
        .ok_or_else(|| io::Error::new(io::ErrorKind::NotFound, "No private key found"))
}