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