// Copyright 2010 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

// TLS low level connection and record layer

package runner

import (
	"bytes"
	"crypto/aes"
	"crypto/cipher"
	"crypto/ecdsa"
	"crypto/subtle"
	"crypto/x509"
	"encoding/binary"
	"errors"
	"fmt"
	"io"
	"net"
	"slices"
	"sync"
	"time"

	"golang.org/x/crypto/chacha20"
	"golang.org/x/crypto/cryptobyte"
)

// A Conn represents a secured connection.
// It implements the net.Conn interface.
type Conn struct {
	// constant
	conn     net.Conn
	isDTLS   bool
	isClient bool

	// constant after handshake; protected by handshakeMutex
	handshakeMutex          sync.Mutex // handshakeMutex < in.Mutex, out.Mutex, errMutex
	handshakeErr            error      // error resulting from handshake
	wireVersion             uint16     // TLS wire version
	vers                    uint16     // TLS version
	haveVers                bool       // version has been negotiated
	config                  *Config    // configuration passed to constructor
	handshakeComplete       bool
	skipEarlyData           bool // On a server, indicates that the client is sending early data that must be skipped over.
	didResume               bool // whether this connection was a session resumption
	extendedMasterSecret    bool // whether this session used an extended master secret
	cipherSuite             *cipherSuite
	ocspResponse            []byte // stapled OCSP response
	sctList                 []byte // signed certificate timestamp list
	peerCertificates        []*x509.Certificate
	peerDelegatedCredential []byte
	// verifiedChains contains the certificate chains that we built, as
	// opposed to the ones presented by the server.
	verifiedChains [][]*x509.Certificate
	// serverName contains the server name indicated by the client, if any.
	serverName string
	// firstFinished contains the first Finished hash sent during the
	// handshake. This is the "tls-unique" channel binding value.
	firstFinished [12]byte
	// peerSignatureAlgorithm contains the signature algorithm that was used
	// by the peer in the handshake, or zero if not applicable.
	peerSignatureAlgorithm signatureAlgorithm
	// curveID contains the curve that was used in the handshake, or zero if
	// not applicable.
	curveID CurveID
	// quicTransportParams contains the QUIC transport params received
	// by the peer using codepoint 57.
	quicTransportParams []byte
	// quicTransportParams contains the QUIC transport params received
	// by the peer using legacy codepoint 0xffa5.
	quicTransportParamsLegacy []byte

	clientRandom, serverRandom [32]byte
	earlyExporterSecret        []byte
	exporterSecret             []byte
	resumptionSecret           []byte

	clientProtocol         string
	clientProtocolFallback bool
	usedALPN               bool

	localApplicationSettings, peerApplicationSettings       []byte
	hasApplicationSettings                                  bool
	localApplicationSettingsOld, peerApplicationSettingsOld []byte
	hasApplicationSettingsOld                               bool

	// verify_data values for the renegotiation extension.
	clientVerify []byte
	serverVerify []byte

	channelID *ecdsa.PublicKey

	srtpProtectionProfile uint16

	clientVersion uint16

	// input/output
	in, out  halfConn     // in.Mutex < out.Mutex
	rawInput bytes.Buffer // raw input, right off the wire
	input    bytes.Buffer // application record waiting to be read
	hand     bytes.Buffer // handshake record waiting to be read

	// pendingFlight, if PackHandshakeFlight is enabled, is the buffer of
	// handshake data to be split into records at the end of the flight.
	pendingFlight bytes.Buffer

	// DTLS state
	sendHandshakeSeq uint16
	recvHandshakeSeq uint16
	handMsg          []byte   // pending assembled handshake message
	handMsgLen       int      // handshake message length, not including the header
	pendingFragments [][]byte // pending outgoing handshake fragments.
	pendingPacket    []byte   // pending outgoing packet.

	keyUpdateSeen      bool
	keyUpdateRequested bool
	seenOneByteRecord  bool

	expectTLS13ChangeCipherSpec bool

	// seenHandshakePackEnd is whether the most recent handshake record was
	// not full for ExpectPackedEncryptedHandshake. If true, no more
	// handshake data may be received until the next flight or epoch change.
	seenHandshakePackEnd bool

	// echAccepted indicates whether ECH was accepted for this connection.
	echAccepted bool

	tmp [16]byte
}

func (c *Conn) init() {
	c.in.isDTLS = c.isDTLS
	c.out.isDTLS = c.isDTLS
	c.in.config = c.config
	c.out.config = c.config
	c.in.conn = c
	c.out.conn = c
}

// Access to net.Conn methods.
// Cannot just embed net.Conn because that would
// export the struct field too.

// LocalAddr returns the local network address.
func (c *Conn) LocalAddr() net.Addr {
	return c.conn.LocalAddr()
}

// RemoteAddr returns the remote network address.
func (c *Conn) RemoteAddr() net.Addr {
	return c.conn.RemoteAddr()
}

// SetDeadline sets the read and write deadlines associated with the connection.
// A zero value for t means Read and Write will not time out.
// After a Write has timed out, the TLS state is corrupt and all future writes will return the same error.
func (c *Conn) SetDeadline(t time.Time) error {
	return c.conn.SetDeadline(t)
}

// SetReadDeadline sets the read deadline on the underlying connection.
// A zero value for t means Read will not time out.
func (c *Conn) SetReadDeadline(t time.Time) error {
	return c.conn.SetReadDeadline(t)
}

// SetWriteDeadline sets the write deadline on the underlying conneciton.
// A zero value for t means Write will not time out.
// After a Write has timed out, the TLS state is corrupt and all future writes will return the same error.
func (c *Conn) SetWriteDeadline(t time.Time) error {
	return c.conn.SetWriteDeadline(t)
}

// A halfConn represents one direction of the record layer
// connection, either sending or receiving.
type halfConn struct {
	sync.Mutex

	err                   error  // first permanent error
	version               uint16 // protocol version
	wireVersion           uint16 // wire version
	isDTLS                bool
	cipher                any // cipher algorithm
	recordNumberEncrypter recordNumberEncrypter
	mac                   macFunction
	seq                   [8]byte // 64-bit sequence number

	nextCipher any         // next encryption state
	nextMac    macFunction // next MAC algorithm
	nextSeq    [6]byte     // next epoch's starting sequence number in DTLS

	// used to save allocating a new buffer for each MAC.
	macBuf []byte

	trafficSecret []byte

	config *Config
	conn   *Conn
}

func (hc *halfConn) setErrorLocked(err error) error {
	hc.err = err
	return err
}

func (hc *halfConn) error() error {
	// This should be locked, but I've removed it for the renegotiation
	// tests since we don't concurrently read and write the same tls.Conn
	// in any case during testing.
	err := hc.err
	return err
}

// prepareCipherSpec sets the encryption and MAC states
// that a subsequent changeCipherSpec will use.
func (hc *halfConn) prepareCipherSpec(version uint16, cipher any, mac macFunction) {
	hc.wireVersion = version
	protocolVersion, ok := wireToVersion(version, hc.isDTLS)
	if !ok {
		panic("TLS: unknown version")
	}
	hc.version = protocolVersion
	hc.nextCipher = cipher
	hc.nextMac = mac
}

// changeCipherSpec changes the encryption and MAC states
// to the ones previously passed to prepareCipherSpec.
func (hc *halfConn) changeCipherSpec(config *Config) error {
	if hc.nextCipher == nil {
		return alertInternalError
	}
	hc.cipher = hc.nextCipher
	hc.mac = hc.nextMac
	hc.nextCipher = nil
	hc.nextMac = nil
	hc.config = config
	hc.incEpoch()

	if config.Bugs.NullAllCiphers {
		hc.cipher = nullCipher{}
		hc.mac = nil
	}
	return nil
}

// useTrafficSecret sets the current cipher state for TLS 1.3.
func (hc *halfConn) useTrafficSecret(version uint16, suite *cipherSuite, secret []byte, side trafficDirection, level encryptionLevel) {
	hc.wireVersion = version
	protocolVersion, ok := wireToVersion(version, hc.isDTLS)
	if !ok {
		panic("TLS: unknown version")
	}
	hc.version = protocolVersion
	hc.cipher = deriveTrafficAEAD(version, suite, secret, side, hc.isDTLS)
	if hc.isDTLS && !hc.config.Bugs.NullAllCiphers {
		sn_key := hkdfExpandLabel(suite.hash(), secret, []byte("sn"), nil, suite.keyLen, hc.isDTLS)
		switch suite.id {
		case TLS_CHACHA20_POLY1305_SHA256:
			hc.recordNumberEncrypter = newChachaRecordNumberEncrypter(sn_key)
		case TLS_AES_128_GCM_SHA256, TLS_AES_256_GCM_SHA384:
			hc.recordNumberEncrypter = newAESRecordNumberEncrypter(sn_key)
		default:
			panic("Cipher suite does not support TLS 1.3")
		}
	}
	if hc.config.Bugs.NullAllCiphers {
		hc.cipher = nullCipher{}
	}
	hc.trafficSecret = secret
	if hc.isDTLS && protocolVersion == VersionTLS13 {
		hc.setEpoch(uint16(level))
	} else {
		hc.incEpoch()
	}
}

