package tls
import (
)
const maxClientPSKIdentities = 5
type serverHandshakeStateTLS13 struct {
c *Conn
ctx context.Context
clientHello *clientHelloMsg
hello *serverHelloMsg
sentDummyCCS bool
usingPSK bool
suite *cipherSuiteTLS13
cert *Certificate
sigAlg SignatureScheme
earlySecret []byte
sharedKey []byte
handshakeSecret []byte
masterSecret []byte
trafficSecret []byte
transcript hash.Hash
clientFinished []byte
}
func ( *serverHandshakeStateTLS13) () error {
:= .c
if := .processClientHello(); != nil {
return
}
if := .checkForResumption(); != nil {
return
}
if := .pickCertificate(); != nil {
return
}
.buffering = true
if := .sendServerParameters(); != nil {
return
}
if := .sendServerCertificate(); != nil {
return
}
if := .sendServerFinished(); != nil {
return
}
if , := .flush(); != nil {
return
}
if := .readClientCertificate(); != nil {
return
}
if := .readClientFinished(); != nil {
return
}
atomic.StoreUint32(&.handshakeStatus, 1)
return nil
}
func ( *serverHandshakeStateTLS13) () error {
:= .c
.hello = new(serverHelloMsg)
.hello.vers = VersionTLS12
.hello.supportedVersion = .vers
if len(.clientHello.supportedVersions) == 0 {
.sendAlert(alertIllegalParameter)
return errors.New("tls: client used the legacy version field to negotiate TLS 1.3")
}
for , := range .clientHello.cipherSuites {
if == TLS_FALLBACK_SCSV {
if .vers < .config.maxSupportedVersion(roleServer) {
.sendAlert(alertInappropriateFallback)
return errors.New("tls: client using inappropriate protocol fallback")
}
break
}
}
if len(.clientHello.compressionMethods) != 1 ||
.clientHello.compressionMethods[0] != compressionNone {
.sendAlert(alertIllegalParameter)
return errors.New("tls: TLS 1.3 client supports illegal compression methods")
}
.hello.random = make([]byte, 32)
if , := io.ReadFull(.config.rand(), .hello.random); != nil {
.sendAlert(alertInternalError)
return
}
if len(.clientHello.secureRenegotiation) != 0 {
.sendAlert(alertHandshakeFailure)
return errors.New("tls: initial handshake had non-empty renegotiation extension")
}
if .clientHello.earlyData {
.sendAlert(alertUnsupportedExtension)
return errors.New("tls: client sent unexpected early data")
}
.hello.sessionId = .clientHello.sessionId
.hello.compressionMethod = compressionNone
:= defaultCipherSuitesTLS13
if !hasAESGCMHardwareSupport || !aesgcmPreferred(.clientHello.cipherSuites) {
= defaultCipherSuitesTLS13NoAES
}
for , := range {
.suite = mutualCipherSuiteTLS13(.clientHello.cipherSuites, )
if .suite != nil {
break
}
}
if .suite == nil {
.sendAlert(alertHandshakeFailure)
return errors.New("tls: no cipher suite supported by both client and server")
}
.cipherSuite = .suite.id
.hello.cipherSuite = .suite.id
.transcript = .suite.hash.New()
var CurveID
var *keyShare
:
for , := range .config.curvePreferences() {
for , := range .clientHello.keyShares {
if .group == {
= .group
= &
break
}
}
if != 0 {
continue
}
for , := range .clientHello.supportedCurves {
if == {
=
break
}
}
}
if == 0 {
.sendAlert(alertHandshakeFailure)
return errors.New("tls: no ECDHE curve supported by both client and server")
}
if == nil {
if := .doHelloRetryRequest(); != nil {
return
}
= &.clientHello.keyShares[0]
}
if , := curveForCurveID(); != X25519 && ! {
.sendAlert(alertInternalError)
return errors.New("tls: CurvePreferences includes unsupported curve")
}
, := generateECDHEParameters(.config.rand(), )
if != nil {
.sendAlert(alertInternalError)
return
}
.hello.serverShare = keyShare{group: , data: .PublicKey()}
.sharedKey = .SharedKey(.data)
if .sharedKey == nil {
.sendAlert(alertIllegalParameter)
return errors.New("tls: invalid client key share")
}
.serverName = .clientHello.serverName
return nil
}
func ( *serverHandshakeStateTLS13) () error {
:= .c
if .config.SessionTicketsDisabled {
return nil
}
:= false
for , := range .clientHello.pskModes {
if == pskModeDHE {
= true
break
}
}
if ! {
return nil
}
if len(.clientHello.pskIdentities) != len(.clientHello.pskBinders) {
.sendAlert(alertIllegalParameter)
return errors.New("tls: invalid or missing PSK binders")
}
if len(.clientHello.pskIdentities) == 0 {
return nil
}
for , := range .clientHello.pskIdentities {
if >= maxClientPSKIdentities {
break
}
, := .decryptTicket(.label)
if == nil {
continue
}
:= new(sessionStateTLS13)
if := .unmarshal(); ! {
continue
}
:= time.Unix(int64(.createdAt), 0)
if .config.time().Sub() > maxSessionTicketLifetime {
continue
}
:= cipherSuiteTLS13ByID(.cipherSuite)
if == nil || .hash != .suite.hash {
continue
}
:= len(.certificate.Certificate) != 0
:= requiresClientCert(.config.ClientAuth)
if && ! {
continue
}
if && .config.ClientAuth == NoClientCert {
continue
}
:= .suite.expandLabel(.resumptionSecret, "resumption",
nil, .suite.hash.Size())
.earlySecret = .suite.extract(, nil)
:= .suite.deriveSecret(.earlySecret, resumptionBinderLabel, nil)
:= cloneHash(.transcript, .suite.hash)
if == nil {
.sendAlert(alertInternalError)
return errors.New("tls: internal error: failed to clone hash")
}
.Write(.clientHello.marshalWithoutBinders())
:= .suite.finishedHash(, )
if !hmac.Equal(.clientHello.pskBinders[], ) {
.sendAlert(alertDecryptError)
return errors.New("tls: invalid PSK binder")
}
.didResume = true
if := .processCertsFromClient(.certificate); != nil {
return
}
.hello.selectedIdentityPresent = true
.hello.selectedIdentity = uint16()
.usingPSK = true
return nil
}
return nil
}
func ( hash.Hash, crypto.Hash) hash.Hash {
type interface {
() ( []byte, error)
( []byte) error
}
, := .()
if ! {
return nil
}
, := .()
if != nil {
return nil
}
:= .New()
, := .()
if ! {
return nil
}
if := .(); != nil {
return nil
}
return
}
func ( *serverHandshakeStateTLS13) () error {
:= .c
if .usingPSK {
return nil
}
if len(.clientHello.supportedSignatureAlgorithms) == 0 {
return .sendAlert(alertMissingExtension)
}
, := .config.getCertificate(clientHelloInfo(.ctx, , .clientHello))
if != nil {
if == errNoCertificates {
.sendAlert(alertUnrecognizedName)
} else {
.sendAlert(alertInternalError)
}
return
}
.sigAlg, = selectSignatureScheme(.vers, , .clientHello.supportedSignatureAlgorithms)
if != nil {
.sendAlert(alertHandshakeFailure)
return
}
.cert =
return nil
}
func ( *serverHandshakeStateTLS13) () error {
if .sentDummyCCS {
return nil
}
.sentDummyCCS = true
, := .c.writeRecord(recordTypeChangeCipherSpec, []byte{1})
return
}
func ( *serverHandshakeStateTLS13) ( CurveID) error {
:= .c
.transcript.Write(.clientHello.marshal())
:= .transcript.Sum(nil)
.transcript.Reset()
.transcript.Write([]byte{typeMessageHash, 0, 0, uint8(len())})
.transcript.Write()
:= &serverHelloMsg{
vers: .hello.vers,
random: helloRetryRequestRandom,
sessionId: .hello.sessionId,
cipherSuite: .hello.cipherSuite,
compressionMethod: .hello.compressionMethod,
supportedVersion: .hello.supportedVersion,
selectedGroup: ,
}
.transcript.Write(.marshal())
if , := .writeRecord(recordTypeHandshake, .marshal()); != nil {
return
}
if := .sendDummyChangeCipherSpec(); != nil {
return
}
, := .readHandshake()
if != nil {
return
}
, := .(*clientHelloMsg)
if ! {
.sendAlert(alertUnexpectedMessage)
return unexpectedMessageError(, )
}
if len(.keyShares) != 1 || .keyShares[0].group != {
.sendAlert(alertIllegalParameter)
return errors.New("tls: client sent invalid key share in second ClientHello")
}
if .earlyData {
.sendAlert(alertIllegalParameter)
return errors.New("tls: client indicated early data in second ClientHello")
}
if illegalClientHelloChange(, .clientHello) {
.sendAlert(alertIllegalParameter)
return errors.New("tls: client illegally modified second ClientHello")
}
.clientHello =
return nil
}
func (, *clientHelloMsg) bool {
if len(.supportedVersions) != len(.supportedVersions) ||
len(.cipherSuites) != len(.cipherSuites) ||
len(.supportedCurves) != len(.supportedCurves) ||
len(.supportedSignatureAlgorithms) != len(.supportedSignatureAlgorithms) ||
len(.supportedSignatureAlgorithmsCert) != len(.supportedSignatureAlgorithmsCert) ||
len(.alpnProtocols) != len(.alpnProtocols) {
return true
}
for := range .supportedVersions {
if .supportedVersions[] != .supportedVersions[] {
return true
}
}
for := range .cipherSuites {
if .cipherSuites[] != .cipherSuites[] {
return true
}
}
for := range .supportedCurves {
if .supportedCurves[] != .supportedCurves[] {
return true
}
}
for := range .supportedSignatureAlgorithms {
if .supportedSignatureAlgorithms[] != .supportedSignatureAlgorithms[] {
return true
}
}
for := range .supportedSignatureAlgorithmsCert {
if .supportedSignatureAlgorithmsCert[] != .supportedSignatureAlgorithmsCert[] {
return true
}
}
for := range .alpnProtocols {
if .alpnProtocols[] != .alpnProtocols[] {
return true
}
}
return .vers != .vers ||
!bytes.Equal(.random, .random) ||
!bytes.Equal(.sessionId, .sessionId) ||
!bytes.Equal(.compressionMethods, .compressionMethods) ||
.serverName != .serverName ||
.ocspStapling != .ocspStapling ||
!bytes.Equal(.supportedPoints, .supportedPoints) ||
.ticketSupported != .ticketSupported ||
!bytes.Equal(.sessionTicket, .sessionTicket) ||
.secureRenegotiationSupported != .secureRenegotiationSupported ||
!bytes.Equal(.secureRenegotiation, .secureRenegotiation) ||
.scts != .scts ||
!bytes.Equal(.cookie, .cookie) ||
!bytes.Equal(.pskModes, .pskModes)
}
func ( *serverHandshakeStateTLS13) () error {
:= .c
.transcript.Write(.clientHello.marshal())
.transcript.Write(.hello.marshal())
if , := .writeRecord(recordTypeHandshake, .hello.marshal()); != nil {
return
}
if := .sendDummyChangeCipherSpec(); != nil {
return
}
:= .earlySecret
if == nil {
= .suite.extract(nil, nil)
}
.handshakeSecret = .suite.extract(.sharedKey,
.suite.deriveSecret(, "derived", nil))
:= .suite.deriveSecret(.handshakeSecret,
clientHandshakeTrafficLabel, .transcript)
.in.setTrafficSecret(.suite, )
:= .suite.deriveSecret(.handshakeSecret,
serverHandshakeTrafficLabel, .transcript)
.out.setTrafficSecret(.suite, )
:= .config.writeKeyLog(keyLogLabelClientHandshake, .clientHello.random, )
if != nil {
.sendAlert(alertInternalError)
return
}
= .config.writeKeyLog(keyLogLabelServerHandshake, .clientHello.random, )
if != nil {
.sendAlert(alertInternalError)
return
}
:= new(encryptedExtensionsMsg)
, := negotiateALPN(.config.NextProtos, .clientHello.alpnProtocols)
if != nil {
.sendAlert(alertNoApplicationProtocol)
return
}
.alpnProtocol =
.clientProtocol =
.transcript.Write(.marshal())
if , := .writeRecord(recordTypeHandshake, .marshal()); != nil {
return
}
return nil
}
func ( *serverHandshakeStateTLS13) () bool {
return .c.config.ClientAuth >= RequestClientCert && !.usingPSK
}
func ( *serverHandshakeStateTLS13) () error {
:= .c
if .usingPSK {
return nil
}
if .requestClientCert() {
:= new(certificateRequestMsgTLS13)
.ocspStapling = true
.scts = true
.supportedSignatureAlgorithms = supportedSignatureAlgorithms
if .config.ClientCAs != nil {
.certificateAuthorities = .config.ClientCAs.Subjects()
}
.transcript.Write(.marshal())
if , := .writeRecord(recordTypeHandshake, .marshal()); != nil {
return
}
}
:= new(certificateMsgTLS13)
.certificate = *.cert
.scts = .clientHello.scts && len(.cert.SignedCertificateTimestamps) > 0
.ocspStapling = .clientHello.ocspStapling && len(.cert.OCSPStaple) > 0
.transcript.Write(.marshal())
if , := .writeRecord(recordTypeHandshake, .marshal()); != nil {
return
}
:= new(certificateVerifyMsg)
.hasSignatureAlgorithm = true
.signatureAlgorithm = .sigAlg
, , := typeAndHashFromSignatureScheme(.sigAlg)
if != nil {
return .sendAlert(alertInternalError)
}
:= signedMessage(, serverSignatureContext, .transcript)
:= crypto.SignerOpts()
if == signatureRSAPSS {
= &rsa.PSSOptions{SaltLength: rsa.PSSSaltLengthEqualsHash, Hash: }
}
, := .cert.PrivateKey.(crypto.Signer).Sign(.config.rand(), , )
if != nil {
:= .cert.PrivateKey.(crypto.Signer).Public()
if , := .(*rsa.PublicKey); && == signatureRSAPSS &&
.N.BitLen()/8 < .Size()*2+2 {
.sendAlert(alertHandshakeFailure)
} else {
.sendAlert(alertInternalError)
}
return errors.New("tls: failed to sign handshake: " + .Error())
}
.signature =
.transcript.Write(.marshal())
if , := .writeRecord(recordTypeHandshake, .marshal()); != nil {
return
}
return nil
}
func ( *serverHandshakeStateTLS13) () error {
:= .c
:= &finishedMsg{
verifyData: .suite.finishedHash(.out.trafficSecret, .transcript),
}
.transcript.Write(.marshal())
if , := .writeRecord(recordTypeHandshake, .marshal()); != nil {
return
}
.masterSecret = .suite.extract(nil,
.suite.deriveSecret(.handshakeSecret, "derived", nil))
.trafficSecret = .suite.deriveSecret(.masterSecret,
clientApplicationTrafficLabel, .transcript)
:= .suite.deriveSecret(.masterSecret,
serverApplicationTrafficLabel, .transcript)
.out.setTrafficSecret(.suite, )
:= .config.writeKeyLog(keyLogLabelClientTraffic, .clientHello.random, .trafficSecret)
if != nil {
.sendAlert(alertInternalError)
return
}
= .config.writeKeyLog(keyLogLabelServerTraffic, .clientHello.random, )
if != nil {
.sendAlert(alertInternalError)
return
}
.ekm = .suite.exportKeyingMaterial(.masterSecret, .transcript)
if !.requestClientCert() {
if := .sendSessionTickets(); != nil {
return
}
}
return nil
}
func ( *serverHandshakeStateTLS13) () bool {
if .c.config.SessionTicketsDisabled {
return false
}
for , := range .clientHello.pskModes {
if == pskModeDHE {
return true
}
}
return false
}
func ( *serverHandshakeStateTLS13) () error {
:= .c
.clientFinished = .suite.finishedHash(.in.trafficSecret, .transcript)
:= &finishedMsg{
verifyData: .clientFinished,
}
.transcript.Write(.marshal())
if !.shouldSendSessionTickets() {
return nil
}
:= .suite.deriveSecret(.masterSecret,
resumptionLabel, .transcript)
:= new(newSessionTicketMsgTLS13)
var [][]byte
for , := range .peerCertificates {
= append(, .Raw)
}
:= sessionStateTLS13{
cipherSuite: .suite.id,
createdAt: uint64(.config.time().Unix()),
resumptionSecret: ,
certificate: Certificate{
Certificate: ,
OCSPStaple: .ocspResponse,
SignedCertificateTimestamps: .scts,
},
}
var error
.label, = .encryptTicket(.marshal())
if != nil {
return
}
.lifetime = uint32(maxSessionTicketLifetime / time.Second)
if , := .writeRecord(recordTypeHandshake, .marshal()); != nil {
return
}
return nil
}
func ( *serverHandshakeStateTLS13) () error {
:= .c
if !.requestClientCert() {
if .config.VerifyConnection != nil {
if := .config.VerifyConnection(.connectionStateLocked()); != nil {
.sendAlert(alertBadCertificate)
return
}
}
return nil
}
, := .readHandshake()
if != nil {
return
}
, := .(*certificateMsgTLS13)
if ! {
.sendAlert(alertUnexpectedMessage)
return unexpectedMessageError(, )
}
.transcript.Write(.marshal())
if := .processCertsFromClient(.certificate); != nil {
return
}
if .config.VerifyConnection != nil {
if := .config.VerifyConnection(.connectionStateLocked()); != nil {
.sendAlert(alertBadCertificate)
return
}
}
if len(.certificate.Certificate) != 0 {
, = .readHandshake()
if != nil {
return
}
, := .(*certificateVerifyMsg)
if ! {
.sendAlert(alertUnexpectedMessage)
return unexpectedMessageError(, )
}
if !isSupportedSignatureAlgorithm(.signatureAlgorithm, supportedSignatureAlgorithms) {
.sendAlert(alertIllegalParameter)
return errors.New("tls: client certificate used with invalid signature algorithm")
}
, , := typeAndHashFromSignatureScheme(.signatureAlgorithm)
if != nil {
return .sendAlert(alertInternalError)
}
if == signaturePKCS1v15 || == crypto.SHA1 {
.sendAlert(alertIllegalParameter)
return errors.New("tls: client certificate used with invalid signature algorithm")
}
:= signedMessage(, clientSignatureContext, .transcript)
if := verifyHandshakeSignature(, .peerCertificates[0].PublicKey,
, , .signature); != nil {
.sendAlert(alertDecryptError)
return errors.New("tls: invalid signature by the client certificate: " + .Error())
}
.transcript.Write(.marshal())
}
if := .sendSessionTickets(); != nil {
return
}
return nil
}
func ( *serverHandshakeStateTLS13) () error {
:= .c
, := .readHandshake()
if != nil {
return
}
, := .(*finishedMsg)
if ! {
.sendAlert(alertUnexpectedMessage)
return unexpectedMessageError(, )
}
if !hmac.Equal(.clientFinished, .verifyData) {
.sendAlert(alertDecryptError)
return errors.New("tls: invalid client finished hash")
}
.in.setTrafficSecret(.suite, .trafficSecret)
return nil
}