Skip to main content

rustls/server/
connection.rs

1use alloc::boxed::Box;
2use alloc::vec::Vec;
3use core::ops::Deref;
4use core::{fmt, mem};
5
6use pki_types::{DnsName, FipsStatus};
7
8use super::config::{ClientHello, ServerConfig};
9use crate::common_state::{
10    CommonState, ConnectionOutputs, EarlyDataEvent, Event, Protocol, Side, maybe_send_fatal_alert,
11};
12use crate::conn::private::SideOutput;
13use crate::conn::split::SplitConnection;
14use crate::conn::{
15    Connection, ConnectionCommon, KeyingMaterialExporter, MessageHandler, NeedsInput, SideData,
16    StateMachine, TlsInputBuffer, VerifyPeerIdentity,
17};
18#[cfg(doc)]
19use crate::crypto;
20use crate::crypto::cipher::OutboundPlain;
21use crate::error::Error;
22use crate::msgs::ServerExtensionsInput;
23use crate::server::hs::{ChooseConfig, ExpectClientHello, ReadClientHello, ServerState};
24use crate::suites::ExtractedSecrets;
25use crate::sync::Arc;
26use crate::tracing::trace;
27use crate::verify::ClientIdentity;
28
29/// This represents a single TLS server connection.
30///
31/// Encrypt data destined for the peer using [`Connection::write()`].
32/// Process received data from the peer using [`Connection::read_tls()`].
33pub struct ServerConnection {
34    pub(super) inner: ConnectionCommon<ServerSide>,
35}
36
37impl ServerConnection {
38    /// Make a new ServerConnection.  `config` controls how
39    /// we behave in the TLS protocol.
40    pub fn new(config: Arc<ServerConfig>) -> Result<Self, Error> {
41        Ok(Self {
42            inner: ConnectionCommon::for_server(
43                config,
44                ServerExtensionsInput::default(),
45                Protocol::Tcp,
46            )?,
47        })
48    }
49
50    /// Split a post-handshake connection into a [`SplitConnection`].
51    ///
52    /// This allows the two directions (transmit and receive) of the connection to be progressed
53    /// separately (including by different threads, which would allow dedicating a CPU core for each
54    /// direction rather than one per connection; this can dramatically improve performance for
55    /// full-duplex protocols).
56    ///
57    /// It also separates out the [`ConnectionOutputs`] which gives the application direct control
58    /// of how long this is kept.
59    ///
60    /// This fails if:
61    ///
62    /// - the handshake is not complete. Check with [`Connection::is_handshaking()`].
63    /// - there is any buffered TLS data to send.  Obtain it first with [`Connection::write()`].
64    pub fn split(self) -> Result<SplitConnection<ServerSide>, Error> {
65        self.inner.split()
66    }
67
68    /// Retrieves the server name, if any, used to select the certificate and
69    /// private key.
70    ///
71    /// This returns `None` until some time after the client's server name indication
72    /// (SNI) extension value is processed during the handshake. It will never be
73    /// `None` when the connection is ready to send or process application data,
74    /// unless the client does not support SNI.
75    ///
76    /// This is useful for application protocols that need to enforce that the
77    /// server name matches an application layer protocol hostname. For
78    /// example, HTTP/1.1 servers commonly expect the `Host:` header field of
79    /// every request on a connection to match the hostname in the SNI extension
80    /// when the client provides the SNI extension.
81    ///
82    /// The server name is also used to match sessions during session resumption.
83    pub fn server_name(&self) -> Option<&DnsName<'_>> {
84        self.inner.side.server_name()
85    }
86
87    /// Application-controlled portion of the resumption ticket supplied by the client, if any.
88    ///
89    /// Recovered from the prior session's `set_resumption_data`. Integrity is guaranteed by rustls.
90    ///
91    /// Returns `Some` if and only if a valid resumption ticket has been received from the client.
92    pub fn received_resumption_data(&self) -> Option<&[u8]> {
93        self.inner
94            .side
95            .received_resumption_data()
96    }
97
98    /// Set the resumption data to embed in future resumption tickets supplied to the client.
99    ///
100    /// Defaults to the empty byte string. Must be less than 2^15 bytes to allow room for other
101    /// data. Should be called while `is_handshaking` returns true to ensure all transmitted
102    /// resumption tickets are affected.
103    ///
104    /// Integrity will be assured by rustls, but the data will be visible to the client. If secrecy
105    /// from the client is desired, encrypt the data separately.
106    pub fn set_resumption_data(&mut self, data: &[u8]) -> Result<(), Error> {
107        assert!(data.len() < 2usize.pow(15));
108        match &mut self.inner.state {
109            Ok(st) => st.set_resumption_data(data),
110            Err(e) => Err(e.clone()),
111        }
112    }
113
114    /// Returns a handle to TLS1.3 0RTT/"early" data facilities if the client's early
115    /// data offer was accepted.
116    ///
117    /// The early data itself is read via [`MessageHandler::next_early_data()`] while
118    /// processing input; this handle gives access to the "early" keying material exporter.
119    ///
120    /// This returns `None` in many circumstances, such as :
121    ///
122    /// - Early data is disabled if [`ServerConfig::max_early_data_size`] is zero (the default).
123    /// - The session negotiated with the client is not TLS1.3.
124    /// - The client just doesn't support early data.
125    /// - The connection doesn't resume an existing session.
126    /// - The client hasn't sent a full ClientHello yet.
127    pub fn early_data(&mut self) -> Option<ReadEarlyData<'_>> {
128        if self
129            .inner
130            .side
131            .early_data
132            .was_accepted()
133        {
134            Some(ReadEarlyData::new(&mut self.inner))
135        } else {
136            None
137        }
138    }
139}
140
141impl Connection for ServerConnection {
142    type Side = ServerSide;
143
144    fn write(&mut self, plaintext: OutboundPlain<'_>, tls: &mut Vec<u8>) -> Result<(), Error> {
145        self.inner.write(plaintext, tls)
146    }
147
148    fn wants_read(&self) -> bool {
149        self.inner.wants_read()
150    }
151
152    fn read_tls<'a, 'm>(
153        &'a mut self,
154        input: &'m mut dyn TlsInputBuffer,
155        tls: &'a mut Vec<u8>,
156    ) -> MessageHandler<'a, 'm, ServerSide> {
157        self.inner.read_tls(input, tls)
158    }
159
160    fn exporter(&mut self) -> Result<KeyingMaterialExporter, Error> {
161        self.inner.exporter()
162    }
163
164    fn dangerous_extract_secrets(self) -> Result<ExtractedSecrets, Error> {
165        self.inner.dangerous_extract_secrets()
166    }
167
168    fn refresh_traffic_keys(&mut self, tls: &mut Vec<u8>) -> Result<(), Error> {
169        self.inner.refresh_traffic_keys(tls)
170    }
171
172    fn send_close_notify(&mut self, tls: &mut Vec<u8>) {
173        self.inner.send_close_notify(tls);
174    }
175
176    fn is_handshaking(&self) -> bool {
177        self.inner.is_handshaking()
178    }
179
180    fn fips(&self) -> FipsStatus {
181        self.inner.fips
182    }
183}
184
185impl Deref for ServerConnection {
186    type Target = ConnectionOutputs;
187
188    fn deref(&self) -> &Self::Target {
189        &self.inner
190    }
191}
192
193impl fmt::Debug for ServerConnection {
194    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
195        f.debug_struct("ServerConnection")
196            .finish_non_exhaustive()
197    }
198}
199
200impl ConnectionCommon<ServerSide> {
201    pub(crate) fn for_server(
202        config: Arc<ServerConfig>,
203        extra_exts: ServerExtensionsInput,
204        protocol: Protocol,
205    ) -> Result<Self, Error> {
206        let mut common = CommonState::new(Side::Server, config.fips());
207        common
208            .send
209            .set_max_fragment_size(config.max_fragment_size)?;
210        Ok(Self::new(
211            Box::new(ExpectClientHello::new(
212                config,
213                extra_exts,
214                Vec::new(),
215                protocol,
216            ))
217            .into(),
218            ServerConnectionData::default(),
219            common,
220        ))
221    }
222
223    pub(crate) fn for_acceptor(protocol: Protocol) -> Self {
224        Self::new(
225            ReadClientHello::new(protocol).into(),
226            ServerConnectionData::default(),
227            CommonState::new(Side::Server, FipsStatus::Unvalidated),
228        )
229    }
230}
231
232/// An in-progress TLS server handshake.
233#[non_exhaustive]
234#[derive(Debug)]
235pub enum ServerHandshake {
236    /// More data needs to be received to make progress.
237    NeedsInput(NeedsInput<ServerSide>),
238
239    /// A complete `ClientHello` has been received.
240    ///
241    /// The handshake can be progressed by choosing a [`ServerConfig`] based on
242    /// [`Accepted::client_hello()`] and providing it to [`Accepted::choose_config()`].
243    Accepted(Accepted),
244
245    /// The client's presented identity must be verified.
246    ///
247    /// See [`VerifyPeerIdentity`] for how to proceed.
248    VerifyClientIdentity(VerifyPeerIdentity<ServerSide>),
249
250    /// The handshake is complete.
251    ///
252    /// Now see [`SplitConnection`] to continue the connection.
253    Complete(SplitConnection<ServerSide>),
254}
255
256impl ServerHandshake {
257    /// Creates a new [`ServerHandshake`] via the payload of the [`ServerHandshake::NeedsInput`] variant.
258    ///
259    /// It is a fundamental fact of server TLS connections that the server reads first; this is reflected
260    /// in the returned type.
261    ///
262    /// You may wrap this in the [`ServerHandshake::NeedsInput`] variant to generalise the type to a
263    /// [`ServerHandshake`].
264    ///
265    /// The returned object should be fed data from a single potential client.
266    pub fn start() -> NeedsInput<ServerSide> {
267        NeedsInput {
268            inner: ConnectionCommon::for_acceptor(Protocol::Tcp),
269        }
270    }
271}
272
273impl TryFrom<ConnectionCommon<ServerSide>> for ServerHandshake {
274    type Error = Error;
275
276    fn try_from(mut inner: ConnectionCommon<ServerSide>) -> Result<Self, Error> {
277        const MISUSED: Error = Error::Unreachable("forgot to restore state");
278
279        Ok(match mem::replace(&mut inner.state, Err(MISUSED))? {
280            ServerState::ChooseConfig(choose_config) => Self::Accepted(Accepted {
281                inner,
282                choose_config,
283            }),
284
285            ServerState::VerifyClientIdentity(verify_identity) => {
286                Self::VerifyClientIdentity(VerifyPeerIdentity {
287                    inner,
288                    verify_identity,
289                })
290            }
291
292            state if state.is_traffic() => {
293                inner.state = Ok(state);
294                Self::Complete(SplitConnection::try_from(inner)?)
295            }
296
297            state => {
298                inner.state = Ok(state);
299                Self::NeedsInput(NeedsInput { inner })
300            }
301        })
302    }
303}
304
305/// Represents a `ClientHello` message.
306///
307/// The handshake can be progressed by choosing a [`ServerConfig`] based on
308/// [`Accepted::client_hello()`] and providing it to [`Accepted::choose_config()`].
309pub struct Accepted {
310    // invariant: `inner.state` is `Err(_)` and requires restoring
311    inner: ConnectionCommon<ServerSide>,
312    choose_config: Box<ChooseConfig>,
313}
314
315impl Accepted {
316    /// Get the [`ClientHello`] for this connection.
317    pub fn client_hello(&self) -> ClientHello<'_> {
318        let ch = self.choose_config.client_hello();
319        trace!("Accepted::client_hello(): {ch:#?}");
320        ch
321    }
322
323    /// Choose a [`ServerConfig`] to progress the handshake.
324    ///
325    /// Output to send to the peer is appended to `tls`.  Typically, this is the `ServerHello`,
326    /// but it may also be an `Alert` if an error is returned.
327    ///
328    /// Returns an error if configuration-dependent validation of the received `ClientHello` message fails.
329    pub fn choose_config(
330        mut self,
331        config: Arc<ServerConfig>,
332        tls: &mut Vec<u8>,
333    ) -> Result<ServerHandshake, Error> {
334        let result = self.inner.accepted(
335            self.choose_config,
336            ServerExtensionsInput::default(),
337            None,
338            config,
339            tls,
340        );
341
342        let send_path = &mut self.inner.common.send;
343
344        if let Err(err) = &result {
345            maybe_send_fatal_alert(send_path, err, tls);
346        }
347
348        result?;
349
350        Ok(ServerHandshake::NeedsInput(NeedsInput {
351            inner: self.inner,
352        }))
353    }
354}
355
356impl fmt::Debug for Accepted {
357    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
358        f.debug_struct("Accepted")
359            .finish_non_exhaustive()
360    }
361}
362
363/// State associated with a server connection.
364#[expect(clippy::exhaustive_structs)]
365#[derive(Debug)]
366pub struct ServerSide;
367
368impl SideData for ServerSide {
369    type Handshake = ServerHandshake;
370
371    type PeerIdentity<'a> = ClientIdentity<'static, 'a>;
372
373    #[expect(private_interfaces)]
374    fn handshake_from_inner(common: ConnectionCommon<Self>) -> Result<Self::Handshake, Error> {
375        ServerHandshake::try_from(common)
376    }
377}
378
379impl crate::conn::private::Side for ServerSide {
380    type Data = ServerConnectionData;
381    type State = ServerState;
382}
383
384/// State associated with a server connection.
385#[derive(Default)]
386pub(crate) struct ServerConnectionData {
387    sni: Option<DnsName<'static>>,
388    received_resumption_data: Option<Vec<u8>>,
389    early_data: EarlyDataState,
390}
391
392impl ServerConnectionData {
393    pub(crate) fn received_resumption_data(&self) -> Option<&[u8]> {
394        self.received_resumption_data.as_deref()
395    }
396
397    pub(crate) fn server_name(&self) -> Option<&DnsName<'static>> {
398        self.sni.as_ref()
399    }
400}
401
402impl SideOutput for ServerConnectionData {
403    fn emit(&mut self, ev: Event) {
404        match ev {
405            Event::EarlyData(EarlyDataEvent::Accepted) => self.early_data.accept(),
406            Event::ReceivedServerName(sni) => self.sni = sni,
407            Event::ResumptionData(data) => self.received_resumption_data = Some(data),
408            _ => unreachable!(),
409        }
410    }
411}
412
413/// Access to early data facilities in resumed TLS1.3 connections.
414///
415/// "Early data" is also known as "0-RTT data".
416///
417/// The early data itself is read via [`MessageHandler::next_early_data()`]; this
418/// type provides the matching "early" keying material exporter.
419pub struct ReadEarlyData<'a> {
420    common: &'a mut ConnectionCommon<ServerSide>,
421}
422
423impl<'a> ReadEarlyData<'a> {
424    fn new(common: &'a mut ConnectionCommon<ServerSide>) -> Self {
425        ReadEarlyData { common }
426    }
427
428    /// Returns the "early" exporter that can derive key material for use in early data
429    ///
430    /// See [RFC 5705][] for general details on what exporters are, and [RFC 9846 S7.5][] for
431    /// specific details on the "early" exporter.
432    ///
433    /// **Beware** that the early exporter requires care, as it is subject to the same
434    /// potential for replay as early data itself.  See [RFC 9846 appendix F.5.1][] for
435    /// more detail.
436    ///
437    /// This function can be called at most once per connection. This function will error:
438    /// if called more than once per connection.
439    ///
440    /// If you are looking for the normal exporter, this is available from
441    /// [`Connection::exporter()`].
442    ///
443    /// [RFC 5705]: https://datatracker.ietf.org/doc/html/rfc5705
444    /// [RFC 9846 S7.5]: https://datatracker.ietf.org/doc/html/rfc9846#section-7.5
445    /// [RFC 9846 appendix F.5.1]: https://datatracker.ietf.org/doc/html/rfc9846#appendix-F.5.1
446    /// [`Connection::exporter()`]: crate::conn::Connection::exporter()
447    pub fn exporter(&mut self) -> Result<KeyingMaterialExporter, Error> {
448        self.common.common.early_exporter()
449    }
450}
451
452#[derive(Default)]
453pub(super) enum EarlyDataState {
454    #[default]
455    New,
456    Accepted,
457}
458
459impl EarlyDataState {
460    fn accept(&mut self) {
461        *self = Self::Accepted;
462    }
463
464    fn was_accepted(&self) -> bool {
465        matches!(self, Self::Accepted)
466    }
467}