// resetCipher resets the cipher state back to no encryption to be able
// to send an unencrypted ClientHello in response to HelloRetryRequest
// after 0-RTT data was rejected.
func (hc *halfConn) resetCipher() {
	// In all cases, the cipher is set to nil so that second ClientHello
	// will be sent with no encryption (instead of with early data keys).
	hc.cipher = nil
	// TODO(crbug.com/42290594): When handling 0-RTT rejections in DTLS, we
	// need to reset the epoch to 0 and reset the sequence number to where
	// it was prior to sending early data (this is different than resetting
	// it to 0).
}

// incSeq increments the sequence number.
func (hc *halfConn) incSeq() {
	limit := 0
	increment := uint64(1)
	if hc.isDTLS {
		// Increment up to the epoch in DTLS.
		limit = 2
	}
	for i := 7; i >= limit; i-- {
		increment += uint64(hc.seq[i])
		hc.seq[i] = byte(increment)
		increment >>= 8
	}

	// Not allowed to let sequence number wrap.
	// Instead, must renegotiate before it does.
	// Not likely enough to bother.
	if increment != 0 {
		panic("TLS: sequence number wraparound")
	}
}

// incNextSeq increments the starting sequence number for the next epoch.
func (hc *halfConn) incNextSeq() {
	for i := len(hc.nextSeq) - 1; i >= 0; i-- {
		hc.nextSeq[i]++
		if hc.nextSeq[i] != 0 {
			return
		}
	}
	panic("TLS: sequence number wraparound")
}

// incEpoch resets the sequence number. In DTLS, it also increments the epoch
// half of the sequence number.
func (hc *halfConn) incEpoch() {
	if hc.isDTLS {
		for i := 1; i >= 0; i-- {
			hc.seq[i]++
			if hc.seq[i] != 0 {
				break
			}
			if i == 0 {
				panic("TLS: epoch number wraparound")
			}
		}
		copy(hc.seq[2:], hc.nextSeq[:])
		clear(hc.nextSeq[:])
	} else {
		clear(hc.seq[:])
	}
}

func (hc *halfConn) setEpoch(epoch uint16) {
	if !hc.isDTLS {
		panic("Internal error: called setEpoch on non-DTLS connection")
	}
	hc.seq[0] = byte(epoch >> 8)
	hc.seq[1] = byte(epoch)
	copy(hc.seq[2:], hc.nextSeq[:])
	clear(hc.nextSeq[:])
}

func (hc *halfConn) sequenceNumberForOutput() []byte {
	if !hc.isDTLS || hc.config.Bugs.SequenceNumberMapping == nil {
		return hc.seq[:]
	}

	var seq [8]byte
	seqU64 := binary.BigEndian.Uint64(hc.seq[:])
	seqU64 = hc.config.Bugs.SequenceNumberMapping(seqU64)
	binary.BigEndian.PutUint64(seq[:], seqU64)
	// The DTLS epoch cannot be changed.
	copy(seq[:2], hc.seq[:2])
	return seq[:]
}

func (hc *halfConn) explicitIVLen() int {
	if hc.cipher == nil {
		return 0
	}
	switch c := hc.cipher.(type) {
	case cipher.Stream:
		return 0
	case *tlsAead:
		if c.explicitNonce {
			return 8
		}
		return 0
	case cbcMode:
		if hc.version >= VersionTLS11 || hc.isDTLS {
			return c.BlockSize()
		}
		return 0
	case nullCipher:
		return 0
	default:
		panic("unknown cipher type")
	}
}

func (hc *halfConn) computeMAC(seq, header, data []byte) []byte {
	hc.macBuf = hc.mac.MAC(hc.macBuf[:0], seq, header[:3], header[len(header)-2:], data)
	return hc.macBuf
}

// removePadding returns an unpadded slice, in constant time, which is a prefix
// of the input. It also returns a byte which is equal to 255 if the padding
// was valid and 0 otherwise. See RFC 2246, section 6.2.3.2
func removePadding(payload []byte) ([]byte, byte) {
	if len(payload) < 1 {
		return payload, 0
	}

	paddingLen := payload[len(payload)-1]
	t := uint(len(payload)-1) - uint(paddingLen)
	// if len(payload) >= (paddingLen - 1) then the MSB of t is zero
	good := byte(int32(^t) >> 31)

	toCheck := 255 // the maximum possible padding length
	// The length of the padded data is public, so we can use an if here
	if toCheck+1 > len(payload) {
		toCheck = len(payload) - 1
	}

	for i := 0; i < toCheck; i++ {
		t := uint(paddingLen) - uint(i)
		// if i <= paddingLen then the MSB of t is zero
		mask := byte(int32(^t) >> 31)
		b := payload[len(payload)-1-i]
		good &^= mask&paddingLen ^ mask&b
	}

	// We AND together the bits of good and replicate the result across
	// all the bits.
	good &= good << 4
	good &= good << 2
	good &= good << 1
	good = uint8(int8(good) >> 7)

	toRemove := good&paddingLen + 1
	return payload[:len(payload)-int(toRemove)], good
}

func roundUp(a, b int) int {
	return a + (b-a%b)%b
}

// cbcMode is an interface for block ciphers using cipher block chaining.
type cbcMode interface {
	cipher.BlockMode
	SetIV([]byte)
}

// decrypt checks and strips the mac and decrypts the data in record. Returns a
// success boolean, the application payload, the encrypted record type (or 0
// if there is none), and an optional alert value. Decryption occurs in-place,
// so the contents of record will be overwritten as part of this process.
func (hc *halfConn) decrypt(seq []byte, recordHeaderLen int, record []byte) (ok bool, contentType recordType, data []byte, alertValue alert) {
	// pull out payload
	payload := record[recordHeaderLen:]

	macSize := 0
	if hc.mac != nil {
		macSize = hc.mac.Size()
	}

	paddingGood := byte(255)
	explicitIVLen := hc.explicitIVLen()

	// decrypt
	if hc.cipher != nil {
		switch c := hc.cipher.(type) {
		case cipher.Stream:
			c.XORKeyStream(payload, payload)
		case *tlsAead:
			nonce := seq
			if explicitIVLen != 0 {
				if len(payload) < explicitIVLen {
					return false, 0, nil, alertBadRecordMAC
				}
				nonce = payload[:explicitIVLen]
				payload = payload[explicitIVLen:]
			}

			var additionalData []byte
			if hc.version < VersionTLS13 {
				additionalData = make([]byte, 13)
				copy(additionalData, seq)
				copy(additionalData[8:], record[:3])
				n := len(payload) - c.Overhead()
				additionalData[11] = byte(n >> 8)
				additionalData[12] = byte(n)
			} else {
				additionalData = record[:recordHeaderLen]
			}
			var err error
			payload, err = c.Open(payload[:0], nonce, payload, additionalData)
			if err != nil {
				return false, 0, nil, alertBadRecordMAC
			}
		case cbcMode:
			blockSize := c.BlockSize()
			if len(payload)%blockSize != 0 || len(payload) < roundUp(explicitIVLen+macSize+1, blockSize) {
				return false, 0, nil, alertBadRecordMAC
			}

			if explicitIVLen > 0 {
				c.SetIV(payload[:explicitIVLen])
				payload = payload[explicitIVLen:]
			}
			c.CryptBlocks(payload, payload)
			payload, paddingGood = removePadding(payload)

			// note that we still have a timing side-channel in the
			// MAC check, below. An attacker can align the record
			// so that a correct padding will cause one less hash
			// block to be calculated. Then they can iteratively
			// decrypt a record by breaking each byte. See
			// "Password Interception in a SSL/TLS Channel", Brice
			// Canvel et al.
			//
			// However, our behavior matches OpenSSL, so we leak
			// only as much as they do.
		case nullCipher:
			break
		default:
			panic("unknown cipher type")
		}

		if hc.version >= VersionTLS13 {
			i := len(payload)
			for i > 0 && payload[i-1] == 0 {
				i--
			}
			payload = payload[:i]
			if len(payload) == 0 {
				return false, 0, nil, alertUnexpectedMessage
			}
			contentType = recordType(payload[len(payload)-1])
			payload = payload[:len(payload)-1]
		}
	}

	// check, strip mac
	if hc.mac != nil {
		if len(payload) < macSize {
			return false, 0, nil, alertBadRecordMAC
		}

		// strip mac off payload
		n := len(payload) - macSize
		remoteMAC := payload[n:]
		payload = payload[:n]
		record[recordHeaderLen-2] = byte(n >> 8)
		record[recordHeaderLen-1] = byte(n)
		localMAC := hc.computeMAC(seq, record[:recordHeaderLen], payload)
		if subtle.ConstantTimeCompare(localMAC, remoteMAC) != 1 || paddingGood != 255 {
			return false, 0, nil, alertBadRecordMAC
		}
	}
	hc.incSeq()

	return true, contentType, payload, 0
}

// extendSlice updates *data to contain n more bytes and returns a slice
// containing the bytes that were added.
func extendSlice(data *[]byte, n int) []byte {
	// Reallocate the slice if needed.
	*data = slices.Grow(*data, n)
	// Extend data into the capacity and return the newly added slice.
	oldLen := len(*data)
	newLen := oldLen + n
	*data = (*data)[:newLen]
	return (*data)[oldLen:newLen]
}

