summaryrefslogtreecommitdiff
path: root/src/lib.rs
diff options
context:
space:
mode:
authorGravatar Junho Choi <junho@cloudflare.com> 2021-05-03 12:04:31 -0700
committerGravatar Alessandro Ghedini <alessandro@ghedini.me> 2021-05-05 10:07:47 +0100
commit720cd94a0966c0d3ba3818b98ec94e5ea4e5d4d1 (patch)
tree068d6130771d0ec0accf5358a21d6bf528eee713 /src/lib.rs
parent4fbbc0d882717b366082373638edb0a97d557f7f (diff)
downloadquiche-720cd94a0966c0d3ba3818b98ec94e5ea4e5d4d1.tar.gz
quiche-720cd94a0966c0d3ba3818b98ec94e5ea4e5d4d1.tar.zst
quiche-720cd94a0966c0d3ba3818b98ec94e5ea4e5d4d1.zip
check the packet length against the buffer size
When we queue 0-rtt packets in undecryptable_pkts, there is a case that actual packet length is smaller than the size in the payload (packet length field) which may cause a runtime panic. Such packet is undecryptable in any way, so check it early and return error.
Diffstat (limited to '')
-rw-r--r--src/lib.rs71
1 files changed, 70 insertions, 1 deletions
diff --git a/src/lib.rs b/src/lib.rs
index 1a3d6d6e..db472c46 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -1834,6 +1834,17 @@ impl Connection {
})? as usize
};
+ // Make sure the buffer is same or larger than an explicit
+ // payload length.
+ if payload_len > b.cap() {
+ return Err(drop_pkt_on_err(
+ Error::InvalidPacket,
+ self.recv_count,
+ self.is_server,
+ &self.trace_id,
+ ));
+ }
+
// Derive initial secrets on the server.
if !self.derived_initial_secrets {
let (aead_open, aead_seal) = crypto::derive_initial_key_material(
@@ -5967,6 +5978,64 @@ mod tests {
}
#[test]
+ fn handshake_0rtt_truncated() {
+ let mut buf = [0; 65535];
+
+ let mut config = Config::new(crate::PROTOCOL_VERSION).unwrap();
+ config
+ .load_cert_chain_from_pem_file("examples/cert.crt")
+ .unwrap();
+ config
+ .load_priv_key_from_pem_file("examples/cert.key")
+ .unwrap();
+ config
+ .set_application_protos(b"\x06proto1\x06proto2")
+ .unwrap();
+ config.set_initial_max_data(30);
+ config.set_initial_max_stream_data_bidi_local(15);
+ config.set_initial_max_stream_data_bidi_remote(15);
+ config.set_initial_max_streams_bidi(3);
+ config.enable_early_data();
+ config.verify_peer(false);
+
+ // Perform initial handshake.
+ let mut pipe = testing::Pipe::with_config(&mut config).unwrap();
+ assert_eq!(pipe.handshake(), Ok(()));
+
+ // Extract session,
+ let session = pipe.client.session().unwrap();
+
+ // Configure session on new connection.
+ let mut pipe = testing::Pipe::with_config(&mut config).unwrap();
+ assert_eq!(pipe.client.set_session(&session), Ok(()));
+
+ // Client sends initial flight.
+ pipe.client.send(&mut buf).unwrap();
+
+ // Client sends 0-RTT packet.
+ let pkt_type = packet::Type::ZeroRTT;
+
+ let frames = [frame::Frame::Stream {
+ stream_id: 4,
+ data: stream::RangeBuf::from(b"aaaaa", 0, true),
+ }];
+
+ let len =
+ testing::encode_pkt(&mut pipe.client, pkt_type, &frames, &mut buf)
+ .unwrap();
+
+ // Simulate a truncated packet by sending one byte less.
+ let mut zrtt = (&buf[..len - 1]).to_vec();
+
+ // 0-RTT packet is received before the Initial one.
+ assert_eq!(pipe.server.recv(&mut zrtt), Err(Error::InvalidPacket));
+
+ assert_eq!(pipe.server.undecryptable_pkts.len(), 0);
+
+ assert!(pipe.server.is_closed());
+ }
+
+ #[test]
/// Tests that a pre-v1 client can connect to a v1-enabled server, by making
/// the server downgrade to the pre-v1 version.
fn handshake_downgrade_v1() {
@@ -7655,7 +7724,7 @@ mod tests {
assert_eq!(
pipe.server.recv(&mut buf[..written]),
- Err(Error::BufferTooShort)
+ Err(Error::InvalidPacket)
);
assert!(pipe.server.is_closed());