diff --git a/internal/protocol/protocol.go b/internal/protocol/protocol.go index eb245e88..2821d2cd 100644 --- a/internal/protocol/protocol.go +++ b/internal/protocol/protocol.go @@ -27,14 +27,14 @@ const ( type PacketType uint8 const ( - // PacketTypeInitial is the packet type of a Initial packet - PacketTypeInitial PacketType = 2 + // PacketTypeInitial is the packet type of an Initial packet + PacketTypeInitial PacketType = 0x7f // PacketTypeRetry is the packet type of a Retry packet - PacketTypeRetry PacketType = 3 - // PacketTypeHandshake is the packet type of a Cleartext packet - PacketTypeHandshake PacketType = 4 + PacketTypeRetry PacketType = 0x7e + // PacketTypeHandshake is the packet type of a Handshake packet + PacketTypeHandshake PacketType = 0x7d // PacketType0RTT is the packet type of a 0-RTT packet - PacketType0RTT PacketType = 5 + PacketType0RTT PacketType = 0x7c ) func (t PacketType) String() string { diff --git a/internal/wire/header.go b/internal/wire/header.go index 19c45c3e..207312ff 100644 --- a/internal/wire/header.go +++ b/internal/wire/header.go @@ -50,6 +50,7 @@ func ParseHeaderSentByServer(b *bytes.Reader, version protocol.VersionNumber) (* // the client knows the version that this packet was sent with isPublicHeader = !version.UsesTLS() } + return parsePacketHeader(b, protocol.PerspectiveServer, isPublicHeader) } @@ -61,12 +62,13 @@ func ParseHeaderSentByClient(b *bytes.Reader) (*Header, error) { } _ = b.UnreadByte() // unread the type byte - // If this is a gQUIC header 0x80 and 0x40 will be set to 0. - // If this is an IETF QUIC header there are two options: - // * either 0x80 will be 1 (for the Long Header) - // * or 0x40 (the Connection ID Flag) will be 0 (for the Short Header), since we don't the client to omit it - isPublicHeader := typeByte&0xc0 == 0 - + // In an IETF QUIC packet header + // * either 0x80 is set (for the Long Header) + // * or 0x8 is unset (for the Short Header) + // In a gQUIC Public Header + // * 0x80 is always unset and + // * and 0x8 is always set (this is the Connection ID flag, which the client always sets) + isPublicHeader := typeByte&0x88 == 0x8 return parsePacketHeader(b, protocol.PerspectiveClient, isPublicHeader) } diff --git a/internal/wire/header_test.go b/internal/wire/header_test.go index 0d636035..a6128c7a 100644 --- a/internal/wire/header_test.go +++ b/internal/wire/header_test.go @@ -21,7 +21,7 @@ var _ = Describe("Header", func() { Context("parsing", func() { It("parses an IETF draft Short Header, when the QUIC version supports TLS", func() { buf := &bytes.Buffer{} - // use a short header, which isn't distinguishable from the gQUIC Public Header when looking at the type byte + // use a Short Header, which isn't distinguishable from the gQUIC Public Header when looking at the type byte err := (&Header{ IsLongHeader: false, KeyPhase: 1, @@ -53,7 +53,7 @@ var _ = Describe("Header", func() { Expect(hdr.Version).To(Equal(protocol.VersionNumber(0x1234))) }) - It("doens't mistake packets with a Short Header for Version Negotiation Packets", func() { + It("doesn't mistake packets with a Short Header for Version Negotiation Packets", func() { // make sure this packet could be mistaken for a Version Negotiation Packet, if we only look at the 0x1 bit buf := &bytes.Buffer{} err := (&Header{ @@ -62,7 +62,6 @@ var _ = Describe("Header", func() { PacketNumber: 0x42, }).writeHeader(buf) Expect(err).ToNot(HaveOccurred()) - Expect(buf.Bytes()[0] & 0x1).To(BeEquivalentTo(0x1)) hdr, err := ParseHeaderSentByServer(bytes.NewReader(buf.Bytes()), versionIETFHeader) Expect(err).ToNot(HaveOccurred()) Expect(hdr.isPublicHeader).To(BeFalse()) diff --git a/internal/wire/ietf_header.go b/internal/wire/ietf_header.go index 60e4dd0f..6d18ef39 100644 --- a/internal/wire/ietf_header.go +++ b/internal/wire/ietf_header.go @@ -2,6 +2,7 @@ package wire import ( "bytes" + "errors" "fmt" "github.com/lucas-clemente/quic-go/internal/protocol" @@ -71,26 +72,40 @@ func parseLongHeader(b *bytes.Reader, sentBy protocol.Perspective, typeByte byte } func parseShortHeader(b *bytes.Reader, typeByte byte) (*Header, error) { - hasConnID := typeByte&0x40 > 0 + omitConnID := typeByte&0x40 > 0 var connID uint64 - if hasConnID { + if !omitConnID { var err error connID, err = utils.BigEndian.ReadUint64(b) if err != nil { return nil, err } } - pnLen := 1 << ((typeByte & 0x3) - 1) + // bit 4 must be set, bit 5 must be unset + if typeByte&0x18 != 0x10 { + return nil, errors.New("invalid bit 4 and 5") + } + var pnLen protocol.PacketNumberLen + switch typeByte & 0x7 { + case 0x0: + pnLen = protocol.PacketNumberLen1 + case 0x1: + pnLen = protocol.PacketNumberLen2 + case 0x2: + pnLen = protocol.PacketNumberLen4 + default: + return nil, errors.New("invalid short header type") + } pn, err := utils.BigEndian.ReadUintN(b, uint8(pnLen)) if err != nil { return nil, err } return &Header{ KeyPhase: int(typeByte&0x20) >> 5, - OmitConnectionID: !hasConnID, + OmitConnectionID: omitConnID, ConnectionID: protocol.ConnectionID(connID), PacketNumber: protocol.PacketNumber(pn), - PacketNumberLen: protocol.PacketNumberLen(pnLen), + PacketNumberLen: pnLen, }, nil } @@ -112,17 +127,17 @@ func (h *Header) writeLongHeader(b *bytes.Buffer) error { } func (h *Header) writeShortHeader(b *bytes.Buffer) error { - typeByte := byte(h.KeyPhase << 5) - if !h.OmitConnectionID { + typeByte := byte(0x10) + typeByte ^= byte(h.KeyPhase << 5) + if h.OmitConnectionID { typeByte ^= 0x40 } switch h.PacketNumberLen { case protocol.PacketNumberLen1: - typeByte ^= 0x1 case protocol.PacketNumberLen2: - typeByte ^= 0x2 + typeByte ^= 0x1 case protocol.PacketNumberLen4: - typeByte ^= 0x3 + typeByte ^= 0x2 default: return fmt.Errorf("invalid packet number length: %d", h.PacketNumberLen) } diff --git a/internal/wire/ietf_header_test.go b/internal/wire/ietf_header_test.go index de69ddf1..9eecde82 100644 --- a/internal/wire/ietf_header_test.go +++ b/internal/wire/ietf_header_test.go @@ -115,7 +115,7 @@ var _ = Describe("IETF draft Header", func() { Context("short headers", func() { It("reads a short header with a connection ID", func() { data := []byte{ - 0x40 ^ 0x1, // + 0x10, // 1 byte packet number 0xde, 0xad, 0xbe, 0xef, 0xca, 0xfe, 0x13, 0x37, // connection ID 0x42, // packet number } @@ -133,7 +133,7 @@ var _ = Describe("IETF draft Header", func() { It("reads the Key Phase Bit", func() { data := []byte{ - 0x20 ^ 0x1, + 0x10 ^ 0x40 ^ 0x20, 0x11, } b := bytes.NewReader(data) @@ -146,7 +146,7 @@ var _ = Describe("IETF draft Header", func() { It("reads a header with omitted connection ID", func() { data := []byte{ - 0x1, + 0x10 ^ 0x40, 0x21, // packet number } b := bytes.NewReader(data) @@ -161,7 +161,7 @@ var _ = Describe("IETF draft Header", func() { It("reads a header with a 2 byte packet number", func() { data := []byte{ - 0x2, + 0x10 ^ 0x40 ^ 0x1, 0x13, 0x37, // packet number } b := bytes.NewReader(data) @@ -175,7 +175,7 @@ var _ = Describe("IETF draft Header", func() { It("reads a header with a 4 byte packet number", func() { data := []byte{ - 0x3, + 0x10 ^ 0x40 ^ 0x2, 0xde, 0xad, 0xbe, 0xef, // packet number } b := bytes.NewReader(data) @@ -189,7 +189,7 @@ var _ = Describe("IETF draft Header", func() { It("errors on EOF", func() { data := []byte{ - 0x40 ^ 0x3, + 0x10 ^ 0x2, 0xde, 0xad, 0xbe, 0xef, 0xca, 0xfe, 0x13, 0x37, // connection ID 0xde, 0xca, 0xfb, 0xad, // packet number } @@ -236,7 +236,7 @@ var _ = Describe("IETF draft Header", func() { }).writeHeader(buf) Expect(err).ToNot(HaveOccurred()) Expect(buf.Bytes()).To(Equal([]byte{ - 0x40 ^ 0x1, + 0x10, 0xde, 0xad, 0xbe, 0xef, 0xca, 0xfe, 0x13, 0x37, // connection ID 0x42, // packet number })) @@ -250,7 +250,7 @@ var _ = Describe("IETF draft Header", func() { }).writeHeader(buf) Expect(err).ToNot(HaveOccurred()) Expect(buf.Bytes()).To(Equal([]byte{ - 0x1, + 0x10 ^ 0x40, 0x42, // packet number })) }) @@ -263,7 +263,7 @@ var _ = Describe("IETF draft Header", func() { }).writeHeader(buf) Expect(err).ToNot(HaveOccurred()) Expect(buf.Bytes()).To(Equal([]byte{ - 0x2, + 0x10 ^ 0x40 ^ 0x1, 0x13, 0x37, // packet number })) }) @@ -276,7 +276,7 @@ var _ = Describe("IETF draft Header", func() { }).writeHeader(buf) Expect(err).ToNot(HaveOccurred()) Expect(buf.Bytes()).To(Equal([]byte{ - 0x3, + 0x10 ^ 0x40 ^ 0x2, 0xde, 0xca, 0xfb, 0xad, // packet number })) }) @@ -299,7 +299,7 @@ var _ = Describe("IETF draft Header", func() { }).writeHeader(buf) Expect(err).ToNot(HaveOccurred()) Expect(buf.Bytes()).To(Equal([]byte{ - 0x20 ^ 0x1, + 0x10 ^ 0x40 ^ 0x20, 0x42, // packet number })) })