package tls
import (
)
type serverHandshakeState struct {
c *Conn
ctx context.Context
clientHello *clientHelloMsg
hello *serverHelloMsg
suite *cipherSuite
ecdheOk bool
ecSignOk bool
rsaDecryptOk bool
rsaSignOk bool
sessionState *sessionState
finishedHash finishedHash
masterSecret []byte
cert *Certificate
}
func ( *Conn) ( context.Context) error {
, := .readClientHello()
if != nil {
return
}
if .vers == VersionTLS13 {
:= serverHandshakeStateTLS13{
c: ,
ctx: ,
clientHello: ,
}
return .handshake()
}
:= serverHandshakeState{
c: ,
ctx: ,
clientHello: ,
}
return .handshake()
}
func ( *serverHandshakeState) () error {
:= .c
if := .processClientHello(); != nil {
return
}
.buffering = true
if .checkForResumption() {
.didResume = true
if := .doResumeHandshake(); != nil {
return
}
if := .establishKeys(); != nil {
return
}
if := .sendSessionTicket(); != nil {
return
}
if := .sendFinished(.serverFinished[:]); != nil {
return
}
if , := .flush(); != nil {
return
}
.clientFinishedIsFirst = false
if := .readFinished(nil); != nil {
return
}
} else {
if := .pickCipherSuite(); != nil {
return
}
if := .doFullHandshake(); != nil {
return
}
if := .establishKeys(); != nil {
return
}
if := .readFinished(.clientFinished[:]); != nil {
return
}
.clientFinishedIsFirst = true
.buffering = true
if := .sendSessionTicket(); != nil {
return
}
if := .sendFinished(nil); != nil {
return
}
if , := .flush(); != nil {
return
}
}
.ekm = ekmFromMasterSecret(.vers, .suite, .masterSecret, .clientHello.random, .hello.random)
atomic.StoreUint32(&.handshakeStatus, 1)
return nil
}
func ( *Conn) ( context.Context) (*clientHelloMsg, error) {
, := .readHandshake()
if != nil {
return nil,
}
, := .(*clientHelloMsg)
if ! {
.sendAlert(alertUnexpectedMessage)
return nil, unexpectedMessageError(, )
}
var *Config
:= .config
if .config.GetConfigForClient != nil {
:= clientHelloInfo(, , )
if , = .config.GetConfigForClient(); != nil {
.sendAlert(alertInternalError)
return nil,
} else if != nil {
.config =
}
}
.ticketKeys = .ticketKeys()
:= .supportedVersions
if len(.supportedVersions) == 0 {
= supportedVersionsFromMax(.vers)
}
.vers, = .config.mutualVersion(roleServer, )
if ! {
.sendAlert(alertProtocolVersion)
return nil, fmt.Errorf("tls: client offered only unsupported versions: %x", )
}
.haveVers = true
.in.version = .vers
.out.version = .vers
return , nil
}
func ( *serverHandshakeState) () error {
:= .c
.hello = new(serverHelloMsg)
.hello.vers = .vers
:= false
for , := range .clientHello.compressionMethods {
if == compressionNone {
= true
break
}
}
if ! {
.sendAlert(alertHandshakeFailure)
return errors.New("tls: client does not support uncompressed connections")
}
.hello.random = make([]byte, 32)
:= .hello.random
:= .config.maxSupportedVersion(roleServer)
if >= VersionTLS12 && .vers < || testingOnlyForceDowngradeCanary {
if .vers == VersionTLS12 {
copy([24:], downgradeCanaryTLS12)
} else {
copy([24:], downgradeCanaryTLS11)
}
= [:24]
}
, := io.ReadFull(.config.rand(), )
if != nil {
.sendAlert(alertInternalError)
return
}
if len(.clientHello.secureRenegotiation) != 0 {
.sendAlert(alertHandshakeFailure)
return errors.New("tls: initial handshake had non-empty renegotiation extension")
}
.hello.secureRenegotiationSupported = .clientHello.secureRenegotiationSupported
.hello.compressionMethod = compressionNone
if len(.clientHello.serverName) > 0 {
.serverName = .clientHello.serverName
}
, := negotiateALPN(.config.NextProtos, .clientHello.alpnProtocols)
if != nil {
.sendAlert(alertNoApplicationProtocol)
return
}
.hello.alpnProtocol =
.clientProtocol =
.cert, = .config.getCertificate(clientHelloInfo(.ctx, , .clientHello))
if != nil {
if == errNoCertificates {
.sendAlert(alertUnrecognizedName)
} else {
.sendAlert(alertInternalError)
}
return
}
if .clientHello.scts {
.hello.scts = .cert.SignedCertificateTimestamps
}
.ecdheOk = supportsECDHE(.config, .clientHello.supportedCurves, .clientHello.supportedPoints)
if .ecdheOk {
.hello.supportedPoints = []uint8{pointFormatUncompressed}
}
if , := .cert.PrivateKey.(crypto.Signer); {
switch .Public().(type) {
case *ecdsa.PublicKey:
.ecSignOk = true
case ed25519.PublicKey:
.ecSignOk = true
case *rsa.PublicKey:
.rsaSignOk = true
default:
.sendAlert(alertInternalError)
return fmt.Errorf("tls: unsupported signing key type (%T)", .Public())
}
}
if , := .cert.PrivateKey.(crypto.Decrypter); {
switch .Public().(type) {
case *rsa.PublicKey:
.rsaDecryptOk = true
default:
.sendAlert(alertInternalError)
return fmt.Errorf("tls: unsupported decryption key type (%T)", .Public())
}
}
return nil
}
func (, []string) (string, error) {
if len() == 0 || len() == 0 {
return "", nil
}
var bool
for , := range {
for , := range {
if == {
return , nil
}
if == "h2" && == "http/1.1" {
= true
}
}
}
if {
return "", nil
}
return "", fmt.Errorf("tls: client requested unsupported application protocols (%s)", )
}
func ( *Config, []CurveID, []uint8) bool {
:= false
for , := range {
if .supportsCurve() {
= true
break
}
}
:= false
for , := range {
if == pointFormatUncompressed {
= true
break
}
}
return &&
}
func ( *serverHandshakeState) () error {
:= .c
:= cipherSuitesPreferenceOrder
if !hasAESGCMHardwareSupport || !aesgcmPreferred(.clientHello.cipherSuites) {
= cipherSuitesPreferenceOrderNoAES
}
:= .config.cipherSuites()
:= make([]uint16, 0, len())
for , := range {
for , := range {
if == {
= append(, )
break
}
}
}
.suite = selectCipherSuite(, .clientHello.cipherSuites, .cipherSuiteOk)
if .suite == nil {
.sendAlert(alertHandshakeFailure)
return errors.New("tls: no cipher suite supported by both client and server")
}
.cipherSuite = .suite.id
for , := range .clientHello.cipherSuites {
if == TLS_FALLBACK_SCSV {
if .clientHello.vers < .config.maxSupportedVersion(roleServer) {
.sendAlert(alertInappropriateFallback)
return errors.New("tls: client using inappropriate protocol fallback")
}
break
}
}
return nil
}
func ( *serverHandshakeState) ( *cipherSuite) bool {
if .flags&suiteECDHE != 0 {
if !.ecdheOk {
return false
}
if .flags&suiteECSign != 0 {
if !.ecSignOk {
return false
}
} else if !.rsaSignOk {
return false
}
} else if !.rsaDecryptOk {
return false
}
if .c.vers < VersionTLS12 && .flags&suiteTLS12 != 0 {
return false
}
return true
}
func ( *serverHandshakeState) () bool {
:= .c
if .config.SessionTicketsDisabled {
return false
}
, := .decryptTicket(.clientHello.sessionTicket)
if == nil {
return false
}
.sessionState = &sessionState{usedOldKey: }
:= .sessionState.unmarshal()
if ! {
return false
}
:= time.Unix(int64(.sessionState.createdAt), 0)
if .config.time().Sub() > maxSessionTicketLifetime {
return false
}
if .vers != .sessionState.vers {
return false
}
:= false
for , := range .clientHello.cipherSuites {
if == .sessionState.cipherSuite {
= true
break
}
}
if ! {
return false
}
.suite = selectCipherSuite([]uint16{.sessionState.cipherSuite},
.config.cipherSuites(), .cipherSuiteOk)
if .suite == nil {
return false
}
:= len(.sessionState.certificates) != 0
:= requiresClientCert(.config.ClientAuth)
if && ! {
return false
}
if && .config.ClientAuth == NoClientCert {
return false
}
return true
}
func ( *serverHandshakeState) () error {
:= .c
.hello.cipherSuite = .suite.id
.cipherSuite = .suite.id
.hello.sessionId = .clientHello.sessionId
.hello.ticketSupported = .sessionState.usedOldKey
.finishedHash = newFinishedHash(.vers, .suite)
.finishedHash.discardHandshakeBuffer()
.finishedHash.Write(.clientHello.marshal())
.finishedHash.Write(.hello.marshal())
if , := .writeRecord(recordTypeHandshake, .hello.marshal()); != nil {
return
}
if := .processCertsFromClient(Certificate{
Certificate: .sessionState.certificates,
}); != nil {
return
}
if .config.VerifyConnection != nil {
if := .config.VerifyConnection(.connectionStateLocked()); != nil {
.sendAlert(alertBadCertificate)
return
}
}
.masterSecret = .sessionState.masterSecret
return nil
}
func ( *serverHandshakeState) () error {
:= .c
if .clientHello.ocspStapling && len(.cert.OCSPStaple) > 0 {
.hello.ocspStapling = true
}
.hello.ticketSupported = .clientHello.ticketSupported && !.config.SessionTicketsDisabled
.hello.cipherSuite = .suite.id
.finishedHash = newFinishedHash(.c.vers, .suite)
if .config.ClientAuth == NoClientCert {
.finishedHash.discardHandshakeBuffer()
}
.finishedHash.Write(.clientHello.marshal())
.finishedHash.Write(.hello.marshal())
if , := .writeRecord(recordTypeHandshake, .hello.marshal()); != nil {
return
}
:= new(certificateMsg)
.certificates = .cert.Certificate
.finishedHash.Write(.marshal())
if , := .writeRecord(recordTypeHandshake, .marshal()); != nil {
return
}
if .hello.ocspStapling {
:= new(certificateStatusMsg)
.response = .cert.OCSPStaple
.finishedHash.Write(.marshal())
if , := .writeRecord(recordTypeHandshake, .marshal()); != nil {
return
}
}
:= .suite.ka(.vers)
, := .generateServerKeyExchange(.config, .cert, .clientHello, .hello)
if != nil {
.sendAlert(alertHandshakeFailure)
return
}
if != nil {
.finishedHash.Write(.marshal())
if , := .writeRecord(recordTypeHandshake, .marshal()); != nil {
return
}
}
var *certificateRequestMsg
if .config.ClientAuth >= RequestClientCert {
= new(certificateRequestMsg)
.certificateTypes = []byte{
byte(certTypeRSASign),
byte(certTypeECDSASign),
}
if .vers >= VersionTLS12 {
.hasSignatureAlgorithm = true
.supportedSignatureAlgorithms = supportedSignatureAlgorithms
}
if .config.ClientCAs != nil {
.certificateAuthorities = .config.ClientCAs.Subjects()
}
.finishedHash.Write(.marshal())
if , := .writeRecord(recordTypeHandshake, .marshal()); != nil {
return
}
}
:= new(serverHelloDoneMsg)
.finishedHash.Write(.marshal())
if , := .writeRecord(recordTypeHandshake, .marshal()); != nil {
return
}
if , := .flush(); != nil {
return
}
var crypto.PublicKey
, := .readHandshake()
if != nil {
return
}
if .config.ClientAuth >= RequestClientCert {
, := .(*certificateMsg)
if ! {
.sendAlert(alertUnexpectedMessage)
return unexpectedMessageError(, )
}
.finishedHash.Write(.marshal())
if := .processCertsFromClient(Certificate{
Certificate: .certificates,
}); != nil {
return
}
if len(.certificates) != 0 {
= .peerCertificates[0].PublicKey
}
, = .readHandshake()
if != nil {
return
}
}
if .config.VerifyConnection != nil {
if := .config.VerifyConnection(.connectionStateLocked()); != nil {
.sendAlert(alertBadCertificate)
return
}
}
, := .(*clientKeyExchangeMsg)
if ! {
.sendAlert(alertUnexpectedMessage)
return unexpectedMessageError(, )
}
.finishedHash.Write(.marshal())
, := .processClientKeyExchange(.config, .cert, , .vers)
if != nil {
.sendAlert(alertHandshakeFailure)
return
}
.masterSecret = masterFromPreMasterSecret(.vers, .suite, , .clientHello.random, .hello.random)
if := .config.writeKeyLog(keyLogLabelTLS12, .clientHello.random, .masterSecret); != nil {
.sendAlert(alertInternalError)
return
}
if len(.peerCertificates) > 0 {
, = .readHandshake()
if != nil {
return
}
, := .(*certificateVerifyMsg)
if ! {
.sendAlert(alertUnexpectedMessage)
return unexpectedMessageError(, )
}
var uint8
var crypto.Hash
if .vers >= VersionTLS12 {
if !isSupportedSignatureAlgorithm(.signatureAlgorithm, .supportedSignatureAlgorithms) {
.sendAlert(alertIllegalParameter)
return errors.New("tls: client certificate used with invalid signature algorithm")
}
, , = typeAndHashFromSignatureScheme(.signatureAlgorithm)
if != nil {
return .sendAlert(alertInternalError)
}
} else {
, , = legacyTypeAndHashFromPublicKey()
if != nil {
.sendAlert(alertIllegalParameter)
return
}
}
:= .finishedHash.hashForClientCertificate(, , .masterSecret)
if := verifyHandshakeSignature(, , , , .signature); != nil {
.sendAlert(alertDecryptError)
return errors.New("tls: invalid signature by the client certificate: " + .Error())
}
.finishedHash.Write(.marshal())
}
.finishedHash.discardHandshakeBuffer()
return nil
}
func ( *serverHandshakeState) () error {
:= .c
, , , , , :=
keysFromMasterSecret(.vers, .suite, .masterSecret, .clientHello.random, .hello.random, .suite.macLen, .suite.keyLen, .suite.ivLen)
var , any
var , hash.Hash
if .suite.aead == nil {
= .suite.cipher(, , true )
= .suite.mac()
= .suite.cipher(, , false )
= .suite.mac()
} else {
= .suite.aead(, )
= .suite.aead(, )
}
.in.prepareCipherSpec(.vers, , )
.out.prepareCipherSpec(.vers, , )
return nil
}
func ( *serverHandshakeState) ( []byte) error {
:= .c
if := .readChangeCipherSpec(); != nil {
return
}
, := .readHandshake()
if != nil {
return
}
, := .(*finishedMsg)
if ! {
.sendAlert(alertUnexpectedMessage)
return unexpectedMessageError(, )
}
:= .finishedHash.clientSum(.masterSecret)
if len() != len(.verifyData) ||
subtle.ConstantTimeCompare(, .verifyData) != 1 {
.sendAlert(alertHandshakeFailure)
return errors.New("tls: client's Finished message is incorrect")
}
.finishedHash.Write(.marshal())
copy(, )
return nil
}
func ( *serverHandshakeState) () error {
if !.hello.ticketSupported {
return nil
}
:= .c
:= new(newSessionTicketMsg)
:= uint64(.config.time().Unix())
if .sessionState != nil {
= .sessionState.createdAt
}
var [][]byte
for , := range .peerCertificates {
= append(, .Raw)
}
:= sessionState{
vers: .vers,
cipherSuite: .suite.id,
createdAt: ,
masterSecret: .masterSecret,
certificates: ,
}
var error
.ticket, = .encryptTicket(.marshal())
if != nil {
return
}
.finishedHash.Write(.marshal())
if , := .writeRecord(recordTypeHandshake, .marshal()); != nil {
return
}
return nil
}
func ( *serverHandshakeState) ( []byte) error {
:= .c
if , := .writeRecord(recordTypeChangeCipherSpec, []byte{1}); != nil {
return
}
:= new(finishedMsg)
.verifyData = .finishedHash.serverSum(.masterSecret)
.finishedHash.Write(.marshal())
if , := .writeRecord(recordTypeHandshake, .marshal()); != nil {
return
}
copy(, .verifyData)
return nil
}
func ( *Conn) ( Certificate) error {
:= .Certificate
:= make([]*x509.Certificate, len())
var error
for , := range {
if [], = x509.ParseCertificate(); != nil {
.sendAlert(alertBadCertificate)
return errors.New("tls: failed to parse client certificate: " + .Error())
}
}
if len() == 0 && requiresClientCert(.config.ClientAuth) {
.sendAlert(alertBadCertificate)
return errors.New("tls: client didn't provide a certificate")
}
if .config.ClientAuth >= VerifyClientCertIfGiven && len() > 0 {
:= x509.VerifyOptions{
Roots: .config.ClientCAs,
CurrentTime: .config.time(),
Intermediates: x509.NewCertPool(),
KeyUsages: []x509.ExtKeyUsage{x509.ExtKeyUsageClientAuth},
}
for , := range [1:] {
.Intermediates.AddCert()
}
, := [0].Verify()
if != nil {
.sendAlert(alertBadCertificate)
return errors.New("tls: failed to verify client certificate: " + .Error())
}
.verifiedChains =
}
.peerCertificates =
.ocspResponse = .OCSPStaple
.scts = .SignedCertificateTimestamps
if len() > 0 {
switch [0].PublicKey.(type) {
case *ecdsa.PublicKey, *rsa.PublicKey, ed25519.PublicKey:
default:
.sendAlert(alertUnsupportedCertificate)
return fmt.Errorf("tls: client certificate contains an unsupported public key of type %T", [0].PublicKey)
}
}
if .config.VerifyPeerCertificate != nil {
if := .config.VerifyPeerCertificate(, .verifiedChains); != nil {
.sendAlert(alertBadCertificate)
return
}
}
return nil
}
func ( context.Context, *Conn, *clientHelloMsg) *ClientHelloInfo {
:= .supportedVersions
if len(.supportedVersions) == 0 {
= supportedVersionsFromMax(.vers)
}
return &ClientHelloInfo{
CipherSuites: .cipherSuites,
ServerName: .serverName,
SupportedCurves: .supportedCurves,
SupportedPoints: .supportedPoints,
SignatureSchemes: .supportedSignatureAlgorithms,
SupportedProtos: .alpnProtocols,
SupportedVersions: ,
Conn: .conn,
config: .config,
ctx: ,
}
}