Skip to content

Commit 23106dd

Browse files
authored
chore(tls): Update to rustls 0.22.0 (#1509)
* chore(tls): Update to rustls 0.22.0 * chore: Add examples to deny skip-tree
1 parent 2a2809b commit 23106dd

File tree

6 files changed

+74
-193
lines changed

6 files changed

+74
-193
lines changed

Cargo.toml

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,4 +28,3 @@ members = [
2828
"tests/default_stubs",
2929
]
3030
resolver = "2"
31-

deny.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ skip-tree = [
2222
{ name = "syn" },
2323
{ name = "bitflags" },
2424
{ name = "indexmap" },
25+
{ name = "examples" },
2526
]
2627

2728
[licenses]

tonic/Cargo.toml

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ gzip = ["dep:flate2"]
2828
zstd = ["dep:zstd"]
2929
default = ["transport", "codegen", "prost"]
3030
prost = ["dep:prost"]
31-
tls = ["dep:rustls-pemfile", "transport", "dep:tokio-rustls", "dep:rustls", "tokio/rt", "tokio/macros"]
31+
tls = ["dep:rustls-pki-types", "dep:rustls-pemfile", "transport", "dep:tokio-rustls", "tokio/rt", "tokio/macros"]
3232
tls-roots = ["tls-roots-common", "dep:rustls-native-certs"]
3333
tls-roots-common = ["tls"]
3434
tls-webpki-roots = ["tls-roots-common", "dep:webpki-roots"]
@@ -78,11 +78,11 @@ axum = {version = "0.6.9", default_features = false, optional = true}
7878

7979
# rustls
8080
async-stream = { version = "0.3", optional = true }
81-
rustls-pemfile = { version = "1.0", optional = true }
82-
rustls-native-certs = { version = "0.6.3", optional = true }
83-
tokio-rustls = { version = "0.24.1", optional = true }
84-
rustls = { version = "0.21.7", optional = true }
85-
webpki-roots = { version = "0.25.0", optional = true }
81+
rustls-pki-types = { version = "1.0", optional = true }
82+
rustls-pemfile = { version = "2.0", optional = true }
83+
rustls-native-certs = { version = "0.7", optional = true }
84+
tokio-rustls = { version = "0.25", optional = true }
85+
webpki-roots = { version = "0.26", optional = true }
8686

8787
# compression
8888
flate2 = {version = "1.0", optional = true}

tonic/src/transport/channel/tls.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -60,8 +60,8 @@ impl ClientTlsConfig {
6060

6161
pub(crate) fn tls_connector(&self, uri: Uri) -> Result<TlsConnector, crate::Error> {
6262
let domain = match &self.domain {
63-
None => uri.host().ok_or_else(Error::new_invalid_uri)?.to_string(),
64-
Some(domain) => domain.clone(),
63+
Some(domain) => domain,
64+
None => uri.host().ok_or_else(Error::new_invalid_uri)?,
6565
};
6666
TlsConnector::new(self.cert.clone(), self.identity.clone(), domain)
6767
}

tonic/src/transport/service/connector.rs

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -39,9 +39,7 @@ impl<C> Connector<C> {
3939
_ => return None,
4040
};
4141

42-
host.try_into()
43-
.ok()
44-
.and_then(|dns| TlsConnector::new(None, None, dns).ok())
42+
TlsConnector::new(None, None, host).ok()
4543
}
4644
}
4745

tonic/src/transport/service/tls.rs

