From 21a3c0f482b2e9ed5cf40560cb4c7da320caae0c Mon Sep 17 00:00:00 2001 From: Andreas Auernhammer Date: Wed, 25 Apr 2018 00:47:30 +0200 Subject: [PATCH] disable elliptic curves P-384 and P-521 for TLS. (#5845) This change disables the non-constant-time implementations of P-384 and P-521. As a consequence a client using just these curves cannot connect to the server. This should be no real issues because (all) clients at least support P-256. Further this change also rejects ECDSA private keys of P-384 and P-521. While non-constant-time implementations for the ECDHE exchange don't expose an obvious vulnerability, using P-384 or P-521 keys for the ECDSA signature may allow pratical timing attacks. Fixes #5844 --- cmd/certs.go | 12 ++++++++++++ cmd/http/server.go | 4 ++++ docs/tls/README.md | 3 +++ 3 files changed, 19 insertions(+) diff --git a/cmd/certs.go b/cmd/certs.go index 78f147b68..609263c2b 100644 --- a/cmd/certs.go +++ b/cmd/certs.go @@ -17,6 +17,8 @@ package cmd import ( + "crypto" + "crypto/ecdsa" "crypto/tls" "crypto/x509" "encoding/pem" @@ -142,6 +144,16 @@ func getSSLConfig() (x509Certs []*x509.Certificate, rootCAs *x509.CertPool, tlsC if cert, err = loadX509KeyPair(getPublicCertFile(), getPrivateKeyFile()); err != nil { return nil, nil, nil, false, err } + // Ensure that the private key is not a P-384 or P-521 EC key. + // The Go TLS stack does not provide constant-time implementations of P-384 and P-521. + if priv, ok := cert.PrivateKey.(crypto.Signer); ok { + if pub, ok := priv.Public().(*ecdsa.PublicKey); ok { + if name := pub.Params().Name; name == "P-384" || name == "P-521" { // unfortunately there is no cleaner way to check + return nil, nil, nil, false, fmt.Errorf("TLS: the ECDSA curve '%s' is not supported", name) + } + } + + } tlsCert = &cert diff --git a/cmd/http/server.go b/cmd/http/server.go index 91ad0e84e..964a17389 100644 --- a/cmd/http/server.go +++ b/cmd/http/server.go @@ -172,6 +172,9 @@ var defaultCipherSuites = []uint16{ tls.TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384, } +// Go only provides constant-time implementations of Curve25519 and NIST P-256 curve. +var secureCurves = []tls.CurveID{tls.X25519, tls.CurveP256} + // NewServer - creates new HTTP server using given arguments. func NewServer(addrs []string, handler http.Handler, certificate *tls.Certificate) *Server { var tlsConfig *tls.Config @@ -179,6 +182,7 @@ func NewServer(addrs []string, handler http.Handler, certificate *tls.Certificat tlsConfig = &tls.Config{ PreferServerCipherSuites: true, CipherSuites: defaultCipherSuites, + CurvePreferences: secureCurves, MinVersion: tls.VersionTLS12, NextProtos: []string{"http/1.1", "h2"}, } diff --git a/docs/tls/README.md b/docs/tls/README.md index b5c9bfc05..43f16777c 100644 --- a/docs/tls/README.md +++ b/docs/tls/README.md @@ -43,6 +43,9 @@ or protect the private key additionally with a password: ```sh openssl ecparam -genkey -name prime256v1 | openssl ec -aes256 -out private.key -passout pass:PASSWORD ``` + +Notice that the NIST curves P-384 and P-521 are not supported yet. + 2. **RSA:** ```sh openssl genrsa -out private.key 2048