Copyright 2018 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 tls

import (
	
	
	
	
	
	
	
	
)

type clientHandshakeStateTLS13 struct {
	c           *Conn
	serverHello *serverHelloMsg
	hello       *clientHelloMsg
	ecdheParams ecdheParameters

	session     *ClientSessionState
	earlySecret []byte
	binderKey   []byte

	certReq       *certificateRequestMsgTLS13
	usingPSK      bool
	sentDummyCCS  bool
	suite         *cipherSuiteTLS13
	transcript    hash.Hash
	masterSecret  []byte
	trafficSecret []byte // client_application_traffic_secret_0
}
handshake requires hs.c, hs.hello, hs.serverHello, hs.ecdheParams, and, optionally, hs.session, hs.earlySecret and hs.binderKey to be set.
func ( *clientHandshakeStateTLS13) () error {
	 := .c
The server must not select TLS 1.3 in a renegotiation. See RFC 8446, sections 4.1.2 and 4.1.3.
	if .handshakes > 0 {
		.sendAlert(alertProtocolVersion)
		return errors.New("tls: server selected TLS 1.3 in a renegotiation")
	}
Consistency check on the presence of a keyShare and its parameters.
	if .ecdheParams == nil || len(.hello.keyShares) != 1 {
		return .sendAlert(alertInternalError)
	}

	if  := .checkServerHelloOrHRR();  != nil {
		return 
	}

	.transcript = .suite.hash.New()
	.transcript.Write(.hello.marshal())

	if bytes.Equal(.serverHello.random, helloRetryRequestRandom) {
		if  := .sendDummyChangeCipherSpec();  != nil {
			return 
		}
		if  := .processHelloRetryRequest();  != nil {
			return 
		}
	}

	.transcript.Write(.serverHello.marshal())

	.buffering = true
	if  := .processServerHello();  != nil {
		return 
	}
	if  := .sendDummyChangeCipherSpec();  != nil {
		return 
	}
	if  := .establishHandshakeKeys();  != nil {
		return 
	}
	if  := .readServerParameters();  != nil {
		return 
	}
	if  := .readServerCertificate();  != nil {
		return 
	}
	if  := .readServerFinished();  != nil {
		return 
	}
	if  := .sendClientCertificate();  != nil {
		return 
	}
	if  := .sendClientFinished();  != nil {
		return 
	}
	if ,  := .flush();  != nil {
		return 
	}

	atomic.StoreUint32(&.handshakeStatus, 1)

	return nil
}
checkServerHelloOrHRR does validity checks that apply to both ServerHello and HelloRetryRequest messages. It sets hs.suite.
func ( *clientHandshakeStateTLS13) () error {
	 := .c

	if .serverHello.supportedVersion == 0 {
		.sendAlert(alertMissingExtension)
		return errors.New("tls: server selected TLS 1.3 using the legacy version field")
	}

	if .serverHello.supportedVersion != VersionTLS13 {
		.sendAlert(alertIllegalParameter)
		return errors.New("tls: server selected an invalid version after a HelloRetryRequest")
	}

	if .serverHello.vers != VersionTLS12 {
		.sendAlert(alertIllegalParameter)
		return errors.New("tls: server sent an incorrect legacy version")
	}

	if .serverHello.ocspStapling ||
		.serverHello.ticketSupported ||
		.serverHello.secureRenegotiationSupported ||
		len(.serverHello.secureRenegotiation) != 0 ||
		len(.serverHello.alpnProtocol) != 0 ||
		len(.serverHello.scts) != 0 {
		.sendAlert(alertUnsupportedExtension)
		return errors.New("tls: server sent a ServerHello extension forbidden in TLS 1.3")
	}

	if !bytes.Equal(.hello.sessionId, .serverHello.sessionId) {
		.sendAlert(alertIllegalParameter)
		return errors.New("tls: server did not echo the legacy session ID")
	}

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

	 := mutualCipherSuiteTLS13(.hello.cipherSuites, .serverHello.cipherSuite)
	if .suite != nil &&  != .suite {
		.sendAlert(alertIllegalParameter)
		return errors.New("tls: server changed cipher suite after a HelloRetryRequest")
	}
	if  == nil {
		.sendAlert(alertIllegalParameter)
		return errors.New("tls: server chose an unconfigured cipher suite")
	}
	.suite = 
	.cipherSuite = .suite.id

	return nil
}
sendDummyChangeCipherSpec sends a ChangeCipherSpec record for compatibility with middleboxes that didn't implement TLS correctly. See RFC 8446, Appendix D.4.
processHelloRetryRequest handles the HRR in hs.serverHello, modifies and resends hs.hello, and reads the new ServerHello into hs.serverHello.
The first ClientHello gets double-hashed into the transcript upon a HelloRetryRequest. (The idea is that the server might offload transcript storage to the client in the cookie.) See RFC 8446, Section 4.4.1.
The only HelloRetryRequest extensions we support are key_share and cookie, and clients must abort the handshake if the HRR would not result in any change in the ClientHello.
	if .serverHello.selectedGroup == 0 && .serverHello.cookie == nil {
		.sendAlert(alertIllegalParameter)
		return errors.New("tls: server sent an unnecessary HelloRetryRequest message")
	}

	if .serverHello.cookie != nil {
		.hello.cookie = .serverHello.cookie
	}

	if .serverHello.serverShare.group != 0 {
		.sendAlert(alertDecodeError)
		return errors.New("tls: received malformed key_share extension")
	}
