// Copyright 2009 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.

package runner

import (
	"bytes"
	"crypto"
	"crypto/ecdsa"
	"crypto/ed25519"
	"crypto/elliptic"
	"crypto/rsa"
	"crypto/subtle"
	"crypto/x509"
	"errors"
	"fmt"
	"io"
	"math/big"
	"net"
	"slices"
	"time"

	"boringssl.googlesource.com/boringssl.git/ssl/test/runner/hpke"
	"boringssl.googlesource.com/boringssl.git/ssl/test/runner/spake2plus"
	"filippo.io/mldsa"
	"golang.org/x/crypto/cryptobyte"
)

const echBadPayloadByte = 0xff

type clientHandshakeState struct {
	c              *Conn
	serverHello    *serverHelloMsg
	hello          *clientHelloMsg
	innerHello     *clientHelloMsg
	echHPKEContext *hpke.Context
	suite          *cipherSuite
	finishedHash   finishedHash
	keyShares      map[CurveID]kemImplementation
	masterSecret   []byte
	session        *ClientSessionState
	preSharedKeys  []*preSharedKey
	finishedBytes  []byte
	peerPublicKey  crypto.PublicKey
	pakeContext    *spake2plus.Context
}

func mapClientHelloVersion(vers uint16, isDTLS bool) uint16 {
	if !isDTLS {
		return vers
	}

	switch vers {
	case VersionTLS12:
		return VersionDTLS12
	case VersionTLS11, VersionTLS10:
		// There is no DTLS 1.1.
		return VersionDTLS10
	}

	panic("Unknown ClientHello version.")
}

// replaceClientHello returns a new clientHelloMsg which serializes to |in|, but
// with key shares copied from |hello|. This allows sending an exact
// externally-specified ClientHello in tests. However, we use |hello|'s key
// shares. This ensures we have the private keys to complete the handshake. Note
// this function does not update internal handshake state, so the test must be
// configured compatibly with |in|.
func replaceClientHello(hello *clientHelloMsg, in []byte) (*clientHelloMsg, error) {
	copied := slices.Clone(in)
	newHello := new(clientHelloMsg)
	if !newHello.unmarshal(copied) {
		return nil, errors.New("tls: invalid ClientHello")
	}

	// Replace |newHellos|'s key shares with those of |hello|. For simplicity,
	// we require their lengths match, which is satisfied by matching the
	// DefaultCurves setting to the selection in the replacement ClientHello.
	bb := cryptobyte.NewBuilder(nil)
	hello.marshalKeyShares(bb)
	keyShares, err := bb.Bytes()
	if err != nil {
		return nil, err
	}
	if len(keyShares) != len(newHello.keySharesRaw) {
		return nil, errors.New("tls: ClientHello key share length is inconsistent with DefaultCurves setting")
	}
	// |newHello.keySharesRaw| aliases |copied|.
	copy(newHello.keySharesRaw, keyShares)
	newHello.keyShares = hello.keyShares

	return newHello, nil
}

