Skip to content

Commit ad7d00d

Browse files
authored
Update to rustls 0.22 (#154)
1 parent 04b33e7 commit ad7d00d

File tree

4 files changed

+102
-75
lines changed

4 files changed

+102
-75
lines changed

Cargo.toml

+6-5
Original file line numberDiff line numberDiff line change
@@ -23,13 +23,14 @@ log = "0.4.17"
2323
mime = {version = "0.3.16", optional = true}
2424
multipart = {version = "0.18.0", default-features = false, features = ["client"], optional = true}
2525
native-tls = {version = "0.2.10", optional = true}
26-
rustls-native-certs = { version = "0.6", optional = true}
27-
rustls-opt-dep = {package = "rustls", version = "0.21.0", features = ["dangerous_configuration"], optional = true}
26+
rustls-native-certs = { version = "0.7", optional = true}
27+
rustls-opt-dep = {package = "rustls", version = "0.22.0", optional = true}
28+
rustls-pki-types = "1"
2829
serde = {version = "1.0.143", optional = true}
2930
serde_json = {version = "1.0.83", optional = true}
3031
serde_urlencoded = {version = "0.7.1", optional = true}
3132
url = "2.2.2"
32-
webpki-roots = {version = "0.25.1", optional = true}
33+
webpki-roots = {version = "0.26.0", optional = true}
3334

3435
[dev-dependencies]
3536
anyhow = "1.0.61"
@@ -40,9 +41,9 @@ http02 = {package = "http", version = "0.2"}
4041
hyper = "0.14.20"
4142
lazy_static = "1.4.0"
4243
multipart = {version = "0.18.0", default-features = false, features = ["server"]}
43-
rustls-pemfile = "1.0.3"
44+
rustls-pemfile = "2"
4445
tokio = {version = "1.20.1", features = ["full"]}
45-
tokio-rustls = "0.24.1"
46+
tokio-rustls = "0.25.0"
4647
tokio-stream = {version = "0.1.9", features = ["net"]}
4748
warp = "0.3.2"
4849

src/error.rs

+12
Original file line numberDiff line numberDiff line change
@@ -89,6 +89,9 @@ pub enum ErrorKind {
8989
InvalidMimeType(String),
9090
/// TLS was not enabled by features.
9191
TlsDisabled,
92+
/// Empty cert store
93+
#[cfg(all(feature = "__rustls", not(feature = "tls-native")))]
94+
ServerCertVerifier(rustls::client::VerifierBuilderError),
9295
}
9396

9497
/// A type that contains all the errors that can possibly occur while accessing an HTTP server.
@@ -132,6 +135,8 @@ impl Display for Error {
132135
InvalidDNSName(ref e) => write!(w, "Invalid DNS name: {e}"),
133136
InvalidMimeType(ref e) => write!(w, "Invalid mime type: {e}"),
134137
TlsDisabled => write!(w, "TLS is disabled, activate one of the tls- features"),
138+
#[cfg(all(feature = "__rustls", not(feature = "tls-native")))]
139+
ServerCertVerifier(ref e) => write!(w, "Invalid certificate: {e}"),
135140
}
136141
}
137142
}
@@ -216,6 +221,13 @@ impl From<InvalidResponseKind> for Error {
216221
}
217222
}
218223

