deframer.rs: clarifications & tidying

Try to make it clear which parts of this file are for the TLS
message protocol, and which are for the TLS handshake protocol.

Correct comments mentioning `buf`, vectors or an output frames
queue (these longer exist.)
This commit is contained in:
Joseph Birr-Pixton 2024-01-04 12:04:18 +00:00
parent 27d722beb4
commit c6a1e58954
1 changed files with 21 additions and 17 deletions

View File

@ -14,8 +14,9 @@ use crate::record_layer::{Decrypted, RecordLayer};
/// This deframer works to reconstruct TLS messages from a stream of arbitrary-sized reads.
///
/// It buffers incoming data into a `Vec` through `read()`, and returns messages through `pop()`.
/// QUIC connections will call `push()` to append handshake payload data directly.
/// It buffers incoming data into the supplied buffer through `read()`, and returns messages
/// through `pop()`. QUIC connections will call `push()` to append handshake payload data
/// directly.
#[derive(Default)]
pub struct MessageDeframer {
/// Set if the peer is not talking TLS, but some other
@ -49,6 +50,8 @@ impl MessageDeframer {
// For records that decrypt as `Handshake`, we keep the current state of the joined
// handshake message payload in `self.joining_hs`, appending to it as we see records.
let expected_len = loop {
// Fragmented handshake messages are collected (in plaintext) at the start of
// `buffer`, and the usage for this purpose is tracked by `joining_hs`.
let start = match &self.joining_hs {
Some(meta) => {
match meta.expected_len {
@ -63,9 +66,10 @@ impl MessageDeframer {
None => 0,
};
// Does our `buf` contain a full message? It does if it is big enough to
// contain a header, and that header has a length which falls within `buf`.
// If so, deframe it and place the message onto the frames output queue.
// The new data to parse exists starting at `start` in `buffer`.
// Does it contain a full message? It does if it is big enough to
// contain a header, and that header has a length which falls within the
// buffer.
let mut rd = codec::Reader::init(buffer.filled_get(start..));
let m = match OpaqueMessage::read(&mut rd) {
Ok(m) => m,
@ -190,7 +194,7 @@ impl MessageDeframer {
// `expected_len` to match the state of that remaining payload.
meta.payload.start += expected_len;
meta.expected_len =
payload_size(buffer.filled_get(meta.payload.start..meta.payload.end))?;
handshake_payload_size(buffer.filled_get(meta.payload.start..meta.payload.end))?;
} else {
// Otherwise, we've yielded the last handshake payload in the buffer, so we can
// discard all of the bytes that we're previously buffered as handshake data.
@ -238,7 +242,7 @@ impl MessageDeframer {
/// Write the handshake message contents into the buffer and update the metadata.
///
/// Returns true if a complete message is found.
/// Returns [`HandshakePayloadState::Complete`] if a complete message is found.
fn append_hs<T: DeframerBuffer<QUIC>, const QUIC: bool>(
&mut self,
version: ProtocolVersion,
@ -259,8 +263,9 @@ impl MessageDeframer {
// If we haven't parsed the payload size yet, try to do so now.
if meta.expected_len.is_none() {
meta.expected_len =
payload_size(buffer.filled_get(meta.payload.start..meta.payload.end))?;
meta.expected_len = handshake_payload_size(
buffer.filled_get(meta.payload.start..meta.payload.end),
)?;
}
meta
@ -269,7 +274,7 @@ impl MessageDeframer {
// We've found a new handshake message here.
// Write it into the buffer and create the metadata.
let expected_len = payload_size(payload)?;
let expected_len = handshake_payload_size(payload)?;
DeframerBuffer::<QUIC>::copy(buffer, payload, 0);
self.joining_hs
.insert(HandshakePayloadMeta {
@ -294,8 +299,7 @@ impl MessageDeframer {
})
}
/// Read some bytes from `rd`, and add them to our internal buffer.
#[allow(clippy::comparison_chain)]
/// Read some bytes from `rd`, and add them to the supplied buffer.
pub fn read(
&mut self,
rd: &mut dyn io::Read,
@ -543,17 +547,17 @@ struct HandshakePayloadMeta {
/// Returns `Err` if the advertised length is larger than what we want to accept
/// (`MAX_HANDSHAKE_SIZE`), `Ok(None)` if the buffer is too small to contain a complete header,
/// and `Ok(Some(len))` otherwise.
fn payload_size(buf: &[u8]) -> Result<Option<usize>, Error> {
if buf.len() < HEADER_SIZE {
fn handshake_payload_size(buf: &[u8]) -> Result<Option<usize>, Error> {
if buf.len() < HANDSHAKE_HEADER_SIZE {
return Ok(None);
}
let (header, _) = buf.split_at(HEADER_SIZE);
let (header, _) = buf.split_at(HANDSHAKE_HEADER_SIZE);
match codec::u24::read_bytes(&header[1..]) {
Ok(len) if len.0 > MAX_HANDSHAKE_SIZE => Err(Error::InvalidMessage(
InvalidMessage::HandshakePayloadTooLarge,
)),
Ok(len) => Ok(Some(HEADER_SIZE + usize::from(len))),
Ok(len) => Ok(Some(HANDSHAKE_HEADER_SIZE + usize::from(len))),
_ => Ok(None),
}
}
@ -566,7 +570,7 @@ pub struct Deframed {
pub message: PlainMessage,
}
const HEADER_SIZE: usize = 1 + 3;
const HANDSHAKE_HEADER_SIZE: usize = 1 + 3;
/// TLS allows for handshake messages of up to 16MB. We
/// restrict that to 64KB to limit potential for denial-of-