]> Cypherpunks.ru repositories - gostls13.git/commitdiff
crypto/tls: improve error message for unsupported certificates in TLS 1.3
authorFilippo Valsorda <hi@filippo.io>
Thu, 29 Nov 2018 07:30:26 +0000 (02:30 -0500)
committerFilippo Valsorda <filippo@golang.org>
Fri, 30 Nov 2018 19:11:39 +0000 (19:11 +0000)
Fixes #28960

Change-Id: I0d049d4776dc42ef165a1da15f63de08677fbb85
Reviewed-on: https://go-review.googlesource.com/c/151661
Run-TryBot: Filippo Valsorda <filippo@golang.org>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Brad Fitzpatrick <bradfitz@golang.org>
Reviewed-by: Adam Langley <agl@golang.org>
src/crypto/tls/auth.go
src/crypto/tls/handshake_client_tls13.go
src/crypto/tls/handshake_server_tls13.go

index b277e74b53d1ce0bcd22be309d8e021ab306ed5e..6fe97185050d61213a0e8d9869fe9a99a16e075d 100644 (file)
@@ -143,7 +143,7 @@ func signatureSchemesForCertificate(version uint16, cert *Certificate) []Signatu
                return nil
        }
 
-       switch priv := priv.Public().(type) {
+       switch pub := priv.Public().(type) {
        case *ecdsa.PublicKey:
                if version != VersionTLS13 {
                        // In TLS 1.2 and earlier, ECDSA algorithms are not
@@ -155,7 +155,7 @@ func signatureSchemesForCertificate(version uint16, cert *Certificate) []Signatu
                                ECDSAWithSHA1,
                        }
                }
-               switch priv.Curve {
+               switch pub.Curve {
                case elliptic.P256():
                        return []SignatureScheme{ECDSAWithP256AndSHA256}
                case elliptic.P384():
@@ -187,3 +187,35 @@ func signatureSchemesForCertificate(version uint16, cert *Certificate) []Signatu
                return nil
        }
 }
+
+// unsupportedCertificateError returns a helpful error for certificates with
+// an unsupported private key.
+func unsupportedCertificateError(cert *Certificate) error {
+       switch cert.PrivateKey.(type) {
+       case rsa.PrivateKey, ecdsa.PrivateKey:
+               return fmt.Errorf("tls: unsupported certificate: private key is %T, expected *%T",
+                       cert.PrivateKey, cert.PrivateKey)
+       }
+
+       signer, ok := cert.PrivateKey.(crypto.Signer)
+       if !ok {
+               return fmt.Errorf("tls: certificate private key (%T) does not implement crypto.Signer",
+                       cert.PrivateKey)
+       }
+
+       switch pub := signer.Public().(type) {
+       case *ecdsa.PublicKey:
+               switch pub.Curve {
+               case elliptic.P256():
+               case elliptic.P384():
+               case elliptic.P521():
+               default:
+                       return fmt.Errorf("tls: unsupported certificate curve (%s)", pub.Curve.Params().Name)
+               }
+       case *rsa.PublicKey:
+       default:
+               return fmt.Errorf("tls: unsupported certificate key (%T)", pub)
+       }
+
+       return fmt.Errorf("tls: internal error: unsupported key (%T)", cert.PrivateKey)
+}
index f8e90f9457196c789a5f190768df67a8fe3595a2..85715b721c0dd8d0bd3a9e7e8c0b913ec47d844f 100644 (file)
@@ -10,7 +10,6 @@ import (
        "crypto/hmac"
        "crypto/rsa"
        "errors"
-       "fmt"
        "hash"
        "sync/atomic"
        "time"
@@ -559,7 +558,7 @@ func (hs *clientHandshakeStateTLS13) sendClientCertificate() error {
        supportedAlgs := signatureSchemesForCertificate(c.vers, cert)
        if supportedAlgs == nil {
                c.sendAlert(alertInternalError)
-               return fmt.Errorf("tls: unsupported certificate key (%T)", cert.PrivateKey)
+               return unsupportedCertificateError(cert)
        }
        // Pick signature scheme in server preference order, as the client
        // preference order is not configurable.
index 6f20d61aa42715dddf1b6c5347459b44d7cd475f..fa76f7ca065679ebb8fc26c973c0078768301f8b 100644 (file)
@@ -10,7 +10,6 @@ import (
        "crypto/hmac"
        "crypto/rsa"
        "errors"
-       "fmt"
        "hash"
        "io"
        "sync/atomic"
@@ -372,7 +371,7 @@ func (hs *serverHandshakeStateTLS13) pickCertificate() error {
        supportedAlgs := signatureSchemesForCertificate(c.vers, certificate)
        if supportedAlgs == nil {
                c.sendAlert(alertInternalError)
-               return fmt.Errorf("tls: unsupported certificate key (%T)", certificate.PrivateKey)
+               return unsupportedCertificateError(certificate)
        }
        // Pick signature scheme in client preference order, as the server
        // preference order is not configurable.