github.com/ooni/psiphon/tunnel-core@v0.0.0-20230105123940-fe12a24c96ee/oovendor/quic-go/packet_unpacker.go (about)

     1  package quic
     2  
     3  import (
     4  	"bytes"
     5  	"fmt"
     6  	"time"
     7  
     8  	"github.com/ooni/psiphon/tunnel-core/oovendor/quic-go/internal/handshake"
     9  	"github.com/ooni/psiphon/tunnel-core/oovendor/quic-go/internal/protocol"
    10  	"github.com/ooni/psiphon/tunnel-core/oovendor/quic-go/internal/wire"
    11  )
    12  
    13  type headerDecryptor interface {
    14  	DecryptHeader(sample []byte, firstByte *byte, pnBytes []byte)
    15  }
    16  
    17  type headerParseError struct {
    18  	err error
    19  }
    20  
    21  func (e *headerParseError) Unwrap() error {
    22  	return e.err
    23  }
    24  
    25  func (e *headerParseError) Error() string {
    26  	return e.err.Error()
    27  }
    28  
    29  type unpackedPacket struct {
    30  	packetNumber    protocol.PacketNumber // the decoded packet number
    31  	hdr             *wire.ExtendedHeader
    32  	encryptionLevel protocol.EncryptionLevel
    33  	data            []byte
    34  }
    35  
    36  // The packetUnpacker unpacks QUIC packets.
    37  type packetUnpacker struct {
    38  	cs handshake.CryptoSetup
    39  
    40  	version protocol.VersionNumber
    41  }
    42  
    43  var _ unpacker = &packetUnpacker{}
    44  
    45  func newPacketUnpacker(cs handshake.CryptoSetup, version protocol.VersionNumber) unpacker {
    46  	return &packetUnpacker{
    47  		cs:      cs,
    48  		version: version,
    49  	}
    50  }
    51  
    52  // If the reserved bits are invalid, the error is wire.ErrInvalidReservedBits.
    53  // If any other error occurred when parsing the header, the error is of type headerParseError.
    54  // If decrypting the payload fails for any reason, the error is the error returned by the AEAD.
    55  func (u *packetUnpacker) Unpack(hdr *wire.Header, rcvTime time.Time, data []byte) (*unpackedPacket, error) {
    56  	var encLevel protocol.EncryptionLevel
    57  	var extHdr *wire.ExtendedHeader
    58  	var decrypted []byte
    59  	//nolint:exhaustive // Retry packets can't be unpacked.
    60  	switch hdr.Type {
    61  	case protocol.PacketTypeInitial:
    62  		encLevel = protocol.EncryptionInitial
    63  		opener, err := u.cs.GetInitialOpener()
    64  		if err != nil {
    65  			return nil, err
    66  		}
    67  		extHdr, decrypted, err = u.unpackLongHeaderPacket(opener, hdr, data)
    68  		if err != nil {
    69  			return nil, err
    70  		}
    71  	case protocol.PacketTypeHandshake:
    72  		encLevel = protocol.EncryptionHandshake
    73  		opener, err := u.cs.GetHandshakeOpener()
    74  		if err != nil {
    75  			return nil, err
    76  		}
    77  		extHdr, decrypted, err = u.unpackLongHeaderPacket(opener, hdr, data)
    78  		if err != nil {
    79  			return nil, err
    80  		}
    81  	case protocol.PacketType0RTT:
    82  		encLevel = protocol.Encryption0RTT
    83  		opener, err := u.cs.Get0RTTOpener()
    84  		if err != nil {
    85  			return nil, err
    86  		}
    87  		extHdr, decrypted, err = u.unpackLongHeaderPacket(opener, hdr, data)
    88  		if err != nil {
    89  			return nil, err
    90  		}
    91  	default:
    92  		if hdr.IsLongHeader {
    93  			return nil, fmt.Errorf("unknown packet type: %s", hdr.Type)
    94  		}
    95  		encLevel = protocol.Encryption1RTT
    96  		opener, err := u.cs.Get1RTTOpener()
    97  		if err != nil {
    98  			return nil, err
    99  		}
   100  		extHdr, decrypted, err = u.unpackShortHeaderPacket(opener, hdr, rcvTime, data)
   101  		if err != nil {
   102  			return nil, err
   103  		}
   104  	}
   105  
   106  	return &unpackedPacket{
   107  		hdr:             extHdr,
   108  		packetNumber:    extHdr.PacketNumber,
   109  		encryptionLevel: encLevel,
   110  		data:            decrypted,
   111  	}, nil
   112  }
   113  
   114  func (u *packetUnpacker) unpackLongHeaderPacket(opener handshake.LongHeaderOpener, hdr *wire.Header, data []byte) (*wire.ExtendedHeader, []byte, error) {
   115  	extHdr, parseErr := u.unpackHeader(opener, hdr, data)
   116  	// If the reserved bits are set incorrectly, we still need to continue unpacking.
   117  	// This avoids a timing side-channel, which otherwise might allow an attacker
   118  	// to gain information about the header encryption.
   119  	if parseErr != nil && parseErr != wire.ErrInvalidReservedBits {
   120  		return nil, nil, parseErr
   121  	}
   122  	extHdrLen := extHdr.ParsedLen()
   123  	extHdr.PacketNumber = opener.DecodePacketNumber(extHdr.PacketNumber, extHdr.PacketNumberLen)
   124  	decrypted, err := opener.Open(data[extHdrLen:extHdrLen], data[extHdrLen:], extHdr.PacketNumber, data[:extHdrLen])
   125  	if err != nil {
   126  		return nil, nil, err
   127  	}
   128  	if parseErr != nil {
   129  		return nil, nil, parseErr
   130  	}
   131  	return extHdr, decrypted, nil
   132  }
   133  
   134  func (u *packetUnpacker) unpackShortHeaderPacket(
   135  	opener handshake.ShortHeaderOpener,
   136  	hdr *wire.Header,
   137  	rcvTime time.Time,
   138  	data []byte,
   139  ) (*wire.ExtendedHeader, []byte, error) {
   140  	extHdr, parseErr := u.unpackHeader(opener, hdr, data)
   141  	// If the reserved bits are set incorrectly, we still need to continue unpacking.
   142  	// This avoids a timing side-channel, which otherwise might allow an attacker
   143  	// to gain information about the header encryption.
   144  	if parseErr != nil && parseErr != wire.ErrInvalidReservedBits {
   145  		return nil, nil, parseErr
   146  	}
   147  	extHdr.PacketNumber = opener.DecodePacketNumber(extHdr.PacketNumber, extHdr.PacketNumberLen)
   148  	extHdrLen := extHdr.ParsedLen()
   149  	decrypted, err := opener.Open(data[extHdrLen:extHdrLen], data[extHdrLen:], rcvTime, extHdr.PacketNumber, extHdr.KeyPhase, data[:extHdrLen])
   150  	if err != nil {
   151  		return nil, nil, err
   152  	}
   153  	if parseErr != nil {
   154  		return nil, nil, parseErr
   155  	}
   156  	return extHdr, decrypted, nil
   157  }
   158  
   159  // The error is either nil, a wire.ErrInvalidReservedBits or of type headerParseError.
   160  func (u *packetUnpacker) unpackHeader(hd headerDecryptor, hdr *wire.Header, data []byte) (*wire.ExtendedHeader, error) {
   161  	extHdr, err := unpackHeader(hd, hdr, data, u.version)
   162  	if err != nil && err != wire.ErrInvalidReservedBits {
   163  		return nil, &headerParseError{err: err}
   164  	}
   165  	return extHdr, err
   166  }
   167  
   168  func unpackHeader(hd headerDecryptor, hdr *wire.Header, data []byte, version protocol.VersionNumber) (*wire.ExtendedHeader, error) {
   169  	r := bytes.NewReader(data)
   170  
   171  	hdrLen := hdr.ParsedLen()
   172  	if protocol.ByteCount(len(data)) < hdrLen+4+16 {
   173  		//nolint:stylecheck
   174  		return nil, fmt.Errorf("Packet too small. Expected at least 20 bytes after the header, got %d", protocol.ByteCount(len(data))-hdrLen)
   175  	}
   176  	// The packet number can be up to 4 bytes long, but we won't know the length until we decrypt it.
   177  	// 1. save a copy of the 4 bytes
   178  	origPNBytes := make([]byte, 4)
   179  	copy(origPNBytes, data[hdrLen:hdrLen+4])
   180  	// 2. decrypt the header, assuming a 4 byte packet number
   181  	hd.DecryptHeader(
   182  		data[hdrLen+4:hdrLen+4+16],
   183  		&data[0],
   184  		data[hdrLen:hdrLen+4],
   185  	)
   186  	// 3. parse the header (and learn the actual length of the packet number)
   187  	extHdr, parseErr := hdr.ParseExtended(r, version)
   188  	if parseErr != nil && parseErr != wire.ErrInvalidReservedBits {
   189  		return nil, parseErr
   190  	}
   191  	// 4. if the packet number is shorter than 4 bytes, replace the remaining bytes with the copy we saved earlier
   192  	if extHdr.PacketNumberLen != protocol.PacketNumberLen4 {
   193  		copy(data[extHdr.ParsedLen():hdrLen+4], origPNBytes[int(extHdr.PacketNumberLen):])
   194  	}
   195  	return extHdr, parseErr
   196  }