Skip to content

Commit a3c138a

Browse files
authored
Update TLS ciphers and protocols for JDK 11 (#41808)
* Update TLS ciphers and protocols for JDK 11 (#41385) 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. * Fixes for TLSv1.3 on JDK11 * fix for JDK-8212885
1 parent 2e40881 commit a3c138a

File tree

36 files changed

+352
-186
lines changed

36 files changed

+352
-186
lines changed

client/rest/src/test/java/org/elasticsearch/client/RestClientBuilderIntegTests.java

Lines changed: 34 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,8 +38,10 @@
3838
import java.net.InetSocketAddress;
3939
import java.nio.file.Files;
4040
import java.nio.file.Paths;
41+
import java.security.AccessController;
4142
import java.security.KeyFactory;
4243
import java.security.KeyStore;
44+
import java.security.PrivilegedAction;
4345
import java.security.cert.Certificate;
4446
import java.security.cert.CertificateFactory;
4547
import java.security.spec.PKCS8EncodedKeySpec;
@@ -106,7 +108,7 @@ private RestClient buildRestClient() {
106108
}
107109

108110
private static SSLContext getSslContext() throws Exception {
109-
SSLContext sslContext = SSLContext.getInstance("TLS");
111+
SSLContext sslContext = SSLContext.getInstance(getProtocol());
110112
try (InputStream certFile = RestClientBuilderIntegTests.class.getResourceAsStream("/test.crt")) {
111113
// Build a keystore of default type programmatically since we can't use JKS keystores to
112114
// init a KeyManagerFactory in FIPS 140 JVMs.
@@ -126,4 +128,35 @@ private static SSLContext getSslContext() throws Exception {
126128
}
127129
return sslContext;
128130
}
131+
132+
/**
133+
* The {@link HttpsServer} in the JDK has issues with TLSv1.3 when running in a JDK prior to
134+
* 12.0.1 so we pin to TLSv1.2 when running on an earlier JDK
135+
*/
136+
private static String getProtocol() {
137+
String version = AccessController.doPrivileged((PrivilegedAction<String>) () -> System.getProperty("java.version"));
138+
String[] components = version.split("\\.");
139+
if (components.length > 0) {
140+
final int major = Integer.valueOf(components[0]);
141+
if (major > 12) {
142+
return "TLS";
143+
} else if (major == 12 && components.length > 2) {
144+
final int minor = Integer.valueOf(components[1]);
145+
if (minor > 0) {
146+
return "TLS";
147+
} else {
148+
String patch = components[2];
149+
final int index = patch.indexOf("_");
150+
if (index > -1) {
151+
patch = patch.substring(0, index);
152+
}
153+
154+
if (Integer.valueOf(patch) >= 1) {
155+
return "TLS";
156+
}
157+
}
158+
}
159+
}
160+
return "TLSv1.2";
161+
}
129162
}

docs/reference/settings/security-settings.asciidoc

Lines changed: 16 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -513,8 +513,7 @@ and `full`. Defaults to `full`.
513513
See <<ssl-tls-settings,`ssl.verification_mode`>> for an explanation of these values.
514514

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

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

767766
`ssl.supported_protocols`::
768-
Supported protocols for TLS/SSL (with versions). Defaults to `TLSv1.3,TLSv1.2,TLSv1.1` if
769-
the JVM supports TLSv1.3, otherwise `TLSv1.2,TLSv1.1`.
767+
Supported protocols for TLS/SSL (with versions). Defaults to `TLSv1.3,TLSv1.2,TLSv1.1`.
770768

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

11751173
`ssl.supported_protocols`::
1176-
Specifies the supported protocols for TLS/SSL. Defaults to `TLSv1.3,TLSv1.2,TLSv1.1` if
1177-
the JVM supports TLSv1.3, otherwise `TLSv1.2,TLSv1.1`.
1174+
Specifies the supported protocols for TLS/SSL. Defaults to `TLSv1.3,TLSv1.2,TLSv1.1`.
11781175

11791176
`ssl.cipher_suites`::
11801177
Specifies the
@@ -1494,8 +1491,7 @@ For more information, see
14941491

14951492
`*.ssl.supported_protocols`::
14961493
Supported protocols with versions. Valid protocols: `SSLv2Hello`,
1497-
`SSLv3`, `TLSv1`, `TLSv1.1`, `TLSv1.2`, `TLSv1.3`. Defaults to `TLSv1.3,TLSv1.2,TLSv1.1` if
1498-
the JVM supports TLSv1.3, otherwise `TLSv1.2,TLSv1.1`.
1494+
`SSLv3`, `TLSv1`, `TLSv1.1`, `TLSv1.2`, `TLSv1.3`. Defaults to `TLSv1.3,TLSv1.2,TLSv1.1`.
14991495
+
15001496
--
15011497
NOTE: If `xpack.security.fips_mode.enabled` is `true`, you cannot use `SSLv2Hello`
@@ -1526,13 +1522,18 @@ Controls the verification of certificates. Valid values are:
15261522
The default value is `full`.
15271523

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

15371538
[float]
15381539
[[tls-ssl-key-settings]]

libs/ssl-config/src/main/java/org/elasticsearch/common/ssl/SslConfiguration.java

Lines changed: 1 addition & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,6 @@
2424
import javax.net.ssl.X509ExtendedTrustManager;
2525
import java.nio.file.Path;
2626
import java.security.GeneralSecurityException;
27-
import java.security.NoSuchAlgorithmException;
2827
import java.util.Collection;
2928
import java.util.Collections;
3029
import java.util.HashSet;
@@ -52,12 +51,7 @@ public class SslConfiguration {
5251
static final Map<String, String> ORDERED_PROTOCOL_ALGORITHM_MAP;
5352
static {
5453
LinkedHashMap<String, String> protocolAlgorithmMap = new LinkedHashMap<>();
55-
try {
56-
SSLContext.getInstance("TLSv1.3");
57-
protocolAlgorithmMap.put("TLSv1.3", "TLSv1.3");
58-
} catch (NoSuchAlgorithmException e) {
59-
// ignore since we support JVMs that do not support TLSv1.3
60-
}
54+
protocolAlgorithmMap.put("TLSv1.3", "TLSv1.3");
6155
protocolAlgorithmMap.put("TLSv1.2", "TLSv1.2");
6256
protocolAlgorithmMap.put("TLSv1.1", "TLSv1.1");
6357
protocolAlgorithmMap.put("TLSv1", "TLSv1");

libs/ssl-config/src/main/java/org/elasticsearch/common/ssl/SslConfigurationLoader.java

Lines changed: 16 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -19,21 +19,15 @@
1919

2020
package org.elasticsearch.common.ssl;
2121

22-
import javax.crypto.Cipher;
2322
import javax.net.ssl.KeyManagerFactory;
2423
import javax.net.ssl.TrustManagerFactory;
2524
import java.nio.file.Path;
26-
import java.security.NoSuchAlgorithmException;
27-
import java.util.ArrayList;
28-
import java.util.Arrays;
29-
import java.util.Collections;
3025
import java.util.List;
3126
import java.util.Objects;
3227
import java.util.function.Function;
3328
import java.util.stream.Collectors;
3429

3530
import static org.elasticsearch.common.ssl.KeyStoreUtil.inferKeyStoreType;
36-
import static org.elasticsearch.common.ssl.SslConfiguration.ORDERED_PROTOCOL_ALGORITHM_MAP;
3731
import static org.elasticsearch.common.ssl.SslConfigurationKeys.CERTIFICATE;
3832
import static org.elasticsearch.common.ssl.SslConfigurationKeys.CERTIFICATE_AUTHORITIES;
3933
import static org.elasticsearch.common.ssl.SslConfigurationKeys.CIPHERS;
@@ -70,10 +64,22 @@
7064
*/
7165
public abstract class SslConfigurationLoader {
7266

73-
static final List<String> DEFAULT_PROTOCOLS = Collections.unmodifiableList(
74-
ORDERED_PROTOCOL_ALGORITHM_MAP.containsKey("TLSv1.3") ?
75-
Arrays.asList("TLSv1.3", "TLSv1.2", "TLSv1.1") : Arrays.asList("TLSv1.2", "TLSv1.1"));
76-
static final List<String> DEFAULT_CIPHERS = loadDefaultCiphers();
67+
static final List<String> DEFAULT_PROTOCOLS = List.of("TLSv1.3", "TLSv1.2", "TLSv1.1");
68+
69+
/**
70+
* This list has been created with ordering
71+
*/
72+
static final List<String> DEFAULT_CIPHERS = List.of(
73+
"TLS_AES_256_GCM_SHA384", "TLS_AES_128_GCM_SHA256", // TLSv1.3 cipher has PFS, AEAD, hardware support
74+
"TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384", "TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256", // PFS, AEAD, hardware support
75+
"TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384", "TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256", // PFS, AEAD, hardware support
76+
"TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384", "TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256", // PFS, hardware support
77+
"TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384", "TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256", // PFS, hardware support
78+
"TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA", "TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA", // PFS, hardware support
79+
"TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA", "TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA", // PFS, hardware support
80+
"TLS_RSA_WITH_AES_256_GCM_SHA384", "TLS_RSA_WITH_AES_128_GCM_SHA256", // AEAD, hardware support
81+
"TLS_RSA_WITH_AES_256_CBC_SHA256", "TLS_RSA_WITH_AES_128_CBC_SHA256", // hardware support
82+
"TLS_RSA_WITH_AES_256_CBC_SHA", "TLS_RSA_WITH_AES_128_CBC_SHA"); // hardware support
7783
private static final char[] EMPTY_PASSWORD = new char[0];
7884

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

142148
/**
143149
* Change the default supported ciphers.
144-
* The initial cipher list depends on the availability of {@link #has256BitAES() 256 bit AES}.
145-
*
146-
* @see #loadDefaultCiphers()
147150
*/
148151
public void setDefaultCiphers(List<String> defaultCiphers) {
149152
this.defaultCiphers = defaultCiphers;
@@ -336,40 +339,4 @@ private <V> List<V> resolveListSetting(String key, Function<String, V> parser, L
336339
throw new SslConfigException("cannot retrieve setting [" + settingPrefix + key + "]", e);
337340
}
338341
}
339-
340-
private static List<String> loadDefaultCiphers() {
341-
final List<String> ciphers128 = Arrays.asList(
342-
"TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256",
343-
"TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256",
344-
"TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA",
345-
"TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA",
346-
"TLS_RSA_WITH_AES_128_CBC_SHA256",
347-
"TLS_RSA_WITH_AES_128_CBC_SHA"
348-
);
349-
final List<String> ciphers256 = Arrays.asList(
350-
"TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384",
351-
"TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384",
352-
"TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA",
353-
"TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA",
354-
"TLS_RSA_WITH_AES_256_CBC_SHA256",
355-
"TLS_RSA_WITH_AES_256_CBC_SHA"
356-
);
357-
if (has256BitAES()) {
358-
List<String> ciphers = new ArrayList<>(ciphers256.size() + ciphers128.size());
359-
ciphers.addAll(ciphers256);
360-
ciphers.addAll(ciphers128);
361-
return ciphers;
362-
} else {
363-
return ciphers128;
364-
}
365-
}
366-
367-
private static boolean has256BitAES() {
368-
try {
369-
return Cipher.getMaxAllowedKeyLength("AES") > 128;
370-
} catch (NoSuchAlgorithmException e) {
371-
// No AES? Things are going to be very weird, but technically that means we don't have 256 bit AES, so ...
372-
return false;
373-
}
374-
}
375342
}

modules/reindex/src/test/java/org/elasticsearch/index/reindex/ReindexRestClientSslTests.java

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -120,6 +120,7 @@ public void testClientFailsWithUntrustedCertificate() throws IOException {
120120
final List<Thread> threads = new ArrayList<>();
121121
final Settings settings = Settings.builder()
122122
.put("path.home", createTempDir())
123+
.put("reindex.ssl.supported_protocols", "TLSv1.2")
123124
.build();
124125
final Environment environment = TestEnvironment.newEnvironment(settings);
125126
final ReindexSslConfig ssl = new ReindexSslConfig(settings, environment, mock(ResourceWatcherService.class));
@@ -134,6 +135,7 @@ public void testClientSucceedsWithCertificateAuthorities() throws IOException {
134135
final Settings settings = Settings.builder()
135136
.put("path.home", createTempDir())
136137
.putList("reindex.ssl.certificate_authorities", ca.toString())
138+
.put("reindex.ssl.supported_protocols", "TLSv1.2")
137139
.build();
138140
final Environment environment = TestEnvironment.newEnvironment(settings);
139141
final ReindexSslConfig ssl = new ReindexSslConfig(settings, environment, mock(ResourceWatcherService.class));
@@ -149,6 +151,7 @@ public void testClientSucceedsWithVerificationDisabled() throws IOException {
149151
final Settings settings = Settings.builder()
150152
.put("path.home", createTempDir())
151153
.put("reindex.ssl.verification_mode", "NONE")
154+
.put("reindex.ssl.supported_protocols", "TLSv1.2")
152155
.build();
153156
final Environment environment = TestEnvironment.newEnvironment(settings);
154157
final ReindexSslConfig ssl = new ReindexSslConfig(settings, environment, mock(ResourceWatcherService.class));
@@ -169,6 +172,7 @@ public void testClientPassesClientCertificate() throws IOException {
169172
.put("reindex.ssl.certificate", cert)
170173
.put("reindex.ssl.key", key)
171174
.put("reindex.ssl.key_passphrase", "client-password")
175+
.put("reindex.ssl.supported_protocols", "TLSv1.2")
172176
.build();
173177
AtomicReference<Certificate[]> clientCertificates = new AtomicReference<>();
174178
handler = https -> {

plugins/discovery-azure-classic/src/test/java/org/elasticsearch/discovery/azure/classic/AzureDiscoveryClusterFormationTests.java

Lines changed: 21 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@
2525
import com.sun.net.httpserver.HttpsConfigurator;
2626
import com.sun.net.httpserver.HttpsServer;
2727
import org.apache.logging.log4j.LogManager;
28+
import org.elasticsearch.bootstrap.JavaVersion;
2829
import org.elasticsearch.cloud.azure.classic.management.AzureComputeService;
2930
import org.elasticsearch.common.SuppressForbidden;
3031
import org.elasticsearch.common.io.FileSystemUtils;
@@ -59,7 +60,9 @@
5960
import java.nio.charset.StandardCharsets;
6061
import java.nio.file.Files;
6162
import java.nio.file.Path;
63+
import java.security.AccessController;
6264
import java.security.KeyStore;
65+
import java.security.PrivilegedAction;
6366
import java.util.Arrays;
6467
import java.util.Collection;
6568
import java.util.Collections;
@@ -262,11 +265,28 @@ private static SSLContext getSSLContext() throws Exception {
262265
kmf.init(ks, passphrase);
263266
TrustManagerFactory tmf = TrustManagerFactory.getInstance("SunX509");
264267
tmf.init(ks);
265-
SSLContext ssl = SSLContext.getInstance("TLS");
268+
SSLContext ssl = SSLContext.getInstance(getProtocol());
266269
ssl.init(kmf.getKeyManagers(), tmf.getTrustManagers(), null);
267270
return ssl;
268271
}
269272

273+
/**
274+
* The {@link HttpsServer} in the JDK has issues with TLSv1.3 when running in a JDK prior to
275+
* 12.0.1 so we pin to TLSv1.2 when running on an earlier JDK
276+
*/
277+
private static String getProtocol() {
278+
if (JavaVersion.current().compareTo(JavaVersion.parse("12")) < 0) {
279+
return "TLSv1.2";
280+
} else {
281+
JavaVersion full =
282+
AccessController.doPrivileged((PrivilegedAction<JavaVersion>) () -> JavaVersion.parse(System.getProperty("java.version")));
283+
if (full.compareTo(JavaVersion.parse("12.0.1")) < 0) {
284+
return "TLSv1.2";
285+
}
286+
}
287+
return "TLS";
288+
}
289+
270290
@AfterClass
271291
public static void stopHttpd() throws IOException {
272292
for (int i = 0; i < internalCluster().size(); i++) {

0 commit comments

Comments
 (0)