// computingCBCPaddingLength returns the number of bytes of CBC padding to use
// for a payload (plaintext + MAC) of length payloadLen.
func computingCBCPaddingLength(payloadLen, blockSize int, config *Config) int {
	paddingLen := blockSize - payloadLen%blockSize
	if config.Bugs.MaxPadding {
		for paddingLen+blockSize <= 256 {
			paddingLen += blockSize
		}
	}
	return paddingLen
}

// appendCBCPadding computes paddingLen bytes of padding data, appends it to b,
// and returns the result.
func appendCBCPadding(b []byte, paddingLen int, config *Config) []byte {
	padding := extendSlice(&b, paddingLen)
	for i := range padding {
		padding[i] = byte(paddingLen - 1)
	}
	if config.Bugs.PaddingFirstByteBad || config.Bugs.PaddingFirstByteBadIf255 && paddingLen == 256 {
		padding[0] ^= 0xff
	}
	return b
}

func (hc *halfConn) maxEncryptOverhead(payloadLen int) int {
	var macSize int
	if hc.mac != nil {
		macSize = hc.mac.Size()
	}
	overhead := macSize + hc.explicitIVLen()
	if hc.version >= VersionTLS13 {
		overhead += 1 + hc.config.Bugs.RecordPadding // type + padding
	}
	if hc.cipher != nil {
		switch c := hc.cipher.(type) {
		case cipher.Stream, *nullCipher:
		case *tlsAead:
			overhead += c.Overhead()
		case cbcMode:
			overhead += computingCBCPaddingLength(payloadLen+macSize, c.BlockSize(), hc.config)
		case nullCipher:
			break
		default:
			panic("unknown cipher type")
		}
	}
	return overhead
}

func (c *Conn) useDTLSPlaintextHeader() bool {
	return c.config.Bugs.DTLSUsePlaintextRecordHeader && c.handshakeComplete
}

// encrypt encrypts and MACs the data in payload, appending it record. On
// entry, the last headerLen bytes of record must be the header. The length
// (which must be in the last two bytes of the header) should be computed for
// the unencrypted, unpadded payload. It will be updated, potentially in-place,
// with the final length.
func (hc *halfConn) encrypt(record, payload []byte, typ recordType, headerLen int, headerHasLength bool, seq []byte) ([]byte, error) {
	prefixLen := len(record)
	header := record[prefixLen-headerLen:]
	explicitIVLen := hc.explicitIVLen()

	// Reserve some space for the explicit IV. The slice may get reallocated
	// after this, so don't use the return value.
	extendSlice(&record, explicitIVLen)

	// Stage the plaintext, TLS 1.3 padding, and TLS 1.2 MAC in the record, to
	// be encrypted in-place.
	record = append(record, payload...)

	if hc.version >= VersionTLS13 && hc.cipher != nil {
		if hc.config.Bugs.OmitRecordContents {
			record = record[:len(record)-len(payload)]
		} else {
			record = append(record, byte(typ))
		}
		padding := extendSlice(&record, hc.config.Bugs.RecordPadding)
		clear(padding)
	}

	if hc.mac != nil {
		record = append(record, hc.computeMAC(seq, header, payload)...)
	}

	explicitIV := record[prefixLen : prefixLen+explicitIVLen]
	if hc.cipher != nil {
		switch c := hc.cipher.(type) {
		case cipher.Stream:
			if explicitIVLen != 0 {
				panic("tls: unexpected explicit IV length")
			}
			c.XORKeyStream(record[prefixLen:], record[prefixLen:])
		case *tlsAead:
			nonce := seq
			if hc.isDTLS && hc.version >= VersionTLS13 && !hc.conn.useDTLSPlaintextHeader() {
				// Unlike DTLS 1.2, DTLS 1.3's nonce construction does not use
				// the epoch number. We store the epoch and nonce numbers
				// together, so make a copy without the epoch.
				nonce = make([]byte, 8)
				copy(nonce[2:], seq[2:])
			}

			// Save the explicit IV, if not empty.
			if len(explicitIV) != 0 {
				if explicitIVLen != len(nonce) {
					panic("tls: unexpected explicit IV length")
				}
				copy(explicitIV, nonce)
			}

			var additionalData []byte
			if hc.version < VersionTLS13 {
				// (D)TLS 1.2's AD is seq_num || type || version || plaintext length
				additionalData = make([]byte, 13)
				copy(additionalData, seq)
				copy(additionalData[8:], header[:3])
				additionalData[11] = byte(len(payload) >> 8)
				additionalData[12] = byte(len(payload))
			} else {
				// (D)TLS 1.3's AD is the ciphertext record header, so update the
				// length now.
				if headerHasLength {
					n := len(record) - prefixLen + c.Overhead()
					record[prefixLen-2] = byte(n >> 8)
					record[prefixLen-1] = byte(n)
				}
				additionalData = record[prefixLen-headerLen : prefixLen]
			}

			record = c.Seal(record[:prefixLen+explicitIVLen], nonce, record[prefixLen+explicitIVLen:], additionalData)
		case cbcMode:
			if explicitIVLen > 0 {
				if _, err := io.ReadFull(hc.config.rand(), explicitIV); err != nil {
					return nil, err
				}
				c.SetIV(explicitIV)
			}

			blockSize := c.BlockSize()
			paddingLen := computingCBCPaddingLength(len(record)-prefixLen, blockSize, hc.config)
			record = appendCBCPadding(record, paddingLen, hc.config)
			c.CryptBlocks(record[prefixLen:], record[prefixLen:])
		case nullCipher:
			break
		default:
			panic("unknown cipher type")
		}
	}

	// Update the record header to include the encryption overhead.
	if headerHasLength {
		n := len(record) - prefixLen
		record[prefixLen-2] = byte(n >> 8)
		record[prefixLen-1] = byte(n)
	}
	hc.incSeq()

	return record, nil
}

type recordNumberEncrypter interface {
	// GenerateMask takes a sample of the encrypted record and returns the
	// mask used to encrypt and decrypt record numbers.
	generateMask(sample []byte) []byte
}

type aesRecordNumberEncrypter struct {
	aesCipher cipher.Block
}

func newAESRecordNumberEncrypter(key []byte) *aesRecordNumberEncrypter {
	aesCipher, err := aes.NewCipher(key)
	if err != nil {
		panic("Incorrect usage of newAESRecordNumberEncrypter")
	}
	return &aesRecordNumberEncrypter{
		aesCipher: aesCipher,
	}
}

func (a *aesRecordNumberEncrypter) generateMask(sample []byte) []byte {
	out := make([]byte, len(sample))
	a.aesCipher.Encrypt(out, sample)
	return out
}

type chachaRecordNumberEncrypter struct {
	key []byte
}

func newChachaRecordNumberEncrypter(key []byte) *chachaRecordNumberEncrypter {
	out := &chachaRecordNumberEncrypter{
		key: key,
	}
	return out
}

func (c *chachaRecordNumberEncrypter) generateMask(sample []byte) []byte {
	var counter, nonce []byte
	sampleReader := cryptobyte.String(sample)
	if !sampleReader.ReadBytes(&counter, 4) || !sampleReader.ReadBytes(&nonce, 12) {
		panic("chachaRecordNumberEncrypter.GenerateMask called with wrong size sample")
	}
	cipher, err := chacha20.NewUnauthenticatedCipher(c.key, nonce)
	if err != nil {
		panic("Failed to create chacha20 cipher for record number encryption")
	}
	cipher.SetCounter(binary.LittleEndian.Uint32(counter))
	out := make([]byte, 2)
	cipher.XORKeyStream(out, out)
	return out
}

func (c *Conn) useInTrafficSecret(level encryptionLevel, version uint16, suite *cipherSuite, secret []byte) error {
	if c.hand.Len() != 0 {
		return c.in.setErrorLocked(errors.New("tls: buffered handshake messages on cipher change"))
	}
	side := serverWrite
	if !c.isClient {
		side = clientWrite
	}
	if c.config.Bugs.MockQUICTransport != nil {
		c.config.Bugs.MockQUICTransport.readLevel = level
		c.config.Bugs.MockQUICTransport.readSecret = secret
		c.config.Bugs.MockQUICTransport.readCipherSuite = suite.id
	}
	c.in.useTrafficSecret(version, suite, secret, side, level)
	c.seenHandshakePackEnd = false
	return nil
}

func (c *Conn) useOutTrafficSecret(level encryptionLevel, version uint16, suite *cipherSuite, secret []byte) {
	side := serverWrite
	if c.isClient {
		side = clientWrite
	}
	if c.config.Bugs.MockQUICTransport != nil {
		c.config.Bugs.MockQUICTransport.writeLevel = level
		c.config.Bugs.MockQUICTransport.writeSecret = secret
		c.config.Bugs.MockQUICTransport.writeCipherSuite = suite.id
	}
	c.out.useTrafficSecret(version, suite, secret, side, level)
}

