Skip to main content

rustls/conn/
handshake.rs

1//! Transport-generic handshake machinery.
2//!
3//! [`Accepted`] and [`VerifyPeerIdentity`] are public and generic over [`Transport`].
4//!
5//! The remaining public handshake types (`rustls::{NeedsInput, ClientHandshake,
6//! ServerHandshake}` and their `rustls::quic` counterparts) are thin shims over the types
7//! in this module.  The shims own the public signatures and documentation; the shared
8//! underlying logic lives here, parameterised by [`Transport`].
9
10use alloc::boxed::Box;
11use alloc::vec::Vec;
12use core::{fmt, mem};
13
14use super::{
15    Connection, NeedsInput, SideCommonOutput, SideData, StateMachine, VerifySidePeerIdentity,
16};
17use crate::client::{ClientSide, ClientState};
18use crate::common_state::{Protocol, maybe_send_fatal_alert};
19use crate::crypto::VerifiedIdentity;
20use crate::error::Error;
21use crate::msgs::ServerExtensionsInput;
22use crate::quic::{FromConn, Quic, QuicEvent, QuicOutput};
23use crate::server::{
24    ChooseConfig, ClientHello, ServerConfig, ServerHandshake, ServerSide, ServerState,
25};
26use crate::sync::Arc;
27use crate::tracing::trace;
28
29/// The states a server handshake can be in, for any transport.
30pub(crate) enum ServerNext<T: Transport> {
31    NeedsInput(Connection<ServerSide, T>),
32    ChooseConfig(Accepted<T>),
33    VerifyClientIdentity(VerifyPeerIdentity<ServerSide, T>),
34    Complete(Connection<ServerSide, T>),
35}
36
37impl<T: Transport> TryFrom<Connection<ServerSide, T>> for ServerNext<T> {
38    type Error = Error;
39
40    fn try_from(mut conn: Connection<ServerSide, T>) -> Result<Self, Error> {
41        const MISUSED: Error = Error::Unreachable("forgot to restore state");
42
43        Ok(match mem::replace(&mut conn.state, Err(MISUSED))? {
44            ServerState::ChooseConfig(choose_config) => Self::ChooseConfig(Accepted {
45                conn,
46                choose_config,
47            }),
48
49            ServerState::VerifyClientIdentity(verify_identity) => {
50                Self::VerifyClientIdentity(VerifyPeerIdentity {
51                    conn,
52                    verify_identity,
53                })
54            }
55
56            state if state.is_traffic() => {
57                conn.state = Ok(state);
58                Self::Complete(conn)
59            }
60
61            state => {
62                conn.state = Ok(state);
63                Self::NeedsInput(conn)
64            }
65        })
66    }
67}
68
69/// The states a client handshake can be in, for any transport.
70pub(crate) enum ClientNext<T: Transport> {
71    NeedsInput(Connection<ClientSide, T>),
72    VerifyServerIdentity(VerifyPeerIdentity<ClientSide, T>),
73    Complete(Connection<ClientSide, T>),
74}
75
76impl<T: Transport> TryFrom<Connection<ClientSide, T>> for ClientNext<T> {
77    type Error = Error;
78
79    fn try_from(mut conn: Connection<ClientSide, T>) -> Result<Self, Error> {
80        const MISUSED: Error = Error::Unreachable("forgot to restore state");
81
82        Ok(match mem::replace(&mut conn.state, Err(MISUSED))? {
83            ClientState::VerifyServerIdentity(verify_identity) => {
84                Self::VerifyServerIdentity(VerifyPeerIdentity {
85                    conn,
86                    verify_identity,
87                })
88            }
89
90            state if state.is_traffic() => {
91                conn.state = Ok(state);
92                Self::Complete(conn)
93            }
94
95            state => {
96                conn.state = Ok(state);
97                Self::NeedsInput(conn)
98            }
99        })
100    }
101}
102
103/// Represents that a `ClientHello` message has been received.
104///
105/// The handshake can be progressed by choosing a [`ServerConfig`] based on
106/// [`Self::client_hello()`] and providing it to [`Self::choose_config()`].
107pub struct Accepted<T: Transport> {
108    // invariant: `core.inner.state` is `Err(_)` and requires restoring
109    pub(crate) conn: Connection<ServerSide, T>,
110    choose_config: Box<ChooseConfig>,
111}
112
113impl<T: Transport> Accepted<T> {
114    /// Get the [`ClientHello`] for this connection.
115    pub fn client_hello(&self) -> ClientHello<'_> {
116        let ch = self.choose_config.client_hello();
117        trace!("Accepted::client_hello(): {ch:#?}");
118        ch
119    }
120
121    pub(crate) fn partial_choose_config(
122        self,
123        config: Arc<ServerConfig>,
124        exts: ServerExtensionsInput,
125        tls: &mut Vec<u8>,
126    ) -> Result<Connection<ServerSide, T>, Error> {
127        let Self {
128            mut conn,
129            choose_config,
130        } = self;
131
132        let result = conn.accepted(choose_config, exts, config, tls);
133
134        let send_path = &mut conn.common.send;
135
136        if let Err(err) = &result {
137            maybe_send_fatal_alert(send_path, err, tls)?;
138        }
139
140        result?;
141        Ok(conn)
142    }
143}
144
145impl Accepted<Tcp> {
146    /// Choose a [`ServerConfig`] to progress the handshake.
147    ///
148    /// Output to send to the peer is appended to `tls`.  Typically, this is the `ServerHello`,
149    /// but it may also be an `Alert` if an error is returned.
150    ///
151    /// Returns an error if configuration-dependent validation of the received `ClientHello` message fails.
152    pub fn choose_config(
153        self,
154        config: Arc<ServerConfig>,
155        tls: &mut Vec<u8>,
156    ) -> Result<ServerHandshake, Error> {
157        Ok(ServerHandshake::NeedsInput(NeedsInput(
158            self.partial_choose_config(config, ServerExtensionsInput::default(), tls)?,
159        )))
160    }
161}
162
163impl<T: Transport> fmt::Debug for Accepted<T> {
164    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
165        f.debug_struct("Accepted")
166            .finish_non_exhaustive()
167    }
168}
169
170/// The peer's presented identity must be verified.
171///
172/// The caller has three choices:
173///
174/// - Call [`Self::with_config()`].  This calls the configured verifier trait
175///   ([`ClientVerifier::verify_identity()`][] or [`ServerVerifier::verify_identity()`][])
176///   synchronously.
177///
178/// - Call [`Self::presented_identity()`] to obtain the peer's presented identity,
179///   verify that outside the library (perhaps asynchronously), and then continue the handshake with
180///   [`Self::continue_with()`].
181///
182///   If the verification fails, the error can be passed into [`Self::continue_with()`] to follow
183///   a uniform error handling path.
184///
185/// - Abandon the handshake by discarding this object.
186///
187/// The returned object is a further handshake state for this side.  Commonly this will
188/// contain a [`ServerHandshake::NeedsInput`][], [`ClientHandshake::NeedsInput`][],
189/// [`quic::ServerHandshake::NeedsInput`][] or [`quic::ClientHandshake::NeedsInput`][]
190/// which will accept and process further data.
191///
192/// [`ClientVerifier::verify_identity()`]: crate::verify::ClientVerifier::verify_identity
193/// [`ServerVerifier::verify_identity()`]: crate::verify::ServerVerifier::verify_identity
194/// [`ServerHandshake::NeedsInput`]: crate::server::ServerHandshake::NeedsInput
195/// [`ClientHandshake::NeedsInput`]: crate::client::ClientHandshake::NeedsInput
196/// [`quic::ServerHandshake::NeedsInput`]: crate::quic::ServerHandshake::NeedsInput
197/// [`quic::ClientHandshake::NeedsInput`]: crate::quic::ClientHandshake::NeedsInput
198pub struct VerifyPeerIdentity<Side: SideData, T: Transport> {
199    // invariant: `core.inner.state` is `Err(_)` and requires restoring
200    conn: Connection<Side, T>,
201    verify_identity: Box<dyn VerifySidePeerIdentity<Side>>,
202}
203
204impl<Side: SideData, T: Transport> VerifyPeerIdentity<Side, T> {
205    /// Inspect the identity that the peer has provided.
206    pub fn presented_identity(&self) -> Result<Side::PeerIdentity<'_>, Error> {
207        self.verify_identity
208            .presented_identity()
209    }
210}
211
212impl<Side: SideData> VerifyPeerIdentity<Side, Tcp> {
213    /// Progress the handshake by calling the pre-configured certificate verification trait.
214    pub fn with_config(self, tls: &mut Vec<u8>) -> Result<Side::Handshake, Error> {
215        let result = self
216            .verify_identity
217            .verify_with_config();
218        self.continue_with(result, tls)
219    }
220
221    /// Progress the handshake by incorporating the result of an external verification.
222    ///
223    /// Further data to send to the peer may be appended to `tls`.
224    ///
225    /// If `verification_result` is an error, this error is returned and the handshake terminates.
226    /// An alert may be appended to `tls` for sending to the peer.
227    pub fn continue_with(
228        self,
229        verification_result: Result<VerifiedIdentity<'static>, Error>,
230        tls: &mut Vec<u8>,
231    ) -> Result<Side::Handshake, Error> {
232        self.partial_continue_with(verification_result, tls)?
233            .into_handshake()
234    }
235}
236
237impl<Side: SideData> VerifyPeerIdentity<Side, Quic> {
238    /// Progress the handshake by calling the pre-configured certificate verification trait.
239    pub fn with_config(self, output: &mut Vec<QuicEvent>) -> Result<Side::QuicHandshake, Error> {
240        let result = self
241            .verify_identity
242            .verify_with_config();
243        self.continue_with(result, output)
244    }
245
246    /// Progress the handshake by incorporating the result of an external verification.
247    ///
248    /// If `verification_result` is an error, this error is returned and the handshake terminates.
249    ///
250    /// Events are appended to `output`.
251    pub fn continue_with(
252        self,
253        verification_result: Result<VerifiedIdentity<'static>, Error>,
254        output: &mut Vec<QuicEvent>,
255    ) -> Result<Side::QuicHandshake, Error> {
256        Side::QuicHandshake::from_conn(
257            self.partial_continue_with(verification_result, &mut Vec::new())?,
258            output,
259        )
260    }
261}
262
263impl<Side: SideData, T: Transport> VerifyPeerIdentity<Side, T> {
264    fn partial_continue_with(
265        self,
266        verification_result: Result<VerifiedIdentity<'static>, Error>,
267        tls: &mut Vec<u8>,
268    ) -> Result<Connection<Side, T>, Error> {
269        let Self {
270            mut conn,
271            verify_identity,
272        } = self;
273
274        let result = verification_result.and_then(|verified| {
275            verify_identity.continue_with(
276                verified,
277                &mut SideCommonOutput {
278                    side: &mut conn.side,
279                    quic: T::quic(&mut conn.transport),
280                    common: &mut conn.common,
281                    tls,
282                },
283            )
284        });
285
286        if let Err(err) = &result {
287            maybe_send_fatal_alert(&mut conn.common.send, err, tls)?;
288        }
289
290        conn.state = result;
291        Ok(conn)
292    }
293}
294
295impl<Side: SideData, T: Transport> fmt::Debug for VerifyPeerIdentity<Side, T> {
296    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
297        f.debug_struct("VerifyPeerIdentity")
298            .finish_non_exhaustive()
299    }
300}
301
302/// The aspects of a handshake that depend on the underlying transport.
303#[expect(private_bounds)]
304pub trait Transport: Sized + sealed::Transport {}
305
306pub(crate) mod sealed {
307    use super::QuicOutput;
308    use crate::Protocol;
309
310    pub(crate) trait Transport {
311        fn protocol(&self) -> Protocol;
312
313        /// The sink for QUIC-specific events.
314        fn quic(&mut self) -> Option<&mut dyn QuicOutput>;
315    }
316}
317
318/// TLS over TCP.
319#[expect(clippy::exhaustive_structs)]
320pub struct Tcp;
321
322impl Transport for Tcp {}
323
324impl sealed::Transport for Tcp {
325    fn protocol(&self) -> Protocol {
326        Protocol::Tcp
327    }
328
329    fn quic(&mut self) -> Option<&mut dyn QuicOutput> {
330        None
331    }
332}