// 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"
	"slices"
	"time"

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

// serverHandshakeState contains details of a server handshake in progress.
// It's discarded once the handshake has completed.
type serverHandshakeState struct {
	c               *Conn
	clientHello     *clientHelloMsg
	hello           *serverHelloMsg
	suite           *cipherSuite
	ellipticOk      bool
	ecdsaOk         bool
	sessionState    *sessionState
	finishedHash    finishedHash
	masterSecret    []byte
	certsFromClient [][]byte
	cert            *Credential
	finishedBytes   []byte
	echHPKEContext  *hpke.Context
	echConfigID     uint8
}

// serverHandshake performs a TLS handshake as a server.
func (c *Conn) serverHandshake() error {
	config := c.config

	// If this is the first server handshake, we generate a random key to
	// encrypt the tickets with.
	config.serverInitOnce.Do(config.serverInit)

	c.sendHandshakeSeq = 0
	c.recvHandshakeSeq = 0

	hs := serverHandshakeState{
		c: c,
	}
	if err := hs.readClientHello(); err != nil {
		return err
	}

	if c.vers.protocolVersion() >= VersionTLS13 {
		if err := hs.doTLS13Handshake(); err != nil {
			return err
		}
	} else {
		isResume, err := hs.processClientHello()
		if err != nil {
			return err
		}

		// We only implement enough of SSL 3.0 to test that the client doesn't:
		// if negotiated (possibly with the NegotiateVersion bug), we send a
		// ServerHello and look for the resulting client protocol_version alert.
		if c.vers.protocolVersion() == VersionSSL30 {
			c.writeRecord(recordTypeHandshake, hs.hello.marshal())
			if err := c.flushHandshake(); err != nil {
				return err
			}
			if _, err := c.readHandshake(); err != nil {
				return err
			}
			return errors.New("tls: client did not reject an SSL 3.0 ServerHello")
		}

		// For an overview of TLS handshaking, see https://tools.ietf.org/html/rfc5246#section-7.3
		if isResume {
			// The client has included a session ticket and so we do an abbreviated handshake.
			if err := hs.doResumeHandshake(); err != nil {
				return err
			}
			if err := hs.establishKeys(); err != nil {
				return err
			}
			if c.config.Bugs.RenewTicketOnResume {
				if err := hs.sendSessionTicket(); err != nil {
					return err
				}
			}
			if err := hs.sendFinished(c.firstFinished[:], isResume); err != nil {
				return err
			}
			if err := hs.readFinished(nil, isResume); err != nil {
				return err
			}
			if err := c.ackHandshake(); err != nil {
				return err
			}
			c.didResume = true
		} else {
			// The client didn't include a session ticket, or it wasn't
			// valid so we do a full handshake.
			if err := hs.doFullHandshake(); err != nil {
				return err
			}
			if err := hs.establishKeys(); err != nil {
				return err
			}
			if err := hs.readFinished(c.firstFinished[:], isResume); err != nil {
				return err
			}
			if c.config.Bugs.AlertBeforeFalseStartTest != 0 {
				c.sendAlert(c.config.Bugs.AlertBeforeFalseStartTest)
			}
			if c.config.Bugs.ExpectFalseStart {
				if err := c.readRecord(recordTypeApplicationData); err != nil {
					return fmt.Errorf("tls: peer did not false start: %s", err)
				}
			}
			if err := hs.sendSessionTicket(); err != nil {
				return err
			}
			if err := hs.sendFinished(nil, isResume); err != nil {
				return err
			}
		}

		c.exporterSecret = hs.masterSecret
	}
	c.handshakeComplete = true
	copy(c.clientRandom[:], hs.clientHello.random)
	copy(c.serverRandom[:], hs.hello.random)

	return nil
}

func (c *Conn) shouldSendHelloVerifyRequest() bool {
	if !c.isDTLS {
		return false
	}
	if c.config.Bugs.ForceHelloVerifyRequest {
		return true
	}
	if c.config.Bugs.SkipHelloVerifyRequest {
		return false
	}
	// Don't send HVR for DTLS 1.3; do send it for DTLS <= 1.2.
	return c.vers.protocolVersion() < VersionTLS13
}

// readClientHello reads a ClientHello message from the client and determines
// the protocol version.
func (hs *serverHandshakeState) readClientHello() error {
	config := hs.c.config
	c := hs.c

	var err error
	hs.clientHello, err = readHandshakeType[clientHelloMsg](c)
	if err != nil {
		return err
	}
	if config.Bugs.CheckClientHello != nil {
		if err = config.Bugs.CheckClientHello(hs.clientHello); err != nil {
			return err
		}
	}
	if size := config.Bugs.RequireClientHelloSize; size != 0 && len(hs.clientHello.raw) != size {
		return fmt.Errorf("tls: ClientHello record size is %d, but expected %d", len(hs.clientHello.raw), size)
	}
	if isAllZero(hs.clientHello.random) {
		// If the client forgets to fill in the client random, it will likely be
		// all zero.
		return errors.New("tls: ClientHello random was all zero")
	}

	if expected := config.Bugs.ExpectOuterServerName; len(expected) != 0 && expected != hs.clientHello.serverName {
		return fmt.Errorf("tls: unexpected ClientHelloOuter server name: wanted %q, got %q", expected, hs.clientHello.serverName)
	}

	// We check this both before and after decrypting ECH.
	if !hs.clientHello.hasGREASEExtension && config.Bugs.ExpectGREASE {
		return errors.New("tls: no GREASE extension found")
	}

	if config.Bugs.ExpectClientECH && hs.clientHello.echOuter == nil {
		return errors.New("tls: expected client to offer ECH")
	}
	if config.Bugs.ExpectNoClientECH && hs.clientHello.echOuter != nil {
		return errors.New("tls: expected client not to offer ECH")
	}

	if echOuter := hs.clientHello.echOuter; echOuter != nil {
		for _, candidate := range config.ServerECHConfigs {
			if candidate.ECHConfig.ConfigID != echOuter.configID {
				continue
			}
			if !slices.Contains(candidate.ECHConfig.CipherSuites, HPKECipherSuite{KDF: echOuter.kdfID, AEAD: echOuter.aeadID}) {
				continue
			}
			info := []byte("tls ech\x00")
			info = append(info, candidate.ECHConfig.Raw...)
			hs.echHPKEContext, err = hpke.SetupBaseReceiverX25519(echOuter.kdfID, echOuter.aeadID, echOuter.enc, candidate.Key, info)
			if err != nil {
				continue
			}
			clientHelloInner, err := hs.decryptClientHello(hs.clientHello)
			if err != nil {
				if _, ok := err.(*echDecryptError); ok {
					continue
				}
				c.sendAlert(alertDecryptError)
				return fmt.Errorf("tls: error decrypting ClientHello: %s", err)
			}
			if config.Bugs.UseInnerSessionWithClientHelloOuter {
				hs.clientHello.pskIdentities = clientHelloInner.pskIdentities
			} else {
				c.echAccepted = true
				hs.clientHello = clientHelloInner
				hs.echConfigID = echOuter.configID
			}
		}
	}

	c.clientVersion = hs.clientHello.vers

	// Use the versions extension if supplied, otherwise use the legacy ClientHello version.
	if len(hs.clientHello.supportedVersions) == 0 {
		if c.isDTLS {
			if hs.clientHello.vers <= VersionDTLS12 {
				hs.clientHello.supportedVersions = append(hs.clientHello.supportedVersions, VersionDTLS12)
			}
			if hs.clientHello.vers <= VersionDTLS10 {
				hs.clientHello.supportedVersions = append(hs.clientHello.supportedVersions, VersionDTLS10)
			}
		} else {
			if hs.clientHello.vers >= VersionTLS12 {
				hs.clientHello.supportedVersions = append(hs.clientHello.supportedVersions, VersionTLS12)
			}
			if hs.clientHello.vers >= VersionTLS11 {
				hs.clientHello.supportedVersions = append(hs.clientHello.supportedVersions, VersionTLS11)
			}
			if hs.clientHello.vers >= VersionTLS10 {
				hs.clientHello.supportedVersions = append(hs.clientHello.supportedVersions, VersionTLS10)
			}
			if hs.clientHello.vers >= VersionSSL30 {
				hs.clientHello.supportedVersions = append(hs.clientHello.supportedVersions, VersionSSL30)
			}
		}
	} else if config.Bugs.ExpectGREASE && !containsGREASE(hs.clientHello.supportedVersions) {
		return errors.New("tls: no GREASE version value found")
	}

	var wireVersion uint16
	if !c.haveVers {
		if config.Bugs.NegotiateVersion != 0 {
			wireVersion = config.Bugs.NegotiateVersion
		} else {
			idx := slices.IndexFunc(hs.clientHello.supportedVersions, func(vers uint16) bool {
				_, ok := config.isSupportedVersion(vers, c.isDTLS)
				return ok
			})
			if idx < 0 {
				c.sendAlert(alertProtocolVersion)
				return errors.New("tls: client did not offer any supported protocol versions")
			}
			wireVersion = hs.clientHello.supportedVersions[idx]
		}
	} else {
		// This is a renegotiation and we already have a version.
		wireVersion = c.vers.wire
		if config.Bugs.NegotiateVersionOnRenego != 0 {
			wireVersion = config.Bugs.NegotiateVersionOnRenego
		}
	}

	var ok bool
	c.vers, ok = wireToVersion(wireVersion, c.isDTLS)
	if !ok {
		panic(fmt.Sprintf("Could not map wire version 0x%x", wireVersion))
	}

	clientVers, clientVersOK := wireToVersion(c.clientVersion, c.isDTLS)

	if c.shouldSendHelloVerifyRequest() {
		// Per RFC 6347, the version field in HelloVerifyRequest SHOULD
		// be always DTLS 1.0
		cookieLen := c.config.Bugs.HelloVerifyRequestCookieLength
		if cookieLen == 0 {
			cookieLen = 32
		}
		if c.config.Bugs.EmptyHelloVerifyRequestCookie {
			cookieLen = 0
		}
		helloVerifyRequest := &helloVerifyRequestMsg{
			vers:   VersionDTLS10,
			cookie: make([]byte, cookieLen),
		}
		if _, err := io.ReadFull(c.config.rand(), helloVerifyRequest.cookie); err != nil {
			c.sendAlert(alertInternalError)
			return errors.New("dtls: short read from Rand: " + err.Error())
		}
		c.writeRecord(recordTypeHandshake, helloVerifyRequest.marshal())
		if err := c.flushHandshake(); err != nil {
			return err
		}

		newClientHello, err := readHandshakeType[clientHelloMsg](c)
		if err != nil {
			return err
		}
		if !bytes.Equal(newClientHello.cookie, helloVerifyRequest.cookie) {
			return errors.New("dtls: invalid cookie")
		}
		// Allow the client to recompute the pre_shared_key extension. It is
		// possible we'll want to remove this and instead require the client
		// keep it unchanged. (Either by remembering it or hashing the
		// ClientHello funny.) See discussion at
		// https://mailarchive.ietf.org/arch/msg/tls/HSTgV2voS9tn03oasGmBAdwazWA/
		if err := checkClientHellosEqual(hs.clientHello.raw, newClientHello.raw, c.isDTLS, []uint16{extensionPreSharedKey}); err != nil {
			return err
		}
		hs.clientHello = newClientHello
	}
	// The version for the connection is selected before sending
	// HelloVerifyRequest, but haveVers isn't set until after we send it and
	// receive the second ClientHello. This is intentional because once the
	// version for the Conn has been negotiated, we enforce that the version
	// in the record layer matches the negotiated version.
	//
	// At the time the server has selected a version and decided to send a
	// HelloVerifyRequest to the client, only the server knows the selected
	// version. Even though there is a version field in HelloVerifyRequest,
	// it is only used to indicate packet formatting and is not part of
	// version negotiation. Thus, when the client sends its second
	// ClientHello (in response to HelloVerifyRequest), it does not know the
	// version selected for this connection. Therefore, this server can't
	// enforce that the client used the correct version in the record layer.
	c.haveVers = true

	if config.Bugs.RequireSameRenegoClientVersion && c.clientVersion != 0 {
		if c.clientVersion != hs.clientHello.vers {
			return fmt.Errorf("tls: client offered different version on renego")
		}
	}

	if config.Bugs.FailIfPostQuantumOffered && slices.ContainsFunc(hs.clientHello.supportedCurves, isPqGroup) {
		return errors.New("tls: post-quantum group was offered")
	}

	if expected := config.Bugs.ExpectedKeyShares; expected != nil {
		if len(expected) != len(hs.clientHello.keyShares) {
			return fmt.Errorf("tls: expected %d key shares, but found %d", len(expected), len(hs.clientHello.keyShares))
		}

		for i, group := range expected {
			if found := hs.clientHello.keyShares[i].group; found != group {
				return fmt.Errorf("tls: key share #%d is for group %d, not %d", i, found, group)
			}
		}
	}

	// Reject < 1.2 ClientHellos with signature_algorithms.
	if clientVersOK && clientVers.protocolVersion() < VersionTLS12 && len(hs.clientHello.signatureAlgorithms) > 0 {
		return fmt.Errorf("tls: client included signature_algorithms before TLS 1.2")
	}

	// Check the client cipher list is consistent with the version.
	if clientVersOK && clientVers.protocolVersion() < VersionTLS12 && slices.ContainsFunc(hs.clientHello.cipherSuites, isTLS12Cipher) {
		return fmt.Errorf("tls: client offered TLS 1.2 cipher before TLS 1.2")
	}

	if config.Bugs.MockQUICTransport != nil && len(hs.clientHello.sessionID) > 0 {
		return fmt.Errorf("tls: QUIC client did not disable compatibility mode")
	}
	if config.Bugs.ExpectNoSessionID && len(hs.clientHello.sessionID) > 0 {
		return fmt.Errorf("tls: client offered an unexpected session ID")
	}
	if config.Bugs.ExpectNoTLS12Session {
		if len(hs.clientHello.sessionID) > 0 {
			if _, ok := config.ServerSessionCache.Get(string(hs.clientHello.sessionID)); ok {
				return fmt.Errorf("tls: client offered an unexpected TLS 1.2 session")
			}
		}
		if len(hs.clientHello.sessionTicket) > 0 {
			return fmt.Errorf("tls: client offered an unexpected session ticket")
		}
	}
	if config.Bugs.ExpectNoTLS12TicketSupport && hs.clientHello.ticketSupported {
		return fmt.Errorf("tls: client sent unexpected session ticket extension")
	}

	if config.Bugs.ExpectNoTLS13PSK && len(hs.clientHello.pskIdentities) > 0 {
		return fmt.Errorf("tls: client offered unexpected PSK identities")
	}

	scsvFound := slices.Contains(hs.clientHello.cipherSuites, fallbackSCSV)
	if !scsvFound && config.Bugs.FailIfNotFallbackSCSV {
		return errors.New("tls: no fallback SCSV found when expected")
	} else if scsvFound && !config.Bugs.FailIfNotFallbackSCSV {
		return errors.New("tls: fallback SCSV found when not expected")
	}

	if config.Bugs.ExpectGREASE && !containsGREASE(hs.clientHello.cipherSuites) {
		return errors.New("tls: no GREASE cipher suite value found")
	}

	if config.Bugs.ExpectGREASE && !slices.ContainsFunc(hs.clientHello.supportedCurves, func(c CurveID) bool { return isGREASEValue(uint16(c)) }) {
		return errors.New("tls: no GREASE curve value found")
	}

	if len(hs.clientHello.keyShares) > 0 {
		greaseFound := slices.ContainsFunc(hs.clientHello.keyShares, func(ks keyShareEntry) bool { return isGREASEValue(uint16(ks.group)) })
		if !greaseFound && config.Bugs.ExpectGREASE {
			return errors.New("tls: no GREASE curve value found")
		}
	}

	if len(hs.clientHello.sessionID) == 0 && c.config.Bugs.ExpectClientHelloSessionID {
		return errors.New("tls: expected non-empty session ID from client")
	}

	if expected := c.config.Bugs.ExpectPeerRequestedTrustAnchors; expected != nil {
		if hs.clientHello.trustAnchors == nil {
			return errors.New("tls: client did not send trust anchors")
		}
		if !slices.EqualFunc(expected, hs.clientHello.trustAnchors, slices.Equal) {
			return fmt.Errorf("tls: client offered trust anchors %v, but expected %v", hs.clientHello.trustAnchors, expected)
		}
	}

	applyBugsToClientHello(hs.clientHello, config)

	return nil
}

