Skip to content

Commit

Permalink
Update TLS ciphers and protocols for JDK 11 (elastic#41385)
Browse files Browse the repository at this point in the history
This commit updates the default ciphers and TLS protocols that are used
after the minimum supported JDK is JDK 11. The conditionals around
TLSv1.3 and 256-bit cipher support have been removed. JDK 11 no longer
requires an unlimited JCE policy file for 256 bit cipher support and
TLSv1.3 is supported in JDK 11+. New cipher support has been introduced
in the newer JDK versions as well. The ciphers are ordered with PFS
ciphers being most preferred, then AEAD ciphers, and finally those with
mainstream hardware support.
  • Loading branch information
jaymode committed May 3, 2019
1 parent c7df2b8 commit 476c82d
Show file tree
Hide file tree
Showing 25 changed files with 135 additions and 174 deletions.
31 changes: 16 additions & 15 deletions docs/reference/settings/security-settings.asciidoc
Original file line number Diff line number Diff line change
Expand Up @@ -513,8 +513,7 @@ and `full`. Defaults to `full`.
See <<ssl-tls-settings,`ssl.verification_mode`>> for an explanation of these values.

`ssl.supported_protocols`::
Supported protocols for TLS/SSL (with versions). Defaults to `TLSv1.3,TLSv1.2,TLSv1.1` if
the JVM supports TLSv1.3, otherwise `TLSv1.2,TLSv1.1`.
Supported protocols for TLS/SSL (with versions). Defaults to `TLSv1.3,TLSv1.2,TLSv1.1`.

`ssl.cipher_suites`:: Specifies the cipher suites that should be supported when
communicating with the LDAP server.
Expand Down Expand Up @@ -765,8 +764,7 @@ and `full`. Defaults to `full`.
See <<ssl-tls-settings,`ssl.verification_mode`>> for an explanation of these values.

`ssl.supported_protocols`::
Supported protocols for TLS/SSL (with versions). Defaults to `TLSv1.3,TLSv1.2,TLSv1.1` if
the JVM supports TLSv1.3, otherwise `TLSv1.2,TLSv1.1`.
Supported protocols for TLS/SSL (with versions). Defaults to `TLSv1.3,TLSv1.2,TLSv1.1`.

`ssl.cipher_suites`:: Specifies the cipher suites that should be supported when
communicating with the Active Directory server.
Expand Down Expand Up @@ -1173,8 +1171,7 @@ Defaults to `full`.
See <<ssl-tls-settings,`ssl.verification_mode`>> for a more detailed explanation of these values.

`ssl.supported_protocols`::
Specifies the supported protocols for TLS/SSL. Defaults to `TLSv1.3,TLSv1.2,TLSv1.1` if
the JVM supports TLSv1.3, otherwise `TLSv1.2,TLSv1.1`.
Specifies the supported protocols for TLS/SSL. Defaults to `TLSv1.3,TLSv1.2,TLSv1.1`.

`ssl.cipher_suites`::
Specifies the
Expand Down Expand Up @@ -1489,8 +1486,7 @@ settings. For more information, see

`ssl.supported_protocols`::
Supported protocols with versions. Valid protocols: `SSLv2Hello`,
`SSLv3`, `TLSv1`, `TLSv1.1`, `TLSv1.2`, `TLSv1.3`. Defaults to `TLSv1.3,TLSv1.2,TLSv1.1` if
the JVM supports TLSv1.3, otherwise `TLSv1.2,TLSv1.1`.
`SSLv3`, `TLSv1`, `TLSv1.1`, `TLSv1.2`, `TLSv1.3`. Defaults to `TLSv1.3,TLSv1.2,TLSv1.1`.
+
--
NOTE: If `xpack.security.fips_mode.enabled` is `true`, you cannot use `SSLv2Hello`
Expand Down Expand Up @@ -1521,13 +1517,18 @@ Controls the verification of certificates. Valid values are:
The default value is `full`.

`ssl.cipher_suites`::
Supported cipher suites can be found in Oracle's http://docs.oracle.com/javase/8/docs/technotes/guides/security/SunProviders.html[
Java Cryptography Architecture documentation]. Defaults to `TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256`,
`TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256`, `TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA`, `TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA`,
`TLS_RSA_WITH_AES_128_CBC_SHA256`, `TLS_RSA_WITH_AES_128_CBC_SHA`. If the _Java Cryptography Extension (JCE) Unlimited Strength
Jurisdiction Policy Files_ has been installed, the default value also includes `TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384`,
`TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384`, `TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA`, `TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA`,
`TLS_RSA_WITH_AES_256_CBC_SHA256`, `TLS_RSA_WITH_AES_256_CBC_SHA`.
Supported cipher suites can be found in Oracle's
https://docs.oracle.com/en/java/javase/11/security/oracle-providers.html#GUID-7093246A-31A3-4304-AC5F-5FB6400405E2[Java Cryptography Architecture documentation].
Defaults to `TLS_AES_256_GCM_SHA384`, `TLS_AES_128_GCM_SHA256`,
`TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384`, `TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256`,
`TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384`, `TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256`,
`TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384`, `TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256`,
`TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384`, `TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256`,
`TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA`, `TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA`,
`TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA`, `TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA`,
`TLS_RSA_WITH_AES_256_GCM_SHA384`, `TLS_RSA_WITH_AES_128_GCM_SHA256`,
`TLS_RSA_WITH_AES_256_CBC_SHA256`, `TLS_RSA_WITH_AES_128_CBC_SHA256`,
`TLS_RSA_WITH_AES_256_CBC_SHA`, `TLS_RSA_WITH_AES_128_CBC_SHA`.

