Skip to main content

rustls/conn/
mod.rs

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