func (c *Conn) setSkipEarlyData() {
	if c.config.Bugs.MockQUICTransport != nil {
		c.config.Bugs.MockQUICTransport.skipEarlyData = true
	} else {
		c.skipEarlyData = true
	}
}

func (c *Conn) shouldSkipEarlyData() bool {
	if c.config.Bugs.MockQUICTransport != nil {
		return c.config.Bugs.MockQUICTransport.skipEarlyData
	}
	return c.skipEarlyData
}

func (c *Conn) readRawInputUntil(n int) error {
	if c.rawInput.Len() >= n {
		return nil
	}

	n -= c.rawInput.Len()
	c.rawInput.Grow(n)
	buf := c.rawInput.AvailableBuffer()
	nread, err := io.ReadAtLeast(c.conn, buf[:cap(buf)], n)
	c.rawInput.Write(buf[:nread])
	return err
}

func (c *Conn) doReadRecord(want recordType) (recordType, []byte, error) {
RestartReadRecord:
	if c.isDTLS {
		return c.dtlsDoReadRecord(want)
	}

	recordHeaderLen := tlsRecordHeaderLen

	// Read header, payload.
	if err := c.readRawInputUntil(recordHeaderLen); err != nil {
		// RFC suggests that EOF without an alertCloseNotify is
		// an error, but popular web sites seem to do this,
		// so we can't make it an error, outside of tests.
		if err == io.EOF && c.config.Bugs.ExpectCloseNotify {
			err = io.ErrUnexpectedEOF
		}
		if e, ok := err.(net.Error); !ok || !e.Temporary() {
			c.in.setErrorLocked(err)
		}
		return 0, nil, err
	}

	header := c.rawInput.Bytes()[:recordHeaderLen]
	typ := recordType(header[0])

	// No valid TLS record has a type of 0x80, however SSLv2 handshakes
	// start with a uint16 length where the MSB is set and the first record
	// is always < 256 bytes long. Therefore typ == 0x80 strongly suggests
	// an SSLv2 client.
	if want == recordTypeHandshake && typ == 0x80 {
		c.sendAlert(alertProtocolVersion)
		return 0, nil, c.in.setErrorLocked(errors.New("tls: unsupported SSLv2 handshake received"))
	}

	vers := uint16(header[1])<<8 | uint16(header[2])
	n := int(header[3])<<8 | int(header[4])

	// Alerts sent near version negotiation do not have a well-defined
	// record-layer version prior to TLS 1.3. (In TLS 1.3, the record-layer
	// version is irrelevant.)
	if typ != recordTypeAlert {
		var expect uint16
		if c.haveVers {
			expect = c.vers
			if c.vers >= VersionTLS13 {
				expect = VersionTLS12
			}
		} else {
			expect = c.config.Bugs.ExpectInitialRecordVersion
		}
		if expect != 0 && vers != expect {
			c.sendAlert(alertProtocolVersion)
			return 0, nil, c.in.setErrorLocked(fmt.Errorf("tls: received record with version %x when expecting version %x", vers, expect))
		}
	}
	if n > maxCiphertext {
		c.sendAlert(alertRecordOverflow)
		return 0, nil, c.in.setErrorLocked(fmt.Errorf("tls: oversized record received with length %d", n))
	}
	if !c.haveVers {
		// First message, be extra suspicious:
		// this might not be a TLS client.
		// Bail out before reading a full 'body', if possible.
		// The current max version is 3.1.
		// If the version is >= 16.0, it's probably not real.
		// Similarly, a clientHello message encodes in
		// well under a kilobyte.  If the length is >= 12 kB,
		// it's probably not real.
		if (typ != recordTypeAlert && typ != want) || vers >= 0x1000 || n >= 0x3000 {
			c.sendAlert(alertUnexpectedMessage)
			return 0, nil, c.in.setErrorLocked(fmt.Errorf("tls: first record does not look like a TLS handshake"))
		}
	}
	if err := c.readRawInputUntil(recordHeaderLen + n); err != nil {
		if err == io.EOF {
			err = io.ErrUnexpectedEOF
		}
		if e, ok := err.(net.Error); !ok || !e.Temporary() {
			c.in.setErrorLocked(err)
		}
		return 0, nil, err
	}

	// Process message.
	b := c.rawInput.Next(recordHeaderLen + n)
	ok, encTyp, data, alertValue := c.in.decrypt(c.in.seq[:], recordHeaderLen, b)
	if !ok {
		// TLS 1.3 early data uses trial decryption.
		if c.skipEarlyData {
			goto RestartReadRecord
		}
		return 0, nil, c.in.setErrorLocked(c.sendAlert(alertValue))
	}

	// If the server is expecting a second ClientHello (in response to
	// a HelloRetryRequest) and the client sends early data, there
	// won't be a decryption failure (we will interpret the ciphertext
	// as plaintext application data) but it still needs to be skipped.
	if c.in.cipher == nil && typ == recordTypeApplicationData && c.skipEarlyData {
		goto RestartReadRecord
	}

	c.skipEarlyData = false

	if c.vers >= VersionTLS13 && c.in.cipher != nil {
		if typ != recordTypeApplicationData {
			return 0, nil, c.in.setErrorLocked(fmt.Errorf("tls: outer record type is not application data"))
		}
		typ = encTyp
	}

	if c.config.Bugs.ExpectRecordSplitting && typ == recordTypeApplicationData && len(data) != 1 && !c.seenOneByteRecord {
		return 0, nil, c.in.setErrorLocked(fmt.Errorf("tls: application data records were not split"))
	}

	c.seenOneByteRecord = typ == recordTypeApplicationData && len(data) == 1
	return typ, data, nil
}

func (c *Conn) readTLS13ChangeCipherSpec() error {
	if c.config.Bugs.MockQUICTransport != nil {
		return nil
	}
	if c.isDTLS {
		// ChangeCipherSpec in DTLS 1.3 is handled within dtlsDoReadRecord.
		return nil
	}
	if !c.expectTLS13ChangeCipherSpec {
		panic("c.expectTLS13ChangeCipherSpec not set")
	}

	// Read the ChangeCipherSpec.
	if err := c.readRawInputUntil(6); err != nil {
		return c.in.setErrorLocked(fmt.Errorf("tls: error reading TLS 1.3 ChangeCipherSpec: %s", err))
	}
	if recordType(c.rawInput.Bytes()[0]) == recordTypeAlert {
		// If the client is sending an alert, allow the ChangeCipherSpec
		// to be skipped. It may be rejecting a sufficiently malformed
		// ServerHello that it can't parse out the version.
		c.expectTLS13ChangeCipherSpec = false
		return nil
	}

	// Check they match that we expect.
	expected := [6]byte{byte(recordTypeChangeCipherSpec), 3, 1, 0, 1, 1}
	if c.vers >= VersionTLS13 {
		expected[2] = 3
	}
	if data := c.rawInput.Bytes()[:6]; !bytes.Equal(data, expected[:]) {
		return c.in.setErrorLocked(fmt.Errorf("tls: error invalid TLS 1.3 ChangeCipherSpec: %x", data))
	}

	// Discard the data.
	c.rawInput.Next(6)

	c.expectTLS13ChangeCipherSpec = false
	return nil
}

// readRecord reads the next TLS record from the connection
// and updates the record layer state.
// c.in.Mutex <= L; c.input == nil.
func (c *Conn) readRecord(want recordType) error {
	// Caller must be in sync with connection:
	// handshake data if handshake not yet completed,
	// else application data.
	switch want {
	default:
		c.sendAlert(alertInternalError)
		return c.in.setErrorLocked(errors.New("tls: unknown record type requested"))
	case recordTypeChangeCipherSpec:
		if c.handshakeComplete {
			c.sendAlert(alertInternalError)
			return c.in.setErrorLocked(errors.New("tls: ChangeCipherSpec requested after handshake complete"))
		}
	case recordTypeApplicationData, recordTypeAlert, recordTypeHandshake:
		break
	}

	if c.expectTLS13ChangeCipherSpec {
		if err := c.readTLS13ChangeCipherSpec(); err != nil {
			return err
		}
	}

Again:
	doReadRecord := c.doReadRecord
	if c.config.Bugs.MockQUICTransport != nil {
		doReadRecord = c.config.Bugs.MockQUICTransport.readRecord
	}
	typ, data, err := doReadRecord(want)
	if err != nil {
		return err
	}
	max := maxPlaintext
	if c.config.Bugs.MaxReceivePlaintext != 0 {
		max = c.config.Bugs.MaxReceivePlaintext
	}
	if len(data) > max {
		err := c.sendAlert(alertRecordOverflow)
		return c.in.setErrorLocked(err)
	}

	if typ != recordTypeHandshake {
		c.seenHandshakePackEnd = false
	} else if c.seenHandshakePackEnd {
		return c.in.setErrorLocked(errors.New("tls: peer violated ExpectPackedEncryptedHandshake"))
	}

	switch typ {
	default:
		c.in.setErrorLocked(c.sendAlert(alertUnexpectedMessage))

	case recordTypeAlert:
		if len(data) != 2 {
			c.in.setErrorLocked(c.sendAlert(alertUnexpectedMessage))
			break
		}
		if alert(data[1]) == alertCloseNotify {
			c.in.setErrorLocked(io.EOF)
			break
		}
		switch data[0] {
		case alertLevelWarning:
			// drop on the floor
			goto Again
		case alertLevelError:
			c.in.setErrorLocked(&net.OpError{Op: "remote error", Err: alert(data[1])})
		default:
			c.in.setErrorLocked(c.sendAlert(alertUnexpectedMessage))
		}

	case recordTypeChangeCipherSpec:
		if typ != want || len(data) != 1 || data[0] != 1 {
			c.in.setErrorLocked(c.sendAlert(alertUnexpectedMessage))
			break
		}
		if c.hand.Len() != 0 {
			c.in.setErrorLocked(errors.New("tls: buffered handshake messages on cipher change"))
			break
		}
		if err := c.in.changeCipherSpec(c.config); err != nil {
			c.in.setErrorLocked(c.sendAlert(err.(alert)))
		}

	case recordTypeApplicationData:
		if typ != want {
			c.in.setErrorLocked(c.sendAlert(alertUnexpectedMessage))
			break
		}
		c.input.Write(data)

	case recordTypeHandshake:
		// Allow handshake data while reading application data to
		// trigger post-handshake messages.
		// TODO(rsc): Should at least pick off connection close.
		if typ != want && want != recordTypeApplicationData {
			return c.in.setErrorLocked(c.sendAlert(alertNoRenegotiation))
		}
		c.hand.Write(data)
		if pack := c.config.Bugs.ExpectPackedEncryptedHandshake; pack > 0 && len(data) < pack && c.out.cipher != nil {
			c.seenHandshakePackEnd = true
		}
	}

	return c.in.err
}

