diff options
Diffstat (limited to 'libgo/go/crypto/tls/handshake_server.go')
-rw-r--r-- | libgo/go/crypto/tls/handshake_server.go | 122 |
1 files changed, 81 insertions, 41 deletions
diff --git a/libgo/go/crypto/tls/handshake_server.go b/libgo/go/crypto/tls/handshake_server.go index e16cddcb..1aac729 100644 --- a/libgo/go/crypto/tls/handshake_server.go +++ b/libgo/go/crypto/tls/handshake_server.go @@ -35,6 +35,7 @@ type serverHandshakeState struct { } // serverHandshake performs a TLS handshake as a server. +// c.out.Mutex <= L; c.handshakeMutex <= L. func (c *Conn) serverHandshake() error { config := c.config @@ -51,6 +52,7 @@ func (c *Conn) serverHandshake() error { } // For an overview of TLS handshaking, see https://tools.ietf.org/html/rfc5246#section-7.3 + c.buffering = true if isResume { // The client has included a session ticket and so we do an abbreviated handshake. if err := hs.doResumeHandshake(); err != nil { @@ -67,9 +69,13 @@ func (c *Conn) serverHandshake() error { return err } } - if err := hs.sendFinished(c.firstFinished[:]); err != nil { + if err := hs.sendFinished(c.serverFinished[:]); err != nil { return err } + if _, err := c.flush(); err != nil { + return err + } + c.clientFinishedIsFirst = false if err := hs.readFinished(nil); err != nil { return err } @@ -83,15 +89,20 @@ func (c *Conn) serverHandshake() error { if err := hs.establishKeys(); err != nil { return err } - if err := hs.readFinished(c.firstFinished[:]); err != nil { + if err := hs.readFinished(c.clientFinished[:]); err != nil { return err } + c.clientFinishedIsFirst = true + c.buffering = true if err := hs.sendSessionTicket(); err != nil { return err } if err := hs.sendFinished(nil); err != nil { return err } + if _, err := c.flush(); err != nil { + return err + } } c.handshakeComplete = true @@ -165,7 +176,13 @@ Curves: c.sendAlert(alertInternalError) return false, err } - hs.hello.secureRenegotiation = hs.clientHello.secureRenegotiation + + if len(hs.clientHello.secureRenegotiation) != 0 { + c.sendAlert(alertHandshakeFailure) + return false, errors.New("tls: initial handshake had non-empty renegotiation extension") + } + + hs.hello.secureRenegotiationSupported = hs.clientHello.secureRenegotiationSupported hs.hello.compressionMethod = compressionNone if len(hs.clientHello.serverName) > 0 { c.serverName = hs.clientHello.serverName @@ -187,12 +204,13 @@ Curves: } } - if hs.cert, err = config.getCertificate(&ClientHelloInfo{ + hs.cert, err = config.getCertificate(&ClientHelloInfo{ CipherSuites: hs.clientHello.cipherSuites, ServerName: hs.clientHello.serverName, SupportedCurves: hs.clientHello.supportedCurves, SupportedPoints: hs.clientHello.supportedPoints, - }); err != nil { + }) + if err != nil { c.sendAlert(alertInternalError) return false, err } @@ -208,7 +226,7 @@ Curves: hs.rsaSignOk = true default: c.sendAlert(alertInternalError) - return false, fmt.Errorf("crypto/tls: unsupported signing key type (%T)", priv.Public()) + return false, fmt.Errorf("tls: unsupported signing key type (%T)", priv.Public()) } } if priv, ok := hs.cert.PrivateKey.(crypto.Decrypter); ok { @@ -217,7 +235,7 @@ Curves: hs.rsaDecryptOk = true default: c.sendAlert(alertInternalError) - return false, fmt.Errorf("crypto/tls: unsupported decryption key type (%T)", priv.Public()) + return false, fmt.Errorf("tls: unsupported decryption key type (%T)", priv.Public()) } } @@ -245,7 +263,7 @@ Curves: return false, errors.New("tls: no cipher suite supported by both client and server") } - // See https://tools.ietf.org/html/draft-ietf-tls-downgrade-scsv-00. + // See https://tools.ietf.org/html/rfc7507. for _, id := range hs.clientHello.cipherSuites { if id == TLS_FALLBACK_SCSV { // The client is doing a fallback connection. @@ -274,10 +292,8 @@ func (hs *serverHandshakeState) checkForResumption() bool { return false } - if hs.sessionState.vers > hs.clientHello.vers { - return false - } - if vers, ok := c.config.mutualVersion(hs.sessionState.vers); !ok || vers != hs.sessionState.vers { + // Never resume a session for a different TLS version. + if c.vers != hs.sessionState.vers { return false } @@ -322,7 +338,9 @@ func (hs *serverHandshakeState) doResumeHandshake() error { hs.finishedHash.discardHandshakeBuffer() hs.finishedHash.Write(hs.clientHello.marshal()) hs.finishedHash.Write(hs.hello.marshal()) - c.writeRecord(recordTypeHandshake, hs.hello.marshal()) + if _, err := c.writeRecord(recordTypeHandshake, hs.hello.marshal()); err != nil { + return err + } if len(hs.sessionState.certificates) > 0 { if _, err := hs.processCertsFromClient(hs.sessionState.certificates); err != nil { @@ -354,19 +372,25 @@ func (hs *serverHandshakeState) doFullHandshake() error { } hs.finishedHash.Write(hs.clientHello.marshal()) hs.finishedHash.Write(hs.hello.marshal()) - c.writeRecord(recordTypeHandshake, hs.hello.marshal()) + if _, err := c.writeRecord(recordTypeHandshake, hs.hello.marshal()); err != nil { + return err + } certMsg := new(certificateMsg) certMsg.certificates = hs.cert.Certificate hs.finishedHash.Write(certMsg.marshal()) - c.writeRecord(recordTypeHandshake, certMsg.marshal()) + if _, err := c.writeRecord(recordTypeHandshake, certMsg.marshal()); err != nil { + return err + } if hs.hello.ocspStapling { certStatus := new(certificateStatusMsg) certStatus.statusType = statusTypeOCSP certStatus.response = hs.cert.OCSPStaple hs.finishedHash.Write(certStatus.marshal()) - c.writeRecord(recordTypeHandshake, certStatus.marshal()) + if _, err := c.writeRecord(recordTypeHandshake, certStatus.marshal()); err != nil { + return err + } } keyAgreement := hs.suite.ka(c.vers) @@ -377,7 +401,9 @@ func (hs *serverHandshakeState) doFullHandshake() error { } if skx != nil { hs.finishedHash.Write(skx.marshal()) - c.writeRecord(recordTypeHandshake, skx.marshal()) + if _, err := c.writeRecord(recordTypeHandshake, skx.marshal()); err != nil { + return err + } } if config.ClientAuth >= RequestClientCert { @@ -401,12 +427,20 @@ func (hs *serverHandshakeState) doFullHandshake() error { certReq.certificateAuthorities = config.ClientCAs.Subjects() } hs.finishedHash.Write(certReq.marshal()) - c.writeRecord(recordTypeHandshake, certReq.marshal()) + if _, err := c.writeRecord(recordTypeHandshake, certReq.marshal()); err != nil { + return err + } } helloDone := new(serverHelloDoneMsg) hs.finishedHash.Write(helloDone.marshal()) - c.writeRecord(recordTypeHandshake, helloDone.marshal()) + if _, err := c.writeRecord(recordTypeHandshake, helloDone.marshal()); err != nil { + return err + } + + if _, err := c.flush(); err != nil { + return err + } var pub crypto.PublicKey // public key for client auth, if any @@ -462,7 +496,7 @@ func (hs *serverHandshakeState) doFullHandshake() error { // 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 + // 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. @@ -499,7 +533,7 @@ func (hs *serverHandshakeState) doFullHandshake() error { switch key := pub.(type) { case *ecdsa.PublicKey: if signatureAndHash.signature != signatureECDSA { - err = errors.New("bad signature type for client's ECDSA certificate") + err = errors.New("tls: bad signature type for client's ECDSA certificate") break } ecdsaSig := new(ecdsaSignature) @@ -507,7 +541,7 @@ func (hs *serverHandshakeState) doFullHandshake() error { break } if ecdsaSig.R.Sign() <= 0 || ecdsaSig.S.Sign() <= 0 { - err = errors.New("ECDSA signature contained zero or negative values") + err = errors.New("tls: ECDSA signature contained zero or negative values") break } var digest []byte @@ -515,11 +549,11 @@ func (hs *serverHandshakeState) doFullHandshake() error { break } if !ecdsa.Verify(key, digest, ecdsaSig.R, ecdsaSig.S) { - err = errors.New("ECDSA verification failure") + err = errors.New("tls: ECDSA verification failure") } case *rsa.PublicKey: if signatureAndHash.signature != signatureRSA { - err = errors.New("bad signature type for client's RSA certificate") + err = errors.New("tls: bad signature type for client's RSA certificate") break } var digest []byte @@ -571,8 +605,8 @@ func (hs *serverHandshakeState) readFinished(out []byte) error { c := hs.c c.readRecord(recordTypeChangeCipherSpec) - if err := c.in.error(); err != nil { - return err + if c.in.err != nil { + return c.in.err } if hs.hello.nextProtoNeg { @@ -632,7 +666,9 @@ func (hs *serverHandshakeState) sendSessionTicket() error { } hs.finishedHash.Write(m.marshal()) - c.writeRecord(recordTypeHandshake, m.marshal()) + if _, err := c.writeRecord(recordTypeHandshake, m.marshal()); err != nil { + return err + } return nil } @@ -640,12 +676,16 @@ func (hs *serverHandshakeState) sendSessionTicket() error { func (hs *serverHandshakeState) sendFinished(out []byte) error { c := hs.c - c.writeRecord(recordTypeChangeCipherSpec, []byte{1}) + if _, err := c.writeRecord(recordTypeChangeCipherSpec, []byte{1}); err != nil { + return err + } finished := new(finishedMsg) finished.verifyData = hs.finishedHash.serverSum(hs.masterSecret) hs.finishedHash.Write(finished.marshal()) - c.writeRecord(recordTypeHandshake, finished.marshal()) + if _, err := c.writeRecord(recordTypeHandshake, finished.marshal()); err != nil { + return err + } c.cipherSuite = hs.suite.id copy(out, finished.verifyData) @@ -690,20 +730,20 @@ func (hs *serverHandshakeState) processCertsFromClient(certificates [][]byte) (c c.verifiedChains = chains } - if len(certs) > 0 { - var pub crypto.PublicKey - switch key := certs[0].PublicKey.(type) { - case *ecdsa.PublicKey, *rsa.PublicKey: - pub = key - default: - c.sendAlert(alertUnsupportedCertificate) - return nil, fmt.Errorf("tls: client's certificate contains an unsupported public key of type %T", certs[0].PublicKey) - } - c.peerCertificates = certs - return pub, nil + if len(certs) == 0 { + return nil, nil } - return nil, nil + var pub crypto.PublicKey + switch key := certs[0].PublicKey.(type) { + case *ecdsa.PublicKey, *rsa.PublicKey: + pub = key + default: + c.sendAlert(alertUnsupportedCertificate) + return nil, fmt.Errorf("tls: client's certificate contains an unsupported public key of type %T", certs[0].PublicKey) + } + c.peerCertificates = certs + return pub, nil } // setCipherSuite sets a cipherSuite with the given id as the serverHandshakeState |