Skip to content

Commit

Permalink
HBASE-28122: Support TLSv1.3 cipher suites (#5444)
Browse files Browse the repository at this point in the history
Co-authored-by: Charles Connell <cconnell@hubspot.com>
Signed-off-by: Duo Zhang <zhangduo@apache.org>
(cherry picked from commit d8b5198)
  • Loading branch information
charlesconnell authored and Apache9 committed Nov 9, 2023
1 parent 3f29f8e commit 154b766
Show file tree
Hide file tree
Showing 2 changed files with 28 additions and 19 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -115,6 +115,10 @@ public final class X509Util {
"hbase.client.netty.tls.handshaketimeout";
public static final int DEFAULT_HANDSHAKE_DETECTION_TIMEOUT_MILLIS = 5000;

private static String[] getTls13Ciphers() {
return new String[] { "TLS_AES_128_GCM_SHA256", "TLS_AES_256_GCM_SHA384" };
}

private static String[] getGCMCiphers() {
return new String[] { "TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256",
"TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256", "TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384",
Expand All @@ -136,14 +140,17 @@ private static String[] getCBCCiphers() {
// Note that this performance assumption might not hold true for architectures other than x86_64.
private static final String[] DEFAULT_CIPHERS_JAVA9 =
ObjectArrays.concat(getGCMCiphers(), getCBCCiphers(), String.class);
private static final String[] DEFAULT_CIPHERS_JAVA11 =
ObjectArrays.concat(ObjectArrays.concat(getTls13Ciphers(), getGCMCiphers(), String.class),
getCBCCiphers(), String.class);

private static final String[] DEFAULT_CIPHERS_OPENSSL = getOpenSslFilteredDefaultCiphers();

/**
* Not all of our default ciphers are available in OpenSSL. Takes our default cipher lists and
* filters them to only those available in OpenSsl. Does GCM first, then CBC because GCM tends to
* be better and faster, and we don't need to worry about the java8 vs 9 performance issue if
* OpenSSL is handling it.
* filters them to only those available in OpenSsl. Prefers TLS 1.3, then GCM, then CBC because
* GCM tends to be better and faster, and we don't need to worry about the java8 vs 9 performance
* issue if OpenSSL is handling it.
*/
private static String[] getOpenSslFilteredDefaultCiphers() {
if (!OpenSsl.isAvailable()) {
Expand All @@ -152,16 +159,9 @@ private static String[] getOpenSslFilteredDefaultCiphers() {

Set<String> openSslSuites = OpenSsl.availableJavaCipherSuites();
List<String> defaultSuites = new ArrayList<>();
for (String cipher : getGCMCiphers()) {
if (openSslSuites.contains(cipher)) {
defaultSuites.add(cipher);
}
}
for (String cipher : getCBCCiphers()) {
if (openSslSuites.contains(cipher)) {
defaultSuites.add(cipher);
}
}
Arrays.stream(getTls13Ciphers()).filter(openSslSuites::contains).forEach(defaultSuites::add);
Arrays.stream(getGCMCiphers()).filter(openSslSuites::contains).forEach(defaultSuites::add);
Arrays.stream(getCBCCiphers()).filter(openSslSuites::contains).forEach(defaultSuites::add);
return defaultSuites.toArray(new String[0]);
}

Expand Down Expand Up @@ -219,10 +219,19 @@ static String[] getDefaultCipherSuites(boolean useOpenSsl) {

static String[] getDefaultCipherSuitesForJavaVersion(String javaVersion) {
Objects.requireNonNull(javaVersion);

if (javaVersion.matches("\\d+")) {
// Must be Java 9 or later
LOG.debug("Using Java9+ optimized cipher suites for Java version {}", javaVersion);
return DEFAULT_CIPHERS_JAVA9;
int javaVersionInt = Integer.parseInt(javaVersion);
if (javaVersionInt >= 11) {
LOG.debug(
"Using Java11+ optimized cipher suites for Java version {}, including TLSv1.3 support",
javaVersion);
return DEFAULT_CIPHERS_JAVA11;
} else {
LOG.debug("Using Java9+ optimized cipher suites for Java version {}", javaVersion);
return DEFAULT_CIPHERS_JAVA9;
}
} else if (javaVersion.startsWith("1.")) {
// Must be Java 1.8 or earlier
LOG.debug("Using Java8 optimized cipher suites for Java version {}", javaVersion);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -379,21 +379,21 @@ public void testGetDefaultCipherSuitesJava8() {
public void testGetDefaultCipherSuitesJava9() {
String[] cipherSuites = X509Util.getDefaultCipherSuitesForJavaVersion("9");
// Java 9+ default should have the GCM suites first
assertThat(cipherSuites[0], containsString("GCM"));
assertEquals(cipherSuites[0], "TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256");
}

@Test
public void testGetDefaultCipherSuitesJava10() {
String[] cipherSuites = X509Util.getDefaultCipherSuitesForJavaVersion("10");
// Java 9+ default should have the GCM suites first
assertThat(cipherSuites[0], containsString("GCM"));
assertEquals(cipherSuites[0], "TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256");
}

@Test
public void testGetDefaultCipherSuitesJava11() {
String[] cipherSuites = X509Util.getDefaultCipherSuitesForJavaVersion("11");
// Java 9+ default should have the GCM suites first
assertThat(cipherSuites[0], containsString("GCM"));
// Java 11+ default should have the TLSv1.3 suites first
assertThat(cipherSuites[0], containsString("TLS_AES_128_GCM"));
}

@Test
Expand Down

0 comments on commit 154b766

Please sign in to comment.