// sendAlert sends a TLS alert message.
// c.out.Mutex <= L.
func (c *Conn) sendAlertLocked(level byte, err alert) error {
	c.tmp[0] = level
	c.tmp[1] = byte(err)
	if c.config.Bugs.FragmentAlert {
		c.writeRecord(recordTypeAlert, c.tmp[0:1])
		c.writeRecord(recordTypeAlert, c.tmp[1:2])
	} else if c.config.Bugs.DoubleAlert {
		copy(c.tmp[2:4], c.tmp[0:2])
		c.writeRecord(recordTypeAlert, c.tmp[0:4])
	} else {
		c.writeRecord(recordTypeAlert, c.tmp[0:2])
	}
	// Error alerts are fatal to the connection.
	if level == alertLevelError {
		return c.out.setErrorLocked(&net.OpError{Op: "local error", Err: err})
	}
	return nil
}

// sendAlert sends a TLS alert message.
// L < c.out.Mutex.
func (c *Conn) sendAlert(err alert) error {
	level := byte(alertLevelError)
	if err == alertNoRenegotiation || err == alertCloseNotify {
		level = alertLevelWarning
	}
	return c.SendAlert(level, err)
}

func (c *Conn) SendAlert(level byte, err alert) error {
	c.out.Lock()
	defer c.out.Unlock()
	return c.sendAlertLocked(level, err)
}

// writeV2Record writes a record for a V2ClientHello.
func (c *Conn) writeV2Record(data []byte) (n int, err error) {
	record := make([]byte, 2+len(data))
	record[0] = uint8(len(data)>>8) | 0x80
	record[1] = uint8(len(data))
	copy(record[2:], data)
	return c.conn.Write(record)
}

// writeRecord writes a TLS record with the given type and payload
// to the connection and updates the record layer state.
// c.out.Mutex <= L.
func (c *Conn) writeRecord(typ recordType, data []byte) (n int, err error) {
	c.seenHandshakePackEnd = false
	if typ == recordTypeHandshake {
		msgType := data[0]
		if c.config.Bugs.SendWrongMessageType != 0 && msgType == c.config.Bugs.SendWrongMessageType {
			msgType += 42
		}
		if msgType != data[0] {
			data = append([]byte{msgType}, data[1:]...)
		}

		if c.config.Bugs.SendTrailingMessageData != 0 && msgType == c.config.Bugs.SendTrailingMessageData {
			// Add a 0 to the body.
			newData := make([]byte, len(data)+1)
			copy(newData, data)

			// Fix the header.
			newLen := len(newData) - 4
			newData[1] = byte(newLen >> 16)
			newData[2] = byte(newLen >> 8)
			newData[3] = byte(newLen)

			data = newData
		}

		if c.config.Bugs.TrailingDataWithFinished && msgType == typeFinished {
			// Add a 0 to the record. Note unused bytes in |data| may be owned by the
			// caller, so we force a new allocation.
			data = append(data[:len(data):len(data)], 0)
		}
	}

	if c.isDTLS {
		return c.dtlsWriteRecord(typ, data)
	}
	if c.config.Bugs.MockQUICTransport != nil {
		return c.config.Bugs.MockQUICTransport.writeRecord(typ, data)
	}

	if typ == recordTypeHandshake {
		if c.config.Bugs.SendHelloRequestBeforeEveryHandshakeMessage {
			newData := make([]byte, 0, 4+len(data))
			newData = append(newData, typeHelloRequest, 0, 0, 0)
			newData = append(newData, data...)
			data = newData
		}

		if c.config.Bugs.PackHandshakeFlight {
			c.pendingFlight.Write(data)
			return len(data), nil
		}
	}

	// Flush buffered data before writing anything.
	if err := c.flushHandshake(); err != nil {
		return 0, err
	}

	if typ == recordTypeApplicationData && c.config.Bugs.SendPostHandshakeChangeCipherSpec {
		if _, err := c.doWriteRecord(recordTypeChangeCipherSpec, []byte{1}); err != nil {
			return 0, err
		}
	}

	return c.doWriteRecord(typ, data)
}

func (c *Conn) doWriteRecord(typ recordType, data []byte) (n int, err error) {
	first := true
	isClientHello := typ == recordTypeHandshake && len(data) > 0 && data[0] == typeClientHello
	for len(data) > 0 || first {
		m := len(data)
		if m > maxPlaintext && !c.config.Bugs.SendLargeRecords {
			m = maxPlaintext
		}
		if typ == recordTypeHandshake && c.config.Bugs.MaxHandshakeRecordLength > 0 && m > c.config.Bugs.MaxHandshakeRecordLength {
			m = c.config.Bugs.MaxHandshakeRecordLength
			// By default, do not fragment the client_version or
			// server_version, which are located in the first 6
			// bytes.
			if first && isClientHello && !c.config.Bugs.FragmentClientVersion && m < 6 {
				m = 6
			}
		}
		first = false

		// Determine record version.
		vers := c.vers
		if vers == 0 {
			// Some TLS servers fail if the record version is
			// greater than TLS 1.0 for the initial ClientHello.
			//
			// TLS 1.3 fixes the version number in the record
			// layer to {3, 1}.
			vers = VersionTLS10
		}
		if c.vers >= VersionTLS13 || c.out.version >= VersionTLS13 {
			vers = VersionTLS12
		}
		if c.config.Bugs.SendRecordVersion != 0 {
			vers = c.config.Bugs.SendRecordVersion
		}
		if c.vers == 0 && c.config.Bugs.SendInitialRecordVersion != 0 {
			vers = c.config.Bugs.SendInitialRecordVersion
		}

		// Assemble the record header.
		record := make([]byte, tlsRecordHeaderLen, tlsRecordHeaderLen+m+c.out.maxEncryptOverhead(m))
		record[0] = byte(typ)
		if c.vers >= VersionTLS13 && c.out.cipher != nil {
			record[0] = byte(recordTypeApplicationData)
			if outerType := c.config.Bugs.OuterRecordType; outerType != 0 {
				record[0] = byte(outerType)
			}
		}
		record[1] = byte(vers >> 8)
		record[2] = byte(vers)
		record[3] = byte(m >> 8) // encrypt will update this
		record[4] = byte(m)

		record, err = c.out.encrypt(record, data[:m], typ, tlsRecordHeaderLen, true /* header has length */, c.out.seq[:])
		if err != nil {
			return
		}
		_, err = c.conn.Write(record)
		if err != nil {
			break
		}
		n += m
		data = data[m:]
	}

	if typ == recordTypeChangeCipherSpec && c.vers < VersionTLS13 {
		err = c.out.changeCipherSpec(c.config)
		if err != nil {
			return n, c.sendAlertLocked(alertLevelError, err.(alert))
		}
	}
	return
}

func (c *Conn) flushHandshake() error {
	if c.isDTLS {
		return c.dtlsFlushHandshake()
	}

	for c.pendingFlight.Len() > 0 {
		var buf [maxPlaintext]byte
		n, _ := c.pendingFlight.Read(buf[:])
		if _, err := c.doWriteRecord(recordTypeHandshake, buf[:n]); err != nil {
			return err
		}
	}

	c.pendingFlight.Reset()
	return nil
}

