From c25988233609787e15b25f2cd155d6e98ccd9ef3 Mon Sep 17 00:00:00 2001 From: gustavowd Date: Wed, 27 Mar 2024 06:12:56 -0300 Subject: [PATCH] Upgrade rustls-pemfile and tokio-rustls (#253) --- Cargo.toml | 6 ++-- examples/tls-client.rs | 59 +++++++++++++++++++++------------------- examples/tls-server.rs | 62 ++++++++++++++++++++++-------------------- 3 files changed, 68 insertions(+), 59 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 7a9d9fd..60434dd 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -51,11 +51,13 @@ tokio = { version = "1.35.1", default-features = false, features = [ "time", ] } tokio-serial = { version = "5.4.4", default-features = false } -rustls-pemfile = "1.0.3" -tokio-rustls = "0.24.1" +rustls-pemfile = "2.1.1" +tokio-rustls = "0.25.0" pkcs8 = { version = "0.10.2", features = ["encryption", "pem", "std"] } pem = "3.0.3" webpki = "0.22.4" +pki-types = { package = "rustls-pki-types", version = "1" } +rustls = "0.22.3" [features] default = ["rtu", "tcp"] diff --git a/examples/tls-client.rs b/examples/tls-client.rs index f37fe8d..6508abb 100644 --- a/examples/tls-client.rs +++ b/examples/tls-client.rs @@ -16,18 +16,15 @@ use std::{ }; use pkcs8::der::Decode; +use pki_types::{CertificateDer, PrivateKeyDer, ServerName}; use rustls_pemfile::{certs, pkcs8_private_keys}; -use tokio_rustls::rustls::{self, Certificate, OwnedTrustAnchor, PrivateKey}; use tokio_rustls::TlsConnector; -use webpki::TrustAnchor; -fn load_certs(path: &Path) -> io::Result> { - certs(&mut BufReader::new(File::open(path)?)) - .map_err(|_| io::Error::new(io::ErrorKind::InvalidInput, "invalid cert")) - .map(|mut certs| certs.drain(..).map(Certificate).collect()) +fn load_certs(path: &Path) -> io::Result>> { + certs(&mut BufReader::new(File::open(path)?)).collect() } -fn load_keys(path: &Path, password: Option<&str>) -> io::Result> { +fn load_keys(path: &Path, password: Option<&str>) -> io::Result> { let expected_tag = match &password { Some(_) => "ENCRYPTED PRIVATE KEY", None => "PRIVATE KEY", @@ -35,8 +32,9 @@ fn load_keys(path: &Path, password: Option<&str>) -> io::Result> if expected_tag.eq("PRIVATE KEY") { pkcs8_private_keys(&mut BufReader::new(File::open(path)?)) - .map_err(|_| io::Error::new(io::ErrorKind::InvalidInput, "invalid key")) - .map(|mut keys| keys.drain(..).map(PrivateKey).collect()) + .next() + .unwrap() + .map(Into::into) } else { let content = std::fs::read(path)?; let mut iter = pem::parse_many(content) @@ -56,9 +54,23 @@ fn load_keys(path: &Path, password: Option<&str>) -> io::Result> io::Error::new(io::ErrorKind::InvalidData, err.to_string()) })?; let key = decrypted.as_bytes().to_vec(); - let key = rustls::PrivateKey(key); - let private_keys = vec![key]; - io::Result::Ok(private_keys) + match rustls_pemfile::read_one_from_slice(&key) + .expect("cannot parse private key .pem file") + { + Some((rustls_pemfile::Item::Pkcs1Key(key), _keys)) => { + io::Result::Ok(key.into()) + } + Some((rustls_pemfile::Item::Pkcs8Key(key), _keys)) => { + io::Result::Ok(key.into()) + } + Some((rustls_pemfile::Item::Sec1Key(key), _keys)) => { + io::Result::Ok(key.into()) + } + _ => io::Result::Err(io::Error::new( + io::ErrorKind::InvalidInput, + "invalid key", + )), + } } None => io::Result::Err(io::Error::new(io::ErrorKind::InvalidInput, "invalid key")), }, @@ -73,37 +85,28 @@ async fn main() -> Result<(), Box> { let socket_addr: SocketAddr = "127.0.0.1:8802".parse()?; - let mut root_cert_store = rustls::RootCertStore::empty(); + let mut root_cert_store = tokio_rustls::rustls::RootCertStore::empty(); let ca_path = Path::new("./pki/ca.pem"); let mut pem = BufReader::new(File::open(ca_path)?); - let certs = rustls_pemfile::certs(&mut pem)?; - let trust_anchors = certs.iter().map(|cert| { - let ta = TrustAnchor::try_from_cert_der(&cert[..]).expect("cert should parse as anchor!"); - OwnedTrustAnchor::from_subject_spki_name_constraints( - ta.subject, - ta.spki, - ta.name_constraints, - ) - }); - root_cert_store.add_trust_anchors(trust_anchors); + let certs = rustls_pemfile::certs(&mut pem).collect::, _>>()?; + root_cert_store.add_parsable_certificates(certs); let domain = "localhost"; let cert_path = Path::new("./pki/client.pem"); let key_path = Path::new("./pki/client.key"); let certs = load_certs(cert_path)?; - let mut keys = load_keys(key_path, None)?; + let key = load_keys(key_path, None)?; - let config = rustls::ClientConfig::builder() - .with_safe_defaults() + let config = tokio_rustls::rustls::ClientConfig::builder() .with_root_certificates(root_cert_store) - .with_client_auth_cert(certs, keys.remove(0)) + .with_client_auth_cert(certs, key) .map_err(|err| io::Error::new(io::ErrorKind::InvalidInput, err))?; let connector = TlsConnector::from(Arc::new(config)); let stream = TcpStream::connect(&socket_addr).await?; stream.set_nodelay(true)?; - let domain = rustls::ServerName::try_from(domain) + let domain = ServerName::try_from(domain) .map_err(|_| io::Error::new(io::ErrorKind::InvalidInput, "invalid dnsname"))?; let transport = connector.connect(domain, stream).await?; diff --git a/examples/tls-server.rs b/examples/tls-server.rs index 2cf567f..e559356 100644 --- a/examples/tls-server.rs +++ b/examples/tls-server.rs @@ -18,20 +18,17 @@ use std::{ }; use pkcs8::der::Decode; +use pki_types::{CertificateDer, PrivateKeyDer, ServerName}; use rustls_pemfile::{certs, pkcs8_private_keys}; use tokio::net::{TcpListener, TcpStream}; use tokio_modbus::{prelude::*, server::tcp::Server}; -use tokio_rustls::rustls::{self, Certificate, OwnedTrustAnchor, PrivateKey}; use tokio_rustls::{TlsAcceptor, TlsConnector}; -use webpki::TrustAnchor; -fn load_certs(path: &Path) -> io::Result> { - certs(&mut BufReader::new(File::open(path)?)) - .map_err(|_| io::Error::new(io::ErrorKind::InvalidInput, "invalid cert")) - .map(|mut certs| certs.drain(..).map(Certificate).collect()) +fn load_certs(path: &Path) -> io::Result>> { + certs(&mut BufReader::new(File::open(path)?)).collect() } -fn load_keys(path: &Path, password: Option<&str>) -> io::Result> { +fn load_keys(path: &Path, password: Option<&str>) -> io::Result> { let expected_tag = match &password { Some(_) => "ENCRYPTED PRIVATE KEY", None => "PRIVATE KEY", @@ -39,8 +36,9 @@ fn load_keys(path: &Path, password: Option<&str>) -> io::Result> if expected_tag.eq("PRIVATE KEY") { pkcs8_private_keys(&mut BufReader::new(File::open(path)?)) - .map_err(|_| io::Error::new(io::ErrorKind::InvalidInput, "invalid key")) - .map(|mut keys| keys.drain(..).map(PrivateKey).collect()) + .next() + .unwrap() + .map(Into::into) } else { let content = std::fs::read(path)?; let mut iter = pem::parse_many(content) @@ -60,9 +58,23 @@ fn load_keys(path: &Path, password: Option<&str>) -> io::Result> io::Error::new(io::ErrorKind::InvalidData, err.to_string()) })?; let key = decrypted.as_bytes().to_vec(); - let key = rustls::PrivateKey(key); - let private_keys = vec![key]; - io::Result::Ok(private_keys) + match rustls_pemfile::read_one_from_slice(&key) + .expect("cannot parse private key .pem file") + { + Some((rustls_pemfile::Item::Pkcs1Key(key), _keys)) => { + io::Result::Ok(key.into()) + } + Some((rustls_pemfile::Item::Pkcs8Key(key), _keys)) => { + io::Result::Ok(key.into()) + } + Some((rustls_pemfile::Item::Sec1Key(key), _keys)) => { + io::Result::Ok(key.into()) + } + _ => io::Result::Err(io::Error::new( + io::ErrorKind::InvalidInput, + "invalid key", + )), + } } None => io::Result::Err(io::Error::new(io::ErrorKind::InvalidInput, "invalid key")), }, @@ -189,11 +201,10 @@ async fn server_context(socket_addr: SocketAddr) -> anyhow::Result<()> { let cert_path = Path::new("./pki/server.pem"); let key_path = Path::new("./pki/server.key"); let certs = load_certs(cert_path)?; - let mut keys = load_keys(key_path, None)?; + let key = load_keys(key_path, None)?; let config = rustls::ServerConfig::builder() - .with_safe_defaults() .with_no_client_auth() - .with_single_cert(certs, keys.remove(0)) + .with_single_cert(certs, key) .map_err(|err| io::Error::new(io::ErrorKind::InvalidInput, err))?; let acceptor = TlsAcceptor::from(Arc::new(config)); @@ -222,27 +233,20 @@ async fn client_context(socket_addr: SocketAddr) { let mut root_cert_store = rustls::RootCertStore::empty(); let ca_path = Path::new("./pki/ca.pem"); let mut pem = BufReader::new(File::open(ca_path).unwrap()); - let certs = rustls_pemfile::certs(&mut pem).unwrap(); - let trust_anchors = certs.iter().map(|cert| { - let ta = TrustAnchor::try_from_cert_der(&cert[..]).unwrap(); - OwnedTrustAnchor::from_subject_spki_name_constraints( - ta.subject, - ta.spki, - ta.name_constraints, - ) - }); - root_cert_store.add_trust_anchors(trust_anchors); + let certs = rustls_pemfile::certs(&mut pem) + .collect::, _>>() + .unwrap(); + root_cert_store.add_parsable_certificates(certs); let domain = "localhost"; let cert_path = Path::new("./pki/client.pem"); let key_path = Path::new("./pki/client.key"); let certs = load_certs(cert_path).unwrap(); - let mut keys = load_keys(key_path, None).unwrap(); + let key = load_keys(key_path, None).unwrap(); let config = rustls::ClientConfig::builder() - .with_safe_defaults() .with_root_certificates(root_cert_store) - .with_client_auth_cert(certs, keys.remove(0)) + .with_client_auth_cert(certs, key) .map_err(|err| io::Error::new(io::ErrorKind::InvalidInput, err)) .unwrap(); let connector = TlsConnector::from(Arc::new(config)); @@ -250,7 +254,7 @@ async fn client_context(socket_addr: SocketAddr) { let stream = TcpStream::connect(&socket_addr).await.unwrap(); stream.set_nodelay(true).unwrap(); - let domain = rustls::ServerName::try_from(domain) + let domain = ServerName::try_from(domain) .map_err(|_| io::Error::new(io::ErrorKind::InvalidInput, "invalid dnsname")) .unwrap();