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;