If the server sent a key_share extension selecting a group, ensure it's a group we advertised but did not send a key share for, and send a key share for it this time.
	if  := .serverHello.selectedGroup;  != 0 {
		 := false
		for ,  := range .hello.supportedCurves {
			if  ==  {
				 = true
				break
			}
		}
		if ! {
			.sendAlert(alertIllegalParameter)
			return errors.New("tls: server selected unsupported group")
		}
		if .ecdheParams.CurveID() ==  {
			.sendAlert(alertIllegalParameter)
			return errors.New("tls: server sent an unnecessary HelloRetryRequest key_share")
		}
		if ,  := curveForCurveID();  != X25519 && ! {
			.sendAlert(alertInternalError)
			return errors.New("tls: CurvePreferences includes unsupported curve")
		}
		,  := generateECDHEParameters(.config.rand(), )
		if  != nil {
			.sendAlert(alertInternalError)
			return 
		}
		.ecdheParams = 
		.hello.keyShares = []keyShare{{group: , data: .PublicKey()}}
	}

	.hello.raw = nil
	if len(.hello.pskIdentities) > 0 {
		 := cipherSuiteTLS13ByID(.session.cipherSuite)
		if  == nil {
			return .sendAlert(alertInternalError)
		}
Update binders and obfuscated_ticket_age.
			 := uint32(.config.time().Sub(.session.receivedAt) / time.Millisecond)
			.hello.pskIdentities[0].obfuscatedTicketAge =  + .session.ageAdd

			 := .suite.hash.New()
			.Write([]byte{typeMessageHash, 0, 0, uint8(len())})
			.Write()
			.Write(.serverHello.marshal())
			.Write(.hello.marshalWithoutBinders())
			 := [][]byte{.suite.finishedHash(.binderKey, )}
			.hello.updateBinders()
Server selected a cipher suite incompatible with the PSK.
			.hello.pskIdentities = nil
			.hello.pskBinders = nil
		}
	}

	.transcript.Write(.hello.marshal())
	if ,  := .writeRecord(recordTypeHandshake, .hello.marshal());  != nil {
		return 
	}

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

	,  := .(*serverHelloMsg)
	if ! {
		.sendAlert(alertUnexpectedMessage)
		return unexpectedMessageError(, )
	}
	.serverHello = 

	if  := .checkServerHelloOrHRR();  != nil {
		return 
	}

	return nil
}