func applyBugsToClientHello(clientHello *clientHelloMsg, config *Config) {
	if config.Bugs.IgnorePeerSignatureAlgorithmPreferences {
		clientHello.signatureAlgorithms = config.Credential.signatureAlgorithms()
	}
	if config.Bugs.IgnorePeerCurvePreferences {
		clientHello.supportedCurves = config.curvePreferences()
	}
	if config.Bugs.IgnorePeerCipherPreferences {
		clientHello.cipherSuites = config.cipherSuites()
	}
}

type echDecryptError struct {
	error
}

func (hs *serverHandshakeState) decryptClientHello(helloOuter *clientHelloMsg) (helloInner *clientHelloMsg, err error) {
	// ClientHelloOuterAAD is ClientHelloOuter with the payload replaced by
	// zeros. See draft-ietf-tls-esni-13, section 5.2.
	aad := make([]byte, len(helloOuter.raw)-4)
	copy(aad, helloOuter.raw[4:helloOuter.echPayloadStart])
	copy(aad[helloOuter.echPayloadEnd-4:], helloOuter.raw[helloOuter.echPayloadEnd:])

	// In fuzzer mode, the payload is cleartext.
	encoded := helloOuter.echOuter.payload
	if !hs.c.config.Bugs.NullAllCiphers {
		var err error
		encoded, err = hs.echHPKEContext.Open(helloOuter.echOuter.payload, aad)
		if err != nil {
			// Wrap |err| so the caller can implement trial decryption.
			return nil, &echDecryptError{err}
		}
	}

	helloInner, err = decodeClientHelloInner(hs.c.config, encoded, helloOuter)
	if err != nil {
		return nil, err
	}

	if isAllZero(helloInner.random) {
		// If the client forgets to fill in the client random, it will likely be
		// all zero.
		return nil, errors.New("tls: ClientHelloInner random was all zero")
	}
	if bytes.Equal(helloInner.random, helloOuter.random) {
		return nil, errors.New("tls: ClientHelloOuter and ClientHelloInner have the same random values")
	}
	// ClientHelloInner should not offer TLS 1.2 and below.
	if len(helloInner.supportedVersions) == 0 {
		return nil, errors.New("tls: ClientHelloInner did not offer supported_versions")
	}
	for _, vers := range helloInner.supportedVersions {
		switch vers {
		case VersionSSL30, VersionTLS10, VersionTLS11, VersionTLS12, VersionDTLS10, VersionDTLS12:
			return nil, fmt.Errorf("tls: ClientHelloInner offered invalid version: %04x", vers)
		}
	}
	// ClientHelloInner should omit TLS-1.2-only extensions.
	if helloInner.nextProtoNeg || len(helloInner.supportedPoints) != 0 || helloInner.ticketSupported || helloInner.secureRenegotiation != nil || helloInner.extendedMasterSecret {
		return nil, errors.New("tls: ClientHelloInner included a TLS-1.2-only extension")
	}
	if !helloInner.echInner {
		return nil, errors.New("tls: ClientHelloInner missing inner encrypted_client_hello extension")
	}

	return helloInner, nil
}

