s2n_quic/provider/
tls.rs

1// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
2// SPDX-License-Identifier: Apache-2.0
3
4//! Provides TLS support for an endpoint
5
6use cfg_if::cfg_if;
7use s2n_quic_core::crypto;
8
9pub use s2n_quic_core::crypto::tls::ConnectionInfo;
10
11pub trait Provider {
12    type Server: 'static + crypto::tls::Endpoint;
13    type Client: 'static + crypto::tls::Endpoint;
14    type Error: 'static + core::fmt::Display + Send + Sync;
15
16    /// Creates a server endpoint for the given provider
17    fn start_server(self) -> Result<Self::Server, Self::Error>;
18
19    /// Creates a client endpoint for the given provider
20    fn start_client(self) -> Result<Self::Client, Self::Error>;
21}
22
23impl_provider_utils!();
24
25cfg_if! {
26    if #[cfg(feature = "provider-tls-default")] {
27        #[cfg_attr(docsrs, doc(cfg(feature = "provider-tls-default")))]
28        pub mod default {
29            //! Provides the recommended implementation of TLS using platform detection
30            pub use super::default_tls::*;
31        }
32    } else if #[cfg(feature = "provider-tls-s2n")] {
33        pub use s2n_tls as default;
34    } else if #[cfg(feature = "provider-tls-rustls")] {
35        pub use rustls as default;
36    } else {
37        pub mod default {
38            //! Provides the recommended implementation of TLS using platform detection
39            pub use super::default_tls::*;
40        }
41    }
42}
43
44#[derive(Debug, Default)]
45pub struct Default;
46
47impl Provider for Default {
48    type Server = default::Server;
49    type Client = default::Client;
50    type Error = core::convert::Infallible;
51
52    fn start_server(self) -> Result<Self::Server, Self::Error> {
53        Ok(Self::Server::default())
54    }
55
56    fn start_client(self) -> Result<Self::Client, Self::Error> {
57        Ok(Self::Client::default())
58    }
59}
60
61impl Provider for (&std::path::Path, &std::path::Path) {
62    type Server = <Default as Provider>::Server;
63    type Client = <Default as Provider>::Client;
64    type Error = Box<dyn std::error::Error + Send + Sync>;
65
66    fn start_server(self) -> Result<Self::Server, Self::Error> {
67        let server = default::Server::builder()
68            .with_certificate(self.0, self.1)?
69            .build()?;
70
71        Ok(server)
72    }
73
74    fn start_client(self) -> Result<Self::Client, Self::Error> {
75        // TODO support private key
76        let client = default::Client::builder()
77            .with_certificate(self.0)?
78            .build()?;
79
80        Ok(client)
81    }
82}
83
84impl Provider for &std::path::Path {
85    type Server = <Default as Provider>::Server;
86    type Client = <Default as Provider>::Client;
87    type Error = Box<dyn std::error::Error + Send + Sync>;
88
89    fn start_server(self) -> Result<Self::Server, Self::Error> {
90        let empty_cert: &[u8] = &[];
91        let server = default::Server::builder()
92            .with_certificate(empty_cert, self)?
93            .build()?;
94
95        Ok(server)
96    }
97
98    fn start_client(self) -> Result<Self::Client, Self::Error> {
99        let client = default::Client::builder().with_certificate(self)?.build()?;
100
101        Ok(client)
102    }
103}
104
105impl Provider for (&[u8], &[u8]) {
106    type Server = <Default as Provider>::Server;
107    type Client = <Default as Provider>::Client;
108    type Error = Box<dyn std::error::Error + Send + Sync>;
109
110    fn start_server(self) -> Result<Self::Server, Self::Error> {
111        let server = default::Server::builder()
112            .with_certificate(self.0, self.1)?
113            .build()?;
114
115        Ok(server)
116    }
117
118    fn start_client(self) -> Result<Self::Client, Self::Error> {
119        // TODO support private key
120        let client = default::Client::builder()
121            .with_certificate(self.0)?
122            .build()?;
123
124        Ok(client)
125    }
126}
127
128impl Provider for &[u8] {
129    type Server = <Default as Provider>::Server;
130    type Client = <Default as Provider>::Client;
131    type Error = Box<dyn std::error::Error + Send + Sync>;
132
133    fn start_server(self) -> Result<Self::Server, Self::Error> {
134        let empty_cert = &[][..];
135        let server = default::Server::builder()
136            .with_certificate(empty_cert, self)?
137            .build()?;
138
139        Ok(server)
140    }
141
142    fn start_client(self) -> Result<Self::Client, Self::Error> {
143        let client = default::Client::builder().with_certificate(self)?.build()?;
144
145        Ok(client)
146    }
147}
148
149impl Provider for (&str, &str) {
150    type Server = <Default as Provider>::Server;
151    type Client = <Default as Provider>::Client;
152    type Error = Box<dyn std::error::Error + Send + Sync>;
153
154    fn start_server(self) -> Result<Self::Server, Self::Error> {
155        let server = default::Server::builder()
156            .with_certificate(self.0, self.1)?
157            .build()?;
158
159        Ok(server)
160    }
161
162    fn start_client(self) -> Result<Self::Client, Self::Error> {
163        // TODO support private key
164        let client = default::Client::builder()
165            .with_certificate(self.0)?
166            .build()?;
167
168        Ok(client)
169    }
170}
171
172impl Provider for &str {
173    type Server = <Default as Provider>::Server;
174    type Client = <Default as Provider>::Client;
175    type Error = Box<dyn std::error::Error + Send + Sync>;
176
177    fn start_server(self) -> Result<Self::Server, Self::Error> {
178        let empty_cert = "";
179        let server = default::Server::builder()
180            .with_certificate(empty_cert, self)?
181            .build()?;
182
183        Ok(server)
184    }
185
186    fn start_client(self) -> Result<Self::Client, Self::Error> {
187        let client = default::Client::builder().with_certificate(self)?.build()?;
188
189        Ok(client)
190    }
191}
192
193#[cfg(feature = "provider-tls-default")]
194mod default_tls {
195    pub use s2n_quic_tls_default::*;
196
197    // We need to implement the provider trait for whatever the default is as long as it's
198    // not called out explicitly and we're not on the platform that uses it by default.
199    //
200    // Note: I know this looks like a mess. And it is. Hopefully in the future cargo will support
201    // platform-specific default features.
202    #[cfg(not(any(
203        all(not(unix), feature = "s2n-quic-rustls"),
204        all(unix, feature = "s2n-quic-tls")
205    )))]
206    mod default_provider {
207        use super::*;
208        use crate::provider::tls;
209
210        impl tls::Provider for Server {
211            type Server = Self;
212            type Client = Client;
213            type Error = core::convert::Infallible;
214
215            fn start_server(self) -> Result<Self::Server, Self::Error> {
216                Ok(self)
217            }
218
219            fn start_client(self) -> Result<Self::Client, Self::Error> {
220                panic!("cannot create a client from a server");
221            }
222        }
223
224        impl tls::Provider for Client {
225            type Server = Server;
226            type Client = Self;
227            type Error = core::convert::Infallible;
228
229            fn start_server(self) -> Result<Self::Server, Self::Error> {
230                panic!("cannot create a server from a client");
231            }
232
233            fn start_client(self) -> Result<Self::Client, Self::Error> {
234                Ok(self)
235            }
236        }
237    }
238}
239#[cfg(not(feature = "provider-tls-default"))]
240mod default_tls {
241    // TODO stub out default that fails with error when started
242}
243
244#[cfg_attr(docsrs, doc(cfg(feature = "provider-tls-rustls")))]
245#[cfg(feature = "s2n-quic-rustls")]
246pub mod rustls {
247    //! Provides the [rustls](https://docs.rs/rustls/) implementation of TLS
248
249    pub use s2n_quic_rustls::*;
250
251    impl super::Provider for Server {
252        type Server = Self;
253        type Client = Client;
254        type Error = core::convert::Infallible;
255
256        fn start_server(self) -> Result<Self::Server, Self::Error> {
257            Ok(self)
258        }
259
260        fn start_client(self) -> Result<Self::Client, Self::Error> {
261            panic!("cannot create a client from a server");
262        }
263    }
264
265    impl super::Provider for Client {
266        type Server = Server;
267        type Client = Self;
268        type Error = core::convert::Infallible;
269
270        fn start_server(self) -> Result<Self::Server, Self::Error> {
271            panic!("cannot create a server from a client");
272        }
273
274        fn start_client(self) -> Result<Self::Client, Self::Error> {
275            Ok(self)
276        }
277    }
278}
279
280#[cfg_attr(docsrs, doc(cfg(feature = "provider-tls-s2n")))]
281#[cfg(feature = "s2n-quic-tls")]
282pub mod s2n_tls {
283    //! Provides the [s2n-tls](https://github.com/aws/s2n-tls) implementation of TLS
284    pub use s2n_quic_tls::*;
285
286    impl<L: ConfigLoader> super::Provider for Server<L> {
287        type Server = Self;
288        type Client = Client;
289        type Error = core::convert::Infallible;
290
291        fn start_server(self) -> Result<Self::Server, Self::Error> {
292            Ok(self)
293        }
294
295        fn start_client(self) -> Result<Self::Client, Self::Error> {
296            panic!("cannot create a client from a server");
297        }
298    }
299
300    impl<L: ConfigLoader> super::Provider for Client<L> {
301        type Server = Server;
302        type Client = Self;
303        type Error = core::convert::Infallible;
304
305        fn start_server(self) -> Result<Self::Server, Self::Error> {
306            panic!("cannot create a server from a client");
307        }
308
309        fn start_client(self) -> Result<Self::Client, Self::Error> {
310            Ok(self)
311        }
312    }
313}
314
315#[cfg(feature = "unstable-offload-tls")]
316pub mod offload {
317    use super::Provider;
318    use s2n_quic_core::crypto::tls::{offload::OffloadEndpoint, Endpoint};
319    pub use s2n_quic_core::crypto::tls::{
320        offload::{Executor, ExporterHandler},
321        TlsSession,
322    };
323
324    pub struct Offload<E, X, H> {
325        endpoint: E,
326        executor: X,
327        exporter: H,
328        channel_capacity: usize,
329    }
330
331    pub struct OffloadBuilder<E = (), X = (), H = ()> {
332        endpoint: E,
333        executor: X,
334        exporter: H,
335        channel_capacity: usize,
336    }
337
338    impl OffloadBuilder<(), (), ()> {
339        pub fn new() -> Self {
340            Self {
341                endpoint: (),
342                executor: (),
343                exporter: (),
344                channel_capacity: 10,
345            }
346        }
347    }
348
349    impl Default for OffloadBuilder<(), (), ()> {
350        fn default() -> Self {
351            Self::new()
352        }
353    }
354
355    impl<X, H> OffloadBuilder<(), X, H> {
356        pub fn with_endpoint<E: Endpoint>(self, endpoint: E) -> OffloadBuilder<E, X, H> {
357            OffloadBuilder::<E, X, H> {
358                endpoint,
359                executor: self.executor,
360                exporter: self.exporter,
361                channel_capacity: self.channel_capacity,
362            }
363        }
364    }
365
366    impl<E, H> OffloadBuilder<E, (), H> {
367        pub fn with_executor<X: Executor>(self, executor: X) -> OffloadBuilder<E, X, H> {
368            OffloadBuilder::<E, X, H> {
369                endpoint: self.endpoint,
370                executor,
371                exporter: self.exporter,
372                channel_capacity: self.channel_capacity,
373            }
374        }
375    }
376
377    impl<E, X> OffloadBuilder<E, X, ()> {
378        pub fn with_exporter<H: ExporterHandler>(self, exporter: H) -> OffloadBuilder<E, X, H> {
379            OffloadBuilder::<E, X, H> {
380                endpoint: self.endpoint,
381                executor: self.executor,
382                exporter,
383                channel_capacity: self.channel_capacity,
384            }
385        }
386    }
387
388    impl<E, X, H> OffloadBuilder<E, X, H> {
389        pub fn with_channel_capacity(self, channel_capacity: usize) -> OffloadBuilder<E, X, H> {
390            OffloadBuilder::<E, X, H> {
391                endpoint: self.endpoint,
392                executor: self.executor,
393                exporter: self.exporter,
394                channel_capacity,
395            }
396        }
397    }
398
399    impl<E, X, H> OffloadBuilder<E, X, H> {
400        pub fn build(self) -> Offload<E, X, H> {
401            Offload {
402                endpoint: self.endpoint,
403                executor: self.executor,
404                exporter: self.exporter,
405                channel_capacity: self.channel_capacity,
406            }
407        }
408    }
409
410    impl<E, X, H> Provider for Offload<E, X, H>
411    where
412        E: Provider,
413        X: Executor + Send + 'static,
414        H: ExporterHandler + Send + 'static + Sync + Clone,
415    {
416        type Server = OffloadEndpoint<<E as Provider>::Server, X, H>;
417        type Client = OffloadEndpoint<<E as Provider>::Client, X, H>;
418        type Error = E::Error;
419
420        fn start_server(self) -> Result<Self::Server, Self::Error> {
421            Ok(OffloadEndpoint::new(
422                E::start_server(self.endpoint)?,
423                self.executor,
424                self.exporter,
425                self.channel_capacity,
426            ))
427        }
428
429        fn start_client(self) -> Result<Self::Client, Self::Error> {
430            Ok(OffloadEndpoint::new(
431                E::start_client(self.endpoint)?,
432                self.executor,
433                self.exporter,
434                self.channel_capacity,
435            ))
436        }
437    }
438}