mirror of
https://github.com/caddyserver/caddy.git
synced 2024-12-23 22:27:38 -05:00
tls: Prefer ChaCha20 if AES-NI instruction set is unavailable (#1675)
Fixes #1674
This commit is contained in:
parent
8d3f336971
commit
b0cf3f0d2d
3 changed files with 52 additions and 18 deletions
|
@ -9,6 +9,7 @@ import (
|
||||||
"net/url"
|
"net/url"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
|
"github.com/codahale/aesnicheck"
|
||||||
"github.com/mholt/caddy"
|
"github.com/mholt/caddy"
|
||||||
"github.com/xenolf/lego/acme"
|
"github.com/xenolf/lego/acme"
|
||||||
)
|
)
|
||||||
|
@ -294,7 +295,7 @@ func (c *Config) buildStandardTLSConfig() error {
|
||||||
|
|
||||||
// default cipher suites
|
// default cipher suites
|
||||||
if len(config.CipherSuites) == 0 {
|
if len(config.CipherSuites) == 0 {
|
||||||
config.CipherSuites = defaultCiphers
|
config.CipherSuites = getPreferredDefaultCiphers()
|
||||||
}
|
}
|
||||||
|
|
||||||
// for security, ensure TLS_FALLBACK_SCSV is always included first
|
// for security, ensure TLS_FALLBACK_SCSV is always included first
|
||||||
|
@ -380,7 +381,7 @@ func RegisterConfigGetter(serverType string, fn ConfigGetter) {
|
||||||
func SetDefaultTLSParams(config *Config) {
|
func SetDefaultTLSParams(config *Config) {
|
||||||
// If no ciphers provided, use default list
|
// If no ciphers provided, use default list
|
||||||
if len(config.Ciphers) == 0 {
|
if len(config.Ciphers) == 0 {
|
||||||
config.Ciphers = defaultCiphers
|
config.Ciphers = getPreferredDefaultCiphers()
|
||||||
}
|
}
|
||||||
|
|
||||||
// Not a cipher suite, but still important for mitigating protocol downgrade attacks
|
// Not a cipher suite, but still important for mitigating protocol downgrade attacks
|
||||||
|
@ -464,6 +465,35 @@ var defaultCiphers = []uint16{
|
||||||
tls.TLS_RSA_WITH_AES_128_CBC_SHA,
|
tls.TLS_RSA_WITH_AES_128_CBC_SHA,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// List of ciphers we should prefer if native AESNI support is missing
|
||||||
|
var defaultCiphersNonAESNI = []uint16{
|
||||||
|
tls.TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305,
|
||||||
|
tls.TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305,
|
||||||
|
tls.TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384,
|
||||||
|
tls.TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384,
|
||||||
|
tls.TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256,
|
||||||
|
tls.TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256,
|
||||||
|
tls.TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA,
|
||||||
|
tls.TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA,
|
||||||
|
tls.TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA,
|
||||||
|
tls.TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA,
|
||||||
|
tls.TLS_RSA_WITH_AES_256_CBC_SHA,
|
||||||
|
tls.TLS_RSA_WITH_AES_128_CBC_SHA,
|
||||||
|
}
|
||||||
|
|
||||||
|
// getPreferredDefaultCiphers returns an appropriate cipher suite to use, depending on
|
||||||
|
// the hardware support available for AES-NI.
|
||||||
|
//
|
||||||
|
// See https://github.com/mholt/caddy/issues/1674
|
||||||
|
func getPreferredDefaultCiphers() []uint16 {
|
||||||
|
if aesnicheck.HasAESNI() {
|
||||||
|
return defaultCiphers
|
||||||
|
}
|
||||||
|
|
||||||
|
// Return a cipher suite that prefers ChaCha20
|
||||||
|
return defaultCiphersNonAESNI
|
||||||
|
}
|
||||||
|
|
||||||
// Map of supported curves
|
// Map of supported curves
|
||||||
// https://golang.org/pkg/crypto/tls/#CurveID
|
// https://golang.org/pkg/crypto/tls/#CurveID
|
||||||
var supportedCurvesMap = map[string]tls.CurveID{
|
var supportedCurvesMap = map[string]tls.CurveID{
|
||||||
|
|
|
@ -6,6 +6,8 @@ import (
|
||||||
"net/url"
|
"net/url"
|
||||||
"reflect"
|
"reflect"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
|
"github.com/codahale/aesnicheck"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestConvertTLSConfigProtocolVersions(t *testing.T) {
|
func TestConvertTLSConfigProtocolVersions(t *testing.T) {
|
||||||
|
@ -60,10 +62,11 @@ func TestConvertTLSConfigCipherSuites(t *testing.T) {
|
||||||
{Enabled: true, Ciphers: nil},
|
{Enabled: true, Ciphers: nil},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
defaultCiphersExpected := getPreferredDefaultCiphers()
|
||||||
expectedCiphers := [][]uint16{
|
expectedCiphers := [][]uint16{
|
||||||
{tls.TLS_FALLBACK_SCSV, 0xc02c, 0xc030},
|
{tls.TLS_FALLBACK_SCSV, 0xc02c, 0xc030},
|
||||||
{tls.TLS_FALLBACK_SCSV, 0xc012, 0xc030, 0xc00a},
|
{tls.TLS_FALLBACK_SCSV, 0xc012, 0xc030, 0xc00a},
|
||||||
append([]uint16{tls.TLS_FALLBACK_SCSV}, defaultCiphers...),
|
append([]uint16{tls.TLS_FALLBACK_SCSV}, defaultCiphersExpected...),
|
||||||
}
|
}
|
||||||
|
|
||||||
for i, config := range configs {
|
for i, config := range configs {
|
||||||
|
@ -79,6 +82,21 @@ func TestConvertTLSConfigCipherSuites(t *testing.T) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestGetPreferredDefaultCiphers(t *testing.T) {
|
||||||
|
expectedCiphers := defaultCiphers
|
||||||
|
if !aesnicheck.HasAESNI() {
|
||||||
|
expectedCiphers = defaultCiphersNonAESNI
|
||||||
|
}
|
||||||
|
|
||||||
|
// Ensure ordering is correct and ciphers are what we expected.
|
||||||
|
result := getPreferredDefaultCiphers()
|
||||||
|
for i, actual := range result {
|
||||||
|
if actual != expectedCiphers[i] {
|
||||||
|
t.Errorf("Expected cipher in position %d to be %0x, got %0x", i, expectedCiphers[i], actual)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func TestStorageForNoURL(t *testing.T) {
|
func TestStorageForNoURL(t *testing.T) {
|
||||||
c := &Config{}
|
c := &Config{}
|
||||||
if _, err := c.StorageFor(""); err == nil {
|
if _, err := c.StorageFor(""); err == nil {
|
||||||
|
|
|
@ -58,21 +58,7 @@ func TestSetupParseBasic(t *testing.T) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Cipher checks
|
// Cipher checks
|
||||||
expectedCiphers := []uint16{
|
expectedCiphers := append([]uint16{tls.TLS_FALLBACK_SCSV}, getPreferredDefaultCiphers()...)
|
||||||
tls.TLS_FALLBACK_SCSV,
|
|
||||||
tls.TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384,
|
|
||||||
tls.TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384,
|
|
||||||
tls.TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256,
|
|
||||||
tls.TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256,
|
|
||||||
tls.TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305,
|
|
||||||
tls.TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305,
|
|
||||||
tls.TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA,
|
|
||||||
tls.TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA,
|
|
||||||
tls.TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA,
|
|
||||||
tls.TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA,
|
|
||||||
tls.TLS_RSA_WITH_AES_256_CBC_SHA,
|
|
||||||
tls.TLS_RSA_WITH_AES_128_CBC_SHA,
|
|
||||||
}
|
|
||||||
|
|
||||||
// Ensure count is correct (plus one for TLS_FALLBACK_SCSV)
|
// Ensure count is correct (plus one for TLS_FALLBACK_SCSV)
|
||||||
if len(cfg.Ciphers) != len(expectedCiphers) {
|
if len(cfg.Ciphers) != len(expectedCiphers) {
|
||||||
|
|
Loading…
Reference in a new issue