packet_unpacker.go 5.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170
  1. package quic
  2. import (
  3. "bytes"
  4. "fmt"
  5. "time"
  6. "github.com/lucas-clemente/quic-go/internal/handshake"
  7. "github.com/lucas-clemente/quic-go/internal/protocol"
  8. "github.com/lucas-clemente/quic-go/internal/utils"
  9. "github.com/lucas-clemente/quic-go/internal/wire"
  10. )
  11. type headerDecryptor interface {
  12. DecryptHeader(sample []byte, firstByte *byte, pnBytes []byte)
  13. }
  14. type unpackedPacket struct {
  15. packetNumber protocol.PacketNumber // the decoded packet number
  16. hdr *wire.ExtendedHeader
  17. encryptionLevel protocol.EncryptionLevel
  18. data []byte
  19. }
  20. // The packetUnpacker unpacks QUIC packets.
  21. type packetUnpacker struct {
  22. cs handshake.CryptoSetup
  23. largestRcvdPacketNumber protocol.PacketNumber
  24. version protocol.VersionNumber
  25. }
  26. var _ unpacker = &packetUnpacker{}
  27. func newPacketUnpacker(cs handshake.CryptoSetup, version protocol.VersionNumber) unpacker {
  28. return &packetUnpacker{
  29. cs: cs,
  30. version: version,
  31. }
  32. }
  33. func (u *packetUnpacker) Unpack(hdr *wire.Header, rcvTime time.Time, data []byte) (*unpackedPacket, error) {
  34. var encLevel protocol.EncryptionLevel
  35. var extHdr *wire.ExtendedHeader
  36. var decrypted []byte
  37. switch hdr.Type {
  38. case protocol.PacketTypeInitial:
  39. encLevel = protocol.EncryptionInitial
  40. opener, err := u.cs.GetInitialOpener()
  41. if err != nil {
  42. return nil, err
  43. }
  44. extHdr, decrypted, err = u.unpackLongHeaderPacket(opener, hdr, data)
  45. if err != nil {
  46. return nil, err
  47. }
  48. case protocol.PacketTypeHandshake:
  49. encLevel = protocol.EncryptionHandshake
  50. opener, err := u.cs.GetHandshakeOpener()
  51. if err != nil {
  52. return nil, err
  53. }
  54. extHdr, decrypted, err = u.unpackLongHeaderPacket(opener, hdr, data)
  55. if err != nil {
  56. return nil, err
  57. }
  58. default:
  59. if hdr.IsLongHeader {
  60. return nil, fmt.Errorf("unknown packet type: %s", hdr.Type)
  61. }
  62. encLevel = protocol.Encryption1RTT
  63. opener, err := u.cs.Get1RTTOpener()
  64. if err != nil {
  65. return nil, err
  66. }
  67. extHdr, decrypted, err = u.unpackShortHeaderPacket(opener, hdr, rcvTime, data)
  68. if err != nil {
  69. return nil, err
  70. }
  71. }
  72. // Only do this after decrypting, so we are sure the packet is not attacker-controlled
  73. u.largestRcvdPacketNumber = utils.MaxPacketNumber(u.largestRcvdPacketNumber, extHdr.PacketNumber)
  74. return &unpackedPacket{
  75. hdr: extHdr,
  76. packetNumber: extHdr.PacketNumber,
  77. encryptionLevel: encLevel,
  78. data: decrypted,
  79. }, nil
  80. }
  81. func (u *packetUnpacker) unpackLongHeaderPacket(opener handshake.LongHeaderOpener, hdr *wire.Header, data []byte) (*wire.ExtendedHeader, []byte, error) {
  82. extHdr, parseErr := u.unpack(opener, hdr, data)
  83. // If the reserved bits are set incorrectly, we still need to continue unpacking.
  84. // This avoids a timing side-channel, which otherwise might allow an attacker
  85. // to gain information about the header encryption.
  86. if parseErr != nil && parseErr != wire.ErrInvalidReservedBits {
  87. return nil, nil, fmt.Errorf("error parsing extended header: %s", parseErr)
  88. }
  89. extHdrLen := extHdr.GetLength(u.version)
  90. decrypted, err := opener.Open(data[extHdrLen:extHdrLen], data[extHdrLen:], extHdr.PacketNumber, data[:extHdrLen])
  91. if err != nil {
  92. return nil, nil, err
  93. }
  94. if parseErr != nil {
  95. return nil, nil, parseErr
  96. }
  97. return extHdr, decrypted, nil
  98. }
  99. func (u *packetUnpacker) unpackShortHeaderPacket(
  100. opener handshake.ShortHeaderOpener,
  101. hdr *wire.Header,
  102. rcvTime time.Time,
  103. data []byte,
  104. ) (*wire.ExtendedHeader, []byte, error) {
  105. extHdr, parseErr := u.unpack(opener, hdr, data)
  106. // If the reserved bits are set incorrectly, we still need to continue unpacking.
  107. // This avoids a timing side-channel, which otherwise might allow an attacker
  108. // to gain information about the header encryption.
  109. if parseErr != nil && parseErr != wire.ErrInvalidReservedBits {
  110. return nil, nil, parseErr
  111. }
  112. extHdrLen := extHdr.GetLength(u.version)
  113. decrypted, err := opener.Open(data[extHdrLen:extHdrLen], data[extHdrLen:], rcvTime, extHdr.PacketNumber, extHdr.KeyPhase, data[:extHdrLen])
  114. if err != nil {
  115. return nil, nil, err
  116. }
  117. if parseErr != nil {
  118. return nil, nil, parseErr
  119. }
  120. return extHdr, decrypted, nil
  121. }
  122. func (u *packetUnpacker) unpack(hd headerDecryptor, hdr *wire.Header, data []byte) (*wire.ExtendedHeader, error) {
  123. r := bytes.NewReader(data)
  124. hdrLen := int(hdr.ParsedLen())
  125. if len(data) < hdrLen+4+16 {
  126. return nil, fmt.Errorf("Packet too small. Expected at least 20 bytes after the header, got %d", len(data)-hdrLen)
  127. }
  128. // The packet number can be up to 4 bytes long, but we won't know the length until we decrypt it.
  129. // 1. save a copy of the 4 bytes
  130. origPNBytes := make([]byte, 4)
  131. copy(origPNBytes, data[hdrLen:hdrLen+4])
  132. // 2. decrypt the header, assuming a 4 byte packet number
  133. hd.DecryptHeader(
  134. data[hdrLen+4:hdrLen+4+16],
  135. &data[0],
  136. data[hdrLen:hdrLen+4],
  137. )
  138. // 3. parse the header (and learn the actual length of the packet number)
  139. extHdr, parseErr := hdr.ParseExtended(r, u.version)
  140. if parseErr != nil && parseErr != wire.ErrInvalidReservedBits {
  141. return nil, parseErr
  142. }
  143. // 4. if the packet number is shorter than 4 bytes, replace the remaining bytes with the copy we saved earlier
  144. if extHdr.PacketNumberLen != protocol.PacketNumberLen4 {
  145. copy(data[extHdr.GetLength(u.version):hdrLen+4], origPNBytes[int(extHdr.PacketNumberLen):])
  146. }
  147. extHdr.PacketNumber = protocol.DecodePacketNumber(
  148. extHdr.PacketNumberLen,
  149. u.largestRcvdPacketNumber,
  150. extHdr.PacketNumber,
  151. )
  152. return extHdr, parseErr
  153. }