func (c *Conn) doReadHandshake() ([]byte, error) {
	if c.isDTLS {
		return c.dtlsDoReadHandshake()
	}

	for c.hand.Len() < 4 {
		if err := c.in.err; err != nil {
			return nil, err
		}
		if err := c.readRecord(recordTypeHandshake); err != nil {
			return nil, err
		}
	}

	data := c.hand.Bytes()
	n := int(data[1])<<16 | int(data[2])<<8 | int(data[3])
	if n > maxHandshake {
		return nil, c.in.setErrorLocked(c.sendAlert(alertInternalError))
	}
	for c.hand.Len() < 4+n {
		if err := c.in.err; err != nil {
			return nil, err
		}
		if err := c.readRecord(recordTypeHandshake); err != nil {
			return nil, err
		}
	}
	return c.hand.Next(4 + n), nil
}

// readHandshake reads the next handshake message from
// the record layer.
// c.in.Mutex < L; c.out.Mutex < L.
func (c *Conn) readHandshake() (any, error) {
	data, err := c.doReadHandshake()
	if err != nil {
		return nil, err
	}

	var m handshakeMessage
	switch data[0] {
	case typeHelloRequest:
		m = new(helloRequestMsg)
	case typeClientHello:
		m = &clientHelloMsg{
			isDTLS: c.isDTLS,
		}
	case typeServerHello:
		m = &serverHelloMsg{
			isDTLS: c.isDTLS,
		}
	case typeNewSessionTicket:
		m = &newSessionTicketMsg{
			vers:   c.wireVersion,
			isDTLS: c.isDTLS,
		}
	case typeEncryptedExtensions:
		if c.isClient {
			m = new(encryptedExtensionsMsg)
		} else {
			m = new(clientEncryptedExtensionsMsg)
		}
	case typeCertificate:
		m = &certificateMsg{
			hasRequestContext: c.vers >= VersionTLS13,
		}
	case typeCompressedCertificate:
		m = new(compressedCertificateMsg)
	case typeCertificateRequest:
		m = &certificateRequestMsg{
			vers:                  c.wireVersion,
			hasSignatureAlgorithm: c.vers >= VersionTLS12,
			hasRequestContext:     c.vers >= VersionTLS13,
		}
	case typeCertificateStatus:
		m = new(certificateStatusMsg)
	case typeServerKeyExchange:
		m = new(serverKeyExchangeMsg)
	case typeServerHelloDone:
		m = new(serverHelloDoneMsg)
	case typeClientKeyExchange:
		m = new(clientKeyExchangeMsg)
	case typeCertificateVerify:
		m = &certificateVerifyMsg{
			hasSignatureAlgorithm: c.vers >= VersionTLS12,
		}
	case typeNextProtocol:
		m = new(nextProtoMsg)
	case typeFinished:
		m = new(finishedMsg)
	case typeHelloVerifyRequest:
		m = new(helloVerifyRequestMsg)
	case typeChannelID:
		m = new(channelIDMsg)
	case typeKeyUpdate:
		m = new(keyUpdateMsg)
	case typeEndOfEarlyData:
		m = new(endOfEarlyDataMsg)
	default:
		return nil, c.in.setErrorLocked(c.sendAlert(alertUnexpectedMessage))
	}

	// The handshake message unmarshallers
	// expect to be able to keep references to data,
	// so pass in a fresh copy that won't be overwritten.
	data = slices.Clone(data)

	if data[0] == typeServerHello && len(data) >= 38 {
		vers := uint16(data[4])<<8 | uint16(data[5])
		if vers == VersionTLS12 && bytes.Equal(data[6:38], tls13HelloRetryRequest) {
			m = new(helloRetryRequestMsg)
		}
	}

	if !m.unmarshal(data) {
		return nil, c.in.setErrorLocked(c.sendAlert(alertDecodeError))
	}
	return m, nil
}

// skipPacket processes all the DTLS records in packet. It updates
// sequence number expectations but otherwise ignores them.
func (c *Conn) skipPacket(packet []byte) error {
	for len(packet) > 0 {
		if len(packet) < 13 {
			return errors.New("tls: bad packet")
		}
		// Dropped packets are completely ignored save to update
		// expected sequence numbers for this and the next epoch. (We
		// don't assert on the contents of the packets both for
		// simplicity and because a previous test with one shorter
		// timeout schedule would have done so.)
		epoch := packet[3:5]
		seq := packet[5:11]
		length := uint16(packet[11])<<8 | uint16(packet[12])
		if bytes.Equal(c.in.seq[:2], epoch) {
			if bytes.Compare(seq, c.in.seq[2:]) < 0 {
				return errors.New("tls: sequence mismatch")
			}
			copy(c.in.seq[2:], seq)
			c.in.incSeq()
		} else {
			if bytes.Compare(seq, c.in.nextSeq[:]) < 0 {
				return errors.New("tls: sequence mismatch")
			}
			copy(c.in.nextSeq[:], seq)
			c.in.incNextSeq()
		}
		if len(packet) < 13+int(length) {
			return errors.New("tls: bad packet")
		}
		packet = packet[13+length:]
	}
	return nil
}

// simulatePacketLoss simulates the loss of a handshake leg from the
// peer based on the schedule in c.config.Bugs. If resendFunc is
// non-nil, it is called after each simulated timeout to retransmit
// handshake messages from the local end. This is used in cases where
// the peer retransmits on a stale Finished rather than a timeout.
func (c *Conn) simulatePacketLoss(resendFunc func()) error {
	if len(c.config.Bugs.TimeoutSchedule) == 0 {
		return nil
	}
	if !c.isDTLS {
		return errors.New("tls: TimeoutSchedule may only be set in DTLS")
	}
	if c.config.Bugs.PacketAdaptor == nil {
		return errors.New("tls: TimeoutSchedule set without PacketAdapter")
	}
	for _, timeout := range c.config.Bugs.TimeoutSchedule {
		// Simulate a timeout.
		packets, err := c.config.Bugs.PacketAdaptor.SendReadTimeout(timeout)
		if err != nil {
			return err
		}
		for _, packet := range packets {
			if err := c.skipPacket(packet); err != nil {
				return err
			}
		}
		if resendFunc != nil {
			resendFunc()
		}
	}
	return nil
}

func (c *Conn) SendHalfHelloRequest() error {
	if err := c.Handshake(); err != nil {
		return err
	}

	c.out.Lock()
	defer c.out.Unlock()

	if _, err := c.writeRecord(recordTypeHandshake, []byte{typeHelloRequest, 0}); err != nil {
		return err
	}
	return c.flushHandshake()
}

// Write writes data to the connection.
func (c *Conn) Write(b []byte) (int, error) {
	if err := c.Handshake(); err != nil {
		return 0, err
	}

	c.out.Lock()
	defer c.out.Unlock()

	if err := c.out.err; err != nil {
		return 0, err
	}

	if !c.handshakeComplete {
		return 0, alertInternalError
	}

	if c.keyUpdateRequested {
		if err := c.sendKeyUpdateLocked(keyUpdateNotRequested); err != nil {
			return 0, err
		}
		c.keyUpdateRequested = false
	}

	if c.config.Bugs.SendSpuriousAlert != 0 {
		c.sendAlertLocked(alertLevelError, c.config.Bugs.SendSpuriousAlert)
	}

	if c.config.Bugs.SendHelloRequestBeforeEveryAppDataRecord {
		c.writeRecord(recordTypeHandshake, []byte{typeHelloRequest, 0, 0, 0})
		c.flushHandshake()
	}

	// SSL 3.0 and TLS 1.0 are susceptible to a chosen-plaintext
	// attack when using block mode ciphers due to predictable IVs.
	// This can be prevented by splitting each Application Data
	// record into two records, effectively randomizing the IV.
	//
	// http://www.openssl.org/~bodo/tls-cbc.txt
	// https://bugzilla.mozilla.org/show_bug.cgi?id=665814
	// http://www.imperialviolet.org/2012/01/15/beastfollowup.html

	var m int
	if len(b) > 1 && c.vers <= VersionTLS10 && !c.isDTLS {
		if _, ok := c.out.cipher.(cipher.BlockMode); ok {
			n, err := c.writeRecord(recordTypeApplicationData, b[:1])
			if err != nil {
				return n, c.out.setErrorLocked(err)
			}
			m, b = 1, b[1:]
		}
	}

	n, err := c.writeRecord(recordTypeApplicationData, b)
	return n + m, c.out.setErrorLocked(err)
}

