rustls/conn/mod.rs
1use alloc::boxed::Box;
2use core::fmt::{self, Debug};
3use core::mem;
4use core::ops::{Deref, DerefMut, Range};
5#[cfg(feature = "std")]
6use std::io;
7
8use kernel::KernelConnection;
9
10#[cfg(feature = "std")]
11use crate::common_state::Input;
12use crate::common_state::{
13 CommonState, DEFAULT_BUFFER_LIMIT, IoState, Output, State, process_main_protocol,
14};
15use crate::crypto::cipher::{Decrypted, EncodedMessage};
16use crate::enums::{ContentType, ProtocolVersion};
17use crate::error::{ApiMisuse, Error, PeerMisbehaved};
18#[cfg(feature = "std")]
19use crate::msgs::Message;
20use crate::msgs::{
21 BufferProgress, DeframerIter, DeframerVecBuffer, Delocator, HandshakeDeframer, Locator, Random,
22};
23use crate::suites::ExtractedSecrets;
24use crate::vecbuf::ChunkVecBuffer;
25
26// pub so that it can be re-exported from the crate root
27pub mod kernel;
28pub(crate) mod unbuffered;
29
30#[cfg(feature = "std")]
31mod connection {
32 use alloc::vec::Vec;
33 use core::fmt::Debug;
34 use core::ops::{Deref, DerefMut};
35 use std::io::{self, BufRead, Read};
36
37 use crate::common_state::{CommonState, IoState};
38 use crate::conn::{ConnectionCommon, 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 client or server connection.
45 #[expect(clippy::exhaustive_enums)]
46 #[derive(Debug)]
47 pub enum Connection {
48 /// A client connection
49 Client(crate::client::ClientConnection),
50 /// A server connection
51 Server(crate::server::ServerConnection),
52 }
53
54 impl Connection {
55 /// Read TLS content from `rd`.
56 ///
57 /// See [`ConnectionCommon::read_tls()`] for more information.
58 pub fn read_tls(&mut self, rd: &mut dyn Read) -> Result<usize, io::Error> {
59 match self {
60 Self::Client(conn) => conn.read_tls(rd),
61 Self::Server(conn) => conn.read_tls(rd),
62 }
63 }
64
65 /// Writes TLS messages to `wr`.
66 ///
67 /// See [`ConnectionCommon::write_tls()`] for more information.
68 pub fn write_tls(&mut self, wr: &mut dyn io::Write) -> Result<usize, io::Error> {
69 self.send.sendable_tls.write_to(wr)
70 }
71
72 /// Returns an object that allows reading plaintext.
73 pub fn reader(&mut self) -> Reader<'_> {
74 match self {
75 Self::Client(conn) => conn.reader(),
76 Self::Server(conn) => conn.reader(),
77 }
78 }
79
80 /// Returns an object that allows writing plaintext.
81 pub fn writer(&mut self) -> Writer<'_> {
82 match self {
83 Self::Client(conn) => Writer::new(&mut **conn),
84 Self::Server(conn) => Writer::new(&mut **conn),
85 }
86 }
87
88 /// Processes any new packets read by a previous call to [`Connection::read_tls`].
89 ///
90 /// See [`ConnectionCommon::process_new_packets()`] for more information.
91 pub fn process_new_packets(&mut self) -> Result<IoState, Error> {
92 match self {
93 Self::Client(conn) => conn.process_new_packets(),
94 Self::Server(conn) => conn.process_new_packets(),
95 }
96 }
97
98 /// Returns an object that can derive key material from the agreed connection secrets.
99 ///
100 /// See [`ConnectionCommon::exporter()`] for more information.
101 pub fn exporter(&mut self) -> Result<KeyingMaterialExporter, Error> {
102 match self {
103 Self::Client(conn) => conn.exporter(),
104 Self::Server(conn) => conn.exporter(),
105 }
106 }
107
108 /// Extract secrets, so they can be used when configuring kTLS, for example.
109 /// Should be used with care as it exposes secret key material.
110 pub fn dangerous_extract_secrets(self) -> Result<ExtractedSecrets, Error> {
111 match self {
112 Self::Client(client) => client.dangerous_extract_secrets(),
113 Self::Server(server) => server.dangerous_extract_secrets(),
114 }
115 }
116
117 /// Sets a limit on the internal buffers
118 ///
119 /// See [`ConnectionCommon::set_buffer_limit()`] for more information.
120 pub fn set_buffer_limit(&mut self, limit: Option<usize>) {
121 match self {
122 Self::Client(client) => client.set_buffer_limit(limit),
123 Self::Server(server) => server.set_buffer_limit(limit),
124 }
125 }
126
127 /// Sets a limit on the internal plaintext buffer.
128 ///
129 /// See [`ConnectionCommon::set_plaintext_buffer_limit()`] for more information.
130 pub fn set_plaintext_buffer_limit(&mut self, limit: Option<usize>) {
131 match self {
132 Self::Client(client) => client.set_plaintext_buffer_limit(limit),
133 Self::Server(server) => server.set_plaintext_buffer_limit(limit),
134 }
135 }
136
137 /// Sends a TLS1.3 `key_update` message to refresh a connection's keys
138 ///
139 /// See [`ConnectionCommon::refresh_traffic_keys()`] for more information.
140 pub fn refresh_traffic_keys(&mut self) -> Result<(), Error> {
141 match self {
142 Self::Client(client) => client.refresh_traffic_keys(),
143 Self::Server(server) => server.refresh_traffic_keys(),
144 }
145 }
146 }
147
148 impl Deref for Connection {
149 type Target = CommonState;
150
151 fn deref(&self) -> &Self::Target {
152 match self {
153 Self::Client(conn) => conn.core.side.deref(),
154 Self::Server(conn) => conn.core.side.deref(),
155 }
156 }
157 }
158
159 impl DerefMut for Connection {
160 fn deref_mut(&mut self) -> &mut Self::Target {
161 match self {
162 Self::Client(conn) => &mut conn.core.side,
163 Self::Server(conn) => &mut conn.core.side,
164 }
165 }
166 }
167
168 /// A structure that implements [`std::io::Read`] for reading plaintext.
169 pub struct Reader<'a> {
170 pub(super) received_plaintext: &'a mut ChunkVecBuffer,
171 pub(super) has_received_close_notify: bool,
172 pub(super) has_seen_eof: bool,
173 }
174
175 impl<'a> Reader<'a> {
176 /// Check the connection's state if no bytes are available for reading.
177 fn check_no_bytes_state(&self) -> io::Result<()> {
178 match (self.has_received_close_notify, self.has_seen_eof) {
179 // cleanly closed; don't care about TCP EOF: express this as Ok(0)
180 (true, _) => Ok(()),
181 // unclean closure
182 (false, true) => Err(io::Error::new(
183 io::ErrorKind::UnexpectedEof,
184 UNEXPECTED_EOF_MESSAGE,
185 )),
186 // connection still going, but needs more data: signal `WouldBlock` so that
187 // the caller knows this
188 (false, false) => Err(io::ErrorKind::WouldBlock.into()),
189 }
190 }
191
192 /// Obtain a chunk of plaintext data received from the peer over this TLS connection.
193 ///
194 /// This method consumes `self` so that it can return a slice whose lifetime is bounded by
195 /// the [`ConnectionCommon`] that created this `Reader`.
196 pub fn into_first_chunk(self) -> io::Result<&'a [u8]> {
197 match self.received_plaintext.chunk() {
198 Some(chunk) => Ok(chunk),
199 None => {
200 self.check_no_bytes_state()?;
201 Ok(&[])
202 }
203 }
204 }
205 }
206
207 impl Read for Reader<'_> {
208 /// Obtain plaintext data received from the peer over this TLS connection.
209 ///
210 /// If the peer closes the TLS session cleanly, this returns `Ok(0)` once all
211 /// the pending data has been read. No further data can be received on that
212 /// connection, so the underlying TCP connection should be half-closed too.
213 ///
214 /// If the peer closes the TLS session uncleanly (a TCP EOF without sending a
215 /// `close_notify` alert) this function returns a `std::io::Error` of type
216 /// `ErrorKind::UnexpectedEof` once any pending data has been read.
217 ///
218 /// Note that support for `close_notify` varies in peer TLS libraries: many do not
219 /// support it and uncleanly close the TCP connection (this might be
220 /// vulnerable to truncation attacks depending on the application protocol).
221 /// This means applications using rustls must both handle EOF
222 /// from this function, *and* unexpected EOF of the underlying TCP connection.
223 ///
224 /// If there are no bytes to read, this returns `Err(ErrorKind::WouldBlock.into())`.
225 ///
226 /// You may learn the number of bytes available at any time by inspecting
227 /// the return of [`Connection::process_new_packets`].
228 fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
229 let len = self.received_plaintext.read(buf)?;
230 if len > 0 || buf.is_empty() {
231 return Ok(len);
232 }
233
234 self.check_no_bytes_state()
235 .map(|()| len)
236 }
237 }
238
239 impl BufRead for Reader<'_> {
240 /// Obtain a chunk of plaintext data received from the peer over this TLS connection.
241 /// This reads the same data as [`Reader::read()`], but returns a reference instead of
242 /// copying the data.
243 ///
244 /// The caller should call [`Reader::consume()`] afterward to advance the buffer.
245 ///
246 /// See [`Reader::into_first_chunk()`] for a version of this function that returns a
247 /// buffer with a longer lifetime.
248 fn fill_buf(&mut self) -> io::Result<&[u8]> {
249 Reader {
250 // reborrow
251 received_plaintext: self.received_plaintext,
252 ..*self
253 }
254 .into_first_chunk()
255 }
256
257 fn consume(&mut self, amt: usize) {
258 self.received_plaintext
259 .consume_first_chunk(amt)
260 }
261 }
262
263 const UNEXPECTED_EOF_MESSAGE: &str = "peer closed connection without sending TLS close_notify: \
264https://docs.rs/rustls/latest/rustls/manual/_03_howto/index.html#unexpected-eof";
265
266 /// A structure that implements [`std::io::Write`] for writing plaintext.
267 pub struct Writer<'a> {
268 sink: &'a mut dyn PlaintextSink,
269 }
270
271 impl<'a> Writer<'a> {
272 /// Create a new Writer.
273 ///
274 /// This is not an external interface. Get one of these objects
275 /// from [`Connection::writer`].
276 pub(crate) fn new(sink: &'a mut dyn PlaintextSink) -> Self {
277 Writer { sink }
278 }
279 }
280
281 impl io::Write for Writer<'_> {
282 /// Send the plaintext `buf` to the peer, encrypting
283 /// and authenticating it. Once this function succeeds
284 /// you should call [`Connection::write_tls`] which will output the
285 /// corresponding TLS records.
286 ///
287 /// This function buffers plaintext sent before the
288 /// TLS handshake completes, and sends it as soon
289 /// as it can. See [`ConnectionCommon::set_buffer_limit`] to control
290 /// the size of this buffer.
291 fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
292 self.sink.write(buf)
293 }
294
295 fn write_vectored(&mut self, bufs: &[io::IoSlice<'_>]) -> io::Result<usize> {
296 self.sink.write_vectored(bufs)
297 }
298
299 fn flush(&mut self) -> io::Result<()> {
300 self.sink.flush()
301 }
302 }
303
304 /// Internal trait implemented by the [`ServerConnection`]/[`ClientConnection`]
305 /// allowing them to be the subject of a [`Writer`].
306 ///
307 /// [`ServerConnection`]: crate::ServerConnection
308 /// [`ClientConnection`]: crate::ClientConnection
309 pub(crate) trait PlaintextSink {
310 fn write(&mut self, buf: &[u8]) -> io::Result<usize>;
311 fn write_vectored(&mut self, bufs: &[io::IoSlice<'_>]) -> io::Result<usize>;
312 fn flush(&mut self) -> io::Result<()>;
313 }
314
315 impl<Side: SideData> PlaintextSink for ConnectionCommon<Side> {
316 fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
317 let len = self
318 .core
319 .side
320 .send
321 .buffer_plaintext(buf.into(), &mut self.sendable_plaintext);
322 self.core.maybe_refresh_traffic_keys();
323 Ok(len)
324 }
325
326 fn write_vectored(&mut self, bufs: &[io::IoSlice<'_>]) -> io::Result<usize> {
327 let payload_owner: Vec<&[u8]>;
328 let payload = match bufs.len() {
329 0 => return Ok(0),
330 1 => OutboundPlain::Single(bufs[0].deref()),
331 _ => {
332 payload_owner = bufs
333 .iter()
334 .map(|io_slice| io_slice.deref())
335 .collect();
336
337 OutboundPlain::new(&payload_owner)
338 }
339 };
340 let len = self
341 .core
342 .side
343 .send
344 .buffer_plaintext(payload, &mut self.sendable_plaintext);
345 self.core.maybe_refresh_traffic_keys();
346 Ok(len)
347 }
348
349 fn flush(&mut self) -> io::Result<()> {
350 Ok(())
351 }
352 }
353}
354
355#[cfg(feature = "std")]
356pub use connection::{Connection, Reader, Writer};
357
358/// An object of this type can export keying material.
359pub struct KeyingMaterialExporter {
360 pub(crate) inner: Box<dyn Exporter>,
361}
362
363impl KeyingMaterialExporter {
364 /// Derives key material from the agreed connection secrets.
365 ///
366 /// This function fills in `output` with `output.len()` bytes of key
367 /// material derived from a master connection secret using `label`
368 /// and `context` for diversification. Ownership of the buffer is taken
369 /// by the function and returned via the Ok result to ensure no key
370 /// material leaks if the function fails.
371 ///
372 /// See [RFC5705][] for more details on what this does and is for. In
373 /// other libraries this is often named `SSL_export_keying_material()`
374 /// or `SslExportKeyingMaterial()`.
375 ///
376 /// This function is not meaningful if `output.len()` is zero and will
377 /// return an error in that case.
378 ///
379 /// [RFC5705]: https://datatracker.ietf.org/doc/html/rfc5705
380 pub fn derive<T: AsMut<[u8]>>(
381 &self,
382 label: &[u8],
383 context: Option<&[u8]>,
384 mut output: T,
385 ) -> Result<T, Error> {
386 if output.as_mut().is_empty() {
387 return Err(ApiMisuse::ExporterOutputZeroLength.into());
388 }
389
390 self.inner
391 .derive(label, context, output.as_mut())
392 .map(|_| output)
393 }
394}
395
396impl Debug for KeyingMaterialExporter {
397 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
398 f.debug_struct("KeyingMaterialExporter")
399 .finish_non_exhaustive()
400 }
401}
402
403/// This trait is for any object that can export keying material.
404///
405/// The terminology comes from [RFC5705](https://datatracker.ietf.org/doc/html/rfc5705)
406/// but doesn't really involve "exporting" key material (in the usual meaning of "export"
407/// -- of moving an artifact from one domain to another) but is best thought of as key
408/// diversification using an existing secret. That secret is implicit in this interface,
409/// so is assumed to be held by `self`. The secret should be zeroized in `drop()`.
410///
411/// There are several such internal implementations, depending on the context
412/// and protocol version.
413pub(crate) trait Exporter: Send + Sync {
414 /// Fills in `output` with derived keying material.
415 ///
416 /// This is deterministic depending on a base secret (implicit in `self`),
417 /// plus the `label` and `context` values.
418 ///
419 /// Must fill in `output` entirely, or return an error.
420 fn derive(&self, label: &[u8], context: Option<&[u8]>, output: &mut [u8]) -> Result<(), Error>;
421}
422
423#[derive(Debug)]
424pub(crate) struct ConnectionRandoms {
425 pub(crate) client: [u8; 32],
426 pub(crate) server: [u8; 32],
427}
428
429impl ConnectionRandoms {
430 pub(crate) fn new(client: Random, server: Random) -> Self {
431 Self {
432 client: client.0,
433 server: server.0,
434 }
435 }
436}
437
438/// TLS connection state with side-specific data (`Side`).
439///
440/// This is one of the core abstractions of the rustls API. It represents a single connection
441/// to a peer, and holds all the state associated with that connection. Note that it does
442/// not hold any IO objects: the application is responsible for reading and writing TLS records.
443/// If you want an object that does hold IO objects, see `rustls_util::Stream` and
444/// `rustls_util::StreamOwned`.
445///
446/// This object is generic over the `Side` type parameter, which must implement the marker trait
447/// [`SideData`]. This is used to store side-specific data.
448pub struct ConnectionCommon<Side: SideData> {
449 pub(crate) core: ConnectionCore<Side>,
450 deframer_buffer: DeframerVecBuffer,
451 pub(crate) sendable_plaintext: ChunkVecBuffer,
452}
453
454impl<Side: SideData> ConnectionCommon<Side> {
455 /// Processes any new packets read by a previous call to
456 /// [`Connection::read_tls`].
457 ///
458 /// Errors from this function relate to TLS protocol errors, and
459 /// are fatal to the connection. Future calls after an error will do
460 /// no new work and will return the same error. After an error is
461 /// received from [`process_new_packets`], you should not call [`read_tls`]
462 /// any more (it will fill up buffers to no purpose). However, you
463 /// may call the other methods on the connection, including `write`,
464 /// `send_close_notify`, and `write_tls`. Most likely you will want to
465 /// call `write_tls` to send any alerts queued by the error and then
466 /// close the underlying connection.
467 ///
468 /// Success from this function comes with some sundry state data
469 /// about the connection.
470 ///
471 /// [`read_tls`]: Connection::read_tls
472 /// [`process_new_packets`]: Connection::process_new_packets
473 #[inline]
474 pub fn process_new_packets(&mut self) -> Result<IoState, Error> {
475 let io_state = self
476 .core
477 .process_new_packets(&mut self.deframer_buffer)?;
478
479 if !self
480 .core
481 .side
482 .send
483 .may_send_application_data
484 || self.sendable_plaintext.is_empty()
485 {
486 return Ok(io_state);
487 }
488
489 self.core
490 .side
491 .send
492 .send_buffered_plaintext(&mut self.sendable_plaintext);
493 Ok(self.core.side.current_io_state())
494 }
495
496 /// Returns an object that can derive key material from the agreed connection secrets.
497 ///
498 /// See [RFC5705][] for more details on what this is for.
499 ///
500 /// This function can be called at most once per connection.
501 ///
502 /// This function will error:
503 ///
504 /// - if called prior to the handshake completing; (check with
505 /// [`CommonState::is_handshaking`] first).
506 /// - if called more than once per connection.
507 ///
508 /// [RFC5705]: https://datatracker.ietf.org/doc/html/rfc5705
509 pub fn exporter(&mut self) -> Result<KeyingMaterialExporter, Error> {
510 self.core.exporter()
511 }
512
513 /// Extract secrets, so they can be used when configuring kTLS, for example.
514 /// Should be used with care as it exposes secret key material.
515 pub fn dangerous_extract_secrets(self) -> Result<ExtractedSecrets, Error> {
516 self.core.dangerous_extract_secrets()
517 }
518
519 /// Sets a limit on the internal buffers used to buffer
520 /// unsent plaintext (prior to completing the TLS handshake)
521 /// and unsent TLS records. This limit acts only on application
522 /// data written through [`Connection::writer`].
523 ///
524 /// By default the limit is 64KB. The limit can be set
525 /// at any time, even if the current buffer use is higher.
526 ///
527 /// [`None`] means no limit applies, and will mean that written
528 /// data is buffered without bound -- it is up to the application
529 /// to appropriately schedule its plaintext and TLS writes to bound
530 /// memory usage.
531 ///
532 /// For illustration: `Some(1)` means a limit of one byte applies:
533 /// [`Connection::writer`] will accept only one byte, encrypt it and
534 /// add a TLS header. Once this is sent via [`Connection::write_tls`],
535 /// another byte may be sent.
536 ///
537 /// # Internal write-direction buffering
538 /// rustls has two buffers whose size are bounded by this setting:
539 ///
540 /// ## Buffering of unsent plaintext data prior to handshake completion
541 ///
542 /// Calls to [`Connection::writer`] before or during the handshake
543 /// are buffered (up to the limit specified here). Once the
544 /// handshake completes this data is encrypted and the resulting
545 /// TLS records are added to the outgoing buffer.
546 ///
547 /// ## Buffering of outgoing TLS records
548 ///
549 /// This buffer is used to store TLS records that rustls needs to
550 /// send to the peer. It is used in these two circumstances:
551 ///
552 /// - by [`Connection::process_new_packets`] when a handshake or alert
553 /// TLS record needs to be sent.
554 /// - by [`Connection::writer`] post-handshake: the plaintext is
555 /// encrypted and the resulting TLS record is buffered.
556 ///
557 /// This buffer is emptied by [`Connection::write_tls`].
558 ///
559 /// [`Connection::writer`]: crate::Connection::writer
560 /// [`Connection::write_tls`]: crate::Connection::write_tls
561 /// [`Connection::process_new_packets`]: crate::Connection::process_new_packets
562 pub fn set_buffer_limit(&mut self, limit: Option<usize>) {
563 self.sendable_plaintext.set_limit(limit);
564 self.send.sendable_tls.set_limit(limit);
565 }
566
567 /// Sets a limit on the internal buffers used to buffer decoded plaintext.
568 ///
569 /// See [`Self::set_buffer_limit`] for more information on how limits are applied.
570 pub fn set_plaintext_buffer_limit(&mut self, limit: Option<usize>) {
571 self.core
572 .side
573 .recv
574 .received_plaintext
575 .set_limit(limit);
576 }
577
578 /// Sends a TLS1.3 `key_update` message to refresh a connection's keys.
579 ///
580 /// This call refreshes our encryption keys. Once the peer receives the message,
581 /// it refreshes _its_ encryption and decryption keys and sends a response.
582 /// Once we receive that response, we refresh our decryption keys to match.
583 /// At the end of this process, keys in both directions have been refreshed.
584 ///
585 /// Note that this process does not happen synchronously: this call just
586 /// arranges that the `key_update` message will be included in the next
587 /// `write_tls` output.
588 ///
589 /// This fails with `Error::HandshakeNotComplete` if called before the initial
590 /// handshake is complete, or if a version prior to TLS1.3 is negotiated.
591 ///
592 /// # Usage advice
593 /// Note that other implementations (including rustls) may enforce limits on
594 /// the number of `key_update` messages allowed on a given connection to prevent
595 /// denial of service. Therefore, this should be called sparingly.
596 ///
597 /// rustls implicitly and automatically refreshes traffic keys when needed
598 /// according to the selected cipher suite's cryptographic constraints. There
599 /// is therefore no need to call this manually to avoid cryptographic keys
600 /// "wearing out".
601 ///
602 /// The main reason to call this manually is to roll keys when it is known
603 /// a connection will be idle for a long period.
604 pub fn refresh_traffic_keys(&mut self) -> Result<(), Error> {
605 self.core.refresh_traffic_keys()
606 }
607}
608
609#[cfg(feature = "std")]
610impl<Side: SideData> ConnectionCommon<Side> {
611 /// Returns an object that allows reading plaintext.
612 pub fn reader(&mut self) -> Reader<'_> {
613 let common = &mut self.core.side;
614 let has_seen_eof = common.recv.has_seen_eof;
615 let has_received_close_notify = common.recv.has_received_close_notify;
616 Reader {
617 received_plaintext: &mut common.recv.received_plaintext,
618 // Are we done? i.e., have we processed all received messages, and received a
619 // close_notify to indicate that no new messages will arrive?
620 has_received_close_notify,
621 has_seen_eof,
622 }
623 }
624
625 /// Returns an object that allows writing plaintext.
626 pub fn writer(&mut self) -> Writer<'_> {
627 Writer::new(self)
628 }
629
630 /// Extract the first handshake message.
631 ///
632 /// This is a shortcut to the `process_new_packets()` -> `process_msg()` ->
633 /// `process_handshake_messages()` path, specialized for the first handshake message.
634 pub(crate) fn first_handshake_message(&mut self) -> Result<Option<Input<'static>>, Error> {
635 let mut buffer_progress = self.core.hs_deframer.progress();
636
637 let res = self
638 .core
639 .deframe(self.deframer_buffer.filled_mut(), &mut buffer_progress)
640 .map(|opt| opt.map(|pm| Message::try_from(&pm).map(|m| m.into_owned())));
641
642 match res? {
643 Some(Ok(msg)) => {
644 self.deframer_buffer
645 .discard(buffer_progress.take_discard());
646 Ok(Some(Input {
647 message: msg,
648 aligned_handshake: self.core.hs_deframer.aligned(),
649 }))
650 }
651 Some(Err(err)) => Err(err.into()),
652 None => Ok(None),
653 }
654 }
655
656 pub(crate) fn replace_state(&mut self, new: Box<dyn State<Side>>) {
657 self.core.state = Ok(new);
658 }
659
660 /// Read TLS content from `rd` into the internal buffer.
661 ///
662 /// Due to the internal buffering, `rd` can supply TLS messages in arbitrary-sized chunks (like
663 /// a socket or pipe might).
664 ///
665 /// You should call [`process_new_packets()`] each time a call to this function succeeds in order
666 /// to empty the incoming TLS data buffer.
667 ///
668 /// This function returns `Ok(0)` when the underlying `rd` does so. This typically happens when
669 /// a socket is cleanly closed, or a file is at EOF. Errors may result from the IO done through
670 /// `rd`; additionally, errors of `ErrorKind::Other` are emitted to signal backpressure:
671 ///
672 /// * In order to empty the incoming TLS data buffer, you should call [`process_new_packets()`]
673 /// each time a call to this function succeeds.
674 /// * In order to empty the incoming plaintext data buffer, you should empty it through
675 /// the [`reader()`] after the call to [`process_new_packets()`].
676 ///
677 /// This function also returns `Ok(0)` once a `close_notify` alert has been successfully
678 /// received. No additional data is ever read in this state.
679 ///
680 /// [`process_new_packets()`]: ConnectionCommon::process_new_packets
681 /// [`reader()`]: ConnectionCommon::reader
682 pub fn read_tls(&mut self, rd: &mut dyn io::Read) -> Result<usize, io::Error> {
683 if self.recv.received_plaintext.is_full() {
684 return Err(io::Error::other("received plaintext buffer full"));
685 }
686
687 if self.recv.has_received_close_notify {
688 return Ok(0);
689 }
690
691 let res = self
692 .deframer_buffer
693 .read(rd, self.core.hs_deframer.is_active());
694 if let Ok(0) = res {
695 self.recv.has_seen_eof = true;
696 }
697 res
698 }
699
700 /// Writes TLS messages to `wr`.
701 ///
702 /// On success, this function returns `Ok(n)` where `n` is a number of bytes written to `wr`
703 /// (after encoding and encryption).
704 ///
705 /// After this function returns, the connection buffer may not yet be fully flushed. The
706 /// [`CommonState::wants_write`] function can be used to check if the output buffer is empty.
707 pub fn write_tls(&mut self, wr: &mut dyn io::Write) -> Result<usize, io::Error> {
708 self.send.sendable_tls.write_to(wr)
709 }
710}
711
712impl<Side: SideData> Deref for ConnectionCommon<Side> {
713 type Target = CommonState;
714
715 fn deref(&self) -> &Self::Target {
716 &self.core.side
717 }
718}
719
720impl<Side: SideData> DerefMut for ConnectionCommon<Side> {
721 fn deref_mut(&mut self) -> &mut Self::Target {
722 &mut self.core.side
723 }
724}
725
726impl<Side: SideData> From<ConnectionCore<Side>> for ConnectionCommon<Side> {
727 fn from(core: ConnectionCore<Side>) -> Self {
728 Self {
729 core,
730 deframer_buffer: DeframerVecBuffer::default(),
731 sendable_plaintext: ChunkVecBuffer::new(Some(DEFAULT_BUFFER_LIMIT)),
732 }
733 }
734}
735
736/// Interface shared by unbuffered client and server connections.
737pub struct UnbufferedConnectionCommon<Side: SideData> {
738 pub(crate) core: ConnectionCore<Side>,
739 wants_write: bool,
740 emitted_peer_closed_state: bool,
741}
742
743impl<Side: SideData> From<ConnectionCore<Side>> for UnbufferedConnectionCommon<Side> {
744 fn from(core: ConnectionCore<Side>) -> Self {
745 Self {
746 core,
747 wants_write: false,
748 emitted_peer_closed_state: false,
749 }
750 }
751}
752
753impl<Side: SideData> UnbufferedConnectionCommon<Side> {
754 /// Extract secrets, so they can be used when configuring kTLS, for example.
755 /// Should be used with care as it exposes secret key material.
756 pub fn dangerous_extract_secrets(self) -> Result<ExtractedSecrets, Error> {
757 self.core.dangerous_extract_secrets()
758 }
759}
760
761impl<Side: SideData> Deref for UnbufferedConnectionCommon<Side> {
762 type Target = CommonState;
763
764 fn deref(&self) -> &Self::Target {
765 &self.core.side
766 }
767}
768
769pub(crate) struct ConnectionCore<Side: SideData> {
770 pub(crate) state: Result<Box<dyn State<Side>>, Error>,
771 pub(crate) side: Side,
772 pub(crate) hs_deframer: HandshakeDeframer,
773
774 /// We limit consecutive empty fragments to avoid a route for the peer to send
775 /// us significant but fruitless traffic.
776 seen_consecutive_empty_fragments: u8,
777}
778
779impl<Side: SideData> ConnectionCore<Side> {
780 pub(crate) fn new(state: Box<dyn State<Side>>, side: Side) -> Self {
781 Self {
782 state: Ok(state),
783 side,
784 hs_deframer: HandshakeDeframer::default(),
785 seen_consecutive_empty_fragments: 0,
786 }
787 }
788
789 pub(crate) fn process_new_packets(
790 &mut self,
791 deframer_buffer: &mut DeframerVecBuffer,
792 ) -> Result<IoState, Error> {
793 let mut state = match mem::replace(&mut self.state, Err(Error::HandshakeNotComplete)) {
794 Ok(state) => state,
795 Err(e) => {
796 self.state = Err(e.clone());
797 return Err(e);
798 }
799 };
800
801 // Should `EncodedMessage<Payload>` resolve to plaintext application
802 // data it will be allocated within `plaintext` and written to
803 // `CommonState.received_plaintext` buffer.
804 //
805 // TODO `CommonState.received_plaintext` should be hoisted into
806 // `ConnectionCommon`
807 let mut plaintext = None;
808 let mut buffer_progress = self.hs_deframer.progress();
809
810 loop {
811 let buffer = deframer_buffer.filled_mut();
812 let locator = Locator::new(buffer);
813 let res = self.deframe(buffer, &mut buffer_progress);
814
815 let opt_msg = match res {
816 Ok(opt_msg) => opt_msg,
817 Err(e) => {
818 self.side
819 .send
820 .maybe_send_fatal_alert(&e);
821 if let Error::DecryptError = e {
822 state.handle_decrypt_error();
823 }
824 self.state = Err(e.clone());
825 deframer_buffer.discard(buffer_progress.take_discard());
826 return Err(e);
827 }
828 };
829
830 let Some(msg) = opt_msg else {
831 break;
832 };
833
834 match process_main_protocol(
835 msg,
836 self.hs_deframer.aligned(),
837 state,
838 &locator,
839 &mut plaintext,
840 &mut self.side,
841 ) {
842 Ok(new) => state = new,
843 Err(e) => {
844 self.side
845 .send
846 .maybe_send_fatal_alert(&e);
847 self.state = Err(e.clone());
848 deframer_buffer.discard(buffer_progress.take_discard());
849 return Err(e);
850 }
851 }
852
853 if self.side.recv.has_received_close_notify {
854 // "Any data received after a closure alert has been received MUST be ignored."
855 // -- <https://datatracker.ietf.org/doc/html/rfc8446#section-6.1>
856 // This is data that has already been accepted in `read_tls`.
857 buffer_progress.add_discard(deframer_buffer.filled().len());
858 break;
859 }
860
861 if let Some(payload) = plaintext.take() {
862 let payload = payload.reborrow(&Delocator::new(buffer));
863 self.side
864 .recv
865 .received_plaintext
866 .append(payload.into_vec());
867 }
868
869 deframer_buffer.discard(buffer_progress.take_discard());
870 }
871
872 deframer_buffer.discard(buffer_progress.take_discard());
873 self.state = Ok(state);
874 Ok(self.side.current_io_state())
875 }
876
877 /// Pull a message out of the deframer and send any messages that need to be sent as a result.
878 fn deframe<'b>(
879 &mut self,
880 buffer: &'b mut [u8],
881 buffer_progress: &mut BufferProgress,
882 ) -> Result<Option<EncodedMessage<&'b [u8]>>, Error> {
883 // before processing any more of `buffer`, return any extant messages from `hs_deframer`
884 if self.hs_deframer.has_message_ready() {
885 Ok(self.take_handshake_message(buffer, buffer_progress))
886 } else {
887 self.process_more_input(buffer, buffer_progress)
888 }
889 }
890
891 fn take_handshake_message<'b>(
892 &mut self,
893 buffer: &'b [u8],
894 buffer_progress: &mut BufferProgress,
895 ) -> Option<EncodedMessage<&'b [u8]>> {
896 self.hs_deframer
897 .iter(buffer)
898 .next()
899 .map(|(message, discard)| {
900 buffer_progress.add_discard(discard);
901 message
902 })
903 }
904
905 fn process_more_input<'b>(
906 &mut self,
907 buffer: &'b mut [u8],
908 buffer_progress: &mut BufferProgress,
909 ) -> Result<Option<EncodedMessage<&'b [u8]>>, Error> {
910 let version_is_tls13 =
911 matches!(self.side.negotiated_version, Some(ProtocolVersion::TLSv1_3));
912
913 let locator = Locator::new(buffer);
914
915 loop {
916 let mut iter = DeframerIter::new(&mut buffer[buffer_progress.processed()..]);
917
918 let (message, processed) = loop {
919 let message = match iter.next().transpose() {
920 Ok(Some(message)) => message,
921 Ok(None) => return Ok(None),
922 Err(err) => return Err(err),
923 };
924
925 let allowed_plaintext = match message.typ {
926 // CCS messages are always plaintext.
927 ContentType::ChangeCipherSpec => true,
928 // Alerts are allowed to be plaintext if-and-only-if:
929 // * The negotiated protocol version is TLS 1.3. - In TLS 1.2 it is unambiguous when
930 // keying changes based on the CCS message. Only TLS 1.3 requires these heuristics.
931 // * We have not yet decrypted any messages from the peer - if we have we don't
932 // expect any plaintext.
933 // * The payload size is indicative of a plaintext alert message.
934 ContentType::Alert
935 if version_is_tls13
936 && !self
937 .side
938 .recv
939 .decrypt_state
940 .has_decrypted()
941 && message.payload.len() <= 2 =>
942 {
943 true
944 }
945 // In other circumstances, we expect all messages to be encrypted.
946 _ => false,
947 };
948
949 if allowed_plaintext && !self.hs_deframer.is_active() {
950 break (message.into_plain_message(), iter.bytes_consumed());
951 }
952
953 let message = match self
954 .side
955 .recv
956 .decrypt_state
957 .decrypt_incoming(message)
958 {
959 // failed decryption during trial decryption is not allowed to be
960 // interleaved with partial handshake data.
961 Ok(None) if self.hs_deframer.aligned().is_none() => {
962 return Err(
963 PeerMisbehaved::RejectedEarlyDataInterleavedWithHandshakeMessage.into(),
964 );
965 }
966
967 // failed decryption during trial decryption.
968 Ok(None) => continue,
969
970 Ok(Some(message)) => message,
971
972 Err(err) => return Err(err),
973 };
974
975 let Decrypted {
976 want_close_before_decrypt,
977 plaintext,
978 } = message;
979
980 if want_close_before_decrypt {
981 self.side.send_close_notify();
982 }
983
984 break (plaintext, iter.bytes_consumed());
985 };
986
987 if self.hs_deframer.aligned().is_none() && message.typ != ContentType::Handshake {
988 // "Handshake messages MUST NOT be interleaved with other record
989 // types. That is, if a handshake message is split over two or more
990 // records, there MUST NOT be any other records between them."
991 // https://www.rfc-editor.org/rfc/rfc8446#section-5.1
992 return Err(PeerMisbehaved::MessageInterleavedWithHandshakeMessage.into());
993 }
994
995 match message.payload.len() {
996 0 => {
997 if self.seen_consecutive_empty_fragments
998 == ALLOWED_CONSECUTIVE_EMPTY_FRAGMENTS_MAX
999 {
1000 return Err(PeerMisbehaved::TooManyEmptyFragments.into());
1001 }
1002 self.seen_consecutive_empty_fragments += 1;
1003 }
1004 _ => {
1005 self.seen_consecutive_empty_fragments = 0;
1006 }
1007 };
1008
1009 buffer_progress.add_processed(processed);
1010
1011 // do an end-run around the borrow checker, converting `message` (containing
1012 // a borrowed slice) to an unborrowed one (containing a `Range` into the
1013 // same buffer). the reborrow happens inside the branch that returns the
1014 // message.
1015 //
1016 // is fixed by -Zpolonius
1017 // https://github.com/rust-lang/rfcs/blob/master/text/2094-nll.md#problem-case-3-conditional-control-flow-across-functions
1018 let unborrowed = InboundUnborrowedMessage::unborrow(&locator, message);
1019
1020 if unborrowed.typ != ContentType::Handshake {
1021 let message = unborrowed.reborrow(&Delocator::new(buffer));
1022 buffer_progress.add_discard(processed);
1023 return Ok(Some(message));
1024 }
1025
1026 let message = unborrowed.reborrow(&Delocator::new(buffer));
1027 self.hs_deframer
1028 .input_message(message, &locator, buffer_progress.processed());
1029 self.hs_deframer.coalesce(buffer)?;
1030
1031 if self.hs_deframer.has_message_ready() {
1032 // trial decryption finishes with the first handshake message after it started.
1033 self.side
1034 .recv
1035 .decrypt_state
1036 .finish_trial_decryption();
1037
1038 return Ok(self.take_handshake_message(buffer, buffer_progress));
1039 }
1040 }
1041 }
1042
1043 pub(crate) fn dangerous_extract_secrets(self) -> Result<ExtractedSecrets, Error> {
1044 Ok(self
1045 .dangerous_into_kernel_connection()?
1046 .0)
1047 }
1048
1049 pub(crate) fn dangerous_into_kernel_connection(
1050 self,
1051 ) -> Result<(ExtractedSecrets, KernelConnection<Side>), Error> {
1052 let common = self.side.into_common();
1053
1054 if common.is_handshaking() {
1055 return Err(Error::HandshakeNotComplete);
1056 }
1057
1058 if !common.send.sendable_tls.is_empty() {
1059 return Err(ApiMisuse::SecretExtractionWithPendingSendableData.into());
1060 }
1061
1062 let state = self.state?;
1063
1064 let read_seq = common.recv.decrypt_state.read_seq();
1065 let write_seq = common.send.encrypt_state.write_seq();
1066
1067 let (secrets, state) = state.into_external_state()?;
1068 let secrets = ExtractedSecrets {
1069 tx: (write_seq, secrets.tx),
1070 rx: (read_seq, secrets.rx),
1071 };
1072 let external = KernelConnection::new(state, common)?;
1073
1074 Ok((secrets, external))
1075 }
1076
1077 pub(crate) fn exporter(&mut self) -> Result<KeyingMaterialExporter, Error> {
1078 match self.side.exporter.take() {
1079 Some(inner) => Ok(KeyingMaterialExporter { inner }),
1080 None if self.side.is_handshaking() => Err(Error::HandshakeNotComplete),
1081 None => Err(ApiMisuse::ExporterAlreadyUsed.into()),
1082 }
1083 }
1084
1085 #[cfg(feature = "std")]
1086 pub(crate) fn early_exporter(&mut self) -> Result<KeyingMaterialExporter, Error> {
1087 match self.side.early_exporter.take() {
1088 Some(inner) => Ok(KeyingMaterialExporter { inner }),
1089 None => Err(ApiMisuse::ExporterAlreadyUsed.into()),
1090 }
1091 }
1092
1093 /// Trigger a `refresh_traffic_keys` if required by `CommonState`.
1094 fn maybe_refresh_traffic_keys(&mut self) {
1095 if mem::take(
1096 &mut self
1097 .side
1098 .send
1099 .refresh_traffic_keys_pending,
1100 ) {
1101 let _ = self.refresh_traffic_keys();
1102 }
1103 }
1104
1105 fn refresh_traffic_keys(&mut self) -> Result<(), Error> {
1106 match &mut self.state {
1107 Ok(st) => st.send_key_update_request(&mut self.side),
1108 Err(e) => Err(e.clone()),
1109 }
1110 }
1111}
1112
1113/// Data specific to the peer's side (client or server).
1114#[expect(private_bounds)]
1115pub trait SideData: private::SideData {}
1116
1117pub(crate) mod private {
1118 use super::*;
1119
1120 pub(crate) trait SideData:
1121 Output + Debug + Deref<Target = CommonState> + DerefMut
1122 {
1123 fn into_common(self) -> CommonState;
1124 }
1125}
1126
1127/// An [`EncodedMessage<Payload<'_>>`] which does not borrow its payload, but
1128/// references a range that can later be borrowed.
1129struct InboundUnborrowedMessage {
1130 typ: ContentType,
1131 version: ProtocolVersion,
1132 bounds: Range<usize>,
1133}
1134
1135impl InboundUnborrowedMessage {
1136 fn unborrow(locator: &Locator, msg: EncodedMessage<&'_ [u8]>) -> Self {
1137 Self {
1138 typ: msg.typ,
1139 version: msg.version,
1140 bounds: locator.locate(msg.payload),
1141 }
1142 }
1143
1144 fn reborrow<'b>(self, delocator: &Delocator<'b>) -> EncodedMessage<&'b [u8]> {
1145 EncodedMessage {
1146 typ: self.typ,
1147 version: self.version,
1148 payload: delocator.slice_from_range(&self.bounds),
1149 }
1150 }
1151}
1152
1153/// cf. BoringSSL's `kMaxEmptyRecords`
1154/// <https://github.com/google/boringssl/blob/dec5989b793c56ad4dd32173bd2d8595ca78b398/ssl/tls_record.cc#L124-L128>
1155const ALLOWED_CONSECUTIVE_EMPTY_FRAGMENTS_MAX: u8 = 32;