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};
5use std::io::{self, BufRead, Read};
6
7use kernel::KernelConnection;
8use pki_types::FipsStatus;
9
10use crate::common_state::{
11    CommonState, ConnectionOutput, ConnectionOutputs, Event, Output, OutputEvent, UnborrowedPayload,
12};
13use crate::error::{ApiMisuse, Error};
14use crate::kernel::KernelState;
15use crate::msgs::{Delocator, Message, Random, TlsInputBuffer, VecInput};
16use crate::quic::QuicOutput;
17use crate::suites::{ExtractedSecrets, PartiallyExtractedSecrets};
18use crate::tls13::key_schedule::KeyScheduleTrafficSend;
19use crate::vecbuf::ChunkVecBuffer;
20
21// pub so that it can be re-exported from the crate root
22pub mod kernel;
23
24mod receive;
25use receive::JoinOutput;
26pub(crate) use receive::{Input, ReceivePath, TrafficTemperCounters};
27
28mod send;
29use send::DEFAULT_BUFFER_LIMIT;
30pub(crate) use send::{SendOutput, SendPath};
31
32use crate::crypto::cipher::OutboundPlain;
33
34/// A trait generalizing over buffered client or server connections.
35pub trait Connection: Debug + Deref<Target = ConnectionOutputs> {
36    /// Read TLS content from `rd` into the internal buffer.
37    ///
38    /// Due to the internal buffering, `rd` can supply TLS messages in arbitrary-sized chunks (like
39    /// a socket or pipe might).
40    ///
41    /// You should call [`process_new_packets()`] each time a call to this function succeeds in order
42    /// to empty the incoming TLS data buffer.
43    ///
44    /// This function returns `Ok(0)` when the underlying `rd` does so. This typically happens when
45    /// a socket is cleanly closed, or a file is at EOF. Errors may result from the IO done through
46    /// `rd`; additionally, errors of `ErrorKind::Other` are emitted to signal backpressure:
47    ///
48    /// * In order to empty the incoming TLS data buffer, you should call [`process_new_packets()`]
49    ///   each time a call to this function succeeds.
50    /// * In order to empty the incoming plaintext data buffer, you should empty it through
51    ///   the [`reader()`] after the call to [`process_new_packets()`].
52    ///
53    /// This function also returns `Ok(0)` once a `close_notify` alert has been successfully
54    /// received.  No additional data is ever read in this state.
55    ///
56    /// [`process_new_packets()`]: Connection::process_new_packets
57    /// [`reader()`]: Connection::reader
58    fn read_tls(&mut self, rd: &mut dyn Read) -> Result<usize, io::Error>;
59
60    /// Writes TLS messages to `wr`.
61    ///
62    /// On success, this function returns `Ok(n)` where `n` is a number of bytes written to `wr`
63    /// (after encoding and encryption).
64    ///
65    /// After this function returns, the connection buffer may not yet be fully flushed. The
66    /// [`Connection::wants_write()`] function can be used to check if the output buffer is
67    /// empty.
68    fn write_tls(&mut self, wr: &mut dyn io::Write) -> Result<usize, io::Error>;
69
70    /// Returns true if the caller should call [`Connection::read_tls`] as soon
71    /// as possible.
72    ///
73    /// If there is pending plaintext data to read with [`Connection::reader`],
74    /// this returns false.  If your application respects this mechanism,
75    /// only one full TLS message will be buffered by rustls.
76    ///
77    /// [`Connection::reader`]: crate::Connection::reader
78    /// [`Connection::read_tls`]: crate::Connection::read_tls
79    fn wants_read(&self) -> bool;
80
81    /// Returns true if the caller should call [`Connection::write_tls`] as soon as possible.
82    ///
83    /// [`Connection::write_tls`]: crate::Connection::write_tls
84    fn wants_write(&self) -> bool;
85
86    /// Returns an object that allows reading plaintext.
87    fn reader(&mut self) -> Reader<'_>;
88
89    /// Returns an object that allows writing plaintext.
90    fn writer(&mut self) -> Writer<'_>;
91
92    /// Processes any new packets read by a previous call to
93    /// [`Connection::read_tls`].
94    ///
95    /// Errors from this function relate to TLS protocol errors, and
96    /// are fatal to the connection.  Future calls after an error will do
97    /// no new work and will return the same error. After an error is
98    /// received from [`process_new_packets()`], you should not call [`read_tls()`]
99    /// any more (it will fill up buffers to no purpose). However, you
100    /// may call the other methods on the connection, including `write`,
101    /// `send_close_notify`, and `write_tls`. Most likely you will want to
102    /// call `write_tls` to send any alerts queued by the error and then
103    /// close the underlying connection.
104    ///
105    /// Success from this function comes with some sundry state data
106    /// about the connection.
107    ///
108    /// [`process_new_packets()`]: Connection::process_new_packets
109    /// [`read_tls()`]: Connection::read_tls
110    fn process_new_packets(&mut self) -> Result<IoState, Error>;
111
112    /// Returns an object that can derive key material from the agreed connection secrets.
113    ///
114    /// See [RFC5705][] for more details on what this is for.
115    ///
116    /// This function can be called at most once per connection.
117    ///
118    /// This function will error:
119    ///
120    /// - if called prior to the handshake completing; (check with
121    ///   [`Connection::is_handshaking()`] first).
122    /// - if called more than once per connection.
123    ///
124    /// [RFC5705]: https://datatracker.ietf.org/doc/html/rfc5705
125    fn exporter(&mut self) -> Result<KeyingMaterialExporter, Error>;
126
127    /// Extract secrets, so they can be used when configuring kTLS, for example.
128    ///
129    /// Should be used with care as it exposes secret key material.
130    fn dangerous_extract_secrets(self) -> Result<ExtractedSecrets, Error>;
131
132    /// Sets a limit on the internal buffers used to buffer
133    /// unsent plaintext (prior to completing the TLS handshake)
134    /// and unsent TLS records.  This limit acts only on application
135    /// data written through [`Connection::writer`].
136    ///
137    /// By default the limit is 64KB.  The limit can be set
138    /// at any time, even if the current buffer use is higher.
139    ///
140    /// [`None`] means no limit applies, and will mean that written
141    /// data is buffered without bound -- it is up to the application
142    /// to appropriately schedule its plaintext and TLS writes to bound
143    /// memory usage.
144    ///
145    /// For illustration: `Some(1)` means a limit of one byte applies:
146    /// [`Connection::writer`] will accept only one byte, encrypt it and
147    /// add a TLS header.  Once this is sent via [`Connection::write_tls`],
148    /// another byte may be sent.
149    ///
150    /// # Internal write-direction buffering
151    /// rustls has two buffers whose size are bounded by this setting:
152    ///
153    /// ## Buffering of unsent plaintext data prior to handshake completion
154    ///
155    /// Calls to [`Connection::writer`] before or during the handshake
156    /// are buffered (up to the limit specified here).  Once the
157    /// handshake completes this data is encrypted and the resulting
158    /// TLS records are added to the outgoing buffer.
159    ///
160    /// ## Buffering of outgoing TLS records
161    ///
162    /// This buffer is used to store TLS records that rustls needs to
163    /// send to the peer.  It is used in these two circumstances:
164    ///
165    /// - by [`Connection::process_new_packets`] when a handshake or alert
166    ///   TLS record needs to be sent.
167    /// - by [`Connection::writer`] post-handshake: the plaintext is
168    ///   encrypted and the resulting TLS record is buffered.
169    ///
170    /// This buffer is emptied by [`Connection::write_tls`].
171    ///
172    /// [`Connection::writer`]: crate::Connection::writer
173    /// [`Connection::write_tls`]: crate::Connection::write_tls
174    /// [`Connection::process_new_packets`]: crate::Connection::process_new_packets
175    fn set_buffer_limit(&mut self, limit: Option<usize>);
176
177    /// Sets a limit on the internal buffers used to buffer decoded plaintext.
178    ///
179    /// See [`Self::set_buffer_limit`] for more information on how limits are applied.
180    fn set_plaintext_buffer_limit(&mut self, limit: Option<usize>);
181
182    /// Sends a TLS1.3 `key_update` message to refresh a connection's keys.
183    ///
184    /// This call refreshes our encryption keys. Once the peer receives the message,
185    /// it refreshes _its_ encryption and decryption keys and sends a response.
186    /// Once we receive that response, we refresh our decryption keys to match.
187    /// At the end of this process, keys in both directions have been refreshed.
188    ///
189    /// Note that this process does not happen synchronously: this call just
190    /// arranges that the `key_update` message will be included in the next
191    /// `write_tls` output.
192    ///
193    /// This fails with `Error::HandshakeNotComplete` if called before the initial
194    /// handshake is complete, or if a version prior to TLS1.3 is negotiated.
195    ///
196    /// # Usage advice
197    /// Note that other implementations (including rustls) may enforce limits on
198    /// the number of `key_update` messages allowed on a given connection to prevent
199    /// denial of service.  Therefore, this should be called sparingly.
200    ///
201    /// rustls implicitly and automatically refreshes traffic keys when needed
202    /// according to the selected cipher suite's cryptographic constraints.  There
203    /// is therefore no need to call this manually to avoid cryptographic keys
204    /// "wearing out".
205    ///
206    /// The main reason to call this manually is to roll keys when it is known
207    /// a connection will be idle for a long period.
208    fn refresh_traffic_keys(&mut self) -> Result<(), Error>;
209
210    /// Queues a `close_notify` warning alert to be sent in the next
211    /// [`Connection::write_tls`] call.  This informs the peer that the
212    /// connection is being closed.
213    ///
214    /// Does nothing if any `close_notify` or fatal alert was already sent.
215    ///
216    /// [`Connection::write_tls`]: crate::Connection::write_tls
217    fn send_close_notify(&mut self);
218
219    /// Returns true if the connection is currently performing the TLS handshake.
220    ///
221    /// During this time plaintext written to the connection is buffered in memory. After
222    /// [`Connection::process_new_packets()`] has been called, this might start to return `false`
223    /// while the final handshake packets still need to be extracted from the connection's buffers.
224    ///
225    /// [`Connection::process_new_packets()`]: crate::Connection::process_new_packets
226    fn is_handshaking(&self) -> bool;
227
228    /// Return the FIPS validation status of the connection.
229    ///
230    /// This is different from [`CryptoProvider::fips()`][]:
231    /// it is concerned only with cryptography, whereas this _also_ covers TLS-level
232    /// configuration that NIST recommends, as well as ECH HPKE suites if applicable.
233    ///
234    /// [`CryptoProvider::fips()`]: crate::crypto::CryptoProvider::fips()
235    fn fips(&self) -> FipsStatus;
236}
237
238/// A structure that implements [`std::io::Read`] for reading plaintext.
239pub struct Reader<'a> {
240    pub(super) received_plaintext: &'a mut ChunkVecBuffer,
241    pub(super) has_received_close_notify: bool,
242    pub(super) has_seen_eof: bool,
243}
244
245impl<'a> Reader<'a> {
246    /// Check the connection's state if no bytes are available for reading.
247    fn check_no_bytes_state(&self) -> io::Result<()> {
248        match (self.has_received_close_notify, self.has_seen_eof) {
249            // cleanly closed; don't care about TCP EOF: express this as Ok(0)
250            (true, _) => Ok(()),
251            // unclean closure
252            (false, true) => Err(io::Error::new(
253                io::ErrorKind::UnexpectedEof,
254                UNEXPECTED_EOF_MESSAGE,
255            )),
256            // connection still going, but needs more data: signal `WouldBlock` so that
257            // the caller knows this
258            (false, false) => Err(io::ErrorKind::WouldBlock.into()),
259        }
260    }
261
262    /// Obtain a chunk of plaintext data received from the peer over this TLS connection.
263    ///
264    /// This method consumes `self` so that it can return a slice whose lifetime is bounded by
265    /// the [`Connection`] that created this [`Reader`].
266    pub fn into_first_chunk(self) -> io::Result<&'a [u8]> {
267        match self.received_plaintext.chunk() {
268            Some(chunk) => Ok(chunk),
269            None => {
270                self.check_no_bytes_state()?;
271                Ok(&[])
272            }
273        }
274    }
275}
276
277impl Read for Reader<'_> {
278    /// Obtain plaintext data received from the peer over this TLS connection.
279    ///
280    /// If the peer closes the TLS session cleanly, this returns `Ok(0)`  once all
281    /// the pending data has been read. No further data can be received on that
282    /// connection, so the underlying TCP connection should be half-closed too.
283    ///
284    /// If the peer closes the TLS session uncleanly (a TCP EOF without sending a
285    /// `close_notify` alert) this function returns a `std::io::Error` of type
286    /// `ErrorKind::UnexpectedEof` once any pending data has been read.
287    ///
288    /// Note that support for `close_notify` varies in peer TLS libraries: many do not
289    /// support it and uncleanly close the TCP connection (this might be
290    /// vulnerable to truncation attacks depending on the application protocol).
291    /// This means applications using rustls must both handle EOF
292    /// from this function, *and* unexpected EOF of the underlying TCP connection.
293    ///
294    /// If there are no bytes to read, this returns `Err(ErrorKind::WouldBlock.into())`.
295    ///
296    /// You may learn the number of bytes available at any time by inspecting
297    /// the return of [`Connection::process_new_packets`].
298    fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
299        let len = self.received_plaintext.read(buf)?;
300        if len > 0 || buf.is_empty() {
301            return Ok(len);
302        }
303
304        self.check_no_bytes_state()
305            .map(|()| len)
306    }
307}
308
309impl BufRead for Reader<'_> {
310    /// Obtain a chunk of plaintext data received from the peer over this TLS connection.
311    /// This reads the same data as [`Reader::read()`], but returns a reference instead of
312    /// copying the data.
313    ///
314    /// The caller should call [`Reader::consume()`] afterward to advance the buffer.
315    ///
316    /// See [`Reader::into_first_chunk()`] for a version of this function that returns a
317    /// buffer with a longer lifetime.
318    fn fill_buf(&mut self) -> io::Result<&[u8]> {
319        Reader {
320            // reborrow
321            received_plaintext: self.received_plaintext,
322            ..*self
323        }
324        .into_first_chunk()
325    }
326
327    fn consume(&mut self, amt: usize) {
328        self.received_plaintext
329            .consume_first_chunk(amt)
330    }
331}
332
333const UNEXPECTED_EOF_MESSAGE: &str = "peer closed connection without sending TLS close_notify: \
334https://docs.rs/rustls/latest/rustls/manual/_03_howto/index.html#unexpected-eof";
335
336/// A structure that implements [`std::io::Write`] for writing plaintext.
337pub struct Writer<'a> {
338    sink: &'a mut dyn PlaintextSink,
339}
340
341impl<'a> Writer<'a> {
342    /// Create a new Writer.
343    ///
344    /// This is not an external interface.  Get one of these objects
345    /// from [`Connection::writer`].
346    pub(crate) fn new(sink: &'a mut dyn PlaintextSink) -> Self {
347        Writer { sink }
348    }
349}
350
351impl io::Write for Writer<'_> {
352    /// Send the plaintext `buf` to the peer, encrypting
353    /// and authenticating it.  Once this function succeeds
354    /// you should call [`Connection::write_tls`] which will output the
355    /// corresponding TLS records.
356    ///
357    /// This function buffers plaintext sent before the
358    /// TLS handshake completes, and sends it as soon
359    /// as it can.  See [`Connection::set_buffer_limit()`] to control
360    /// the size of this buffer.
361    fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
362        self.sink.write(buf)
363    }
364
365    fn write_vectored(&mut self, bufs: &[io::IoSlice<'_>]) -> io::Result<usize> {
366        self.sink.write_vectored(bufs)
367    }
368
369    fn flush(&mut self) -> io::Result<()> {
370        self.sink.flush()
371    }
372}
373
374/// Internal trait implemented by the [`ServerConnection`]/[`ClientConnection`]
375/// allowing them to be the subject of a [`Writer`].
376///
377/// [`ServerConnection`]: crate::ServerConnection
378/// [`ClientConnection`]: crate::ClientConnection
379pub(crate) trait PlaintextSink {
380    fn write(&mut self, buf: &[u8]) -> io::Result<usize>;
381    fn write_vectored(&mut self, bufs: &[io::IoSlice<'_>]) -> io::Result<usize>;
382    fn flush(&mut self) -> io::Result<()>;
383}
384
385impl<Side: SideData> PlaintextSink for ConnectionCommon<Side> {
386    fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
387        let len = self
388            .core
389            .common
390            .send
391            .buffer_plaintext(buf.into(), &mut self.buffers.sendable_plaintext);
392        self.send.maybe_refresh_traffic_keys();
393        Ok(len)
394    }
395
396    fn write_vectored(&mut self, bufs: &[io::IoSlice<'_>]) -> io::Result<usize> {
397        let payload_owner: Vec<&[u8]>;
398        let payload = match bufs.len() {
399            0 => return Ok(0),
400            1 => OutboundPlain::Single(bufs[0].deref()),
401            _ => {
402                payload_owner = bufs
403                    .iter()
404                    .map(|io_slice| io_slice.deref())
405                    .collect();
406
407                OutboundPlain::new(&payload_owner)
408            }
409        };
410        let len = self
411            .core
412            .common
413            .send
414            .buffer_plaintext(payload, &mut self.buffers.sendable_plaintext);
415        self.send.maybe_refresh_traffic_keys();
416        Ok(len)
417    }
418
419    fn flush(&mut self) -> io::Result<()> {
420        Ok(())
421    }
422}
423
424/// An object of this type can export keying material.
425pub struct KeyingMaterialExporter {
426    pub(crate) inner: Box<dyn Exporter>,
427}
428
429impl KeyingMaterialExporter {
430    /// Derives key material from the agreed connection secrets.
431    ///
432    /// This function fills in `output` with `output.len()` bytes of key
433    /// material derived from a master connection secret using `label`
434    /// and `context` for diversification. Ownership of the buffer is taken
435    /// by the function and returned via the Ok result to ensure no key
436    /// material leaks if the function fails.
437    ///
438    /// See [RFC5705][] for more details on what this does and is for.  In
439    /// other libraries this is often named `SSL_export_keying_material()`
440    /// or `SslExportKeyingMaterial()`.
441    ///
442    /// This function is not meaningful if `output.len()` is zero and will
443    /// return an error in that case.
444    ///
445    /// [RFC5705]: https://datatracker.ietf.org/doc/html/rfc5705
446    pub fn derive<T: AsMut<[u8]>>(
447        &self,
448        label: &[u8],
449        context: Option<&[u8]>,
450        mut output: T,
451    ) -> Result<T, Error> {
452        if output.as_mut().is_empty() {
453            return Err(ApiMisuse::ExporterOutputZeroLength.into());
454        }
455
456        self.inner
457            .derive(label, context, output.as_mut())
458            .map(|_| output)
459    }
460}
461
462impl Debug for KeyingMaterialExporter {
463    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
464        f.debug_struct("KeyingMaterialExporter")
465            .finish_non_exhaustive()
466    }
467}
468
469/// This trait is for any object that can export keying material.
470///
471/// The terminology comes from [RFC5705](https://datatracker.ietf.org/doc/html/rfc5705)
472/// but doesn't really involve "exporting" key material (in the usual meaning of "export"
473/// -- of moving an artifact from one domain to another) but is best thought of as key
474/// diversification using an existing secret.  That secret is implicit in this interface,
475/// so is assumed to be held by `self`. The secret should be zeroized in `drop()`.
476///
477/// There are several such internal implementations, depending on the context
478/// and protocol version.
479pub(crate) trait Exporter: Send + Sync {
480    /// Fills in `output` with derived keying material.
481    ///
482    /// This is deterministic depending on a base secret (implicit in `self`),
483    /// plus the `label` and `context` values.
484    ///
485    /// Must fill in `output` entirely, or return an error.
486    fn derive(&self, label: &[u8], context: Option<&[u8]>, output: &mut [u8]) -> Result<(), Error>;
487}
488
489#[derive(Debug)]
490pub(crate) struct ConnectionRandoms {
491    pub(crate) client: [u8; 32],
492    pub(crate) server: [u8; 32],
493}
494
495impl ConnectionRandoms {
496    pub(crate) fn new(client: Random, server: Random) -> Self {
497        Self {
498            client: client.0,
499            server: server.0,
500        }
501    }
502}
503
504/// TLS connection state with side-specific data (`Side`).
505///
506/// This is one of the core abstractions of the rustls API. It represents a single connection
507/// to a peer, and holds all the state associated with that connection. Note that it does
508/// not hold any IO objects: the application is responsible for reading and writing TLS records.
509/// If you want an object that does hold IO objects, see `rustls_util::Stream` and
510/// `rustls_util::StreamOwned`.
511///
512/// This object is generic over the `Side` type parameter, which must implement the marker trait
513/// [`SideData`]. This is used to store side-specific data.
514pub(crate) struct ConnectionCommon<Side: SideData> {
515    pub(crate) core: ConnectionCore<Side>,
516    pub(crate) fips: FipsStatus,
517    buffers: Buffers,
518}
519
520impl<Side: SideData> ConnectionCommon<Side> {
521    pub(crate) fn new(core: ConnectionCore<Side>, fips: FipsStatus) -> Self {
522        Self {
523            core,
524            fips,
525            buffers: Buffers::new(),
526        }
527    }
528
529    #[inline]
530    pub(crate) fn process_new_packets(&mut self) -> Result<IoState, Error> {
531        loop {
532            let Some(payload) = self
533                .core
534                .process_new_packets(&mut self.buffers.deframer_buffer, None)?
535            else {
536                break;
537            };
538
539            let payload =
540                payload.reborrow(&Delocator::new(self.buffers.deframer_buffer.slice_mut()));
541            self.buffers
542                .received_plaintext
543                .append(payload.into_vec());
544            self.buffers.deframer_buffer.discard(
545                self.core
546                    .common
547                    .recv
548                    .deframer
549                    .take_discard(),
550            );
551        }
552
553        // Release unsent buffered plaintext.
554        if self.send.may_send_application_data
555            && !self
556                .buffers
557                .sendable_plaintext
558                .is_empty()
559        {
560            self.core
561                .common
562                .send
563                .send_buffered_plaintext(&mut self.buffers.sendable_plaintext);
564        }
565
566        Ok(self.current_io_state())
567    }
568
569    pub(crate) fn wants_read(&self) -> bool {
570        // We want to read more data all the time, except when we have unprocessed plaintext.
571        // This provides back-pressure to the TCP buffers. We also don't want to read more after
572        // the peer has sent us a close notification.
573        //
574        // In the handshake case we don't have readable plaintext before the handshake has
575        // completed, but also don't want to read if we still have sendable tls.
576        self.buffers
577            .received_plaintext
578            .is_empty()
579            && !self.recv.has_received_close_notify
580            && (self.send.may_send_application_data || self.send.sendable_tls.is_empty())
581    }
582
583    pub(crate) fn exporter(&mut self) -> Result<KeyingMaterialExporter, Error> {
584        self.core.exporter()
585    }
586
587    /// Extract secrets, so they can be used when configuring kTLS, for example.
588    /// Should be used with care as it exposes secret key material.
589    pub(crate) fn dangerous_extract_secrets(self) -> Result<ExtractedSecrets, Error> {
590        self.core.dangerous_extract_secrets()
591    }
592
593    pub(crate) fn set_buffer_limit(&mut self, limit: Option<usize>) {
594        self.buffers
595            .sendable_plaintext
596            .set_limit(limit);
597        self.send.sendable_tls.set_limit(limit);
598    }
599
600    pub(crate) fn set_plaintext_buffer_limit(&mut self, limit: Option<usize>) {
601        self.buffers
602            .received_plaintext
603            .set_limit(limit);
604    }
605
606    pub(crate) fn refresh_traffic_keys(&mut self) -> Result<(), Error> {
607        self.core
608            .common
609            .send
610            .refresh_traffic_keys()
611    }
612
613    pub(crate) fn current_io_state(&self) -> IoState {
614        let common_state = &self.core.common;
615        IoState {
616            tls_bytes_to_write: common_state.send.sendable_tls.len(),
617            plaintext_bytes_to_read: self.buffers.received_plaintext.len(),
618            peer_has_closed: common_state
619                .recv
620                .has_received_close_notify,
621        }
622    }
623}
624
625impl<Side: SideData> ConnectionCommon<Side> {
626    /// Returns an object that allows reading plaintext.
627    pub(crate) fn reader(&mut self) -> Reader<'_> {
628        let common = &mut self.core.common;
629        let has_received_close_notify = common.recv.has_received_close_notify;
630        Reader {
631            received_plaintext: &mut self.buffers.received_plaintext,
632            // Are we done? i.e., have we processed all received messages, and received a
633            // close_notify to indicate that no new messages will arrive?
634            has_received_close_notify,
635            has_seen_eof: self.buffers.has_seen_eof,
636        }
637    }
638
639    /// Returns an object that allows writing plaintext.
640    pub(crate) fn writer(&mut self) -> Writer<'_> {
641        Writer::new(self)
642    }
643
644    pub(crate) fn read_tls(&mut self, rd: &mut dyn Read) -> Result<usize, io::Error> {
645        if self
646            .buffers
647            .received_plaintext
648            .is_full()
649        {
650            return Err(io::Error::other("received plaintext buffer full"));
651        }
652
653        if self.recv.has_received_close_notify {
654            return Ok(0);
655        }
656
657        let res = self.buffers.deframer_buffer.read(rd);
658        if let Ok(0) = res {
659            self.buffers.has_seen_eof = true;
660        }
661        res
662    }
663
664    pub(crate) fn write_tls(&mut self, wr: &mut dyn io::Write) -> Result<usize, io::Error> {
665        self.send.sendable_tls.write_to(wr)
666    }
667}
668
669impl<Side: SideData> Deref for ConnectionCommon<Side> {
670    type Target = CommonState;
671
672    fn deref(&self) -> &Self::Target {
673        &self.core.common
674    }
675}
676
677impl<Side: SideData> DerefMut for ConnectionCommon<Side> {
678    fn deref_mut(&mut self) -> &mut Self::Target {
679        &mut self.core.common
680    }
681}
682
683/// Common items for buffered, std::io-using connections.
684pub(crate) struct Buffers {
685    deframer_buffer: VecInput,
686    pub(crate) received_plaintext: ChunkVecBuffer,
687    pub(crate) sendable_plaintext: ChunkVecBuffer,
688    pub(crate) has_seen_eof: bool,
689}
690
691impl Buffers {
692    fn new() -> Self {
693        Self {
694            deframer_buffer: VecInput::default(),
695            received_plaintext: ChunkVecBuffer::new(Some(DEFAULT_RECEIVED_PLAINTEXT_LIMIT)),
696            sendable_plaintext: ChunkVecBuffer::new(Some(DEFAULT_BUFFER_LIMIT)),
697            has_seen_eof: false,
698        }
699    }
700}
701
702/// Values of this structure are returned from [`Connection::process_new_packets`]
703/// and tell the caller the current I/O state of the TLS connection.
704///
705/// [`Connection::process_new_packets`]: crate::Connection::process_new_packets
706#[derive(Debug, Eq, PartialEq)]
707pub struct IoState {
708    tls_bytes_to_write: usize,
709    plaintext_bytes_to_read: usize,
710    peer_has_closed: bool,
711}
712
713impl IoState {
714    /// How many bytes could be written by [`Connection::write_tls`] if called
715    /// right now.  A non-zero value implies [`CommonState::wants_write`].
716    ///
717    /// [`Connection::write_tls`]: crate::Connection::write_tls
718    pub fn tls_bytes_to_write(&self) -> usize {
719        self.tls_bytes_to_write
720    }
721
722    /// How many plaintext bytes could be obtained via [`std::io::Read`]
723    /// without further I/O.
724    pub fn plaintext_bytes_to_read(&self) -> usize {
725        self.plaintext_bytes_to_read
726    }
727
728    /// True if the peer has sent us a close_notify alert.  This is
729    /// the TLS mechanism to securely half-close a TLS connection,
730    /// and signifies that the peer will not send any further data
731    /// on this connection.
732    ///
733    /// This is also signalled via returning `Ok(0)` from
734    /// [`std::io::Read`], after all the received bytes have been
735    /// retrieved.
736    pub fn peer_has_closed(&self) -> bool {
737        self.peer_has_closed
738    }
739}
740
741pub(crate) struct ConnectionCore<Side: SideData> {
742    pub(crate) state: Result<Side::State, Error>,
743    pub(crate) side: Side::Data,
744    pub(crate) common: CommonState,
745}
746
747impl<Side: SideData> ConnectionCore<Side> {
748    pub(crate) fn new(state: Side::State, side: Side::Data, common: CommonState) -> Self {
749        Self {
750            state: Ok(state),
751            side,
752            common,
753        }
754    }
755
756    #[inline]
757    pub(crate) fn process_new_packets<'a>(
758        &'a mut self,
759        buffer: &mut dyn TlsInputBuffer,
760        quic: Option<&'a mut dyn QuicOutput>,
761    ) -> Result<Option<UnborrowedPayload>, Error> {
762        let mut output = JoinOutput {
763            outputs: &mut self.common.outputs,
764            quic,
765            send: &mut self.common.send,
766            side: &mut self.side,
767        };
768
769        self.common
770            .recv
771            .process_new_packets::<Side>(buffer, &mut self.state, &mut output)
772    }
773
774    pub(crate) fn dangerous_extract_secrets(self) -> Result<ExtractedSecrets, Error> {
775        Ok(self
776            .dangerous_into_kernel_connection()?
777            .0)
778    }
779
780    pub(crate) fn dangerous_into_kernel_connection(
781        mut self,
782    ) -> Result<(ExtractedSecrets, KernelConnection<Side>), Error> {
783        if self.common.is_handshaking() {
784            return Err(Error::HandshakeNotComplete);
785        }
786        Self::from_parts_into_kernel_connection(
787            &mut self.common.send,
788            self.common.recv,
789            self.common.outputs,
790            self.state?,
791        )
792    }
793
794    pub(crate) fn from_parts_into_kernel_connection(
795        send: &mut SendPath,
796        recv: ReceivePath,
797        outputs: ConnectionOutputs,
798        state: Side::State,
799    ) -> Result<(ExtractedSecrets, KernelConnection<Side>), Error> {
800        if !send.sendable_tls.is_empty() {
801            return Err(ApiMisuse::SecretExtractionWithPendingSendableData.into());
802        }
803
804        let read_seq = recv.decrypt_state.read_seq();
805        let write_seq = send.encrypt_state.write_seq();
806
807        let tls13_key_schedule = send.tls13_key_schedule.take();
808
809        let (secrets, state) = state.into_external_state(&tls13_key_schedule)?;
810        let secrets = ExtractedSecrets {
811            tx: (write_seq, secrets.tx),
812            rx: (read_seq, secrets.rx),
813        };
814        let external = KernelConnection::new(state, outputs, tls13_key_schedule)?;
815
816        Ok((secrets, external))
817    }
818
819    pub(crate) fn exporter(&mut self) -> Result<KeyingMaterialExporter, Error> {
820        match self.common.exporter.take() {
821            Some(inner) => Ok(KeyingMaterialExporter { inner }),
822            None if self.common.is_handshaking() => Err(Error::HandshakeNotComplete),
823            None => Err(ApiMisuse::ExporterAlreadyUsed.into()),
824        }
825    }
826
827    pub(crate) fn early_exporter(&mut self) -> Result<KeyingMaterialExporter, Error> {
828        match self.common.early_exporter.take() {
829            Some(inner) => Ok(KeyingMaterialExporter { inner }),
830            None => Err(ApiMisuse::ExporterAlreadyUsed.into()),
831        }
832    }
833}
834
835pub(crate) struct SideCommonOutput<'a, 'q> {
836    pub(crate) side: &'a mut dyn SideOutput,
837    pub(crate) quic: Option<&'q mut dyn QuicOutput>,
838    pub(crate) common: &'a mut CommonState,
839}
840
841impl<'q> Output<'_> for SideCommonOutput<'_, 'q> {
842    fn emit(&mut self, ev: Event<'_>) {
843        self.side.emit(ev);
844    }
845
846    fn output(&mut self, ev: OutputEvent<'_>) {
847        self.common.outputs.handle(ev);
848    }
849
850    fn send_msg(&mut self, m: Message<'_>, must_encrypt: bool) {
851        match self.quic() {
852            Some(quic) => quic.send_msg(m, must_encrypt),
853            None => self
854                .common
855                .send
856                .send_msg(m, must_encrypt),
857        }
858    }
859
860    fn quic(&mut self) -> Option<&mut dyn QuicOutput> {
861        match self.quic.as_mut() {
862            Some(q) => Some(&mut **q),
863            None => None,
864        }
865    }
866
867    fn start_traffic(&mut self) {
868        self.common
869            .recv
870            .may_receive_application_data = true;
871        self.common
872            .send
873            .start_outgoing_traffic();
874    }
875
876    fn receive(&mut self) -> &mut ReceivePath {
877        &mut self.common.recv
878    }
879
880    fn send(&mut self) -> &mut dyn SendOutput {
881        &mut self.common.send
882    }
883}
884
885/// Data specific to the peer's side (client or server).
886#[expect(private_bounds)]
887pub trait SideData: private::Side {}
888
889pub(crate) mod private {
890    use super::*;
891
892    pub(crate) trait Side: Debug {
893        /// Data storage type.
894        type Data: SideOutput;
895        /// State machine type.
896        type State: StateMachine;
897    }
898
899    pub(crate) trait SideOutput {
900        fn emit(&mut self, ev: Event<'_>);
901    }
902}
903
904use private::SideOutput;
905
906pub(crate) trait StateMachine: Sized {
907    fn handle<'m>(self, input: Input<'m>, output: &mut dyn Output<'m>) -> Result<Self, Error>;
908    fn wants_input(&self) -> bool;
909    fn handle_decrypt_error(&mut self);
910    fn into_external_state(
911        self,
912        send_keys: &Option<Box<KeyScheduleTrafficSend>>,
913    ) -> Result<(PartiallyExtractedSecrets, Box<dyn KernelState + 'static>), Error>;
914}
915
916const DEFAULT_RECEIVED_PLAINTEXT_LIMIT: usize = 16 * 1024;