// 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),
		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,
	}

	// 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

	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
}
