From a7f807856cf74836e6734ea04620679a21fcaf95 Mon Sep 17 00:00:00 2001 From: Marten Seemann Date: Mon, 11 Sep 2023 11:49:29 +0700 Subject: [PATCH] randomize the serialization order of control frames (#4069) * randomize the serialization order of control frames * add comment for packetPacker.appendPacketPayload --- packet_packer.go | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/packet_packer.go b/packet_packer.go index 577f3b04..0483f35b 100644 --- a/packet_packer.go +++ b/packet_packer.go @@ -1,9 +1,13 @@ package quic import ( + crand "crypto/rand" + "encoding/binary" "errors" "fmt" + "golang.org/x/exp/rand" + "github.com/quic-go/quic-go/internal/ackhandler" "github.com/quic-go/quic-go/internal/handshake" "github.com/quic-go/quic-go/internal/protocol" @@ -122,6 +126,7 @@ type packetPacker struct { acks ackFrameSource datagramQueue *datagramQueue retransmissionQueue *retransmissionQueue + rand rand.Rand numNonAckElicitingAcks int } @@ -140,6 +145,9 @@ func newPacketPacker( datagramQueue *datagramQueue, perspective protocol.Perspective, ) *packetPacker { + var b [8]byte + _, _ = crand.Read(b[:]) + return &packetPacker{ cryptoSetup: cryptoSetup, getDestConnID: getDestConnID, @@ -151,6 +159,7 @@ func newPacketPacker( perspective: perspective, framer: framer, acks: acks, + rand: *rand.New(rand.NewSource(binary.BigEndian.Uint64(b[:]))), pnManager: packetNumberManager, } } @@ -832,6 +841,8 @@ func (p *packetPacker) appendShortHeaderPacket( }, nil } +// appendPacketPayload serializes the payload of a packet into the raw byte slice. +// It modifies the order of payload.frames. func (p *packetPacker) appendPacketPayload(raw []byte, pl payload, paddingLen protocol.ByteCount, v protocol.VersionNumber) ([]byte, error) { payloadOffset := len(raw) if pl.ack != nil { @@ -844,6 +855,11 @@ func (p *packetPacker) appendPacketPayload(raw []byte, pl payload, paddingLen pr if paddingLen > 0 { raw = append(raw, make([]byte, paddingLen)...) } + // Randomize the order of the control frames. + // This makes sure that the receiver doesn't rely on the order in which frames are packed. + if len(pl.frames) > 1 { + p.rand.Shuffle(len(pl.frames), func(i, j int) { pl.frames[i], pl.frames[j] = pl.frames[j], pl.frames[i] }) + } for _, f := range pl.frames { var err error raw, err = f.Frame.Append(raw, v)