func (c *Conn) processTLS13NewSessionTicket(newSessionTicket *newSessionTicketMsg, cipherSuite *cipherSuite) error {
	if c.config.Bugs.ExpectGREASE && !newSessionTicket.hasGREASEExtension {
		return errors.New("tls: no GREASE ticket extension found")
	}

	if c.config.Bugs.ExpectTicketEarlyData && newSessionTicket.maxEarlyDataSize == 0 {
		return errors.New("tls: no early_data ticket extension found")
	}

	if c.config.Bugs.ExpectNoNewSessionTicket {
		return errors.New("tls: received unexpected NewSessionTicket")
	}

	if c.config.ClientSessionCache == nil || newSessionTicket.ticketLifetime == 0 {
		return nil
	}

	session := &ClientSessionState{
		sessionTicket:               newSessionTicket.ticket,
		vers:                        c.vers,
		wireVersion:                 c.wireVersion,
		cipherSuite:                 cipherSuite,
		secret:                      deriveSessionPSK(cipherSuite, c.wireVersion, c.resumptionSecret, newSessionTicket.ticketNonce, c.isDTLS),
		serverCertificates:          c.peerCertificates,
		sctList:                     c.sctList,
		ocspResponse:                c.ocspResponse,
		ticketCreationTime:          c.config.time(),
		ticketExpiration:            c.config.time().Add(time.Duration(newSessionTicket.ticketLifetime) * time.Second),
		ticketAgeAdd:                newSessionTicket.ticketAgeAdd,
		maxEarlyDataSize:            newSessionTicket.maxEarlyDataSize,
		earlyALPN:                   c.clientProtocol,
		hasApplicationSettings:      c.hasApplicationSettings,
		localApplicationSettings:    c.localApplicationSettings,
		peerApplicationSettings:     c.peerApplicationSettings,
		hasApplicationSettingsOld:   c.hasApplicationSettingsOld,
		localApplicationSettingsOld: c.localApplicationSettingsOld,
		peerApplicationSettingsOld:  c.peerApplicationSettingsOld,
	}

	cacheKey := clientSessionCacheKey(c.conn.RemoteAddr(), c.config)
	_, ok := c.config.ClientSessionCache.Get(cacheKey)
	if !ok || !c.config.Bugs.UseFirstSessionTicket {
		c.config.ClientSessionCache.Put(cacheKey, session)
	}
	return nil
}

func (c *Conn) handlePostHandshakeMessage() error {
	msg, err := c.readHandshake()
	if err != nil {
		return err
	}

	if c.vers < VersionTLS13 {
		if !c.isClient {
			c.sendAlert(alertUnexpectedMessage)
			return errors.New("tls: unexpected post-handshake message")
		}

		_, ok := msg.(*helloRequestMsg)
		if !ok {
			c.sendAlert(alertUnexpectedMessage)
			return alertUnexpectedMessage
		}

		c.handshakeComplete = false
		return c.Handshake()
	}

	if c.isClient {
		if newSessionTicket, ok := msg.(*newSessionTicketMsg); ok {
			return c.processTLS13NewSessionTicket(newSessionTicket, c.cipherSuite)
		}
	}

	if keyUpdate, ok := msg.(*keyUpdateMsg); ok {
		c.keyUpdateSeen = true

		if c.config.Bugs.RejectUnsolicitedKeyUpdate {
			return errors.New("tls: unexpected KeyUpdate message")
		}
		if err := c.useInTrafficSecret(encryptionApplication, c.in.wireVersion, c.cipherSuite, updateTrafficSecret(c.cipherSuite.hash(), c.wireVersion, c.in.trafficSecret, c.isDTLS)); err != nil {
			return err
		}
		if keyUpdate.keyUpdateRequest == keyUpdateRequested {
			c.keyUpdateRequested = true
		}
		return nil
	}

	c.sendAlert(alertUnexpectedMessage)
	return errors.New("tls: unexpected post-handshake message")
}

// Reads a KeyUpdate acknowledgment from the peer. There may not be any
// application data records before the message.
func (c *Conn) ReadKeyUpdateACK() error {
	c.in.Lock()
	defer c.in.Unlock()

	msg, err := c.readHandshake()
	if err != nil {
		return err
	}

	keyUpdate, ok := msg.(*keyUpdateMsg)
	if !ok {
		c.sendAlert(alertUnexpectedMessage)
		return fmt.Errorf("tls: unexpected message (%T) when reading KeyUpdate", msg)
	}

	if keyUpdate.keyUpdateRequest != keyUpdateNotRequested {
		return errors.New("tls: received invalid KeyUpdate message")
	}

	return c.useInTrafficSecret(encryptionApplication, c.in.wireVersion, c.cipherSuite, updateTrafficSecret(c.cipherSuite.hash(), c.wireVersion, c.in.trafficSecret, c.isDTLS))
}

func (c *Conn) Renegotiate() error {
	if !c.isClient {
		helloReq := new(helloRequestMsg).marshal()
		if c.config.Bugs.BadHelloRequest != nil {
			helloReq = c.config.Bugs.BadHelloRequest
		}
		c.writeRecord(recordTypeHandshake, helloReq)
		c.flushHandshake()
	}

	c.handshakeComplete = false
	return c.Handshake()
}

// Read can be made to time out and return a net.Error with Timeout() == true
// after a fixed time limit; see SetDeadline and SetReadDeadline.
func (c *Conn) Read(b []byte) (n int, err error) {
	if err = c.Handshake(); err != nil {
		return
	}

	c.in.Lock()
	defer c.in.Unlock()

	// Some OpenSSL servers send empty records in order to randomize the
	// CBC IV. So this loop ignores a limited number of empty records.
	const maxConsecutiveEmptyRecords = 100
	for emptyRecordCount := 0; emptyRecordCount <= maxConsecutiveEmptyRecords; emptyRecordCount++ {
		for c.input.Len() == 0 && c.in.err == nil {
			if err := c.readRecord(recordTypeApplicationData); err != nil {
				// Soft error, like EAGAIN
				return 0, err
			}
			for c.hand.Len() > 0 {
				// We received handshake bytes, indicating a
				// post-handshake message.
				if err := c.handlePostHandshakeMessage(); err != nil {
					return 0, err
				}
			}
		}
		if err := c.in.err; err != nil {
			return 0, err
		}

		n, err = c.input.Read(b)
		if c.input.Len() == 0 || c.isDTLS {
			c.input.Reset()
		}

		// If a close-notify alert is waiting, read it so that
		// we can return (n, EOF) instead of (n, nil), to signal
		// to the HTTP response reading goroutine that the
		// connection is now closed. This eliminates a race
		// where the HTTP response reading goroutine would
		// otherwise not observe the EOF until its next read,
		// by which time a client goroutine might have already
		// tried to reuse the HTTP connection for a new
		// request.
		// See https://codereview.appspot.com/76400046
		// and http://golang.org/issue/3514
		if ri := c.rawInput.Bytes(); !c.isDTLS && n != 0 && err == nil &&
			c.input.Len() == 0 && len(ri) > 0 && recordType(ri[0]) == recordTypeAlert {
			if recErr := c.readRecord(recordTypeApplicationData); recErr != nil {
				err = recErr // will be io.EOF on closeNotify
			}
		}

		if n != 0 || err != nil {
			return n, err
		}
	}

	return 0, io.ErrNoProgress
}

// Close closes the connection.
func (c *Conn) Close() error {
	var alertErr error

	c.handshakeMutex.Lock()
	defer c.handshakeMutex.Unlock()
	if c.handshakeComplete && !c.config.Bugs.NoCloseNotify {
		alert := alertCloseNotify
		if c.config.Bugs.SendAlertOnShutdown != 0 {
			alert = c.config.Bugs.SendAlertOnShutdown
		}
		alertErr = c.sendAlert(alert)
		// Clear local alerts when sending alerts so we continue to wait
		// for the peer rather than closing the socket early.
		if opErr, ok := alertErr.(*net.OpError); ok && opErr.Op == "local error" {
			alertErr = nil
		}
	}

	// Consume a close_notify from the peer if one hasn't been received
	// already. This avoids the peer from failing |SSL_shutdown| due to a
	// write failing.
	if c.handshakeComplete && alertErr == nil && c.config.Bugs.ExpectCloseNotify {
		for c.in.error() == nil {
			c.readRecord(recordTypeAlert)
		}
		if c.in.error() != io.EOF {
			alertErr = c.in.error()
		}
	}

	if err := c.conn.Close(); err != nil {
		return err
	}
	return alertErr
}

// Handshake runs the client or server handshake
// protocol if it has not yet been run.
// Most uses of this package need not call Handshake
// explicitly: the first Read or Write will call it automatically.
func (c *Conn) Handshake() error {
	c.handshakeMutex.Lock()
	defer c.handshakeMutex.Unlock()
	if err := c.handshakeErr; err != nil {
		return err
	}
	if c.handshakeComplete {
		return nil
	}

	if c.isDTLS && c.config.Bugs.SendSplitAlert {
		c.conn.Write([]byte{
			byte(recordTypeAlert), // type
			0xfe, 0xff,            // version
			0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, // sequence
			0x0, 0x2, // length
		})
		c.conn.Write([]byte{alertLevelError, byte(alertInternalError)})
	}
	if data := c.config.Bugs.AppDataBeforeHandshake; data != nil {
		c.writeRecord(recordTypeApplicationData, data)
	}
	if c.isClient {
		c.handshakeErr = c.clientHandshake()
	} else {
		c.handshakeErr = c.serverHandshake()
	}
	if c.handshakeErr == nil && c.config.Bugs.SendInvalidRecordType {
		c.writeRecord(recordType(42), []byte("invalid record"))
	}
	return c.handshakeErr
}