224+
#[cfg(all(feature = "__rustls", not(feature = "tls-native")))]
225+
impl From<rustls::client::VerifierBuilderError> for Error {
226+
fn from(err: rustls::client::VerifierBuilderError) -> Error {
227+
Error(Box::new(ErrorKind::ServerCertVerifier(err)))
228+
}
229+
}
230+
219231
impl From<Error> for io::Error {
220232
fn from(err: Error) -> io::Error {
221233
io::Error::new(io::ErrorKind::Other, err)

src/tls/rustls_impl.rs

+68-33
Original file line numberDiff line numberDiff line change
@@ -1,24 +1,25 @@
1-
use std::convert::TryInto;
1+
use std::convert::TryFrom;
22
use std::fmt;
33
use std::io;
44
use std::io::prelude::*;
55
use std::sync::Arc;
6-
use std::time::SystemTime;
76

8-
#[cfg(feature = "tls-rustls-webpki-roots")]
9-
use rustls::OwnedTrustAnchor;
107
use rustls::{
11-
client::{ServerCertVerified, ServerCertVerifier, WebPkiVerifier},
12-
ClientConfig, ClientConnection, RootCertStore, ServerName, StreamOwned,
8+
client::{
9+
danger::{DangerousClientConfigBuilder, HandshakeSignatureValid, ServerCertVerified, ServerCertVerifier},
10+
WebPkiServerVerifier,
11+
},
12+
ClientConfig, ClientConnection, DigitallySignedStruct, RootCertStore, SignatureScheme, StreamOwned,
1313
};
1414
#[cfg(feature = "tls-rustls-native-roots")]
1515
use rustls_native_certs::load_native_certs;
16+
use rustls_pki_types::{CertificateDer, ServerName, UnixTime};
1617
#[cfg(feature = "tls-rustls-webpki-roots")]
1718
use webpki_roots::TLS_SERVER_ROOTS;
1819

1920
use crate::{Error, ErrorKind, Result};
2021

21-
pub type Certificate = rustls::Certificate;
22+
pub type Certificate = CertificateDer<'static>;
2223

2324
pub struct TlsHandshaker {
2425
inner: Option<Arc<ClientConfig>>,
@@ -59,36 +60,33 @@ impl TlsHandshaker {
5960
let mut root_store = RootCertStore::empty();
6061

6162
#[cfg(feature = "tls-rustls-webpki-roots")]
62-
root_store.add_server_trust_anchors(TLS_SERVER_ROOTS.iter().map(|root| {
63-
OwnedTrustAnchor::from_subject_spki_name_constraints(root.subject, root.spki, root.name_constraints)
64-
}));
63+
root_store.extend(TLS_SERVER_ROOTS.iter().cloned());
6564

6665
#[cfg(feature = "tls-rustls-native-roots")]
67-
for native_cert in load_native_certs()? {
68-
let cert = rustls::Certificate(native_cert.0);
66+
for cert in load_native_certs()? {
6967
// Inspired by https://github.com/seanmonstar/reqwest/blob/231b18f83572836c674404b33cb1ca8b35ca3e36/src/async_impl/client.rs#L363-L365
7068
// Native certificate stores often include certificates with invalid formats,
7169
// but we don't want those invalid entries to invalidate the entire process of
7270
// loading native root certificates
73-
if let Err(e) = root_store.add(&cert) {
71+
if let Err(e) = root_store.add(cert) {
7472
warn!("Could not load native root certificate: {}", e);
7573
}
7674
}
7775

78-
for cert in &self.additional_certs {
76+
for cert in self.additional_certs.iter().cloned() {
7977
root_store.add(cert)?;
8078
}
8179

82-
let config = Arc::new(
83-
ClientConfig::builder()
84-
.with_safe_defaults()
85-
.with_custom_certificate_verifier(Arc::new(CustomCertVerifier {
86-
upstream: WebPkiVerifier::new(root_store, None),
87-
accept_invalid_certs: self.accept_invalid_certs,
88-
accept_invalid_hostnames: self.accept_invalid_hostnames,
89-
}))
90-
.with_no_client_auth(),
91-
);
80+
let config = DangerousClientConfigBuilder {
81+
cfg: ClientConfig::builder(),
82+
}
83+
.with_custom_certificate_verifier(Arc::new(CustomCertVerifier {
84+
upstream: WebPkiServerVerifier::builder(root_store.into()).build()?,
85+
accept_invalid_certs: self.accept_invalid_certs,
86+
accept_invalid_hostnames: self.accept_invalid_hostnames,
87+
}))
88+
.with_no_client_auth()
89+
.into();
9290

9391
self.inner = Some(Arc::clone(&config));
9492

@@ -101,9 +99,9 @@ impl TlsHandshaker {
10199
where
102100
S: Read + Write,
103101
{
104-
let domain = domain
105-
.try_into()
106-
.map_err(|_| Error(Box::new(ErrorKind::InvalidDNSName(domain.to_owned()))))?;
102+
let domain = ServerName::try_from(domain)
103+
.map_err(|_| Error(Box::new(ErrorKind::InvalidDNSName(domain.to_owned()))))?
104+
.to_owned();
107105
let config = self.client_config()?;
108106
let mut session = ClientConnection::new(config, domain)?;
109107

@@ -184,24 +182,29 @@ where
184182
}
185183

186184
struct CustomCertVerifier {
187-
upstream: WebPkiVerifier,
185+
upstream: Arc<WebPkiServerVerifier>,
188186
accept_invalid_certs: bool,
189187
accept_invalid_hostnames: bool,
190188
}
191189

190+
impl fmt::Debug for CustomCertVerifier {
191+
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
192+
f.debug_struct("CustomCertVerifier").finish()
193+
}
194+
}
195+
192196
impl ServerCertVerifier for CustomCertVerifier {
193197
fn verify_server_cert(
194198
&self,
195-
end_entity: &Certificate,
196-
intermediates: &[Certificate],
199+
end_entity: &CertificateDer,
200+
intermediates: &[CertificateDer],
197201
server_name: &ServerName,
198-
scts: &mut dyn Iterator<Item = &[u8]>,
199202
ocsp_response: &[u8],
200-
now: SystemTime,
203+
now: UnixTime,
201204
) -> std::result::Result<ServerCertVerified, rustls::Error> {
202205
match self
203206
.upstream
204-
.verify_server_cert(end_entity, intermediates, server_name, scts, ocsp_response, now)
207+
.verify_server_cert(end_entity, intermediates, server_name, ocsp_response, now)
205208
{
206209
Err(rustls::Error::NoCertificatesPresented | rustls::Error::InvalidCertificate(_))
207210
if self.accept_invalid_certs =>
@@ -218,4 +221,36 @@ impl ServerCertVerifier for CustomCertVerifier {
218221
upstream => upstream,
219222
}
220223
}
224+
225+
fn verify_tls12_signature(
226+
&self,
227+
message: &[u8],
228+
cert: &CertificateDer<'_>,
229+
dss: &DigitallySignedStruct,
230+
) -> std::result::Result<HandshakeSignatureValid, rustls::Error> {
231+
rustls::crypto::verify_tls12_signature(
232+
message,
233+
cert,
234+
dss,
235+
&rustls::crypto::ring::default_provider().signature_verification_algorithms,
236+
)
237+
}
238+
239+
fn verify_tls13_signature(
240+
&self,
241+
message: &[u8],
242+
cert: &CertificateDer<'_>,
243+
dss: &DigitallySignedStruct,
244+
) -> std::result::Result<HandshakeSignatureValid, rustls::Error> {
245+
rustls::crypto::verify_tls13_signature(
246+
message,
247+
cert,
248+
dss,
249+
&rustls::crypto::ring::default_provider().signature_verification_algorithms,
250+
)
251+
}
252+
253+
fn supported_verify_schemes(&self) -> Vec<SignatureScheme> {
254+
self.upstream.supported_verify_schemes()
255+
}
221256
}

tests/tools/tls.rs

+16-37
Original file line numberDiff line numberDiff line change
@@ -13,18 +13,14 @@ use futures::ready;
1313
use hyper::server::accept::Accept;
1414
use hyper::server::conn::{AddrIncoming, AddrStream};
1515
use tokio::io::{AsyncRead, AsyncWrite, ReadBuf};
16-
use tokio_rustls::rustls::{ServerConfig, Error as TLSError, PrivateKey, Certificate};
16+
use tokio_rustls::rustls::{Error as TLSError, ServerConfig};
1717

1818
/// Represents errors that can occur building the TlsConfig
1919
#[derive(Debug)]
2020
pub(crate) enum TlsConfigError {
2121
Io(io::Error),
2222
/// An Error parsing the Certificate
2323
CertParseError,
24-
/// An Error parsing a Pkcs8 key
25-
Pkcs8ParseError,
26-
/// An Error parsing a Rsa key
27-
RsaParseError,
2824
/// An error from an empty key
2925
EmptyKey,
3026
/// An error from an invalid key
@@ -36,8 +32,6 @@ impl std::fmt::Display for TlsConfigError {
3632
match self {
3733
TlsConfigError::Io(err) => err.fmt(f),
3834
TlsConfigError::CertParseError => write!(f, "certificate parse error"),
39-
TlsConfigError::Pkcs8ParseError => write!(f, "pkcs8 parse error"),
40-
TlsConfigError::RsaParseError => write!(f, "rsa parse error"),
4135
TlsConfigError::EmptyKey => write!(f, "key contains no private key"),
4236
TlsConfigError::InvalidKey(err) => write!(f, "key contains an invalid key, {err}"),
4337
}
@@ -46,6 +40,12 @@ impl std::fmt::Display for TlsConfigError {
4640

4741
impl std::error::Error for TlsConfigError {}
4842

43+
impl From<io::Error> for TlsConfigError {
44+
fn from(err: io::Error) -> Self {
45+
Self::Io(err)
46+
}
47+
}
48+
4949
/// Builder to set the configuration for the Tls server.
5050
pub(crate) struct TlsConfigBuilder {
5151
cert: Box<dyn Read + Send + Sync>,
@@ -81,41 +81,20 @@ impl TlsConfigBuilder {
8181
self
8282
}
8383

84-
pub(crate) fn build(mut self) -> Result<ServerConfig, TlsConfigError> {
84+
pub(crate) fn build(self) -> Result<ServerConfig, TlsConfigError> {
8585
let mut cert_rdr = BufReader::new(self.cert);
8686
let cert = rustls_pemfile::certs(&mut cert_rdr)
87-
.map_err(|_| TlsConfigError::CertParseError)?.into_iter().map(Certificate).collect();
88-
89-
let key = {
90-
// convert it to Vec<u8> to allow reading it again if key is RSA
91-
let mut key_vec = Vec::new();
92-
self.key.read_to_end(&mut key_vec).map_err(TlsConfigError::Io)?;
93-
94-
if key_vec.is_empty() {
95-
return Err(TlsConfigError::EmptyKey);
96-
}
97-
98-
let mut pkcs8 = rustls_pemfile::pkcs8_private_keys(&mut key_vec.as_slice())
99-
.map_err(|_| TlsConfigError::Pkcs8ParseError)?;
100-
101-
if !pkcs8.is_empty() {
102-
PrivateKey(pkcs8.remove(0))
103-
} else {
104-
let mut rsa = rustls_pemfile::rsa_private_keys(&mut key_vec.as_slice())
105-
.map_err(|_| TlsConfigError::RsaParseError)?;
106-
107-
if !rsa.is_empty() {
108-
PrivateKey(rsa.remove(0))
109-
} else {
110-
return Err(TlsConfigError::EmptyKey);
111-
}
112-
}
87+
.collect::<Result<Vec<_>, _>>()
88+
.map_err(|_| TlsConfigError::CertParseError)?;
89+
90+
let Some(key) = rustls_pemfile::private_key(&mut BufReader::new(self.key))? else {
91+
return Err(TlsConfigError::EmptyKey);
11392
};
11493

11594
let config = ServerConfig::builder()
116-
.with_safe_defaults()
117-
.with_no_client_auth().
118-
with_single_cert_with_ocsp_and_sct(cert, key, self.ocsp_resp, Vec::new()).map_err(TlsConfigError::InvalidKey)?;
95+
.with_no_client_auth()
96+
.with_single_cert_with_ocsp(cert, key, self.ocsp_resp)
97+
.map_err(TlsConfigError::InvalidKey)?;
11998
Ok(config)
12099
}
121100
}

0 commit comments

Comments
 (0)