[float]
[[tls-ssl-key-settings]]
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,6 @@
import javax.net.ssl.X509ExtendedTrustManager;
import java.nio.file.Path;
import java.security.GeneralSecurityException;
import java.security.NoSuchAlgorithmException;
import java.util.Collection;
import java.util.Collections;
import java.util.HashSet;
Expand Down Expand Up @@ -52,12 +51,7 @@ public class SslConfiguration {
static final Map<String, String> ORDERED_PROTOCOL_ALGORITHM_MAP;
static {
LinkedHashMap<String, String> protocolAlgorithmMap = new LinkedHashMap<>();
try {
SSLContext.getInstance("TLSv1.3");
protocolAlgorithmMap.put("TLSv1.3", "TLSv1.3");
} catch (NoSuchAlgorithmException e) {
// ignore since we support JVMs that do not support TLSv1.3
}
protocolAlgorithmMap.put("TLSv1.3", "TLSv1.3");
protocolAlgorithmMap.put("TLSv1.2", "TLSv1.2");
protocolAlgorithmMap.put("TLSv1.1", "TLSv1.1");
protocolAlgorithmMap.put("TLSv1", "TLSv1");
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,21 +19,15 @@

package org.elasticsearch.common.ssl;

import javax.crypto.Cipher;
import javax.net.ssl.KeyManagerFactory;
import javax.net.ssl.TrustManagerFactory;
import java.nio.file.Path;
import java.security.NoSuchAlgorithmException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.Objects;
import java.util.function.Function;
import java.util.stream.Collectors;

import static org.elasticsearch.common.ssl.KeyStoreUtil.inferKeyStoreType;
import static org.elasticsearch.common.ssl.SslConfiguration.ORDERED_PROTOCOL_ALGORITHM_MAP;
import static org.elasticsearch.common.ssl.SslConfigurationKeys.CERTIFICATE;
import static org.elasticsearch.common.ssl.SslConfigurationKeys.CERTIFICATE_AUTHORITIES;
import static org.elasticsearch.common.ssl.SslConfigurationKeys.CIPHERS;
Expand Down Expand Up @@ -70,10 +64,22 @@
*/
public abstract class SslConfigurationLoader {

static final List<String> DEFAULT_PROTOCOLS = Collections.unmodifiableList(
ORDERED_PROTOCOL_ALGORITHM_MAP.containsKey("TLSv1.3") ?
Arrays.asList("TLSv1.3", "TLSv1.2", "TLSv1.1") : Arrays.asList("TLSv1.2", "TLSv1.1"));
static final List<String> DEFAULT_CIPHERS = loadDefaultCiphers();
static final List<String> DEFAULT_PROTOCOLS = List.of("TLSv1.3", "TLSv1.2", "TLSv1.1");

/**
* This list has been created with ordering
*/
static final List<String> DEFAULT_CIPHERS = List.of(
"TLS_AES_256_GCM_SHA384", "TLS_AES_128_GCM_SHA256", // TLSv1.3 cipher has PFS, AEAD, hardware support
"TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384", "TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256", // PFS, AEAD, hardware support
"TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384", "TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256", // PFS, AEAD, hardware support
"TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384", "TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256", // PFS, hardware support
"TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384", "TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256", // PFS, hardware support
"TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA", "TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA", // PFS, hardware support
"TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA", "TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA", // PFS, hardware support
"TLS_RSA_WITH_AES_256_GCM_SHA384", "TLS_RSA_WITH_AES_128_GCM_SHA256", // AEAD, hardware support
"TLS_RSA_WITH_AES_256_CBC_SHA256", "TLS_RSA_WITH_AES_128_CBC_SHA256", // hardware support
"TLS_RSA_WITH_AES_256_CBC_SHA", "TLS_RSA_WITH_AES_128_CBC_SHA"); // hardware support
private static final char[] EMPTY_PASSWORD = new char[0];

private final String settingPrefix;
Expand Down Expand Up @@ -141,9 +147,6 @@ public void setDefaultClientAuth(SslClientAuthenticationMode defaultClientAuth)

/**
* Change the default supported ciphers.
* The initial cipher list depends on the availability of {@link #has256BitAES() 256 bit AES}.
*
* @see #loadDefaultCiphers()
*/
public void setDefaultCiphers(List<String> defaultCiphers) {
this.defaultCiphers = defaultCiphers;
Expand Down Expand Up @@ -336,40 +339,4 @@ private <V> List<V> resolveListSetting(String key, Function<String, V> parser, L
throw new SslConfigException("cannot retrieve setting [" + settingPrefix + key + "]", e);
}
}

private static List<String> loadDefaultCiphers() {
final List<String> ciphers128 = Arrays.asList(
"TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256",
"TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256",
"TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA",
"TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA",
"TLS_RSA_WITH_AES_128_CBC_SHA256",
"TLS_RSA_WITH_AES_128_CBC_SHA"
);
final List<String> ciphers256 = Arrays.asList(
"TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384",
"TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384",
"TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA",
"TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA",
"TLS_RSA_WITH_AES_256_CBC_SHA256",
"TLS_RSA_WITH_AES_256_CBC_SHA"
);
if (has256BitAES()) {
List<String> ciphers = new ArrayList<>(ciphers256.size() + ciphers128.size());
ciphers.addAll(ciphers256);
ciphers.addAll(ciphers128);
return ciphers;
} else {
return ciphers128;
}
}

private static boolean has256BitAES() {
try {
return Cipher.getMaxAllowedKeyLength("AES") > 128;
} catch (NoSuchAlgorithmException e) {
// No AES? Things are going to be very weird, but technically that means we don't have 256 bit AES, so ...
return false;
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -120,6 +120,7 @@ public void testClientFailsWithUntrustedCertificate() throws IOException {
final List<Thread> threads = new ArrayList<>();
final Settings settings = Settings.builder()
.put("path.home", createTempDir())
.put("reindex.ssl.supported_protocols", "TLSv1.2")
.build();
final Environment environment = TestEnvironment.newEnvironment(settings);
final ReindexSslConfig ssl = new ReindexSslConfig(settings, environment, mock(ResourceWatcherService.class));
Expand All @@ -134,6 +135,7 @@ public void testClientSucceedsWithCertificateAuthorities() throws IOException {
final Settings settings = Settings.builder()
.put("path.home", createTempDir())
.putList("reindex.ssl.certificate_authorities", ca.toString())
.put("reindex.ssl.supported_protocols", "TLSv1.2")
.build();
final Environment environment = TestEnvironment.newEnvironment(settings);
final ReindexSslConfig ssl = new ReindexSslConfig(settings, environment, mock(ResourceWatcherService.class));
Expand All @@ -149,6 +151,7 @@ public void testClientSucceedsWithVerificationDisabled() throws IOException {
final Settings settings = Settings.builder()
.put("path.home", createTempDir())
.put("reindex.ssl.verification_mode", "NONE")
.put("reindex.ssl.supported_protocols", "TLSv1.2")
.build();
final Environment environment = TestEnvironment.newEnvironment(settings);
final ReindexSslConfig ssl = new ReindexSslConfig(settings, environment, mock(ResourceWatcherService.class));
Expand All @@ -169,6 +172,7 @@ public void testClientPassesClientCertificate() throws IOException {
.put("reindex.ssl.certificate", cert)
.put("reindex.ssl.key", key)
.put("reindex.ssl.key_passphrase", "client-password")
.put("reindex.ssl.supported_protocols", "TLSv1.2")
.build();
AtomicReference<Certificate[]> clientCertificates = new AtomicReference<>();
handler = https -> {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@

package org.elasticsearch.xpack.core;

import org.apache.logging.log4j.LogManager;
import org.elasticsearch.common.settings.Setting;
import org.elasticsearch.common.settings.Setting.Property;
import org.elasticsearch.xpack.core.security.SecurityField;
Expand All @@ -15,13 +14,10 @@
import org.elasticsearch.xpack.core.ssl.SSLConfigurationSettings;
import org.elasticsearch.xpack.core.ssl.VerificationMode;

import javax.crypto.Cipher;
import javax.crypto.SecretKeyFactory;
import javax.net.ssl.SSLContext;

import java.security.NoSuchAlgorithmException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.Locale;
Expand All @@ -38,7 +34,6 @@ private XPackSettings() {
throw new IllegalStateException("Utility class should not be instantiated");
}


/**
* Setting for controlling whether or not CCR is enabled.
*/
Expand Down Expand Up @@ -122,28 +117,17 @@ private XPackSettings() {
* SSL settings. These are the settings that are specifically registered for SSL. Many are private as we do not explicitly use them
* but instead parse based on a prefix (eg *.ssl.*)
*/
public static final List<String> DEFAULT_CIPHERS;

static {
List<String> ciphers = Arrays.asList("TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256", "TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256",
"TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA", "TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA", "TLS_RSA_WITH_AES_128_CBC_SHA256",
"TLS_RSA_WITH_AES_128_CBC_SHA");
try {
final boolean use256Bit = Cipher.getMaxAllowedKeyLength("AES") > 128;
if (use256Bit) {
List<String> strongerCiphers = new ArrayList<>(ciphers.size() * 2);
strongerCiphers.addAll(Arrays.asList("TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384",
"TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384", "TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA",
"TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA", "TLS_RSA_WITH_AES_256_CBC_SHA256", "TLS_RSA_WITH_AES_256_CBC_SHA"));
strongerCiphers.addAll(ciphers);
ciphers = strongerCiphers;
}
} catch (NoSuchAlgorithmException e) {
// ignore it here - there will be issues elsewhere and its not nice to throw in a static initializer
}

DEFAULT_CIPHERS = ciphers;
}
public static final List<String> DEFAULT_CIPHERS = List.of(
"TLS_AES_256_GCM_SHA384", "TLS_AES_128_GCM_SHA256", // TLSv1.3 cipher has PFS, AEAD, hardware support
"TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384", "TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256", // PFS, AEAD, hardware support
"TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384", "TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256", // PFS, AEAD, hardware support
"TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384", "TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256", // PFS, hardware support
"TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384", "TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256", // PFS, hardware support
"TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA", "TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA", // PFS, hardware support
"TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA", "TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA", // PFS, hardware support
"TLS_RSA_WITH_AES_256_GCM_SHA384", "TLS_RSA_WITH_AES_128_GCM_SHA256", // AEAD, hardware support
"TLS_RSA_WITH_AES_256_CBC_SHA256", "TLS_RSA_WITH_AES_128_CBC_SHA256", // hardware support
"TLS_RSA_WITH_AES_256_CBC_SHA", "TLS_RSA_WITH_AES_128_CBC_SHA"); // hardware support

/*
* Do not allow insecure hashing algorithms to be used for password hashing
Expand All @@ -164,19 +148,7 @@ private XPackSettings() {
}
}, Setting.Property.NodeScope);

public static final List<String> DEFAULT_SUPPORTED_PROTOCOLS;

static {
boolean supportsTLSv13 = false;
try {
SSLContext.getInstance("TLSv1.3");
supportsTLSv13 = true;
} catch (NoSuchAlgorithmException e) {
LogManager.getLogger(XPackSettings.class).debug("TLSv1.3 is not supported", e);
}
DEFAULT_SUPPORTED_PROTOCOLS = supportsTLSv13 ?
Arrays.asList("TLSv1.3", "TLSv1.2", "TLSv1.1") : Arrays.asList("TLSv1.2", "TLSv1.1");
}
public static final List<String> DEFAULT_SUPPORTED_PROTOCOLS = List.of("TLSv1.3", "TLSv1.2", "TLSv1.1");

public static final SSLClientAuth CLIENT_AUTH_DEFAULT = SSLClientAuth.REQUIRED;
public static final SSLClientAuth HTTP_CLIENT_AUTH_DEFAULT = SSLClientAuth.NONE;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -57,8 +57,6 @@
import java.util.function.Supplier;
import java.util.stream.Collectors;

import static org.elasticsearch.xpack.core.XPackSettings.DEFAULT_SUPPORTED_PROTOCOLS;

/**
* Provides access to {@link SSLEngine} and {@link SSLSocketFactory} objects based on a provided configuration. All
* configurations loaded by this service must be configured on construction.
Expand All @@ -75,9 +73,7 @@ public class SSLService {
private static final Map<String, String> ORDERED_PROTOCOL_ALGORITHM_MAP;
static {
LinkedHashMap<String, String> protocolAlgorithmMap = new LinkedHashMap<>();
if (DEFAULT_SUPPORTED_PROTOCOLS.contains("TLSv1.3")) {
protocolAlgorithmMap.put("TLSv1.3", "TLSv1.3");
}
protocolAlgorithmMap.put("TLSv1.3", "TLSv1.3");
protocolAlgorithmMap.put("TLSv1.2", "TLSv1.2");
protocolAlgorithmMap.put("TLSv1.1", "TLSv1.1");
protocolAlgorithmMap.put("TLSv1", "TLSv1");
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -119,9 +119,8 @@ X509ExtendedTrustManager createTrustManager(@Nullable Environment environment) {

try {
return CertParsingUtils.trustManager(trustConfigs.stream()
.flatMap((tc) -> Arrays.stream(tc.createTrustManager(environment).getAcceptedIssuers()))
.collect(Collectors.toList())
.toArray(new X509Certificate[0]));
.flatMap((tc) -> Arrays.stream(tc.createTrustManager(environment).getAcceptedIssuers()))
.toArray(X509Certificate[]::new));
} catch (Exception e) {
throw new ElasticsearchException("failed to create trust manager", e);
}
Expand Down
Loading

0 comments on commit 476c82d

Please sign in to comment.