package tls
import (
)
type clientHandshakeStateTLS13 struct {
c *Conn
ctx context.Context
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
}
func ( *clientHandshakeStateTLS13) () error {
:= .c
if .handshakes > 0 {
.sendAlert(alertProtocolVersion)
return errors.New("tls: server selected TLS 1.3 in a renegotiation")
}
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
}
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
}
func ( *clientHandshakeStateTLS13) () error {
if .sentDummyCCS {
return nil
}
.sentDummyCCS = true
, := .c.writeRecord(recordTypeChangeCipherSpec, []byte{1})
return
}
func ( *clientHandshakeStateTLS13) () error {
:= .c
:= .transcript.Sum(nil)
.transcript.Reset()
.transcript.Write([]byte{typeMessageHash, 0, 0, uint8(len())})
.transcript.Write()
.transcript.Write(.serverHello.marshal())
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 := .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)
}
if .hash == .suite.hash {
:= 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()
} else {
.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 := checkALPN(.hello.alpnProtocols, .alpnProtocol); != nil {
.sendAlert(alertUnsupportedExtension)
return
}
.clientProtocol = .alpnProtocol
return nil
}
func ( *clientHandshakeStateTLS13) () error {
:= .c
if .usingPSK {
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(, )
}
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())
.trafficSecret = .suite.deriveSecret(.masterSecret,
clientApplicationTrafficLabel, .transcript)
:= .suite.deriveSecret(.masterSecret,
serverApplicationTrafficLabel, .transcript)
.in.setTrafficSecret(.suite, )
= .config.writeKeyLog(keyLogLabelClientTraffic, .hello.random, .trafficSecret)
if != nil {
.sendAlert(alertInternalError)
return
}
= .config.writeKeyLog(keyLogLabelServerTraffic, .hello.random, )
if != nil {
.sendAlert(alertInternalError)
return
}
.ekm = .suite.exportKeyingMaterial(.masterSecret, .transcript)
return nil
}
func ( *clientHandshakeStateTLS13) () error {
:= .c
if .certReq == nil {
return nil
}
, := .getClientCertificate(&CertificateRequestInfo{
AcceptableCAs: .certReq.certificateAuthorities,
SignatureSchemes: .certReq.supportedSignatureAlgorithms,
Version: .vers,
ctx: .ctx,
})
if != nil {
return
}
:= new(certificateMsgTLS13)
.certificate = *
.scts = .certReq.scts && len(.SignedCertificateTimestamps) > 0
.ocspStapling = .certReq.ocspStapling && len(.OCSPStaple) > 0
.transcript.Write(.marshal())
if , := .writeRecord(recordTypeHandshake, .marshal()); != nil {
return
}
if len(.Certificate) == 0 {
return nil
}
:= new(certificateVerifyMsg)
.hasSignatureAlgorithm = true
.signatureAlgorithm, = selectSignatureScheme(.vers, , .certReq.supportedSignatureAlgorithms)
if != nil {
.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
}
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)
}
:= &ClientSessionState{
sessionTicket: .label,
vers: .vers,
cipherSuite: .cipherSuite,
masterSecret: .resumptionSecret,
serverCertificates: .peerCertificates,
verifiedChains: .verifiedChains,
receivedAt: .config.time(),
nonce: .nonce,
useBy: .config.time().Add(),
ageAdd: .ageAdd,
ocspResponse: .ocspResponse,
scts: .scts,
}
:= clientSessionCacheKey(.conn.RemoteAddr(), .config)
.config.ClientSessionCache.Put(, )
return nil
}