quic: fix detection of reserved bits in 1-RTT packets

The reserved bits are different for handshake and 1-RT packets.
We were incorrectly checking the same bits for both.

Remove the reservedBits field from longPacket/shortPacket.
The packet parse functions remove header protection from
the input packet, so the caller can just check the first
byte of the packet directly.

For golang/go#58547

Change-Id: Iee9ca5e88df140f115f63f63b5a0ea8d1ae02b95
Reviewed-on: https://go-review.googlesource.com/c/net/+/528697
Reviewed-by: Jonathan Amsterdam <jba@google.com>
LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>
diff --git a/internal/quic/conn_recv.go b/internal/quic/conn_recv.go
index b866d8a..92ee8ea 100644
--- a/internal/quic/conn_recv.go
+++ b/internal/quic/conn_recv.go
@@ -50,7 +50,8 @@
 	if n < 0 {
 		return -1
 	}
-	if p.reservedBits != 0 {
+	if buf[0]&reservedLongBits != 0 {
+		// Reserved header bits must be 0.
 		// https://www.rfc-editor.org/rfc/rfc9000#section-17.2-8.2.1
 		c.abort(now, localTransportError(errProtocolViolation))
 		return -1
@@ -89,7 +90,8 @@
 	if n < 0 {
 		return -1
 	}
-	if p.reservedBits != 0 {
+	if buf[0]&reserved1RTTBits != 0 {
+		// Reserved header bits must be 0.
 		// https://www.rfc-editor.org/rfc/rfc9000#section-17.3.1-4.8.1
 		c.abort(now, localTransportError(errProtocolViolation))
 		return -1
diff --git a/internal/quic/packet.go b/internal/quic/packet.go
index 00c6714..a1bcead 100644
--- a/internal/quic/packet.go
+++ b/internal/quic/packet.go
@@ -40,10 +40,11 @@
 
 // Bits set in the first byte of a packet.
 const (
-	headerFormLong  = 0x80 // https://www.rfc-editor.org/rfc/rfc9000.html#section-17.2-3.2.1
-	headerFormShort = 0x00 // https://www.rfc-editor.org/rfc/rfc9000.html#section-17.3.1-4.2.1
-	fixedBit        = 0x40 // https://www.rfc-editor.org/rfc/rfc9000.html#section-17.2-3.4.1
-	reservedBits    = 0x0c // https://www.rfc-editor.org/rfc/rfc9000#section-17.2-8.2.1
+	headerFormLong   = 0x80 // https://www.rfc-editor.org/rfc/rfc9000.html#section-17.2-3.2.1
+	headerFormShort  = 0x00 // https://www.rfc-editor.org/rfc/rfc9000.html#section-17.3.1-4.2.1
+	fixedBit         = 0x40 // https://www.rfc-editor.org/rfc/rfc9000.html#section-17.2-3.4.1
+	reservedLongBits = 0x0c // https://www.rfc-editor.org/rfc/rfc9000#section-17.2-8.2.1
+	reserved1RTTBits = 0x18 // https://www.rfc-editor.org/rfc/rfc9000#section-17.3.1-4.8.1
 )
 
 // Long Packet Type bits.
@@ -157,13 +158,12 @@
 
 // A longPacket is a long header packet.
 type longPacket struct {
-	ptype        packetType
-	reservedBits uint8
-	version      uint32
-	num          packetNumber
-	dstConnID    []byte
-	srcConnID    []byte
-	payload      []byte
+	ptype     packetType
+	version   uint32
+	num       packetNumber
+	dstConnID []byte
+	srcConnID []byte
+	payload   []byte
 
 	// The extra data depends on the packet type:
 	//   Initial: Token.
@@ -173,7 +173,6 @@
 
 // A shortPacket is a short header (1-RTT) packet.
 type shortPacket struct {
-	reservedBits uint8
-	num          packetNumber
-	payload      []byte
+	num     packetNumber
+	payload []byte
 }
diff --git a/internal/quic/packet_parser.go b/internal/quic/packet_parser.go
index ca5b37b..4323882 100644
--- a/internal/quic/packet_parser.go
+++ b/internal/quic/packet_parser.go
@@ -97,9 +97,6 @@
 		if err != nil {
 			return longPacket{}, -1
 		}
-		// Reserved bits should always be zero, but this is handled
-		// as a protocol-level violation by the caller rather than a parse error.
-		p.reservedBits = pkt[0] & reservedBits
 	}
 	return p, len(pkt)
 }
@@ -152,9 +149,6 @@
 	if err != nil {
 		return shortPacket{}, -1
 	}
-	// Reserved bits should always be zero, but this is handled
-	// as a protocol-level violation by the caller rather than a parse error.
-	p.reservedBits = pkt[0] & reservedBits
 	return p, len(pkt)
 }