func ( *clientHandshakeStateTLS13) () error {
	 := .c

	if bytes.Equal(.serverHello.random, helloRetryRequestRandom) {
		.sendAlert(alertUnexpectedMessage)
		return errors.New("tls: server sent two HelloRetryRequest messages")
	}

	if len(.serverHello.cookie) != 0 {
		.sendAlert(alertUnsupportedExtension)
		return errors.New("tls: server sent a cookie in a normal ServerHello")
	}

	if .serverHello.selectedGroup != 0 {
		.sendAlert(alertDecodeError)
		return errors.New("tls: malformed key_share extension")
	}

	if .serverHello.serverShare.group == 0 {
		.sendAlert(alertIllegalParameter)
		return errors.New("tls: server did not send a key share")
	}
	if .serverHello.serverShare.group != .ecdheParams.CurveID() {
		.sendAlert(alertIllegalParameter)
		return errors.New("tls: server selected unsupported group")
	}

	if !.serverHello.selectedIdentityPresent {
		return nil
	}

	if int(.serverHello.selectedIdentity) >= len(.hello.pskIdentities) {
		.sendAlert(alertIllegalParameter)
		return errors.New("tls: server selected an invalid PSK")
	}

	if len(.hello.pskIdentities) != 1 || .session == nil {
		return .sendAlert(alertInternalError)
	}
	 := cipherSuiteTLS13ByID(.session.cipherSuite)
	if  == nil {
		return .sendAlert(alertInternalError)
	}
	if .hash != .suite.hash {
		.sendAlert(alertIllegalParameter)
		return errors.New("tls: server selected an invalid PSK and cipher suite pair")
	}

	.usingPSK = true
	.didResume = true
	.peerCertificates = .session.serverCertificates
	.verifiedChains = .session.verifiedChains
	.ocspResponse = .session.ocspResponse
	.scts = .session.scts
	return nil
}

func ( *clientHandshakeStateTLS13) () error {
	 := .c

	 := .ecdheParams.SharedKey(.serverHello.serverShare.data)
	if  == nil {
		.sendAlert(alertIllegalParameter)
		return errors.New("tls: invalid server key share")
	}

	 := .earlySecret
	if !.usingPSK {
		 = .suite.extract(nil, nil)
	}
	 := .suite.extract(,
		.suite.deriveSecret(, "derived", nil))

	 := .suite.deriveSecret(,
		clientHandshakeTrafficLabel, .transcript)
	.out.setTrafficSecret(.suite, )
	 := .suite.deriveSecret(,
		serverHandshakeTrafficLabel, .transcript)
	.in.setTrafficSecret(.suite, )

	 := .config.writeKeyLog(keyLogLabelClientHandshake, .hello.random, )
	if  != nil {
		.sendAlert(alertInternalError)
		return 
	}
	 = .config.writeKeyLog(keyLogLabelServerHandshake, .hello.random, )
	if  != nil {
		.sendAlert(alertInternalError)
		return 
	}

	.masterSecret = .suite.extract(nil,
		.suite.deriveSecret(, "derived", nil))

	return nil
}

func ( *clientHandshakeStateTLS13) () error {
	 := .c

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

	,  := .(*encryptedExtensionsMsg)
	if ! {
		.sendAlert(alertUnexpectedMessage)
		return unexpectedMessageError(, )
	}
	.transcript.Write(.marshal())

	if .alpnProtocol != "" {
		if len(.hello.alpnProtocols) == 0 {
			.sendAlert(alertUnsupportedExtension)
			return errors.New("tls: server advertised unrequested ALPN extension")
		}
		if mutualProtocol([]string{.alpnProtocol}, .hello.alpnProtocols) == "" {
			.sendAlert(alertUnsupportedExtension)
			return errors.New("tls: server selected unadvertised ALPN protocol")
		}
		.clientProtocol = .alpnProtocol
	}

	return nil
}

func ( *clientHandshakeStateTLS13) () error {
	 := .c
Either a PSK or a certificate is always used, but not both. See RFC 8446, Section 4.1.1.
Make sure the connection is still being verified whether or not this is a resumption. Resumptions currently don't reverify certificates so they don't call verifyServerCertificate. See Issue 31641.
		if .config.VerifyConnection != nil {
			if  := .config.VerifyConnection(.connectionStateLocked());  != nil {
				.sendAlert(alertBadCertificate)
				return 
			}
		}
		return nil
	}

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

	,  := .(*certificateRequestMsgTLS13)
	if  {
		.transcript.Write(.marshal())

		.certReq = 

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

	,  := .(*certificateMsgTLS13)
	if ! {
		.sendAlert(alertUnexpectedMessage)
		return unexpectedMessageError(, )
	}
	if len(.certificate.Certificate) == 0 {
		.sendAlert(alertDecodeError)
		return errors.New("tls: received empty certificates message")
	}
	.transcript.Write(.marshal())

	.scts = .certificate.SignedCertificateTimestamps
	.ocspResponse = .certificate.OCSPStaple

	if  := .verifyServerCertificate(.certificate.Certificate);  != nil {
		return 
	}

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

	,  := .(*certificateVerifyMsg)
	if ! {
		.sendAlert(alertUnexpectedMessage)
		return unexpectedMessageError(, )
	}
See RFC 8446, Section 4.4.3.
	if !isSupportedSignatureAlgorithm(.signatureAlgorithm, supportedSignatureAlgorithms) {
		.sendAlert(alertIllegalParameter)
		return errors.New("tls: certificate used with invalid signature algorithm")
	}
	, ,  := typeAndHashFromSignatureScheme(.signatureAlgorithm)
	if  != nil {
		return .sendAlert(alertInternalError)
	}
	if  == signaturePKCS1v15 ||  == crypto.SHA1 {
		.sendAlert(alertIllegalParameter)
		return errors.New("tls: certificate used with invalid signature algorithm")
	}
	 := signedMessage(, serverSignatureContext, .transcript)
	if  := verifyHandshakeSignature(, .peerCertificates[0].PublicKey,
		, , .signature);  != nil {
		.sendAlert(alertDecryptError)
		return errors.New("tls: invalid signature by the server certificate: " + .Error())
	}

	.transcript.Write(.marshal())

	return nil
}

