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        _connection_info: tls::ConnectionInfo,
73    ) -> Self::Session {
74        //= https://www.rfc-editor.org/rfc/rfc9001#section-8.2
75        //# Endpoints MUST send the quic_transport_parameters extension;
76        let transport_parameters = transport_parameters.encode_to_vec();
77
78        let session = rustls::quic::ServerConnection::new(
79            self.config.clone(),
80            crate::QUIC_VERSION,
81            transport_parameters,
82        )
83        .expect("could not create rustls server session");
84
85        Session::new(session.into(), None)
86    }
87
88    fn new_client_session<Params: EncoderValue>(
89        &mut self,
90        _transport_parameters: &Params,
91        _sni: ServerName,
92    ) -> Self::Session {
93        panic!("cannot create a client session from a server config");
94    }
95
96    fn max_tag_length(&self) -> usize {
97        s2n_quic_crypto::MAX_TAG_LEN
98    }
99}
100
101pub struct Builder {
102    cert_resolver: Option<Arc<dyn rustls::server::ResolvesServerCert>>,
103    application_protocols: Vec<Vec<u8>>,
104    key_log: Option<Arc<dyn rustls::KeyLog>>,
105    prefer_server_cipher_suite_order: bool,
106}
107
108impl Default for Builder {
109    fn default() -> Self {
110        Self::new()
111    }
112}
113
114impl Builder {
115    pub fn new() -> Self {
116        Self {
117            cert_resolver: None,
118            application_protocols: vec![b"h3".to_vec()],
119            key_log: None,
120            prefer_server_cipher_suite_order: true,
121        }
122    }
123
124    pub fn with_certificate<C: certificate::IntoCertificate, PK: certificate::IntoPrivateKey>(
125        mut self,
126        certificate: C,
127        private_key: PK,
128    ) -> Result<Self, Error> {
129        let certificate = certificate.into_certificate()?;
130        let private_key = private_key.into_private_key()?;
131        let resolver = AlwaysResolvesChain::new(certificate, private_key)?;
132        let resolver = Arc::new(resolver);
133        self.cert_resolver = Some(resolver);
134        Ok(self)
135    }
136
137    #[deprecated = "client and server builders should be used instead"]
138    pub fn with_cert_resolver(
139        mut self,
140        cert_resolver: Arc<dyn rustls::server::ResolvesServerCert>,
141    ) -> Result<Self, Error> {
142        self.cert_resolver = Some(cert_resolver);
143        Ok(self)
144    }
145
146    pub fn with_application_protocols<P: Iterator<Item = I>, I: AsRef<[u8]>>(
147        mut self,
148        protocols: P,
149    ) -> Result<Self, Error> {
150        self.application_protocols = protocols.map(|p| p.as_ref().to_vec()).collect();
151        Ok(self)
152    }
153
154    pub fn with_key_logging(mut self) -> Result<Self, Error> {
155        self.key_log = Some(Arc::new(rustls::KeyLogFile::new()));
156        Ok(self)
157    }
158
159    /// If enabled, the cipher suite order of the client is ignored, and the top cipher suite
160    /// in the server list that the client supports is chosen (default: true)
161    pub fn with_prefer_server_cipher_suite_order(mut self, enabled: bool) -> Result<Self, Error> {
162        self.prefer_server_cipher_suite_order = enabled;
163        Ok(self)
164    }
165
166    pub fn build(self) -> Result<Server, Error> {
167        let builder = default_config_builder()?.with_no_client_auth();
168
169        let mut config = if let Some(cert_resolver) = self.cert_resolver {
170            builder.with_cert_resolver(cert_resolver)
171        } else {
172            return Err(rustls::Error::General(
173                "Missing certificate or certificate resolver".to_string(),
174            )
175            .into());
176        };
177
178        config.ignore_client_order = self.prefer_server_cipher_suite_order;
179        config.max_fragment_size = None;
180        config.alpn_protocols = self.application_protocols;
181
182        if let Some(key_log) = self.key_log {
183            config.key_log = key_log;
184        }
185
186        #[allow(deprecated)]
187        Ok(Server::new(config))
188    }
189}
190
191#[derive(Debug)]
192struct AlwaysResolvesChain(Arc<rustls::sign::CertifiedKey>);
193
194impl AlwaysResolvesChain {
195    fn new(
196        chain: certificate::Certificate,
197        priv_key: certificate::PrivateKey,
198    ) -> Result<Self, rustls::Error> {
199        let key = aws_lc_rs::sign::any_supported_type(&priv_key.0)
200            .map_err(|_| rustls::Error::General("invalid private key".into()))?;
201        Ok(Self(Arc::new(rustls::sign::CertifiedKey::new(
202            chain.0, key,
203        ))))
204    }
205}
206
207impl rustls::server::ResolvesServerCert for AlwaysResolvesChain {
208    fn resolve(
209        &self,
210        _client_hello: rustls::server::ClientHello,
211    ) -> Option<Arc<rustls::sign::CertifiedKey>> {
212        Some(Arc::clone(&self.0))
213    }
214}