// ConnectionState returns basic TLS details about the connection.
func (c *Conn) ConnectionState() ConnectionState {
	c.handshakeMutex.Lock()
	defer c.handshakeMutex.Unlock()

	var state ConnectionState
	state.HandshakeComplete = c.handshakeComplete
	if c.handshakeComplete {
		state.Version = c.vers
		state.NegotiatedProtocol = c.clientProtocol
		state.DidResume = c.didResume
		state.NegotiatedProtocolIsMutual = !c.clientProtocolFallback
		state.NegotiatedProtocolFromALPN = c.usedALPN
		state.CipherSuite = c.cipherSuite.id
		state.PeerCertificates = c.peerCertificates
		state.PeerDelegatedCredential = c.peerDelegatedCredential
		state.VerifiedChains = c.verifiedChains
		state.OCSPResponse = c.ocspResponse
		state.ServerName = c.serverName
		state.ChannelID = c.channelID
		state.SRTPProtectionProfile = c.srtpProtectionProfile
		state.TLSUnique = c.firstFinished[:]
		state.SCTList = c.sctList
		state.PeerSignatureAlgorithm = c.peerSignatureAlgorithm
		state.CurveID = c.curveID
		state.QUICTransportParams = c.quicTransportParams
		state.QUICTransportParamsLegacy = c.quicTransportParamsLegacy
		state.HasApplicationSettings = c.hasApplicationSettings
		state.PeerApplicationSettings = c.peerApplicationSettings
		state.HasApplicationSettingsOld = c.hasApplicationSettingsOld
		state.PeerApplicationSettingsOld = c.peerApplicationSettingsOld
		state.ECHAccepted = c.echAccepted
	}

	return state
}

// VerifyHostname checks that the peer certificate chain is valid for
// connecting to host.  If so, it returns nil; if not, it returns an error
// describing the problem.
func (c *Conn) VerifyHostname(host string) error {
	c.handshakeMutex.Lock()
	defer c.handshakeMutex.Unlock()
	if !c.isClient {
		return errors.New("tls: VerifyHostname called on TLS server connection")
	}
	if !c.handshakeComplete {
		return errors.New("tls: handshake has not yet been performed")
	}
	return c.peerCertificates[0].VerifyHostname(host)
}

func (c *Conn) exportKeyingMaterialTLS13(length int, secret, label, context []byte) []byte {
	hash := c.cipherSuite.hash()
	exporterKeyingLabel := []byte("exporter")
	contextHash := hash.New()
	contextHash.Write(context)
	exporterContext := hash.New().Sum(nil)
	derivedSecret := hkdfExpandLabel(c.cipherSuite.hash(), secret, label, exporterContext, hash.Size(), c.isDTLS)
	return hkdfExpandLabel(c.cipherSuite.hash(), derivedSecret, exporterKeyingLabel, contextHash.Sum(nil), length, c.isDTLS)
}

// ExportKeyingMaterial exports keying material from the current connection
// state, as per RFC 5705.
func (c *Conn) ExportKeyingMaterial(length int, label, context []byte, useContext bool) ([]byte, error) {
	c.handshakeMutex.Lock()
	defer c.handshakeMutex.Unlock()
	if !c.handshakeComplete {
		return nil, errors.New("tls: handshake has not yet been performed")
	}

	if c.vers >= VersionTLS13 {
		return c.exportKeyingMaterialTLS13(length, c.exporterSecret, label, context), nil
	}

	seedLen := len(c.clientRandom) + len(c.serverRandom)
	if useContext {
		seedLen += 2 + len(context)
	}
	seed := make([]byte, 0, seedLen)
	seed = append(seed, c.clientRandom[:]...)
	seed = append(seed, c.serverRandom[:]...)
	if useContext {
		seed = append(seed, byte(len(context)>>8), byte(len(context)))
		seed = append(seed, context...)
	}
	result := make([]byte, length)
	prfForVersion(c.vers, c.cipherSuite)(result, c.exporterSecret, label, seed)
	return result, nil
}

func (c *Conn) ExportEarlyKeyingMaterial(length int, label, context []byte) ([]byte, error) {
	if c.vers < VersionTLS13 {
		return nil, errors.New("tls: early exporters not defined before TLS 1.3")
	}

	if c.earlyExporterSecret == nil {
		return nil, errors.New("tls: no early exporter secret")
	}

	return c.exportKeyingMaterialTLS13(length, c.earlyExporterSecret, label, context), nil
}

// noRenegotiationInfo returns true if the renegotiation info extension
// should be supported in the current handshake.
func (c *Conn) noRenegotiationInfo() bool {
	if c.config.Bugs.NoRenegotiationInfo {
		return true
	}
	if c.cipherSuite == nil && c.config.Bugs.NoRenegotiationInfoInInitial {
		return true
	}
	if c.cipherSuite != nil && c.config.Bugs.NoRenegotiationInfoAfterInitial {
		return true
	}
	return false
}

func (c *Conn) SendNewSessionTicket(nonce []byte) error {
	if c.isClient || c.vers < VersionTLS13 {
		return errors.New("tls: cannot send post-handshake NewSessionTicket")
	}

	var peerCertificatesRaw [][]byte
	for _, cert := range c.peerCertificates {
		peerCertificatesRaw = append(peerCertificatesRaw, cert.Raw)
	}

	addBuffer := make([]byte, 4)
	_, err := io.ReadFull(c.config.rand(), addBuffer)
	if err != nil {
		c.sendAlert(alertInternalError)
		return errors.New("tls: short read from Rand: " + err.Error())
	}
	ticketAgeAdd := uint32(addBuffer[3])<<24 | uint32(addBuffer[2])<<16 | uint32(addBuffer[1])<<8 | uint32(addBuffer[0])

	// TODO(davidben): Allow configuring these values.
	m := &newSessionTicketMsg{
		vers:                        c.wireVersion,
		isDTLS:                      c.isDTLS,
		ticketLifetime:              uint32(24 * time.Hour / time.Second),
		duplicateEarlyDataExtension: c.config.Bugs.DuplicateTicketEarlyData,
		customExtension:             c.config.Bugs.CustomTicketExtension,
		ticketAgeAdd:                ticketAgeAdd,
		ticketNonce:                 nonce,
		maxEarlyDataSize:            c.config.MaxEarlyDataSize,
	}
	if c.config.Bugs.MockQUICTransport != nil && m.maxEarlyDataSize > 0 {
		m.maxEarlyDataSize = 0xffffffff
	}

	if c.config.Bugs.SendTicketLifetime != 0 {
		m.ticketLifetime = uint32(c.config.Bugs.SendTicketLifetime / time.Second)
	}

	state := sessionState{
		vers:                        c.vers,
		cipherSuite:                 c.cipherSuite.id,
		secret:                      deriveSessionPSK(c.cipherSuite, c.wireVersion, c.resumptionSecret, nonce, c.isDTLS),
		certificates:                peerCertificatesRaw,
		ticketCreationTime:          c.config.time(),
		ticketExpiration:            c.config.time().Add(time.Duration(m.ticketLifetime) * time.Second),
		ticketAgeAdd:                uint32(addBuffer[3])<<24 | uint32(addBuffer[2])<<16 | uint32(addBuffer[1])<<8 | uint32(addBuffer[0]),
		earlyALPN:                   []byte(c.clientProtocol),
		hasApplicationSettings:      c.hasApplicationSettings,
		localApplicationSettings:    c.localApplicationSettings,
		peerApplicationSettings:     c.peerApplicationSettings,
		hasApplicationSettingsOld:   c.hasApplicationSettingsOld,
		localApplicationSettingsOld: c.localApplicationSettingsOld,
		peerApplicationSettingsOld:  c.peerApplicationSettingsOld,
	}

	if !c.config.Bugs.SendEmptySessionTicket {
		var err error
		m.ticket, err = c.encryptTicket(&state)
		if err != nil {
			return err
		}
	}
	c.out.Lock()
	defer c.out.Unlock()
	_, err = c.writeRecord(recordTypeHandshake, m.marshal())
	return err
}

func (c *Conn) SendKeyUpdate(keyUpdateRequest byte) error {
	c.out.Lock()
	defer c.out.Unlock()
	return c.sendKeyUpdateLocked(keyUpdateRequest)
}

func (c *Conn) sendKeyUpdateLocked(keyUpdateRequest byte) error {
	if c.vers < VersionTLS13 {
		return errors.New("tls: attempted to send KeyUpdate before TLS 1.3")
	}

	m := keyUpdateMsg{
		keyUpdateRequest: keyUpdateRequest,
	}
	if _, err := c.writeRecord(recordTypeHandshake, m.marshal()); err != nil {
		return err
	}
	if err := c.flushHandshake(); err != nil {
		return err
	}
	c.useOutTrafficSecret(encryptionApplication, c.out.wireVersion, c.cipherSuite, updateTrafficSecret(c.cipherSuite.hash(), c.wireVersion, c.out.trafficSecret, c.isDTLS))
	return nil
}

func (c *Conn) sendFakeEarlyData(len int) error {
	// Assemble a fake early data record. This does not use writeRecord
	// because the record layer may be using different keys at this point.
	payload := make([]byte, 5+len)
	payload[0] = byte(recordTypeApplicationData)
	payload[1] = 3
	payload[2] = 3
	payload[3] = byte(len >> 8)
	payload[4] = byte(len)
	_, err := c.conn.Write(payload)
	return err
}

func (c *Conn) usesEndOfEarlyData() bool {
	if c.isClient && c.config.Bugs.SendEndOfEarlyDataInQUICAndDTLS {
		return true
	}
	return c.config.Bugs.MockQUICTransport == nil && !c.isDTLS
}
