tor_rtcompat/impls/rustls/
rustls_server.rs1use async_trait::async_trait;
4use futures::{AsyncRead, AsyncWrite};
5use pin_project::pin_project;
6use std::{
7 borrow::Cow,
8 io::{Error as IoError, Result as IoResult},
9 marker::PhantomData,
10 pin::Pin,
11 sync::Arc,
12 task::{Context, Poll},
13};
14use tracing::instrument;
15
16use crate::{CertifiedConn, StreamOps, tls::TlsAcceptorSettings, tls::TlsConnector};
17use futures_rustls::rustls::ServerConfig as RustlsServerConfig;
18
19#[pin_project]
23pub struct RustlsServerStream<S> {
24 #[pin]
29 stream: futures_rustls::server::TlsStream<S>,
30
31 cert_der: Arc<[u8]>,
35}
36
37impl<S: AsyncRead + AsyncWrite + Unpin> AsyncRead for RustlsServerStream<S> {
38 fn poll_read(
39 self: Pin<&mut Self>,
40 cx: &mut Context<'_>,
41 buf: &mut [u8],
42 ) -> Poll<IoResult<usize>> {
43 self.project().stream.poll_read(cx, buf)
44 }
45}
46
47impl<S: AsyncRead + AsyncWrite + Unpin> AsyncWrite for RustlsServerStream<S> {
48 fn poll_write(self: Pin<&mut Self>, cx: &mut Context<'_>, buf: &[u8]) -> Poll<IoResult<usize>> {
49 self.project().stream.poll_write(cx, buf)
50 }
51
52 fn poll_flush(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<IoResult<()>> {
53 self.project().stream.poll_flush(cx)
54 }
55
56 fn poll_close(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<IoResult<()>> {
57 self.project().stream.poll_close(cx)
58 }
59}
60
61impl<S: StreamOps> StreamOps for RustlsServerStream<S> {
62 fn set_tcp_notsent_lowat(&self, notsent_lowat: u32) -> IoResult<()> {
63 self.stream.get_ref().0.set_tcp_notsent_lowat(notsent_lowat)
64 }
65
66 fn new_handle(&self) -> Box<dyn StreamOps + Send + Unpin> {
67 self.stream.get_ref().0.new_handle()
68 }
69}
70
71impl<S: AsyncRead + AsyncWrite + Unpin> CertifiedConn for RustlsServerStream<S> {
72 fn peer_certificate(&self) -> IoResult<Option<Cow<'_, [u8]>>> {
73 let (_, session) = self.stream.get_ref();
74 Ok(session
75 .peer_certificates()
76 .and_then(|certs| certs.first().map(|c| Cow::from(c.as_ref()))))
77 }
78
79 fn export_keying_material(
80 &self,
81 len: usize,
82 label: &[u8],
83 context: Option<&[u8]>,
84 ) -> IoResult<Vec<u8>> {
85 let (_, session) = self.stream.get_ref();
86 session
87 .export_keying_material(vec![0_u8; len], label, context)
88 .map_err(|e| IoError::new(std::io::ErrorKind::InvalidData, e))
89 }
90
91 fn own_certificate(&self) -> IoResult<Option<Cow<'_, [u8]>>> {
92 Ok(Some(Cow::from(self.cert_der.as_ref())))
93 }
94}
95
96#[derive(Clone, derive_more::Debug)]
100pub struct RustlsAcceptor<S> {
101 #[debug(skip)]
103 acceptor: futures_rustls::TlsAcceptor,
104 cert_der: Arc<[u8]>,
106 _phantom: PhantomData<fn(S) -> S>,
108}
109
110#[async_trait]
111impl<S> TlsConnector<S> for RustlsAcceptor<S>
112where
113 S: AsyncRead + AsyncWrite + StreamOps + Unpin + Send + 'static,
114{
115 type Conn = RustlsServerStream<S>;
116
117 #[instrument(skip_all, level = "trace")]
118 async fn negotiate_unvalidated(&self, stream: S, sni_hostname: &str) -> IoResult<Self::Conn> {
119 let _ignore = sni_hostname;
120 let stream = self.acceptor.accept(stream).await?;
121 Ok(RustlsServerStream {
122 stream,
123 cert_der: Arc::clone(&self.cert_der),
124 })
125 }
126}
127
128impl<S> RustlsAcceptor<S> {
129 pub(crate) fn new(settings: &TlsAcceptorSettings) -> IoResult<Self> {
131 let cert_der = settings.cert_der().into();
132
133 let cfg: RustlsServerConfig = rustls_server_config(settings)?;
134 let acceptor = futures_rustls::TlsAcceptor::from(Arc::new(cfg));
135 Ok(Self {
136 acceptor,
137 cert_der,
138 _phantom: PhantomData,
139 })
140 }
141}
142
143fn rustls_server_config(settings: &TlsAcceptorSettings) -> IoResult<RustlsServerConfig> {
147 use futures_rustls::rustls::pki_types as pki;
148 use futures_rustls::rustls::version::{TLS12, TLS13};
149
150 let cert_chain = settings
152 .identity
153 .certificates_der()
154 .into_iter()
155 .map(|c| pki::CertificateDer::from_slice(c).into_owned())
156 .collect();
157 let key_der = settings
158 .identity
159 .private_key_pkcs8_der()
160 .map_err(IoError::other)?;
161 let key_der =
162 pki::PrivateKeyDer::Pkcs8(pki::PrivatePkcs8KeyDer::from(key_der.as_ref())).clone_key();
163
164 let mut config = RustlsServerConfig::builder_with_protocol_versions(&[&TLS12, &TLS13]) .with_no_client_auth() .with_single_cert(cert_chain, key_der)
168 .map_err(|e| IoError::new(std::io::ErrorKind::InvalidData, e))?;
169
170 config.send_tls13_tickets = 0;
178
179 Ok(config)
182}