Skip to main content

rustls/conn/
split.rs

1use alloc::boxed::Box;
2use alloc::vec::Vec;
3use core::fmt;
4use core::ops::Range;
5use std::sync::MutexGuard;
6
7use super::kernel::KernelConnection;
8use super::receive::{Discard, JoinOutput};
9use super::{
10    Connection, ConnectionOutputs, DataKind, Encrypter, MessageIter, MessageIterMode, ReceivePath,
11    SendOutput, SendPath, SideData, Tcp, TlsInputBuffer,
12};
13use crate::client::ClientSide;
14use crate::common_state::UnborrowedPayload;
15use crate::crypto::cipher::OutboundPlain;
16use crate::enums::ProtocolVersion;
17use crate::error::{AlertDescription, ApiMisuse, Error};
18use crate::lock::Mutex;
19use crate::msgs::{AlertLevel, Delocator, Message};
20use crate::suites::ExtractedSecrets;
21use crate::sync::Arc;
22use crate::tls13::key_schedule::KeyScheduleTrafficSend;
23
24/// A post-handshake connection which has been split by direction.
25///
26/// Typically you will immediately destructure this type, and give the components
27/// to different threads/handlers to progress separately.
28#[expect(clippy::exhaustive_structs)]
29#[derive(Debug)]
30pub struct SplitConnection<Side: SideData> {
31    /// The ability to encrypt data to be sent.
32    pub send: SendTraffic,
33    /// The ability to decrypt received data.
34    pub receive: ReceiveTraffic<Side>,
35    /// Facts about the connection established during the handshake.
36    pub outputs: ConnectionOutputs,
37    /// Role-specific facts about the connection established during the handshake.
38    ///
39    /// This is [`ClientSide`] for clients and [`ServerSide`] for servers.
40    ///
41    /// [`ServerSide`]: crate::server::ServerSide
42    pub side_outputs: Side,
43}
44
45impl<Side: SideData> SplitConnection<Side> {
46    /// Extract secrets and a [`KernelConnection`], so they can be used when
47    /// configuring kTLS, for example.
48    ///
49    /// Should be used with care as it exposes secret key material.
50    ///
51    /// All TLS data previously written into caller-provided buffers must be sent to the peer before
52    /// calling this function.
53    ///
54    /// The returned [`KernelConnection`] continues to own the connection's
55    /// secrets, so it can compute new traffic secrets on key update and (for
56    /// client connections) accept session tickets.  See the [`kernel`] module
57    /// documentation for the details.
58    ///
59    /// This fails if the connection was not made with [`enable_secret_extraction`] set,
60    /// or if the send half has pending data queued by the receive half (see
61    /// [`ReceiveTrafficState::FlushSender`]). Flush any pending data with
62    /// [`SendTraffic::write()`] before calling this.
63    ///
64    /// [`kernel`]: crate::kernel
65    /// [`enable_secret_extraction`]: crate::ClientConfig::enable_secret_extraction
66    pub fn dangerous_into_kernel_connection(
67        self,
68    ) -> Result<(ExtractedSecrets, KernelConnection<Side>), Error> {
69        let Self {
70            send,
71            receive,
72            outputs,
73            side_outputs: _,
74        } = self;
75
76        // drop our handle on the send path, so `receive` holds the only one.
77        drop(send);
78
79        let ReceiveTraffic {
80            state, recv, send, ..
81        } = receive;
82
83        let send = Arc::into_inner(send)
84            .unwrap()
85            .into_inner()
86            .unwrap();
87
88        // pending data has consumed send sequence numbers so discarding it here
89        // would leave the extracted secrets ahead of what the peer receives.
90        if send.pending_send_data() {
91            return Err(ApiMisuse::KernelConnectionWithPendingSendData.into());
92        }
93
94        Connection::<Side, Tcp>::from_parts_into_kernel_connection(send.send, recv, outputs, state)
95    }
96}
97
98impl<Side: SideData> TryFrom<Connection<Side, Tcp>> for SplitConnection<Side> {
99    type Error = Error;
100
101    fn try_from(conn: Connection<Side, Tcp>) -> Result<Self, Error> {
102        // `SplitConnection` cannot be used to progress a handshake.
103        if conn.is_handshaking() {
104            return Err(ApiMisuse::SplitDuringHandshake.into());
105        }
106
107        let send = Arc::new(Mutex::new(SendInner {
108            send: conn.common.send,
109            aside_buffer: Vec::new(),
110        }));
111        let state = conn.state?;
112
113        Ok(Self {
114            send: SendTraffic(send.clone()),
115            receive: ReceiveTraffic {
116                state,
117                recv: conn.common.recv,
118                send,
119                pending_flush_sender: false,
120            },
121            outputs: conn.common.outputs,
122            side_outputs: conn.side,
123        })
124    }
125}
126
127/// The send-side of a connection, after a successful handshake.
128///
129/// You can use this object to send data to the peer.
130pub struct SendTraffic(pub(super) Arc<Mutex<SendInner>>);
131
132impl SendTraffic {
133    /// Write application data to the peer.
134    ///
135    /// The TLS data to send to the peer is written into `tls`. This data should then be
136    /// communicated to the peer.
137    ///
138    /// When you need to handle a [`ReceiveTrafficState::FlushSender`] state, you can call this
139    /// method with [`OutboundPlain::new_empty()`] to flush any pending TLS data to the peer.
140    ///
141    /// See [`Connection::write()`][crate::Connection::write] for the conditions under which
142    /// this fails.
143    pub fn write(
144        &mut self,
145        application_data: OutboundPlain<'_>,
146        tls: &mut Vec<u8>,
147    ) -> Result<(), Error> {
148        let mut inner = self.0.lock().unwrap();
149        inner.pump(tls);
150        inner
151            .send
152            .send_appdata_encrypt(DataKind::Traffic(application_data), tls)
153            .map(|_| ())
154    }
155
156    /// Conclude sending traffic by sending a `close_notify` alert.
157    ///
158    /// The alert is written into `tls` along with any pending data.
159    /// This data should then be communicated to the peer.
160    ///
161    /// This is the final possible operation with a [`SendTraffic`].
162    pub fn close(self, tls: &mut Vec<u8>) -> Result<(), Error> {
163        let mut inner = self.0.lock().unwrap();
164        inner.pump(tls);
165        inner.send.send_close_notify(tls)
166    }
167
168    /// Writes a TLS 1.3 `key_update` message into `tls` to refresh a connection's keys.
169    ///
170    /// The main reason to call this manually is to roll keys when it is known
171    /// a connection will be idle for a long period.
172    ///
173    /// rustls implicitly and automatically refreshes traffic keys when needed
174    /// according to the selected cipher suite's cryptographic constraints. There
175    /// is therefore no need to call this manually to avoid cryptographic keys
176    /// "wearing out".
177    ///
178    /// This call refreshes our encryption keys. Once the peer receives the message,
179    /// it refreshes _its_ encryption and decryption keys and sends a response.
180    /// Once we receive that response, we refresh our decryption keys to match.
181    /// At the end of this process, keys in both directions have been refreshed.
182    ///
183    /// This returns an error if a version prior to TLS1.3 is negotiated.
184    ///
185    /// # Usage advice
186    /// Note that other implementations (including rustls) may enforce limits on
187    /// the number of `key_update` messages allowed on a given connection to prevent
188    /// denial of service. Therefore, this should be called sparingly.
189    ///
190    /// rustls only allows one outstanding request at a time; this function succeeds
191    /// but sends nothing if a request is already in-flight.
192    pub fn refresh_traffic_keys(&mut self, tls: &mut Vec<u8>) -> Result<(), Error> {
193        let mut inner = self.0.lock().unwrap();
194        inner.pump(tls);
195        inner.send.refresh_traffic_keys(tls)
196    }
197}
198
199impl fmt::Debug for SendTraffic {
200    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
201        f.debug_tuple("SendTraffic")
202            .finish_non_exhaustive()
203    }
204}
205
206pub(super) struct SendInner {
207    send: SendPath,
208    aside_buffer: Vec<u8>,
209}
210
211impl SendInner {
212    fn pump(&mut self, tls: &mut Vec<u8>) {
213        tls.extend_from_slice(&self.aside_buffer);
214        self.aside_buffer.clear();
215    }
216
217    fn pending_send_data(&self) -> bool {
218        !self.aside_buffer.is_empty() || self.send.has_queued_key_update()
219    }
220
221    fn send_alert(&mut self, level: AlertLevel, desc: AlertDescription) -> Result<(), Error> {
222        self.send
223            .send_alert(level, desc, &mut self.aside_buffer)
224    }
225
226    fn send_msg(&mut self, m: Message<'_>, must_encrypt: bool) -> Result<(), Error> {
227        self.send
228            .send_msg(m, must_encrypt, &mut self.aside_buffer)
229    }
230}
231
232/// The receive-side of a connection, after a successful handshake.
233///
234/// You can use this object to receive data from the peer.
235pub struct ReceiveTraffic<Side: SideData> {
236    pub(crate) state: Side::State,
237    pub(crate) recv: ReceivePath,
238    pub(super) send: Arc<Mutex<SendInner>>,
239    pub(crate) pending_flush_sender: bool,
240}
241
242impl<Side: SideData> ReceiveTraffic<Side> {
243    /// Receive application data from the peer.
244    ///
245    /// `input` is an instance of the receive buffer abstraction containing
246    /// TLS-protected data received from the peer.
247    ///
248    /// A [`ReceiveTrafficState`] is returned on success.
249    ///
250    /// An error from this function permanently breaks the ability to receive
251    /// data from the peer. The error may be accompanied by a TLS alert,
252    /// which is sent through the associated [`SendTraffic`].  Callers should
253    /// treat errors received from this function in the same way as
254    /// [`ReceiveTrafficState::FlushSender`] for this reason.
255    pub fn read<'a>(
256        self,
257        input: &'a mut impl TlsInputBuffer,
258    ) -> Result<ReceiveTrafficState<'a, Side>, Error> {
259        let Self {
260            state,
261            mut recv,
262            send,
263            mut pending_flush_sender,
264        } = self;
265
266        let mut tls_unused = Vec::new();
267        let mut send_adapter = SendAdapter::Unlocked(&send);
268        let mut state = Ok(state);
269        let output = JoinOutput {
270            outputs: &mut Discard,
271            quic: None,
272            send: &mut send_adapter,
273            side: &mut Discard,
274        };
275
276        let mut iter = MessageIter::<Side, _>::receive(
277            input,
278            &mut tls_unused,
279            &mut state,
280            &mut recv,
281            output,
282            MessageIterMode::All,
283        );
284        let received_plain = match iter.next(false) {
285            Some(Ok(payload)) => Some(payload),
286            Some(Err(error)) => return Err(error),
287            None => None,
288        };
289        debug_assert!(tls_unused.is_empty());
290
291        // nb. state consumed only on error.
292        let state = state.unwrap();
293
294        if let Some(unborrowed) = received_plain {
295            let pending_discard = recv.deframer.take_discard();
296            let UnborrowedPayload::Unborrowed(range) = unborrowed else {
297                return Err(Error::Unreachable("decrypted data should be borrowed"));
298            };
299
300            if let SendAdapter::Locked { send_required, .. } = send_adapter {
301                pending_flush_sender |= send_required;
302            }
303
304            drop(send_adapter);
305            return Ok(ReceiveTrafficState::Available(ReceivedApplicationData {
306                range,
307                input,
308                pending_discard,
309                rt: Self {
310                    state,
311                    recv,
312                    send,
313                    pending_flush_sender,
314                },
315            }));
316        }
317
318        input.discard(recv.deframer.take_discard());
319
320        // `SendAdapter` records whether a send-side action may be needed after the above
321        // receive-side processing.  If the sender was not locked no change could be made to it.
322        if let SendAdapter::Locked { send_required, .. } = send_adapter {
323            pending_flush_sender |= send_required;
324        }
325
326        drop(send_adapter);
327
328        let mut rt = Self {
329            state,
330            recv,
331            send,
332            pending_flush_sender,
333        };
334
335        if core::mem::take(&mut rt.pending_flush_sender) {
336            return Ok(ReceiveTrafficState::FlushSender(FlushSender { rt }));
337        }
338
339        Ok(match rt.recv.has_received_close_notify {
340            true => ReceiveTrafficState::CloseNotify,
341            false => ReceiveTrafficState::ReadMore(rt),
342        })
343    }
344}
345
346impl ReceiveTraffic<ClientSide> {
347    /// Returns the number of TLS1.3 tickets that have been received.
348    pub fn tls13_tickets_received(&self) -> u32 {
349        self.recv.tls13_tickets_received
350    }
351}
352
353impl<Side: SideData> fmt::Debug for ReceiveTraffic<Side> {
354    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
355        f.debug_struct("ReceiveTraffic")
356            .finish_non_exhaustive()
357    }
358}
359
360/// A state machine that cycles between requiring further received TLS data
361/// and discharging received application data.
362///
363/// Each call to [`ReceiveTraffic::read()`] returns one of these states, and each
364/// non-terminal state lets you obtain the next one: [`ReadMore`] by supplying more
365/// input and calling [`read()`] again, and [`FlushSender`] / [`Available`]
366/// through their `into_next()` methods. [`CloseNotify`] is terminal.
367///
368/// ```text
369///            ╭────────────────╮
370///   ╭───────▶│ ReceiveTraffic │
371///   │        ╰───────┬────────╯
372/// ReadMore           │ read(&mut input)
373///   │                ▼
374///   ╰────╭───────────────────────╮
375///        │  ReceiveTrafficState  │──── CloseNotify ────▶ (terminal)
376///   ╭───▶╰──┬────────────────────╯
377///   │       │              │
378///   │  FlushSender      Available
379///   │  .into_next()    .into_next()
380///   │       │              │
381///   ╰───────┴──────────────╯
382/// ```
383///
384/// - [`ReadMore`]: more TLS input is required. The variant holds the
385///   `ReceiveTraffic`; collect more input and call [`read()`] on it again.
386/// - [`FlushSender`]: receiving may have produced data to send. Make a note to
387///   perform IO with the matching [`SendTraffic`], and then call
388///   [`FlushSender::into_next()`] for the next state.
389/// - [`Available`]: application data was received. Read it via
390///   [`ReceivedApplicationData::data()`], then call
391///   [`ReceivedApplicationData::into_next()`]: this discards the consumed input
392///   and returns the next state.
393/// - [`CloseNotify`]: the peer closed the receive direction cleanly. Terminal.
394///
395/// [`read()`]: ReceiveTraffic::read
396/// [`ReadMore`]: ReceiveTrafficState::ReadMore
397/// [`FlushSender`]: ReceiveTrafficState::FlushSender
398/// [`Available`]: ReceiveTrafficState::Available
399/// [`CloseNotify`]: ReceiveTrafficState::CloseNotify
400#[expect(clippy::exhaustive_enums)]
401pub enum ReceiveTrafficState<'a, Side: SideData> {
402    /// More input is required.
403    ///
404    /// Collect it into your input buffer, and then call [`ReceiveTraffic::read()`] again.
405    ReadMore(ReceiveTraffic<Side>),
406
407    /// The sender may have new data to send.
408    FlushSender(FlushSender<Side>),
409
410    /// Some application data has been received.
411    Available(ReceivedApplicationData<'a, Side>),
412
413    /// We received a `close_notify` alert from the peer.
414    ///
415    /// This means the receive path is closed cleanly.
416    CloseNotify,
417}
418
419impl<Side: SideData> fmt::Debug for ReceiveTrafficState<'_, Side> {
420    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
421        match self {
422            Self::ReadMore(_) => f
423                .debug_tuple("ReadMore")
424                .finish_non_exhaustive(),
425            Self::FlushSender(_) => f
426                .debug_tuple("FlushSender")
427                .finish_non_exhaustive(),
428            Self::Available(_) => f
429                .debug_tuple("Available")
430                .finish_non_exhaustive(),
431            Self::CloseNotify => write!(f, "CloseNotify"),
432        }
433    }
434}
435
436/// Received application data.
437pub struct ReceivedApplicationData<'a, Side: SideData> {
438    /// The source buffer for the data.
439    input: &'a mut dyn TlsInputBuffer,
440
441    /// The span within the `received_tls` buffer holding the received data.
442    range: Range<usize>,
443
444    /// How many bytes on the front of the original input buffer are associated
445    /// with this data.
446    ///
447    /// This value is added to the discard count of the original input
448    /// buffer via [`TlsInputBuffer::discard()`].
449    pending_discard: usize,
450
451    rt: ReceiveTraffic<Side>,
452}
453
454impl<Side: SideData> ReceivedApplicationData<'_, Side> {
455    /// Return the application data bytes.
456    pub fn data(&mut self) -> &[u8] {
457        Delocator::new(self.input.slice_mut()).slice_from_range(&self.range)
458    }
459
460    /// Finish processing this received data.
461    ///
462    /// This acts upon the source buffer (used with the [`ReceiveTraffic::read()`] call) to
463    /// discard the received data.
464    ///
465    /// Returns the next [`ReceiveTrafficState`] state.
466    pub fn into_next(mut self) -> ReceiveTrafficState<'static, Side> {
467        self.input.discard(self.pending_discard);
468
469        if core::mem::take(&mut self.rt.pending_flush_sender) {
470            return ReceiveTrafficState::FlushSender(FlushSender { rt: self.rt });
471        }
472
473        match self.rt.recv.has_received_close_notify {
474            true => ReceiveTrafficState::CloseNotify,
475            false => ReceiveTrafficState::ReadMore(self.rt),
476        }
477    }
478}
479
480/// Notification that receiving data may have changed the state of the associated [`SendTraffic`]
481///
482/// The caller may wish to check whether there is any IO necessary on the send side. If it does
483/// not, and ignores this state, any pending new data to send will be included in the next
484/// attempt to send data.
485pub struct FlushSender<Side: SideData> {
486    rt: ReceiveTraffic<Side>,
487}
488
489impl<Side: SideData> FlushSender<Side> {
490    /// Obtain the next receive-side state.
491    pub fn into_next(self) -> ReceiveTrafficState<'static, Side> {
492        match self.rt.recv.has_received_close_notify {
493            true => ReceiveTrafficState::CloseNotify,
494            false => ReceiveTrafficState::ReadMore(self.rt),
495        }
496    }
497}
498
499/// Allows the receive-side of the connection to manipulate the send-side.
500///
501/// It is important for performance and concurrency that the receive-side
502/// does not regularly lock the send-side, so this is delayed until this
503/// proves to be actually required (via [`SendOutput`] methods).
504///
505/// It is important for analysis that the lock, once taken, remains taken
506/// for the remainder of the processing. This means that, for example,
507/// a sequence of sent messages is not interleaved with others from another
508/// thread.
509pub(super) enum SendAdapter<'a> {
510    Unlocked(&'a Mutex<SendInner>),
511    Locked {
512        guard: MutexGuard<'a, SendInner>,
513        send_required: bool,
514    },
515}
516
517impl<'a> SendAdapter<'a> {
518    fn as_locked<'b>(&'b mut self, may_send: bool) -> &'b mut MutexGuard<'a, SendInner> {
519        if let Self::Unlocked(m) = self {
520            *self = Self::Locked {
521                guard: m.lock().unwrap(),
522                send_required: false,
523            };
524        }
525        let Self::Locked {
526            guard,
527            send_required,
528        } = self
529        else {
530            unreachable!();
531        };
532        *send_required |= may_send;
533        guard
534    }
535}
536
537impl SendOutput for SendAdapter<'_> {
538    fn negotiated_version(&mut self, version: ProtocolVersion) {
539        self.as_locked(false)
540            .send
541            .negotiated_version(version);
542    }
543
544    fn queue_requested_key_update(&mut self) -> Result<(), Error> {
545        // waking the sender here is a policy decision to encourage timely execution of
546        // the write-side key update, it is not strictly required at a protocol level.
547        self.as_locked(true)
548            .send
549            .queue_requested_key_update()
550    }
551
552    fn note_key_update_response(&mut self) {
553        self.as_locked(false)
554            .send
555            .note_key_update_response();
556    }
557
558    fn set_encrypter(&mut self, encrypter: Encrypter) {
559        self.as_locked(false)
560            .send
561            .set_encrypter(encrypter);
562    }
563
564    fn update_key_schedule(&mut self, schedule: Box<KeyScheduleTrafficSend>) {
565        self.as_locked(false)
566            .send
567            .update_key_schedule(schedule);
568    }
569
570    fn send_alert(
571        &mut self,
572        level: AlertLevel,
573        desc: AlertDescription,
574        _wrong_thread_tls: &mut Vec<u8>,
575    ) -> Result<(), Error> {
576        self.as_locked(true)
577            .send_alert(level, desc)
578    }
579
580    fn start_traffic(&mut self) {
581        self.as_locked(false)
582            .send
583            .start_traffic();
584    }
585
586    fn send_msg(
587        &mut self,
588        m: Message<'_>,
589        must_encrypt: bool,
590        _wrong_thread_tls: &mut Vec<u8>,
591    ) -> Result<(), Error> {
592        self.as_locked(true)
593            .send_msg(m, must_encrypt)
594    }
595}
596
597#[cfg(test)]
598mod tests {
599    use super::*;
600    use crate::crypto::test_provider::Tls13Cipher;
601
602    #[test]
603    fn send_adapter_flag() {
604        let mut tls = Vec::new();
605        assert!(!send_flag_for(
606            |adapter| adapter.negotiated_version(ProtocolVersion::TLSv1_3)
607        ));
608        assert!(send_flag_for(|adapter| adapter
609            .queue_requested_key_update()
610            .unwrap()));
611        assert!(!send_flag_for(|adapter| adapter.note_key_update_response()));
612        assert!(!send_flag_for(|adapter| adapter.set_encrypter(Encrypter {
613            encrypter: Box::new(Tls13Cipher),
614            limit: 1234,
615        })));
616        // update_key_schedule too hard
617        assert!(send_flag_for(|adapter| adapter
618            .send_alert(
619                AlertLevel::Fatal,
620                AlertDescription::CertificateUnknown,
621                &mut tls,
622            )
623            .unwrap()));
624        assert!(!send_flag_for(|adapter| adapter.start_traffic()));
625        assert!(send_flag_for(|adapter| adapter
626            .send_msg(Message::build_key_update_notify(), false, &mut tls,)
627            .unwrap()));
628    }
629
630    #[test]
631    fn pending_send_data() {
632        let mut send = SendPath::default();
633        send.set_encrypter(Encrypter {
634            encrypter: Box::new(Tls13Cipher),
635            limit: 1234,
636        });
637        send.may_send_application_data = true;
638
639        let mut inner = SendInner {
640            send,
641            aside_buffer: Vec::new(),
642        };
643        assert!(!inner.pending_send_data());
644
645        // an aside alert is pending until pumped
646        inner
647            .send_alert(AlertLevel::Fatal, AlertDescription::DecodeError)
648            .unwrap();
649        assert!(inner.pending_send_data());
650
651        let mut tls = Vec::new();
652        inner.pump(&mut tls);
653        assert!(!tls.is_empty());
654        assert!(!inner.pending_send_data());
655
656        // subsequent attempts no longer work
657        assert_eq!(
658            inner
659                .send
660                .queue_requested_key_update()
661                .unwrap_err(),
662            Error::EncryptError
663        );
664        assert!(!inner.pending_send_data());
665
666        tls.clear();
667        assert_eq!(
668            inner
669                .send
670                .send_appdata_encrypt(DataKind::Traffic(b"x".as_slice().into()), &mut tls)
671                .unwrap_err(),
672            Error::ApiMisuse(ApiMisuse::WriteAfterSendPathClosed)
673        );
674        assert!(tls.is_empty());
675        assert!(!inner.pending_send_data());
676    }
677
678    fn send_flag_for(f: impl FnOnce(&mut SendAdapter<'_>)) -> bool {
679        let mut send = SendPath::default();
680        send.set_encrypter(Encrypter {
681            encrypter: Box::new(Tls13Cipher),
682            limit: 1234,
683        });
684
685        let send = Mutex::new(SendInner {
686            send,
687            aside_buffer: Vec::new(),
688        });
689
690        let mut adapter = SendAdapter::Unlocked(&send);
691        f(&mut adapter);
692        let SendAdapter::Locked { send_required, .. } = adapter else {
693            panic!("expected to find SendAdapter::Locked");
694        };
695        send_required
696    }
697}