mirror of
https://github.com/refraction-networking/uquic.git
synced 2025-04-03 20:27:35 +03:00
fix decoding of packet numbers in different packet number spaces
When QUIC abandoned the "stream 0" design, it introduced separate packet number spaces for packets with different encryption levels. Packet number compression now also works per packet number space. The current code doesn't lead to any problems if the peer starts sending with packet number 0, as we only exchange a few packets in the Initial and the Handshake packet number space and there's nothing to compress. It might lead to problems if the peer starts with a large packet number in one space (which is allowed by the spec), and then starts with a small packet number in another packet number space.
This commit is contained in:
parent
ed1956f5a9
commit
95334202c5
9 changed files with 125 additions and 57 deletions
|
@ -5,14 +5,14 @@ import (
|
|||
"errors"
|
||||
"time"
|
||||
|
||||
"github.com/lucas-clemente/quic-go/internal/qerr"
|
||||
|
||||
"github.com/golang/mock/gomock"
|
||||
"github.com/lucas-clemente/quic-go/internal/handshake"
|
||||
"github.com/lucas-clemente/quic-go/internal/mocks"
|
||||
"github.com/lucas-clemente/quic-go/internal/protocol"
|
||||
"github.com/lucas-clemente/quic-go/internal/qerr"
|
||||
"github.com/lucas-clemente/quic-go/internal/wire"
|
||||
|
||||
"github.com/golang/mock/gomock"
|
||||
|
||||
. "github.com/onsi/ginkgo"
|
||||
. "github.com/onsi/gomega"
|
||||
)
|
||||
|
@ -97,9 +97,12 @@ var _ = Describe("Packet Unpacker", func() {
|
|||
}
|
||||
hdr, hdrRaw := getHeader(extHdr)
|
||||
opener := mocks.NewMockLongHeaderOpener(mockCtrl)
|
||||
cs.EXPECT().GetInitialOpener().Return(opener, nil)
|
||||
opener.EXPECT().DecryptHeader(gomock.Any(), gomock.Any(), gomock.Any())
|
||||
opener.EXPECT().Open(gomock.Any(), payload, extHdr.PacketNumber, hdrRaw).Return([]byte("decrypted"), nil)
|
||||
gomock.InOrder(
|
||||
cs.EXPECT().GetInitialOpener().Return(opener, nil),
|
||||
opener.EXPECT().DecryptHeader(gomock.Any(), gomock.Any(), gomock.Any()),
|
||||
opener.EXPECT().DecodePacketNumber(protocol.PacketNumber(2), protocol.PacketNumberLen3).Return(protocol.PacketNumber(1234)),
|
||||
opener.EXPECT().Open(gomock.Any(), payload, protocol.PacketNumber(1234), hdrRaw).Return([]byte("decrypted"), nil),
|
||||
)
|
||||
packet, err := unpacker.Unpack(hdr, time.Now(), append(hdrRaw, payload...))
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
Expect(packet.encryptionLevel).To(Equal(protocol.EncryptionInitial))
|
||||
|
@ -115,20 +118,45 @@ var _ = Describe("Packet Unpacker", func() {
|
|||
DestConnectionID: connID,
|
||||
Version: version,
|
||||
},
|
||||
PacketNumber: 2,
|
||||
PacketNumberLen: 3,
|
||||
PacketNumber: 20,
|
||||
PacketNumberLen: 2,
|
||||
}
|
||||
hdr, hdrRaw := getHeader(extHdr)
|
||||
opener := mocks.NewMockLongHeaderOpener(mockCtrl)
|
||||
cs.EXPECT().Get0RTTOpener().Return(opener, nil)
|
||||
opener.EXPECT().DecryptHeader(gomock.Any(), gomock.Any(), gomock.Any())
|
||||
opener.EXPECT().Open(gomock.Any(), payload, extHdr.PacketNumber, hdrRaw).Return([]byte("decrypted"), nil)
|
||||
gomock.InOrder(
|
||||
cs.EXPECT().Get0RTTOpener().Return(opener, nil),
|
||||
opener.EXPECT().DecryptHeader(gomock.Any(), gomock.Any(), gomock.Any()),
|
||||
opener.EXPECT().DecodePacketNumber(protocol.PacketNumber(20), protocol.PacketNumberLen2).Return(protocol.PacketNumber(321)),
|
||||
opener.EXPECT().Open(gomock.Any(), payload, protocol.PacketNumber(321), hdrRaw).Return([]byte("decrypted"), nil),
|
||||
)
|
||||
packet, err := unpacker.Unpack(hdr, time.Now(), append(hdrRaw, payload...))
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
Expect(packet.encryptionLevel).To(Equal(protocol.Encryption0RTT))
|
||||
Expect(packet.data).To(Equal([]byte("decrypted")))
|
||||
})
|
||||
|
||||
It("opens short header packets", func() {
|
||||
extHdr := &wire.ExtendedHeader{
|
||||
Header: wire.Header{DestConnectionID: connID},
|
||||
KeyPhase: protocol.KeyPhaseOne,
|
||||
PacketNumber: 99,
|
||||
PacketNumberLen: protocol.PacketNumberLen4,
|
||||
}
|
||||
hdr, hdrRaw := getHeader(extHdr)
|
||||
opener := mocks.NewMockShortHeaderOpener(mockCtrl)
|
||||
now := time.Now()
|
||||
gomock.InOrder(
|
||||
cs.EXPECT().Get1RTTOpener().Return(opener, nil),
|
||||
opener.EXPECT().DecryptHeader(gomock.Any(), gomock.Any(), gomock.Any()),
|
||||
opener.EXPECT().DecodePacketNumber(protocol.PacketNumber(99), protocol.PacketNumberLen4).Return(protocol.PacketNumber(321)),
|
||||
opener.EXPECT().Open(gomock.Any(), payload, now, protocol.PacketNumber(321), protocol.KeyPhaseOne, hdrRaw).Return([]byte("decrypted"), nil),
|
||||
)
|
||||
packet, err := unpacker.Unpack(hdr, now, append(hdrRaw, payload...))
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
Expect(packet.encryptionLevel).To(Equal(protocol.Encryption1RTT))
|
||||
Expect(packet.data).To(Equal([]byte("decrypted")))
|
||||
})
|
||||
|
||||
It("returns the error when getting the sealer fails", func() {
|
||||
extHdr := &wire.ExtendedHeader{
|
||||
Header: wire.Header{DestConnectionID: connID},
|
||||
|
@ -157,6 +185,7 @@ var _ = Describe("Packet Unpacker", func() {
|
|||
opener := mocks.NewMockLongHeaderOpener(mockCtrl)
|
||||
cs.EXPECT().GetHandshakeOpener().Return(opener, nil)
|
||||
opener.EXPECT().DecryptHeader(gomock.Any(), gomock.Any(), gomock.Any())
|
||||
opener.EXPECT().DecodePacketNumber(gomock.Any(), gomock.Any())
|
||||
opener.EXPECT().Open(gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any()).Return(nil, qerr.CryptoBufferExceeded)
|
||||
_, err := unpacker.Unpack(hdr, time.Now(), append(hdrRaw, payload...))
|
||||
Expect(err).To(MatchError(qerr.CryptoBufferExceeded))
|
||||
|
@ -178,6 +207,7 @@ var _ = Describe("Packet Unpacker", func() {
|
|||
opener := mocks.NewMockLongHeaderOpener(mockCtrl)
|
||||
opener.EXPECT().DecryptHeader(gomock.Any(), gomock.Any(), gomock.Any())
|
||||
cs.EXPECT().GetHandshakeOpener().Return(opener, nil)
|
||||
opener.EXPECT().DecodePacketNumber(gomock.Any(), gomock.Any())
|
||||
opener.EXPECT().Open(gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any()).Return([]byte("payload"), nil)
|
||||
_, err := unpacker.Unpack(hdr, time.Now(), append(hdrRaw, payload...))
|
||||
Expect(err).To(MatchError(wire.ErrInvalidReservedBits))
|
||||
|
@ -194,6 +224,7 @@ var _ = Describe("Packet Unpacker", func() {
|
|||
opener := mocks.NewMockShortHeaderOpener(mockCtrl)
|
||||
opener.EXPECT().DecryptHeader(gomock.Any(), gomock.Any(), gomock.Any())
|
||||
cs.EXPECT().Get1RTTOpener().Return(opener, nil)
|
||||
opener.EXPECT().DecodePacketNumber(gomock.Any(), gomock.Any())
|
||||
opener.EXPECT().Open(gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any()).Return([]byte("payload"), nil)
|
||||
_, err := unpacker.Unpack(hdr, time.Now(), append(hdrRaw, payload...))
|
||||
Expect(err).To(MatchError(wire.ErrInvalidReservedBits))
|
||||
|
@ -210,6 +241,7 @@ var _ = Describe("Packet Unpacker", func() {
|
|||
opener := mocks.NewMockShortHeaderOpener(mockCtrl)
|
||||
opener.EXPECT().DecryptHeader(gomock.Any(), gomock.Any(), gomock.Any())
|
||||
cs.EXPECT().Get1RTTOpener().Return(opener, nil)
|
||||
opener.EXPECT().DecodePacketNumber(gomock.Any(), gomock.Any())
|
||||
opener.EXPECT().Open(gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any()).Return(nil, handshake.ErrDecryptionFailed)
|
||||
_, err := unpacker.Unpack(hdr, time.Now(), append(hdrRaw, payload...))
|
||||
Expect(err).To(MatchError(handshake.ErrDecryptionFailed))
|
||||
|
@ -247,7 +279,8 @@ var _ = Describe("Packet Unpacker", func() {
|
|||
pnBytes[i] ^= 0xff // invert the packet number bytes
|
||||
}
|
||||
}),
|
||||
opener.EXPECT().Open(gomock.Any(), gomock.Any(), protocol.PacketNumber(0x1337), origHdrRaw).Return([]byte{0}, nil),
|
||||
opener.EXPECT().DecodePacketNumber(protocol.PacketNumber(0x1337), protocol.PacketNumberLen2).Return(protocol.PacketNumber(0x7331)),
|
||||
opener.EXPECT().Open(gomock.Any(), gomock.Any(), protocol.PacketNumber(0x7331), origHdrRaw).Return([]byte{0}, nil),
|
||||
)
|
||||
data := hdrRaw
|
||||
for i := 1; i <= 100; i++ {
|
||||
|
@ -255,38 +288,6 @@ var _ = Describe("Packet Unpacker", func() {
|
|||
}
|
||||
packet, err := unpacker.Unpack(hdr, time.Now(), data)
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
Expect(packet.packetNumber).To(Equal(protocol.PacketNumber(0x1337)))
|
||||
})
|
||||
|
||||
It("decodes the packet number", func() {
|
||||
rcvTime := time.Now().Add(-time.Hour)
|
||||
firstHdr := &wire.ExtendedHeader{
|
||||
Header: wire.Header{DestConnectionID: connID},
|
||||
PacketNumber: 0x1337,
|
||||
PacketNumberLen: 2,
|
||||
KeyPhase: protocol.KeyPhaseOne,
|
||||
}
|
||||
opener := mocks.NewMockShortHeaderOpener(mockCtrl)
|
||||
cs.EXPECT().Get1RTTOpener().Return(opener, nil).Times(2)
|
||||
opener.EXPECT().DecryptHeader(gomock.Any(), gomock.Any(), gomock.Any())
|
||||
opener.EXPECT().Open(gomock.Any(), gomock.Any(), rcvTime, firstHdr.PacketNumber, protocol.KeyPhaseOne, gomock.Any()).Return([]byte{0}, nil)
|
||||
hdr, hdrRaw := getHeader(firstHdr)
|
||||
packet, err := unpacker.Unpack(hdr, rcvTime, append(hdrRaw, payload...))
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
Expect(packet.packetNumber).To(Equal(protocol.PacketNumber(0x1337)))
|
||||
// the real packet number is 0x1338, but only the last byte is sent
|
||||
secondHdr := &wire.ExtendedHeader{
|
||||
Header: wire.Header{DestConnectionID: connID},
|
||||
PacketNumber: 0x38,
|
||||
PacketNumberLen: 1,
|
||||
KeyPhase: protocol.KeyPhaseZero,
|
||||
}
|
||||
// expect the call with the decoded packet number
|
||||
opener.EXPECT().DecryptHeader(gomock.Any(), gomock.Any(), gomock.Any())
|
||||
opener.EXPECT().Open(gomock.Any(), gomock.Any(), rcvTime, protocol.PacketNumber(0x1338), protocol.KeyPhaseZero, gomock.Any()).Return([]byte{0}, nil)
|
||||
hdr, hdrRaw = getHeader(secondHdr)
|
||||
packet, err = unpacker.Unpack(hdr, rcvTime, append(hdrRaw, payload...))
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
Expect(packet.packetNumber).To(Equal(protocol.PacketNumber(0x1338)))
|
||||
Expect(packet.packetNumber).To(Equal(protocol.PacketNumber(0x7331)))
|
||||
})
|
||||
})
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue