1#![warn(rust_2018_idioms, clippy::all, missing_docs)]
8
9use std::convert::Infallible;
10use std::future::Future;
11use std::io;
12use std::pin::Pin;
13use std::sync::Arc;
14use std::task::{Context, Poll};
15
16use rustls::pki_types::ServerName;
17use tokio::io::{AsyncRead, AsyncWrite, BufReader, ReadBuf};
18use tokio_postgres::tls;
19#[cfg(feature = "runtime")]
20use tokio_postgres::tls::MakeTlsConnect;
21use tokio_postgres::tls::{ChannelBinding, TlsConnect};
22
23#[cfg(feature = "runtime")]
27#[derive(Clone)]
28pub struct MakeTlsConnector(Arc<rustls::ClientConfig>);
29
30#[cfg(feature = "runtime")]
31impl MakeTlsConnector {
32 pub fn new(config: Arc<rustls::ClientConfig>) -> MakeTlsConnector {
34 MakeTlsConnector(config)
35 }
36}
37
38#[cfg(feature = "runtime")]
39impl<S> MakeTlsConnect<S> for MakeTlsConnector
40where
41 S: AsyncRead + AsyncWrite + Unpin + 'static + Send,
42{
43 type Stream = TlsStream<S>;
44 type TlsConnect = TlsConnector;
45 type Error = Infallible;
46
47 fn make_tls_connect(&mut self, domain: &str) -> Result<TlsConnector, Self::Error> {
48 Ok(TlsConnector::new(self.0.clone(), domain))
49 }
50}
51
52pub struct TlsConnector {
54 connector: tokio_rustls::TlsConnector,
55 domain: String,
59}
60
61impl TlsConnector {
62 pub fn new(config: Arc<rustls::ClientConfig>, domain: &str) -> TlsConnector {
66 TlsConnector {
67 connector: tokio_rustls::TlsConnector::from(config),
68 domain: domain.to_string(),
69 }
70 }
71}
72
73impl<S> TlsConnect<S> for TlsConnector
74where
75 S: AsyncRead + AsyncWrite + Unpin + 'static + Send,
76{
77 type Stream = TlsStream<S>;
78 type Error = io::Error;
79 #[allow(clippy::type_complexity)]
80 type Future = Pin<Box<dyn Future<Output = Result<TlsStream<S>, io::Error>> + Send>>;
81
82 fn connect(self, stream: S) -> Self::Future {
83 let stream = BufReader::with_capacity(8192, stream);
84 Box::pin(async move {
85 let domain = server_name(&self.domain)?;
86 let stream = self.connector.connect(domain, stream).await?;
87 Ok(TlsStream(stream))
88 })
89 }
90}
91
92fn server_name(domain: &str) -> io::Result<ServerName<'static>> {
94 if domain.is_empty() {
95 return Err(io::Error::new(
96 io::ErrorKind::InvalidInput,
97 "no host name to verify the server's TLS certificate against",
98 ));
99 }
100 match ServerName::try_from(domain) {
101 Ok(name) => Ok(name.to_owned()),
102 Err(_) => Err(io::Error::new(
103 io::ErrorKind::InvalidInput,
104 format!("{:?} is not a valid host name for TLS", domain),
105 )),
106 }
107}
108
109pub struct TlsStream<S>(tokio_rustls::client::TlsStream<BufReader<S>>);
111
112impl<S> AsyncRead for TlsStream<S>
113where
114 S: AsyncRead + AsyncWrite + Unpin,
115{
116 fn poll_read(
117 mut self: Pin<&mut Self>,
118 cx: &mut Context<'_>,
119 buf: &mut ReadBuf<'_>,
120 ) -> Poll<io::Result<()>> {
121 Pin::new(&mut self.0).poll_read(cx, buf)
122 }
123}
124
125impl<S> AsyncWrite for TlsStream<S>
126where
127 S: AsyncRead + AsyncWrite + Unpin,
128{
129 fn poll_write(
130 mut self: Pin<&mut Self>,
131 cx: &mut Context<'_>,
132 buf: &[u8],
133 ) -> Poll<io::Result<usize>> {
134 Pin::new(&mut self.0).poll_write(cx, buf)
135 }
136
137 fn poll_flush(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<io::Result<()>> {
138 Pin::new(&mut self.0).poll_flush(cx)
139 }
140
141 fn poll_shutdown(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<io::Result<()>> {
142 Pin::new(&mut self.0).poll_shutdown(cx)
143 }
144}
145
146impl<S> tls::TlsStream for TlsStream<S>
147where
148 S: AsyncRead + AsyncWrite + Unpin,
149{
150 fn channel_binding(&self) -> ChannelBinding {
151 let (_, session) = self.0.get_ref();
152 match session.peer_certificates().and_then(|certs| certs.first()) {
153 Some(cert) => match tls_server_end_point(cert) {
154 Some(hash) => ChannelBinding::tls_server_end_point(hash),
155 None => ChannelBinding::none(),
156 },
157 None => ChannelBinding::none(),
158 }
159 }
160}
161
162fn tls_server_end_point(cert: &[u8]) -> Option<Vec<u8>> {
170 let (oid, parameters) = signature_algorithm(cert)?;
171 let hash = match oid {
172 RSA_PSS => pss_hash(parameters)?,
173 oid => oid,
174 };
175 let algorithm = match hash {
176 RSA_MD5 | RSA_SHA1 | ECDSA_SHA1 | SHA1 => &ring::digest::SHA256,
179 RSA_SHA256 | ECDSA_SHA256 | SHA256 => &ring::digest::SHA256,
180 RSA_SHA384 | ECDSA_SHA384 | SHA384 => &ring::digest::SHA384,
181 RSA_SHA512 | ECDSA_SHA512 | SHA512 => &ring::digest::SHA512,
182 _ => return None,
183 };
184 Some(ring::digest::digest(algorithm, cert).as_ref().to_vec())
185}
186
187const RSA_MD5: &[u8] = &[0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x04];
189const RSA_SHA1: &[u8] = &[0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x05];
190const RSA_PSS: &[u8] = &[0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x0a];
191const RSA_SHA256: &[u8] = &[0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x0b];
192const RSA_SHA384: &[u8] = &[0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x0c];
193const RSA_SHA512: &[u8] = &[0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x0d];
194const ECDSA_SHA1: &[u8] = &[0x2a, 0x86, 0x48, 0xce, 0x3d, 0x04, 0x01];
195const ECDSA_SHA256: &[u8] = &[0x2a, 0x86, 0x48, 0xce, 0x3d, 0x04, 0x03, 0x02];
196const ECDSA_SHA384: &[u8] = &[0x2a, 0x86, 0x48, 0xce, 0x3d, 0x04, 0x03, 0x03];
197const ECDSA_SHA512: &[u8] = &[0x2a, 0x86, 0x48, 0xce, 0x3d, 0x04, 0x03, 0x04];
198
199const SHA1: &[u8] = &[0x2b, 0x0e, 0x03, 0x02, 0x1a];
201const SHA256: &[u8] = &[0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x01];
202const SHA384: &[u8] = &[0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x02];
203const SHA512: &[u8] = &[0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x03];
204
205const SEQUENCE: u8 = 0x30;
206const OID: u8 = 0x06;
207
208fn signature_algorithm(cert: &[u8]) -> Option<(&[u8], &[u8])> {
214 let (certificate, _) = der_element(cert, SEQUENCE)?;
215 let (_tbs, rest) = der_element(certificate, SEQUENCE)?;
216 let (algorithm_identifier, _) = der_element(rest, SEQUENCE)?;
217 der_element(algorithm_identifier, OID)
218}
219
220fn pss_hash(parameters: &[u8]) -> Option<&[u8]> {
226 const HASH_ALGORITHM: u8 = 0xa0; let (params, _) = der_element(parameters, SEQUENCE)?;
228 if params.first() != Some(&HASH_ALGORITHM) {
229 return Some(SHA1);
230 }
231 let (hash_algorithm, _) = der_element(params, HASH_ALGORITHM)?;
232 let (algorithm_identifier, _) = der_element(hash_algorithm, SEQUENCE)?;
233 let (oid, _) = der_element(algorithm_identifier, OID)?;
234 Some(oid)
235}
236
237fn der_element(input: &[u8], tag: u8) -> Option<(&[u8], &[u8])> {
240 let (&actual, input) = input.split_first()?;
241 if actual != tag {
242 return None;
243 }
244 let (&first, mut input) = input.split_first()?;
245 let len = if first < 0x80 {
246 usize::from(first)
247 } else {
248 let count = usize::from(first & 0x7f);
250 if count == 0 || count > std::mem::size_of::<usize>() || input.len() < count {
251 return None;
252 }
253 let (bytes, rest) = input.split_at(count);
254 input = rest;
255 bytes
256 .iter()
257 .fold(0usize, |len, &b| (len << 8) | usize::from(b))
258 };
259 if input.len() < len {
260 return None;
261 }
262 Some(input.split_at(len))
263}
264
265#[cfg(test)]
266mod tests {
267 use super::*;
268
269 fn cert(alg: &'static rcgen::SignatureAlgorithm) -> Vec<u8> {
270 let key = rcgen::KeyPair::generate_for(alg).unwrap();
271 let params = rcgen::CertificateParams::new(vec!["localhost".to_string()]).unwrap();
272 params.self_signed(&key).unwrap().der().to_vec()
273 }
274
275 #[test]
276 fn hashes_with_the_signature_algorithm_hash() {
277 let p256 = cert(&rcgen::PKCS_ECDSA_P256_SHA256);
278 assert_eq!(signature_algorithm(&p256).unwrap().0, ECDSA_SHA256);
279 assert_eq!(
280 tls_server_end_point(&p256).unwrap(),
281 ring::digest::digest(&ring::digest::SHA256, &p256).as_ref()
282 );
283
284 let p384 = cert(&rcgen::PKCS_ECDSA_P384_SHA384);
285 assert_eq!(signature_algorithm(&p384).unwrap().0, ECDSA_SHA384);
286 assert_eq!(
287 tls_server_end_point(&p384).unwrap(),
288 ring::digest::digest(&ring::digest::SHA384, &p384).as_ref()
289 );
290 }
291
292 const RSA_PSS_SHA384_CERT: &[u8] = include_bytes!("../testdata/rsa_pss_sha384.der");
295
296 #[test]
297 fn hashes_rsa_pss_with_the_hash_its_parameters_name() {
298 let (oid, parameters) = signature_algorithm(RSA_PSS_SHA384_CERT).unwrap();
299 assert_eq!(oid, RSA_PSS);
300 assert_eq!(pss_hash(parameters), Some(SHA384));
301 assert_eq!(
302 tls_server_end_point(RSA_PSS_SHA384_CERT).unwrap(),
303 ring::digest::digest(&ring::digest::SHA384, RSA_PSS_SHA384_CERT).as_ref()
304 );
305 }
306
307 fn der(tag: u8, contents: &[u8]) -> Vec<u8> {
309 assert!(contents.len() < 0x80);
310 [&[tag, contents.len() as u8][..], contents].concat()
311 }
312
313 fn pss_cert(parameters: &[u8]) -> Vec<u8> {
316 let algorithm = der(SEQUENCE, &[der(OID, RSA_PSS), parameters.to_vec()].concat());
317 let signature = der(0x03, &[0x00]);
318 der(
319 SEQUENCE,
320 &[der(SEQUENCE, &[]), algorithm, signature].concat(),
321 )
322 }
323
324 fn pss_parameters(hash: &[u8]) -> Vec<u8> {
327 let hash_algorithm = der(SEQUENCE, &[der(OID, hash), der(0x05, &[])].concat());
328 der(SEQUENCE, &der(0xa0, &hash_algorithm))
329 }
330
331 #[test]
332 fn hashes_rsa_pss_by_its_parameters() {
333 for (hash, algorithm) in [
334 (SHA1, &ring::digest::SHA256),
335 (SHA256, &ring::digest::SHA256),
336 (SHA384, &ring::digest::SHA384),
337 (SHA512, &ring::digest::SHA512),
338 ] {
339 let cert = pss_cert(&pss_parameters(hash));
340 assert_eq!(
341 tls_server_end_point(&cert).unwrap(),
342 ring::digest::digest(algorithm, &cert).as_ref()
343 );
344 }
345
346 let cert = pss_cert(&der(SEQUENCE, &[]));
348 assert_eq!(
349 tls_server_end_point(&cert).unwrap(),
350 ring::digest::digest(&ring::digest::SHA256, &cert).as_ref()
351 );
352 }
353
354 #[test]
355 fn has_no_binding_for_rsa_pss_without_a_known_hash() {
356 let sha224 = [0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x04];
358 assert_eq!(
359 tls_server_end_point(&pss_cert(&pss_parameters(&sha224))),
360 None
361 );
362 assert_eq!(tls_server_end_point(&pss_cert(&[])), None);
364 assert_eq!(
366 tls_server_end_point(&pss_cert(&der(SEQUENCE, &[0xa0, 0x05]))),
367 None
368 );
369 }
370
371 #[test]
372 fn has_no_binding_for_ed25519() {
373 let ed25519 = cert(&rcgen::PKCS_ED25519);
374 assert!(signature_algorithm(&ed25519).is_some());
375 assert_eq!(tls_server_end_point(&ed25519), None);
376 }
377
378 fn connector(domain: &str) -> TlsConnector {
379 let provider = Arc::new(rustls::crypto::ring::default_provider());
380 let config = rustls::ClientConfig::builder_with_provider(provider)
381 .with_safe_default_protocol_versions()
382 .unwrap()
383 .with_root_certificates(rustls::RootCertStore::empty())
384 .with_no_client_auth();
385 let mut make = MakeTlsConnector::new(Arc::new(config));
386 MakeTlsConnect::<tokio::io::DuplexStream>::make_tls_connect(&mut make, domain).unwrap()
387 }
388
389 async fn handshake_error(domain: &str) -> String {
390 let (client, _server) = tokio::io::duplex(1024);
391 match connector(domain).connect(client).await {
392 Ok(_) => panic!("expected the handshake to fail"),
393 Err(err) => {
394 assert_eq!(err.kind(), io::ErrorKind::InvalidInput);
395 err.to_string()
396 }
397 }
398 }
399
400 #[tokio::test]
403 async fn an_empty_domain_fails_only_the_handshake() {
404 let err = handshake_error("").await;
405 assert!(err.contains("no host name"), "{err}");
406 }
407
408 #[tokio::test]
409 async fn an_invalid_domain_fails_only_the_handshake() {
410 let err = handshake_error("not a host").await;
411 assert!(
412 err.contains("\"not a host\" is not a valid host name"),
413 "{err}"
414 );
415 }
416
417 #[test]
418 fn rejects_malformed_certificates() {
419 let p256 = cert(&rcgen::PKCS_ECDSA_P256_SHA256);
420 for len in [0, 1, 2, 10, p256.len() / 2] {
421 assert_eq!(tls_server_end_point(&p256[..len]), None);
422 }
423 assert_eq!(
424 tls_server_end_point(&[0x30, 0x84, 0xff, 0xff, 0xff, 0xff]),
425 None
426 );
427 }
428}