1use rustls::{
2 server::{AllowAnyAuthenticatedClient, NoClientAuth},
3 Certificate, ClientConfig, PrivateKey, RootCertStore, ServerConfig,
4};
5
6pub fn cert_from_pem(cert: Vec<u8>) -> Result<Vec<Certificate>, std::io::Error> {
8 let cert_list = rustls_pemfile::read_all(&mut cert.as_ref())?
9 .into_iter()
10 .filter_map(|i| match i {
11 rustls_pemfile::Item::X509Certificate(i) => Some(i),
12 _ => None,
13 })
14 .map(Certificate)
15 .collect::<Vec<_>>();
16 if cert_list.len() >= 1 {
17 Ok(cert_list)
18 } else {
19 Err(std::io::Error::new(
20 std::io::ErrorKind::NotFound,
21 "No certififcate found.",
22 ))
23 }
24}
25
26pub fn key_from_pem(key: Vec<u8>) -> Result<PrivateKey, std::io::Error> {
28 let option_key = rustls_pemfile::read_all(&mut key.as_ref())?
29 .into_iter()
30 .find_map(|i| match i {
31 rustls_pemfile::Item::RSAKey(i)
32 | rustls_pemfile::Item::PKCS8Key(i)
33 | rustls_pemfile::Item::ECKey(i) => Some(i),
34 _ => None,
35 })
36 .map(PrivateKey);
37 match option_key {
38 Some(k) => Ok(k),
39 None => Err(std::io::Error::new(
40 std::io::ErrorKind::NotFound,
41 "No private key found.",
42 )),
43 }
44}
45
46pub fn create_server_config(
48 cert: Vec<Certificate>,
49 key: PrivateKey,
50 ca: Option<Vec<Certificate>>,
51) -> Result<ServerConfig, rustls::Error> {
52 Ok(ServerConfig::builder()
53 .with_safe_defaults()
54 .with_client_cert_verifier(match ca {
55 Some(ca) => AllowAnyAuthenticatedClient::new(root_cert_store(ca)?).boxed(),
56 None => NoClientAuth::boxed(),
57 })
58 .with_single_cert(cert, key)?)
59}
60
61pub fn create_client_config(
64 cert: Option<Vec<Certificate>>,
65 key: Option<PrivateKey>,
66 ca: Vec<Certificate>,
67) -> Result<ClientConfig, rustls::Error> {
68 let builder = ClientConfig::builder()
69 .with_safe_defaults()
70 .with_root_certificates(root_cert_store(ca)?);
71 let config = if let (Some(cert), Some(key)) = (cert, key) {
72 builder.with_client_auth_cert(cert, key)?
73 } else {
74 builder.with_no_client_auth()
75 };
76 Ok(config)
77}
78
79fn root_cert_store(cert: Vec<Certificate>) -> Result<RootCertStore, rustls::Error> {
80 let mut roots = rustls::RootCertStore::empty();
81 for cer in cert {
82 roots.add(&cer)?;
83 }
84 Ok(roots)
85}