libgo: update to Go1.14beta1
[platform/upstream/gcc.git] / libgo / go / crypto / tls / handshake_server.go
index a3d8848..b16415a 100644 (file)
@@ -24,7 +24,7 @@ type serverHandshakeState struct {
        clientHello  *clientHelloMsg
        hello        *serverHelloMsg
        suite        *cipherSuite
-       ecdhOk       bool
+       ecdheOk      bool
        ecSignOk     bool
        rsaDecryptOk bool
        rsaSignOk    bool
@@ -157,7 +157,7 @@ func (c *Conn) readClientHello() (*clientHelloMsg, error) {
        if len(clientHello.supportedVersions) == 0 {
                clientVersions = supportedVersionsFromMax(clientHello.vers)
        }
-       c.vers, ok = c.config.mutualVersion(false, clientVersions)
+       c.vers, ok = c.config.mutualVersion(clientVersions)
        if !ok {
                c.sendAlert(alertProtocolVersion)
                return nil, fmt.Errorf("tls: client offered only unsupported versions: %x", clientVersions)
@@ -175,27 +175,6 @@ func (hs *serverHandshakeState) processClientHello() error {
        hs.hello = new(serverHelloMsg)
        hs.hello.vers = c.vers
 
-       supportedCurve := false
-       preferredCurves := c.config.curvePreferences()
-Curves:
-       for _, curve := range hs.clientHello.supportedCurves {
-               for _, supported := range preferredCurves {
-                       if supported == curve {
-                               supportedCurve = true
-                               break Curves
-                       }
-               }
-       }
-
-       supportedPointFormat := false
-       for _, pointFormat := range hs.clientHello.supportedPoints {
-               if pointFormat == pointFormatUncompressed {
-                       supportedPointFormat = true
-                       break
-               }
-       }
-       hs.ecdhOk = supportedCurve && supportedPointFormat
-
        foundCompression := false
        // We only support null compression, so check that the client offered it.
        for _, compression := range hs.clientHello.compressionMethods {
@@ -213,7 +192,7 @@ Curves:
        hs.hello.random = make([]byte, 32)
        serverRandom := hs.hello.random
        // Downgrade protection canaries. See RFC 8446, Section 4.1.3.
-       maxVers := c.config.maxSupportedVersion(false)
+       maxVers := c.config.maxSupportedVersion()
        if maxVers >= VersionTLS12 && c.vers < maxVers {
                if c.vers == VersionTLS12 {
                        copy(serverRandom[24:], downgradeCanaryTLS12)
@@ -244,26 +223,32 @@ Curves:
                        hs.hello.alpnProtocol = selectedProto
                        c.clientProtocol = selectedProto
                }
-       } else {
-               // Although sending an empty NPN extension is reasonable, Firefox has
-               // had a bug around this. Best to send nothing at all if
-               // c.config.NextProtos is empty. See
-               // https://golang.org/issue/5445.
-               if hs.clientHello.nextProtoNeg && len(c.config.NextProtos) > 0 {
-                       hs.hello.nextProtoNeg = true
-                       hs.hello.nextProtos = c.config.NextProtos
-               }
        }
 
        hs.cert, err = c.config.getCertificate(clientHelloInfo(c, hs.clientHello))
        if err != nil {
-               c.sendAlert(alertInternalError)
+               if err == errNoCertificates {
+                       c.sendAlert(alertUnrecognizedName)
+               } else {
+                       c.sendAlert(alertInternalError)
+               }
                return err
        }
        if hs.clientHello.scts {
                hs.hello.scts = hs.cert.SignedCertificateTimestamps
        }
 
+       hs.ecdheOk = supportsECDHE(c.config, hs.clientHello.supportedCurves, hs.clientHello.supportedPoints)
+
+       if hs.ecdheOk {
+               // Although omitting the ec_point_formats extension is permitted, some
+               // old OpenSSL version will refuse to handshake if not present.
+               //
+               // Per RFC 4492, section 5.1.2, implementations MUST support the
+               // uncompressed point format. See golang.org/issue/31943.
+               hs.hello.supportedPoints = []uint8{pointFormatUncompressed}
+       }
+
        if priv, ok := hs.cert.PrivateKey.(crypto.Signer); ok {
                switch priv.Public().(type) {
                case *ecdsa.PublicKey:
@@ -290,6 +275,28 @@ Curves:
        return nil
 }
 
+// supportsECDHE returns whether ECDHE key exchanges can be used with this
+// pre-TLS 1.3 client.
+func supportsECDHE(c *Config, supportedCurves []CurveID, supportedPoints []uint8) bool {
+       supportsCurve := false
+       for _, curve := range supportedCurves {
+               if c.supportsCurve(curve) {
+                       supportsCurve = true
+                       break
+               }
+       }
+
+       supportsPointFormat := false
+       for _, pointFormat := range supportedPoints {
+               if pointFormat == pointFormatUncompressed {
+                       supportsPointFormat = true
+                       break
+               }
+       }
+
+       return supportsCurve && supportsPointFormat
+}
+
 func (hs *serverHandshakeState) pickCipherSuite() error {
        c := hs.c
 
@@ -302,12 +309,7 @@ func (hs *serverHandshakeState) pickCipherSuite() error {
                supportedList = c.config.cipherSuites()
        }
 
-       for _, id := range preferenceList {
-               if hs.setCipherSuite(id, supportedList, c.vers) {
-                       break
-               }
-       }
-
+       hs.suite = selectCipherSuite(preferenceList, supportedList, hs.cipherSuiteOk)
        if hs.suite == nil {
                c.sendAlert(alertHandshakeFailure)
                return errors.New("tls: no cipher suite supported by both client and server")
@@ -316,7 +318,7 @@ func (hs *serverHandshakeState) pickCipherSuite() error {
        for _, id := range hs.clientHello.cipherSuites {
                if id == TLS_FALLBACK_SCSV {
                        // The client is doing a fallback connection. See RFC 7507.
-                       if hs.clientHello.vers < c.config.maxSupportedVersion(false) {
+                       if hs.clientHello.vers < c.config.maxSupportedVersion() {
                                c.sendAlert(alertInappropriateFallback)
                                return errors.New("tls: client using inappropriate protocol fallback")
                        }
@@ -327,6 +329,27 @@ func (hs *serverHandshakeState) pickCipherSuite() error {
        return nil
 }
 
+func (hs *serverHandshakeState) cipherSuiteOk(c *cipherSuite) bool {
+       if c.flags&suiteECDHE != 0 {
+               if !hs.ecdheOk {
+                       return false
+               }
+               if c.flags&suiteECSign != 0 {
+                       if !hs.ecSignOk {
+                               return false
+                       }
+               } else if !hs.rsaSignOk {
+                       return false
+               }
+       } else if !hs.rsaDecryptOk {
+               return false
+       }
+       if hs.c.vers < VersionTLS12 && c.flags&suiteTLS12 != 0 {
+               return false
+       }
+       return true
+}
+
 // checkForResumption reports whether we should perform resumption on this connection.
 func (hs *serverHandshakeState) checkForResumption() bool {
        c := hs.c
@@ -363,7 +386,9 @@ func (hs *serverHandshakeState) checkForResumption() bool {
        }
 
        // Check that we also support the ciphersuite from the session.
-       if !hs.setCipherSuite(hs.sessionState.cipherSuite, c.config.cipherSuites(), hs.sessionState.vers) {
+       hs.suite = selectCipherSuite([]uint16{hs.sessionState.cipherSuite},
+               c.config.cipherSuites(), hs.cipherSuiteOk)
+       if hs.suite == nil {
                return false
        }
 
@@ -467,7 +492,7 @@ func (hs *serverHandshakeState) doFullHandshake() error {
                }
                if c.vers >= VersionTLS12 {
                        certReq.hasSignatureAlgorithm = true
-                       certReq.supportedSignatureAlgorithms = supportedSignatureAlgorithmsTLS12
+                       certReq.supportedSignatureAlgorithms = supportedSignatureAlgorithms
                }
 
                // An empty list of certificateAuthorities signals to
@@ -562,20 +587,29 @@ func (hs *serverHandshakeState) doFullHandshake() error {
                        return unexpectedMessageError(certVerify, msg)
                }
 
-               // Determine the signature type.
-               _, sigType, hashFunc, err := pickSignatureAlgorithm(pub, []SignatureScheme{certVerify.signatureAlgorithm}, certReq.supportedSignatureAlgorithms, c.vers)
-               if err != nil {
-                       c.sendAlert(alertIllegalParameter)
-                       return err
+               var sigType uint8
+               var sigHash crypto.Hash
+               if c.vers >= VersionTLS12 {
+                       if !isSupportedSignatureAlgorithm(certVerify.signatureAlgorithm, certReq.supportedSignatureAlgorithms) {
+                               c.sendAlert(alertIllegalParameter)
+                               return errors.New("tls: client certificate used with invalid signature algorithm")
+                       }
+                       sigType, sigHash, err = typeAndHashFromSignatureScheme(certVerify.signatureAlgorithm)
+                       if err != nil {
+                               return c.sendAlert(alertInternalError)
+                       }
+               } else {
+                       sigType, sigHash, err = legacyTypeAndHashFromPublicKey(pub)
+                       if err != nil {
+                               c.sendAlert(alertIllegalParameter)
+                               return err
+                       }
                }
 
-               signed, err := hs.finishedHash.hashForClientCertificate(sigType, hashFunc, hs.masterSecret)
-               if err == nil {
-                       err = verifyHandshakeSignature(sigType, pub, hashFunc, signed, certVerify.signature)
-               }
-               if err != nil {
-                       c.sendAlert(alertBadCertificate)
-                       return errors.New("tls: could not validate signature of connection nonces: " + err.Error())
+               signed := hs.finishedHash.hashForClientCertificate(sigType, sigHash, hs.masterSecret)
+               if err := verifyHandshakeSignature(sigType, pub, sigHash, signed, certVerify.signature); err != nil {
+                       c.sendAlert(alertDecryptError)
+                       return errors.New("tls: invalid signature by the client certificate: " + err.Error())
                }
 
                hs.finishedHash.Write(certVerify.marshal())
@@ -618,20 +652,6 @@ func (hs *serverHandshakeState) readFinished(out []byte) error {
                return err
        }
 
-       if hs.hello.nextProtoNeg {
-               msg, err := c.readHandshake()
-               if err != nil {
-                       return err
-               }
-               nextProto, ok := msg.(*nextProtoMsg)
-               if !ok {
-                       c.sendAlert(alertUnexpectedMessage)
-                       return unexpectedMessageError(nextProto, msg)
-               }
-               hs.finishedHash.Write(nextProto.marshal())
-               c.clientProtocol = nextProto.proto
-       }
-
        msg, err := c.readHandshake()
        if err != nil {
                return err
@@ -740,7 +760,7 @@ func (c *Conn) processCertsFromClient(certificate Certificate) error {
                chains, err := certs[0].Verify(opts)
                if err != nil {
                        c.sendAlert(alertBadCertificate)
-                       return errors.New("tls: failed to verify client's certificate: " + err.Error())
+                       return errors.New("tls: failed to verify client certificate: " + err.Error())
                }
 
                c.verifiedChains = chains
@@ -761,7 +781,7 @@ func (c *Conn) processCertsFromClient(certificate Certificate) error {
        case *ecdsa.PublicKey, *rsa.PublicKey, ed25519.PublicKey:
        default:
                c.sendAlert(alertUnsupportedCertificate)
-               return fmt.Errorf("tls: client's certificate contains an unsupported public key of type %T", certs[0].PublicKey)
+               return fmt.Errorf("tls: client certificate contains an unsupported public key of type %T", certs[0].PublicKey)
        }
 
        c.peerCertificates = certs
@@ -770,43 +790,6 @@ func (c *Conn) processCertsFromClient(certificate Certificate) error {
        return nil
 }
 
-// setCipherSuite sets a cipherSuite with the given id as the serverHandshakeState
-// suite if that cipher suite is acceptable to use.
-// It returns a bool indicating if the suite was set.
-func (hs *serverHandshakeState) setCipherSuite(id uint16, supportedCipherSuites []uint16, version uint16) bool {
-       for _, supported := range supportedCipherSuites {
-               if id != supported {
-                       continue
-               }
-               candidate := cipherSuiteByID(id)
-               if candidate == nil {
-                       continue
-               }
-               // Don't select a ciphersuite which we can't
-               // support for this client.
-               if candidate.flags&suiteECDHE != 0 {
-                       if !hs.ecdhOk {
-                               continue
-                       }
-                       if candidate.flags&suiteECSign != 0 {
-                               if !hs.ecSignOk {
-                                       continue
-                               }
-                       } else if !hs.rsaSignOk {
-                               continue
-                       }
-               } else if !hs.rsaDecryptOk {
-                       continue
-               }
-               if version < VersionTLS12 && candidate.flags&suiteTLS12 != 0 {
-                       continue
-               }
-               hs.suite = candidate
-               return true
-       }
-       return false
-}
-
 func clientHelloInfo(c *Conn, clientHello *clientHelloMsg) *ClientHelloInfo {
        supportedVersions := clientHello.supportedVersions
        if len(clientHello.supportedVersions) == 0 {
@@ -822,5 +805,6 @@ func clientHelloInfo(c *Conn, clientHello *clientHelloMsg) *ClientHelloInfo {
                SupportedProtos:   clientHello.alpnProtocols,
                SupportedVersions: supportedVersions,
                Conn:              c.conn,
+               config:            c.config,
        }
 }