forked from quic-go/quic-go
fix timing side channel when reading headers with invalid reserved bits
This commit is contained in:
@@ -91,28 +91,40 @@ func (u *packetUnpacker) Unpack(hdr *wire.Header, data []byte) (*unpackedPacket,
|
||||
}
|
||||
|
||||
func (u *packetUnpacker) unpackLongHeaderPacket(opener handshake.LongHeaderOpener, hdr *wire.Header, data []byte) (*wire.ExtendedHeader, []byte, error) {
|
||||
extHdr, err := u.unpack(opener, hdr, data)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
extHdr, parseErr := u.unpack(opener, hdr, data)
|
||||
// If the reserved bits are set incorrectly, we still need to continue unpacking.
|
||||
// This avoids a timing side-channel, which otherwise might allow an attacker
|
||||
// to gain information about the header encryption.
|
||||
if parseErr != nil && parseErr != wire.ErrInvalidReservedBits {
|
||||
return nil, nil, fmt.Errorf("error parsing extended header: %s", parseErr)
|
||||
}
|
||||
extHdrLen := extHdr.GetLength(u.version)
|
||||
decrypted, err := opener.Open(data[extHdrLen:extHdrLen], data[extHdrLen:], extHdr.PacketNumber, data[:extHdrLen])
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
if parseErr != nil {
|
||||
return nil, nil, parseErr
|
||||
}
|
||||
return extHdr, decrypted, nil
|
||||
}
|
||||
|
||||
func (u *packetUnpacker) unpackShortHeaderPacket(opener handshake.ShortHeaderOpener, hdr *wire.Header, data []byte) (*wire.ExtendedHeader, []byte, error) {
|
||||
extHdr, err := u.unpack(opener, hdr, data)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
extHdr, parseErr := u.unpack(opener, hdr, data)
|
||||
// If the reserved bits are set incorrectly, we still need to continue unpacking.
|
||||
// This avoids a timing side-channel, which otherwise might allow an attacker
|
||||
// to gain information about the header encryption.
|
||||
if parseErr != nil && parseErr != wire.ErrInvalidReservedBits {
|
||||
return nil, nil, parseErr
|
||||
}
|
||||
extHdrLen := extHdr.GetLength(u.version)
|
||||
decrypted, err := opener.Open(data[extHdrLen:extHdrLen], data[extHdrLen:], extHdr.PacketNumber, extHdr.KeyPhase, data[:extHdrLen])
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
if parseErr != nil {
|
||||
return nil, nil, parseErr
|
||||
}
|
||||
return extHdr, decrypted, nil
|
||||
}
|
||||
|
||||
@@ -134,9 +146,9 @@ func (u *packetUnpacker) unpack(hd headerDecryptor, hdr *wire.Header, data []byt
|
||||
data[hdrLen:hdrLen+4],
|
||||
)
|
||||
// 3. parse the header (and learn the actual length of the packet number)
|
||||
extHdr, err := hdr.ParseExtended(r, u.version)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("error parsing extended header: %s", err)
|
||||
extHdr, parseErr := hdr.ParseExtended(r, u.version)
|
||||
if parseErr != nil && parseErr != wire.ErrInvalidReservedBits {
|
||||
return nil, parseErr
|
||||
}
|
||||
// 4. if the packet number is shorter than 4 bytes, replace the remaining bytes with the copy we saved earlier
|
||||
if extHdr.PacketNumberLen != protocol.PacketNumberLen4 {
|
||||
@@ -148,5 +160,5 @@ func (u *packetUnpacker) unpack(hd headerDecryptor, hdr *wire.Header, data []byt
|
||||
u.largestRcvdPacketNumber,
|
||||
extHdr.PacketNumber,
|
||||
)
|
||||
return extHdr, nil
|
||||
return extHdr, parseErr
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user