1package quic 2 3import ( 4 "bytes" 5 "fmt" 6 "time" 7 8 "github.com/lucas-clemente/quic-go/internal/handshake" 9 "github.com/lucas-clemente/quic-go/internal/protocol" 10 "github.com/lucas-clemente/quic-go/internal/wire" 11) 12 13type headerDecryptor interface { 14 DecryptHeader(sample []byte, firstByte *byte, pnBytes []byte) 15} 16 17type headerParseError struct { 18 err error 19} 20 21func (e *headerParseError) Unwrap() error { 22 return e.err 23} 24 25func (e *headerParseError) Error() string { 26 return e.err.Error() 27} 28 29type 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. 37type packetUnpacker struct { 38 cs handshake.CryptoSetup 39 40 version protocol.VersionNumber 41} 42 43var _ unpacker = &packetUnpacker{} 44 45func 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. 55func (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 114func (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 134func (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. 160func (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 168func 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} 197