package crypto import ( "encoding/binary" "errors" "github.com/lucas-clemente/fnv128a" "github.com/lucas-clemente/quic-go/protocol" ) // nullAEAD handles not-yet encrypted packets type nullAEAD struct { perspective protocol.Perspective version protocol.VersionNumber } var _ AEAD = &nullAEAD{} // NewNullAEAD creates a NullAEAD func NewNullAEAD(p protocol.Perspective, v protocol.VersionNumber) AEAD { return &nullAEAD{ perspective: p, version: v, } } // Open and verify the ciphertext func (n *nullAEAD) Open(dst, src []byte, packetNumber protocol.PacketNumber, associatedData []byte) ([]byte, error) { if len(src) < 12 { return nil, errors.New("NullAEAD: ciphertext cannot be less than 12 bytes long") } hash := fnv128a.New() hash.Write(associatedData) hash.Write(src[12:]) if n.version >= protocol.Version37 { if n.perspective == protocol.PerspectiveServer { hash.Write([]byte("Client")) } else { hash.Write([]byte("Server")) } } testHigh, testLow := hash.Sum128() low := binary.LittleEndian.Uint64(src) high := binary.LittleEndian.Uint32(src[8:]) if uint32(testHigh&0xffffffff) != high || testLow != low { return nil, errors.New("NullAEAD: failed to authenticate received data") } return src[12:], nil } // Seal writes hash and ciphertext to the buffer func (n *nullAEAD) Seal(dst, src []byte, packetNumber protocol.PacketNumber, associatedData []byte) []byte { if cap(dst) < 12+len(src) { dst = make([]byte, 12+len(src)) } else { dst = dst[:12+len(src)] } hash := fnv128a.New() hash.Write(associatedData) hash.Write(src) if n.version >= protocol.Version37 { if n.perspective == protocol.PerspectiveServer { hash.Write([]byte("Server")) } else { hash.Write([]byte("Client")) } } high, low := hash.Sum128() copy(dst[12:], src) binary.LittleEndian.PutUint64(dst, low) binary.LittleEndian.PutUint32(dst[8:], uint32(high)) return dst }