s2n_quic_rustls/
server.rs

1// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
2// SPDX-License-Identifier: Apache-2.0
3
4use crate::{certificate, cipher_suite::default_crypto_provider, session::Session, Error};
5use rustls::{crypto::aws_lc_rs, ConfigBuilder, ServerConfig, WantsVerifier};
6use s2n_codec::EncoderValue;
7use s2n_quic_core::{application::ServerName, crypto::tls};
8use std::sync::Arc;
9
10/// Create a QUIC server specific [rustls::ConfigBuilder].
11///
12/// Uses aws_lc_rs as the crypto provider and sets QUIC specific protocol versions.
13fn default_config_builder() -> Result<ConfigBuilder<ServerConfig, WantsVerifier>, rustls::Error> {
14    let tls13_cipher_suite_crypto_provider = default_crypto_provider()?;
15    ServerConfig::builder_with_provider(tls13_cipher_suite_crypto_provider.into())
16        .with_protocol_versions(crate::PROTOCOL_VERSIONS)
17}
18
19#[derive(Clone)]
20pub struct Server {
21    config: Arc<ServerConfig>,
22}
23
24impl Server {
25    /// Build a Server using a custom [rustls::ServerConfig]
26    ///
27    /// In addition to necessary configuration, the applications is responsible for correctly
28    /// setting:
29    /// - QUIC compliant application_protocol
30    /// - QUIC compliant TLS protocol version
31    /// - QUIC compliant ciphersuites
32    #[deprecated = "client and server builders should be used instead"]
33    pub fn new(config: ServerConfig) -> Self {
34        Self {
35            config: Arc::new(config),
36        }
37    }
38
39    pub fn builder() -> Builder {
40        Builder::new()
41    }
42}
43
44impl Default for Server {
45    fn default() -> Self {
46        Self::builder()
47            .build()
48            .expect("could not create default server")
49    }
50}
51
52// TODO this should be removed after removing deprecated re-exports
53impl From<ServerConfig> for Server {
54    fn from(config: ServerConfig) -> Self {
55        Self::from(Arc::new(config))
56    }
57}
58
59// TODO this should be removed after removing deprecated re-exports
60impl From<Arc<ServerConfig>> for Server {
61    fn from(config: Arc<ServerConfig>) -> Self {
62        Self { config }
63    }
64}
65
66impl tls::Endpoint for Server {
67    type Session = Session;
68
69    fn new_server_session<Params: EncoderValue>(
70        &mut self,
71        transport_parameters: &Params,
72    ) -> Self::Session {
73        //= https://www.rfc-editor.org/rfc/rfc9001#section-8.2
74        //# Endpoints MUST send the quic_transport_parameters extension;
75        let transport_parameters = transport_parameters.encode_to_vec();
76
77        let session = rustls::quic::ServerConnection::new(
78            self.config.clone(),
79            crate::QUIC_VERSION,
80            transport_parameters,
81        )
82        .expect("could not create rustls server session");
83
84        Session::new(session.into(), None)
85    }
86
87    fn new_client_session<Params: EncoderValue>(
88        &mut self,
89        _transport_parameters: &Params,
90        _sni: ServerName,
91    ) -> Self::Session {
92        panic!("cannot create a client session from a server config");
93    }
94
95    fn max_tag_length(&self) -> usize {
96        s2n_quic_crypto::MAX_TAG_LEN
97    }
98}
99
100pub struct Builder {
101    cert_resolver: Option<Arc<dyn rustls::server::ResolvesServerCert>>,
102    application_protocols: Vec<Vec<u8>>,
103    key_log: Option<Arc<dyn rustls::KeyLog>>,
104    prefer_server_cipher_suite_order: bool,
105}
106
107impl Default for Builder {
108    fn default() -> Self {
109        Self::new()
110    }
111}
112
113impl Builder {
114    pub fn new() -> Self {
115        Self {
116            cert_resolver: None,
117            application_protocols: vec![b"h3".to_vec()],
118            key_log: None,
119            prefer_server_cipher_suite_order: true,
120        }
121    }
122
123    pub fn with_certificate<C: certificate::IntoCertificate, PK: certificate::IntoPrivateKey>(
124        mut self,
125        certificate: C,
126        private_key: PK,
127    ) -> Result<Self, Error> {
128        let certificate = certificate.into_certificate()?;
129        let private_key = private_key.into_private_key()?;
130        let resolver = AlwaysResolvesChain::new(certificate, private_key)?;
131        let resolver = Arc::new(resolver);
132        self.cert_resolver = Some(resolver);
133        Ok(self)
134    }
135
136    #[deprecated = "client and server builders should be used instead"]
137    pub fn with_cert_resolver(
138        mut self,
139        cert_resolver: Arc<dyn rustls::server::ResolvesServerCert>,
140    ) -> Result<Self, Error> {
141        self.cert_resolver = Some(cert_resolver);
142        Ok(self)
143    }
144
145    pub fn with_application_protocols<P: Iterator<Item = I>, I: AsRef<[u8]>>(
146        mut self,
147        protocols: P,
148    ) -> Result<Self, Error> {
149        self.application_protocols = protocols.map(|p| p.as_ref().to_vec()).collect();
150        Ok(self)
151    }
152
153    pub fn with_key_logging(mut self) -> Result<Self, Error> {
154        self.key_log = Some(Arc::new(rustls::KeyLogFile::new()));
155        Ok(self)
156    }
157
158    /// If enabled, the cipher suite order of the client is ignored, and the top cipher suite
159    /// in the server list that the client supports is chosen (default: true)
160    pub fn with_prefer_server_cipher_suite_order(mut self, enabled: bool) -> Result<Self, Error> {
161        self.prefer_server_cipher_suite_order = enabled;
162        Ok(self)
163    }
164
165    pub fn build(self) -> Result<Server, Error> {
166        let builder = default_config_builder()?.with_no_client_auth();
167
168        let mut config = if let Some(cert_resolver) = self.cert_resolver {
169            builder.with_cert_resolver(cert_resolver)
170        } else {
171            return Err(rustls::Error::General(
172                "Missing certificate or certificate resolver".to_string(),
173            )
174            .into());
175        };
176
177        config.ignore_client_order = self.prefer_server_cipher_suite_order;
178        config.max_fragment_size = None;
179        config.alpn_protocols = self.application_protocols;
180
181        if let Some(key_log) = self.key_log {
182            config.key_log = key_log;
183        }
184
185        #[allow(deprecated)]
186        Ok(Server::new(config))
187    }
188}
189
190#[derive(Debug)]
191struct AlwaysResolvesChain(Arc<rustls::sign::CertifiedKey>);
192
193impl AlwaysResolvesChain {
194    fn new(
195        chain: certificate::Certificate,
196        priv_key: certificate::PrivateKey,
197    ) -> Result<Self, rustls::Error> {
198        let key = aws_lc_rs::sign::any_supported_type(&priv_key.0)
199            .map_err(|_| rustls::Error::General("invalid private key".into()))?;
200        Ok(Self(Arc::new(rustls::sign::CertifiedKey::new(
201            chain.0, key,
202        ))))
203    }
204}
205
206impl rustls::server::ResolvesServerCert for AlwaysResolvesChain {
207    fn resolve(
208        &self,
209        _client_hello: rustls::server::ClientHello,
210    ) -> Option<Arc<rustls::sign::CertifiedKey>> {
211        Some(Arc::clone(&self.0))
212    }
213}