Skip to main content

rustls/conn/
mod.rs

1use alloc::boxed::Box;
2use alloc::vec::Vec;
3use core::fmt::{self, Debug};
4use core::ops::{Deref, DerefMut};
5
6use kernel::KernelConnection;
7use pki_types::FipsStatus;
8
9use crate::common_state::{
10    CommonState, ConnectionOutput, ConnectionOutputs, Event, Output, OutputEvent,
11};
12use crate::crypto::cipher::{OutboundPlain, Payload};
13use crate::error::{ApiMisuse, Error};
14use crate::kernel::KernelState;
15use crate::msgs::{Delocator, Message, Random, ServerExtensionsInput};
16use crate::quic::QuicOutput;
17use crate::server::{ChooseConfig, ServerConfig, ServerSide};
18use crate::suites::{ExtractedSecrets, PartiallyExtractedSecrets};
19use crate::sync::Arc;
20use crate::tls13::key_schedule::KeyScheduleTrafficSend;
21
22// pub so that it can be re-exported from the crate root
23pub mod kernel;
24
25mod receive;
26pub(crate) use receive::{Input, MessageIter, ReceivePath, TrafficTemperCounters};
27pub use receive::{SliceInput, TlsInputBuffer, VecInput};
28
29mod send;
30pub(crate) use send::{SendOutput, SendPath};
31
32pub(crate) mod split;
33use split::SplitConnection;
34
35/// A trait generalizing over buffered client or server connections.
36pub trait Connection: Debug + Deref<Target = ConnectionOutputs> {
37    /// The side (client or server) that this type implements.
38    type Side: SideData;
39
40    /// Writes the application data from `plaintext` into TLS records and appends them to `tls`.
41    ///
42    /// This will fail if either the handshake is not complete yet (because we don't yet have the
43    /// keys to encrypt application data) or if the send path has been closed by sending a
44    /// `close_notify` alert.
45    fn write_tls(&mut self, plaintext: OutboundPlain<'_>, tls: &mut Vec<u8>) -> Result<(), Error>;
46
47    /// Returns true if the caller should call [`Self::process_new_packets()`] as soon as possible.
48    fn wants_read(&self) -> bool;
49
50    /// Build a [`MessageHandler`] to process messages from the input buffer.
51    fn process_new_packets<'a, 'm>(
52        &'a mut self,
53        input: &'m mut dyn TlsInputBuffer,
54        tls: &'a mut Vec<u8>,
55    ) -> MessageHandler<'a, 'm, Self::Side>;
56
57    /// Returns an object that can derive key material from the agreed connection secrets.
58    ///
59    /// See [RFC 5705][] for more details on what this is for.
60    ///
61    /// This function can be called at most once per connection.
62    ///
63    /// This function will error:
64    ///
65    /// - if called prior to the handshake completing; (check with
66    ///   [`Self::is_handshaking()`] first).
67    /// - if called more than once per connection.
68    ///
69    /// [RFC 5705]: https://datatracker.ietf.org/doc/html/rfc5705
70    fn exporter(&mut self) -> Result<KeyingMaterialExporter, Error>;
71
72    /// Extract secrets, so they can be used when configuring kTLS, for example.
73    ///
74    /// Should be used with care as it exposes secret key material.
75    fn dangerous_extract_secrets(self) -> Result<ExtractedSecrets, Error>;
76
77    /// Sends a TLS1.3 `key_update` message into `tls` to refresh a connection's keys.
78    ///
79    /// The main reason to call this manually is to roll keys when it is known
80    /// a connection will be idle for a long period.
81    ///
82    /// rustls implicitly and automatically refreshes traffic keys when needed
83    /// according to the selected cipher suite's cryptographic constraints.  There
84    /// is therefore no need to call this manually to avoid cryptographic keys
85    /// "wearing out".
86    ///
87    /// This call refreshes our encryption keys. Once the peer receives the message,
88    /// it refreshes _its_ encryption and decryption keys and sends a response.
89    /// Once we receive that response, we refresh our decryption keys to match.
90    /// At the end of this process, keys in both directions have been refreshed.
91    ///
92    /// This fails with [`Error::HandshakeNotComplete`] if called before the initial
93    /// handshake is complete, or if a version prior to TLS1.3 is negotiated.
94    ///
95    /// # Usage advice
96    /// Note that other implementations (including rustls) may enforce limits on
97    /// the number of `key_update` messages allowed on a given connection to prevent
98    /// denial of service.  Therefore, this should be called sparingly.
99    ///
100    /// rustls only allows one outstanding request at a time; this function succeeds
101    /// but sends nothing if a request is already in-flight.
102    fn refresh_traffic_keys(&mut self, tls: &mut Vec<u8>) -> Result<(), Error>;
103
104    /// Writes a `close_notify` warning alert into `tls`.
105    ///
106    /// This informs the peer that the connection is being closed.
107    ///
108    /// Does nothing if any `close_notify` or fatal alert was already sent.
109    fn send_close_notify(&mut self, tls: &mut Vec<u8>);
110
111    /// Returns true if the connection is currently performing the TLS handshake.
112    ///
113    /// During this time, [`Self::write_tls()`] will return an error.
114    fn is_handshaking(&self) -> bool;
115
116    /// Return the FIPS validation status of the connection.
117    ///
118    /// This is different from [`CryptoProvider::fips()`][]:
119    /// it is concerned only with cryptography, whereas this _also_ covers TLS-level
120    /// configuration that NIST recommends, as well as ECH HPKE suites if applicable.
121    ///
122    /// [`CryptoProvider::fips()`]: crate::crypto::CryptoProvider::fips()
123    fn fips(&self) -> FipsStatus;
124}
125
126/// TLS connection state with side-specific data (`Side`).
127///
128/// This is one of the core abstractions of the rustls API. It represents a single connection
129/// to a peer, and holds all the state associated with that connection. Note that it does
130/// not hold any IO objects: the application is responsible for reading and writing TLS records.
131/// If you want an object that does hold IO objects, see `rustls_util::Stream` and
132/// `rustls_util::StreamOwned`.
133///
134/// This object is generic over the `Side` type parameter, which must implement the marker trait
135/// [`SideData`]. This is used to store side-specific data.
136pub(crate) struct ConnectionCommon<Side: SideData> {
137    pub(crate) state: Result<Side::State, Error>,
138    pub(crate) side: Side::Data,
139    pub(crate) common: CommonState,
140}
141
142impl<Side: SideData> ConnectionCommon<Side> {
143    pub(crate) fn new(state: Side::State, side: Side::Data, common: CommonState) -> Self {
144        Self {
145            state: Ok(state),
146            side,
147            common,
148        }
149    }
150
151    pub(crate) fn process_new_packets<'a, 'm>(
152        &'a mut self,
153        input: &'m mut dyn TlsInputBuffer,
154        tls: &'a mut Vec<u8>,
155    ) -> MessageHandler<'a, 'm, Side> {
156        MessageHandler::new(input, tls, self)
157    }
158
159    pub(crate) fn write_tls(
160        &mut self,
161        plaintext: OutboundPlain<'_>,
162        tls: &mut Vec<u8>,
163    ) -> Result<(), Error> {
164        if plaintext.is_empty() {
165            return Ok(());
166        } else if !self
167            .common
168            .send
169            .may_send_application_data
170        {
171            return Err(ApiMisuse::WriteTlsBeforeHandshakeComplete.into());
172        } else if self.common.send.has_sent_close_notify {
173            return Err(ApiMisuse::WriteTlsAfterSendPathClosed.into());
174        }
175
176        self.common
177            .send
178            .send_appdata_encrypt(plaintext, tls);
179
180        Ok(())
181    }
182
183    pub(crate) fn wants_read(&self) -> bool {
184        // We want to read more data all the time, except after the peer has sent us
185        // a close notification.
186        !self
187            .common
188            .recv
189            .has_received_close_notify
190    }
191
192    pub(crate) fn refresh_traffic_keys(&mut self, tls: &mut Vec<u8>) -> Result<(), Error> {
193        self.common
194            .send
195            .refresh_traffic_keys(tls)
196    }
197
198    pub(crate) fn split(self) -> Result<SplitConnection<Side>, Error> {
199        // `SplitConnection` cannot be used to progress a handshake.
200        if self.is_handshaking() {
201            return Err(ApiMisuse::SplitDuringHandshake.into());
202        }
203
204        SplitConnection::try_from(self)
205    }
206
207    /// Extract secrets, so they can be used when configuring kTLS, for example.
208    /// Should be used with care as it exposes secret key material.
209    pub(crate) fn dangerous_extract_secrets(self) -> Result<ExtractedSecrets, Error> {
210        Ok(self
211            .dangerous_into_kernel_connection()?
212            .0)
213    }
214
215    pub(crate) fn dangerous_into_kernel_connection(
216        mut self,
217    ) -> Result<(ExtractedSecrets, KernelConnection<Side>), Error> {
218        if self.common.is_handshaking() {
219            return Err(Error::HandshakeNotComplete);
220        }
221        Self::from_parts_into_kernel_connection(
222            &mut self.common.send,
223            self.common.recv,
224            self.common.outputs,
225            self.state?,
226        )
227    }
228
229    pub(crate) fn from_parts_into_kernel_connection(
230        send: &mut SendPath,
231        recv: ReceivePath,
232        outputs: ConnectionOutputs,
233        state: Side::State,
234    ) -> Result<(ExtractedSecrets, KernelConnection<Side>), Error> {
235        let read_seq = recv.decrypt_state.read_seq();
236        let write_seq = send.encrypt_state.write_seq();
237
238        let tls13_key_schedule = send.tls13_key_schedule.take();
239
240        let (secrets, state) = state.into_external_state(&tls13_key_schedule)?;
241        let secrets = ExtractedSecrets {
242            tx: (write_seq, secrets.tx),
243            rx: (read_seq, secrets.rx),
244        };
245        let external = KernelConnection::new(state, outputs, tls13_key_schedule)?;
246
247        Ok((secrets, external))
248    }
249
250    pub(crate) fn exporter(&mut self) -> Result<KeyingMaterialExporter, Error> {
251        match self.common.exporter.take() {
252            Some(inner) => Ok(KeyingMaterialExporter { inner }),
253            None if self.common.is_handshaking() => Err(Error::HandshakeNotComplete),
254            None => Err(ApiMisuse::ExporterAlreadyUsed.into()),
255        }
256    }
257}
258
259impl ConnectionCommon<ServerSide> {
260    pub(crate) fn accepted(
261        &mut self,
262        choose: Box<ChooseConfig>,
263        exts: ServerExtensionsInput,
264        quic: Option<&mut dyn QuicOutput>,
265        config: Arc<ServerConfig>,
266        tls: &mut Vec<u8>,
267    ) -> Result<(), Error> {
268        self.common
269            .send
270            .set_max_fragment_size(config.max_fragment_size)?;
271        self.common.fips = config.fips();
272
273        let mut output = SideCommonOutput {
274            side: &mut self.side,
275            quic,
276            common: &mut self.common,
277            tls,
278        };
279
280        self.state = Ok(choose.use_config(config, exts, &mut output)?);
281        Ok(())
282    }
283}
284
285impl<Side: SideData> Deref for ConnectionCommon<Side> {
286    type Target = CommonState;
287
288    fn deref(&self) -> &Self::Target {
289        &self.common
290    }
291}
292
293impl<Side: SideData> DerefMut for ConnectionCommon<Side> {
294    fn deref_mut(&mut self) -> &mut Self::Target {
295        &mut self.common
296    }
297}
298
299/// Driver for handling messages from the [`TlsInputBuffer`].
300///
301/// Must be driven to completion to make progress, by calling either [`Self::handle_all()`] or
302/// repeatedly calling [`Self::next_payload()`] until it returns `None`.
303///
304/// Backpressure is provided by the [`TlsInputBuffer`] implementation. When using a [`VecInput`]
305/// buffer, [`VecInput::read()`] will not ingest more data once the internal buffer is full.
306#[must_use]
307pub struct MessageHandler<'a, 'm, Side: SideData> {
308    iter: MessageIter<'a, 'm, Side, SendPath>,
309    done: bool,
310}
311
312impl<'a, 'm, Side: SideData> MessageHandler<'a, 'm, Side> {
313    pub(crate) fn new(
314        input: &'m mut dyn TlsInputBuffer,
315        tls: &'a mut Vec<u8>,
316        core: &'a mut ConnectionCommon<Side>,
317    ) -> Self {
318        Self {
319            iter: MessageIter::new(input, tls, None, core),
320            done: false,
321        }
322    }
323}
324
325impl<'a, 'm, Side: SideData> MessageHandler<'a, 'm, Side> {
326    /// Handles all complete messages from the input buffer.
327    ///
328    /// Writes any plaintext application data from the input into `buf`, and returns the I/O
329    /// state of the connection after processing the last message. If an error is returned,
330    /// the connection is in a fatal error state and no further progress can be made. After
331    /// an error is received from this function, you should not continue to fill up the buffer.
332    ///
333    /// However, you may call the other methods on the connection, including
334    /// [`Connection::send_close_notify()`]. Any alert produced by the error will have
335    /// been appended to the `tls` buffer; most likely you will want to send that data
336    /// to the peer and then close the underlying connection.
337    pub fn handle_all(mut self, buf: &mut Vec<u8>) -> Result<IoState, Error> {
338        while let Some(result) = self.next_payload() {
339            buf.extend_from_slice(result?.bytes());
340        }
341
342        Ok(self.state())
343    }
344
345    /// Yields the first payload of plaintext application data from the input buffer.
346    ///
347    /// Should be called repeatedly until it returns `None`, at which point the input buffer no
348    /// longer contains any complete messages and should be refilled by the application.
349    pub fn next_payload(&mut self) -> Option<Result<Payload<'_>, Error>> {
350        if self.done {
351            return None;
352        }
353
354        let Some(result) = self.iter.next() else {
355            self.done = true;
356            return None;
357        };
358
359        let payload = match result {
360            Ok(payload) => payload,
361            Err(err) => {
362                self.done = true;
363                return Some(Err(err));
364            }
365        };
366
367        Some(Ok(
368            payload.reborrow(&Delocator::new(self.iter.input.slice_mut()))
369        ))
370    }
371
372    /// The I/O state of the connection after processing the last message.
373    pub fn state(self) -> IoState {
374        IoState::new(self.iter.recv)
375    }
376}
377
378impl<'a, 'm, Side: SideData + private::Side> Drop for MessageHandler<'a, 'm, Side> {
379    fn drop(&mut self) {
380        let MessageIter { input, recv, .. } = &mut self.iter;
381        input.discard(recv.deframer.take_discard());
382    }
383}
384
385impl<S: SideData> Debug for MessageHandler<'_, '_, S> {
386    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
387        f.debug_struct("MessageHandler")
388            .field("done", &self.done)
389            .finish_non_exhaustive()
390    }
391}
392
393/// An object of this type can export keying material.
394pub struct KeyingMaterialExporter {
395    pub(crate) inner: Box<dyn Exporter>,
396}
397
398impl KeyingMaterialExporter {
399    /// Derives key material from the agreed connection secrets.
400    ///
401    /// This function fills in `output` with `output.len()` bytes of key
402    /// material derived from a master connection secret using `label`
403    /// and `context` for diversification. Ownership of the buffer is taken
404    /// by the function and returned via the Ok result to ensure no key
405    /// material leaks if the function fails.
406    ///
407    /// See [RFC 5705][] for more details on what this does and is for.  In
408    /// other libraries this is often named `SSL_export_keying_material()`
409    /// or `SslExportKeyingMaterial()`.
410    ///
411    /// This function is not meaningful if `output.len()` is zero and will
412    /// return an error in that case.
413    ///
414    /// [RFC 5705]: https://datatracker.ietf.org/doc/html/rfc5705
415    pub fn derive<T: AsMut<[u8]>>(
416        &self,
417        label: &[u8],
418        context: Option<&[u8]>,
419        mut output: T,
420    ) -> Result<T, Error> {
421        if output.as_mut().is_empty() {
422            return Err(ApiMisuse::ExporterOutputZeroLength.into());
423        }
424
425        self.inner
426            .derive(label, context, output.as_mut())
427            .map(|_| output)
428    }
429}
430
431impl Debug for KeyingMaterialExporter {
432    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
433        f.debug_struct("KeyingMaterialExporter")
434            .finish_non_exhaustive()
435    }
436}
437
438/// This trait is for any object that can export keying material.
439///
440/// The terminology comes from [RFC 5705](https://datatracker.ietf.org/doc/html/rfc5705)
441/// but doesn't really involve "exporting" key material (in the usual meaning of "export"
442/// -- of moving an artifact from one domain to another) but is best thought of as key
443/// diversification using an existing secret.  That secret is implicit in this interface,
444/// so is assumed to be held by `self`. The secret should be zeroized in `drop()`.
445///
446/// There are several such internal implementations, depending on the context
447/// and protocol version.
448pub(crate) trait Exporter: Send + Sync {
449    /// Fills in `output` with derived keying material.
450    ///
451    /// This is deterministic depending on a base secret (implicit in `self`),
452    /// plus the `label` and `context` values.
453    ///
454    /// Must fill in `output` entirely, or return an error.
455    fn derive(&self, label: &[u8], context: Option<&[u8]>, output: &mut [u8]) -> Result<(), Error>;
456}
457
458#[derive(Debug)]
459pub(crate) struct ConnectionRandoms {
460    pub(crate) client: [u8; 32],
461    pub(crate) server: [u8; 32],
462}
463
464impl ConnectionRandoms {
465    pub(crate) fn new(client: Random, server: Random) -> Self {
466        Self {
467            client: client.0,
468            server: server.0,
469        }
470    }
471}
472
473/// Values of this structure are returned from [`Connection::process_new_packets()`]
474/// and tell the caller the current I/O state of the TLS connection.
475#[derive(Debug, Eq, PartialEq)]
476pub struct IoState {
477    peer_has_closed: bool,
478}
479
480impl IoState {
481    pub(crate) fn new(recv: &ReceivePath) -> Self {
482        Self {
483            peer_has_closed: recv.has_received_close_notify,
484        }
485    }
486
487    /// True if the peer has sent us a close_notify alert.
488    ///
489    /// This is the TLS mechanism to securely half-close a TLS connection, and signifies that
490    /// the peer will not send any further data on this connection.
491    ///
492    /// This is also signalled via returning `Ok(0)` from [`std::io::Read`], after all the
493    /// received bytes have been retrieved.
494    pub fn peer_has_closed(&self) -> bool {
495        self.peer_has_closed
496    }
497}
498
499pub(crate) struct SideCommonOutput<'a, 'q> {
500    pub(crate) side: &'a mut dyn SideOutput,
501    pub(crate) quic: Option<&'q mut dyn QuicOutput>,
502    pub(crate) common: &'a mut CommonState,
503    pub(crate) tls: &'a mut Vec<u8>,
504}
505
506impl<'q> Output<'_> for SideCommonOutput<'_, 'q> {
507    fn emit(&mut self, ev: Event<'_>) {
508        self.side.emit(ev);
509    }
510
511    fn output(&mut self, ev: OutputEvent<'_>) {
512        if let OutputEvent::ProtocolVersion(ver) = ev {
513            self.common.recv.negotiated_version = Some(ver);
514            self.common.send.negotiated_version(ver);
515        }
516        self.common.outputs.handle(ev);
517    }
518
519    fn send_msg(&mut self, m: Message<'_>, must_encrypt: bool) {
520        match self.quic() {
521            Some(quic) => quic.send_msg(m, must_encrypt),
522            None => self
523                .common
524                .send
525                .send_msg(m, must_encrypt, self.tls),
526        }
527    }
528
529    fn quic(&mut self) -> Option<&mut dyn QuicOutput> {
530        match self.quic.as_mut() {
531            Some(q) => Some(&mut **q),
532            None => None,
533        }
534    }
535
536    fn start_traffic(&mut self) {
537        self.common
538            .recv
539            .may_receive_application_data = true;
540        self.common
541            .send
542            .start_outgoing_traffic();
543    }
544
545    fn receive(&mut self) -> &mut ReceivePath {
546        &mut self.common.recv
547    }
548
549    fn send(&mut self) -> &mut dyn SendOutput {
550        &mut self.common.send
551    }
552}
553
554/// Data specific to the peer's side (client or server).
555#[expect(private_bounds)]
556pub trait SideData: private::Side {}
557
558pub(crate) mod private {
559    use super::*;
560
561    pub(crate) trait Side: Debug {
562        /// Data storage type.
563        type Data: SideOutput;
564        /// State machine type.
565        type State: StateMachine;
566    }
567
568    pub(crate) trait SideOutput {
569        fn emit(&mut self, ev: Event<'_>);
570    }
571}
572
573use private::SideOutput;
574
575pub(crate) trait StateMachine: Sized {
576    fn handle<'m>(self, input: Input<'m>, output: &mut dyn Output<'m>) -> Result<Self, Error>;
577    fn wants_input(&self) -> bool;
578    fn is_traffic(&self) -> bool;
579    fn handle_decrypt_error(&mut self);
580    fn into_external_state(
581        self,
582        send_keys: &Option<Box<KeyScheduleTrafficSend>>,
583    ) -> Result<(PartiallyExtractedSecrets, Box<dyn KernelState + 'static>), Error>;
584}