Lines changed: 64 additions & 181 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,23 @@
1-
use super::io::BoxedIo;
2-
use crate::transport::{
3-
server::{Connected, TlsStream},
4-
Certificate, Identity,
1+
use std::{
2+
io::Cursor,
3+
{fmt, sync::Arc},
54
};
6-
use std::{fmt, sync::Arc};
5+
6+
use rustls_pki_types::{CertificateDer, PrivateKeyDer, ServerName};
77
use tokio::io::{AsyncRead, AsyncWrite};
88
use tokio_rustls::{
9-
rustls::{ClientConfig, RootCertStore, ServerConfig, ServerName},
9+
rustls::{server::WebPkiClientVerifier, ClientConfig, RootCertStore, ServerConfig},
1010
TlsAcceptor as RustlsAcceptor, TlsConnector as RustlsConnector,
1111
};
1212

13+
use super::io::BoxedIo;
14+
use crate::transport::{
15+
server::{Connected, TlsStream},
16+
Certificate, Identity,
17+
};
18+
1319
/// h2 alpn in plain format for rustls.
14-
const ALPN_H2: &str = "h2";
20+
const ALPN_H2: &[u8] = b"h2";
1521

1622
#[derive(Debug)]
1723
enum TlsError {
@@ -23,70 +29,58 @@ enum TlsError {
2329
#[derive(Clone)]
2430
pub(crate) struct TlsConnector {
2531
config: Arc<ClientConfig>,
26-
domain: Arc<ServerName>,
32+
domain: Arc<ServerName<'static>>,
2733
}
2834

2935
impl TlsConnector {
3036
pub(crate) fn new(
3137
ca_cert: Option<Certificate>,
3238
identity: Option<Identity>,
33-
domain: String,
39+
domain: &str,
3440
) -> Result<Self, crate::Error> {
35-
let builder = ClientConfig::builder().with_safe_defaults();
41+
let builder = ClientConfig::builder();
3642
let mut roots = RootCertStore::empty();
3743

3844
#[cfg(feature = "tls-roots")]
39-
roots.add_parsable_certificates(&rustls_native_certs::load_native_certs()?);
45+
roots.add_parsable_certificates(rustls_native_certs::load_native_certs()?);
4046

4147
#[cfg(feature = "tls-webpki-roots")]
42-
roots.add_trust_anchors(webpki_roots::TLS_SERVER_ROOTS.iter().map(|ta| {
43-
tokio_rustls::rustls::OwnedTrustAnchor::from_subject_spki_name_constraints(
44-
ta.subject,
45-
ta.spki,
46-
ta.name_constraints,
47-
)
48-
}));
48+
roots.extend(webpki_roots::TLS_SERVER_ROOTS.iter().cloned());
4949

5050
if let Some(cert) = ca_cert {
51-
rustls_keys::add_certs_from_pem(std::io::Cursor::new(cert.as_ref()), &mut roots)?;
51+
add_certs_from_pem(&mut Cursor::new(cert), &mut roots)?;
5252
}
5353

5454
let builder = builder.with_root_certificates(roots);
5555
let mut config = match identity {
5656
Some(identity) => {
57-
let (client_cert, client_key) = rustls_keys::load_identity(identity)?;
57+
let (client_cert, client_key) = load_identity(identity)?;
5858
builder.with_client_auth_cert(client_cert, client_key)?
5959
}
6060
None => builder.with_no_client_auth(),
6161
};
6262

63-
config.alpn_protocols.push(ALPN_H2.as_bytes().to_vec());
63+
config.alpn_protocols.push(ALPN_H2.into());
6464
Ok(Self {
6565
config: Arc::new(config),
66-
domain: Arc::new(domain.as_str().try_into()?),
66+
domain: Arc::new(ServerName::try_from(domain)?.to_owned()),
6767
})
6868
}
6969

7070
pub(crate) async fn connect<I>(&self, io: I) -> Result<BoxedIo, crate::Error>
7171
where
7272
I: AsyncRead + AsyncWrite + Send + Unpin + 'static,
7373
{
74-
let tls_io = {
75-
let io = RustlsConnector::from(self.config.clone())
76-
.connect(self.domain.as_ref().to_owned(), io)
77-
.await?;
74+
let io = RustlsConnector::from(self.config.clone())
75+
.connect(self.domain.as_ref().to_owned(), io)
76+
.await?;
7877

79-
let (_, session) = io.get_ref();
80-
81-
match session.alpn_protocol() {
82-
Some(b) if b == b"h2" => (),
83-
_ => return Err(TlsError::H2NotNegotiated.into()),
84-
};
85-
86-
BoxedIo::new(io)
87-
};
78+
let (_, session) = io.get_ref();
79+
if session.alpn_protocol() != Some(ALPN_H2) {
80+
return Err(TlsError::H2NotNegotiated)?;
81+
}
8882

89-
Ok(tls_io)
83+
Ok(BoxedIo::new(io))
9084
}
9185
}
9286

@@ -107,30 +101,27 @@ impl TlsAcceptor {
107101
client_ca_root: Option<Certificate>,
108102
client_auth_optional: bool,
109103
) -> Result<Self, crate::Error> {
110-
let builder = ServerConfig::builder().with_safe_defaults();
104+
let builder = ServerConfig::builder();
111105

112-
let builder = match (client_ca_root, client_auth_optional) {
113-
(None, _) => builder.with_no_client_auth(),
114-
(Some(cert), true) => {
115-
use tokio_rustls::rustls::server::AllowAnyAnonymousOrAuthenticatedClient;
116-
let mut roots = RootCertStore::empty();
117-
rustls_keys::add_certs_from_pem(std::io::Cursor::new(cert.as_ref()), &mut roots)?;
118-
builder.with_client_cert_verifier(
119-
AllowAnyAnonymousOrAuthenticatedClient::new(roots).boxed(),
120-
)
121-
}
122-
(Some(cert), false) => {
123-
use tokio_rustls::rustls::server::AllowAnyAuthenticatedClient;
106+
let builder = match client_ca_root {
107+
None => builder.with_no_client_auth(),
108+
Some(cert) => {
124109
let mut roots = RootCertStore::empty();
125-
rustls_keys::add_certs_from_pem(std::io::Cursor::new(cert.as_ref()), &mut roots)?;
126-
builder.with_client_cert_verifier(AllowAnyAuthenticatedClient::new(roots).boxed())
110+
add_certs_from_pem(&mut Cursor::new(cert), &mut roots)?;
111+
let verifier = if client_auth_optional {
112+
WebPkiClientVerifier::builder(roots.into()).allow_unauthenticated()
113+
} else {
114+
WebPkiClientVerifier::builder(roots.into())
115+
}
116+
.build()?;
117+
builder.with_client_cert_verifier(verifier)
127118
}
128119
};
129120

130-
let (cert, key) = rustls_keys::load_identity(identity)?;
121+
let (cert, key) = load_identity(identity)?;
131122
let mut config = builder.with_single_cert(cert, key)?;
132123

133-
config.alpn_protocols.push(ALPN_H2.as_bytes().to_vec());
124+
config.alpn_protocols.push(ALPN_H2.into());
134125
Ok(Self {
135126
inner: Arc::new(config),
136127
})
@@ -166,137 +157,29 @@ impl fmt::Display for TlsError {
166157

167158
impl std::error::Error for TlsError {}
168159

169-
mod rustls_keys {
170-
use std::io::Cursor;
171-
172-
use tokio_rustls::rustls::{Certificate, PrivateKey, RootCertStore};
173-
174-
use crate::transport::service::tls::TlsError;
175-
use crate::transport::Identity;
176-
177-
pub(super) fn load_rustls_private_key(
178-
mut cursor: std::io::Cursor<&[u8]>,
179-
) -> Result<PrivateKey, crate::Error> {
180-
while let Ok(Some(item)) = rustls_pemfile::read_one(&mut cursor) {
181-
match item {
182-
rustls_pemfile::Item::RSAKey(key)
183-
| rustls_pemfile::Item::PKCS8Key(key)
184-
| rustls_pemfile::Item::ECKey(key) => return Ok(PrivateKey(key)),
185-
_ => continue,
186-
}
187-
}
188-
189-
// Otherwise we have a Private Key parsing problem
190-
Err(Box::new(TlsError::PrivateKeyParseError))
191-
}
192-
193-
pub(crate) fn load_identity(
194-
identity: Identity,
195-
) -> Result<(Vec<Certificate>, PrivateKey), crate::Error> {
196-
let cert = {
197-
let mut cert = std::io::Cursor::new(identity.cert.as_ref());
198-
match rustls_pemfile::certs(&mut cert) {
199-
Ok(certs) => certs.into_iter().map(Certificate).collect(),
200-
Err(_) => return Err(Box::new(TlsError::CertificateParseError)),
201-
}
202-
};
203-
204-
let key = {
205-
let key = std::io::Cursor::new(identity.key.as_ref());
206-
match load_rustls_private_key(key) {
207-
Ok(key) => key,
208-
Err(e) => {
209-
return Err(e);
210-
}
211-
}
212-
};
160+
fn load_identity(
161+
identity: Identity,
162+
) -> Result<(Vec<CertificateDer<'static>>, PrivateKeyDer<'static>), TlsError> {
163+
let cert = rustls_pemfile::certs(&mut Cursor::new(identity.cert))
164+
.collect::<Result<Vec<_>, _>>()
165+
.map_err(|_| TlsError::CertificateParseError)?;
213166

214-
Ok((cert, key))
215-
}
167+
let Ok(Some(key)) = rustls_pemfile::private_key(&mut Cursor::new(identity.key)) else {
168+
return Err(TlsError::PrivateKeyParseError);
169+
};
216170

217-
pub(crate) fn add_certs_from_pem(
218-
mut certs: Cursor<&[u8]>,
219-
roots: &mut RootCertStore,
220-
) -> Result<(), crate::Error> {
221-
let (_, ignored) = roots.add_parsable_certificates(&rustls_pemfile::certs(&mut certs)?);
222-
match ignored == 0 {
223-
true => Ok(()),
224-
false => Err(Box::new(TlsError::CertificateParseError)),
225-
}
226-
}
171+
Ok((cert, key))
227172
}
228173

229-
#[cfg(test)]
230-
mod tests {
231-
use std::io::Cursor;
232-
233-
// generated by: openssl ecparam -keygen -name 'prime256v1'
234-
const SIMPLE_EC_KEY: &str = r#"-----BEGIN EC PARAMETERS-----
235-
BggqhkjOPQMBBw==
236-
-----END EC PARAMETERS-----
237-
-----BEGIN EC PRIVATE KEY-----
238-
MHcCAQEEICIDyh40kMVWGDAYr1gXnMfeMeO3zXYigOaWrg5SNB+zoAoGCCqGSM49
239-
AwEHoUQDQgAEacJyVg299dkPTzUaMbOmACUfF67yp+ZrDhXVjn/5WxBAgjcmFBHg
240-
Tw8dfwpMzaJPXX5lWYzP276fcmbRO25CXw==
241-
-----END EC PRIVATE KEY-----"#;
242-
243-
// generated by: openssl genpkey -algorithm rsa
244-
const SIMPLE_PKCS8_KEY: &str = r#"-----BEGIN PRIVATE KEY-----
245-
MIICdwIBADANBgkqhkiG9w0BAQEFAASCAmEwggJdAgEAAoGBAKHkX1YIvqOIAllD
246-
5fKcIxu2kYjIxxAAQrOBRTloGZUKdPFQY1RANB4t/LEaI5/NJ6NK4915pTn35QAQ
247-
zHJl+X4rNFMgVt+o/nY40PgrQxyyv5A0/URp+iS8Yn3GKt3q6p4zguiO9uNXhiiD
248-
b+VKIFRDm4bHR2yM7pNJ0kMdoattAgMBAAECgYAMpw6UaMaNfVnBpD7agT11MwWY
249-
zShRpdOQt++zFuG49kJBgejhcssf+LQhG0vhd2U7q+S3MISrTSaGpMl1v2aKR/nV
250-
G7X4Bb6X8vrVSMrfze2loT0aNri9jKDZkD/muy6+9JkhRa03NOdhDdseokmcqF3L
251-
xsU4BUOOFYb23ycoeQJBANOGxbZu/3BqsPJMQmXWo1CXuaviZ83lTczPtrz9mJVl
252-
Zs/KmGnJ8I2Azu/dlYXsHRvbIbqA93l1M3GnsWl5IxsCQQDD7hKvOY6qzUNyj+R4
253-
vul/3xaqjiTj59f3jN7Fh6+9AY+WfvEkWfyUUAXY74z43wBgtORfMXnZnjFO96tJ
254-
sswXAkBDYDtb19E/cox4MTg5DfwpMJrwmAYufCqi4Uq4uiI++/SanVKc57jaqbvA
255-
hZkZ9lJzTAJbULcDFgTT3/FPwkkfAkEAqbSDMIzdGuox2n/x9/f8jcpweogmQdUl
256-
xgCZUGSnfkFk2ojXW5Ip6Viqx+0toL6fOCRWjnFvRmPz958kGPCqPwJBAID4y7XV
257-
peOO6Yadu0YbSmFNluRebia6410p5jR21LhG1ty2h22xVhlBWjOC+TyDuKwhmiYT
258-
ed50S3LR1PWt4zE=
259-
-----END PRIVATE KEY-----"#;
260-
261-
// generated by: openssl genrsa
262-
const SIMPLE_RSA_KEY: &str = r#"-----BEGIN RSA PRIVATE KEY-----
263-
MIIEogIBAAKCAQEAoEILGds1/RGBHT7jM4R+EL24sQ6Bsn14GgTHc7WoZ7lainEH
264-
H/n+DtHCYUXYyJnN5AMIi3pkigCP1hdXXBQga3zs3lXoi/mAMkT6vjuqQ7Xg5/95
265-
ABx5Ztyy25mZNaXm77glyAzSscKHxWYooXVJYG4C3SGuBJJ1zVjxen6Rkzse5Lpr
266-
yZOUUeqeV3M6KbJ/dkR37HFQVwmlctQukFnb4kozFBQDDnkXi9jT/PH00g6JpW3z
267-
YMzdMq2RMadJ0dzYv62OtdtqmQpVz0dRu/yODV4DkhrWwgPRj2uY4DnYthzILESB
268-
x41gxHj+jqo6NW+C+0fr6uh2CXtD0p+ZVANtBQIDAQABAoIBAE7IaOCrLV1dr5WL
269-
BvKancbpHdSdBxGSMOrJkqvFkCZ9ro8EhbYolcb/Q4nCZpInWlpPS3IWFzroj811
270-
6BJyKoXtAh1DKnE1lNohowrGFiv3S7uBkiCF3wC8Wokud20yQ9dxNdGkzCdrNIfM
271-
cwj8ubfYHTxMhFnnDlaG9R98/V/dFy0FLxL37eMP/heMbcwKKm9P/G2FqvuCn8a4
272-
FoPbAfvaR64IGCybjoiTjUD7xMHIV4Gr5K07br2TzG2zVlFTacoqXyGBbVVy+ibt
273-
QMh0sn+rMkAy+cFse+yCYZeAFa4FzwGz43sdFviU7uvLG7yXpvZ+uDACFzxlxUVg
274-
v57r1cECgYEA1MMJEe6IunDUyuzRaFNTfQX16QcAv/xLN/1TtVB3HUX5p2bIZKDr
275-
XEl0NCVOrCoz5RsYqbtGmp8B4Yxl3DeX+WeWeD9/f2ZTVGWyBx1N6dZ5hRsyfzG/
276-
xVBUqYxkChjXQ20cNtf8u7JKdnVjOJen9M92nXhFRTwgH83Id4gPp70CgYEAwNN8
277-
lvVJnd05ekyf1qIKOSyKiSGnGa5288PpqsjYMZisXy12y4n8cK2pX5Z5PICHeJVu
278-
K99WdTtO7Q4ghCXRB1jR5pTd4/3/3089SQyDnWz9jlA3pGWcSLDTB1dBJXpMQ6yG
279-
cR2dX5hPDNIdKsc+9Bl/OF5PScvGVUYv4SLF6ukCgYAVhh2WyNDgO6XrWYXdzgA2
280-
N7Im/uReh8F8So57W0aRmZCmFMnVFEp7LZsp41RQKnzRgqo+EYoU/l0MWk27t4wS
281-
WR5pz9KwKsPnV9poydgl/eKRSq0THQ9PgM7v0BoWw2iTk6g1DCivPFw4G6wL/5uo
282-
MozHZXFsjaaaUREktokO6QKBgC3Dg7RILtqaoIOYH+9OseJz4cU+CWyc7XpZKuHv
283-
nO/YbkCAh8syyojrjmEzUz66umwx+t3KubhFBSxZx/nVB9EYkWiKOEdeBxY2tjLa
284-
F3qLXXojK7GGtBrEbLE3UizU47jD/3xlLO59NXWzgFygwR4p1vnH2EWJaV7fs4lZ
285-
OWPRAoGAL0nX0vZ0N9qPETiQan1uHjKYuuFiSP+cwRXVSUYIQM9qDRlKG9zjugwO
286-
az+B6uiR4TrgbwG+faCQwcGk9B8QbcoIb8IigwrWe3XpVaEtcsqFORX0r+tJNDoY
287-
I0O2DOQVPKSK2N5AZzXY4IkybWTV4Yxc7rdXEO3dOOpHGKbpwFQ=
288-
-----END RSA PRIVATE KEY-----"#;
289-
290-
#[test]
291-
fn test_parse_ec_key() {
292-
for (n, key) in [SIMPLE_EC_KEY, SIMPLE_PKCS8_KEY, SIMPLE_RSA_KEY]
293-
.iter()
294-
.enumerate()
295-
{
296-
let c = Cursor::new(key.as_bytes());
297-
let key = super::rustls_keys::load_rustls_private_key(c);
298-
299-
assert!(key.is_ok(), "at the {}-th case", n);
300-
}
174+
fn add_certs_from_pem(
175+
mut certs: &mut dyn std::io::BufRead,
176+
roots: &mut RootCertStore,
177+
) -> Result<(), crate::Error> {
178+
for cert in rustls_pemfile::certs(&mut certs).collect::<Result<Vec<_>, _>>()? {
179+
roots
180+
.add(cert)
181+
.map_err(|_| TlsError::CertificateParseError)?;
301182
}
183+
184+
Ok(())
302185
}

0 commit comments

Comments
 (0)