Skip to content

Commit 7b9280c

Browse files
ctzisabelatkinson
andauthored
RUST-2171 Update rustls to 0.23 (#1322)
* Take rustls 0.23 rustls 0.21 is EOL for security support at the end of March 2025. - Drop rustls-pemfile, as it is now incorporated into rustls-pki-types; use the new iterator-based API. - Use the ring-based provider, to align with previous version's build-time requirements. * fixup: update src/runtime/tls_rustls.rs Co-authored-by: Isabel Atkinson <[email protected]> * fmt --------- Co-authored-by: Isabel Atkinson <[email protected]> Co-authored-by: Isabel Atkinson <[email protected]>
1 parent 5b603f2 commit 7b9280c

File tree

2 files changed

+116
-79
lines changed

2 files changed

+116
-79
lines changed

Cargo.toml

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ exclude = [
3131
default = ["compat-3-0-0", "rustls-tls", "dns-resolver"]
3232
compat-3-0-0 = []
3333
sync = []
34-
rustls-tls = ["dep:rustls", "dep:rustls-pemfile", "dep:tokio-rustls"]
34+
rustls-tls = ["dep:rustls", "dep:tokio-rustls"]
3535
openssl-tls = ["dep:openssl", "dep:openssl-probe", "dep:tokio-openssl"]
3636
dns-resolver = ["dep:hickory-resolver", "dep:hickory-proto"]
3737
cert-key-password = ["dep:pem", "dep:pkcs8"]
@@ -102,7 +102,6 @@ pkcs8 = { version = "0.10.2", features = ["encryption", "pkcs5"], optional = tru
102102
rand = { version = "0.8.3", features = ["small_rng"] }
103103
rayon = { version = "1.5.3", optional = true }
104104
rustc_version_runtime = "0.3.0"
105-
rustls-pemfile = { version = "1.0.1", optional = true }
106105
serde_with = "3.8.1"
107106
sha-1 = "0.10.0"
108107
sha2 = "0.10.2"
@@ -115,7 +114,7 @@ thiserror = "1.0.24"
115114
tokio-openssl = { version = "0.6.3", optional = true }
116115
tracing = { version = "0.1.36", optional = true }
117116
typed-builder = "0.10.0"
118-
webpki-roots = "0.25.2"
117+
webpki-roots = "0.26"
119118
zstd = { version = "0.11.2", optional = true }
120119
macro_magic = "0.5.1"
121120

@@ -130,9 +129,10 @@ default-features = false
130129
features = ["json", "rustls-tls"]
131130

132131
[dependencies.rustls]
133-
version = "0.21.6"
132+
version = "0.23.20"
134133
optional = true
135-
features = ["dangerous_configuration"]
134+
default-features = false
135+
features = ["logging", "ring", "std", "tls12"]
136136

137137
[dependencies.serde]
138138
version = "1.0.125"
@@ -146,9 +146,10 @@ version = "1.17.0"
146146
features = ["io-util", "sync", "macros", "net", "process", "rt", "time", "fs"]
147147

148148
[dependencies.tokio-rustls]
149-
version = "0.24.1"
149+
version = "0.26"
150150
optional = true
151-
features = ["dangerous_configuration"]
151+
default-features = false
152+
features = ["logging", "ring", "tls12"]
152153

153154
[dependencies.tokio-util]
154155
version = "0.7.0"

src/runtime/tls_rustls.rs

Lines changed: 108 additions & 72 deletions
Original file line numberDiff line numberDiff line change
@@ -3,17 +3,15 @@ use std::{
33
fs::File,
44
io::{BufReader, Seek},
55
sync::Arc,
6-
time::SystemTime,
76
};
87

98
use rustls::{
10-
client::{ClientConfig, ServerCertVerified, ServerCertVerifier, ServerName},
11-
Certificate,
9+
client::ClientConfig,
10+
crypto::ring as provider,
11+
pki_types::{pem::PemObject, CertificateDer, PrivateKeyDer, ServerName},
1212
Error as TlsError,
13-
OwnedTrustAnchor,
1413
RootCertStore,
1514
};
16-
use rustls_pemfile::{certs, read_one, Item};
1715
use tokio::net::TcpStream;
1816
use tokio_rustls::TlsConnector;
1917
use webpki_roots::TLS_SERVER_ROOTS;
@@ -49,9 +47,11 @@ pub(super) async fn tls_connect(
4947
tcp_stream: TcpStream,
5048
cfg: &TlsConfig,
5149
) -> Result<TlsStream> {
52-
let name = ServerName::try_from(host).map_err(|e| ErrorKind::DnsResolve {
53-
message: format!("could not resolve {:?}: {}", host, e),
54-
})?;
50+
let name = ServerName::try_from(host)
51+
.map_err(|e| ErrorKind::DnsResolve {
52+
message: format!("could not resolve {:?}: {}", host, e),
53+
})?
54+
.to_owned();
5555

5656
let conn = cfg
5757
.connector
@@ -66,110 +66,146 @@ pub(super) async fn tls_connect(
6666
fn make_rustls_config(cfg: TlsOptions) -> Result<rustls::ClientConfig> {
6767
let mut store = RootCertStore::empty();
6868
if let Some(path) = cfg.ca_file_path {
69-
let ders = certs(&mut BufReader::new(File::open(&path)?)).map_err(|_| {
70-
ErrorKind::InvalidTlsConfig {
69+
let ders = CertificateDer::pem_file_iter(&path)
70+
.map_err(|err| ErrorKind::InvalidTlsConfig {
7171
message: format!(
72-
"Unable to parse PEM-encoded root certificate from {}",
72+
"Unable to parse PEM-encoded root certificate from {}: {err}",
7373
path.display()
7474
),
75-
}
76-
})?;
77-
store.add_parsable_certificates(&ders);
75+
})?
76+
.flatten();
77+
store.add_parsable_certificates(ders);
7878
} else {
79-
let trust_anchors = TLS_SERVER_ROOTS.iter().map(|ta| {
80-
OwnedTrustAnchor::from_subject_spki_name_constraints(
81-
ta.subject,
82-
ta.spki,
83-
ta.name_constraints,
84-
)
85-
});
86-
store.add_trust_anchors(trust_anchors);
79+
store.extend(TLS_SERVER_ROOTS.iter().cloned());
8780
}
8881

82+
let config_builder = ClientConfig::builder_with_provider(provider::default_provider().into())
83+
.with_safe_default_protocol_versions()
84+
.map_err(|e| ErrorKind::InvalidTlsConfig {
85+
message: format!(
86+
"built-in provider should support default protocol versions: {}",
87+
e
88+
),
89+
})?
90+
.with_root_certificates(store);
91+
8992
let mut config = if let Some(path) = cfg.cert_key_file_path {
9093
let mut file = BufReader::new(File::open(&path)?);
91-
let certs = match certs(&mut file) {
92-
Ok(certs) => certs.into_iter().map(Certificate).collect(),
93-
Err(error) => {
94-
return Err(ErrorKind::InvalidTlsConfig {
95-
message: format!(
96-
"Unable to parse PEM-encoded client certificate from {}: {}",
97-
path.display(),
98-
error,
99-
),
100-
}
101-
.into())
102-
}
103-
};
94+
let mut certs = vec![];
95+
96+
for cert in CertificateDer::pem_reader_iter(&mut file) {
97+
let cert = cert.map_err(|error| ErrorKind::InvalidTlsConfig {
98+
message: format!(
99+
"Unable to parse PEM-encoded client certificate from {}: {error}",
100+
path.display(),
101+
),
102+
})?;
103+
certs.push(cert);
104+
}
104105

105106
file.rewind()?;
106-
let key = loop {
107+
let key = 'key: {
107108
#[cfg(feature = "cert-key-password")]
108109
if let Some(key_pw) = cfg.tls_certificate_key_file_password.as_deref() {
110+
use rustls::pki_types::PrivatePkcs8KeyDer;
109111
use std::io::Read;
110112
let mut contents = vec![];
111113
file.read_to_end(&mut contents)?;
112-
break rustls::PrivateKey(super::pem::decrypt_private_key(&contents, key_pw)?);
114+
break 'key PrivatePkcs8KeyDer::from(super::pem::decrypt_private_key(
115+
&contents, key_pw,
116+
)?)
117+
.into();
113118
}
114-
match read_one(&mut file) {
115-
Ok(Some(Item::PKCS8Key(bytes))) | Ok(Some(Item::RSAKey(bytes))) => {
116-
break rustls::PrivateKey(bytes)
117-
}
118-
Ok(Some(_)) => continue,
119-
Ok(None) => {
120-
return Err(ErrorKind::InvalidTlsConfig {
121-
message: format!("No PEM-encoded keys in {}", path.display()),
122-
}
123-
.into())
124-
}
125-
Err(_) => {
119+
match PrivateKeyDer::from_pem_reader(&mut file) {
120+
Ok(key) => break 'key key,
121+
Err(err) => {
126122
return Err(ErrorKind::InvalidTlsConfig {
127123
message: format!(
128-
"Unable to parse PEM-encoded item from {}",
129-
path.display()
124+
"Unable to parse PEM-encoded item from {}: {err}",
125+
path.display(),
130126
),
131127
}
132128
.into())
133129
}
134130
}
135131
};
136132

137-
ClientConfig::builder()
138-
.with_safe_defaults()
139-
.with_root_certificates(store)
133+
config_builder
140134
.with_client_auth_cert(certs, key)
141135
.map_err(|error| ErrorKind::InvalidTlsConfig {
142136
message: error.to_string(),
143137
})?
144138
} else {
145-
ClientConfig::builder()
146-
.with_safe_defaults()
147-
.with_root_certificates(store)
148-
.with_no_client_auth()
139+
config_builder.with_no_client_auth()
149140
};
150141

151142
if let Some(true) = cfg.allow_invalid_certificates {
152143
// nosemgrep: rustls-dangerous
153144
config // mongodb rating: No Fix Needed
154145
.dangerous()
155-
.set_certificate_verifier(Arc::new(NoCertVerifier {}));
146+
.set_certificate_verifier(Arc::new(danger::NoCertVerifier(
147+
provider::default_provider(),
148+
)));
156149
}
157150

158151
Ok(config)
159152
}
160153

161-
struct NoCertVerifier {}
162-
163-
impl ServerCertVerifier for NoCertVerifier {
164-
fn verify_server_cert(
165-
&self,
166-
_: &Certificate,
167-
_: &[Certificate],
168-
_: &ServerName,
169-
_: &mut dyn Iterator<Item = &[u8]>,
170-
_: &[u8],
171-
_: SystemTime,
172-
) -> std::result::Result<ServerCertVerified, TlsError> {
173-
Ok(ServerCertVerified::assertion())
154+
mod danger {
155+
use super::*;
156+
use rustls::{
157+
client::danger::{HandshakeSignatureValid, ServerCertVerified, ServerCertVerifier},
158+
crypto::{verify_tls12_signature, verify_tls13_signature, CryptoProvider},
159+
pki_types::UnixTime,
160+
DigitallySignedStruct,
161+
SignatureScheme,
162+
};
163+
164+
#[derive(Debug)]
165+
pub(super) struct NoCertVerifier(pub(super) CryptoProvider);
166+
167+
impl ServerCertVerifier for NoCertVerifier {
168+
fn verify_server_cert(
169+
&self,
170+
_end_entity: &CertificateDer<'_>,
171+
_intermediates: &[CertificateDer<'_>],
172+
_server_name: &ServerName<'_>,
173+
_ocsp: &[u8],
174+
_now: UnixTime,
175+
) -> std::result::Result<ServerCertVerified, TlsError> {
176+
Ok(ServerCertVerified::assertion())
177+
}
178+
179+
fn verify_tls12_signature(
180+
&self,
181+
message: &[u8],
182+
cert: &CertificateDer<'_>,
183+
dss: &DigitallySignedStruct,
184+
) -> std::result::Result<HandshakeSignatureValid, TlsError> {
185+
verify_tls12_signature(
186+
message,
187+
cert,
188+
dss,
189+
&self.0.signature_verification_algorithms,
190+
)
191+
}
192+
193+
fn verify_tls13_signature(
194+
&self,
195+
message: &[u8],
196+
cert: &CertificateDer<'_>,
197+
dss: &DigitallySignedStruct,
198+
) -> std::result::Result<HandshakeSignatureValid, TlsError> {
199+
verify_tls13_signature(
200+
message,
201+
cert,
202+
dss,
203+
&self.0.signature_verification_algorithms,
204+
)
205+
}
206+
207+
fn supported_verify_schemes(&self) -> Vec<SignatureScheme> {
208+
self.0.signature_verification_algorithms.supported_schemes()
209+
}
174210
}
175211
}

0 commit comments

Comments
 (0)