Skip to content

Commit fe2aaec

Browse files
committed
quinn-rs#2057: Use randomly generated GREASE transport parameter.
1 parent 9386cde commit fe2aaec

File tree

1 file changed

+67
-3
lines changed

1 file changed

+67
-3
lines changed

quinn-proto/src/transport_parameters.rs

+67-3
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ use std::{
1212
};
1313

1414
use bytes::{Buf, BufMut};
15+
use rand::{Rng, RngCore};
1516
use thiserror::Error;
1617

1718
use crate::{
@@ -300,9 +301,7 @@ impl TransportParameters {
300301
}
301302
apply_params!(write_params);
302303

303-
// Add a reserved parameter to keep people on their toes
304-
w.write_var(31 * 5 + 27);
305-
w.write_var(0);
304+
write_random_grease_reserved_parameter(w, &mut rand::thread_rng());
306305

307306
if let Some(ref x) = self.stateless_reset_token {
308307
w.write_var(0x02);
@@ -476,6 +475,34 @@ fn decode_cid(len: usize, value: &mut Option<ConnectionId>, r: &mut impl Buf) ->
476475
Ok(())
477476
}
478477

478+
// Write transport parameter with up to 16 bytes of random payload and ID from reserved values.
479+
fn write_random_grease_reserved_parameter<W: BufMut, R: RngCore>(w: &mut W, rng: &mut R) {
480+
// See: https://datatracker.ietf.org/doc/html/rfc9000#section-22.3
481+
// Inspired by quic-go & quiche implementation:
482+
// [1] https://github.com/quic-go/quic-go/blob/3e0a67b2476e1819752f04d75968de042b197b56/internal/wire/transport_parameters.go#L338-L344
483+
// [2] https://github.com/google/quiche/blob/cb1090b20c40e2f0815107857324e99acf6ec567/quiche/quic/core/crypto/transport_parameters.cc#L843-L860
484+
485+
let id = {
486+
let rand = rng.next_u64();
487+
let n = (rand % ((1 << 62) - 27)) / 31;
488+
31 * n + 27
489+
};
490+
debug_assert!(id < (1 << 62));
491+
debug_assert!(id % 31 == 27);
492+
493+
let len = rng.gen_range(0..16);
494+
495+
let payload = {
496+
let mut slice = [0u8; 16];
497+
rng.fill_bytes(&mut slice[..len]);
498+
slice
499+
};
500+
501+
w.write_var(id);
502+
w.write_var(len as u64);
503+
w.put_slice(&payload[..len]);
504+
}
505+
479506
#[cfg(test)]
480507
mod test {
481508
use super::*;
@@ -507,6 +534,43 @@ mod test {
507534
);
508535
}
509536

537+
#[test]
538+
fn write_random_reserved_transport_parameter() {
539+
use rand::rngs::mock::StepRng;
540+
let mut rngs = [
541+
StepRng::new(0, 1),
542+
StepRng::new(1, 1),
543+
StepRng::new(27, 1),
544+
StepRng::new(31, 1),
545+
StepRng::new(u32::MAX as u64, 1),
546+
StepRng::new(u32::MAX as u64 - 1, 1),
547+
StepRng::new(u32::MAX as u64 + 1, 1),
548+
StepRng::new(u32::MAX as u64 - 27, 1),
549+
StepRng::new(u32::MAX as u64 + 27, 1),
550+
StepRng::new(u32::MAX as u64 - 31, 1),
551+
StepRng::new(u32::MAX as u64 + 31, 1),
552+
StepRng::new(u64::MAX as u64, 1),
553+
StepRng::new(u64::MAX as u64 - 1, 1),
554+
StepRng::new(u64::MAX as u64 - 27, 1),
555+
StepRng::new(u64::MAX as u64 - 31, 1),
556+
StepRng::new(1 << 62, 1),
557+
StepRng::new((1 << 62) - 1, 1),
558+
StepRng::new((1 << 62) + 1, 1),
559+
StepRng::new((1 << 62) - 27, 1),
560+
StepRng::new((1 << 62) + 27, 1),
561+
StepRng::new((1 << 62) - 31, 1),
562+
StepRng::new((1 << 62) + 31, 1),
563+
];
564+
for rng in &mut rngs {
565+
let mut buf = Vec::new();
566+
write_random_grease_reserved_parameter(&mut buf, rng);
567+
assert_eq!(
568+
TransportParameters::read(Side::Client, &mut buf.as_slice()).unwrap(),
569+
TransportParameters::default(),
570+
);
571+
}
572+
}
573+
510574
#[test]
511575
fn read_semantic_validation() {
512576
#[allow(clippy::type_complexity)]

0 commit comments

Comments
 (0)