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