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