func (hs *serverHandshakeState) doTLS13Handshake() error {
	c := hs.c
	config := c.config

	// We've read the ClientHello, so the next record must be preceded with ChangeCipherSpec.
	c.expectTLS13ChangeCipherSpec = true
	sessionID := hs.clientHello.sessionID
	if c.isDTLS && !config.Bugs.DTLS13EchoSessionID {
		sessionID = nil
	}

	hs.hello = &serverHelloMsg{
		isDTLS:                c.isDTLS,
		vers:                  c.vers.wire,
		sessionID:             sessionID,
		compressionMethod:     config.Bugs.SendCompressionMethod,
		versOverride:          config.Bugs.SendServerHelloVersion,
		supportedVersOverride: config.Bugs.SendServerSupportedVersionExtension,
		omitSupportedVers:     config.Bugs.OmitServerSupportedVersionExtension,
		customExtension:       config.Bugs.CustomUnencryptedExtension,
		unencryptedALPN:       config.Bugs.SendUnencryptedALPN,
	}

	hs.hello.random = make([]byte, 32)
	if _, err := io.ReadFull(config.rand(), hs.hello.random); err != nil {
		c.sendAlert(alertInternalError)
		return err
	}

	// TLS 1.3 forbids clients from advertising any non-null compression.
	if len(hs.clientHello.compressionMethods) != 1 || hs.clientHello.compressionMethods[0] != compressionNone {
		return errors.New("tls: client sent compression method other than null for TLS 1.3")
	}

	// Prepare an EncryptedExtensions message, but do not send it yet.
	encryptedExtensions := new(encryptedExtensionsMsg)
	encryptedExtensions.empty = config.Bugs.EmptyEncryptedExtensions
	if err := hs.processClientExtensions(&encryptedExtensions.extensions); err != nil {
		return err
	}

	// Select the cipher suite.
	var preferenceList, supportedList []uint16
	if config.PreferServerCipherSuites {
		preferenceList = config.cipherSuites()
		supportedList = hs.clientHello.cipherSuites
	} else {
		preferenceList = hs.clientHello.cipherSuites
		supportedList = config.cipherSuites()
	}

	for _, id := range preferenceList {
		if hs.suite = c.tryCipherSuite(id, supportedList, c.vers, true, true); hs.suite != nil {
			break
		}
	}

	if hs.suite == nil {
		c.sendAlert(alertHandshakeFailure)
		return errors.New("tls: no cipher suite supported by both client and server")
	}

	hs.hello.cipherSuite = hs.suite.id
	if c.config.Bugs.SendCipherSuite != 0 {
		hs.hello.cipherSuite = c.config.Bugs.SendCipherSuite
	}

	hs.finishedHash = newFinishedHash(c.vers, hs.suite.hash())
	hs.finishedHash.discardHandshakeBuffer()
	hs.writeClientHash(hs.clientHello.marshal())

	pskIdentities := hs.clientHello.pskIdentities
	pskKEModes := hs.clientHello.pskKEModes

	var replacedPSKIdentities bool
	if len(pskIdentities) == 0 && len(hs.clientHello.sessionTicket) > 0 && c.config.Bugs.AcceptAnySession {
		// Pick up the ticket from the TLS 1.2 extension, to test the
		// client does not get in a mixed up state.
		psk := pskIdentity{
			ticket: hs.clientHello.sessionTicket,
		}
		pskIdentities = []pskIdentity{psk}
		pskKEModes = []byte{pskDHEKEMode}
		replacedPSKIdentities = true
	}
	if config.Bugs.UseInnerSessionWithClientHelloOuter {
		replacedPSKIdentities = true
	}

	var psk *preSharedKey
	foundKEMode := bytes.IndexByte(pskKEModes, pskDHEKEMode) >= 0

	// If using PSKs, require that we are able to use it. (We may override the
	// choice with session resumption later.)
	if config.Credential.Type == CredentialTypePreSharedKey {
		if !foundKEMode {
			return errors.New("tls: no common PSK key exchange mode")
		}
		psk = importPSK(config.Credential, c.vers, hs.suite.hash())
		pskIndex := slices.IndexFunc(pskIdentities, func(id pskIdentity) bool {
			return bytes.Equal(id.ticket, psk.identity)
		})
		if pskIndex < 0 {
			return errors.New("tls: client did not offer expected PSK")
		}
		binderToVerify := hs.clientHello.pskBinders[pskIndex]
		if err := verifyPSKBinder(psk, hs.clientHello, binderToVerify, []byte{}, []byte{}); err != nil {
			return err
		}
		hs.hello.hasPSKIdentity = true
		hs.hello.pskIdentity = uint16(pskIndex)
		c.selectedPSK = config.Credential
	}

	if foundKEMode && !config.SessionTicketsDisabled {
		for i, pskIdentity := range pskIdentities {
			// TODO(svaldez): Check the obfuscatedTicketAge before accepting 0-RTT.
			sessionState, ok := c.decryptTicket(pskIdentity.ticket)
			if !ok {
				continue
			}

			if !config.Bugs.AcceptAnySession {
				if sessionState.vers != c.vers ||
					sessionState.ticketExpiration.Before(c.config.time()) ||
					sessionState.cipherSuite.hash() != hs.suite.hash() {
					continue
				}
			}

			clientTicketAge := time.Duration(uint32(pskIdentity.obfuscatedTicketAge-sessionState.ticketAgeAdd)) * time.Millisecond
			if config.Bugs.ExpectTicketAge != 0 && clientTicketAge != config.Bugs.ExpectTicketAge {
				c.sendAlert(alertHandshakeFailure)
				return errors.New("tls: invalid ticket age")
			}

			psk = newServerSessionPSK(pskIdentity.ticket, sessionState)
			if !replacedPSKIdentities {
				binderToVerify := hs.clientHello.pskBinders[i]
				if err := verifyPSKBinder(psk, hs.clientHello, binderToVerify, []byte{}, []byte{}); err != nil {
					return err
				}
			}

			hs.sessionState = sessionState
			hs.hello.hasPSKIdentity = true
			hs.hello.pskIdentity = uint16(i)
			c.didResume = true
			break
		}
	}

	// Resolve PSK and compute the early secret.
	if psk != nil {
		hs.finishedHash.addEntropy(psk.secret)
	} else {
		hs.finishedHash.addEntropy(hs.finishedHash.zeroSecret())
	}

	if hs.clientHello.hasEarlyData && c.isDTLS {
		return errors.New("tls: early data extension received in DTLS")
	}

	// Decide whether to use key_share.
	hs.hello.hasKeyShare = config.Credential.Type != CredentialTypeSPAKE2PlusV1 && config.Bugs.UnsolicitedPAKE == 0
	if psk != nil && config.Bugs.NegotiatePSKResumption {
		hs.hello.hasKeyShare = false
	}
	if config.Bugs.MissingKeyShare {
		hs.hello.hasKeyShare = false
	}

	// Decide whether a HelloRetryRequest is needed.
	sendHelloRetryRequest := config.Bugs.AlwaysSendHelloRetryRequest
	cipherSuite := hs.suite.id
	if config.Bugs.SendHelloRetryRequestCipherSuite != 0 {
		cipherSuite = config.Bugs.SendHelloRetryRequestCipherSuite
	}
	helloRetryRequest := &helloRetryRequestMsg{
		isDTLS:              c.isDTLS,
		vers:                c.vers.wire,
		sessionID:           hs.clientHello.sessionID,
		cipherSuite:         cipherSuite,
		compressionMethod:   config.Bugs.SendCompressionMethod,
		duplicateExtensions: config.Bugs.DuplicateHelloRetryRequestExtensions,
	}

	if config.Bugs.SendHelloRetryRequestCookie != nil {
		sendHelloRetryRequest = true
		helloRetryRequest.cookie = config.Bugs.SendHelloRetryRequestCookie
	}

	if len(config.Bugs.CustomHelloRetryRequestExtension) > 0 {
		sendHelloRetryRequest = true
		helloRetryRequest.customExtension = config.Bugs.CustomHelloRetryRequestExtension
	}

	var selectedCurve CurveID
	var selectedKeyShare *keyShareEntry
	if hs.hello.hasKeyShare {
		// Select the matching curve.
		supportedCurve := false
		preferredCurves := config.curvePreferences()
		for _, curve := range hs.clientHello.supportedCurves {
			if slices.Contains(preferredCurves, curve) {
				supportedCurve = true
				selectedCurve = curve
				break
			}
		}
		if !supportedCurve {
			c.sendAlert(alertHandshakeFailure)
			return errors.New("tls: no curve supported by both client and server")
		}

		// Look for the key share corresponding to our selected curve.
		for i := range hs.clientHello.keyShares {
			if hs.clientHello.keyShares[i].group == selectedCurve {
				selectedKeyShare = &hs.clientHello.keyShares[i]
				break
			}
		}

		if config.Bugs.ExpectMissingKeyShare && selectedKeyShare != nil {
			return errors.New("tls: expected missing key share")
		}

		if selectedKeyShare == nil {
			helloRetryRequest.hasSelectedGroup = true
			helloRetryRequest.selectedGroup = selectedCurve
			sendHelloRetryRequest = true
		}
	}

	if config.Bugs.SendHelloRetryRequestCurve != 0 {
		helloRetryRequest.hasSelectedGroup = true
		helloRetryRequest.selectedGroup = config.Bugs.SendHelloRetryRequestCurve
		sendHelloRetryRequest = true
	}

	if config.Bugs.SkipHelloRetryRequest {
		sendHelloRetryRequest = false
	}

	if config.Bugs.SendPAKEInHelloRetryRequest {
		helloRetryRequest.pakeID = spakeID
		helloRetryRequest.pakeMessage = []byte{1}
		sendHelloRetryRequest = true
	}

	if sendHelloRetryRequest {
		hs.finishedHash.UpdateForHelloRetryRequest()

		// Emit the ECH confirmation signal when requested.
		if hs.clientHello.echInner {
			helloRetryRequest.echConfirmation = make([]byte, 8)
			helloRetryRequest.echConfirmation = hs.finishedHash.echAcceptConfirmation(hs.clientHello.random, echAcceptConfirmationHRRLabel, helloRetryRequest.marshal())
			helloRetryRequest.raw = nil
		} else if config.Bugs.AlwaysSendECHHelloRetryRequest {
			// When solicited, a random ECH confirmation string should be ignored.
			helloRetryRequest.echConfirmation = make([]byte, 8)
			if _, err := io.ReadFull(config.rand(), helloRetryRequest.echConfirmation); err != nil {
				c.sendAlert(alertInternalError)
				return fmt.Errorf("tls: short read from Rand: %s", err)
			}
		}

		hs.writeServerHash(helloRetryRequest.marshal())
		if c.config.Bugs.PartialServerHelloWithHelloRetryRequest {
			data := helloRetryRequest.marshal()
			c.writeRecord(recordTypeHandshake, append(slices.Clip(data), typeServerHello))
		} else {
			c.writeRecord(recordTypeHandshake, helloRetryRequest.marshal())
		}
		if err := c.flushHandshake(); err != nil {
			return err
		}

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

		if hs.clientHello.hasEarlyData {
			c.setSkipEarlyData()
		}

		// Read new ClientHello.
		newClientHello, err := readHandshakeType[clientHelloMsg](c)
		if err != nil {
			return err
		}

		if expected := config.Bugs.ExpectOuterServerName; len(expected) != 0 && expected != newClientHello.serverName {
			return fmt.Errorf("tls: unexpected ClientHelloOuter server name: wanted %q, got %q", expected, newClientHello.serverName)
		}

		if c.echAccepted {
			if newClientHello.echOuter == nil {
				c.sendAlert(alertMissingExtension)
				return errors.New("tls: second ClientHelloOuter had no encrypted_client_hello extension")
			}
			if newClientHello.echOuter.configID != hs.echConfigID ||
				newClientHello.echOuter.kdfID != hs.echHPKEContext.KDF() ||
				newClientHello.echOuter.aeadID != hs.echHPKEContext.AEAD() {
				c.sendAlert(alertIllegalParameter)
				return errors.New("tls: ECH parameters changed in second ClientHelloOuter")
			}
			if len(newClientHello.echOuter.enc) != 0 {
				c.sendAlert(alertIllegalParameter)
				return errors.New("tls: second ClientHelloOuter had non-empty ECH enc")
			}
			newClientHello, err = hs.decryptClientHello(newClientHello)
			if err != nil {
				c.sendAlert(alertDecryptError)
				return fmt.Errorf("tls: error decrypting ClientHello: %s", err)
			}
		}

		hs.writeClientHash(newClientHello.marshal())

		if config.Bugs.ExpectNoTLS13PSKAfterHRR && len(newClientHello.pskIdentities) > 0 {
			return fmt.Errorf("tls: client offered unexpected PSK identities after HelloRetryRequest")
		}

		applyBugsToClientHello(newClientHello, config)

		// Check that the new ClientHello matches the old ClientHello,
		// except for relevant modifications. See RFC 8446, section 4.1.2.
		ignoreExtensions := []uint16{extensionPadding}

		if helloRetryRequest.hasSelectedGroup {
			newKeyShares := newClientHello.keyShares
			if len(newKeyShares) != 1 || newKeyShares[0].group != helloRetryRequest.selectedGroup {
				return errors.New("tls: KeyShare from HelloRetryRequest not in new ClientHello")
			}
			selectedKeyShare = &newKeyShares[0]
			ignoreExtensions = append(ignoreExtensions, extensionKeyShare)
		}

		if len(helloRetryRequest.cookie) > 0 {
			if !bytes.Equal(newClientHello.tls13Cookie, helloRetryRequest.cookie) {
				return errors.New("tls: cookie from HelloRetryRequest not present in new ClientHello")
			}
			ignoreExtensions = append(ignoreExtensions, extensionCookie)
		}

		// The second ClientHello refreshes binders, and may drop PSK identities
		// that are no longer consistent with the cipher suite.
		oldPSKIdentities := hs.clientHello.pskIdentities
		for _, identity := range newClientHello.pskIdentities {
			// Skip to the matching PSK identity in oldPSKIdentities.
			for len(oldPSKIdentities) > 0 && !bytes.Equal(oldPSKIdentities[0].ticket, identity.ticket) {
				oldPSKIdentities = oldPSKIdentities[1:]
			}
			// The identity now either matches, or oldPSKIdentities is empty.
			if len(oldPSKIdentities) == 0 {
				return errors.New("tls: unexpected PSK identity in second ClientHello")
			}
			oldPSKIdentities = oldPSKIdentities[1:]
		}
		ignoreExtensions = append(ignoreExtensions, extensionPreSharedKey)

		// Update the index for the identity we resumed. The client may have
		// dropped some entries.
		if psk != nil {
			newIndex := slices.IndexFunc(newClientHello.pskIdentities, func(id pskIdentity) bool { return bytes.Equal(id.ticket, psk.identity) })
			if newIndex >= 0 {
				binderToVerify := newClientHello.pskBinders[newIndex]
				if err := verifyPSKBinder(psk, newClientHello, binderToVerify, hs.clientHello.marshal(), helloRetryRequest.marshal()); err != nil {
					return err
				}
				hs.hello.pskIdentity = uint16(newIndex)
			} else if !config.Bugs.AcceptAnySession {
				// If AcceptAnySession is set, the client may have already noticed
				// the selected session is incompatible with the HelloRetryRequest
				// and correctly dropped the PSK identity. We may also have
				// attempted to resume a session from the TLS 1.2 extension.
				return errors.New("tls: second ClientHello is missing selected session")
			}
		}

		// The second ClientHello must stop offering early data.
		if newClientHello.hasEarlyData {
			return errors.New("tls: EarlyData sent in new ClientHello")
		}
		ignoreExtensions = append(ignoreExtensions, extensionEarlyData)

		if err := checkClientHellosEqual(hs.clientHello.raw, newClientHello.raw, c.isDTLS, ignoreExtensions); err != nil {
			return err
		}

		if config.Bugs.SecondHelloRetryRequest {
			c.writeRecord(recordTypeHandshake, helloRetryRequest.marshal())
			// The peer should reject this. Read from the connection to pick up the alert.
			_, err := c.readHandshake()
			if err != nil {
				return err
			}
			return errors.New("tls: client sent message instead of alert")
		}
	}

	// Decide whether or not to accept early data.
	if !sendHelloRetryRequest && hs.clientHello.hasEarlyData {
		if !config.Bugs.AlwaysRejectEarlyData && hs.sessionState != nil {
			if hs.sessionState.cipherSuite.id == hs.suite.id &&
				c.clientProtocol == string(hs.sessionState.earlyALPN) &&
				c.hasApplicationSettings == hs.sessionState.hasApplicationSettings &&
				bytes.Equal(c.localApplicationSettings, hs.sessionState.localApplicationSettings) &&
				c.hasApplicationSettingsOld == hs.sessionState.hasApplicationSettingsOld &&
				bytes.Equal(c.localApplicationSettingsOld, hs.sessionState.localApplicationSettingsOld) {
				encryptedExtensions.extensions.hasEarlyData = true
			}
			if config.Bugs.AlwaysAcceptEarlyData {
				encryptedExtensions.extensions.hasEarlyData = true
			}
		}
		if encryptedExtensions.extensions.hasEarlyData {
			earlyTrafficSecret := hs.finishedHash.deriveSecret(earlyTrafficLabel)
			c.earlyExporterSecret = hs.finishedHash.deriveSecret(earlyExporterLabel)

			// Applications are implicit with early data.
			if !config.Bugs.SendApplicationSettingsWithEarlyData {
				encryptedExtensions.extensions.hasApplicationSettings = false
				encryptedExtensions.extensions.applicationSettings = nil
				encryptedExtensions.extensions.hasApplicationSettingsOld = false
				encryptedExtensions.extensions.applicationSettingsOld = nil
			}

			if err := c.useInTrafficSecret(uint16(encryptionEarlyData), c.vers, hs.sessionState.cipherSuite, earlyTrafficSecret); err != nil {
				return err
			}

			for _, expectedMsg := range config.Bugs.ExpectEarlyData {
				if err := c.readRecord(recordTypeApplicationData); err != nil {
					return err
				}
				if !bytes.Equal(c.input.Bytes(), expectedMsg) {
					return fmt.Errorf("tls: got early data record %x, wanted %x", c.input.Bytes(), expectedMsg)
				}
				c.input.Reset()
			}
		} else {
			c.setSkipEarlyData()
		}
	}

	if config.Bugs.AlwaysSelectPSKIdentity != nil {
		hs.hello.hasPSKIdentity = true
		hs.hello.pskIdentity = *config.Bugs.AlwaysSelectPSKIdentity
	}

	if config.Bugs.SendEarlyDataExtension {
		encryptedExtensions.extensions.hasEarlyData = true
	}

	// Resolve ECDHE and compute the handshake secret.
	if hs.hello.hasKeyShare {
		// Once a curve has been selected and a key share identified,
		// the server needs to generate a public value and send it in
		// the ServerHello.
		kem, ok := kemForCurveID(selectedCurve, config)
		if !ok {
			panic("tls: server failed to look up curve ID")
		}
		c.curveID = selectedCurve

		var peerKey []byte
		if config.Bugs.SkipHelloRetryRequest {
			// If skipping HelloRetryRequest, use a random key to
			// avoid crashing.
			kem2, _ := kemForCurveID(selectedCurve, config)
			var err error
			peerKey, err = kem2.generate(config)
			if err != nil {
				return err
			}
		} else {
			peerKey = selectedKeyShare.keyExchange
		}

		ciphertext, ecdheSecret, err := kem.encap(config, peerKey)
		if err != nil {
			c.sendAlert(alertHandshakeFailure)
			return err
		}
		hs.finishedHash.nextSecret()
		hs.finishedHash.addEntropy(ecdheSecret)
		hs.hello.hasKeyShare = true

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

		hs.hello.keyShare = keyShareEntry{
			group:       curveID,
			keyExchange: ciphertext,
		}

		if config.Bugs.EncryptedExtensionsWithKeyShare {
			encryptedExtensions.extensions.hasKeyShare = true
			encryptedExtensions.extensions.keyShare = keyShareEntry{
				group:       curveID,
				keyExchange: ciphertext,
			}
		}
	} else if hs.cert.Type == CredentialTypeSPAKE2PlusV1 {
		if len(hs.clientHello.pakeShares) == 0 {
			return errors.New("tls: client not configured with PAKE")
		}
		if !bytes.Equal(hs.clientHello.pakeClientID, hs.cert.PAKEClientID) ||
			!bytes.Equal(hs.clientHello.pakeServerID, hs.cert.PAKEServerID) {
			return fmt.Errorf("tls: client configured with different PAKE identities: got (%x, %x), wanted (%x, %x)", hs.clientHello.pakeClientID, hs.clientHello.pakeServerID, hs.cert.PAKEClientID, hs.cert.PAKEServerID)
		}
		var pakeMessage []byte
		for _, pake := range hs.clientHello.pakeShares {
			if pake.id == spakeID {
				pakeMessage = pake.msg
			}
		}
		if pakeMessage == nil {
			return errors.New("tls: client does not support SPAKE2+")
		}
		w0, _, registrationRecord, err := spake2plus.Register(hs.cert.PAKEPassword, hs.cert.PAKEClientID, hs.cert.PAKEServerID)
		if err != nil {
			return err
		}
		pake, err := spake2plus.NewVerifier(hs.cert.PAKEContext, hs.cert.PAKEClientID, hs.cert.PAKEServerID, w0, registrationRecord)
		if err != nil {
			return err
		}
		share, confirm, sharedSecret, err := pake.ProcessProverShare(pakeMessage)
		if err != nil {
			c.sendAlert(alertHandshakeFailure)
			return fmt.Errorf("while processing SPAKE2+ prover share: %w", err)
		}
		hs.finishedHash.nextSecret()
		hs.finishedHash.addEntropy(sharedSecret)
		hs.hello.pakeID = spakeID
		if hs.cert.OverridePAKECodepoint != 0 {
			hs.hello.pakeID = hs.cert.OverridePAKECodepoint
		}
		hs.hello.pakeMessage = slices.Concat(share, confirm)
		if c.config.Bugs.TruncatePAKEMessage {
			hs.hello.pakeMessage = hs.hello.pakeMessage[:len(hs.hello.pakeMessage)-1]
		}
	} else if config.Bugs.UnsolicitedPAKE != 0 {
		hs.finishedHash.nextSecret()
		hs.finishedHash.addEntropy(hs.finishedHash.zeroSecret())
		hs.hello.pakeID = config.Bugs.UnsolicitedPAKE
		hs.hello.pakeMessage = []byte{1}
	} else {
		hs.finishedHash.nextSecret()
		hs.finishedHash.addEntropy(hs.finishedHash.zeroSecret())
	}

	// Emit the ECH confirmation signal when requested.
	if hs.clientHello.echInner && !config.Bugs.OmitServerHelloECHConfirmation {
		randomSuffix := hs.hello.random[len(hs.hello.random)-echAcceptConfirmationLength:]
		clear(randomSuffix)
		copy(randomSuffix, hs.finishedHash.echAcceptConfirmation(hs.clientHello.random, echAcceptConfirmationLabel, hs.hello.marshal()))
		hs.hello.raw = nil
	}

	// Send unencrypted ServerHello.
	helloBytes := hs.hello.marshal()
	hs.writeServerHash(helloBytes)
	if config.Bugs.PartialServerHelloWithHelloRetryRequest {
		// The first byte has already been written.
		helloBytes = helloBytes[1:]
	}
	if config.Bugs.PartialEncryptedExtensionsWithServerHello {
		c.writeRecord(recordTypeHandshake, append(slices.Clip(helloBytes), typeEncryptedExtensions))
	} else {
		c.writeRecord(recordTypeHandshake, helloBytes)
	}

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

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

	if config.Bugs.UnencryptedEncryptedExtensions {
		c.writeRecord(recordTypeHandshake, encryptedExtensions.marshal())
	}

	// Switch to handshake traffic keys.
	serverHandshakeTrafficSecret := hs.finishedHash.deriveSecret(serverHandshakeTrafficLabel)
	c.useOutTrafficSecret(uint16(encryptionHandshake), c.vers, hs.suite, serverHandshakeTrafficSecret)
	// Derive handshake traffic read key, but don't switch yet.
	clientHandshakeTrafficSecret := hs.finishedHash.deriveSecret(clientHandshakeTrafficLabel)

	// Send EncryptedExtensions.
	hs.writeServerHash(encryptedExtensions.marshal())
	if config.Bugs.PartialEncryptedExtensionsWithServerHello {
		// The first byte has already been sent.
		c.writeRecord(recordTypeHandshake, encryptedExtensions.marshal()[1:])
	} else if !config.Bugs.UnencryptedEncryptedExtensions {
		c.writeRecord(recordTypeHandshake, encryptedExtensions.marshal())
	}

	var requestClientCert bool
	if (psk == nil && hs.cert.Type != CredentialTypeSPAKE2PlusV1) || config.Bugs.AlwaysSendCertificateRequest {
		requestClientCert = config.ClientAuth >= RequestClientCert
	}
	if requestClientCert {
		// Request a client certificate
		certReq := &certificateRequestMsg{
			hasSignatureAlgorithm: !config.Bugs.OmitCertificateRequestAlgorithms,
			hasRequestContext:     true,
			requestContext:        config.Bugs.SendRequestContext,
			customExtension:       config.Bugs.SendCustomCertificateRequest,
		}
		if !config.Bugs.NoSignatureAlgorithms {
			certReq.signatureAlgorithms = config.verifySignatureAlgorithms()
		}

		// An empty list of certificateAuthorities signals to
		// the client that it may send any certificate in response
		// to our request. When we know the CAs we trust, then
		// we can send them down, so that the client can choose
		// an appropriate certificate to give to us.
		if config.ClientCAs != nil {
			certReq.certificateAuthorities = config.ClientCAs.Subjects()
		}
		hs.writeServerHash(certReq.marshal())
		c.writeRecord(recordTypeHandshake, certReq.marshal())
	}

	if (psk == nil && hs.cert.Type != CredentialTypeSPAKE2PlusV1) || config.Bugs.AlwaysSendCertificate {
		useCert := hs.cert
		if config.Bugs.UseCertificateCredential != nil {
			useCert = config.Bugs.UseCertificateCredential
		}
		certMsg := &certificateMsg{
			hasRequestContext: true,
		}
		certMsg.sendTrustAnchorWrongCertificate = config.Bugs.SendTrustAnchorWrongCertificate
		certMsg.sendNonEmptyTrustAnchorMatch = config.Bugs.SendNonEmptyTrustAnchorMatch
		if config.Bugs.AlwaysMatchTrustAnchorID {
			certMsg.matchedTrustAnchor = true
		} else {
			if hs.clientHello.trustAnchors != nil && useCert.TrustAnchorID != nil {
				for _, id := range hs.clientHello.trustAnchors {
					if bytes.Equal(useCert.TrustAnchorID, id) {
						certMsg.matchedTrustAnchor = true
					}
				}
			}
		}
		if !config.Bugs.EmptyCertificateList {
			for i, certData := range useCert.Certificate {
				cert := certificateEntry{
					data: certData,
				}
				if i == 0 {
					if hs.clientHello.ocspStapling && !c.config.Bugs.NoOCSPStapling {
						cert.ocspResponse = useCert.OCSPStaple
					}
					if hs.clientHello.sctListSupported && !c.config.Bugs.NoSignedCertificateTimestamps {
						cert.sctList = useCert.SignedCertificateTimestampList
					}
					cert.duplicateExtensions = config.Bugs.SendDuplicateCertExtensions
					cert.extraExtension = config.Bugs.SendExtensionOnCertificate
				} else {
					if config.Bugs.SendOCSPOnIntermediates != nil {
						cert.ocspResponse = config.Bugs.SendOCSPOnIntermediates
					}
					if config.Bugs.SendSCTOnIntermediates != nil {
						cert.sctList = config.Bugs.SendSCTOnIntermediates
					}
				}
				certMsg.certificates = append(certMsg.certificates, cert)
			}
		}
		certMsgBytes := certMsg.marshal()
		sentCompressedCertMsg := false

		for id, alg := range c.config.CertCompressionAlgs {
			if slices.Contains(hs.clientHello.compressedCertAlgs, id) {
				if expected := config.Bugs.ExpectedCompressedCert; expected != 0 && expected != id {
					return fmt.Errorf("tls: expected to send compressed cert with alg %d, but picked %d", expected, id)
				}
				if config.Bugs.ExpectUncompressedCert {
					return errors.New("tls: expected to send uncompressed cert")
				}

				if override := config.Bugs.SendCertCompressionAlgID; override != 0 {
					id = override
				}

				uncompressed := certMsgBytes[4:]
				uncompressedLen := uint32(len(uncompressed))
				if override := config.Bugs.SendCertUncompressedLength; override != 0 {
					uncompressedLen = override
				}

				compressedCertMsgBytes := (&compressedCertificateMsg{
					algID:              id,
					uncompressedLength: uncompressedLen,
					compressed:         alg.Compress(uncompressed),
				}).marshal()

				hs.writeServerHash(compressedCertMsgBytes)
				c.writeRecord(recordTypeHandshake, compressedCertMsgBytes)
				sentCompressedCertMsg = true
				break
			}
		}

		if !sentCompressedCertMsg {
			if config.Bugs.ExpectedCompressedCert != 0 {
				return errors.New("tls: unexpectedly sent uncompressed certificate")
			}
			hs.writeServerHash(certMsgBytes)
			c.writeRecord(recordTypeHandshake, certMsgBytes)
		}

		certVerify := &certificateVerifyMsg{
			hasSignatureAlgorithm: true,
		}

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

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

		if config.Bugs.SendSignatureAlgorithm != 0 {
			certVerify.signatureAlgorithm = config.Bugs.SendSignatureAlgorithm
		}

		if !config.Bugs.SkipCertificateVerify {
			hs.writeServerHash(certVerify.marshal())
			c.writeRecord(recordTypeHandshake, certVerify.marshal())
		}
	} else if hs.sessionState != nil {
		// Pick up certificates from the session instead.
		if len(hs.sessionState.certificates) > 0 {
			if _, err := hs.processCertsFromClient(hs.sessionState.certificates); err != nil {
				return err
			}
		}
	}

	finished := new(finishedMsg)
	finished.verifyData = hs.finishedHash.serverSum(serverHandshakeTrafficSecret)
	if config.Bugs.BadFinished {
		finished.verifyData[0]++
	}
	hs.writeServerHash(finished.marshal())
	c.writeRecord(recordTypeHandshake, finished.marshal())
	if c.config.Bugs.SendExtraFinished {
		c.writeRecord(recordTypeHandshake, finished.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(hs.finishedHash.zeroSecret())

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

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

	// Switch to application data keys on write. In particular, any alerts
	// from the client certificate are sent over these keys.
	c.useOutTrafficSecret(uint16(encryptionApplication), c.vers, hs.suite, serverTrafficSecret)

	// In TLS, we need to consume EndOfEarlyData, and also test early data that
	// was only partially written while reading the ServerHello. Both of these
	// require flushing ServerHello first. Neither of these apply to DTLS, where
	// we need to flush after installing handshake keys.
	if encryptedExtensions.extensions.hasEarlyData && !c.isDTLS {
		if err := c.flushHandshake(); err != nil {
			return err
		}
		for _, expectedMsg := range config.Bugs.ExpectLateEarlyData {
			if err := c.readRecord(recordTypeApplicationData); err != nil {
				return err
			}
			if !bytes.Equal(c.input.Bytes(), expectedMsg) {
				return fmt.Errorf("tls: got late early data record %x, wanted %x", c.input.Bytes(), expectedMsg)
			}
			c.input.Reset()
		}
		if c.usesEndOfEarlyData() {
			endOfEarlyData, err := readHandshakeType[endOfEarlyDataMsg](c)
			if err != nil {
				return err
			}
			hs.writeClientHash(endOfEarlyData.marshal())
		}
	}

	// Switch input stream to handshake traffic keys.
	if err := c.useInTrafficSecret(uint16(encryptionHandshake), c.vers, hs.suite, clientHandshakeTrafficSecret); err != nil {
		return err
	}

	// DTLS testing requires this flush occur after installing handshake keys,
	// so that we can process ACKs.
	if err := c.flushHandshake(); err != nil {
		return err
	}

	// If we sent an ALPS extension, the client must respond with a single EncryptedExtensions.
	if encryptedExtensions.extensions.hasApplicationSettings || encryptedExtensions.extensions.hasApplicationSettingsOld {
		clientEncryptedExtensions, err := readHandshakeType[clientEncryptedExtensionsMsg](c)
		if err != nil {
			return err
		}
		hs.writeClientHash(clientEncryptedExtensions.marshal())

		// Expect client send new application settings not old.
		if encryptedExtensions.extensions.hasApplicationSettings {
			if !clientEncryptedExtensions.hasApplicationSettings {
				c.sendAlert(alertMissingExtension)
				return errors.New("tls: client didn't provide new application settings")
			}
			if clientEncryptedExtensions.hasApplicationSettingsOld {
				c.sendAlert(alertUnsupportedExtension)
				return errors.New("tls: client shouldn't provide old application settings")
			}
			c.peerApplicationSettings = clientEncryptedExtensions.applicationSettings
		}

		// Expect client send old application settings not new.
		if encryptedExtensions.extensions.hasApplicationSettingsOld {
			if !clientEncryptedExtensions.hasApplicationSettingsOld {
				c.sendAlert(alertMissingExtension)
				return errors.New("tls: client didn't provide old application settings")
			}
			if clientEncryptedExtensions.hasApplicationSettings {
				c.sendAlert(alertUnsupportedExtension)
				return errors.New("tls: client shouldn't provide new application settings")
			}
			c.peerApplicationSettingsOld = clientEncryptedExtensions.applicationSettingsOld
		}
	} else if encryptedExtensions.extensions.hasEarlyData {
		// 0-RTT sessions carry application settings over.
		c.peerApplicationSettings = hs.sessionState.peerApplicationSettings
		c.peerApplicationSettingsOld = hs.sessionState.peerApplicationSettingsOld
	}

	// If we requested a client certificate, then the client must send a
	// certificate message, even if it's empty.
	if requestClientCert {
		certMsg, err := readHandshakeType[certificateMsg](c)
		if err != nil {
			return err
		}
		hs.writeClientHash(certMsg.marshal())

		if len(certMsg.certificates) == 0 {
			// The client didn't actually send a certificate
			switch config.ClientAuth {
			case RequireAnyClientCert, RequireAndVerifyClientCert:
				c.sendAlert(alertCertificateRequired)
				return errors.New("tls: client didn't provide a certificate")
			}
		}

		var certs [][]byte
		for _, cert := range certMsg.certificates {
			certs = append(certs, cert.data)
			// OCSP responses and SCT lists are not negotiated in
			// client certificates.
			if cert.ocspResponse != nil || cert.sctList != nil {
				c.sendAlert(alertUnsupportedExtension)
				return errors.New("tls: unexpected extensions in the client certificate")
			}
		}
		pub, err := hs.processCertsFromClient(certs)
		if err != nil {
			return err
		}

		if len(c.peerCertificates) > 0 {
			certVerify, err := readHandshakeType[certificateVerifyMsg](c)
			if err != nil {
				return err
			}
			c.peerSignatureAlgorithm = certVerify.signatureAlgorithm
			input := hs.finishedHash.certificateVerifyInput(clientCertificateVerifyContextTLS13)
			if err := verifyMessage(c.isClient, c.vers, pub, config, certVerify.signatureAlgorithm, input, certVerify.signature); err != nil {
				c.sendAlert(alertBadCertificate)
				return err
			}
			hs.writeClientHash(certVerify.marshal())
		}
	}

	if encryptedExtensions.extensions.channelIDRequested {
		channelIDMsg, err := readHandshakeType[channelIDMsg](c)
		if err != nil {
			return err
		}
		channelIDHash := crypto.SHA256.New()
		channelIDHash.Write(hs.finishedHash.certificateVerifyInput(channelIDContextTLS13))
		channelID, err := verifyChannelIDMessage(channelIDMsg, channelIDHash.Sum(nil))
		if err != nil {
			return err
		}
		c.channelID = channelID

		hs.writeClientHash(channelIDMsg.marshal())
	}

	// Read the client Finished message.
	clientFinished, err := readHandshakeType[finishedMsg](c)
	if err != nil {
		return err
	}
	verify := hs.finishedHash.clientSum(clientHandshakeTrafficSecret)
	if len(verify) != len(clientFinished.verifyData) ||
		subtle.ConstantTimeCompare(verify, clientFinished.verifyData) != 1 {
		c.sendAlert(alertHandshakeFailure)
		return errors.New("tls: client's Finished message was incorrect")
	}
	hs.writeClientHash(clientFinished.marshal())

	// Switch to application data keys on read.
	if err := c.useInTrafficSecret(uint16(encryptionApplication), c.vers, hs.suite, clientTrafficSecret); err != nil {
		return err
	}

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

	c.cipherSuite = hs.suite
	c.resumptionSecret = hs.finishedHash.deriveSecret(resumptionLabel)

	// TODO(davidben): Allow configuring the number of tickets sent for
	// testing.
	if !c.config.SessionTicketsDisabled && foundKEMode {
		ticketCount := 2
		for i := range ticketCount {
			c.SendNewSessionTicket([]byte{byte(i)})
		}
		if err := c.flushHandshake(); err != nil {
			return err
		}
	}
	return nil
}

// processClientHello processes the ClientHello message from the client and
// decides whether we will perform session resumption.
func (hs *serverHandshakeState) processClientHello() (isResume bool, err error) {
	config := hs.c.config
	c := hs.c

	hs.hello = &serverHelloMsg{
		isDTLS:            c.isDTLS,
		vers:              c.vers.wire,
		versOverride:      config.Bugs.SendServerHelloVersion,
		compressionMethod: config.Bugs.SendCompressionMethod,
		extensions: serverExtensions{
			supportedVersion: config.Bugs.SendServerSupportedVersionExtension,
		},
		omitExtensions:  config.Bugs.OmitExtensions,
		emptyExtensions: config.Bugs.EmptyExtensions,
	}

	hs.hello.random = make([]byte, 32)
	_, err = io.ReadFull(config.rand(), hs.hello.random)
	if err != nil {
		c.sendAlert(alertInternalError)
		return false, err
	}

	_, supportsTLS13 := c.config.isSupportedVersion(VersionTLS13, false)

	// Signal downgrades in the server random, per RFC 8446, section 4.1.3.
	if supportsTLS13 || config.Bugs.SendTLS13DowngradeRandom {
		if c.vers.protocolVersion() <= VersionTLS12 && config.maxVersion() >= VersionTLS13 {
			copy(hs.hello.random[len(hs.hello.random)-8:], downgradeTLS13)
		}
		if c.vers.protocolVersion() <= VersionTLS11 && config.maxVersion() == VersionTLS12 {
			copy(hs.hello.random[len(hs.hello.random)-8:], downgradeTLS12)
		}
	}
	if config.Bugs.SendJDK11DowngradeRandom {
		copy(hs.hello.random[len(hs.hello.random)-8:], downgradeJDK11)
	}

	// We only support null compression, so check that the client offered it.
	if !slices.Contains(hs.clientHello.compressionMethods, compressionNone) {
		c.sendAlert(alertHandshakeFailure)
		return false, errors.New("tls: client does not support uncompressed connections")
	}

	if err := hs.processClientExtensions(&hs.hello.extensions); err != nil {
		return false, err
	}

	supportedCurve := false
	preferredCurves := config.curvePreferences()
	for _, curve := range hs.clientHello.supportedCurves {
		if isPqGroup(curve) && c.vers.protocolVersion() < VersionTLS13 {
			// Post-quantum is TLS 1.3 only.
			continue
		}

		if slices.Contains(preferredCurves, curve) {
			supportedCurve = true
			break
		}
	}

	supportedPointFormat := slices.Contains(hs.clientHello.supportedPoints, pointFormatUncompressed)
	hs.ellipticOk = supportedCurve && supportedPointFormat

	_, hs.ecdsaOk = hs.cert.PrivateKey.(*ecdsa.PrivateKey)
	// Ed25519 also uses ECDSA certificates.
	_, ed25519Ok := hs.cert.PrivateKey.(ed25519.PrivateKey)
	hs.ecdsaOk = hs.ecdsaOk || ed25519Ok

	// For test purposes, check that the peer never offers a session when
	// renegotiating.
	if c.cipherSuite != nil && len(hs.clientHello.sessionID) > 0 && c.config.Bugs.FailIfResumeOnRenego {
		return false, errors.New("tls: offered resumption on renegotiation")
	}

	if hs.checkForResumption() {
		return true, nil
	}

	var preferenceList, supportedList []uint16
	if c.config.PreferServerCipherSuites {
		preferenceList = c.config.cipherSuites()
		supportedList = hs.clientHello.cipherSuites
	} else {
		preferenceList = hs.clientHello.cipherSuites
		supportedList = c.config.cipherSuites()
	}

	for _, id := range preferenceList {
		if hs.suite = c.tryCipherSuite(id, supportedList, c.vers, hs.ellipticOk, hs.ecdsaOk); hs.suite != nil {
			break
		}
	}

	if hs.suite == nil {
		c.sendAlert(alertHandshakeFailure)
		return false, errors.New("tls: no cipher suite supported by both client and server")
	}

	return false, nil
}

// processClientExtensions processes all ClientHello extensions not directly
// related to cipher suite negotiation and writes responses in serverExtensions.
func (hs *serverHandshakeState) processClientExtensions(serverExtensions *serverExtensions) error {
	config := hs.c.config
	c := hs.c

	if c.vers.protocolVersion() < VersionTLS13 || config.Bugs.NegotiateRenegotiationInfoAtAllVersions {
		if !bytes.Equal(c.clientVerify, hs.clientHello.secureRenegotiation) {
			c.sendAlert(alertHandshakeFailure)
			return errors.New("tls: renegotiation mismatch")
		}

		if len(c.clientVerify) > 0 && !c.config.Bugs.EmptyRenegotiationInfo {
			serverExtensions.secureRenegotiation = append(serverExtensions.secureRenegotiation, c.clientVerify...)
			serverExtensions.secureRenegotiation = append(serverExtensions.secureRenegotiation, c.serverVerify...)
			if c.config.Bugs.BadRenegotiationInfo {
				serverExtensions.secureRenegotiation[0] ^= 0x80
			}
			if c.config.Bugs.BadRenegotiationInfoEnd {
				serverExtensions.secureRenegotiation[len(serverExtensions.secureRenegotiation)-1] ^= 0x80
			}
		} else {
			serverExtensions.secureRenegotiation = hs.clientHello.secureRenegotiation
		}

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

	serverExtensions.duplicateExtension = c.config.Bugs.DuplicateExtension

	if len(hs.clientHello.serverName) > 0 {
		c.serverName = hs.clientHello.serverName
	}
	if config.Credential == nil {
		c.sendAlert(alertInternalError)
		return errors.New("tls: no certificates configured")
	}
	hs.cert = config.Credential
	if expected := c.config.Bugs.ExpectServerName; expected != "" && expected != hs.clientHello.serverName {
		return fmt.Errorf("tls: unexpected server name: wanted %q, got %q", expected, hs.clientHello.serverName)
	}

	if cert := config.Bugs.RenegotiationCertificate; c.cipherSuite != nil && cert != nil {
		hs.cert = cert
	}

	if len(hs.clientHello.alpnProtocols) > 0 {
		// We will never offer ALPN as a client on renegotiation
		// handshakes.
		if len(c.clientVerify) > 0 {
			return errors.New("tls: offered ALPN on renegotiation")
		}
		if proto := c.config.Bugs.ALPNProtocol; proto != nil {
			serverExtensions.alpnProtocol = *proto
			serverExtensions.alpnProtocolEmpty = len(*proto) == 0
			c.clientProtocol = *proto
			c.usedALPN = true
		} else if selectedProto, fallback := mutualProtocol(hs.clientHello.alpnProtocols, c.config.NextProtos); !fallback {
			serverExtensions.alpnProtocol = selectedProto
			c.clientProtocol = selectedProto
			c.usedALPN = true
		}

		var alpsAllowed, alpsAllowedOld bool
		if c.vers.protocolVersion() >= VersionTLS13 {
			alpsAllowed = slices.Contains(hs.clientHello.alpsProtocols, c.clientProtocol)
			alpsAllowedOld = slices.Contains(hs.clientHello.alpsProtocolsOld, c.clientProtocol)
		}

		if c.config.Bugs.AlwaysNegotiateApplicationSettingsBoth {
			alpsAllowed = true
			alpsAllowedOld = true
		}
		if c.config.Bugs.AlwaysNegotiateApplicationSettingsNew {
			alpsAllowed = true
		}
		if c.config.Bugs.AlwaysNegotiateApplicationSettingsOld {
			alpsAllowedOld = true
		}
		if settings, ok := c.config.ApplicationSettings[c.clientProtocol]; ok && alpsAllowed {
			c.hasApplicationSettings = true
			c.localApplicationSettings = settings
			// Note these fields may later be cleared we accept 0-RTT.
			serverExtensions.hasApplicationSettings = true
			serverExtensions.applicationSettings = settings
		}
		if settings, ok := c.config.ApplicationSettings[c.clientProtocol]; ok && alpsAllowedOld {
			c.hasApplicationSettingsOld = true
			c.localApplicationSettingsOld = settings
			// Note these fields may later be cleared we accept 0-RTT.
			serverExtensions.hasApplicationSettingsOld = true
			serverExtensions.applicationSettingsOld = settings
		}
	}

	if len(c.config.Bugs.SendALPN) > 0 {
		serverExtensions.alpnProtocol = c.config.Bugs.SendALPN
	}

	if c.vers.protocolVersion() < VersionTLS13 || config.Bugs.NegotiateNPNAtAllVersions {
		if len(hs.clientHello.alpnProtocols) == 0 || c.config.Bugs.NegotiateALPNAndNPN {
			if hs.clientHello.nextProtoNeg && (len(config.NextProtos) > 0 || config.NegotiateNPNWithNoProtos) {
				serverExtensions.nextProtoNeg = true
				serverExtensions.nextProtos = config.NextProtos
				serverExtensions.npnAfterAlpn = config.Bugs.SwapNPNAndALPN
			}
		}
	}

	if len(hs.clientHello.quicTransportParams) > 0 {
		c.quicTransportParams = hs.clientHello.quicTransportParams
	}
	if c.config.QUICTransportParamsUseLegacyCodepoint.IncludeStandard() {
		serverExtensions.quicTransportParams = c.config.QUICTransportParams
	}

	if len(hs.clientHello.quicTransportParamsLegacy) > 0 {
		c.quicTransportParamsLegacy = hs.clientHello.quicTransportParamsLegacy
	}
	if c.config.QUICTransportParamsUseLegacyCodepoint.IncludeLegacy() {
		serverExtensions.quicTransportParamsLegacy = c.config.QUICTransportParams
	}

	if c.vers.protocolVersion() < VersionTLS13 || config.Bugs.NegotiateEMSAtAllVersions {
		disableEMS := config.Bugs.NoExtendedMasterSecret
		if c.cipherSuite != nil {
			disableEMS = config.Bugs.NoExtendedMasterSecretOnRenegotiation
		}
		serverExtensions.extendedMasterSecret = hs.clientHello.extendedMasterSecret && !disableEMS
	}

	if config.Bugs.AlwaysNegotiateChannelID || (hs.clientHello.channelIDSupported && config.RequestChannelID) {
		serverExtensions.channelIDRequested = true
	}

	if hs.clientHello.srtpProtectionProfiles != nil {
		for _, p := range c.config.SRTPProtectionProfiles {
			if slices.Contains(hs.clientHello.srtpProtectionProfiles, p) {
				serverExtensions.srtpProtectionProfile = p
				c.srtpProtectionProfile = p
				break
			}
		}
	}

	if c.config.Bugs.SendSRTPProtectionProfile != 0 {
		serverExtensions.srtpProtectionProfile = c.config.Bugs.SendSRTPProtectionProfile
	}

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

	if c.config.Bugs.AdvertiseTicketExtension {
		serverExtensions.ticketSupported = true
	}

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

	if c.config.Bugs.SendServerSupportedCurves {
		serverExtensions.supportedCurves = c.config.curvePreferences()
	}

	if !hs.clientHello.hasGREASEExtension && config.Bugs.ExpectGREASE {
		return errors.New("tls: no GREASE extension found")
	}

	if hs.clientHello.trustAnchors != nil || config.Bugs.AlwaysSendAvailableTrustAnchors {
		serverExtensions.trustAnchors = c.config.AvailableTrustAnchors
	}
	serverExtensions.serverNameAck = c.config.Bugs.SendServerNameAck

	if (c.vers.protocolVersion() >= VersionTLS13 && hs.clientHello.echOuter != nil) || c.config.Bugs.AlwaysSendECHRetryConfigs {
		if len(config.Bugs.SendECHRetryConfigs) > 0 {
			serverExtensions.echRetryConfigs = config.Bugs.SendECHRetryConfigs
		} else if len(config.ServerECHConfigs) > 0 {
			echConfigs := make([][]byte, len(config.ServerECHConfigs))
			for i, echConfig := range config.ServerECHConfigs {
				echConfigs[i] = echConfig.ECHConfig.Raw
			}
			serverExtensions.echRetryConfigs = CreateECHConfigList(echConfigs...)
		}
	}

	return nil
}

// checkForResumption returns true if we should perform resumption on this connection.
func (hs *serverHandshakeState) checkForResumption() bool {
	c := hs.c

	ticket := hs.clientHello.sessionTicket
	if len(ticket) == 0 && len(hs.clientHello.pskIdentities) > 0 && c.config.Bugs.AcceptAnySession {
		ticket = hs.clientHello.pskIdentities[0].ticket
	}
	if len(ticket) > 0 {
		if c.config.SessionTicketsDisabled {
			return false
		}

		var ok bool
		if hs.sessionState, ok = c.decryptTicket(ticket); !ok {
			return false
		}
	} else {
		if c.config.ServerSessionCache == nil {
			return false
		}

		var ok bool
		sessionID := string(hs.clientHello.sessionID)
		if hs.sessionState, ok = c.config.ServerSessionCache.Get(sessionID); !ok {
			return false
		}
	}

	if c.config.Bugs.AcceptAnySession {
		// Replace the cipher suite with one known to work, to test
		// cross-version resumption attempts.
		hs.sessionState.cipherSuite = cipherSuiteFromID(TLS_RSA_WITH_AES_128_CBC_SHA)
	} else {
		// Never resume a session for a different SSL version, and check
		// that the client is still offering the ciphersuite in the session.
		if c.vers != hs.sessionState.vers ||
			!slices.Contains(hs.clientHello.cipherSuites, hs.sessionState.cipherSuite.id) {
			return false
		}
	}

	// Check that we also support the ciphersuite from the session.
	hs.suite = c.tryCipherSuite(hs.sessionState.cipherSuite.id, c.config.cipherSuites(), c.vers, hs.ellipticOk, hs.ecdsaOk)

	if hs.suite == nil {
		return false
	}

	sessionHasClientCerts := len(hs.sessionState.certificates) != 0
	needClientCerts := c.config.ClientAuth == RequireAnyClientCert || c.config.ClientAuth == RequireAndVerifyClientCert
	if needClientCerts && !sessionHasClientCerts {
		return false
	}
	if sessionHasClientCerts && c.config.ClientAuth == NoClientCert {
		return false
	}

	return true
}

func (hs *serverHandshakeState) doResumeHandshake() error {
	c := hs.c

	hs.hello.cipherSuite = hs.suite.id
	if c.config.Bugs.SendCipherSuite != 0 {
		hs.hello.cipherSuite = c.config.Bugs.SendCipherSuite
	}
	// We echo the client's session ID in the ServerHello to let it know
	// that we're doing a resumption.
	hs.hello.sessionID = hs.clientHello.sessionID
	hs.hello.extensions.ticketSupported = c.config.Bugs.RenewTicketOnResume

	if c.config.Bugs.SendSCTListOnResume != nil {
		hs.hello.extensions.sctList = c.config.Bugs.SendSCTListOnResume
	}

	if c.config.Bugs.SendOCSPResponseOnResume != nil {
		// There is no way, syntactically, to send an OCSP response on a
		// resumption handshake.
		hs.hello.extensions.ocspStapling = true
	}

	hs.finishedHash = newFinishedHash(c.vers, hs.suite.hash())
	hs.finishedHash.discardHandshakeBuffer()
	hs.writeClientHash(hs.clientHello.marshal())
	hs.writeServerHash(hs.hello.marshal())

	c.writeRecord(recordTypeHandshake, hs.hello.marshal())

	if len(hs.sessionState.certificates) > 0 {
		if _, err := hs.processCertsFromClient(hs.sessionState.certificates); err != nil {
			return err
		}
	}

	hs.masterSecret = hs.sessionState.secret
	c.extendedMasterSecret = hs.sessionState.extendedMasterSecret

	return nil
}

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

	isPSK := hs.suite.flags&suitePSK != 0
	if !isPSK && hs.clientHello.ocspStapling && hs.cert.OCSPStaple != nil && !c.config.Bugs.NoOCSPStapling {
		hs.hello.extensions.ocspStapling = true
	}

	if hs.clientHello.sctListSupported && len(hs.cert.SignedCertificateTimestampList) > 0 && !c.config.Bugs.NoSignedCertificateTimestamps {
		hs.hello.extensions.sctList = hs.cert.SignedCertificateTimestampList
	}

	if len(c.clientVerify) > 0 && config.Bugs.SendSCTListOnRenegotiation != nil {
		hs.hello.extensions.sctList = config.Bugs.SendSCTListOnRenegotiation
	}

	hs.hello.extensions.ticketSupported = hs.clientHello.ticketSupported && !config.SessionTicketsDisabled
	hs.hello.cipherSuite = hs.suite.id
	if config.Bugs.SendCipherSuite != 0 {
		hs.hello.cipherSuite = config.Bugs.SendCipherSuite
	}
	c.extendedMasterSecret = hs.hello.extensions.extendedMasterSecret

	// Generate a session ID if we're to save the session.
	if !hs.hello.extensions.ticketSupported && config.ServerSessionCache != nil {
		l := config.Bugs.NewSessionIDLength
		if l == 0 {
			l = 32
		}
		hs.hello.sessionID = make([]byte, l)
		if _, err := io.ReadFull(config.rand(), hs.hello.sessionID); err != nil {
			c.sendAlert(alertInternalError)
			return errors.New("tls: short read from Rand: " + err.Error())
		}
	}
	if config.Bugs.EchoSessionIDInFullHandshake {
		hs.hello.sessionID = hs.clientHello.sessionID
	}

	hs.finishedHash = newFinishedHash(c.vers, hs.suite.hash())
	hs.writeClientHash(hs.clientHello.marshal())
	hs.writeServerHash(hs.hello.marshal())

	if config.Bugs.SendSNIWarningAlert {
		c.SendAlert(alertLevelWarning, alertUnrecognizedName)
	}

	c.writeRecord(recordTypeHandshake, hs.hello.marshal())

	if !isPSK {
		certMsg := new(certificateMsg)
		if !config.Bugs.EmptyCertificateList {
			for _, certData := range hs.cert.Certificate {
				certMsg.certificates = append(certMsg.certificates, certificateEntry{
					data: certData,
				})
			}
		}
		if !config.Bugs.UnauthenticatedECDH {
			certMsgBytes := certMsg.marshal()
			hs.writeServerHash(certMsgBytes)
			c.writeRecord(recordTypeHandshake, certMsgBytes)
		}
	}

	if hs.hello.extensions.ocspStapling && !c.config.Bugs.SkipCertificateStatus {
		certStatus := new(certificateStatusMsg)
		certStatus.statusType = statusTypeOCSP
		certStatus.response = hs.cert.OCSPStaple
		if len(c.clientVerify) > 0 && config.Bugs.SendOCSPResponseOnRenegotiation != nil {
			certStatus.response = config.Bugs.SendOCSPResponseOnRenegotiation
		}
		hs.writeServerHash(certStatus.marshal())
		c.writeRecord(recordTypeHandshake, certStatus.marshal())
	}

	keyAgreement := hs.suite.ka(c.vers)
	skx, err := keyAgreement.generateServerKeyExchange(config, hs.cert, hs.clientHello, hs.hello)
	if err != nil {
		c.sendAlert(alertHandshakeFailure)
		return err
	}
	if ecdhe, ok := keyAgreement.(*ecdheKeyAgreement); ok {
		c.curveID = ecdhe.curveID
	}
	if skx != nil && !config.Bugs.SkipServerKeyExchange {
		hs.writeServerHash(skx.marshal())
		c.writeRecord(recordTypeHandshake, skx.marshal())
	}

	if config.ClientAuth >= RequestClientCert {
		// Request a client certificate
		certReq := &certificateRequestMsg{
			certificateTypes: config.ClientCertificateTypes,
		}
		if certReq.certificateTypes == nil {
			certReq.certificateTypes = []byte{CertTypeRSASign, CertTypeECDSASign}
		}
		if c.vers.protocolVersion() >= VersionTLS12 {
			certReq.hasSignatureAlgorithm = true
			if !config.Bugs.NoSignatureAlgorithms {
				certReq.signatureAlgorithms = config.verifySignatureAlgorithms()
			}
		}

		// An empty list of certificateAuthorities signals to
		// the client that it may send any certificate in response
		// to our request. When we know the CAs we trust, then
		// we can send them down, so that the client can choose
		// an appropriate certificate to give to us.
		if config.ClientCAs != nil {
			certReq.certificateAuthorities = config.ClientCAs.Subjects()
		}
		hs.writeServerHash(certReq.marshal())
		c.writeRecord(recordTypeHandshake, certReq.marshal())
	}

	helloDone := new(serverHelloDoneMsg)
	helloDoneBytes := helloDone.marshal()
	hs.writeServerHash(helloDoneBytes)
	var toAppend byte
	if config.Bugs.PartialNewSessionTicketWithServerHelloDone {
		toAppend = typeNewSessionTicket
	} else if config.Bugs.PartialFinishedWithServerHelloDone {
		toAppend = typeFinished
	}
	if toAppend != 0 {
		c.writeRecord(recordTypeHandshake, append(slices.Clip(helloDoneBytes), toAppend))
	} else {
		c.writeRecord(recordTypeHandshake, helloDoneBytes)
	}
	if err := c.flushHandshake(); err != nil {
		return err
	}

	var pub crypto.PublicKey // public key for client auth, if any

	// If we requested a client certificate, then the client must send a
	// certificate message, even if it's empty.
	if config.ClientAuth >= RequestClientCert {
		certMsg, err := readHandshakeType[certificateMsg](c)
		if err != nil {
			return err
		}
		hs.writeClientHash(certMsg.marshal())

		if len(certMsg.certificates) == 0 {
			// The client didn't actually send a certificate
			switch config.ClientAuth {
			case RequireAnyClientCert, RequireAndVerifyClientCert:
				c.sendAlert(alertBadCertificate)
				return errors.New("tls: client didn't provide a certificate")
			}
		}

		var certificates [][]byte
		for _, cert := range certMsg.certificates {
			certificates = append(certificates, cert.data)
		}

		pub, err = hs.processCertsFromClient(certificates)
		if err != nil {
			return err
		}
	}

	// Get client key exchange
	ckx, err := readHandshakeType[clientKeyExchangeMsg](c)
	if err != nil {
		return err
	}
	hs.writeClientHash(ckx.marshal())

	preMasterSecret, err := keyAgreement.processClientKeyExchange(config, hs.cert, ckx)
	if err != nil {
		c.sendAlert(alertHandshakeFailure)
		return err
	}
	if c.extendedMasterSecret {
		hs.masterSecret = extendedMasterFromPreMasterSecret(c.vers, hs.suite, preMasterSecret, hs.finishedHash)
	} 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.clientHello.random, hs.hello.random)
	}

	// If we received a client cert in response to our certificate request message,
	// the client will send us a certificateVerifyMsg immediately after the
	// clientKeyExchangeMsg.  This message is a digest of all preceding
	// handshake-layer messages that is signed using the private key corresponding
	// to the client's certificate. This allows us to verify that the client is in
	// possession of the private key of the certificate.
	if len(c.peerCertificates) > 0 {
		certVerify, err := readHandshakeType[certificateVerifyMsg](c)
		if err != nil {
			return err
		}

		// Determine the signature type.
		var sigAlg signatureAlgorithm
		if certVerify.hasSignatureAlgorithm {
			sigAlg = certVerify.signatureAlgorithm
			c.peerSignatureAlgorithm = sigAlg
		}

		if err := verifyMessage(c.isClient, c.vers, pub, c.config, sigAlg, hs.finishedHash.buffer, certVerify.signature); err != nil {
			c.sendAlert(alertBadCertificate)
			return errors.New("could not validate signature of connection nonces: " + err.Error())
		}

		hs.writeClientHash(certVerify.marshal())
	}

	hs.finishedHash.discardHandshakeBuffer()

	return nil
}

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

	clientMAC, serverMAC, clientKey, serverKey, clientIV, serverIV := keysFromMasterSecret(c.vers, hs.suite, hs.masterSecret, hs.clientHello.random, hs.hello.random, hs.suite.macLen, hs.suite.keyLen, hs.suite.ivLen(c.vers))

	var clientCipher, serverCipher any
	var clientHash, serverHash macFunction

	if hs.suite.aead == nil {
		clientCipher = hs.suite.cipher(clientKey, clientIV, true /* for reading */)
		clientHash = hs.suite.mac(c.vers, clientMAC)
		serverCipher = hs.suite.cipher(serverKey, serverIV, false /* not 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, clientCipher, clientHash)
	c.out.prepareCipherSpec(c.vers, serverCipher, serverHash)

	return nil
}

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

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

	if hs.hello.extensions.nextProtoNeg {
		nextProto, err := readHandshakeType[nextProtoMsg](c)
		if err != nil {
			return err
		}
		hs.writeClientHash(nextProto.marshal())
		c.clientProtocol = nextProto.proto
	}

	if hs.hello.extensions.channelIDRequested {
		channelIDMsg, err := readHandshakeType[channelIDMsg](c)
		if err != nil {
			return err
		}
		var resumeHash []byte
		if isResume {
			resumeHash = hs.sessionState.handshakeHash
		}
		channelID, err := verifyChannelIDMessage(channelIDMsg, hs.finishedHash.hashForChannelID(resumeHash))
		if err != nil {
			return err
		}
		c.channelID = channelID

		hs.writeClientHash(channelIDMsg.marshal())
	}

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

	verify := hs.finishedHash.clientSum(hs.masterSecret)
	if len(verify) != len(clientFinished.verifyData) ||
		subtle.ConstantTimeCompare(verify, clientFinished.verifyData) != 1 {
		c.sendAlert(alertHandshakeFailure)
		return errors.New("tls: client's Finished message is incorrect")
	}
	c.clientVerify = append(c.clientVerify[:0], clientFinished.verifyData...)
	copy(out, clientFinished.verifyData)

	hs.writeClientHash(clientFinished.marshal())
	return nil
}

func (hs *serverHandshakeState) sendSessionTicket() error {
	c := hs.c
	state := sessionState{
		vers:          c.vers,
		cipherSuite:   hs.suite,
		secret:        hs.masterSecret,
		certificates:  hs.certsFromClient,
		handshakeHash: hs.finishedHash.Sum(),
	}

	if !hs.hello.extensions.ticketSupported || hs.c.config.Bugs.SkipNewSessionTicket {
		if c.config.ServerSessionCache != nil && len(hs.hello.sessionID) != 0 {
			c.config.ServerSessionCache.Put(string(hs.hello.sessionID), &state)
		}
		return nil
	}

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

	if !c.config.Bugs.SendEmptySessionTicket {
		var err error
		m.ticket, err = c.encryptTicket(&state)
		if err != nil {
			return err
		}
	}

	hs.writeServerHash(m.marshal())
	if c.config.Bugs.PartialNewSessionTicketWithServerHelloDone {
		// The first byte was already sent.
		c.writeRecord(recordTypeHandshake, m.marshal()[1:])
	} else {
		c.writeRecord(recordTypeHandshake, m.marshal())
	}

	return nil
}

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

	finished := new(finishedMsg)
	finished.verifyData = hs.finishedHash.serverSum(hs.masterSecret)
	copy(out, finished.verifyData)
	if c.config.Bugs.BadFinished {
		finished.verifyData[0]++
	}
	c.serverVerify = append(c.serverVerify[:0], finished.verifyData...)
	hs.finishedBytes = finished.marshal()
	hs.writeServerHash(hs.finishedBytes)
	postCCSBytes := hs.finishedBytes
	if c.config.Bugs.PartialFinishedWithServerHelloDone {
		// The first byte has already been sent.
		postCCSBytes = postCCSBytes[1:]
	}

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

	if !c.config.Bugs.SkipChangeCipherSpec {
		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 && len(postCCSBytes) > 0 {
		c.writeRecord(recordTypeHandshake, postCCSBytes)
		if c.config.Bugs.SendExtraFinished {
			c.writeRecord(recordTypeHandshake, finished.marshal())
		}
	}

	if isResume || (!c.config.Bugs.PackHelloRequestWithFinished && !c.config.Bugs.PackAppDataWithHandshake) {
		// Defer flushing until Renegotiate() or Write().
		if err := c.flushHandshake(); err != nil {
			return err
		}
	}

	c.cipherSuite = hs.suite

	return nil
}

// processCertsFromClient takes a chain of client certificates either from a
// Certificates message or from a sessionState and verifies them. It returns
// the public key of the leaf certificate.
func (hs *serverHandshakeState) processCertsFromClient(certificates [][]byte) (crypto.PublicKey, error) {
	c := hs.c

	hs.certsFromClient = certificates
	certs := make([]*x509.Certificate, len(certificates))
	var err error
	for i, asn1Data := range certificates {
		if certs[i], err = x509.ParseCertificate(asn1Data); err != nil {
			c.sendAlert(alertBadCertificate)
			return nil, errors.New("tls: failed to parse client certificate: " + err.Error())
		}
	}

	if c.config.ClientAuth >= VerifyClientCertIfGiven && len(certs) > 0 {
		opts := x509.VerifyOptions{
			Roots:         c.config.ClientCAs,
			CurrentTime:   c.config.time(),
			Intermediates: x509.NewCertPool(),
			KeyUsages:     []x509.ExtKeyUsage{x509.ExtKeyUsageClientAuth},
		}

		for _, cert := range certs[1:] {
			opts.Intermediates.AddCert(cert)
		}

		chains, err := certs[0].Verify(opts)
		if err != nil {
			c.sendAlert(alertBadCertificate)
			return nil, errors.New("tls: failed to verify client's certificate: " + err.Error())
		}

		if !slices.Contains(certs[0].ExtKeyUsage, x509.ExtKeyUsageClientAuth) {
			c.sendAlert(alertHandshakeFailure)
			return nil, errors.New("tls: client's certificate's extended key usage doesn't permit it to be used for client authentication")
		}

		c.verifiedChains = chains
	}

	if len(certs) > 0 {
		pub := certs[0].PublicKey
		switch pub.(type) {
		case *ecdsa.PublicKey, *rsa.PublicKey, ed25519.PublicKey:
			break
		default:
			c.sendAlert(alertUnsupportedCertificate)
			return nil, fmt.Errorf("tls: client's certificate contains an unsupported public key of type %T", pub)
		}
		c.peerCertificates = certs
		return pub, nil
	}

	return nil, nil
}

func verifyChannelIDMessage(channelIDMsg *channelIDMsg, channelIDHash []byte) (*ecdsa.PublicKey, error) {
	x := new(big.Int).SetBytes(channelIDMsg.channelID[0:32])
	y := new(big.Int).SetBytes(channelIDMsg.channelID[32:64])
	r := new(big.Int).SetBytes(channelIDMsg.channelID[64:96])
	s := new(big.Int).SetBytes(channelIDMsg.channelID[96:128])
	if !elliptic.P256().IsOnCurve(x, y) {
		return nil, errors.New("tls: invalid channel ID public key")
	}
	channelID := &ecdsa.PublicKey{Curve: elliptic.P256(), X: x, Y: y}
	if !ecdsa.Verify(channelID, channelIDHash, r, s) {
		return nil, errors.New("tls: invalid channel ID signature")
	}
	return channelID, nil
}

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

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

// tryCipherSuite returns a cipherSuite with the given id if that cipher suite
// is acceptable to use.
func (c *Conn) tryCipherSuite(id uint16, supportedCipherSuites []uint16, version version, ellipticOk, ecdsaOk bool) *cipherSuite {
	protoVers := version.protocolVersion()
	candidate := mutualCipherSuite(supportedCipherSuites, id)
	if candidate == nil {
		return nil
	}

	// Don't select a ciphersuite which we can't
	// support for this client.
	if protoVers >= VersionTLS13 || candidate.flags&suiteTLS13 != 0 {
		if protoVers < VersionTLS13 || candidate.flags&suiteTLS13 == 0 {
			return nil
		}
		return candidate
	}
	if (candidate.flags&suiteECDHE != 0) && !ellipticOk {
		return nil
	}
	if (candidate.flags&suiteECDSA != 0) != ecdsaOk {
		return nil
	}
	if protoVers < VersionTLS12 && candidate.flags&suiteTLS12 != 0 {
		return nil
	}
	return candidate
}

func isTLS12Cipher(id uint16) bool {
	cipher := cipherSuiteFromID(id)
	return cipher != nil && cipher.flags&suiteTLS12 != 0
}

func isGREASEValue(val uint16) bool {
	return val&0x0f0f == 0x0a0a && val&0xff == val>>8
}

func verifyPSKBinder(psk *preSharedKey, clientHello *clientHelloMsg, binderToVerify, firstClientHello, helloRetryRequest []byte) error {
	binderLen := 2
	for _, binder := range clientHello.pskBinders {
		binderLen += 1 + len(binder)
	}

	truncatedHello := clientHello.marshal()
	truncatedHello = truncatedHello[:len(truncatedHello)-binderLen]
	binder := psk.computeBinder(firstClientHello, helloRetryRequest, truncatedHello)
	if !bytes.Equal(binder, binderToVerify) {
		return errors.New("tls: PSK binder does not verify")
	}

	return nil
}

// checkClientHellosEqual checks whether a and b are equal ClientHello
// messages. If isDTLS is true, the ClientHellos are parsed as DTLS and any
// differences in the cookie field are ignored. Extensions listed in
// ignoreExtensions may change or be removed between the two ClientHellos.
func checkClientHellosEqual(a, b []byte, isDTLS bool, ignoreExtensions []uint16) error {
	ignoreExtensionsSet := make(map[uint16]struct{})
	for _, ext := range ignoreExtensions {
		ignoreExtensionsSet[ext] = struct{}{}
	}

	// Skip the handshake message header.
	aReader := cryptobyte.String(a[4:])
	bReader := cryptobyte.String(b[4:])

	var aVers, bVers uint16
	var aRandom, bRandom []byte
	var aSessionID, bSessionID []byte
	if !aReader.ReadUint16(&aVers) ||
		!bReader.ReadUint16(&bVers) ||
		!aReader.ReadBytes(&aRandom, 32) ||
		!bReader.ReadBytes(&bRandom, 32) ||
		!readUint8LengthPrefixedBytes(&aReader, &aSessionID) ||
		!readUint8LengthPrefixedBytes(&bReader, &bSessionID) {
		return errors.New("tls: could not parse ClientHello")
	}

	if aVers != bVers {
		return errors.New("tls: second ClientHello version did not match")
	}
	if !bytes.Equal(aRandom, bRandom) {
		return errors.New("tls: second ClientHello random did not match")
	}
	if !bytes.Equal(aSessionID, bSessionID) {
		return errors.New("tls: second ClientHello session ID did not match")
	}

	if isDTLS {
		// DTLS 1.2 checks two ClientHellos match after a HelloVerifyRequest,
		// where we expect the cookies to change. DTLS 1.3 forbids the legacy
		// cookie altogether. If we implement DTLS 1.3, we'll need to ensure
		// that parsing logic above this function rejects this cookie.
		var aCookie, bCookie []byte
		if !readUint8LengthPrefixedBytes(&aReader, &aCookie) ||
			!readUint8LengthPrefixedBytes(&bReader, &bCookie) {
			return errors.New("tls: could not parse ClientHello")
		}
	}

	var aCipherSuites, bCipherSuites, aCompressionMethods, bCompressionMethods []byte
	if !readUint16LengthPrefixedBytes(&aReader, &aCipherSuites) ||
		!readUint16LengthPrefixedBytes(&bReader, &bCipherSuites) ||
		!readUint8LengthPrefixedBytes(&aReader, &aCompressionMethods) ||
		!readUint8LengthPrefixedBytes(&bReader, &bCompressionMethods) {
		return errors.New("tls: could not parse ClientHello")
	}
	if !bytes.Equal(aCipherSuites, bCipherSuites) {
		return errors.New("tls: second ClientHello cipher suites did not match")
	}
	if !bytes.Equal(aCompressionMethods, bCompressionMethods) {
		return errors.New("tls: second ClientHello compression methods did not match")
	}

	if len(aReader) == 0 && len(bReader) == 0 {
		// Both ClientHellos omit the extensions block.
		return nil
	}

	var aExtensions, bExtensions cryptobyte.String
	if !aReader.ReadUint16LengthPrefixed(&aExtensions) ||
		!bReader.ReadUint16LengthPrefixed(&bExtensions) ||
		len(aReader) != 0 ||
		len(bReader) != 0 {
		return errors.New("tls: could not parse ClientHello")
	}

	for len(aExtensions) != 0 {
		var aID uint16
		var aBody []byte
		if !aExtensions.ReadUint16(&aID) ||
			!readUint16LengthPrefixedBytes(&aExtensions, &aBody) {
			return errors.New("tls: could not parse ClientHello")
		}
		if _, ok := ignoreExtensionsSet[aID]; ok {
			continue
		}

		for {
			if len(bExtensions) == 0 {
				return fmt.Errorf("tls: second ClientHello missing extension %d", aID)
			}
			var bID uint16
			var bBody []byte
			if !bExtensions.ReadUint16(&bID) ||
				!readUint16LengthPrefixedBytes(&bExtensions, &bBody) {
				return errors.New("tls: could not parse ClientHello")
			}
			if _, ok := ignoreExtensionsSet[bID]; ok {
				continue
			}
			if aID != bID {
				return fmt.Errorf("tls: unexpected extension %d in second ClientHello (wanted %d)", bID, aID)
			}
			if !bytes.Equal(aBody, bBody) {
				return fmt.Errorf("tls: extension %d in second ClientHello unexpectedly changed", aID)
			}
			break
		}
	}

	// Any remaining extensions in the second ClientHello must be in the
	// ignored set.
	for len(bExtensions) != 0 {
		var id uint16
		var body []byte
		if !bExtensions.ReadUint16(&id) ||
			!readUint16LengthPrefixedBytes(&bExtensions, &body) {
			return errors.New("tls: could not parse ClientHello")
		}
		if _, ok := ignoreExtensionsSet[id]; !ok {
			return fmt.Errorf("tls: unexpected extension %d in second ClientHello", id)
		}
	}

	return nil
}
