Respect the Provider when detecting if TLSv1.3 is used by default / supported (#10621)

Motivation:

We need to take the Provider into account as well when trying to detect if TLSv1.3 is used by default / supported

Modifications:

- Change utility method to respect provider as well
- Change testcode

Result:

Less error-prone tests
This commit is contained in:
Norman Maurer 2020-09-29 16:59:11 +02:00 committed by GitHub
parent 6545e4eb2b
commit 4d09c5ff98
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 79 additions and 52 deletions

View File

@ -19,6 +19,8 @@ package io.netty.handler.ssl;
import io.netty.util.ReferenceCounted; import io.netty.util.ReferenceCounted;
import io.netty.util.internal.UnstableApi; import io.netty.util.internal.UnstableApi;
import java.security.Provider;
/** /**
* An enumeration of SSL/TLS protocol providers. * An enumeration of SSL/TLS protocol providers.
*/ */
@ -41,6 +43,7 @@ public enum SslProvider {
* Returns {@code true} if the specified {@link SslProvider} supports * Returns {@code true} if the specified {@link SslProvider} supports
* <a href="https://tools.ietf.org/html/rfc7301#section-6">TLS ALPN Extension</a>, {@code false} otherwise. * <a href="https://tools.ietf.org/html/rfc7301#section-6">TLS ALPN Extension</a>, {@code false} otherwise.
*/ */
@SuppressWarnings("deprecation")
public static boolean isAlpnSupported(final SslProvider provider) { public static boolean isAlpnSupported(final SslProvider provider) {
switch (provider) { switch (provider) {
case JDK: case JDK:
@ -57,15 +60,23 @@ public enum SslProvider {
* Returns {@code true} if the specified {@link SslProvider} supports * Returns {@code true} if the specified {@link SslProvider} supports
* <a href="https://tools.ietf.org/html/rfc8446">TLS 1.3</a>, {@code false} otherwise. * <a href="https://tools.ietf.org/html/rfc8446">TLS 1.3</a>, {@code false} otherwise.
*/ */
public static boolean isTlsv13Supported(final SslProvider provider) { public static boolean isTlsv13Supported(final SslProvider sslProvider) {
switch (provider) { return isTlsv13Supported(sslProvider, null);
}
/**
* Returns {@code true} if the specified {@link SslProvider} supports
* <a href="https://tools.ietf.org/html/rfc8446">TLS 1.3</a>, {@code false} otherwise.
*/
public static boolean isTlsv13Supported(final SslProvider sslProvider, Provider provider) {
switch (sslProvider) {
case JDK: case JDK:
return SslUtils.isTLSv13SupportedByJDK(); return SslUtils.isTLSv13SupportedByJDK(provider);
case OPENSSL: case OPENSSL:
case OPENSSL_REFCNT: case OPENSSL_REFCNT:
return OpenSsl.isTlsv13Supported(); return OpenSsl.isTlsv13Supported();
default: default:
throw new Error("Unknown SslProvider: " + provider); throw new Error("Unknown SslProvider: " + sslProvider);
} }
} }
@ -73,15 +84,15 @@ public enum SslProvider {
* Returns {@code true} if the specified {@link SslProvider} enables * Returns {@code true} if the specified {@link SslProvider} enables
* <a href="https://tools.ietf.org/html/rfc8446">TLS 1.3</a> by default, {@code false} otherwise. * <a href="https://tools.ietf.org/html/rfc8446">TLS 1.3</a> by default, {@code false} otherwise.
*/ */
static boolean isTlsv13EnabledByDefault(final SslProvider provider) { static boolean isTlsv13EnabledByDefault(final SslProvider sslProvider, Provider provider) {
switch (provider) { switch (sslProvider) {
case JDK: case JDK:
return SslUtils.isTLSv13EnabledByJDK(); return SslUtils.isTLSv13EnabledByJDK(provider);
case OPENSSL: case OPENSSL:
case OPENSSL_REFCNT: case OPENSSL_REFCNT:
return OpenSsl.isTlsv13Supported(); return OpenSsl.isTlsv13Supported();
default: default:
throw new Error("Unknown SslProvider: " + provider); throw new Error("Unknown SslProvider: " + sslProvider);
} }
} }
} }

View File

@ -28,6 +28,9 @@ import io.netty.util.internal.logging.InternalLoggerFactory;
import java.nio.ByteBuffer; import java.nio.ByteBuffer;
import java.nio.ByteOrder; import java.nio.ByteOrder;
import java.security.KeyManagementException;
import java.security.NoSuchAlgorithmException;
import java.security.Provider;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Collections; import java.util.Collections;
import java.util.LinkedHashSet; import java.util.LinkedHashSet;
@ -110,35 +113,8 @@ final class SslUtils {
private static final boolean TLSV1_3_JDK_DEFAULT_ENABLED; private static final boolean TLSV1_3_JDK_DEFAULT_ENABLED;
static { static {
boolean tlsv13Supported = false; TLSV1_3_JDK_SUPPORTED = isTLSv13SupportedByJDK0(null);
boolean tlsv13Enabled = false; TLSV1_3_JDK_DEFAULT_ENABLED = isTLSv13EnabledByJDK0(null);
Throwable cause = null;
try {
SSLContext context = SSLContext.getInstance("TLS");
context.init(null, new TrustManager[0], null);
for (String supported: context.getSupportedSSLParameters().getProtocols()) {
if (PROTOCOL_TLS_V1_3.equals(supported)) {
tlsv13Supported = true;
break;
}
}
for (String enabled: context.getDefaultSSLParameters().getProtocols()) {
if (PROTOCOL_TLS_V1_3.equals(enabled)) {
tlsv13Enabled = true;
break;
}
}
} catch (Throwable error) {
cause = error;
}
if (cause == null) {
logger.debug("JDK SSLEngine supports TLSv1.3: {}", tlsv13Supported);
} else {
logger.debug("Unable to detect if JDK SSLEngine supports TLSv1.3, assuming no", cause);
}
TLSV1_3_JDK_SUPPORTED = tlsv13Supported;
TLSV1_3_JDK_DEFAULT_ENABLED = tlsv13Enabled;
if (TLSV1_3_JDK_SUPPORTED) { if (TLSV1_3_JDK_SUPPORTED) {
DEFAULT_TLSV13_CIPHER_SUITES = TLSV13_CIPHER_SUITES; DEFAULT_TLSV13_CIPHER_SUITES = TLSV13_CIPHER_SUITES;
} else { } else {
@ -168,15 +144,64 @@ final class SslUtils {
/** /**
* Returns {@code true} if the JDK itself supports TLSv1.3, {@code false} otherwise. * Returns {@code true} if the JDK itself supports TLSv1.3, {@code false} otherwise.
*/ */
static boolean isTLSv13SupportedByJDK() { static boolean isTLSv13SupportedByJDK(Provider provider) {
return TLSV1_3_JDK_SUPPORTED; if (provider == null) {
return TLSV1_3_JDK_SUPPORTED;
}
return isTLSv13SupportedByJDK0(provider);
}
private static boolean isTLSv13SupportedByJDK0(Provider provider) {
try {
return arrayContains(newInitContext(provider)
.getSupportedSSLParameters().getProtocols(), PROTOCOL_TLS_V1_3);
} catch (Throwable cause) {
logger.debug("Unable to detect if JDK SSLEngine with provider {} supports TLSv1.3, assuming no",
provider, cause);
return false;
}
} }
/** /**
* Returns {@code true} if the JDK itself supports TLSv1.3 and enabled it by default, {@code false} otherwise. * Returns {@code true} if the JDK itself supports TLSv1.3 and enabled it by default, {@code false} otherwise.
*/ */
static boolean isTLSv13EnabledByJDK() { static boolean isTLSv13EnabledByJDK(Provider provider) {
return TLSV1_3_JDK_DEFAULT_ENABLED; if (provider == null) {
return TLSV1_3_JDK_DEFAULT_ENABLED;
}
return isTLSv13EnabledByJDK0(provider);
}
private static boolean isTLSv13EnabledByJDK0(Provider provider) {
try {
return arrayContains(newInitContext(provider)
.getDefaultSSLParameters().getProtocols(), PROTOCOL_TLS_V1_3);
} catch (Throwable cause) {
logger.debug("Unable to detect if JDK SSLEngine with provider {} enables TLSv1.3 by default," +
" assuming no", provider, cause);
return false;
}
}
private static SSLContext newInitContext(Provider provider)
throws NoSuchAlgorithmException, KeyManagementException {
final SSLContext context;
if (provider == null) {
context = SSLContext.getInstance("TLS");
} else {
context = SSLContext.getInstance("TLS", provider);
}
context.init(null, new TrustManager[0], null);
return context;
}
static boolean arrayContains(String[] array, String value) {
for (String v: array) {
if (value.equals(v)) {
return true;
}
}
return false;
} }
/** /**

View File

@ -3609,21 +3609,12 @@ public abstract class SSLEngineTest {
ssc.delete(); ssc.delete();
} }
assertEquals(SslProvider.isTlsv13EnabledByDefault(sslClientProvider()), assertEquals(SslProvider.isTlsv13EnabledByDefault(sslClientProvider(), clientSslContextProvider()),
arrayContains(clientProtocols, PROTOCOL_TLS_V1_3)); arrayContains(clientProtocols, PROTOCOL_TLS_V1_3));
assertEquals(SslProvider.isTlsv13EnabledByDefault(sslServerProvider()), assertEquals(SslProvider.isTlsv13EnabledByDefault(sslServerProvider(), serverSslContextProvider()),
arrayContains(serverProtocols, PROTOCOL_TLS_V1_3)); arrayContains(serverProtocols, PROTOCOL_TLS_V1_3));
} }
private static boolean arrayContains(String[] array, String value) {
for (String v: array) {
if (value.equals(v)) {
return true;
}
}
return false;
}
protected SSLEngine wrapEngine(SSLEngine engine) { protected SSLEngine wrapEngine(SSLEngine engine) {
return engine; return engine;
} }