func (c *Conn) clientHandshake() error {
	if c.config == nil {
		c.config = defaultConfig()
	}

	if len(c.config.ServerName) == 0 && !c.config.InsecureSkipVerify {
		return errors.New("tls: either ServerName or InsecureSkipVerify must be specified in the tls.Config")
	}

	c.sendHandshakeSeq = 0
	c.recvHandshakeSeq = 0

	hs := &clientHandshakeState{
		c:         c,
		keyShares: make(map[CurveID]kemImplementation),
	}

	// Pick a session to resume.
	var session *ClientSessionState
	var cacheKey string
	sessionCache := c.config.ClientSessionCache
	if sessionCache != nil {
		// Try to resume a previously negotiated TLS session, if
		// available.
		cacheKey = clientSessionCacheKey(c.conn.RemoteAddr(), c.config)
		// TODO(nharper): Support storing more than one session
		// ticket for TLS 1.3.
		candidateSession, ok := sessionCache.Get(cacheKey)
		if ok {
			ticketOk := !c.config.SessionTicketsDisabled || candidateSession.sessionTicket == nil
			lifetimeOk := c.config.time().Before(candidateSession.ticketExpiration)

			// Check that the ciphersuite/version used for the
			// previous session are still valid.
			cipherSuiteOk := false
			if candidateSession.vers.protocolVersion() <= VersionTLS12 {
				cipherSuiteOk = slices.Contains(c.config.cipherSuites(), candidateSession.cipherSuite.id)
			} else {
				// TLS 1.3 allows the cipher to change on
				// resumption.
				cipherSuiteOk = true
			}

			_, versOk := c.config.isSupportedVersion(candidateSession.vers.wire, c.isDTLS)
			if ticketOk && lifetimeOk && versOk && cipherSuiteOk {
				session = candidateSession
				hs.session = session
			}
		}
	}

	if session != nil && c.config.Bugs.FilterTicket != nil && len(session.sessionTicket) > 0 {
		// Copy the ticket so FilterTicket may act in-place.
		session.sessionTicket = slices.Clone(session.sessionTicket)
		var err error
		session.sessionTicket, err = c.config.Bugs.FilterTicket(session.sessionTicket)
		if err != nil {
			return err
		}
	}

	// Set up TLS 1.3 pre-shared keys.
	if session != nil && (session.vers.protocolVersion() >= VersionTLS13 || c.config.Bugs.SendBothTickets) {
		hs.preSharedKeys = append(hs.preSharedKeys, newClientSessionPSK(session))
	}
	pskCreds := c.config.PSKCredentials
	if c.config.Credential != nil && c.config.Credential.Type == CredentialTypePreSharedKey {
		pskCreds = append(slices.Clone(pskCreds), c.config.Credential)
	}
	for _, cred := range pskCreds {
		targetProtocol := version{VersionTLS13}
		if c.isDTLS {
			targetProtocol = version{VersionDTLS13}
		}
		if len(cred.ImportTargetPSKHashes) != 0 {
			for _, targetHash := range cred.ImportTargetPSKHashes {
				hs.preSharedKeys = append(hs.preSharedKeys, importPSK(cred, targetProtocol, targetHash))
			}
		} else {
			hs.preSharedKeys = append(hs.preSharedKeys, importPSK(cred, targetProtocol, crypto.SHA256))
			hs.preSharedKeys = append(hs.preSharedKeys, importPSK(cred, targetProtocol, crypto.SHA384))
		}
	}

	// Set up ECH parameters.
	var err error
	var earlyHello *clientHelloMsg
	if c.config.ClientECHConfig != nil {
		if c.config.ClientECHConfig.KEM != hpke.X25519WithHKDFSHA256 {
			return errors.New("tls: unsupported KEM type in ECHConfig")
		}

		echCipherSuite, ok := chooseECHCipherSuite(c.config.ClientECHConfig, c.config)
		if !ok {
			return errors.New("tls: did not find compatible cipher suite in ECHConfig")
		}

		info := []byte("tls ech\x00")
		info = append(info, c.config.ClientECHConfig.Raw...)

		var echEnc []byte
		hs.echHPKEContext, echEnc, err = hpke.SetupBaseSenderX25519(echCipherSuite.KDF, echCipherSuite.AEAD, c.config.ClientECHConfig.PublicKey, info, nil)
		if err != nil {
			return errors.New("tls: ech: failed to set up client's HPKE sender context")
		}

		hs.innerHello, err = hs.createClientHello(nil, nil)
		if err != nil {
			return err
		}
		hs.hello, err = hs.createClientHello(hs.innerHello, echEnc)
		if err != nil {
			return err
		}
		earlyHello = hs.innerHello
	} else {
		hs.hello, err = hs.createClientHello(nil, nil)
		if err != nil {
			return err
		}
		earlyHello = hs.hello
	}

	if len(earlyHello.pskIdentities) == 0 || c.config.Bugs.SendEarlyData == nil {
		earlyHello = nil
	}

	if c.config.Bugs.SendV2ClientHello {
		hs.hello.isV2ClientHello = true

		// The V2ClientHello "challenge" field is variable-length and is
		// left-padded or truncated to become the SSL3/TLS random.
		challengeLength := c.config.Bugs.V2ClientHelloChallengeLength
		if challengeLength == 0 {
			challengeLength = len(hs.hello.random)
		}
		if challengeLength <= len(hs.hello.random) {
			skip := len(hs.hello.random) - challengeLength
			clear(hs.hello.random[:skip])
			hs.hello.v2Challenge = hs.hello.random[skip:]
		} else {
			hs.hello.v2Challenge = make([]byte, challengeLength)
			copy(hs.hello.v2Challenge, hs.hello.random)
			if _, err := io.ReadFull(c.config.rand(), hs.hello.v2Challenge[len(hs.hello.random):]); err != nil {
				c.sendAlert(alertInternalError)
				return fmt.Errorf("tls: short read from Rand: %s", err)
			}
		}

		c.writeV2Record(hs.hello.marshal())
	} else {
		helloBytes := hs.hello.marshal()
		var appendToHello byte
		if c.config.Bugs.PartialClientFinishedWithClientHello {
			appendToHello = typeFinished
		} else if c.config.Bugs.PartialEndOfEarlyDataWithClientHello {
			appendToHello = typeEndOfEarlyData
		} else if c.config.Bugs.PartialSecondClientHelloAfterFirst {
			appendToHello = typeClientHello
		} else if c.config.Bugs.PartialClientKeyExchangeWithClientHello {
			appendToHello = typeClientKeyExchange
		}
		if appendToHello != 0 {
			c.writeRecord(recordTypeHandshake, append(slices.Clip(helloBytes), appendToHello))
		} else {
			c.writeRecord(recordTypeHandshake, helloBytes)
		}
	}
	if err := c.flushHandshake(); err != nil {
		return err
	}

	if c.config.Bugs.SendEarlyAlert {
		c.sendAlert(alertHandshakeFailure)
	}
	if c.config.Bugs.SendFakeEarlyDataLength > 0 {
		c.sendFakeEarlyData(c.config.Bugs.SendFakeEarlyDataLength)
	}

	// Derive early write keys and set Conn state to allow early writes.
	if earlyHello != nil {
		finishedHash := newFinishedHash(session.vers, session.cipherSuite.hash())
		finishedHash.addEntropy(session.secret)
		finishedHash.Write(earlyHello.marshal())

		if !c.config.Bugs.SkipChangeCipherSpec {
			c.vers = session.vers
			c.writeRecord(recordTypeChangeCipherSpec, []byte{1})
			c.vers = version{}
		}

		earlyTrafficSecret := finishedHash.deriveSecret(earlyTrafficLabel)
		c.earlyExporterSecret = finishedHash.deriveSecret(earlyExporterLabel)

		c.useOutTrafficSecret(uint16(encryptionEarlyData), session.vers, session.cipherSuite, earlyTrafficSecret)
		for _, earlyData := range c.config.Bugs.SendEarlyData {
			if _, err := c.writeRecord(recordTypeApplicationData, earlyData); err != nil {
				return err
			}
		}
	}

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

	if c.isDTLS {
		helloVerifyRequest, ok := msg.(*helloVerifyRequestMsg)
		if ok {
			if helloVerifyRequest.vers != VersionDTLS10 {
				// Per RFC 6347, the version field in
				// HelloVerifyRequest SHOULD be always DTLS
				// 1.0. Enforce this for testing purposes.
				return errors.New("dtls: bad HelloVerifyRequest version")
			}

			hs.hello.raw = nil
			hs.hello.cookie = helloVerifyRequest.cookie
			c.writeRecord(recordTypeHandshake, hs.hello.marshal())
			if err := c.flushHandshake(); err != nil {
				return err
			}

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

	// The first message is either ServerHello or HelloRetryRequest, either of
	// which determines the version and cipher suite.
	var serverWireVersion, suiteID uint16
	switch m := msg.(type) {
	case *helloRetryRequestMsg:
		serverWireVersion = m.vers
		suiteID = m.cipherSuite
	case *serverHelloMsg:
		serverWireVersion = m.vers
		suiteID = m.cipherSuite
	default:
		c.sendAlert(alertUnexpectedMessage)
		return fmt.Errorf("tls: received unexpected message of type %T when waiting for HelloRetryRequest or ServerHello", msg)
	}

	serverVersion, ok := c.config.isSupportedVersion(serverWireVersion, c.isDTLS)
	if !ok {
		c.sendAlert(alertProtocolVersion)
		return fmt.Errorf("tls: server selected unsupported protocol version %x", c.vers)
	}
	c.vers = serverVersion
	c.haveVers = true

	// We only implement enough of SSL 3.0 to test that the server doesn't:
	// we can send a ClientHello and attempt to read a ServerHello. The server
	// should respond with a protocol_version alert and not get this far.
	if c.vers.protocolVersion() == VersionSSL30 {
		return errors.New("tls: server selected SSL 3.0")
	}

	cipherSuites := hs.hello.cipherSuites
	if hs.innerHello != nil && c.config.Bugs.MinimalClientHelloOuter {
		// hs.hello has a placeholder list of ciphers if testing with
		// MinimalClientHelloOuter, so we use hs.innerHello instead. (We do not
		// attempt to support actual different cipher suite preferences between
		// the two.)
		cipherSuites = hs.innerHello.cipherSuites
	}
	hs.suite = mutualCipherSuite(cipherSuites, suiteID)
	if hs.suite == nil {
		c.sendAlert(alertHandshakeFailure)
		return fmt.Errorf("tls: server selected an unsupported cipher suite")
	}

	hs.finishedHash = newFinishedHash(c.vers, hs.suite.hash())
	hs.finishedHash.WriteHandshake(hs.hello.marshal(), hs.c.sendHandshakeSeq-1)

	if c.vers.protocolVersion() >= VersionTLS13 {
		if err := hs.doTLS13Handshake(msg); err != nil {
			return err
		}
	} else {
		hs.serverHello, ok = msg.(*serverHelloMsg)
		if !ok {
			c.sendAlert(alertUnexpectedMessage)
			return unexpectedMessageError(hs.serverHello, msg)
		}
		if isAllZero(hs.serverHello.random) {
			// If the server forgets to fill in the server random, it will
			// likely be all zero.
			return errors.New("tls: ServerHello random was all zero")
		}

		hs.writeServerHash(hs.serverHello.marshal())
		if c.config.Bugs.EarlyChangeCipherSpec > 0 {
			hs.establishKeys()
			c.writeRecord(recordTypeChangeCipherSpec, []byte{1})
		}

		if hs.serverHello.compressionMethod != compressionNone {
			c.sendAlert(alertUnexpectedMessage)
			return errors.New("tls: server selected unsupported compression format")
		}

		err = hs.processServerExtensions(&hs.serverHello.extensions)
		if err != nil {
			return err
		}

		isResume, err := hs.processServerHello()
		if err != nil {
			return err
		}

		err = hs.processServerExtensionsAfterResume(&hs.serverHello.extensions, isResume)
		if err != nil {
			return err
		}

		if isResume {
			if c.config.Bugs.EarlyChangeCipherSpec == 0 {
				if err := hs.establishKeys(); err != nil {
					return err
				}
			}
			if err := hs.readSessionTicket(); err != nil {
				return err
			}
			if err := hs.readFinished(c.firstFinished[:]); err != nil {
				return err
			}
			if err := hs.sendFinished(nil, isResume); err != nil {
				return err
			}
		} else {
			if err := hs.doFullHandshake(); err != nil {
				return err
			}
			if err := hs.establishKeys(); err != nil {
				return err
			}
			if err := hs.sendFinished(c.firstFinished[:], isResume); err != nil {
				return err
			}
			if err := hs.readSessionTicket(); err != nil {
				return err
			}
			if err := hs.readFinished(nil); err != nil {
				return err
			}
			if err := c.ackHandshake(); err != nil {
				return err
			}
		}

		if sessionCache != nil && hs.session != nil && session != hs.session {
			if c.config.Bugs.RequireSessionTickets && len(hs.session.sessionTicket) == 0 {
				return errors.New("tls: new session used session IDs instead of tickets")
			}
			if c.config.Bugs.RequireSessionIDs && len(hs.session.sessionID) == 0 {
				return errors.New("tls: new session used session tickets instead of IDs")
			}
			sessionCache.Put(cacheKey, hs.session)
		}

		c.didResume = isResume
		c.exporterSecret = hs.masterSecret
	}

	c.handshakeComplete = true
	c.cipherSuite = hs.suite
	copy(c.clientRandom[:], hs.hello.random)
	copy(c.serverRandom[:], hs.serverHello.random)

	return nil
}

func chooseECHCipherSuite(echConfig *ECHConfig, config *Config) (HPKECipherSuite, bool) {
	if echConfig.KEM != hpke.X25519WithHKDFSHA256 {
		return HPKECipherSuite{}, false
	}

	for _, suite := range config.echCipherSuitePreferences() {
		if config.Bugs.IgnoreECHConfigCipherPreferences || slices.Contains(echConfig.CipherSuites, suite) {
			return suite, true
		}
	}
	return HPKECipherSuite{}, false
}

// createClientHello creates a new ClientHello message. If |innerHello| is not
// nil, this is a ClientHelloOuter that should contain an encrypted |innerHello|
// with |echEnc| as the encapsulated public key. Otherwise, the ClientHello
// should reflect the connection's true preferences.
func (hs *clientHandshakeState) createClientHello(innerHello *clientHelloMsg, echEnc []byte) (*clientHelloMsg, error) {
	c := hs.c
	nextProtosLength := 0
	for _, proto := range c.config.NextProtos {
		if l := len(proto); l > 255 {
			return nil, errors.New("tls: invalid NextProtos value")
		} else {
			nextProtosLength += 1 + l
		}
	}
	if nextProtosLength > 0xffff {
		return nil, errors.New("tls: NextProtos values too large")
	}

	quicTransportParams := c.config.QUICTransportParams
	quicTransportParamsLegacy := c.config.QUICTransportParams
	if !c.config.QUICTransportParamsUseLegacyCodepoint.IncludeStandard() {
		quicTransportParams = nil
	}
	if !c.config.QUICTransportParamsUseLegacyCodepoint.IncludeLegacy() {
		quicTransportParamsLegacy = nil
	}

	isInner := innerHello == nil && hs.echHPKEContext != nil

	minVersion := c.config.minVersion()
	maxVersion := c.config.maxVersion()
	// The ClientHelloInner may not offer TLS 1.2 or below.
	requireTLS13 := isInner && !c.config.Bugs.AllowTLS12InClientHelloInner
	if requireTLS13 && minVersion < VersionTLS13 {
		minVersion = VersionTLS13
		if minVersion > maxVersion {
			return nil, errors.New("tls: ECH requires TLS 1.3")
		}
	}

	hello := &clientHelloMsg{
		isDTLS:                     c.isDTLS,
		compressionMethods:         []uint8{compressionNone},
		random:                     make([]byte, 32),
		cookie:                     c.config.Bugs.SendLegacyDTLSCookie,
		ocspStapling:               !c.config.Bugs.NoOCSPStapling,
		sctListSupported:           !c.config.Bugs.NoSignedCertificateTimestamps,
		supportedCurves:            c.config.curvePreferences(),
		supportedPoints:            []uint8{pointFormatUncompressed},
		nextProtoNeg:               len(c.config.NextProtos) > 0,
		secureRenegotiation:        []byte{},
		alpnProtocols:              c.config.NextProtos,
		quicTransportParams:        quicTransportParams,
		quicTransportParamsLegacy:  quicTransportParamsLegacy,
		duplicateExtension:         c.config.Bugs.DuplicateExtension,
		channelIDSupported:         c.config.ChannelID != nil,
		extendedMasterSecret:       maxVersion >= VersionTLS10,
		srtpProtectionProfiles:     c.config.SRTPProtectionProfiles,
		srtpMasterKeyIdentifier:    c.config.Bugs.SRTPMasterKeyIdentifier,
		customExtension:            c.config.Bugs.CustomExtension,
		omitExtensions:             c.config.Bugs.OmitExtensions,
		emptyExtensions:            c.config.Bugs.EmptyExtensions,
		delegatedCredential:        c.config.DelegatedCredentialAlgorithms,
		trustAnchors:               c.config.RequestTrustAnchors,
		clientCertificateTypes:     c.config.Bugs.SendClientCertificateTypes,
		serverCertificateTypes:     c.config.Bugs.SendServerCertificateTypes,
		extensionsWithTrailingData: c.config.Bugs.ExtensionsWithTrailingData,
		serverPaddingRequest:       c.config.RequestServerPadding,
	}

	// Translate the bugs that modify ClientHello extension order into a
	// list of prefix extensions. The marshal function will try these
	// extensions before any others, followed by any remaining extensions in
	// the default order.
	if c.config.Bugs.PSKBinderFirst && !c.config.Bugs.OnlyCorruptSecondPSKBinder {
		hello.prefixExtensions = append(hello.prefixExtensions, extensionPreSharedKey)
	}
	if c.config.Bugs.SwapNPNAndALPN {
		hello.prefixExtensions = append(hello.prefixExtensions, extensionALPN)
		hello.prefixExtensions = append(hello.prefixExtensions, extensionNextProtoNeg)
	}

	// Configure ech_outer_extensions.
	if isInner {
		hello.outerExtensions = c.config.ECHOuterExtensions
		// If |OnlyCompressSecondClientHelloInner| is set, we still configure
		// |hello.outerExtensions| for ordering, so that we do not introduce an
		// unsolicited change across HelloRetryRequest.
		hello.reorderOuterExtensionsWithoutCompressing = c.config.Bugs.OnlyCompressSecondClientHelloInner
	} else {
		// Compressed extensions must appear in the same relative order between
		// ClientHelloInner and ClientHelloOuter. For simplicity, we default to
		// forcing their order to match, but the caller can override this with
		// either valid or invalid explicit orders.
		if c.config.Bugs.ECHOuterExtensionOrder != nil {
			hello.prefixExtensions = append(hello.prefixExtensions, c.config.Bugs.ECHOuterExtensionOrder...)
		} else {
			hello.prefixExtensions = append(hello.prefixExtensions, c.config.ECHOuterExtensions...)
		}
	}

	if maxVersion >= VersionTLS13 {
		hello.vers = mapClientHelloVersion(VersionTLS12, c.isDTLS)
		if !c.config.Bugs.OmitSupportedVersions {
			hello.supportedVersions = c.config.supportedVersions(c.isDTLS, requireTLS13)
		}
		hello.pskKEModes = []byte{pskDHEKEMode}
	} else {
		hello.vers = mapClientHelloVersion(maxVersion, c.isDTLS)
	}

	if c.config.Bugs.SendClientVersion != 0 {
		hello.vers = c.config.Bugs.SendClientVersion
	}

	if len(c.config.Bugs.SendSupportedVersions) > 0 {
		hello.supportedVersions = c.config.Bugs.SendSupportedVersions
	}

	if innerHello != nil {
		hello.serverName = c.config.ClientECHConfig.PublicName
	} else {
		hello.serverName = c.config.ServerName
	}

	if !isInner && c.config.Bugs.OmitPublicName {
		hello.serverName = ""
	}

	disableEMS := c.config.Bugs.NoExtendedMasterSecret
	if c.cipherSuite != nil {
		disableEMS = c.config.Bugs.NoExtendedMasterSecretOnRenegotiation
	}

	if disableEMS {
		hello.extendedMasterSecret = false
	}

	if c.config.Bugs.NoSupportedCurves {
		hello.supportedCurves = nil
	}

	if c.config.Bugs.SendPSKKeyExchangeModes != nil {
		hello.pskKEModes = c.config.Bugs.SendPSKKeyExchangeModes
	}

	if c.config.Bugs.SendCompressionMethods != nil {
		hello.compressionMethods = c.config.Bugs.SendCompressionMethods
	}

	if c.config.Bugs.SendSupportedPointFormats != nil {
		hello.supportedPoints = c.config.Bugs.SendSupportedPointFormats
	}

	if len(c.clientVerify) > 0 && !c.config.Bugs.EmptyRenegotiationInfo {
		if c.config.Bugs.BadRenegotiationInfo {
			hello.secureRenegotiation = append(hello.secureRenegotiation, c.clientVerify...)
			hello.secureRenegotiation[0] ^= 0x80
		} else {
			hello.secureRenegotiation = c.clientVerify
		}
	}

	if c.config.Bugs.DuplicateCompressedCertAlgs {
		hello.compressedCertAlgs = []uint16{1, 1}
	} else if len(c.config.CertCompressionAlgs) > 0 {
		hello.compressedCertAlgs = make([]uint16, 0, len(c.config.CertCompressionAlgs))
		for id := range c.config.CertCompressionAlgs {
			hello.compressedCertAlgs = append(hello.compressedCertAlgs, uint16(id))
		}
	}

	if c.noRenegotiationInfo() {
		hello.secureRenegotiation = nil
	}

	if c.config.ALPSUseNewCodepoint.IncludeNew() {
		for protocol := range c.config.ApplicationSettings {
			hello.alpsProtocols = append(hello.alpsProtocols, protocol)
		}
	}
	if c.config.ALPSUseNewCodepoint.IncludeOld() {
		for protocol := range c.config.ApplicationSettings {
			hello.alpsProtocolsOld = append(hello.alpsProtocolsOld, protocol)
		}
	}

	if c.config.SendRootCAs && c.config.RootCAs != nil {
		hello.certificateAuthorities = c.config.RootCAs.Subjects()
	}
	if c.config.Bugs.SendEmptyCertificateAuthorities {
		hello.certificateAuthorities = [][]byte{}
	}

	if maxVersion >= VersionTLS13 {
		// Use the same key shares between ClientHelloInner and ClientHelloOuter.
		if innerHello != nil {
			hello.hasKeyShares = innerHello.hasKeyShares
			hello.keyShares = innerHello.keyShares
		} else {
			hello.hasKeyShares = true
			hello.trailingKeyShareData = c.config.Bugs.TrailingKeyShareData
			curvesToSend := c.config.defaultCurves()
			for _, curveID := range hello.supportedCurves {
				if !curvesToSend[curveID] {
					continue
				}
				kem, ok := kemForCurveID(curveID, c.config)
				if !ok {
					continue
				}
				publicKey, err := kem.generate(c.config)
				if err != nil {
					return nil, err
				}

				if c.config.Bugs.SendCurve != 0 {
					curveID = c.config.Bugs.SendCurve
				}

				hello.keyShares = append(hello.keyShares, keyShareEntry{
					group:       curveID,
					keyExchange: publicKey,
				})
				hs.keyShares[curveID] = kem

				if c.config.Bugs.DuplicateKeyShares {
					hello.keyShares = append(hello.keyShares, hello.keyShares[len(hello.keyShares)-1])
				}
			}

			if c.config.Bugs.MissingKeyShare {
				hello.hasKeyShares = false
			}
		}
	}

	for _, id := range c.config.Bugs.OfferExtraPAKEs {
		hello.pakeClientID = c.config.Bugs.OfferExtraPAKEClientID
		hello.pakeServerID = c.config.Bugs.OfferExtraPAKEServerID
		hello.pakeShares = append(hello.pakeShares, pakeShare{id: id, msg: []byte{1}})
	}
	if cred := c.config.Credential; cred != nil && cred.Type == CredentialTypeSPAKE2PlusV1 {
		if maxVersion < VersionTLS13 {
			panic("The PAKE extension is only supported in TLS 1.3")
		}
		w0, w1, _, err := spake2plus.Register(cred.PAKEPassword, cred.PAKEClientID, cred.PAKEServerID)
		if err != nil {
			return nil, err
		}
		hs.pakeContext, err = spake2plus.NewProver(cred.PAKEContext, cred.PAKEClientID, cred.PAKEServerID, w0, w1)
		if err != nil {
			return nil, err
		}
		share, err := hs.pakeContext.GenerateProverShare()
		if err != nil {
			return nil, err
		}
		if c.config.Bugs.TruncatePAKEMessage {
			share = share[:len(share)-1]
		}
		hello.pakeClientID = cred.PAKEClientID
		hello.pakeServerID = cred.PAKEServerID
		id := spakeID
		if cred.OverridePAKECodepoint != 0 {
			id = cred.OverridePAKECodepoint
		}
		hello.pakeShares = append(hello.pakeShares, pakeShare{id: id, msg: share})
		hello.hasKeyShares = false
		hello.keyShares = nil
	}

	possibleCipherSuites := c.config.cipherSuites()
	hello.cipherSuites = make([]uint16, 0, len(possibleCipherSuites))

	for _, suiteID := range possibleCipherSuites {
		suite := cipherSuiteFromID(suiteID)
		if suite == nil {
			continue
		}
		// Don't advertise TLS 1.2-only cipher suites unless
		// we're attempting TLS 1.2.
		if maxVersion < VersionTLS12 && suite.flags&suiteTLS12 != 0 {
			continue
		}
		hello.cipherSuites = append(hello.cipherSuites, suiteID)
	}

	if c.config.Bugs.AdvertiseAllConfiguredCiphers {
		hello.cipherSuites = possibleCipherSuites
	}

	if c.config.Bugs.SendRenegotiationSCSV {
		hello.cipherSuites = append(hello.cipherSuites, renegotiationSCSV)
	}

	if c.config.Bugs.SendFallbackSCSV {
		hello.cipherSuites = append(hello.cipherSuites, fallbackSCSV)
	}

	_, err := io.ReadFull(c.config.rand(), hello.random)
	if err != nil {
		c.sendAlert(alertInternalError)
		return nil, errors.New("tls: short read from Rand: " + err.Error())
	}

	if maxVersion >= VersionTLS12 && !c.config.Bugs.NoSignatureAlgorithms {
		hello.signatureAlgorithms = c.config.verifySignatureAlgorithms()
	}

	if c.config.ClientSessionCache != nil {
		hello.ticketSupported = !c.config.SessionTicketsDisabled
	}

	// ClientHelloOuter cannot offer sessions or PSKs.
	session := hs.session
	preSharedKeys := hs.preSharedKeys
	if innerHello != nil && !c.config.Bugs.OfferSessionInClientHelloOuter {
		session = nil
		preSharedKeys = nil
	}

	if session != nil && (session.vers.protocolVersion() < VersionTLS13 || c.config.Bugs.SendBothTickets) {
		if ticket := session.sessionTicket; ticket != nil {
			hello.sessionTicket = ticket
			// A random session ID is used to detect when the
			// server accepted the ticket and is resuming a session
			// (see RFC 5077).
			sessionIDLen := 16
			if c.config.Bugs.TicketSessionIDLength != 0 {
				sessionIDLen = c.config.Bugs.TicketSessionIDLength
			}
			if c.config.Bugs.EmptyTicketSessionID {
				sessionIDLen = 0
			}
			hello.sessionID = make([]byte, sessionIDLen)
			if _, err := io.ReadFull(c.config.rand(), hello.sessionID); err != nil {
				c.sendAlert(alertInternalError)
				return nil, errors.New("tls: short read from Rand: " + err.Error())
			}
		} else {
			hello.sessionID = session.sessionID
		}
	}

	for _, psk := range preSharedKeys {
		var ticketAge uint32
		if !psk.creationTime.IsZero() {
			ticketAge = uint32(c.config.time().Sub(psk.creationTime) / time.Millisecond)
		}
		if c.config.Bugs.SendTicketAge != 0 {
			ticketAge = uint32(c.config.Bugs.SendTicketAge / time.Millisecond)
		}
		psk := pskIdentity{
			ticket:              psk.identity,
			obfuscatedTicketAge: psk.ticketAgeAdd + ticketAge,
		}
		hello.pskIdentities = append(hello.pskIdentities, psk)
	}
	if len(hello.pskIdentities) != 0 && c.config.Bugs.ExtraPSKIdentity {
		hello.pskIdentities = append(hello.pskIdentities, hello.pskIdentities[0])
	}

	if innerHello == nil {
		// Request compatibility mode from the client by sending a fake session
		// ID. Although BoringSSL always enables compatibility mode, other
		// implementations make it conditional on the ClientHello. We test
		// BoringSSL's expected behavior with SendClientHelloSessionID.
		if len(hello.sessionID) == 0 && maxVersion >= VersionTLS13 {
			hello.sessionID = make([]byte, 32)
			if _, err := io.ReadFull(c.config.rand(), hello.sessionID); err != nil {
				c.sendAlert(alertInternalError)
				return nil, errors.New("tls: short read from Rand: " + err.Error())
			}
		}
		if c.config.Bugs.MockQUICTransport != nil && !c.config.Bugs.CompatModeWithQUIC {
			hello.sessionID = []byte{}
		}
		if c.config.Bugs.SendClientHelloSessionID != nil {
			hello.sessionID = c.config.Bugs.SendClientHelloSessionID
		}
	} else {
		// ClientHelloOuter's session ID is copied from ClientHelloINnner.
		hello.sessionID = innerHello.sessionID
	}

	if c.config.Bugs.SendCipherSuites != nil {
		hello.cipherSuites = c.config.Bugs.SendCipherSuites
	}

	if innerHello == nil {
		if len(hello.pskIdentities) > 0 && c.config.Bugs.SendEarlyData != nil {
			hello.hasEarlyData = true
		}
		if c.config.Bugs.SendFakeEarlyDataLength > 0 {
			hello.hasEarlyData = true
		}
		if c.config.Bugs.OmitEarlyDataExtension {
			hello.hasEarlyData = false
		}
	} else {
		hello.hasEarlyData = innerHello.hasEarlyData
	}

	if (isInner && !c.config.Bugs.OmitECHInner) || c.config.Bugs.AlwaysSendECHInner {
		hello.echInner = true
		hello.invalidECHInner = c.config.Bugs.SendInvalidECHInner
	}

	if innerHello != nil {
		if err := hs.encryptClientHello(hello, innerHello, c.config.ClientECHConfig.ConfigID, echEnc); err != nil {
			return nil, err
		}
		if c.config.Bugs.CorruptEncryptedClientHello {
			if c.config.Bugs.NullAllCiphers {
				hello.echOuter.payload = []byte{echBadPayloadByte}
			} else {
				hello.echOuter.payload[0] ^= 1
			}
		}
	}

	// PSK binders and ECH both must be computed last because they incorporate
	// the rest of the ClientHello and conflict. ECH resolves this by forbidding
	// clients from offering PSKs on ClientHelloOuter, but we still need to test
	// servers handle it correctly so they tolerate GREASE. In other cases, we
	// expect the server to reject ECH, so we put PSK last. Note this renders
	// ECH undecryptable.
	if len(hello.pskIdentities) > 0 {
		hs.generatePSKBinders(hello, nil, nil)
	}

	if c.config.Bugs.SendClientHelloWithFixes != nil {
		hello, err = replaceClientHello(hello, c.config.Bugs.SendClientHelloWithFixes)
		if err != nil {
			return nil, err
		}
	}

	return hello, nil
}

// encryptClientHello encrypts |innerHello| using the specified HPKE context and
// adds the extension to |hello|.
func (hs *clientHandshakeState) encryptClientHello(hello, innerHello *clientHelloMsg, configID uint8, enc []byte) error {
	c := hs.c

	if c.config.Bugs.MinimalClientHelloOuter {
		*hello = clientHelloMsg{
			isDTLS:             c.isDTLS,
			vers:               VersionTLS12,
			random:             hello.random,
			sessionID:          hello.sessionID,
			cipherSuites:       []uint16{0x0a0a},
			compressionMethods: hello.compressionMethods,
		}
		if c.isDTLS {
			hello.vers = VersionDTLS12
		}
	}

	if c.config.Bugs.TruncateClientECHEnc {
		enc = enc[:1]
	}

	encodedInner := innerHello.marshalForEncodedInner()
	padding := make([]byte, c.config.Bugs.ClientECHPadding)
	if c.config.Bugs.BadClientECHPadding {
		padding[0] = 1
	}
	encodedInner = append(encodedInner, padding...)

	// Encode ClientHelloOuter with a placeholder payload string.
	payloadLength := len(encodedInner)
	if !c.config.Bugs.NullAllCiphers {
		payloadLength += hs.echHPKEContext.Overhead()
	}
	hello.echOuter = &echClientOuter{
		kdfID:    hs.echHPKEContext.KDF(),
		aeadID:   hs.echHPKEContext.AEAD(),
		configID: configID,
		enc:      enc,
		payload:  make([]byte, payloadLength),
	}
	aad := hello.marshal()[4:] // Remove message header

	hello.raw = nil
	hello.echOuter.payload = hs.echHPKEContext.Seal(encodedInner, aad)
	if c.config.Bugs.NullAllCiphers {
		hello.echOuter.payload = encodedInner
	}

	if c.config.Bugs.RecordClientHelloInner != nil {
		if err := c.config.Bugs.RecordClientHelloInner(encodedInner, hello.marshal()[4:]); err != nil {
			return err
		}
		// ECH is normally the last extension added to |hello|, but, when
		// OfferSessionInClientHelloOuter is enabled, we may modify it again.
		hello.raw = nil
	}

	return nil
}

func (hs *clientHandshakeState) checkECHConfirmation(msg any, hello *clientHelloMsg, finishedHash *finishedHash) bool {
	var offset int
	var raw, label []byte
	if hrr, ok := msg.(*helloRetryRequestMsg); ok {
		if hrr.echConfirmationOffset == 0 {
			return false
		}
		raw = hrr.raw
		label = echAcceptConfirmationHRRLabel
		offset = hrr.echConfirmationOffset
	} else {
		raw = msg.(*serverHelloMsg).raw
		label = echAcceptConfirmationLabel
		offset = 4 + 2 + 32 - echAcceptConfirmationLength
	}

	withZeros := slices.Clone(raw)
	clear(withZeros[offset : offset+echAcceptConfirmationLength])

	confirmation := finishedHash.echAcceptConfirmation(hello.random, label, withZeros)
	return bytes.Equal(confirmation, raw[offset:offset+echAcceptConfirmationLength])
}

func (hs *clientHandshakeState) doTLS13Handshake(msg any) error {
	c := hs.c

	// The first message may be a ServerHello or HelloRetryRequest.
	helloRetryRequest, haveHelloRetryRequest := msg.(*helloRetryRequestMsg)
	if haveHelloRetryRequest {
		hs.finishedHash.UpdateForHelloRetryRequest()
	}

	// Determine whether the server accepted ECH and drop the unnecessary
	// transcript.
	if hs.innerHello != nil {
		innerFinishedHash := newFinishedHash(c.vers, hs.suite.hash())
		innerFinishedHash.WriteHandshake(hs.innerHello.marshal(), hs.c.sendHandshakeSeq-1)
		if haveHelloRetryRequest {
			innerFinishedHash.UpdateForHelloRetryRequest()
		}
		if hs.checkECHConfirmation(msg, hs.innerHello, &innerFinishedHash) {
			c.echAccepted = true
			// Replace the transcript. For now, leave hs.hello and hs.innerHello
			// as-is. HelloRetryRequest requires both be available.
			hs.finishedHash = innerFinishedHash
		}
	} else {
		// When not offering ECH, test that the backend server does not (or does)
		// send a confirmation as expected.
		confirmed := hs.checkECHConfirmation(msg, hs.hello, &hs.finishedHash)
		if hs.hello.echInner && !confirmed {
			return fmt.Errorf("tls: server did not send ECH confirmation in %T when requested", msg)
		} else if !hs.hello.echInner && confirmed {
			return fmt.Errorf("tls: server sent ECH confirmation in %T when not requested", msg)
		}
	}

	// Once the PRF hash is known, TLS 1.3 does not require a handshake buffer.
	hs.finishedHash.discardHandshakeBuffer()

	// The first server message must be followed by a ChangeCipherSpec.
	c.expectTLS13ChangeCipherSpec = !c.isDTLS

	expectedSessionID := hs.hello.sessionID
	if c.isDTLS {
		expectedSessionID = nil
	}
	if haveHelloRetryRequest {
		hs.writeServerHash(helloRetryRequest.marshal())

		if !bytes.Equal(expectedSessionID, helloRetryRequest.sessionID) {
			return errors.New("tls: ClientHello and HelloRetryRequest session IDs did not match.")
		}

		if c.config.Bugs.FailIfHelloRetryRequested {
			return errors.New("tls: unexpected HelloRetryRequest")
		}
		// Explicitly read the ChangeCipherSpec now; it should
		// be attached to the first flight, not the second flight.
		if err := c.readTLS13ChangeCipherSpec(); err != nil {
			return err
		}

		// Reset the encryption state, in case we sent 0-RTT data.
		c.out.resetCipher()

		if c.echAccepted {
			if err := hs.applyHelloRetryRequest(helloRetryRequest, hs.innerHello, hs.hello); err != nil {
				return err
			}
			hs.writeClientHash(hs.innerHello.marshal())
		} else {
			if err := hs.applyHelloRetryRequest(helloRetryRequest, hs.hello, nil); err != nil {
				return err
			}
			hs.writeClientHash(hs.hello.marshal())
		}
		toWrite := hs.hello.marshal()

		if c.config.Bugs.PartialSecondClientHelloAfterFirst {
			// The first byte has already been sent.
			toWrite = toWrite[1:]
		}

		if c.config.Bugs.InterleaveEarlyData {
			c.sendFakeEarlyData(4)
			c.writeRecord(recordTypeHandshake, toWrite[:16])
			c.sendFakeEarlyData(4)
			c.writeRecord(recordTypeHandshake, toWrite[16:])
		} else if c.config.Bugs.PartialClientFinishedWithSecondClientHello {
			toWrite = append(make([]byte, 0, len(toWrite)+1), toWrite...)
			toWrite = append(toWrite, typeFinished)
			c.writeRecord(recordTypeHandshake, toWrite)
		} else {
			c.writeRecord(recordTypeHandshake, toWrite)
		}
		if err := c.flushHandshake(); err != nil {
			return err
		}

		if c.config.Bugs.SendEarlyDataOnSecondClientHello {
			c.sendFakeEarlyData(4)
		}

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

	// We no longer need to retain two ClientHellos.
	if c.echAccepted {
		hs.hello = hs.innerHello
	}
	hs.innerHello = nil

	var ok bool
	hs.serverHello, ok = msg.(*serverHelloMsg)
	if !ok {
		c.sendAlert(alertUnexpectedMessage)
		return unexpectedMessageError(hs.serverHello, msg)
	}

	if isAllZero(hs.serverHello.random) {
		// If the server forgets to fill in the server random, it will
		// likely be all zero.
		return errors.New("tls: ServerHello random was all zero")
	}

	if c.vers.wire != hs.serverHello.vers {
		c.sendAlert(alertIllegalParameter)
		return fmt.Errorf("tls: server sent non-matching version %x vs %x", c.vers.wire, hs.serverHello.vers)
	}

	if hs.suite.id != hs.serverHello.cipherSuite {
		c.sendAlert(alertIllegalParameter)
		return fmt.Errorf("tls: server sent non-matching cipher suite %04x vs %04x", hs.suite.id, hs.serverHello.cipherSuite)
	}

	// ServerHello must be consistent with HelloRetryRequest, if any.
	if haveHelloRetryRequest {
		if helloRetryRequest.hasSelectedGroup && (!hs.serverHello.hasKeyShare || helloRetryRequest.selectedGroup != hs.serverHello.keyShare.group) {
			c.sendAlert(alertHandshakeFailure)
			return errors.New("tls: ServerHello parameters did not match HelloRetryRequest")
		}

		// Both the ServerHello and HelloRetryRequest must have an ECH confirmation.
		echConfirmed := hs.checkECHConfirmation(hs.serverHello, hs.hello, &hs.finishedHash)
		if hs.hello.echInner && !echConfirmed {
			return errors.New("tls: server did not send ECH confirmation in ServerHello when requested")
		} else if !hs.hello.echInner && echConfirmed {
			return errors.New("tls: server sent ECH confirmation in ServerHello when not requested")
		}
	}

	if !bytes.Equal(expectedSessionID, hs.serverHello.sessionID) {
		return errors.New("tls: ClientHello and ServerHello session IDs did not match.")
	}

	// Resolve PSK and compute the early secret.
	zeroSecret := hs.finishedHash.zeroSecret()
	var psk *preSharedKey
	if hs.serverHello.hasPSKIdentity {
		if int(hs.serverHello.pskIdentity) >= len(hs.preSharedKeys) {
			c.sendAlert(alertUnknownPSKIdentity)
			return errors.New("tls: server sent unknown PSK identity")
		}
		psk = hs.preSharedKeys[hs.serverHello.pskIdentity]
		if psk.version != c.vers {
			c.sendAlert(alertIllegalParameter)
			return errors.New("tls: server selected an invalid PSK for the protocol version")
		}
		if psk.hash != hs.suite.hash() {
			c.sendAlert(alertIllegalParameter)
			return errors.New("tls: server selected an invalid PSK for the cipher suite")
		}
		c.didResume = psk.clientSession != nil
		c.selectedPSK = psk.credential
		hs.finishedHash.addEntropy(psk.secret)
	} else {
		hs.finishedHash.addEntropy(zeroSecret)
	}

	sharedSecret := zeroSecret
	if len(hs.serverHello.pakeMessage) != 0 {
		if psk != nil {
			return errors.New("server selected PSK and PAKE at the same time")
		}
		if hs.pakeContext == nil {
			return errors.New("server selected a PAKE unexpectedly")
		}
		if hs.serverHello.pakeID != spakeID {
			return errors.New("server selected an unknown PAKE")
		}
		if expected := 65 + 32; len(hs.serverHello.pakeMessage) != expected {
			return fmt.Errorf("wrong length SPAKE2+ message, got %d, want %d", len(hs.serverHello.pakeMessage), expected)
		}
		if hs.serverHello.hasKeyShare || hs.serverHello.hasPSKIdentity {
			return errors.New("server included invalid extension with PAKE extension")
		}

		var err error
		if _, sharedSecret, err = hs.pakeContext.ComputeProverConfirmation(hs.serverHello.pakeMessage[:65], hs.serverHello.pakeMessage[65:]); err != nil {
			return fmt.Errorf("while computing SPAKE2+ confirmation: %w", err)
		}
	} else if hs.pakeContext != nil {
		return errors.New("server didn't respond with PAKE message")
	} else {
		if !hs.serverHello.hasKeyShare {
			c.sendAlert(alertUnsupportedExtension)
			return errors.New("tls: server omitted KeyShare on resumption.")
		}

		// Resolve ECDHE and compute the handshake secret.
		if !c.config.Bugs.MissingKeyShare && !c.config.Bugs.SecondClientHelloMissingKeyShare {
			kem, ok := hs.keyShares[hs.serverHello.keyShare.group]
			if !ok {
				c.sendAlert(alertHandshakeFailure)
				return errors.New("tls: server selected an unsupported group")
			}
			c.curveID = hs.serverHello.keyShare.group

			var err error
			sharedSecret, err = kem.decap(c.config, hs.serverHello.keyShare.keyExchange)
			if err != nil {
				return err
			}
		}
	}

	hs.finishedHash.nextSecret()
	hs.finishedHash.addEntropy(sharedSecret)
	hs.writeServerHash(hs.serverHello.marshal())

	// Derive handshake traffic keys and switch read key to handshake
	// traffic key.
	clientHandshakeTrafficSecret := hs.finishedHash.deriveSecret(clientHandshakeTrafficLabel)
	serverHandshakeTrafficSecret := hs.finishedHash.deriveSecret(serverHandshakeTrafficLabel)
	if err := c.useInTrafficSecret(uint16(encryptionHandshake), c.vers, hs.suite, serverHandshakeTrafficSecret); err != nil {
		return err
	}

	encryptedExtensions, err := readHandshakeType[encryptedExtensionsMsg](c)
	if err != nil {
		return err
	}
	hs.writeServerHash(encryptedExtensions.marshal())

	if !bytes.Equal(encryptedExtensions.extensions.echRetryConfigs, c.config.Bugs.ExpectECHRetryConfigs) {
		return errors.New("tls: server sent ECH retry_configs with unexpected contents")
	}

	err = hs.processServerExtensions(&encryptedExtensions.extensions)
	if err != nil {
		return err
	}

	err = hs.processServerExtensionsAfterResume(&encryptedExtensions.extensions, c.didResume)
	if err != nil {
		return err
	}

	var credential *Credential
	var certReq *certificateRequestMsg
	if c.didResume {
		// Copy over authentication from the session.
		c.peerCertificates = hs.session.serverCertificates
		c.sctList = hs.session.sctList
		c.ocspResponse = hs.session.ocspResponse
		c.peerRawPublicKey = hs.session.serverRawPublicKey
	} else if hs.pakeContext == nil && psk == nil {
		msg, err := c.readHandshake()
		if err != nil {
			return err
		}

		var ok bool
		certReq, ok = msg.(*certificateRequestMsg)
		if ok {
			if len(certReq.requestContext) != 0 {
				return errors.New("tls: non-empty certificate request context sent in handshake")
			}

			hs.writeServerHash(certReq.marshal())

			credential = c.config.Credential
			if credential != nil && c.config.Bugs.IgnorePeerSignatureAlgorithmPreferences {
				certReq.signatureAlgorithms = credential.signatureAlgorithms()
			}

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

		var certMsg *certificateMsg

		if compressedCertMsg, ok := msg.(*compressedCertificateMsg); ok {
			hs.writeServerHash(compressedCertMsg.marshal())

			alg, ok := c.config.CertCompressionAlgs[compressedCertMsg.algID]
			if !ok {
				c.sendAlert(alertBadCertificate)
				return fmt.Errorf("tls: received certificate compressed with unknown algorithm %x", compressedCertMsg.algID)
			}

			decompressed := make([]byte, 4+int(compressedCertMsg.uncompressedLength))
			if !alg.Decompress(decompressed[4:], compressedCertMsg.compressed) {
				c.sendAlert(alertBadCertificate)
				return fmt.Errorf("tls: failed to decompress certificate with algorithm %x", compressedCertMsg.algID)
			}

			certMsg = &certificateMsg{
				hasRequestContext:          true,
				extensionsWithTrailingData: c.config.Bugs.ExtensionsWithTrailingData,
			}

			if !certMsg.unmarshal(decompressed) {
				c.sendAlert(alertBadCertificate)
				return errors.New("tls: failed to parse decompressed certificate")
			}

			if expected := c.config.Bugs.ExpectedCompressedCert; expected != 0 && expected != compressedCertMsg.algID {
				return fmt.Errorf("tls: expected certificate compressed with algorithm %x, but message used %x", expected, compressedCertMsg.algID)
			}

			if c.config.Bugs.ExpectUncompressedCert {
				return errors.New("tls: compressed certificate received")
			}
		} else {
			if certMsg, ok = msg.(*certificateMsg); !ok {
				c.sendAlert(alertUnexpectedMessage)
				return unexpectedMessageError(certMsg, msg)
			}
			hs.writeServerHash(certMsg.marshal())

			if c.config.Bugs.ExpectedCompressedCert != 0 {
				return errors.New("tls: uncompressed certificate received")
			}
		}

		// Check for unsolicited extensions.
		for i, cert := range certMsg.certificates {
			if c.config.Bugs.NoOCSPStapling && cert.ocspResponse != nil {
				c.sendAlert(alertUnsupportedExtension)
				return errors.New("tls: unexpected OCSP response in the server certificate")
			}
			if c.config.Bugs.NoSignedCertificateTimestamps && cert.sctList != nil {
				c.sendAlert(alertUnsupportedExtension)
				return errors.New("tls: unexpected SCT list in the server certificate")
			}
			if i > 0 && c.config.Bugs.ExpectNoExtensionsOnIntermediate && (cert.ocspResponse != nil || cert.sctList != nil) {
				c.sendAlert(alertUnsupportedExtension)
				return errors.New("tls: unexpected extensions in the server certificate")
			}
		}
		if c.config.RequestTrustAnchors == nil && certMsg.matchedTrustAnchor {
			return errors.New("tls: unsolicited trust_anchors extension in the server certificate")
		}
		if expected := c.config.Bugs.ExpectPeerMatchTrustAnchor; expected != nil && certMsg.matchedTrustAnchor != *expected {
			if certMsg.matchedTrustAnchor {
				return errors.New("tls: server certificate unexpectedly matched trust anchor")
			}
			return errors.New("tls: server certificate unexpectedly did not match trust anchor")
		}

		if err := hs.verifyCertificates(certMsg); err != nil {
			return err
		}
		c.ocspResponse = certMsg.certificates[0].ocspResponse
		c.sctList = certMsg.certificates[0].sctList

		certVerifyMsg, err := readHandshakeType[certificateVerifyMsg](c)
		if err != nil {
			return err
		}

		c.peerSignatureAlgorithm = certVerifyMsg.signatureAlgorithm
		input := hs.finishedHash.certificateVerifyInput(serverCertificateVerifyContextTLS13)
		if c.peerDelegatedCredential != nil {
			err = verifyMessageDC(c.isClient, c.vers, hs.peerPublicKey, c.config, certVerifyMsg.signatureAlgorithm, input, certVerifyMsg.signature)
		} else {
			err = verifyMessage(c.isClient, c.vers, hs.peerPublicKey, c.config, certVerifyMsg.signatureAlgorithm, input, certVerifyMsg.signature)
		}
		if err != nil {
			return err
		}

		hs.writeServerHash(certVerifyMsg.marshal())
	}

	serverFinished, err := readHandshakeType[finishedMsg](c)
	if err != nil {
		return err
	}
	verify := hs.finishedHash.serverSum(serverHandshakeTrafficSecret)
	if len(verify) != len(serverFinished.verifyData) ||
		subtle.ConstantTimeCompare(verify, serverFinished.verifyData) != 1 {
		c.sendAlert(alertHandshakeFailure)
		return errors.New("tls: server's Finished message was incorrect")
	}

	hs.writeServerHash(serverFinished.marshal())

	// The various secrets do not incorporate the client's final leg, so
	// derive them now before updating the handshake context.
	hs.finishedHash.nextSecret()
	hs.finishedHash.addEntropy(zeroSecret)

	clientTrafficSecret := hs.finishedHash.deriveSecret(clientApplicationTrafficLabel)
	serverTrafficSecret := hs.finishedHash.deriveSecret(serverApplicationTrafficLabel)
	c.exporterSecret = hs.finishedHash.deriveSecret(exporterLabel)

	// Switch to application data keys on read. In particular, any alerts
	// from the client certificate are read over these keys.
	if err := c.useInTrafficSecret(uint16(encryptionApplication), c.vers, hs.suite, serverTrafficSecret); err != nil {
		return err
	}

	// If we're expecting 0.5-RTT messages from the server, read them now.
	var deferredTickets []*newSessionTicketMsg
	if encryptedExtensions.extensions.hasEarlyData {
		// BoringSSL will always send two tickets half-RTT when
		// negotiating 0-RTT.
		for i := 0; i < shimConfig.HalfRTTTickets; i++ {
			newSessionTicket, err := readHandshakeType[newSessionTicketMsg](c)
			if err != nil {
				return fmt.Errorf("tls: error reading half-RTT ticket: %s", err)
			}
			// Defer processing until the resumption secret is computed.
			deferredTickets = append(deferredTickets, newSessionTicket)
		}
		for _, expectedMsg := range c.config.Bugs.ExpectHalfRTTData {
			if err := c.readRecord(recordTypeApplicationData); err != nil {
				return err
			}
			if !bytes.Equal(c.input.Bytes(), expectedMsg) {
				return fmt.Errorf("tls: got half-RTT data record %x, wanted %x", c.input.Bytes(), expectedMsg)
			}
			c.input.Reset()
		}
	}

	// Send EndOfEarlyData and then switch write key to handshake
	// traffic key.
	if encryptedExtensions.extensions.hasEarlyData && !c.config.Bugs.SkipEndOfEarlyData && c.usesEndOfEarlyData() {
		if c.config.Bugs.SendStrayEarlyHandshake {
			helloRequest := new(helloRequestMsg)
			c.writeRecord(recordTypeHandshake, helloRequest.marshal())
		}
		endOfEarlyData := new(endOfEarlyDataMsg)
		endOfEarlyData.nonEmpty = c.config.Bugs.NonEmptyEndOfEarlyData
		hs.writeClientHash(endOfEarlyData.marshal())
		if c.config.Bugs.PartialEndOfEarlyDataWithClientHello {
			// The first byte has already been sent.
			c.writeRecord(recordTypeHandshake, endOfEarlyData.marshal()[1:])
		} else {
			c.writeRecord(recordTypeHandshake, endOfEarlyData.marshal())
		}
	}

	if !c.config.Bugs.SkipChangeCipherSpec && !hs.hello.hasEarlyData && !c.isDTLS {
		c.writeRecord(recordTypeChangeCipherSpec, []byte{1})
	}

	for i := 0; i < c.config.Bugs.SendExtraChangeCipherSpec; i++ {
		c.writeRecord(recordTypeChangeCipherSpec, []byte{1})
	}

	c.useOutTrafficSecret(uint16(encryptionHandshake), c.vers, hs.suite, clientHandshakeTrafficSecret)

	// The client EncryptedExtensions message is sent if some extension uses it.
	// (Currently only ALPS does.)
	hasEncryptedExtensions := c.config.Bugs.AlwaysSendClientEncryptedExtensions
	clientEncryptedExtensions := new(clientEncryptedExtensionsMsg)
	if encryptedExtensions.extensions.hasApplicationSettings || (c.config.Bugs.SendApplicationSettingsWithEarlyData && c.hasApplicationSettings) {
		hasEncryptedExtensions = true
		if !c.config.Bugs.OmitClientApplicationSettings {
			clientEncryptedExtensions.hasApplicationSettings = true
			clientEncryptedExtensions.applicationSettings = c.localApplicationSettings
		}
	}
	if encryptedExtensions.extensions.hasApplicationSettingsOld || (c.config.Bugs.SendApplicationSettingsWithEarlyData && c.hasApplicationSettingsOld) {
		hasEncryptedExtensions = true
		if !c.config.Bugs.OmitClientApplicationSettings {
			clientEncryptedExtensions.hasApplicationSettingsOld = true
			clientEncryptedExtensions.applicationSettingsOld = c.localApplicationSettingsOld
		}
	}
	if c.config.Bugs.SendExtraClientEncryptedExtension {
		hasEncryptedExtensions = true
		clientEncryptedExtensions.customExtension = []byte{0}
	}
	if hasEncryptedExtensions && !c.config.Bugs.OmitClientEncryptedExtensions {
		hs.writeClientHash(clientEncryptedExtensions.marshal())
		c.writeRecord(recordTypeHandshake, clientEncryptedExtensions.marshal())
	}

	if certReq != nil && !c.config.Bugs.SkipClientCertificate {
		certMsg := &certificateMsg{
			hasRequestContext: true,
			requestContext:    certReq.requestContext,
		}
		if credential != nil {
			certMsg.certificateType = credential.Type.CertificateType()
			if !c.config.Bugs.EmptyCertificateList {
				for _, certData := range credential.Certificate {
					certMsg.certificates = append(certMsg.certificates, certificateEntry{
						data:           certData,
						extraExtension: c.config.Bugs.SendExtensionOnCertificate,
					})
				}
			}
		}
		hs.writeClientHash(certMsg.marshal())
		c.writeRecord(recordTypeHandshake, certMsg.marshal())

		if credential != nil {
			certVerify := &certificateVerifyMsg{
				hasSignatureAlgorithm: true,
			}

			// Determine the hash to sign.
			var err error
			certVerify.signatureAlgorithm, err = selectSignatureAlgorithm(c.isClient, c.vers, credential, c.config, certReq.signatureAlgorithms)
			if err != nil {
				c.sendAlert(alertInternalError)
				return err
			}

			privKey := credential.PrivateKey
			input := hs.finishedHash.certificateVerifyInput(clientCertificateVerifyContextTLS13)
			certVerify.signature, err = signMessage(c.isClient, c.vers, privKey, c.config, certVerify.signatureAlgorithm, input)
			if err != nil {
				c.sendAlert(alertInternalError)
				return err
			}
			if c.config.Bugs.SendSignatureAlgorithm != 0 {
				certVerify.signatureAlgorithm = c.config.Bugs.SendSignatureAlgorithm
			}

			if !c.config.Bugs.SkipCertificateVerify {
				hs.writeClientHash(certVerify.marshal())
				c.writeRecord(recordTypeHandshake, certVerify.marshal())
			}
		}
	}

	if encryptedExtensions.extensions.channelIDRequested {
		channelIDHash := crypto.SHA256.New()
		channelIDHash.Write(hs.finishedHash.certificateVerifyInput(channelIDContextTLS13))
		channelIDMsgBytes, err := hs.writeChannelIDMessage(channelIDHash.Sum(nil))
		if err != nil {
			return err
		}
		hs.writeClientHash(channelIDMsgBytes)
		c.writeRecord(recordTypeHandshake, channelIDMsgBytes)
	}

	// Send a client Finished message.
	finished := new(finishedMsg)
	finished.verifyData = hs.finishedHash.clientSum(clientHandshakeTrafficSecret)
	if c.config.Bugs.BadFinished {
		finished.verifyData[0]++
	}
	hs.writeClientHash(finished.marshal())
	if c.config.Bugs.PartialClientFinishedWithClientHello {
		// The first byte has already been sent.
		c.writeRecord(recordTypeHandshake, finished.marshal()[1:])
	} else if c.config.Bugs.InterleaveEarlyData {
		finishedBytes := finished.marshal()
		c.sendFakeEarlyData(4)
		c.writeRecord(recordTypeHandshake, finishedBytes[:1])
		c.sendFakeEarlyData(4)
		c.writeRecord(recordTypeHandshake, finishedBytes[1:])
	} else {
		c.writeRecord(recordTypeHandshake, finished.marshal())
	}
	if c.config.Bugs.SendExtraFinished {
		c.writeRecord(recordTypeHandshake, finished.marshal())
	}

	if data := c.config.Bugs.AppDataBeforeTLS13KeyChange; data != nil {
		c.writeRecord(recordTypeApplicationData, data)
	}

	// Switch to application data keys.
	c.useOutTrafficSecret(uint16(encryptionApplication), c.vers, hs.suite, clientTrafficSecret)
	c.resumptionSecret = hs.finishedHash.deriveSecret(resumptionLabel)

	if err := c.flushHandshake(); err != nil {
		return err
	}
	if c.isDTLS && len(c.expectedACK) != 0 && !c.config.Bugs.SkipImplicitACKRead {
		if err := c.readRecord(recordTypeACK); err != nil {
			return err
		}
	}

	for _, ticket := range deferredTickets {
		if err := c.processTLS13NewSessionTicket(ticket, hs.suite); err != nil {
			return err
		}
	}

	return nil
}

// applyHelloRetryRequest updates |hello| in-place based on |helloRetryRequest|.
// If |outerHello| is not nil, |outerHello| will be updated to contain an
// encrypted copy of |hello|.
func (hs *clientHandshakeState) applyHelloRetryRequest(helloRetryRequest *helloRetryRequestMsg, hello, outerHello *clientHelloMsg) error {
	c := hs.c
	firstHelloBytes := hello.marshal()
	if len(helloRetryRequest.cookie) > 0 {
		hello.tls13Cookie = helloRetryRequest.cookie
	}

	if c.config.Bugs.MisinterpretHelloRetryRequestCurve != 0 {
		helloRetryRequest.hasSelectedGroup = true
		helloRetryRequest.selectedGroup = c.config.Bugs.MisinterpretHelloRetryRequestCurve
	}
	if helloRetryRequest.hasSelectedGroup {
		group := helloRetryRequest.selectedGroup
		if !slices.Contains(hello.supportedCurves, group) || hs.keyShares[group] != nil {
			c.sendAlert(alertHandshakeFailure)
			return errors.New("tls: received invalid HelloRetryRequest")
		}
		kem, ok := kemForCurveID(group, c.config)
		if !ok {
			return errors.New("tls: Unable to get curve requested in HelloRetryRequest")
		}
		publicKey, err := kem.generate(c.config)
		if err != nil {
			return err
		}
		hs.keyShares[group] = kem
		hello.keyShares = []keyShareEntry{{
			group:       group,
			keyExchange: publicKey,
		}}
	}

	if c.config.Bugs.SecondClientHelloMissingKeyShare {
		hello.hasKeyShares = false
	}

	if c.config.Bugs.OmitSecondECHInner {
		hello.echInner = false
	}

	hello.hasEarlyData = c.config.Bugs.SendEarlyDataOnSecondClientHello
	// The first ClientHello may have skipped this due to OnlyCorruptSecondPSKBinder.
	if c.config.Bugs.PSKBinderFirst && c.config.Bugs.OnlyCorruptSecondPSKBinder {
		hello.prefixExtensions = append(hello.prefixExtensions, extensionPreSharedKey)
	}
	// The first ClientHello may have set this due to OnlyCompressSecondClientHelloInner.
	hello.reorderOuterExtensionsWithoutCompressing = false
	hello.pskIdentities = hello.pskIdentities[c.config.Bugs.OmitPSKsOnSecondClientHello:]
	hs.preSharedKeys = hs.preSharedKeys[c.config.Bugs.OmitPSKsOnSecondClientHello:]
	if c.config.Bugs.OmitAllPSKsOnSecondClientHello {
		hello.pskIdentities = nil
		hs.preSharedKeys = nil
	}
	hello.raw = nil

	if len(hello.pskIdentities) > 0 {
		hs.generatePSKBinders(hello, firstHelloBytes, helloRetryRequest.marshal())
	} else {
		hello.pskBinders = nil
	}

	if outerHello != nil {
		outerHello.raw = nil
		// We know the server has accepted ECH, so the ClientHelloOuter's fields
		// are irrelevant. In the general case, the HelloRetryRequest may not
		// even be valid for ClientHelloOuter. However, we copy the key shares
		// from ClientHelloInner so they remain eligible for compression.
		if !c.config.Bugs.MinimalClientHelloOuter {
			outerHello.keyShares = hello.keyShares
		}

		if c.config.Bugs.OmitSecondEncryptedClientHello {
			outerHello.echOuter = nil
		} else {
			configID := c.config.ClientECHConfig.ConfigID
			if c.config.Bugs.CorruptSecondEncryptedClientHelloConfigID {
				configID ^= 1
			}
			if err := hs.encryptClientHello(outerHello, hello, configID, nil); err != nil {
				return err
			}
			if c.config.Bugs.CorruptSecondEncryptedClientHello {
				if c.config.Bugs.NullAllCiphers {
					outerHello.echOuter.payload = []byte{echBadPayloadByte}
				} else {
					outerHello.echOuter.payload[0] ^= 1
				}
			}
		}
	}

	return nil
}

func (hs *clientHandshakeState) doFullHandshake() error {
	c := hs.c

	if hs.suite.flags&suitePSK == 0 {
		certMsg, err := readHandshakeType[certificateMsg](c)
		if err != nil {
			return err
		}
		hs.writeServerHash(certMsg.marshal())

		if err := hs.verifyCertificates(certMsg); err != nil {
			return err
		}
	}

	if hs.serverHello.extensions.ocspStapling {
		cs, err := readHandshakeType[certificateStatusMsg](c)
		if err != nil {
			return err
		}
		hs.writeServerHash(cs.marshal())

		if cs.statusType == statusTypeOCSP {
			c.ocspResponse = cs.response
		}
	}

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

	keyAgreement := hs.suite.ka(c.vers)

	skx, ok := msg.(*serverKeyExchangeMsg)
	if ok {
		hs.writeServerHash(skx.marshal())
		err = keyAgreement.processServerKeyExchange(c.config, hs.hello, hs.serverHello, hs.peerPublicKey, skx)
		if err != nil {
			c.sendAlert(alertUnexpectedMessage)
			return err
		}
		if ecdhe, ok := keyAgreement.(*ecdheKeyAgreement); ok {
			c.curveID = ecdhe.curveID
		}

		c.peerSignatureAlgorithm = keyAgreement.peerSignatureAlgorithm()

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

	var credential *Credential
	var certRequested bool
	certReq, ok := msg.(*certificateRequestMsg)
	if ok {
		certRequested = true
		hs.writeServerHash(certReq.marshal())

		credential = c.config.Credential
		if credential != nil && c.config.Bugs.IgnorePeerSignatureAlgorithmPreferences {
			certReq.signatureAlgorithms = credential.signatureAlgorithms()
		}

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

	shd, ok := msg.(*serverHelloDoneMsg)
	if !ok {
		c.sendAlert(alertUnexpectedMessage)
		return unexpectedMessageError(shd, msg)
	}
	hs.writeServerHash(shd.marshal())

	// If the server requested a certificate then we have to send a
	// Certificate message in TLS, even if it's empty because we don't have
	// a certificate to send.
	if certRequested && !c.config.Bugs.SkipClientCertificate {
		certMsg := new(certificateMsg)
		if credential != nil {
			certMsg.certificateType = credential.Type.CertificateType()
			if !c.config.Bugs.EmptyCertificateList {
				for _, certData := range credential.Certificate {
					certMsg.certificates = append(certMsg.certificates, certificateEntry{
						data: certData,
					})
				}
			}
		}
		hs.writeClientHash(certMsg.marshal())
		c.writeRecord(recordTypeHandshake, certMsg.marshal())
	}

	preMasterSecret, ckx, err := keyAgreement.generateClientKeyExchange(c.config, hs.hello, hs.peerPublicKey)
	if err != nil {
		c.sendAlert(alertInternalError)
		return err
	}
	if ckx != nil {
		if c.config.Bugs.EarlyChangeCipherSpec < 2 {
			hs.writeClientHash(ckx.marshal())
		}
		if c.config.Bugs.PartialClientKeyExchangeWithClientHello {
			// The first byte was already written.
			c.writeRecord(recordTypeHandshake, ckx.marshal()[1:])
		} else {
			c.writeRecord(recordTypeHandshake, ckx.marshal())
		}
	}

	if hs.serverHello.extensions.extendedMasterSecret {
		hs.masterSecret = extendedMasterFromPreMasterSecret(c.vers, hs.suite, preMasterSecret, hs.finishedHash)
		c.extendedMasterSecret = true
	} else {
		if c.config.Bugs.RequireExtendedMasterSecret {
			return errors.New("tls: extended master secret required but not supported by peer")
		}
		hs.masterSecret = masterFromPreMasterSecret(c.vers, hs.suite, preMasterSecret, hs.hello.random, hs.serverHello.random)
	}

	if credential != nil {
		certVerify := &certificateVerifyMsg{
			hasSignatureAlgorithm: c.vers.protocolVersion() >= VersionTLS12,
		}

		// Determine the hash to sign.
		if certVerify.hasSignatureAlgorithm {
			certVerify.signatureAlgorithm, err = selectSignatureAlgorithm(c.isClient, c.vers, credential, c.config, certReq.signatureAlgorithms)
			if err != nil {
				c.sendAlert(alertInternalError)
				return err
			}
		}

		privKey := c.config.Credential.PrivateKey
		certVerify.signature, err = signMessage(c.isClient, c.vers, privKey, c.config, certVerify.signatureAlgorithm, hs.finishedHash.buffer)
		if err == nil && c.config.Bugs.SendSignatureAlgorithm != 0 {
			certVerify.signatureAlgorithm = c.config.Bugs.SendSignatureAlgorithm
		}
		if err != nil {
			c.sendAlert(alertInternalError)
			return errors.New("tls: failed to sign handshake with client certificate: " + err.Error())
		}

		if !c.config.Bugs.SkipCertificateVerify {
			hs.writeClientHash(certVerify.marshal())
			c.writeRecord(recordTypeHandshake, certVerify.marshal())
		}
	}
	// flushHandshake will be called in sendFinished.

	hs.finishedHash.discardHandshakeBuffer()

	return nil
}

// delegatedCredentialSignedMessage returns the bytes that are signed in order
// to authenticate a delegated credential.
func delegatedCredentialSignedMessage(credBytes []byte, algorithm signatureAlgorithm, leafDER []byte) []byte {
	// https://www.rfc-editor.org/rfc/rfc9345.html#section-4
	ret := make([]byte, 64, 128)
	for i := range ret {
		ret[i] = 0x20
	}

	ret = append(ret, []byte("TLS, server delegated credentials\x00")...)
	ret = append(ret, leafDER...)
	ret = append(ret, byte(algorithm>>8), byte(algorithm))
	ret = append(ret, credBytes...)

	return ret
}

func (hs *clientHandshakeState) verifyCertificates(certMsg *certificateMsg) error {
	c := hs.c

	if len(certMsg.certificates) == 0 {
		c.sendAlert(alertIllegalParameter)
		return errors.New("tls: no certificates sent")
	}

	// Parse the subjectPublicKeyInfo struct for RawPublicKey cert type.
	var peerPublicKey crypto.PublicKey
	if certMsg.certificateType == certTypeRawPublicKey {
		rpkData := certMsg.certificates[0].data
		c.peerRawPublicKey = rpkData
		var err error
		peerPublicKey, err = x509.ParsePKIXPublicKey(rpkData)
		if err != nil {
			c.sendAlert(alertBadCertificate)
			return errors.New("tls: failed to parse public key from raw public key: " + err.Error())
		}

		if len(certMsg.certificates) > 1 {
			c.sendAlert(alertIllegalParameter)
			return errors.New("tls: server sent too many certificates for RawPublicKey cert type")
		}

		if len(certMsg.certificates[0].ocspResponse) != 0 ||
			len(certMsg.certificates[0].sctList) != 0 ||
			certMsg.certificates[0].delegatedCredential != nil {
			c.sendAlert(alertBadCertificate)
			return errors.New("tls: server sent unexpected extension with raw public key")
		}
	}

	// Parse and verify X.509 certificates.
	var dc *delegatedCredential
	certs := make([]*x509.Certificate, len(certMsg.certificates))
	if certMsg.certificateType == certTypeX509 {
		for i, certEntry := range certMsg.certificates {
			cert, err := ParseX509Certificate(certEntry.data)
			if err != nil {
				c.sendAlert(alertBadCertificate)
				return errors.New("tls: failed to parse certificate from server: " + err.Error())
			}
			certs[i] = cert

			if certEntry.delegatedCredential != nil {
				if i != 0 {
					c.sendAlert(alertIllegalParameter)
					return errors.New("tls: non-leaf certificate has a delegated credential")
				}
				if len(c.config.DelegatedCredentialAlgorithms) == 0 {
					c.sendAlert(alertIllegalParameter)
					return errors.New("tls: server sent delegated credential without it being requested")
				}
				dc = certEntry.delegatedCredential
			}
		}

		if !c.config.InsecureSkipVerify {
			opts := x509.VerifyOptions{
				Roots:         c.config.RootCAs,
				CurrentTime:   c.config.time(),
				DNSName:       c.config.ServerName,
				Intermediates: x509.NewCertPool(),
			}

			for i, cert := range certs {
				if i == 0 {
					continue
				}
				opts.Intermediates.AddCert(cert)
			}
			var err error
			c.verifiedChains, err = certs[0].Verify(opts)
			if err != nil {
				c.sendAlert(alertBadCertificate)
				return err
			}
		}

		peerPublicKey = certs[0].PublicKey
		c.peerCertificates = certs
	}

	switch peerPublicKey.(type) {
	case *rsa.PublicKey, *ecdsa.PublicKey, ed25519.PublicKey, *mldsa.PublicKey:
		break
	default:
		c.sendAlert(alertUnsupportedCertificate)
		return fmt.Errorf("tls: server's certificate contains an unsupported type of public key: %T", peerPublicKey)
	}

	if dc != nil {
		// Note that this doesn't check a) the delegated credential temporal
		// validity nor b) that the certificate has the special OID asserted.
		var err error
		if hs.peerPublicKey, err = x509.ParsePKIXPublicKey(dc.pkixPublicKey); err != nil {
			c.sendAlert(alertBadCertificate)
			return errors.New("tls: failed to parse public key from delegated credential: " + err.Error())
		}

		signedMsg := delegatedCredentialSignedMessage(dc.signedBytes, dc.algorithm, certs[0].Raw)
		if err := verifyMessage(c.isClient, c.vers, peerPublicKey, c.config, dc.algorithm, signedMsg, dc.signature); err != nil {
			c.sendAlert(alertBadCertificate)
			return errors.New("tls: failed to verify delegated credential: " + err.Error())
		}
		c.peerDelegatedCredential = dc.raw
	} else {
		hs.peerPublicKey = peerPublicKey
	}

	return nil
}

func (hs *clientHandshakeState) establishKeys() error {
	c := hs.c

	clientMAC, serverMAC, clientKey, serverKey, clientIV, serverIV := keysFromMasterSecret(c.vers, hs.suite, hs.masterSecret, hs.hello.random, hs.serverHello.random, hs.suite.macLen, hs.suite.keyLen, hs.suite.ivLen(c.vers))
	var clientCipher, serverCipher any
	var clientHash, serverHash macFunction
	if hs.suite.cipher != nil {
		clientCipher = hs.suite.cipher(clientKey, clientIV, false /* not for reading */)
		clientHash = hs.suite.mac(c.vers, clientMAC)
		serverCipher = hs.suite.cipher(serverKey, serverIV, true /* for reading */)
		serverHash = hs.suite.mac(c.vers, serverMAC)
	} else {
		clientCipher = hs.suite.aead(c.vers, clientKey, clientIV)
		serverCipher = hs.suite.aead(c.vers, serverKey, serverIV)
	}

	c.in.prepareCipherSpec(c.vers, serverCipher, serverHash)
	c.out.prepareCipherSpec(c.vers, clientCipher, clientHash)
	return nil
}

func (hs *clientHandshakeState) processServerExtensions(serverExtensions *serverExtensions) error {
	c := hs.c

	if c.vers.protocolVersion() < VersionTLS13 {
		if c.config.Bugs.RequireRenegotiationInfo && serverExtensions.secureRenegotiation == nil {
			return errors.New("tls: renegotiation extension missing")
		}

		if len(c.clientVerify) > 0 && !c.noRenegotiationInfo() {
			var expectedRenegInfo []byte
			expectedRenegInfo = append(expectedRenegInfo, c.clientVerify...)
			expectedRenegInfo = append(expectedRenegInfo, c.serverVerify...)
			if !bytes.Equal(serverExtensions.secureRenegotiation, expectedRenegInfo) {
				c.sendAlert(alertHandshakeFailure)
				return fmt.Errorf("tls: renegotiation mismatch")
			}
		}
	} else if serverExtensions.secureRenegotiation != nil {
		return errors.New("tls: renegotiation info sent in TLS 1.3")
	}

	if expected := c.config.Bugs.ExpectedCustomExtension; expected != nil {
		if serverExtensions.customExtension != *expected {
			return fmt.Errorf("tls: bad custom extension contents %q", serverExtensions.customExtension)
		}
	}

	clientDidNPN := hs.hello.nextProtoNeg
	clientDidALPN := len(hs.hello.alpnProtocols) > 0
	serverHasNPN := serverExtensions.nextProtoNeg
	serverHasALPN := len(serverExtensions.alpnProtocol) > 0

	if !clientDidNPN && serverHasNPN {
		c.sendAlert(alertHandshakeFailure)
		return errors.New("server advertised unrequested NPN extension")
	}

	if !clientDidALPN && serverHasALPN {
		c.sendAlert(alertHandshakeFailure)
		return errors.New("server advertised unrequested ALPN extension")
	}

	if serverHasNPN && serverHasALPN {
		c.sendAlert(alertHandshakeFailure)
		return errors.New("server advertised both NPN and ALPN extensions")
	}

	if serverHasALPN {
		c.clientProtocol = serverExtensions.alpnProtocol
		c.clientProtocolFallback = false
		c.usedALPN = true
	}

	if serverHasNPN && c.vers.protocolVersion() >= VersionTLS13 {
		c.sendAlert(alertHandshakeFailure)
		return errors.New("server advertised NPN over TLS 1.3")
	}

	if !hs.hello.channelIDSupported && serverExtensions.channelIDRequested {
		c.sendAlert(alertHandshakeFailure)
		return errors.New("server advertised unrequested Channel ID extension")
	}

	if serverExtensions.extendedMasterSecret && c.vers.protocolVersion() >= VersionTLS13 {
		return errors.New("tls: server advertised extended master secret over TLS 1.3")
	}

	if serverExtensions.ticketSupported && c.vers.protocolVersion() >= VersionTLS13 {
		return errors.New("tls: server advertised ticket extension over TLS 1.3")
	}

	if serverExtensions.ocspStapling && c.vers.protocolVersion() >= VersionTLS13 {
		return errors.New("tls: server advertised OCSP in ServerHello over TLS 1.3")
	}

	if serverExtensions.ocspStapling && c.config.Bugs.NoOCSPStapling {
		return errors.New("tls: server advertised unrequested OCSP extension")
	}

	if len(serverExtensions.sctList) > 0 && c.vers.protocolVersion() >= VersionTLS13 {
		return errors.New("tls: server advertised SCTs in ServerHello over TLS 1.3")
	}

	if len(serverExtensions.sctList) > 0 && c.config.Bugs.NoSignedCertificateTimestamps {
		return errors.New("tls: server advertised unrequested SCTs")
	}

	if len(serverExtensions.trustAnchors) > 0 && c.config.RequestTrustAnchors == nil {
		return errors.New("tls: server advertised unrequested trust anchor IDs")
	}
	if expected := c.config.Bugs.ExpectPeerAvailableTrustAnchors; expected != nil && !slices.EqualFunc(expected, serverExtensions.trustAnchors, slices.Equal) {
		return errors.New("tls: server advertised trust anchor IDs that did not match expectations")
	}

	if serverExtensions.serverNameAck {
		if len(hs.hello.serverName) == 0 {
			return errors.New("tls: server acknowledged server_name, but client did not send it")
		}
		if c.didResume {
			return errors.New("tls: server acknowledged server_name when resuming")
		}
		c.serverNameAck = serverExtensions.serverNameAck
	}

	if serverExtensions.srtpProtectionProfile != 0 {
		if serverExtensions.srtpMasterKeyIdentifier != "" {
			return errors.New("tls: server selected SRTP MKI value")
		}

		if !slices.Contains(c.config.SRTPProtectionProfiles, serverExtensions.srtpProtectionProfile) {
			return errors.New("tls: server advertised unsupported SRTP profile")
		}

		c.srtpProtectionProfile = serverExtensions.srtpProtectionProfile
	}

	if c.vers.protocolVersion() >= VersionTLS13 && c.didResume {
		if c.config.Bugs.ExpectEarlyDataAccepted && !serverExtensions.hasEarlyData {
			c.sendAlert(alertHandshakeFailure)
			return errors.New("tls: server did not accept early data when expected")
		}

		if !c.config.Bugs.ExpectEarlyDataAccepted && serverExtensions.hasEarlyData {
			c.sendAlert(alertHandshakeFailure)
			return errors.New("tls: server accepted early data when not expected")
		}
	} else if serverExtensions.hasEarlyData {
		return errors.New("tls: server accepted early data when not resuming")
	}

	if len(serverExtensions.quicTransportParams) > 0 {
		if c.vers.protocolVersion() < VersionTLS13 {
			c.sendAlert(alertHandshakeFailure)
			return errors.New("tls: server sent QUIC transport params for TLS version less than 1.3")
		}
		c.quicTransportParams = serverExtensions.quicTransportParams
	}

	if len(serverExtensions.quicTransportParamsLegacy) > 0 {
		if c.vers.protocolVersion() < VersionTLS13 {
			c.sendAlert(alertHandshakeFailure)
			return errors.New("tls: server sent QUIC transport params for TLS version less than 1.3")
		}
		c.quicTransportParamsLegacy = serverExtensions.quicTransportParamsLegacy
	}

	if serverExtensions.hasApplicationSettings && serverExtensions.hasApplicationSettingsOld {
		return errors.New("tls: server negotiated both old and new application settings together")
	}

	if serverExtensions.hasApplicationSettings || serverExtensions.hasApplicationSettingsOld {
		if c.vers.protocolVersion() < VersionTLS13 {
			return errors.New("tls: server sent application settings at invalid version")
		}
		if serverExtensions.hasEarlyData {
			return errors.New("tls: server sent application settings with 0-RTT")
		}
		if !serverHasALPN {
			return errors.New("tls: server sent application settings without ALPN")
		}
		settings, ok := c.config.ApplicationSettings[serverExtensions.alpnProtocol]
		if !ok {
			return errors.New("tls: server sent application settings for invalid protocol")
		}

		if serverExtensions.hasApplicationSettings {
			c.hasApplicationSettings = true
			c.localApplicationSettings = settings
			c.peerApplicationSettings = serverExtensions.applicationSettings
		}

		if serverExtensions.hasApplicationSettingsOld {
			c.hasApplicationSettingsOld = true
			c.localApplicationSettingsOld = settings
			c.peerApplicationSettingsOld = serverExtensions.applicationSettingsOld
		}
	} else if serverExtensions.hasEarlyData {
		// 0-RTT connections inherit application settings from the session.
		c.hasApplicationSettings = hs.session.hasApplicationSettings
		c.localApplicationSettings = hs.session.localApplicationSettings
		c.peerApplicationSettings = hs.session.peerApplicationSettings
		c.hasApplicationSettingsOld = hs.session.hasApplicationSettingsOld
		c.localApplicationSettingsOld = hs.session.localApplicationSettingsOld
		c.peerApplicationSettingsOld = hs.session.peerApplicationSettingsOld
	}

	if expected := c.config.Bugs.ExpectServerCertificateTypes; expected != nil {
		if len(expected) > 1 {
			panic("Expected server_certificate_type must not contain more than 1 value.")
		}
		var found []CertificateType
		if serverExtensions.serverCertificateType != nil {
			found = []CertificateType{*serverExtensions.serverCertificateType}
		}
		if !slices.Equal(found, expected) {
			return fmt.Errorf("tls: server sent server certificate type %v, but expected %v", found, expected)
		}
	}
	c.serverCertificateType = serverExtensions.serverCertificateType

	return nil
}

func (hs *clientHandshakeState) processServerExtensionsAfterResume(serverExtensions *serverExtensions, isResume bool) error {
	c := hs.c

	if expected := c.config.Bugs.ExpectClientCertificateTypes; expected != nil {
		if len(expected) > 1 {
			panic("Expected client_certificate_type must not contain more than 1 value.")
		}
		var found []CertificateType
		if serverExtensions.clientCertificateType != nil {
			found = []CertificateType{*serverExtensions.clientCertificateType}
		}
		// The server should not request a client cert if resuming.
		if isResume && len(found) > 0 {
			return errors.New("tls: server sent client_certificate_type on resumption")
		}
		if !isResume && !slices.Equal(found, expected) {
			return fmt.Errorf("tls: server sent client certificate type %v, but expected %v", found, expected)
		}
	}
	c.clientCertificateType = serverExtensions.clientCertificateType

	// Server padding should never be sent on resumption handshakes.
	if serverExtensions.serverPadding != nil && isResume {
		return errors.New("tls: server sent padding on a resumption handshake")
	}

	// If this isn't a resumption handshake, run server padding checks.
	if !isResume {
		if serverExtensions.serverPadding != nil && c.vers.protocolVersion() < VersionTLS13 {
			return errors.New("tls: server sent padding over non-TLS 1.3 connection")
		}

		if !c.config.Bugs.ExpectedServerPadding && serverExtensions.serverPadding != nil {
			return errors.New("tls: server sent unexpected padding")
		}

		if c.config.Bugs.ExpectedServerPadding && serverExtensions.serverPadding == nil {
			return fmt.Errorf("tls: server did not send padding, expected %d bytes",
				*c.config.RequestServerPadding)
		}

		// We expected padding of a certain amount, and got some padding. Check that
		// they match.
		if c.config.Bugs.ExpectedServerPadding && serverExtensions.serverPadding != nil {
			if *serverExtensions.serverPadding != *c.config.RequestServerPadding {
				return fmt.Errorf("tls: server sent %d bytes of padding instead of %d bytes", *serverExtensions.serverPadding, *c.config.RequestServerPadding)
			}
		}
	}

	return nil
}

func (hs *clientHandshakeState) serverResumedSession() bool {
	// If the server responded with the same sessionID then it means the
	// sessionTicket is being used to resume a TLS session.
	//
	// Note that, if hs.hello.sessionID is a non-nil empty array, this will
	// accept an empty session ID from the server as resumption. See
	// EmptyTicketSessionID.
	return hs.session != nil && hs.hello.sessionID != nil &&
		bytes.Equal(hs.serverHello.sessionID, hs.hello.sessionID)
}

func (hs *clientHandshakeState) processServerHello() (bool, error) {
	c := hs.c

	// Check for downgrade signals in the server random, per RFC 8446, section 4.1.3.
	gotDowngrade := hs.serverHello.random[len(hs.serverHello.random)-8:]
	if !c.config.Bugs.IgnoreTLS13DowngradeRandom {
		if c.config.maxVersion() >= VersionTLS13 {
			if bytes.Equal(gotDowngrade, downgradeTLS13) {
				c.sendAlert(alertProtocolVersion)
				return false, errors.New("tls: downgrade from TLS 1.3 detected")
			}
		}
		if c.vers.protocolVersion() <= VersionTLS11 && c.config.maxVersion() >= VersionTLS12 {
			if bytes.Equal(gotDowngrade, downgradeTLS12) {
				c.sendAlert(alertProtocolVersion)
				return false, errors.New("tls: downgrade from TLS 1.2 detected")
			}
		}
	}

	if bytes.Equal(gotDowngrade, downgradeJDK11) != c.config.Bugs.ExpectJDK11DowngradeRandom {
		c.sendAlert(alertProtocolVersion)
		if c.config.Bugs.ExpectJDK11DowngradeRandom {
			return false, errors.New("tls: server did not send a JDK 11 downgrade signal")
		}
		return false, errors.New("tls: server sent an unexpected JDK 11 downgrade signal")
	}

	if c.config.Bugs.ExpectOmitExtensions && !hs.serverHello.omitExtensions {
		return false, errors.New("tls: ServerHello did not omit extensions")
	}

	if hs.serverResumedSession() {
		// For test purposes, assert that the server never accepts the
		// resumption offer on renegotiation.
		if c.cipherSuite != nil && c.config.Bugs.FailIfResumeOnRenego {
			return false, errors.New("tls: server resumed session on renegotiation")
		}

		if hs.session.vers != c.vers {
			return false, errors.New("tls: server resumed an invalid session for the protocol version")
		}

		if hs.session.cipherSuite.id != hs.suite.id {
			return false, errors.New("tls: server resumed an invalid session for the cipher suite")
		}

		if hs.serverHello.extensions.sctList != nil {
			return false, errors.New("tls: server sent SCT extension on session resumption")
		}

		if hs.serverHello.extensions.ocspStapling {
			return false, errors.New("tls: server sent OCSP extension on session resumption")
		}

		// Restore masterSecret and peerCerts from previous state
		hs.masterSecret = hs.session.secret
		c.peerCertificates = hs.session.serverCertificates
		c.peerDelegatedCredential = hs.session.serverDelegatedCredential
		c.extendedMasterSecret = hs.session.extendedMasterSecret
		c.sctList = hs.session.sctList
		c.ocspResponse = hs.session.ocspResponse
		c.peerRawPublicKey = hs.session.serverRawPublicKey
		hs.finishedHash.discardHandshakeBuffer()
		return true, nil
	}

	if hs.serverHello.extensions.sctList != nil {
		c.sctList = hs.serverHello.extensions.sctList
	}

	return false, nil
}

func (hs *clientHandshakeState) readFinished(out []byte) error {
	c := hs.c

	c.readRecord(recordTypeChangeCipherSpec)
	if err := c.in.error(); err != nil {
		return err
	}

	serverFinished, err := readHandshakeType[finishedMsg](c)
	if err != nil {
		return err
	}

	if c.config.Bugs.EarlyChangeCipherSpec == 0 {
		verify := hs.finishedHash.serverSum(hs.masterSecret)
		if len(verify) != len(serverFinished.verifyData) ||
			subtle.ConstantTimeCompare(verify, serverFinished.verifyData) != 1 {
			c.sendAlert(alertHandshakeFailure)
			return errors.New("tls: server's Finished message was incorrect")
		}
	}
	c.serverVerify = append(c.serverVerify[:0], serverFinished.verifyData...)
	copy(out, serverFinished.verifyData)
	hs.writeServerHash(serverFinished.marshal())
	return nil
}

func (hs *clientHandshakeState) readSessionTicket() error {
	c := hs.c

	// Create a session with no server identifier. Either a
	// session ID or session ticket will be attached.
	session := &ClientSessionState{
		vers:                      c.vers,
		cipherSuite:               hs.suite,
		secret:                    hs.masterSecret,
		handshakeHash:             hs.finishedHash.Sum(),
		serverCertificates:        c.peerCertificates,
		serverDelegatedCredential: c.peerDelegatedCredential,
		sctList:                   c.sctList,
		ocspResponse:              c.ocspResponse,
		ticketExpiration:          c.config.time().Add(time.Duration(7 * 24 * time.Hour)),
		serverRawPublicKey:        c.peerRawPublicKey,
	}

	if !hs.serverHello.extensions.ticketSupported {
		if c.config.Bugs.ExpectNewTicket {
			return errors.New("tls: expected new ticket")
		}
		if hs.session == nil && len(hs.serverHello.sessionID) > 0 {
			session.sessionID = hs.serverHello.sessionID
			hs.session = session
		}
		return nil
	}

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

	sessionTicketMsg, err := readHandshakeType[newSessionTicketMsg](c)
	if err != nil {
		return err
	}

	if c.config.Bugs.ExpectNoNonEmptyNewSessionTicket && len(sessionTicketMsg.ticket) != 0 {
		return errors.New("tls: received unexpected non-empty NewSessionTicket")
	}

	session.sessionTicket = sessionTicketMsg.ticket
	hs.session = session

	hs.writeServerHash(sessionTicketMsg.marshal())

	return nil
}

func (hs *clientHandshakeState) sendFinished(out []byte, isResume bool) error {
	c := hs.c

	var postCCSMsgs [][]byte
	seqno := hs.c.sendHandshakeSeq
	if hs.serverHello.extensions.nextProtoNeg {
		nextProto := new(nextProtoMsg)
		proto, fallback := mutualProtocol(c.config.NextProtos, hs.serverHello.extensions.nextProtos)
		if fallback && c.config.NoFallbackNextProto {
			proto = ""
			fallback = false
		}
		nextProto.proto = proto
		c.clientProtocol = proto
		c.clientProtocolFallback = fallback

		nextProtoBytes := nextProto.marshal()
		hs.finishedHash.WriteHandshake(nextProtoBytes, seqno)
		seqno++
		postCCSMsgs = append(postCCSMsgs, nextProtoBytes)
	}

	if hs.serverHello.extensions.channelIDRequested {
		var resumeHash []byte
		if isResume {
			resumeHash = hs.session.handshakeHash
		}
		channelIDMsgBytes, err := hs.writeChannelIDMessage(hs.finishedHash.hashForChannelID(resumeHash))
		if err != nil {
			return err
		}
		hs.finishedHash.WriteHandshake(channelIDMsgBytes, seqno)
		seqno++
		postCCSMsgs = append(postCCSMsgs, channelIDMsgBytes)
	}

	finished := new(finishedMsg)
	if c.config.Bugs.EarlyChangeCipherSpec == 2 {
		finished.verifyData = hs.finishedHash.clientSum(nil)
	} else {
		finished.verifyData = hs.finishedHash.clientSum(hs.masterSecret)
	}
	copy(out, finished.verifyData)
	if c.config.Bugs.BadFinished {
		finished.verifyData[0]++
	}
	c.clientVerify = append(c.clientVerify[:0], finished.verifyData...)
	hs.finishedBytes = finished.marshal()
	hs.finishedHash.WriteHandshake(hs.finishedBytes, seqno)
	if c.config.Bugs.PartialClientFinishedWithClientHello {
		// The first byte has already been written.
		postCCSMsgs = append(postCCSMsgs, hs.finishedBytes[1:])
	} else {
		postCCSMsgs = append(postCCSMsgs, hs.finishedBytes)
	}

	if c.config.Bugs.FragmentAcrossChangeCipherSpec {
		c.writeRecord(recordTypeHandshake, postCCSMsgs[0][:5])
		postCCSMsgs[0] = postCCSMsgs[0][5:]
	}

	if !c.config.Bugs.SkipChangeCipherSpec &&
		c.config.Bugs.EarlyChangeCipherSpec == 0 {
		ccs := []byte{1}
		if c.config.Bugs.BadChangeCipherSpec != nil {
			ccs = c.config.Bugs.BadChangeCipherSpec
		}
		c.writeRecord(recordTypeChangeCipherSpec, ccs)
	}

	if c.config.Bugs.AppDataAfterChangeCipherSpec != nil {
		c.writeRecord(recordTypeApplicationData, c.config.Bugs.AppDataAfterChangeCipherSpec)
	}
	if c.config.Bugs.AlertAfterChangeCipherSpec != 0 {
		c.sendAlert(c.config.Bugs.AlertAfterChangeCipherSpec)
		return errors.New("tls: simulating post-CCS alert")
	}

	if !c.config.Bugs.SkipFinished {
		for _, msg := range postCCSMsgs {
			c.writeRecord(recordTypeHandshake, msg)
		}

		if c.config.Bugs.SendExtraFinished {
			c.writeRecord(recordTypeHandshake, finished.marshal())
		}
	}

	if !isResume || !c.config.Bugs.PackAppDataWithHandshake {
		return c.flushHandshake()
	}
	return nil
}

func (hs *clientHandshakeState) writeChannelIDMessage(channelIDHash []byte) ([]byte, error) {
	c := hs.c
	channelIDMsg := new(channelIDMsg)
	if c.config.ChannelID.Curve != elliptic.P256() {
		return nil, fmt.Errorf("tls: Channel ID is not on P-256.")
	}
	r, s, err := ecdsa.Sign(c.config.rand(), c.config.ChannelID, channelIDHash)
	if err != nil {
		return nil, err
	}
	channelID := make([]byte, 128)
	writeIntPadded(channelID[0:32], c.config.ChannelID.X)
	writeIntPadded(channelID[32:64], c.config.ChannelID.Y)
	writeIntPadded(channelID[64:96], r)
	writeIntPadded(channelID[96:128], s)
	if c.config.Bugs.InvalidChannelIDSignature {
		channelID[64] ^= 1
	}
	channelIDMsg.channelID = channelID

	c.channelID = &c.config.ChannelID.PublicKey

	return channelIDMsg.marshal(), nil
}

func (hs *clientHandshakeState) writeClientHash(msg []byte) {
	// writeClientHash is called before writeRecord.
	hs.finishedHash.WriteHandshake(msg, hs.c.sendHandshakeSeq)
}

func (hs *clientHandshakeState) writeServerHash(msg []byte) {
	// writeServerHash is called after readHandshake.
	hs.finishedHash.WriteHandshake(msg, hs.c.recvHandshakeSeq-1)
}

// clientSessionCacheKey returns a key used to cache sessionTickets that could
// be used to resume previously negotiated TLS sessions with a server.
func clientSessionCacheKey(serverAddr net.Addr, config *Config) string {
	if len(config.ServerName) > 0 {
		return config.ServerName
	}
	return serverAddr.String()
}

// mutualProtocol finds the mutual Next Protocol Negotiation or ALPN protocol
// given list of possible protocols and a list of the preference order. The
// first list must not be empty. It returns the resulting protocol and flag
// indicating if the fallback case was reached.
func mutualProtocol(protos, preferenceProtos []string) (string, bool) {
	for _, s := range preferenceProtos {
		if slices.Contains(protos, s) {
			return s, false
		}
	}

	return protos[0], true
}

// writeIntPadded writes x into b, padded up with leading zeros as
// needed.
func writeIntPadded(b []byte, x *big.Int) {
	clear(b)
	xb := x.Bytes()
	copy(b[len(b)-len(xb):], xb)
}

func (hs *clientHandshakeState) generatePSKBinders(hello *clientHelloMsg, firstClientHello, helloRetryRequest []byte) {
	config := hs.c.config

	applyBinderBugs := !config.Bugs.OnlyCorruptSecondPSKBinder || len(firstClientHello) > 0
	if applyBinderBugs && config.Bugs.SendNoPSKBinder {
		// The binders may have been set from the previous
		// ClientHello.
		hello.pskBinders = nil
		return
	}

	corruptBinders := func(binders [][]byte) [][]byte {
		for i, binder := range binders {
			if applyBinderBugs && config.Bugs.SendShortPSKBinder {
				binder = binder[:len(binder)-1]
			}
			if applyBinderBugs && config.Bugs.SendInvalidPSKBinder {
				binder = slices.Clone(binder)
				binder[0] ^= 1
			}
			binders[i] = binder
		}
		if applyBinderBugs && config.Bugs.SendExtraPSKBinder {
			binders = append(binders, binders[0])
		}
		return binders
	}

	// Fill hello.pskBinders with appropriate length arrays of zeros so the
	// length prefixes are correct when computing the binder over the truncated
	// ClientHello message.
	hello.pskBinders = make([][]byte, len(hs.preSharedKeys))
	for i, psk := range hs.preSharedKeys {
		hello.pskBinders[i] = make([]byte, psk.hash.Size())
	}
	hello.pskBinders = corruptBinders(hello.pskBinders)

	// Serialize the ClientHello with the placeholder binders truncated.
	bindersSize := 2 // Length prefix
	for _, binder := range hello.pskBinders {
		bindersSize += 1 /* Length prefix */ + len(binder)
	}
	helloBytes := hello.marshal()
	truncatedHello := helloBytes[:len(helloBytes)-bindersSize]

	// Fill in the actual binders.
	hello.pskBinders = make([][]byte, len(hs.preSharedKeys))
	for i, psk := range hs.preSharedKeys {
		hello.pskBinders[i] = psk.computeBinder(firstClientHello, helloRetryRequest, truncatedHello)
	}
	hello.pskBinders = corruptBinders(hello.pskBinders)

	// Clear the cached encoding.
	hello.raw = nil
}