func ( *clientHandshakeStateTLS13) () error {
	 := .c

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

	,  := .(*finishedMsg)
	if ! {
		.sendAlert(alertUnexpectedMessage)
		return unexpectedMessageError(, )
	}

	 := .suite.finishedHash(.in.trafficSecret, .transcript)
	if !hmac.Equal(, .verifyData) {
		.sendAlert(alertDecryptError)
		return errors.New("tls: invalid server finished hash")
	}

	.transcript.Write(.marshal())
Derive secrets that take context through the server Finished.
If we sent an empty certificate message, skip the CertificateVerify.
	if len(.Certificate) == 0 {
		return nil
	}

	 := new(certificateVerifyMsg)
	.hasSignatureAlgorithm = true

	.signatureAlgorithm,  = selectSignatureScheme(.vers, , .certReq.supportedSignatureAlgorithms)
getClientCertificate returned a certificate incompatible with the CertificateRequestInfo supported signature algorithms.
		.sendAlert(alertHandshakeFailure)
		return 
	}

	, ,  := typeAndHashFromSignatureScheme(.signatureAlgorithm)
	if  != nil {
		return .sendAlert(alertInternalError)
	}

	 := signedMessage(, clientSignatureContext, .transcript)
	 := crypto.SignerOpts()
	if  == signatureRSAPSS {
		 = &rsa.PSSOptions{SaltLength: rsa.PSSSaltLengthEqualsHash, Hash: }
	}
	,  := .PrivateKey.(crypto.Signer).Sign(.config.rand(), , )
	if  != nil {
		.sendAlert(alertInternalError)
		return errors.New("tls: failed to sign handshake: " + .Error())
	}
	.signature = 

	.transcript.Write(.marshal())
	if ,  := .writeRecord(recordTypeHandshake, .marshal());  != nil {
		return 
	}

	return nil
}

func ( *clientHandshakeStateTLS13) () error {
	 := .c

	 := &finishedMsg{
		verifyData: .suite.finishedHash(.out.trafficSecret, .transcript),
	}

	.transcript.Write(.marshal())
	if ,  := .writeRecord(recordTypeHandshake, .marshal());  != nil {
		return 
	}

	.out.setTrafficSecret(.suite, .trafficSecret)

	if !.config.SessionTicketsDisabled && .config.ClientSessionCache != nil {
		.resumptionSecret = .suite.deriveSecret(.masterSecret,
			resumptionLabel, .transcript)
	}

	return nil
}

func ( *Conn) ( *newSessionTicketMsgTLS13) error {
	if !.isClient {
		.sendAlert(alertUnexpectedMessage)
		return errors.New("tls: received new session ticket from a client")
	}

	if .config.SessionTicketsDisabled || .config.ClientSessionCache == nil {
		return nil
	}
See RFC 8446, Section 4.6.1.
	if .lifetime == 0 {
		return nil
	}
	 := time.Duration(.lifetime) * time.Second
	if  > maxSessionTicketLifetime {
		.sendAlert(alertIllegalParameter)
		return errors.New("tls: received a session ticket with invalid lifetime")
	}

	 := cipherSuiteTLS13ByID(.cipherSuite)
	if  == nil || .resumptionSecret == nil {
		return .sendAlert(alertInternalError)
	}
Save the resumption_master_secret and nonce instead of deriving the PSK to do the least amount of work on NewSessionTicket messages before we know if the ticket will be used. Forward secrecy of resumed connections is guaranteed by the requirement for pskModeDHE.