Add support for TLSv1.3 (#8293)
Motivation: TLSv1.3 support is included in java11 and is also supported by OpenSSL 1.1.1, so we should support when possible. Modifications: - Add support for TLSv1.3 using either the JDK implementation or the native implementation provided by netty-tcnative when compiled against openssl 1.1.1 - Adjust unit tests for semantics provided by TLSv1.3 - Correctly handle custom Provider implementations that not support TLSv1.3 Result: Be able to use TLSv1.3 with netty.
This commit is contained in:
parent
9eebe7ed74
commit
0ddc62cec0
@ -122,33 +122,6 @@ final class CipherSuiteConverter {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Converts the specified Java cipher suites to the colon-separated OpenSSL cipher suite specification.
|
|
||||||
*/
|
|
||||||
static String toOpenSsl(Iterable<String> javaCipherSuites) {
|
|
||||||
final StringBuilder buf = new StringBuilder();
|
|
||||||
for (String c: javaCipherSuites) {
|
|
||||||
if (c == null) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
String converted = toOpenSsl(c);
|
|
||||||
if (converted != null) {
|
|
||||||
c = converted;
|
|
||||||
}
|
|
||||||
|
|
||||||
buf.append(c);
|
|
||||||
buf.append(':');
|
|
||||||
}
|
|
||||||
|
|
||||||
if (buf.length() > 0) {
|
|
||||||
buf.setLength(buf.length() - 1);
|
|
||||||
return buf.toString();
|
|
||||||
} else {
|
|
||||||
return "";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Converts the specified Java cipher suite to its corresponding OpenSSL cipher suite name.
|
* Converts the specified Java cipher suite to its corresponding OpenSSL cipher suite name.
|
||||||
*
|
*
|
||||||
@ -423,5 +396,47 @@ final class CipherSuiteConverter {
|
|||||||
return hmacAlgo;
|
return hmacAlgo;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Convert the given ciphers if needed to OpenSSL format and append them to the correct {@link StringBuilder}
|
||||||
|
* depending on if its a TLSv1.3 cipher or not. If this methods returns without throwing an exception its
|
||||||
|
* guaranteed that at least one of the {@link StringBuilder}s contain some ciphers that can be used to configure
|
||||||
|
* OpenSSL.
|
||||||
|
*/
|
||||||
|
static void convertToCipherStrings(
|
||||||
|
Iterable<String> cipherSuites, StringBuilder cipherBuilder, StringBuilder cipherTLSv13Builder) {
|
||||||
|
for (String c: cipherSuites) {
|
||||||
|
if (c == null) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
String converted = toOpenSsl(c);
|
||||||
|
if (converted == null) {
|
||||||
|
converted = c;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!OpenSsl.isCipherSuiteAvailable(converted)) {
|
||||||
|
throw new IllegalArgumentException("unsupported cipher suite: " + c + '(' + converted + ')');
|
||||||
|
}
|
||||||
|
|
||||||
|
if (SslUtils.isTLSv13Cipher(converted)) {
|
||||||
|
cipherTLSv13Builder.append(converted);
|
||||||
|
cipherTLSv13Builder.append(':');
|
||||||
|
} else {
|
||||||
|
cipherBuilder.append(converted);
|
||||||
|
cipherBuilder.append(':');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (cipherBuilder.length() == 0 && cipherTLSv13Builder.length() == 0) {
|
||||||
|
throw new IllegalArgumentException("empty cipher suites");
|
||||||
|
}
|
||||||
|
if (cipherBuilder.length() > 0) {
|
||||||
|
cipherBuilder.setLength(cipherBuilder.length() - 1);
|
||||||
|
}
|
||||||
|
if (cipherTLSv13Builder.length() > 0) {
|
||||||
|
cipherTLSv13Builder.setLength(cipherTLSv13Builder.length() - 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private CipherSuiteConverter() { }
|
private CipherSuiteConverter() { }
|
||||||
}
|
}
|
||||||
|
@ -17,6 +17,7 @@
|
|||||||
package io.netty.handler.ssl;
|
package io.netty.handler.ssl;
|
||||||
|
|
||||||
import io.netty.buffer.ByteBufAllocator;
|
import io.netty.buffer.ByteBufAllocator;
|
||||||
|
import io.netty.util.ReferenceCountUtil;
|
||||||
import io.netty.util.internal.logging.InternalLogger;
|
import io.netty.util.internal.logging.InternalLogger;
|
||||||
import io.netty.util.internal.logging.InternalLoggerFactory;
|
import io.netty.util.internal.logging.InternalLoggerFactory;
|
||||||
|
|
||||||
@ -26,6 +27,7 @@ import java.security.InvalidAlgorithmParameterException;
|
|||||||
import java.security.KeyException;
|
import java.security.KeyException;
|
||||||
import java.security.KeyStoreException;
|
import java.security.KeyStoreException;
|
||||||
import java.security.NoSuchAlgorithmException;
|
import java.security.NoSuchAlgorithmException;
|
||||||
|
import java.security.Provider;
|
||||||
import java.security.Security;
|
import java.security.Security;
|
||||||
import java.security.UnrecoverableKeyException;
|
import java.security.UnrecoverableKeyException;
|
||||||
import java.security.cert.CertificateException;
|
import java.security.cert.CertificateException;
|
||||||
@ -34,6 +36,7 @@ import java.util.ArrayList;
|
|||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.HashSet;
|
import java.util.HashSet;
|
||||||
|
import java.util.LinkedHashSet;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
|
||||||
@ -58,11 +61,13 @@ public class JdkSslContext extends SslContext {
|
|||||||
static final String PROTOCOL = "TLS";
|
static final String PROTOCOL = "TLS";
|
||||||
private static final String[] DEFAULT_PROTOCOLS;
|
private static final String[] DEFAULT_PROTOCOLS;
|
||||||
private static final List<String> DEFAULT_CIPHERS;
|
private static final List<String> DEFAULT_CIPHERS;
|
||||||
|
private static final List<String> DEFAULT_CIPHERS_NON_TLSV13;
|
||||||
private static final Set<String> SUPPORTED_CIPHERS;
|
private static final Set<String> SUPPORTED_CIPHERS;
|
||||||
|
private static final Set<String> SUPPORTED_CIPHERS_NON_TLSV13;
|
||||||
|
private static final Provider DEFAULT_PROVIDER;
|
||||||
|
|
||||||
static {
|
static {
|
||||||
SSLContext context;
|
SSLContext context;
|
||||||
int i;
|
|
||||||
try {
|
try {
|
||||||
context = SSLContext.getInstance(PROTOCOL);
|
context = SSLContext.getInstance(PROTOCOL);
|
||||||
context.init(null, null, null);
|
context.init(null, null, null);
|
||||||
@ -70,31 +75,54 @@ public class JdkSslContext extends SslContext {
|
|||||||
throw new Error("failed to initialize the default SSL context", e);
|
throw new Error("failed to initialize the default SSL context", e);
|
||||||
}
|
}
|
||||||
|
|
||||||
SSLEngine engine = context.createSSLEngine();
|
DEFAULT_PROVIDER = context.getProvider();
|
||||||
|
|
||||||
|
SSLEngine engine = context.createSSLEngine();
|
||||||
|
DEFAULT_PROTOCOLS = defaultProtocols(engine);
|
||||||
|
|
||||||
|
SUPPORTED_CIPHERS = Collections.unmodifiableSet(supportedCiphers(engine));
|
||||||
|
DEFAULT_CIPHERS = Collections.unmodifiableList(defaultCiphers(engine, SUPPORTED_CIPHERS));
|
||||||
|
|
||||||
|
List<String> ciphersNonTLSv13 = new ArrayList<String>(DEFAULT_CIPHERS);
|
||||||
|
ciphersNonTLSv13.removeAll(Arrays.asList(SslUtils.DEFAULT_TLSV13_CIPHER_SUITES));
|
||||||
|
DEFAULT_CIPHERS_NON_TLSV13 = Collections.unmodifiableList(ciphersNonTLSv13);
|
||||||
|
|
||||||
|
Set<String> suppertedCiphersNonTLSv13 = new LinkedHashSet<String>(SUPPORTED_CIPHERS);
|
||||||
|
suppertedCiphersNonTLSv13.removeAll(Arrays.asList(SslUtils.DEFAULT_TLSV13_CIPHER_SUITES));
|
||||||
|
SUPPORTED_CIPHERS_NON_TLSV13 = Collections.unmodifiableSet(suppertedCiphersNonTLSv13);
|
||||||
|
|
||||||
|
if (logger.isDebugEnabled()) {
|
||||||
|
logger.debug("Default protocols (JDK): {} ", Arrays.asList(DEFAULT_PROTOCOLS));
|
||||||
|
logger.debug("Default cipher suites (JDK): {}", DEFAULT_CIPHERS);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static String[] defaultProtocols(SSLEngine engine) {
|
||||||
// Choose the sensible default list of protocols.
|
// Choose the sensible default list of protocols.
|
||||||
final String[] supportedProtocols = engine.getSupportedProtocols();
|
final String[] supportedProtocols = engine.getSupportedProtocols();
|
||||||
Set<String> supportedProtocolsSet = new HashSet<String>(supportedProtocols.length);
|
Set<String> supportedProtocolsSet = new HashSet<String>(supportedProtocols.length);
|
||||||
for (i = 0; i < supportedProtocols.length; ++i) {
|
for (int i = 0; i < supportedProtocols.length; ++i) {
|
||||||
supportedProtocolsSet.add(supportedProtocols[i]);
|
supportedProtocolsSet.add(supportedProtocols[i]);
|
||||||
}
|
}
|
||||||
List<String> protocols = new ArrayList<String>();
|
List<String> protocols = new ArrayList<String>();
|
||||||
addIfSupported(
|
addIfSupported(
|
||||||
supportedProtocolsSet, protocols,
|
supportedProtocolsSet, protocols,
|
||||||
"TLSv1.2", "TLSv1.1", "TLSv1");
|
// Do not include TLSv1.3 for now by default.
|
||||||
|
SslUtils.PROTOCOL_TLS_V1_2, SslUtils.PROTOCOL_TLS_V1_1, SslUtils.PROTOCOL_TLS_V1);
|
||||||
|
|
||||||
if (!protocols.isEmpty()) {
|
if (!protocols.isEmpty()) {
|
||||||
DEFAULT_PROTOCOLS = protocols.toArray(new String[0]);
|
return protocols.toArray(new String[0]);
|
||||||
} else {
|
}
|
||||||
DEFAULT_PROTOCOLS = engine.getEnabledProtocols();
|
return engine.getEnabledProtocols();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static Set<String> supportedCiphers(SSLEngine engine) {
|
||||||
// Choose the sensible default list of cipher suites.
|
// Choose the sensible default list of cipher suites.
|
||||||
final String[] supportedCiphers = engine.getSupportedCipherSuites();
|
final String[] supportedCiphers = engine.getSupportedCipherSuites();
|
||||||
SUPPORTED_CIPHERS = new HashSet<String>(supportedCiphers.length);
|
Set<String> supportedCiphersSet = new LinkedHashSet<String>(supportedCiphers.length);
|
||||||
for (i = 0; i < supportedCiphers.length; ++i) {
|
for (int i = 0; i < supportedCiphers.length; ++i) {
|
||||||
String supportedCipher = supportedCiphers[i];
|
String supportedCipher = supportedCiphers[i];
|
||||||
SUPPORTED_CIPHERS.add(supportedCipher);
|
supportedCiphersSet.add(supportedCipher);
|
||||||
// IBM's J9 JVM utilizes a custom naming scheme for ciphers and only returns ciphers with the "SSL_"
|
// IBM's J9 JVM utilizes a custom naming scheme for ciphers and only returns ciphers with the "SSL_"
|
||||||
// prefix instead of the "TLS_" prefix (as defined in the JSSE cipher suite names [1]). According to IBM's
|
// prefix instead of the "TLS_" prefix (as defined in the JSSE cipher suite names [1]). According to IBM's
|
||||||
// documentation [2] the "SSL_" prefix is "interchangeable" with the "TLS_" prefix.
|
// documentation [2] the "SSL_" prefix is "interchangeable" with the "TLS_" prefix.
|
||||||
@ -108,21 +136,29 @@ public class JdkSslContext extends SslContext {
|
|||||||
final String tlsPrefixedCipherName = "TLS_" + supportedCipher.substring("SSL_".length());
|
final String tlsPrefixedCipherName = "TLS_" + supportedCipher.substring("SSL_".length());
|
||||||
try {
|
try {
|
||||||
engine.setEnabledCipherSuites(new String[]{tlsPrefixedCipherName});
|
engine.setEnabledCipherSuites(new String[]{tlsPrefixedCipherName});
|
||||||
SUPPORTED_CIPHERS.add(tlsPrefixedCipherName);
|
supportedCiphersSet.add(tlsPrefixedCipherName);
|
||||||
} catch (IllegalArgumentException ignored) {
|
} catch (IllegalArgumentException ignored) {
|
||||||
// The cipher is not supported ... move on to the next cipher.
|
// The cipher is not supported ... move on to the next cipher.
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
List<String> ciphers = new ArrayList<String>();
|
return supportedCiphersSet;
|
||||||
addIfSupported(SUPPORTED_CIPHERS, ciphers, DEFAULT_CIPHER_SUITES);
|
|
||||||
useFallbackCiphersIfDefaultIsEmpty(ciphers, engine.getEnabledCipherSuites());
|
|
||||||
DEFAULT_CIPHERS = Collections.unmodifiableList(ciphers);
|
|
||||||
|
|
||||||
if (logger.isDebugEnabled()) {
|
|
||||||
logger.debug("Default protocols (JDK): {} ", Arrays.asList(DEFAULT_PROTOCOLS));
|
|
||||||
logger.debug("Default cipher suites (JDK): {}", DEFAULT_CIPHERS);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static List<String> defaultCiphers(SSLEngine engine, Set<String> supportedCiphers) {
|
||||||
|
List<String> ciphers = new ArrayList<String>();
|
||||||
|
addIfSupported(supportedCiphers, ciphers, DEFAULT_CIPHER_SUITES);
|
||||||
|
useFallbackCiphersIfDefaultIsEmpty(ciphers, engine.getEnabledCipherSuites());
|
||||||
|
return ciphers;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static boolean isTlsV13Supported(String[] protocols) {
|
||||||
|
for (String protocol: protocols) {
|
||||||
|
if (SslUtils.PROTOCOL_TLS_V1_3.equals(protocol)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
private final String[] protocols;
|
private final String[] protocols;
|
||||||
@ -205,11 +241,49 @@ public class JdkSslContext extends SslContext {
|
|||||||
super(startTls);
|
super(startTls);
|
||||||
this.apn = checkNotNull(apn, "apn");
|
this.apn = checkNotNull(apn, "apn");
|
||||||
this.clientAuth = checkNotNull(clientAuth, "clientAuth");
|
this.clientAuth = checkNotNull(clientAuth, "clientAuth");
|
||||||
cipherSuites = checkNotNull(cipherFilter, "cipherFilter").filterCipherSuites(
|
|
||||||
ciphers, DEFAULT_CIPHERS, SUPPORTED_CIPHERS);
|
|
||||||
this.protocols = protocols == null ? DEFAULT_PROTOCOLS : protocols;
|
|
||||||
unmodifiableCipherSuites = Collections.unmodifiableList(Arrays.asList(cipherSuites));
|
|
||||||
this.sslContext = checkNotNull(sslContext, "sslContext");
|
this.sslContext = checkNotNull(sslContext, "sslContext");
|
||||||
|
|
||||||
|
final List<String> defaultCiphers;
|
||||||
|
final Set<String> supportedCiphers;
|
||||||
|
if (DEFAULT_PROVIDER.equals(sslContext.getProvider())) {
|
||||||
|
this.protocols = protocols == null? DEFAULT_PROTOCOLS : protocols;
|
||||||
|
if (isTlsV13Supported(this.protocols)) {
|
||||||
|
supportedCiphers = SUPPORTED_CIPHERS;
|
||||||
|
defaultCiphers = DEFAULT_CIPHERS;
|
||||||
|
} else {
|
||||||
|
// TLSv1.3 is not supported, ensure we do not include any TLSv1.3 ciphersuite.
|
||||||
|
supportedCiphers = SUPPORTED_CIPHERS_NON_TLSV13;
|
||||||
|
defaultCiphers = DEFAULT_CIPHERS_NON_TLSV13;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// This is a different Provider then the one used by the JDK by default so we can not just assume
|
||||||
|
// the same protocols and ciphers are supported. For example even if Java11+ is used Conscrypt will
|
||||||
|
// not support TLSv1.3 and the TLSv1.3 ciphersuites.
|
||||||
|
SSLEngine engine = sslContext.createSSLEngine();
|
||||||
|
try {
|
||||||
|
if (protocols == null) {
|
||||||
|
this.protocols = defaultProtocols(engine);
|
||||||
|
} else {
|
||||||
|
this.protocols = protocols;
|
||||||
|
}
|
||||||
|
supportedCiphers = supportedCiphers(engine);
|
||||||
|
defaultCiphers = defaultCiphers(engine, supportedCiphers);
|
||||||
|
if (!isTlsV13Supported(this.protocols)) {
|
||||||
|
// TLSv1.3 is not supported, ensure we do not include any TLSv1.3 ciphersuite.
|
||||||
|
for (String cipher: SslUtils.DEFAULT_TLSV13_CIPHER_SUITES) {
|
||||||
|
supportedCiphers.remove(cipher);
|
||||||
|
defaultCiphers.remove(cipher);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} finally {
|
||||||
|
ReferenceCountUtil.release(engine);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
cipherSuites = checkNotNull(cipherFilter, "cipherFilter").filterCipherSuites(
|
||||||
|
ciphers, defaultCiphers, supportedCiphers);
|
||||||
|
|
||||||
|
unmodifiableCipherSuites = Collections.unmodifiableList(Arrays.asList(cipherSuites));
|
||||||
this.isClient = isClient;
|
this.isClient = isClient;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -31,6 +31,7 @@ import io.netty.util.internal.SystemPropertyUtil;
|
|||||||
import io.netty.util.internal.logging.InternalLogger;
|
import io.netty.util.internal.logging.InternalLogger;
|
||||||
import io.netty.util.internal.logging.InternalLoggerFactory;
|
import io.netty.util.internal.logging.InternalLoggerFactory;
|
||||||
|
|
||||||
|
import javax.net.ssl.SSLException;
|
||||||
import java.security.AccessController;
|
import java.security.AccessController;
|
||||||
import java.security.PrivilegedAction;
|
import java.security.PrivilegedAction;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
@ -48,6 +49,7 @@ import static io.netty.handler.ssl.SslUtils.PROTOCOL_SSL_V3;
|
|||||||
import static io.netty.handler.ssl.SslUtils.PROTOCOL_TLS_V1;
|
import static io.netty.handler.ssl.SslUtils.PROTOCOL_TLS_V1;
|
||||||
import static io.netty.handler.ssl.SslUtils.PROTOCOL_TLS_V1_1;
|
import static io.netty.handler.ssl.SslUtils.PROTOCOL_TLS_V1_1;
|
||||||
import static io.netty.handler.ssl.SslUtils.PROTOCOL_TLS_V1_2;
|
import static io.netty.handler.ssl.SslUtils.PROTOCOL_TLS_V1_2;
|
||||||
|
import static io.netty.handler.ssl.SslUtils.PROTOCOL_TLS_V1_3;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Tells if <a href="http://netty.io/wiki/forked-tomcat-native.html">{@code netty-tcnative}</a> and its OpenSSL support
|
* Tells if <a href="http://netty.io/wiki/forked-tomcat-native.html">{@code netty-tcnative}</a> and its OpenSSL support
|
||||||
@ -66,6 +68,12 @@ public final class OpenSsl {
|
|||||||
private static final boolean SUPPORTS_HOSTNAME_VALIDATION;
|
private static final boolean SUPPORTS_HOSTNAME_VALIDATION;
|
||||||
private static final boolean USE_KEYMANAGER_FACTORY;
|
private static final boolean USE_KEYMANAGER_FACTORY;
|
||||||
private static final boolean SUPPORTS_OCSP;
|
private static final boolean SUPPORTS_OCSP;
|
||||||
|
private static final String TLSV13_CIPHERS = "TLS_AES_256_GCM_SHA384" + ':' +
|
||||||
|
"TLS_CHACHA20_POLY1305_SHA256" + ':' +
|
||||||
|
"TLS_AES_128_GCM_SHA256" + ':' +
|
||||||
|
"TLS_AES_128_CCM_8_SHA256" + ':' +
|
||||||
|
"TLS_AES_128_CCM_SHA256";
|
||||||
|
private static final boolean TLSV13_SUPPORTED;
|
||||||
|
|
||||||
static final Set<String> SUPPORTED_PROTOCOLS_SET;
|
static final Set<String> SUPPORTED_PROTOCOLS_SET;
|
||||||
|
|
||||||
@ -139,17 +147,30 @@ public final class OpenSsl {
|
|||||||
boolean supportsKeyManagerFactory = false;
|
boolean supportsKeyManagerFactory = false;
|
||||||
boolean useKeyManagerFactory = false;
|
boolean useKeyManagerFactory = false;
|
||||||
boolean supportsHostNameValidation = false;
|
boolean supportsHostNameValidation = false;
|
||||||
|
boolean tlsv13Supported = false;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
final long sslCtx = SSLContext.make(SSL.SSL_PROTOCOL_ALL, SSL.SSL_MODE_SERVER);
|
final long sslCtx = SSLContext.make(SSL.SSL_PROTOCOL_ALL, SSL.SSL_MODE_SERVER);
|
||||||
long certBio = 0;
|
long certBio = 0;
|
||||||
SelfSignedCertificate cert = null;
|
SelfSignedCertificate cert = null;
|
||||||
try {
|
try {
|
||||||
SSLContext.setCipherSuite(sslCtx, "ALL");
|
if (PlatformDependent.javaVersion() >= 11) {
|
||||||
|
try {
|
||||||
|
SSLContext.setCipherSuite(sslCtx, TLSV13_CIPHERS, true);
|
||||||
|
tlsv13Supported = true;
|
||||||
|
} catch (Exception ignore) {
|
||||||
|
tlsv13Supported = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
SSLContext.setCipherSuite(sslCtx, "ALL", false);
|
||||||
|
|
||||||
final long ssl = SSL.newSSL(sslCtx, true);
|
final long ssl = SSL.newSSL(sslCtx, true);
|
||||||
try {
|
try {
|
||||||
for (String c: SSL.getCiphers(ssl)) {
|
for (String c: SSL.getCiphers(ssl)) {
|
||||||
// Filter out bad input.
|
// Filter out bad input.
|
||||||
if (c == null || c.isEmpty() || availableOpenSslCipherSuites.contains(c)) {
|
if (c == null || c.isEmpty() || availableOpenSslCipherSuites.contains(c) ||
|
||||||
|
// Filter out TLSv1.3 ciphers if not supported.
|
||||||
|
!tlsv13Supported && SslUtils.isTLSv13Cipher(c)) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
availableOpenSslCipherSuites.add(c);
|
availableOpenSslCipherSuites.add(c);
|
||||||
@ -200,8 +221,13 @@ public final class OpenSsl {
|
|||||||
AVAILABLE_OPENSSL_CIPHER_SUITES.size() * 2);
|
AVAILABLE_OPENSSL_CIPHER_SUITES.size() * 2);
|
||||||
for (String cipher: AVAILABLE_OPENSSL_CIPHER_SUITES) {
|
for (String cipher: AVAILABLE_OPENSSL_CIPHER_SUITES) {
|
||||||
// Included converted but also openssl cipher name
|
// Included converted but also openssl cipher name
|
||||||
|
if (!SslUtils.isTLSv13Cipher(cipher)) {
|
||||||
availableJavaCipherSuites.add(CipherSuiteConverter.toJava(cipher, "TLS"));
|
availableJavaCipherSuites.add(CipherSuiteConverter.toJava(cipher, "TLS"));
|
||||||
availableJavaCipherSuites.add(CipherSuiteConverter.toJava(cipher, "SSL"));
|
availableJavaCipherSuites.add(CipherSuiteConverter.toJava(cipher, "SSL"));
|
||||||
|
} else {
|
||||||
|
// TLSv1.3 ciphers have the correct format.
|
||||||
|
availableJavaCipherSuites.add(cipher);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
addIfSupported(availableJavaCipherSuites, defaultCiphers, DEFAULT_CIPHER_SUITES);
|
addIfSupported(availableJavaCipherSuites, defaultCiphers, DEFAULT_CIPHER_SUITES);
|
||||||
@ -239,6 +265,18 @@ public final class OpenSsl {
|
|||||||
protocols.add(PROTOCOL_TLS_V1_2);
|
protocols.add(PROTOCOL_TLS_V1_2);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// This is only supported by java11 and later.
|
||||||
|
if (tlsv13Supported && doesSupportProtocol(SSL.SSL_PROTOCOL_TLSV1_3, SSL.SSL_OP_NO_TLSv1_3)
|
||||||
|
&& PlatformDependent.javaVersion() >= 11) {
|
||||||
|
// We can only support TLS1.3 when using Java 11 or higher as otherwise it will fail to create the
|
||||||
|
// internal instance of an sun.security.ssl.ProtocolVersion as can not parse the version string :/
|
||||||
|
// See http://mail.openjdk.java.net/pipermail/security-dev/2018-September/018242.html
|
||||||
|
protocols.add(PROTOCOL_TLS_V1_3);
|
||||||
|
TLSV13_SUPPORTED = true;
|
||||||
|
} else {
|
||||||
|
TLSV13_SUPPORTED = false;
|
||||||
|
}
|
||||||
|
|
||||||
SUPPORTED_PROTOCOLS_SET = Collections.unmodifiableSet(protocols);
|
SUPPORTED_PROTOCOLS_SET = Collections.unmodifiableSet(protocols);
|
||||||
SUPPORTS_OCSP = doesSupportOcsp();
|
SUPPORTS_OCSP = doesSupportOcsp();
|
||||||
|
|
||||||
@ -256,6 +294,7 @@ public final class OpenSsl {
|
|||||||
USE_KEYMANAGER_FACTORY = false;
|
USE_KEYMANAGER_FACTORY = false;
|
||||||
SUPPORTED_PROTOCOLS_SET = Collections.emptySet();
|
SUPPORTED_PROTOCOLS_SET = Collections.emptySet();
|
||||||
SUPPORTS_OCSP = false;
|
SUPPORTS_OCSP = false;
|
||||||
|
TLSV13_SUPPORTED = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -450,4 +489,8 @@ public final class OpenSsl {
|
|||||||
ReferenceCountUtil.safeRelease(counted);
|
ReferenceCountUtil.safeRelease(counted);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static boolean isTlsv13Supported() {
|
||||||
|
return TLSV13_SUPPORTED;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -24,8 +24,11 @@ import io.netty.internal.tcnative.SSLContext;
|
|||||||
import java.security.KeyStore;
|
import java.security.KeyStore;
|
||||||
import java.security.PrivateKey;
|
import java.security.PrivateKey;
|
||||||
import java.security.cert.X509Certificate;
|
import java.security.cert.X509Certificate;
|
||||||
|
|
||||||
|
import java.util.Arrays;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.HashSet;
|
import java.util.HashSet;
|
||||||
|
import java.util.LinkedHashSet;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
|
||||||
import javax.net.ssl.KeyManagerFactory;
|
import javax.net.ssl.KeyManagerFactory;
|
||||||
@ -47,6 +50,12 @@ import javax.security.auth.x500.X500Principal;
|
|||||||
public final class ReferenceCountedOpenSslClientContext extends ReferenceCountedOpenSslContext {
|
public final class ReferenceCountedOpenSslClientContext extends ReferenceCountedOpenSslContext {
|
||||||
private static final InternalLogger logger =
|
private static final InternalLogger logger =
|
||||||
InternalLoggerFactory.getInstance(ReferenceCountedOpenSslClientContext.class);
|
InternalLoggerFactory.getInstance(ReferenceCountedOpenSslClientContext.class);
|
||||||
|
private static final Set<String> SUPPORTED_KEY_TYPES = Collections.unmodifiableSet(new LinkedHashSet<String>(
|
||||||
|
Arrays.asList(OpenSslKeyMaterialManager.KEY_TYPE_RSA,
|
||||||
|
OpenSslKeyMaterialManager.KEY_TYPE_DH_RSA,
|
||||||
|
OpenSslKeyMaterialManager.KEY_TYPE_EC,
|
||||||
|
OpenSslKeyMaterialManager.KEY_TYPE_EC_RSA,
|
||||||
|
OpenSslKeyMaterialManager.KEY_TYPE_EC_EC)));
|
||||||
private final OpenSslSessionContext sessionContext;
|
private final OpenSslSessionContext sessionContext;
|
||||||
|
|
||||||
ReferenceCountedOpenSslClientContext(X509Certificate[] trustCertCollection, TrustManagerFactory trustManagerFactory,
|
ReferenceCountedOpenSslClientContext(X509Certificate[] trustCertCollection, TrustManagerFactory trustManagerFactory,
|
||||||
@ -277,7 +286,8 @@ public final class ReferenceCountedOpenSslClientContext extends ReferenceCounted
|
|||||||
*/
|
*/
|
||||||
private static Set<String> supportedClientKeyTypes(byte[] clientCertificateTypes) {
|
private static Set<String> supportedClientKeyTypes(byte[] clientCertificateTypes) {
|
||||||
if (clientCertificateTypes == null) {
|
if (clientCertificateTypes == null) {
|
||||||
return Collections.emptySet();
|
// Try all of the supported key types.
|
||||||
|
return SUPPORTED_KEY_TYPES;
|
||||||
}
|
}
|
||||||
Set<String> result = new HashSet<String>(clientCertificateTypes.length);
|
Set<String> result = new HashSet<String>(clientCertificateTypes.length);
|
||||||
for (byte keyTypeCode : clientCertificateTypes) {
|
for (byte keyTypeCode : clientCertificateTypes) {
|
||||||
|
@ -225,16 +225,53 @@ public abstract class ReferenceCountedOpenSslContext extends SslContext implemen
|
|||||||
boolean success = false;
|
boolean success = false;
|
||||||
try {
|
try {
|
||||||
try {
|
try {
|
||||||
int opts = SSL.SSL_PROTOCOL_SSLV3 | SSL.SSL_PROTOCOL_TLSV1 |
|
int protocolOpts = SSL.SSL_PROTOCOL_SSLV3 | SSL.SSL_PROTOCOL_TLSV1 |
|
||||||
SSL.SSL_PROTOCOL_TLSV1_1 | SSL.SSL_PROTOCOL_TLSV1_2;
|
SSL.SSL_PROTOCOL_TLSV1_1 | SSL.SSL_PROTOCOL_TLSV1_2;
|
||||||
ctx = SSLContext.make(opts, mode);
|
if (OpenSsl.isTlsv13Supported()) {
|
||||||
|
protocolOpts |= SSL.SSL_PROTOCOL_TLSV1_3;
|
||||||
|
}
|
||||||
|
ctx = SSLContext.make(protocolOpts, mode);
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
throw new SSLException("failed to create an SSL_CTX", e);
|
throw new SSLException("failed to create an SSL_CTX", e);
|
||||||
}
|
}
|
||||||
|
|
||||||
SSLContext.setOptions(ctx, SSLContext.getOptions(ctx) |
|
boolean tlsv13Supported = OpenSsl.isTlsv13Supported();
|
||||||
|
StringBuilder cipherBuilder = new StringBuilder();
|
||||||
|
StringBuilder cipherTLSv13Builder = new StringBuilder();
|
||||||
|
|
||||||
|
/* List the ciphers that are permitted to negotiate. */
|
||||||
|
try {
|
||||||
|
if (unmodifiableCiphers.isEmpty()) {
|
||||||
|
// Set non TLSv1.3 ciphers.
|
||||||
|
SSLContext.setCipherSuite(ctx, StringUtil.EMPTY_STRING, false);
|
||||||
|
if (tlsv13Supported) {
|
||||||
|
// Set TLSv1.3 ciphers.
|
||||||
|
SSLContext.setCipherSuite(ctx, StringUtil.EMPTY_STRING, true);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
CipherSuiteConverter.convertToCipherStrings(
|
||||||
|
unmodifiableCiphers, cipherBuilder, cipherTLSv13Builder);
|
||||||
|
|
||||||
|
// Set non TLSv1.3 ciphers.
|
||||||
|
SSLContext.setCipherSuite(ctx, cipherBuilder.toString(), false);
|
||||||
|
if (tlsv13Supported) {
|
||||||
|
// Set TLSv1.3 ciphers.
|
||||||
|
SSLContext.setCipherSuite(ctx, cipherTLSv13Builder.toString(), true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (SSLException e) {
|
||||||
|
throw e;
|
||||||
|
} catch (Exception e) {
|
||||||
|
throw new SSLException("failed to set cipher suite: " + unmodifiableCiphers, e);
|
||||||
|
}
|
||||||
|
|
||||||
|
int options = SSLContext.getOptions(ctx) |
|
||||||
SSL.SSL_OP_NO_SSLv2 |
|
SSL.SSL_OP_NO_SSLv2 |
|
||||||
SSL.SSL_OP_NO_SSLv3 |
|
SSL.SSL_OP_NO_SSLv3 |
|
||||||
|
// Disable TLSv1.3 by default for now. Even if TLSv1.3 is not supported this will
|
||||||
|
// work fine as in this case SSL_OP_NO_TLSv1_3 will be 0.
|
||||||
|
SSL.SSL_OP_NO_TLSv1_3 |
|
||||||
|
|
||||||
SSL.SSL_OP_CIPHER_SERVER_PREFERENCE |
|
SSL.SSL_OP_CIPHER_SERVER_PREFERENCE |
|
||||||
|
|
||||||
// We do not support compression at the moment so we should explicitly disable it.
|
// We do not support compression at the moment so we should explicitly disable it.
|
||||||
@ -244,7 +281,15 @@ public abstract class ReferenceCountedOpenSslContext extends SslContext implemen
|
|||||||
// This also let SSLSession.getId() work the same way for the JDK implementation and the
|
// This also let SSLSession.getId() work the same way for the JDK implementation and the
|
||||||
// OpenSSLEngine. If tickets are supported SSLSession.getId() will only return an ID on the
|
// OpenSSLEngine. If tickets are supported SSLSession.getId() will only return an ID on the
|
||||||
// server-side if it could make use of tickets.
|
// server-side if it could make use of tickets.
|
||||||
SSL.SSL_OP_NO_TICKET);
|
SSL.SSL_OP_NO_TICKET;
|
||||||
|
|
||||||
|
if (cipherBuilder.length() == 0) {
|
||||||
|
// No ciphers that are compatible with SSLv2 / SSLv3 / TLSv1 / TLSv1.1 / TLSv1.2
|
||||||
|
options |= SSL.SSL_OP_NO_SSLv2 | SSL.SSL_OP_NO_SSLv3 | SSL.SSL_OP_NO_TLSv1
|
||||||
|
| SSL.SSL_OP_NO_TLSv1_1 | SSL.SSL_OP_NO_TLSv1_2;
|
||||||
|
}
|
||||||
|
|
||||||
|
SSLContext.setOptions(ctx, options);
|
||||||
|
|
||||||
// We need to enable SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER as the memory address may change between
|
// We need to enable SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER as the memory address may change between
|
||||||
// calling OpenSSLEngine.wrap(...).
|
// calling OpenSSLEngine.wrap(...).
|
||||||
@ -255,15 +300,6 @@ public abstract class ReferenceCountedOpenSslContext extends SslContext implemen
|
|||||||
SSLContext.setTmpDHLength(ctx, DH_KEY_LENGTH);
|
SSLContext.setTmpDHLength(ctx, DH_KEY_LENGTH);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* List the ciphers that are permitted to negotiate. */
|
|
||||||
try {
|
|
||||||
SSLContext.setCipherSuite(ctx, CipherSuiteConverter.toOpenSsl(unmodifiableCiphers));
|
|
||||||
} catch (SSLException e) {
|
|
||||||
throw e;
|
|
||||||
} catch (Exception e) {
|
|
||||||
throw new SSLException("failed to set cipher suite: " + unmodifiableCiphers, e);
|
|
||||||
}
|
|
||||||
|
|
||||||
List<String> nextProtoList = apn.protocols();
|
List<String> nextProtoList = apn.protocols();
|
||||||
/* Set next protocols for next protocol negotiation extension, if specified */
|
/* Set next protocols for next protocol negotiation extension, if specified */
|
||||||
if (!nextProtoList.isEmpty()) {
|
if (!nextProtoList.isEmpty()) {
|
||||||
|
@ -66,9 +66,8 @@ import static io.netty.handler.ssl.SslUtils.PROTOCOL_SSL_V3;
|
|||||||
import static io.netty.handler.ssl.SslUtils.PROTOCOL_TLS_V1;
|
import static io.netty.handler.ssl.SslUtils.PROTOCOL_TLS_V1;
|
||||||
import static io.netty.handler.ssl.SslUtils.PROTOCOL_TLS_V1_1;
|
import static io.netty.handler.ssl.SslUtils.PROTOCOL_TLS_V1_1;
|
||||||
import static io.netty.handler.ssl.SslUtils.PROTOCOL_TLS_V1_2;
|
import static io.netty.handler.ssl.SslUtils.PROTOCOL_TLS_V1_2;
|
||||||
|
import static io.netty.handler.ssl.SslUtils.PROTOCOL_TLS_V1_3;
|
||||||
import static io.netty.handler.ssl.SslUtils.SSL_RECORD_HEADER_LENGTH;
|
import static io.netty.handler.ssl.SslUtils.SSL_RECORD_HEADER_LENGTH;
|
||||||
import static io.netty.internal.tcnative.SSL.SSL_MAX_PLAINTEXT_LENGTH;
|
|
||||||
import static io.netty.internal.tcnative.SSL.SSL_MAX_RECORD_LENGTH;
|
|
||||||
import static io.netty.util.internal.EmptyArrays.EMPTY_CERTIFICATES;
|
import static io.netty.util.internal.EmptyArrays.EMPTY_CERTIFICATES;
|
||||||
import static io.netty.util.internal.EmptyArrays.EMPTY_JAVAX_X509_CERTIFICATES;
|
import static io.netty.util.internal.EmptyArrays.EMPTY_JAVAX_X509_CERTIFICATES;
|
||||||
import static io.netty.util.internal.ObjectUtil.checkNotNull;
|
import static io.netty.util.internal.ObjectUtil.checkNotNull;
|
||||||
@ -109,12 +108,14 @@ public class ReferenceCountedOpenSslEngine extends SSLEngine implements Referenc
|
|||||||
private static final int OPENSSL_OP_NO_PROTOCOL_INDEX_TLSv1 = 2;
|
private static final int OPENSSL_OP_NO_PROTOCOL_INDEX_TLSv1 = 2;
|
||||||
private static final int OPENSSL_OP_NO_PROTOCOL_INDEX_TLSv1_1 = 3;
|
private static final int OPENSSL_OP_NO_PROTOCOL_INDEX_TLSv1_1 = 3;
|
||||||
private static final int OPENSSL_OP_NO_PROTOCOL_INDEX_TLSv1_2 = 4;
|
private static final int OPENSSL_OP_NO_PROTOCOL_INDEX_TLSv1_2 = 4;
|
||||||
|
private static final int OPENSSL_OP_NO_PROTOCOL_INDEX_TLSv1_3 = 5;
|
||||||
private static final int[] OPENSSL_OP_NO_PROTOCOLS = {
|
private static final int[] OPENSSL_OP_NO_PROTOCOLS = {
|
||||||
SSL.SSL_OP_NO_SSLv2,
|
SSL.SSL_OP_NO_SSLv2,
|
||||||
SSL.SSL_OP_NO_SSLv3,
|
SSL.SSL_OP_NO_SSLv3,
|
||||||
SSL.SSL_OP_NO_TLSv1,
|
SSL.SSL_OP_NO_TLSv1,
|
||||||
SSL.SSL_OP_NO_TLSv1_1,
|
SSL.SSL_OP_NO_TLSv1_1,
|
||||||
SSL.SSL_OP_NO_TLSv1_2
|
SSL.SSL_OP_NO_TLSv1_2,
|
||||||
|
SSL.SSL_OP_NO_TLSv1_3
|
||||||
};
|
};
|
||||||
/**
|
/**
|
||||||
* <a href="https://www.openssl.org/docs/man1.0.2/crypto/X509_check_host.html">The flags argument is usually 0</a>.
|
* <a href="https://www.openssl.org/docs/man1.0.2/crypto/X509_check_host.html">The flags argument is usually 0</a>.
|
||||||
@ -124,11 +125,11 @@ public class ReferenceCountedOpenSslEngine extends SSLEngine implements Referenc
|
|||||||
/**
|
/**
|
||||||
* Depends upon tcnative ... only use if tcnative is available!
|
* Depends upon tcnative ... only use if tcnative is available!
|
||||||
*/
|
*/
|
||||||
static final int MAX_PLAINTEXT_LENGTH = SSL_MAX_PLAINTEXT_LENGTH;
|
static final int MAX_PLAINTEXT_LENGTH = SSL.SSL_MAX_PLAINTEXT_LENGTH;
|
||||||
/**
|
/**
|
||||||
* Depends upon tcnative ... only use if tcnative is available!
|
* Depends upon tcnative ... only use if tcnative is available!
|
||||||
*/
|
*/
|
||||||
private static final int MAX_RECORD_SIZE = SSL_MAX_RECORD_LENGTH;
|
private static final int MAX_RECORD_SIZE = SSL.SSL_MAX_RECORD_LENGTH;
|
||||||
|
|
||||||
private static final AtomicIntegerFieldUpdater<ReferenceCountedOpenSslEngine> DESTROYED_UPDATER =
|
private static final AtomicIntegerFieldUpdater<ReferenceCountedOpenSslEngine> DESTROYED_UPDATER =
|
||||||
AtomicIntegerFieldUpdater.newUpdater(ReferenceCountedOpenSslEngine.class, "destroyed");
|
AtomicIntegerFieldUpdater.newUpdater(ReferenceCountedOpenSslEngine.class, "destroyed");
|
||||||
@ -1206,7 +1207,10 @@ public class ReferenceCountedOpenSslEngine extends SSLEngine implements Referenc
|
|||||||
// As rejectRemoteInitiatedRenegotiation() is called in a finally block we also need to check if we shutdown
|
// As rejectRemoteInitiatedRenegotiation() is called in a finally block we also need to check if we shutdown
|
||||||
// the engine before as otherwise SSL.getHandshakeCount(ssl) will throw an NPE if the passed in ssl is 0.
|
// the engine before as otherwise SSL.getHandshakeCount(ssl) will throw an NPE if the passed in ssl is 0.
|
||||||
// See https://github.com/netty/netty/issues/7353
|
// See https://github.com/netty/netty/issues/7353
|
||||||
if (!isDestroyed() && SSL.getHandshakeCount(ssl) > 1) {
|
if (!isDestroyed() && SSL.getHandshakeCount(ssl) > 1 &&
|
||||||
|
// As we may count multiple handshakes when TLSv1.3 is used we should just ignore this here as
|
||||||
|
// renegotiation is not supported in TLSv1.3 as per spec.
|
||||||
|
!SslUtils.PROTOCOL_TLS_V1_3.equals(session.getProtocol()) && handshakeState == HandshakeState.FINISHED) {
|
||||||
// TODO: In future versions me may also want to send a fatal_alert to the client and so notify it
|
// TODO: In future versions me may also want to send a fatal_alert to the client and so notify it
|
||||||
// that the renegotiation failed.
|
// that the renegotiation failed.
|
||||||
shutdown();
|
shutdown();
|
||||||
@ -1379,15 +1383,18 @@ public class ReferenceCountedOpenSslEngine extends SSLEngine implements Referenc
|
|||||||
if (enabled == null) {
|
if (enabled == null) {
|
||||||
return EmptyArrays.EMPTY_STRINGS;
|
return EmptyArrays.EMPTY_STRINGS;
|
||||||
} else {
|
} else {
|
||||||
|
List<String> enabledList = new ArrayList<String>();
|
||||||
synchronized (this) {
|
synchronized (this) {
|
||||||
for (int i = 0; i < enabled.length; i++) {
|
for (int i = 0; i < enabled.length; i++) {
|
||||||
String mapped = toJavaCipherSuite(enabled[i]);
|
String mapped = toJavaCipherSuite(enabled[i]);
|
||||||
if (mapped != null) {
|
final String cipher = mapped == null ? enabled[i] : mapped;
|
||||||
enabled[i] = mapped;
|
if (!OpenSsl.isTlsv13Supported() && SslUtils.isTLSv13Cipher(cipher)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
enabledList.add(cipher);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
return enabledList.toArray(new String[0]);
|
||||||
return enabled;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1396,35 +1403,28 @@ public class ReferenceCountedOpenSslEngine extends SSLEngine implements Referenc
|
|||||||
checkNotNull(cipherSuites, "cipherSuites");
|
checkNotNull(cipherSuites, "cipherSuites");
|
||||||
|
|
||||||
final StringBuilder buf = new StringBuilder();
|
final StringBuilder buf = new StringBuilder();
|
||||||
for (String c: cipherSuites) {
|
final StringBuilder bufTLSv13 = new StringBuilder();
|
||||||
if (c == null) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
String converted = CipherSuiteConverter.toOpenSsl(c);
|
|
||||||
if (converted == null) {
|
|
||||||
converted = c;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!OpenSsl.isCipherSuiteAvailable(converted)) {
|
|
||||||
throw new IllegalArgumentException("unsupported cipher suite: " + c + '(' + converted + ')');
|
|
||||||
}
|
|
||||||
|
|
||||||
buf.append(converted);
|
|
||||||
buf.append(':');
|
|
||||||
}
|
|
||||||
|
|
||||||
if (buf.length() == 0) {
|
|
||||||
throw new IllegalArgumentException("empty cipher suites");
|
|
||||||
}
|
|
||||||
buf.setLength(buf.length() - 1);
|
|
||||||
|
|
||||||
|
CipherSuiteConverter.convertToCipherStrings(Arrays.asList(cipherSuites), buf, bufTLSv13);
|
||||||
final String cipherSuiteSpec = buf.toString();
|
final String cipherSuiteSpec = buf.toString();
|
||||||
|
final String cipherSuiteSpecTLSv13 = bufTLSv13.toString();
|
||||||
|
|
||||||
|
if (!OpenSsl.isTlsv13Supported() && !cipherSuiteSpecTLSv13.isEmpty()) {
|
||||||
|
throw new IllegalArgumentException("TLSv1.3 is not supported by this java version.");
|
||||||
|
}
|
||||||
synchronized (this) {
|
synchronized (this) {
|
||||||
if (!isDestroyed()) {
|
if (!isDestroyed()) {
|
||||||
|
// TODO: Should we also adjust the protocols based on if there are any ciphers left that can be used
|
||||||
|
// for TLSv1.3 or for previor SSL/TLS versions ?
|
||||||
try {
|
try {
|
||||||
SSL.setCipherSuites(ssl, cipherSuiteSpec);
|
// Set non TLSv1.3 ciphers.
|
||||||
|
SSL.setCipherSuites(ssl, cipherSuiteSpec, false);
|
||||||
|
|
||||||
|
if (OpenSsl.isTlsv13Supported()) {
|
||||||
|
// Set TLSv1.3 ciphers.
|
||||||
|
SSL.setCipherSuites(ssl, cipherSuiteSpecTLSv13, true);
|
||||||
|
}
|
||||||
|
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
throw new IllegalStateException("failed to enable cipher suites: " + cipherSuiteSpec, e);
|
throw new IllegalStateException("failed to enable cipher suites: " + cipherSuiteSpec, e);
|
||||||
}
|
}
|
||||||
@ -1462,6 +1462,9 @@ public class ReferenceCountedOpenSslEngine extends SSLEngine implements Referenc
|
|||||||
if (isProtocolEnabled(opts, SSL.SSL_OP_NO_TLSv1_2, PROTOCOL_TLS_V1_2)) {
|
if (isProtocolEnabled(opts, SSL.SSL_OP_NO_TLSv1_2, PROTOCOL_TLS_V1_2)) {
|
||||||
enabled.add(PROTOCOL_TLS_V1_2);
|
enabled.add(PROTOCOL_TLS_V1_2);
|
||||||
}
|
}
|
||||||
|
if (isProtocolEnabled(opts, SSL.SSL_OP_NO_TLSv1_3, PROTOCOL_TLS_V1_3)) {
|
||||||
|
enabled.add(PROTOCOL_TLS_V1_3);
|
||||||
|
}
|
||||||
if (isProtocolEnabled(opts, SSL.SSL_OP_NO_SSLv2, PROTOCOL_SSL_V2)) {
|
if (isProtocolEnabled(opts, SSL.SSL_OP_NO_SSLv2, PROTOCOL_SSL_V2)) {
|
||||||
enabled.add(PROTOCOL_SSL_V2);
|
enabled.add(PROTOCOL_SSL_V2);
|
||||||
}
|
}
|
||||||
@ -1533,13 +1536,20 @@ public class ReferenceCountedOpenSslEngine extends SSLEngine implements Referenc
|
|||||||
if (maxProtocolIndex < OPENSSL_OP_NO_PROTOCOL_INDEX_TLSv1_2) {
|
if (maxProtocolIndex < OPENSSL_OP_NO_PROTOCOL_INDEX_TLSv1_2) {
|
||||||
maxProtocolIndex = OPENSSL_OP_NO_PROTOCOL_INDEX_TLSv1_2;
|
maxProtocolIndex = OPENSSL_OP_NO_PROTOCOL_INDEX_TLSv1_2;
|
||||||
}
|
}
|
||||||
|
} else if (p.equals(PROTOCOL_TLS_V1_3)) {
|
||||||
|
if (minProtocolIndex > OPENSSL_OP_NO_PROTOCOL_INDEX_TLSv1_3) {
|
||||||
|
minProtocolIndex = OPENSSL_OP_NO_PROTOCOL_INDEX_TLSv1_3;
|
||||||
|
}
|
||||||
|
if (maxProtocolIndex < OPENSSL_OP_NO_PROTOCOL_INDEX_TLSv1_3) {
|
||||||
|
maxProtocolIndex = OPENSSL_OP_NO_PROTOCOL_INDEX_TLSv1_3;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
synchronized (this) {
|
synchronized (this) {
|
||||||
if (!isDestroyed()) {
|
if (!isDestroyed()) {
|
||||||
// Clear out options which disable protocols
|
// Clear out options which disable protocols
|
||||||
SSL.clearOptions(ssl, SSL.SSL_OP_NO_SSLv2 | SSL.SSL_OP_NO_SSLv3 | SSL.SSL_OP_NO_TLSv1 |
|
SSL.clearOptions(ssl, SSL.SSL_OP_NO_SSLv2 | SSL.SSL_OP_NO_SSLv3 | SSL.SSL_OP_NO_TLSv1 |
|
||||||
SSL.SSL_OP_NO_TLSv1_1 | SSL.SSL_OP_NO_TLSv1_2);
|
SSL.SSL_OP_NO_TLSv1_1 | SSL.SSL_OP_NO_TLSv1_2 | SSL.SSL_OP_NO_TLSv1_3);
|
||||||
|
|
||||||
int opts = 0;
|
int opts = 0;
|
||||||
for (int i = 0; i < minProtocolIndex; ++i) {
|
for (int i = 0; i < minProtocolIndex; ++i) {
|
||||||
|
@ -22,9 +22,14 @@ import io.netty.channel.ChannelHandlerContext;
|
|||||||
import io.netty.handler.codec.base64.Base64;
|
import io.netty.handler.codec.base64.Base64;
|
||||||
import io.netty.handler.codec.base64.Base64Dialect;
|
import io.netty.handler.codec.base64.Base64Dialect;
|
||||||
import io.netty.util.NetUtil;
|
import io.netty.util.NetUtil;
|
||||||
|
import io.netty.util.internal.EmptyArrays;
|
||||||
|
import io.netty.util.internal.PlatformDependent;
|
||||||
|
|
||||||
import java.nio.ByteBuffer;
|
import java.nio.ByteBuffer;
|
||||||
import java.nio.ByteOrder;
|
import java.nio.ByteOrder;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.HashSet;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
|
||||||
@ -36,7 +41,11 @@ import static java.util.Arrays.asList;
|
|||||||
* Constants for SSL packets.
|
* Constants for SSL packets.
|
||||||
*/
|
*/
|
||||||
final class SslUtils {
|
final class SslUtils {
|
||||||
|
// See https://tools.ietf.org/html/rfc8446#appendix-B.4
|
||||||
|
private static final Set<String> TLSV13_CIPHERS = Collections.unmodifiableSet(new HashSet<String>(
|
||||||
|
asList("TLS_AES_256_GCM_SHA384", "TLS_CHACHA20_POLY1305_SHA256",
|
||||||
|
"TLS_AES_128_GCM_SHA256", "TLS_AES_128_CCM_8_SHA256",
|
||||||
|
"TLS_AES_128_CCM_SHA256")));
|
||||||
// Protocols
|
// Protocols
|
||||||
static final String PROTOCOL_SSL_V2_HELLO = "SSLv2Hello";
|
static final String PROTOCOL_SSL_V2_HELLO = "SSLv2Hello";
|
||||||
static final String PROTOCOL_SSL_V2 = "SSLv2";
|
static final String PROTOCOL_SSL_V2 = "SSLv2";
|
||||||
@ -44,6 +53,7 @@ final class SslUtils {
|
|||||||
static final String PROTOCOL_TLS_V1 = "TLSv1";
|
static final String PROTOCOL_TLS_V1 = "TLSv1";
|
||||||
static final String PROTOCOL_TLS_V1_1 = "TLSv1.1";
|
static final String PROTOCOL_TLS_V1_1 = "TLSv1.1";
|
||||||
static final String PROTOCOL_TLS_V1_2 = "TLSv1.2";
|
static final String PROTOCOL_TLS_V1_2 = "TLSv1.2";
|
||||||
|
static final String PROTOCOL_TLS_V1_3 = "TLSv1.3";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* change cipher spec
|
* change cipher spec
|
||||||
@ -85,20 +95,36 @@ final class SslUtils {
|
|||||||
*/
|
*/
|
||||||
static final int NOT_ENCRYPTED = -2;
|
static final int NOT_ENCRYPTED = -2;
|
||||||
|
|
||||||
static final String[] DEFAULT_CIPHER_SUITES = {
|
static final String[] DEFAULT_CIPHER_SUITES;
|
||||||
|
static final String[] DEFAULT_TLSV13_CIPHER_SUITES;
|
||||||
|
|
||||||
|
static {
|
||||||
|
if (PlatformDependent.javaVersion() >= 11) {
|
||||||
|
DEFAULT_TLSV13_CIPHER_SUITES = new String[] { "TLS_AES_128_GCM_SHA256", "TLS_AES_256_GCM_SHA384" };
|
||||||
|
} else {
|
||||||
|
DEFAULT_TLSV13_CIPHER_SUITES = EmptyArrays.EMPTY_STRINGS;
|
||||||
|
}
|
||||||
|
|
||||||
|
List<String> defaultCiphers = new ArrayList<String>();
|
||||||
// GCM (Galois/Counter Mode) requires JDK 8.
|
// GCM (Galois/Counter Mode) requires JDK 8.
|
||||||
"TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384",
|
defaultCiphers.add("TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384");
|
||||||
"TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256",
|
defaultCiphers.add("TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256");
|
||||||
"TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256",
|
defaultCiphers.add("TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256");
|
||||||
"TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA",
|
defaultCiphers.add("TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA");
|
||||||
// AES256 requires JCE unlimited strength jurisdiction policy files.
|
// AES256 requires JCE unlimited strength jurisdiction policy files.
|
||||||
"TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA",
|
defaultCiphers.add("TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA");
|
||||||
// GCM (Galois/Counter Mode) requires JDK 8.
|
// GCM (Galois/Counter Mode) requires JDK 8.
|
||||||
"TLS_RSA_WITH_AES_128_GCM_SHA256",
|
defaultCiphers.add("TLS_RSA_WITH_AES_128_GCM_SHA256");
|
||||||
"TLS_RSA_WITH_AES_128_CBC_SHA",
|
defaultCiphers.add("TLS_RSA_WITH_AES_128_CBC_SHA");
|
||||||
// AES256 requires JCE unlimited strength jurisdiction policy files.
|
// AES256 requires JCE unlimited strength jurisdiction policy files.
|
||||||
"TLS_RSA_WITH_AES_256_CBC_SHA"
|
defaultCiphers.add("TLS_RSA_WITH_AES_256_CBC_SHA");
|
||||||
};
|
|
||||||
|
for (String tlsv13Cipher: DEFAULT_TLSV13_CIPHER_SUITES) {
|
||||||
|
defaultCiphers.add(tlsv13Cipher);
|
||||||
|
}
|
||||||
|
|
||||||
|
DEFAULT_CIPHER_SUITES = defaultCiphers.toArray(new String[0]);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Add elements from {@code names} into {@code enabled} if they are in {@code supported}.
|
* Add elements from {@code names} into {@code enabled} if they are in {@code supported}.
|
||||||
@ -361,6 +387,14 @@ final class SslUtils {
|
|||||||
!NetUtil.isValidIpV6Address(hostname);
|
!NetUtil.isValidIpV6Address(hostname);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns {@code true} if the the given cipher (in openssl format) is for TLSv1.3, {@code false} otherwise.
|
||||||
|
*/
|
||||||
|
static boolean isTLSv13Cipher(String cipher) {
|
||||||
|
// See https://tools.ietf.org/html/rfc8446#appendix-B.4
|
||||||
|
return TLSV13_CIPHERS.contains(cipher);
|
||||||
|
}
|
||||||
|
|
||||||
private SslUtils() {
|
private SslUtils() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -125,12 +125,16 @@ public class CipherSuiteCanaryTest {
|
|||||||
final SslContext sslServerContext = SslContextBuilder.forServer(CERT.certificate(), CERT.privateKey())
|
final SslContext sslServerContext = SslContextBuilder.forServer(CERT.certificate(), CERT.privateKey())
|
||||||
.sslProvider(serverSslProvider)
|
.sslProvider(serverSslProvider)
|
||||||
.ciphers(ciphers)
|
.ciphers(ciphers)
|
||||||
|
// As this is not a TLSv1.3 cipher we should ensure we talk something else.
|
||||||
|
.protocols(SslUtils.PROTOCOL_TLS_V1_2)
|
||||||
.build();
|
.build();
|
||||||
|
|
||||||
try {
|
try {
|
||||||
final SslContext sslClientContext = SslContextBuilder.forClient()
|
final SslContext sslClientContext = SslContextBuilder.forClient()
|
||||||
.sslProvider(clientSslProvider)
|
.sslProvider(clientSslProvider)
|
||||||
.ciphers(ciphers)
|
.ciphers(ciphers)
|
||||||
|
// As this is not a TLSv1.3 cipher we should ensure we talk something else.
|
||||||
|
.protocols(SslUtils.PROTOCOL_TLS_V1_2)
|
||||||
.trustManager(InsecureTrustManagerFactory.INSTANCE)
|
.trustManager(InsecureTrustManagerFactory.INSTANCE)
|
||||||
.build();
|
.build();
|
||||||
|
|
||||||
|
@ -22,8 +22,7 @@ import org.junit.Test;
|
|||||||
|
|
||||||
import static org.hamcrest.Matchers.is;
|
import static org.hamcrest.Matchers.is;
|
||||||
import static org.hamcrest.Matchers.sameInstance;
|
import static org.hamcrest.Matchers.sameInstance;
|
||||||
import static org.junit.Assert.assertNull;
|
import static org.junit.Assert.*;
|
||||||
import static org.junit.Assert.assertThat;
|
|
||||||
|
|
||||||
public class CipherSuiteConverterTest {
|
public class CipherSuiteConverterTest {
|
||||||
|
|
||||||
|
@ -31,17 +31,17 @@ import static org.junit.Assume.assumeTrue;
|
|||||||
@RunWith(Parameterized.class)
|
@RunWith(Parameterized.class)
|
||||||
public class ConscryptJdkSslEngineInteropTest extends SSLEngineTest {
|
public class ConscryptJdkSslEngineInteropTest extends SSLEngineTest {
|
||||||
|
|
||||||
@Parameterized.Parameters(name = "{index}: bufferType = {0}")
|
@Parameterized.Parameters(name = "{index}: bufferType = {0}, combo = {1}")
|
||||||
public static Collection<Object> data() {
|
public static Collection<Object[]> data() {
|
||||||
List<Object> params = new ArrayList<Object>();
|
List<Object[]> params = new ArrayList<Object[]>();
|
||||||
for (BufferType type: BufferType.values()) {
|
for (BufferType type: BufferType.values()) {
|
||||||
params.add(type);
|
params.add(new Object[] { type, ProtocolCipherCombo.tlsv12()});
|
||||||
}
|
}
|
||||||
return params;
|
return params;
|
||||||
}
|
}
|
||||||
|
|
||||||
public ConscryptJdkSslEngineInteropTest(BufferType type) {
|
public ConscryptJdkSslEngineInteropTest(BufferType type, ProtocolCipherCombo combo) {
|
||||||
super(type);
|
super(type, combo);
|
||||||
}
|
}
|
||||||
|
|
||||||
@BeforeClass
|
@BeforeClass
|
||||||
|
@ -30,17 +30,17 @@ import static org.junit.Assume.assumeTrue;
|
|||||||
@RunWith(Parameterized.class)
|
@RunWith(Parameterized.class)
|
||||||
public class ConscryptSslEngineTest extends SSLEngineTest {
|
public class ConscryptSslEngineTest extends SSLEngineTest {
|
||||||
|
|
||||||
@Parameterized.Parameters(name = "{index}: bufferType = {0}")
|
@Parameterized.Parameters(name = "{index}: bufferType = {0}, combo = {1}")
|
||||||
public static Collection<Object> data() {
|
public static Collection<Object[]> data() {
|
||||||
List<Object> params = new ArrayList<Object>();
|
List<Object[]> params = new ArrayList<Object[]>();
|
||||||
for (BufferType type: BufferType.values()) {
|
for (BufferType type: BufferType.values()) {
|
||||||
params.add(type);
|
params.add(new Object[] { type, ProtocolCipherCombo.tlsv12()});
|
||||||
}
|
}
|
||||||
return params;
|
return params;
|
||||||
}
|
}
|
||||||
|
|
||||||
public ConscryptSslEngineTest(BufferType type) {
|
public ConscryptSslEngineTest(BufferType type, ProtocolCipherCombo combo) {
|
||||||
super(type);
|
super(type, combo);
|
||||||
}
|
}
|
||||||
|
|
||||||
@BeforeClass
|
@BeforeClass
|
||||||
|
@ -16,6 +16,7 @@
|
|||||||
package io.netty.handler.ssl;
|
package io.netty.handler.ssl;
|
||||||
|
|
||||||
import java.security.Provider;
|
import java.security.Provider;
|
||||||
|
|
||||||
import org.junit.BeforeClass;
|
import org.junit.BeforeClass;
|
||||||
import org.junit.Ignore;
|
import org.junit.Ignore;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
@ -31,17 +32,17 @@ import static org.junit.Assume.assumeTrue;
|
|||||||
@RunWith(Parameterized.class)
|
@RunWith(Parameterized.class)
|
||||||
public class JdkConscryptSslEngineInteropTest extends SSLEngineTest {
|
public class JdkConscryptSslEngineInteropTest extends SSLEngineTest {
|
||||||
|
|
||||||
@Parameterized.Parameters(name = "{index}: bufferType = {0}")
|
@Parameterized.Parameters(name = "{index}: bufferType = {0}, combo = {1}")
|
||||||
public static Collection<Object> data() {
|
public static Collection<Object[]> data() {
|
||||||
List<Object> params = new ArrayList<Object>();
|
List<Object[]> params = new ArrayList<Object[]>();
|
||||||
for (BufferType type: BufferType.values()) {
|
for (BufferType type: BufferType.values()) {
|
||||||
params.add(type);
|
params.add(new Object[] { type, ProtocolCipherCombo.tlsv12()});
|
||||||
}
|
}
|
||||||
return params;
|
return params;
|
||||||
}
|
}
|
||||||
|
|
||||||
public JdkConscryptSslEngineInteropTest(BufferType type) {
|
public JdkConscryptSslEngineInteropTest(BufferType type, ProtocolCipherCombo combo) {
|
||||||
super(type);
|
super(type, combo);
|
||||||
}
|
}
|
||||||
|
|
||||||
@BeforeClass
|
@BeforeClass
|
||||||
|
@ -15,6 +15,7 @@
|
|||||||
*/
|
*/
|
||||||
package io.netty.handler.ssl;
|
package io.netty.handler.ssl;
|
||||||
|
|
||||||
|
import io.netty.util.internal.PlatformDependent;
|
||||||
import org.junit.BeforeClass;
|
import org.junit.BeforeClass;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
import org.junit.runner.RunWith;
|
import org.junit.runner.RunWith;
|
||||||
@ -32,17 +33,21 @@ import static org.junit.Assume.assumeTrue;
|
|||||||
@RunWith(Parameterized.class)
|
@RunWith(Parameterized.class)
|
||||||
public class JdkOpenSslEngineInteroptTest extends SSLEngineTest {
|
public class JdkOpenSslEngineInteroptTest extends SSLEngineTest {
|
||||||
|
|
||||||
@Parameterized.Parameters(name = "{index}: bufferType = {0}")
|
@Parameterized.Parameters(name = "{index}: bufferType = {0}, combo = {1}")
|
||||||
public static Collection<Object> data() {
|
public static Collection<Object[]> data() {
|
||||||
List<Object> params = new ArrayList<Object>();
|
List<Object[]> params = new ArrayList<Object[]>();
|
||||||
for (BufferType type: BufferType.values()) {
|
for (BufferType type: BufferType.values()) {
|
||||||
params.add(type);
|
params.add(new Object[] { type, ProtocolCipherCombo.tlsv12()});
|
||||||
|
|
||||||
|
if (PlatformDependent.javaVersion() >= 11 && OpenSsl.isTlsv13Supported()) {
|
||||||
|
params.add(new Object[] { type, ProtocolCipherCombo.tlsv13() });
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return params;
|
return params;
|
||||||
}
|
}
|
||||||
|
|
||||||
public JdkOpenSslEngineInteroptTest(BufferType type) {
|
public JdkOpenSslEngineInteroptTest(BufferType type, ProtocolCipherCombo protocolCipherCombo) {
|
||||||
super(type);
|
super(type, protocolCipherCombo);
|
||||||
}
|
}
|
||||||
|
|
||||||
@BeforeClass
|
@BeforeClass
|
||||||
|
@ -26,6 +26,7 @@ import java.security.Provider;
|
|||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
|
|
||||||
|
import io.netty.util.internal.EmptyArrays;
|
||||||
import io.netty.util.internal.PlatformDependent;
|
import io.netty.util.internal.PlatformDependent;
|
||||||
import org.junit.Ignore;
|
import org.junit.Ignore;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
@ -141,12 +142,15 @@ public class JdkSslEngineTest extends SSLEngineTest {
|
|||||||
private static final String FALLBACK_APPLICATION_LEVEL_PROTOCOL = "my-protocol-http1_1";
|
private static final String FALLBACK_APPLICATION_LEVEL_PROTOCOL = "my-protocol-http1_1";
|
||||||
private static final String APPLICATION_LEVEL_PROTOCOL_NOT_COMPATIBLE = "my-protocol-FOO";
|
private static final String APPLICATION_LEVEL_PROTOCOL_NOT_COMPATIBLE = "my-protocol-FOO";
|
||||||
|
|
||||||
@Parameterized.Parameters(name = "{index}: providerType = {0}, bufferType = {1}")
|
@Parameterized.Parameters(name = "{index}: providerType = {0}, bufferType = {1}, combo = {2}")
|
||||||
public static Collection<Object[]> data() {
|
public static Collection<Object[]> data() {
|
||||||
List<Object[]> params = new ArrayList<Object[]>();
|
List<Object[]> params = new ArrayList<Object[]>();
|
||||||
for (ProviderType providerType : ProviderType.values()) {
|
for (ProviderType providerType : ProviderType.values()) {
|
||||||
for (BufferType bufferType : BufferType.values()) {
|
for (BufferType bufferType : BufferType.values()) {
|
||||||
params.add(new Object[]{providerType, bufferType});
|
params.add(new Object[]{ providerType, bufferType, ProtocolCipherCombo.tlsv12()});
|
||||||
|
if (PlatformDependent.javaVersion() >= 11) {
|
||||||
|
params.add(new Object[] { providerType, bufferType, ProtocolCipherCombo.tlsv13() });
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return params;
|
return params;
|
||||||
@ -156,8 +160,8 @@ public class JdkSslEngineTest extends SSLEngineTest {
|
|||||||
|
|
||||||
private Provider provider;
|
private Provider provider;
|
||||||
|
|
||||||
public JdkSslEngineTest(ProviderType providerType, BufferType bufferType) {
|
public JdkSslEngineTest(ProviderType providerType, BufferType bufferType, ProtocolCipherCombo protocolCipherCombo) {
|
||||||
super(bufferType);
|
super(bufferType, protocolCipherCombo);
|
||||||
this.providerType = providerType;
|
this.providerType = providerType;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -235,9 +239,11 @@ public class JdkSslEngineTest extends SSLEngineTest {
|
|||||||
InsecureTrustManagerFactory.INSTANCE, null,
|
InsecureTrustManagerFactory.INSTANCE, null,
|
||||||
IdentityCipherSuiteFilter.INSTANCE, clientApn, 0, 0);
|
IdentityCipherSuiteFilter.INSTANCE, clientApn, 0, 0);
|
||||||
|
|
||||||
setupHandlers(serverSslCtx, clientSslCtx);
|
setupHandlers(new TestDelegatingSslContext(serverSslCtx), new TestDelegatingSslContext(clientSslCtx));
|
||||||
assertTrue(clientLatch.await(2, TimeUnit.SECONDS));
|
assertTrue(clientLatch.await(2, TimeUnit.SECONDS));
|
||||||
assertTrue(clientException instanceof SSLHandshakeException);
|
// When using TLSv1.3 the handshake is NOT sent in an extra round trip which means there will be
|
||||||
|
// no exception reported in this case but just the channel will be closed.
|
||||||
|
assertTrue(clientException instanceof SSLHandshakeException || clientException == null);
|
||||||
}
|
}
|
||||||
} catch (SkipTestException e) {
|
} catch (SkipTestException e) {
|
||||||
// ALPN availability is dependent on the java version. If ALPN is not available because of
|
// ALPN availability is dependent on the java version. If ALPN is not available because of
|
||||||
@ -358,4 +364,16 @@ public class JdkSslEngineTest extends SSLEngineTest {
|
|||||||
super(message);
|
super(message);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private final class TestDelegatingSslContext extends DelegatingSslContext {
|
||||||
|
TestDelegatingSslContext(SslContext ctx) {
|
||||||
|
super(ctx);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void initEngine(SSLEngine engine) {
|
||||||
|
engine.setEnabledProtocols(protocols());
|
||||||
|
engine.setEnabledCipherSuites(ciphers().toArray(EmptyArrays.EMPTY_STRINGS));
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -67,17 +67,21 @@ public class OpenSslEngineTest extends SSLEngineTest {
|
|||||||
private static final String PREFERRED_APPLICATION_LEVEL_PROTOCOL = "my-protocol-http2";
|
private static final String PREFERRED_APPLICATION_LEVEL_PROTOCOL = "my-protocol-http2";
|
||||||
private static final String FALLBACK_APPLICATION_LEVEL_PROTOCOL = "my-protocol-http1_1";
|
private static final String FALLBACK_APPLICATION_LEVEL_PROTOCOL = "my-protocol-http1_1";
|
||||||
|
|
||||||
@Parameterized.Parameters(name = "{index}: bufferType = {0}")
|
@Parameterized.Parameters(name = "{index}: bufferType = {0}, combo = {1}")
|
||||||
public static Collection<Object> data() {
|
public static Collection<Object[]> data() {
|
||||||
List<Object> params = new ArrayList<Object>();
|
List<Object[]> params = new ArrayList<Object[]>();
|
||||||
for (BufferType type: BufferType.values()) {
|
for (BufferType type: BufferType.values()) {
|
||||||
params.add(type);
|
params.add(new Object[] { type, ProtocolCipherCombo.tlsv12()});
|
||||||
|
|
||||||
|
if (PlatformDependent.javaVersion() >= 11 && OpenSsl.isTlsv13Supported()) {
|
||||||
|
params.add(new Object[] { type, ProtocolCipherCombo.tlsv13() });
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return params;
|
return params;
|
||||||
}
|
}
|
||||||
|
|
||||||
public OpenSslEngineTest(BufferType type) {
|
public OpenSslEngineTest(BufferType type, ProtocolCipherCombo cipherCombo) {
|
||||||
super(type);
|
super(type, cipherCombo);
|
||||||
}
|
}
|
||||||
|
|
||||||
@BeforeClass
|
@BeforeClass
|
||||||
@ -208,10 +212,14 @@ public class OpenSslEngineTest extends SSLEngineTest {
|
|||||||
clientSslCtx = SslContextBuilder.forClient()
|
clientSslCtx = SslContextBuilder.forClient()
|
||||||
.trustManager(InsecureTrustManagerFactory.INSTANCE)
|
.trustManager(InsecureTrustManagerFactory.INSTANCE)
|
||||||
.sslProvider(sslClientProvider())
|
.sslProvider(sslClientProvider())
|
||||||
|
.protocols(protocols())
|
||||||
|
.ciphers(ciphers())
|
||||||
.build();
|
.build();
|
||||||
SelfSignedCertificate ssc = new SelfSignedCertificate();
|
SelfSignedCertificate ssc = new SelfSignedCertificate();
|
||||||
serverSslCtx = SslContextBuilder.forServer(ssc.certificate(), ssc.privateKey())
|
serverSslCtx = SslContextBuilder.forServer(ssc.certificate(), ssc.privateKey())
|
||||||
.sslProvider(sslServerProvider())
|
.sslProvider(sslServerProvider())
|
||||||
|
.protocols(protocols())
|
||||||
|
.ciphers(ciphers())
|
||||||
.build();
|
.build();
|
||||||
SSLEngine clientEngine = null;
|
SSLEngine clientEngine = null;
|
||||||
SSLEngine serverEngine = null;
|
SSLEngine serverEngine = null;
|
||||||
@ -242,10 +250,14 @@ public class OpenSslEngineTest extends SSLEngineTest {
|
|||||||
clientSslCtx = SslContextBuilder.forClient()
|
clientSslCtx = SslContextBuilder.forClient()
|
||||||
.trustManager(InsecureTrustManagerFactory.INSTANCE)
|
.trustManager(InsecureTrustManagerFactory.INSTANCE)
|
||||||
.sslProvider(sslClientProvider())
|
.sslProvider(sslClientProvider())
|
||||||
|
.protocols(protocols())
|
||||||
|
.ciphers(ciphers())
|
||||||
.build();
|
.build();
|
||||||
SelfSignedCertificate ssc = new SelfSignedCertificate();
|
SelfSignedCertificate ssc = new SelfSignedCertificate();
|
||||||
serverSslCtx = SslContextBuilder.forServer(ssc.certificate(), ssc.privateKey())
|
serverSslCtx = SslContextBuilder.forServer(ssc.certificate(), ssc.privateKey())
|
||||||
.sslProvider(sslServerProvider())
|
.sslProvider(sslServerProvider())
|
||||||
|
.protocols(protocols())
|
||||||
|
.ciphers(ciphers())
|
||||||
.build();
|
.build();
|
||||||
SSLEngine clientEngine = null;
|
SSLEngine clientEngine = null;
|
||||||
SSLEngine serverEngine = null;
|
SSLEngine serverEngine = null;
|
||||||
@ -293,10 +305,14 @@ public class OpenSslEngineTest extends SSLEngineTest {
|
|||||||
clientSslCtx = SslContextBuilder.forClient()
|
clientSslCtx = SslContextBuilder.forClient()
|
||||||
.trustManager(InsecureTrustManagerFactory.INSTANCE)
|
.trustManager(InsecureTrustManagerFactory.INSTANCE)
|
||||||
.sslProvider(sslClientProvider())
|
.sslProvider(sslClientProvider())
|
||||||
|
.protocols(protocols())
|
||||||
|
.ciphers(ciphers())
|
||||||
.build();
|
.build();
|
||||||
SelfSignedCertificate ssc = new SelfSignedCertificate();
|
SelfSignedCertificate ssc = new SelfSignedCertificate();
|
||||||
serverSslCtx = SslContextBuilder.forServer(ssc.certificate(), ssc.privateKey())
|
serverSslCtx = SslContextBuilder.forServer(ssc.certificate(), ssc.privateKey())
|
||||||
.sslProvider(sslServerProvider())
|
.sslProvider(sslServerProvider())
|
||||||
|
.protocols(protocols())
|
||||||
|
.ciphers(ciphers())
|
||||||
.build();
|
.build();
|
||||||
SSLEngine clientEngine = null;
|
SSLEngine clientEngine = null;
|
||||||
SSLEngine serverEngine = null;
|
SSLEngine serverEngine = null;
|
||||||
@ -329,10 +345,14 @@ public class OpenSslEngineTest extends SSLEngineTest {
|
|||||||
clientSslCtx = SslContextBuilder.forClient()
|
clientSslCtx = SslContextBuilder.forClient()
|
||||||
.trustManager(InsecureTrustManagerFactory.INSTANCE)
|
.trustManager(InsecureTrustManagerFactory.INSTANCE)
|
||||||
.sslProvider(sslClientProvider())
|
.sslProvider(sslClientProvider())
|
||||||
|
.protocols(protocols())
|
||||||
|
.ciphers(ciphers())
|
||||||
.build();
|
.build();
|
||||||
SelfSignedCertificate ssc = new SelfSignedCertificate();
|
SelfSignedCertificate ssc = new SelfSignedCertificate();
|
||||||
serverSslCtx = SslContextBuilder.forServer(ssc.certificate(), ssc.privateKey())
|
serverSslCtx = SslContextBuilder.forServer(ssc.certificate(), ssc.privateKey())
|
||||||
.sslProvider(sslServerProvider())
|
.sslProvider(sslServerProvider())
|
||||||
|
.protocols(protocols())
|
||||||
|
.ciphers(ciphers())
|
||||||
.build();
|
.build();
|
||||||
SSLEngine clientEngine = null;
|
SSLEngine clientEngine = null;
|
||||||
SSLEngine serverEngine = null;
|
SSLEngine serverEngine = null;
|
||||||
@ -376,6 +396,8 @@ public class OpenSslEngineTest extends SSLEngineTest {
|
|||||||
clientSslCtx = SslContextBuilder.forClient()
|
clientSslCtx = SslContextBuilder.forClient()
|
||||||
.trustManager(InsecureTrustManagerFactory.INSTANCE)
|
.trustManager(InsecureTrustManagerFactory.INSTANCE)
|
||||||
.sslProvider(sslClientProvider())
|
.sslProvider(sslClientProvider())
|
||||||
|
.protocols(protocols())
|
||||||
|
.ciphers(ciphers())
|
||||||
.build();
|
.build();
|
||||||
SSLEngine clientEngine = null;
|
SSLEngine clientEngine = null;
|
||||||
try {
|
try {
|
||||||
@ -392,6 +414,8 @@ public class OpenSslEngineTest extends SSLEngineTest {
|
|||||||
clientSslCtx = SslContextBuilder.forClient()
|
clientSslCtx = SslContextBuilder.forClient()
|
||||||
.trustManager(InsecureTrustManagerFactory.INSTANCE)
|
.trustManager(InsecureTrustManagerFactory.INSTANCE)
|
||||||
.sslProvider(sslClientProvider())
|
.sslProvider(sslClientProvider())
|
||||||
|
.protocols(protocols())
|
||||||
|
.ciphers(ciphers())
|
||||||
.build();
|
.build();
|
||||||
SSLEngine clientEngine = null;
|
SSLEngine clientEngine = null;
|
||||||
try {
|
try {
|
||||||
@ -416,11 +440,15 @@ public class OpenSslEngineTest extends SSLEngineTest {
|
|||||||
SelfSignedCertificate ssc = new SelfSignedCertificate();
|
SelfSignedCertificate ssc = new SelfSignedCertificate();
|
||||||
serverSslCtx = SslContextBuilder.forServer(ssc.certificate(), ssc.privateKey())
|
serverSslCtx = SslContextBuilder.forServer(ssc.certificate(), ssc.privateKey())
|
||||||
.sslProvider(sslServerProvider())
|
.sslProvider(sslServerProvider())
|
||||||
|
.protocols(protocols())
|
||||||
|
.ciphers(ciphers())
|
||||||
.build();
|
.build();
|
||||||
|
|
||||||
clientSslCtx = SslContextBuilder.forClient()
|
clientSslCtx = SslContextBuilder.forClient()
|
||||||
.trustManager(InsecureTrustManagerFactory.INSTANCE)
|
.trustManager(InsecureTrustManagerFactory.INSTANCE)
|
||||||
.sslProvider(sslClientProvider())
|
.sslProvider(sslClientProvider())
|
||||||
|
.protocols(protocols())
|
||||||
|
.ciphers(ciphers())
|
||||||
.build();
|
.build();
|
||||||
SSLEngine clientEngine = null;
|
SSLEngine clientEngine = null;
|
||||||
SSLEngine serverEngine = null;
|
SSLEngine serverEngine = null;
|
||||||
@ -613,12 +641,16 @@ public class OpenSslEngineTest extends SSLEngineTest {
|
|||||||
.forClient()
|
.forClient()
|
||||||
.trustManager(cert.cert())
|
.trustManager(cert.cert())
|
||||||
.sslProvider(sslClientProvider())
|
.sslProvider(sslClientProvider())
|
||||||
|
.protocols(protocols())
|
||||||
|
.ciphers(ciphers())
|
||||||
.build();
|
.build();
|
||||||
SSLEngine client = wrapEngine(clientSslCtx.newHandler(UnpooledByteBufAllocator.DEFAULT).engine());
|
SSLEngine client = wrapEngine(clientSslCtx.newHandler(UnpooledByteBufAllocator.DEFAULT).engine());
|
||||||
|
|
||||||
serverSslCtx = SslContextBuilder
|
serverSslCtx = SslContextBuilder
|
||||||
.forServer(cert.certificate(), cert.privateKey())
|
.forServer(cert.certificate(), cert.privateKey())
|
||||||
.sslProvider(sslServerProvider())
|
.sslProvider(sslServerProvider())
|
||||||
|
.protocols(protocols())
|
||||||
|
.ciphers(ciphers())
|
||||||
.build();
|
.build();
|
||||||
SSLEngine server = wrapEngine(serverSslCtx.newHandler(UnpooledByteBufAllocator.DEFAULT).engine());
|
SSLEngine server = wrapEngine(serverSslCtx.newHandler(UnpooledByteBufAllocator.DEFAULT).engine());
|
||||||
|
|
||||||
@ -690,12 +722,16 @@ public class OpenSslEngineTest extends SSLEngineTest {
|
|||||||
.forClient()
|
.forClient()
|
||||||
.trustManager(cert.cert())
|
.trustManager(cert.cert())
|
||||||
.sslProvider(sslClientProvider())
|
.sslProvider(sslClientProvider())
|
||||||
|
.protocols(protocols())
|
||||||
|
.ciphers(ciphers())
|
||||||
.build();
|
.build();
|
||||||
SSLEngine client = wrapEngine(clientSslCtx.newHandler(UnpooledByteBufAllocator.DEFAULT).engine());
|
SSLEngine client = wrapEngine(clientSslCtx.newHandler(UnpooledByteBufAllocator.DEFAULT).engine());
|
||||||
|
|
||||||
serverSslCtx = SslContextBuilder
|
serverSslCtx = SslContextBuilder
|
||||||
.forServer(cert.certificate(), cert.privateKey())
|
.forServer(cert.certificate(), cert.privateKey())
|
||||||
.sslProvider(sslServerProvider())
|
.sslProvider(sslServerProvider())
|
||||||
|
.protocols(protocols())
|
||||||
|
.ciphers(ciphers())
|
||||||
.build();
|
.build();
|
||||||
SSLEngine server = wrapEngine(serverSslCtx.newHandler(UnpooledByteBufAllocator.DEFAULT).engine());
|
SSLEngine server = wrapEngine(serverSslCtx.newHandler(UnpooledByteBufAllocator.DEFAULT).engine());
|
||||||
|
|
||||||
@ -774,12 +810,16 @@ public class OpenSslEngineTest extends SSLEngineTest {
|
|||||||
.forClient()
|
.forClient()
|
||||||
.trustManager(cert.cert())
|
.trustManager(cert.cert())
|
||||||
.sslProvider(sslClientProvider())
|
.sslProvider(sslClientProvider())
|
||||||
|
.protocols(protocols())
|
||||||
|
.ciphers(ciphers())
|
||||||
.build();
|
.build();
|
||||||
SSLEngine client = wrapEngine(clientSslCtx.newHandler(UnpooledByteBufAllocator.DEFAULT).engine());
|
SSLEngine client = wrapEngine(clientSslCtx.newHandler(UnpooledByteBufAllocator.DEFAULT).engine());
|
||||||
|
|
||||||
serverSslCtx = SslContextBuilder
|
serverSslCtx = SslContextBuilder
|
||||||
.forServer(cert.certificate(), cert.privateKey())
|
.forServer(cert.certificate(), cert.privateKey())
|
||||||
.sslProvider(sslServerProvider())
|
.sslProvider(sslServerProvider())
|
||||||
|
.protocols(protocols())
|
||||||
|
.ciphers(ciphers())
|
||||||
.build();
|
.build();
|
||||||
SSLEngine server = wrapEngine(serverSslCtx.newHandler(UnpooledByteBufAllocator.DEFAULT).engine());
|
SSLEngine server = wrapEngine(serverSslCtx.newHandler(UnpooledByteBufAllocator.DEFAULT).engine());
|
||||||
|
|
||||||
@ -849,12 +889,16 @@ public class OpenSslEngineTest extends SSLEngineTest {
|
|||||||
.forClient()
|
.forClient()
|
||||||
.trustManager(cert.cert())
|
.trustManager(cert.cert())
|
||||||
.sslProvider(sslClientProvider())
|
.sslProvider(sslClientProvider())
|
||||||
|
.protocols(protocols())
|
||||||
|
.ciphers(ciphers())
|
||||||
.build();
|
.build();
|
||||||
SSLEngine client = wrapEngine(clientSslCtx.newHandler(UnpooledByteBufAllocator.DEFAULT).engine());
|
SSLEngine client = wrapEngine(clientSslCtx.newHandler(UnpooledByteBufAllocator.DEFAULT).engine());
|
||||||
|
|
||||||
serverSslCtx = SslContextBuilder
|
serverSslCtx = SslContextBuilder
|
||||||
.forServer(cert.certificate(), cert.privateKey())
|
.forServer(cert.certificate(), cert.privateKey())
|
||||||
.sslProvider(sslServerProvider())
|
.sslProvider(sslServerProvider())
|
||||||
|
.protocols(protocols())
|
||||||
|
.ciphers(ciphers())
|
||||||
.build();
|
.build();
|
||||||
SSLEngine server = wrapEngine(serverSslCtx.newHandler(UnpooledByteBufAllocator.DEFAULT).engine());
|
SSLEngine server = wrapEngine(serverSslCtx.newHandler(UnpooledByteBufAllocator.DEFAULT).engine());
|
||||||
|
|
||||||
@ -983,6 +1027,8 @@ public class OpenSslEngineTest extends SSLEngineTest {
|
|||||||
SelfSignedCertificate ssc = new SelfSignedCertificate();
|
SelfSignedCertificate ssc = new SelfSignedCertificate();
|
||||||
serverSslCtx = SslContextBuilder.forServer(ssc.certificate(), ssc.privateKey())
|
serverSslCtx = SslContextBuilder.forServer(ssc.certificate(), ssc.privateKey())
|
||||||
.sslProvider(sslServerProvider())
|
.sslProvider(sslServerProvider())
|
||||||
|
.protocols(protocols())
|
||||||
|
.ciphers(ciphers())
|
||||||
.build();
|
.build();
|
||||||
|
|
||||||
SSLEngine engine = wrapEngine(serverSslCtx.newEngine(UnpooledByteBufAllocator.DEFAULT));
|
SSLEngine engine = wrapEngine(serverSslCtx.newEngine(UnpooledByteBufAllocator.DEFAULT));
|
||||||
@ -1003,6 +1049,8 @@ public class OpenSslEngineTest extends SSLEngineTest {
|
|||||||
SelfSignedCertificate ssc = new SelfSignedCertificate();
|
SelfSignedCertificate ssc = new SelfSignedCertificate();
|
||||||
serverSslCtx = SslContextBuilder.forServer(ssc.certificate(), ssc.privateKey())
|
serverSslCtx = SslContextBuilder.forServer(ssc.certificate(), ssc.privateKey())
|
||||||
.sslProvider(sslServerProvider())
|
.sslProvider(sslServerProvider())
|
||||||
|
.protocols(protocols())
|
||||||
|
.ciphers(ciphers())
|
||||||
.build();
|
.build();
|
||||||
|
|
||||||
SSLEngine engine = wrapEngine(serverSslCtx.newEngine(UnpooledByteBufAllocator.DEFAULT));
|
SSLEngine engine = wrapEngine(serverSslCtx.newEngine(UnpooledByteBufAllocator.DEFAULT));
|
||||||
@ -1023,6 +1071,8 @@ public class OpenSslEngineTest extends SSLEngineTest {
|
|||||||
SelfSignedCertificate ssc = new SelfSignedCertificate();
|
SelfSignedCertificate ssc = new SelfSignedCertificate();
|
||||||
serverSslCtx = SslContextBuilder.forServer(ssc.certificate(), ssc.privateKey())
|
serverSslCtx = SslContextBuilder.forServer(ssc.certificate(), ssc.privateKey())
|
||||||
.sslProvider(sslServerProvider())
|
.sslProvider(sslServerProvider())
|
||||||
|
.protocols(protocols())
|
||||||
|
.ciphers(ciphers())
|
||||||
.build();
|
.build();
|
||||||
|
|
||||||
SSLEngine engine = wrapEngine(serverSslCtx.newEngine(UnpooledByteBufAllocator.DEFAULT));
|
SSLEngine engine = wrapEngine(serverSslCtx.newEngine(UnpooledByteBufAllocator.DEFAULT));
|
||||||
|
@ -15,6 +15,7 @@
|
|||||||
*/
|
*/
|
||||||
package io.netty.handler.ssl;
|
package io.netty.handler.ssl;
|
||||||
|
|
||||||
|
import io.netty.util.internal.PlatformDependent;
|
||||||
import org.junit.BeforeClass;
|
import org.junit.BeforeClass;
|
||||||
import org.junit.Ignore;
|
import org.junit.Ignore;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
@ -34,17 +35,21 @@ import static org.junit.Assume.assumeTrue;
|
|||||||
@RunWith(Parameterized.class)
|
@RunWith(Parameterized.class)
|
||||||
public class OpenSslJdkSslEngineInteroptTest extends SSLEngineTest {
|
public class OpenSslJdkSslEngineInteroptTest extends SSLEngineTest {
|
||||||
|
|
||||||
@Parameterized.Parameters(name = "{index}: bufferType = {0}")
|
@Parameterized.Parameters(name = "{index}: bufferType = {0}, combo = {1}")
|
||||||
public static Collection<Object> data() {
|
public static Collection<Object[]> data() {
|
||||||
List<Object> params = new ArrayList<Object>();
|
List<Object[]> params = new ArrayList<Object[]>();
|
||||||
for (BufferType type: BufferType.values()) {
|
for (BufferType type: BufferType.values()) {
|
||||||
params.add(type);
|
params.add(new Object[] { type, ProtocolCipherCombo.tlsv12()});
|
||||||
|
|
||||||
|
if (PlatformDependent.javaVersion() >= 11 && OpenSsl.isTlsv13Supported()) {
|
||||||
|
params.add(new Object[] { type, ProtocolCipherCombo.tlsv13() });
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return params;
|
return params;
|
||||||
}
|
}
|
||||||
|
|
||||||
public OpenSslJdkSslEngineInteroptTest(BufferType type) {
|
public OpenSslJdkSslEngineInteroptTest(BufferType type, ProtocolCipherCombo combo) {
|
||||||
super(type);
|
super(type, combo);
|
||||||
}
|
}
|
||||||
|
|
||||||
@BeforeClass
|
@BeforeClass
|
||||||
|
@ -15,6 +15,12 @@
|
|||||||
*/
|
*/
|
||||||
package io.netty.handler.ssl;
|
package io.netty.handler.ssl;
|
||||||
|
|
||||||
|
import io.netty.util.internal.PlatformDependent;
|
||||||
|
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.Collections;
|
||||||
|
|
||||||
|
import static io.netty.handler.ssl.SslUtils.PROTOCOL_TLS_V1_2;
|
||||||
import static org.junit.Assume.assumeTrue;
|
import static org.junit.Assume.assumeTrue;
|
||||||
|
|
||||||
final class OpenSslTestUtils {
|
final class OpenSslTestUtils {
|
||||||
@ -28,4 +34,17 @@ final class OpenSslTestUtils {
|
|||||||
static boolean isBoringSSL() {
|
static boolean isBoringSSL() {
|
||||||
return "BoringSSL".equals(OpenSsl.versionString());
|
return "BoringSSL".equals(OpenSsl.versionString());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static SslContextBuilder configureProtocolForMutualAuth(
|
||||||
|
SslContextBuilder ctx, SslProvider sslClientProvider, SslProvider sslServerProvider) {
|
||||||
|
if (PlatformDependent.javaVersion() >= 11
|
||||||
|
&& sslClientProvider == SslProvider.JDK && sslServerProvider != SslProvider.JDK) {
|
||||||
|
// Make sure we do not use TLSv1.3 as there seems to be a bug currently in the JDK TLSv1.3 implementation.
|
||||||
|
// See:
|
||||||
|
// - http://mail.openjdk.java.net/pipermail/security-dev/2018-September/018191.html
|
||||||
|
// - https://bugs.openjdk.java.net/projects/JDK/issues/JDK-8210846
|
||||||
|
ctx.protocols(PROTOCOL_TLS_V1_2).ciphers(Collections.singleton("TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256"));
|
||||||
|
}
|
||||||
|
return ctx;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -382,11 +382,20 @@ public class ParameterizedSslHandlerTest {
|
|||||||
|
|
||||||
final SslContext sslServerCtx = SslContextBuilder.forServer(ssc.certificate(), ssc.privateKey())
|
final SslContext sslServerCtx = SslContextBuilder.forServer(ssc.certificate(), ssc.privateKey())
|
||||||
.sslProvider(serverProvider)
|
.sslProvider(serverProvider)
|
||||||
|
// Use TLSv1.2 as we depend on the fact that the handshake
|
||||||
|
// is done in an extra round trip in the test which
|
||||||
|
// is not true in TLSv1.3
|
||||||
|
.protocols(SslUtils.PROTOCOL_TLS_V1_2)
|
||||||
.build();
|
.build();
|
||||||
|
|
||||||
final SslContext sslClientCtx = SslContextBuilder.forClient()
|
final SslContext sslClientCtx = SslContextBuilder.forClient()
|
||||||
.trustManager(InsecureTrustManagerFactory.INSTANCE)
|
.trustManager(InsecureTrustManagerFactory.INSTANCE)
|
||||||
.sslProvider(clientProvider).build();
|
.sslProvider(clientProvider)
|
||||||
|
// Use TLSv1.2 as we depend on the fact that the handshake
|
||||||
|
// is done in an extra round trip in the test which
|
||||||
|
// is not true in TLSv1.3
|
||||||
|
.protocols(SslUtils.PROTOCOL_TLS_V1_2)
|
||||||
|
.build();
|
||||||
|
|
||||||
EventLoopGroup group = new NioEventLoopGroup();
|
EventLoopGroup group = new NioEventLoopGroup();
|
||||||
Channel sc = null;
|
Channel sc = null;
|
||||||
|
@ -23,8 +23,8 @@ import javax.net.ssl.SSLEngine;
|
|||||||
|
|
||||||
public class ReferenceCountedOpenSslEngineTest extends OpenSslEngineTest {
|
public class ReferenceCountedOpenSslEngineTest extends OpenSslEngineTest {
|
||||||
|
|
||||||
public ReferenceCountedOpenSslEngineTest(BufferType type) {
|
public ReferenceCountedOpenSslEngineTest(BufferType type, ProtocolCipherCombo combo) {
|
||||||
super(type);
|
super(type, combo);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -62,6 +62,8 @@ public class ReferenceCountedOpenSslEngineTest extends OpenSslEngineTest {
|
|||||||
clientSslCtx = SslContextBuilder.forClient()
|
clientSslCtx = SslContextBuilder.forClient()
|
||||||
.trustManager(InsecureTrustManagerFactory.INSTANCE)
|
.trustManager(InsecureTrustManagerFactory.INSTANCE)
|
||||||
.sslProvider(sslClientProvider())
|
.sslProvider(sslClientProvider())
|
||||||
|
.protocols(protocols())
|
||||||
|
.ciphers(ciphers())
|
||||||
.build();
|
.build();
|
||||||
|
|
||||||
clientSslCtx.newEngine(null);
|
clientSslCtx.newEngine(null);
|
||||||
|
@ -33,6 +33,7 @@ import io.netty.channel.nio.NioEventLoopGroup;
|
|||||||
import io.netty.channel.socket.SocketChannel;
|
import io.netty.channel.socket.SocketChannel;
|
||||||
import io.netty.channel.socket.nio.NioServerSocketChannel;
|
import io.netty.channel.socket.nio.NioServerSocketChannel;
|
||||||
import io.netty.channel.socket.nio.NioSocketChannel;
|
import io.netty.channel.socket.nio.NioSocketChannel;
|
||||||
|
import io.netty.handler.ssl.ApplicationProtocolConfig.Protocol;
|
||||||
import io.netty.handler.ssl.util.InsecureTrustManagerFactory;
|
import io.netty.handler.ssl.util.InsecureTrustManagerFactory;
|
||||||
import io.netty.handler.ssl.util.SelfSignedCertificate;
|
import io.netty.handler.ssl.util.SelfSignedCertificate;
|
||||||
import io.netty.handler.ssl.util.SimpleTrustManagerFactory;
|
import io.netty.handler.ssl.util.SimpleTrustManagerFactory;
|
||||||
@ -67,6 +68,7 @@ import java.security.Provider;
|
|||||||
import java.security.cert.Certificate;
|
import java.security.cert.Certificate;
|
||||||
import java.security.cert.CertificateException;
|
import java.security.cert.CertificateException;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
|
import java.util.Collections;
|
||||||
import java.util.HashSet;
|
import java.util.HashSet;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
@ -79,6 +81,7 @@ import javax.net.ssl.ManagerFactoryParameters;
|
|||||||
import javax.net.ssl.SNIHostName;
|
import javax.net.ssl.SNIHostName;
|
||||||
import javax.net.ssl.SSLEngine;
|
import javax.net.ssl.SSLEngine;
|
||||||
import javax.net.ssl.SSLEngineResult;
|
import javax.net.ssl.SSLEngineResult;
|
||||||
|
import javax.net.ssl.SSLEngineResult.Status;
|
||||||
import javax.net.ssl.SSLException;
|
import javax.net.ssl.SSLException;
|
||||||
import javax.net.ssl.SSLHandshakeException;
|
import javax.net.ssl.SSLHandshakeException;
|
||||||
import javax.net.ssl.SSLParameters;
|
import javax.net.ssl.SSLParameters;
|
||||||
@ -89,14 +92,7 @@ import javax.net.ssl.TrustManagerFactorySpi;
|
|||||||
import javax.net.ssl.X509TrustManager;
|
import javax.net.ssl.X509TrustManager;
|
||||||
import javax.security.cert.X509Certificate;
|
import javax.security.cert.X509Certificate;
|
||||||
|
|
||||||
import static io.netty.handler.ssl.SslUtils.PROTOCOL_SSL_V2;
|
import static io.netty.handler.ssl.SslUtils.*;
|
||||||
import static io.netty.handler.ssl.SslUtils.PROTOCOL_SSL_V2_HELLO;
|
|
||||||
import static io.netty.handler.ssl.SslUtils.PROTOCOL_SSL_V3;
|
|
||||||
import static io.netty.handler.ssl.SslUtils.PROTOCOL_TLS_V1;
|
|
||||||
import static io.netty.handler.ssl.SslUtils.PROTOCOL_TLS_V1_1;
|
|
||||||
import static io.netty.handler.ssl.SslUtils.PROTOCOL_TLS_V1_2;
|
|
||||||
import static io.netty.handler.ssl.SslUtils.SSL_RECORD_HEADER_LENGTH;
|
|
||||||
|
|
||||||
import static org.junit.Assert.assertArrayEquals;
|
import static org.junit.Assert.assertArrayEquals;
|
||||||
import static org.junit.Assert.assertEquals;
|
import static org.junit.Assert.assertEquals;
|
||||||
import static org.junit.Assert.assertFalse;
|
import static org.junit.Assert.assertFalse;
|
||||||
@ -220,10 +216,42 @@ public abstract class SSLEngineTest {
|
|||||||
Mixed
|
Mixed
|
||||||
}
|
}
|
||||||
|
|
||||||
private final BufferType type;
|
static final class ProtocolCipherCombo {
|
||||||
|
private static final ProtocolCipherCombo TLSV12 = new ProtocolCipherCombo(
|
||||||
|
PROTOCOL_TLS_V1_2, "TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256");
|
||||||
|
private static final ProtocolCipherCombo TLSV13 = new ProtocolCipherCombo(
|
||||||
|
PROTOCOL_TLS_V1_3, "TLS_AES_128_GCM_SHA256");
|
||||||
|
final String protocol;
|
||||||
|
final String cipher;
|
||||||
|
|
||||||
protected SSLEngineTest(BufferType type) {
|
private ProtocolCipherCombo(String protocol, String cipher) {
|
||||||
|
this.protocol = protocol;
|
||||||
|
this.cipher = cipher;
|
||||||
|
}
|
||||||
|
|
||||||
|
static ProtocolCipherCombo tlsv12() {
|
||||||
|
return TLSV12;
|
||||||
|
}
|
||||||
|
|
||||||
|
static ProtocolCipherCombo tlsv13() {
|
||||||
|
return TLSV13;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return "ProtocolCipherCombo{" +
|
||||||
|
"protocol='" + protocol + '\'' +
|
||||||
|
", cipher='" + cipher + '\'' +
|
||||||
|
'}';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private final BufferType type;
|
||||||
|
private final ProtocolCipherCombo protocolCipherCombo;
|
||||||
|
|
||||||
|
protected SSLEngineTest(BufferType type, ProtocolCipherCombo protocolCipherCombo) {
|
||||||
this.type = type;
|
this.type = type;
|
||||||
|
this.protocolCipherCombo = protocolCipherCombo;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected ByteBuffer allocateBuffer(int len) {
|
protected ByteBuffer allocateBuffer(int len) {
|
||||||
@ -620,36 +648,46 @@ public abstract class SSLEngineTest {
|
|||||||
}
|
}
|
||||||
|
|
||||||
protected boolean mySetupMutualAuthServerIsValidException(Throwable cause) {
|
protected boolean mySetupMutualAuthServerIsValidException(Throwable cause) {
|
||||||
return cause instanceof SSLHandshakeException || cause instanceof ClosedChannelException;
|
// As in TLSv1.3 the handshake is sent without an extra roundtrip an SSLException is valid as well.
|
||||||
|
return cause instanceof SSLException || cause instanceof ClosedChannelException;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void mySetupMutualAuthServerInitSslHandler(SslHandler handler) {
|
protected void mySetupMutualAuthServerInitSslHandler(SslHandler handler) {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private SslContextBuilder configureProtocolForMutualAuth(SslContextBuilder ctx) {
|
||||||
|
return OpenSslTestUtils.configureProtocolForMutualAuth(ctx, sslClientProvider(), sslServerProvider());
|
||||||
|
}
|
||||||
|
|
||||||
private void mySetupMutualAuth(KeyManagerFactory serverKMF, final File serverTrustManager,
|
private void mySetupMutualAuth(KeyManagerFactory serverKMF, final File serverTrustManager,
|
||||||
KeyManagerFactory clientKMF, File clientTrustManager,
|
KeyManagerFactory clientKMF, File clientTrustManager,
|
||||||
ClientAuth clientAuth, final boolean failureExpected,
|
ClientAuth clientAuth, final boolean failureExpected,
|
||||||
final boolean serverInitEngine)
|
final boolean serverInitEngine)
|
||||||
throws SSLException, InterruptedException {
|
throws SSLException, InterruptedException {
|
||||||
serverSslCtx = SslContextBuilder.forServer(serverKMF)
|
serverSslCtx = configureProtocolForMutualAuth(
|
||||||
|
SslContextBuilder.forServer(serverKMF)
|
||||||
|
.protocols(protocols())
|
||||||
|
.ciphers(ciphers())
|
||||||
.sslProvider(sslServerProvider())
|
.sslProvider(sslServerProvider())
|
||||||
.sslContextProvider(serverSslContextProvider())
|
.sslContextProvider(serverSslContextProvider())
|
||||||
.trustManager(serverTrustManager)
|
.trustManager(serverTrustManager)
|
||||||
.clientAuth(clientAuth)
|
.clientAuth(clientAuth)
|
||||||
.ciphers(null, IdentityCipherSuiteFilter.INSTANCE)
|
.ciphers(null, IdentityCipherSuiteFilter.INSTANCE)
|
||||||
.sessionCacheSize(0)
|
.sessionCacheSize(0)
|
||||||
.sessionTimeout(0)
|
.sessionTimeout(0)).build();
|
||||||
.build();
|
|
||||||
|
|
||||||
clientSslCtx = SslContextBuilder.forClient()
|
clientSslCtx = configureProtocolForMutualAuth(
|
||||||
|
SslContextBuilder.forClient()
|
||||||
|
.protocols(protocols())
|
||||||
|
.ciphers(ciphers())
|
||||||
.sslProvider(sslClientProvider())
|
.sslProvider(sslClientProvider())
|
||||||
.sslContextProvider(clientSslContextProvider())
|
.sslContextProvider(clientSslContextProvider())
|
||||||
.trustManager(clientTrustManager)
|
.trustManager(clientTrustManager)
|
||||||
.keyManager(clientKMF)
|
.keyManager(clientKMF)
|
||||||
.ciphers(null, IdentityCipherSuiteFilter.INSTANCE)
|
.ciphers(null, IdentityCipherSuiteFilter.INSTANCE)
|
||||||
.sessionCacheSize(0)
|
.sessionCacheSize(0)
|
||||||
.sessionTimeout(0)
|
.sessionTimeout(0)).build();
|
||||||
.build();
|
|
||||||
serverConnectedChannel = null;
|
serverConnectedChannel = null;
|
||||||
sb = new ServerBootstrap();
|
sb = new ServerBootstrap();
|
||||||
cb = new Bootstrap();
|
cb = new Bootstrap();
|
||||||
@ -711,10 +749,11 @@ public abstract class SSLEngineTest {
|
|||||||
@Override
|
@Override
|
||||||
public void userEventTriggered(ChannelHandlerContext ctx, Object evt) throws Exception {
|
public void userEventTriggered(ChannelHandlerContext ctx, Object evt) throws Exception {
|
||||||
if (evt == SslHandshakeCompletionEvent.SUCCESS) {
|
if (evt == SslHandshakeCompletionEvent.SUCCESS) {
|
||||||
if (failureExpected) {
|
// With TLS1.3 a mutal auth error will not be propagated as a handshake error most of the
|
||||||
clientException = new IllegalStateException("handshake complete. expected failure");
|
// time as the handshake needs NO extra roundtrip.
|
||||||
}
|
if (!failureExpected) {
|
||||||
clientLatch.countDown();
|
clientLatch.countDown();
|
||||||
|
}
|
||||||
} else if (evt instanceof SslHandshakeCompletionEvent) {
|
} else if (evt instanceof SslHandshakeCompletionEvent) {
|
||||||
clientException = ((SslHandshakeCompletionEvent) evt).cause();
|
clientException = ((SslHandshakeCompletionEvent) evt).cause();
|
||||||
clientLatch.countDown();
|
clientLatch.countDown();
|
||||||
@ -724,7 +763,7 @@ public abstract class SSLEngineTest {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
|
public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
|
||||||
if (cause.getCause() instanceof SSLHandshakeException) {
|
if (cause.getCause() instanceof SSLException) {
|
||||||
clientException = cause.getCause();
|
clientException = cause.getCause();
|
||||||
clientLatch.countDown();
|
clientLatch.countDown();
|
||||||
} else {
|
} else {
|
||||||
@ -735,7 +774,7 @@ public abstract class SSLEngineTest {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
serverChannel = sb.bind(new InetSocketAddress(0)).sync().channel();
|
serverChannel = sb.bind(new InetSocketAddress(8443)).sync().channel();
|
||||||
int port = ((InetSocketAddress) serverChannel.localAddress()).getPort();
|
int port = ((InetSocketAddress) serverChannel.localAddress()).getPort();
|
||||||
|
|
||||||
ChannelFuture ccf = cb.connect(new InetSocketAddress(NetUtil.LOCALHOST, port));
|
ChannelFuture ccf = cb.connect(new InetSocketAddress(NetUtil.LOCALHOST, port));
|
||||||
@ -776,6 +815,8 @@ public abstract class SSLEngineTest {
|
|||||||
final String expectedHost = "localhost";
|
final String expectedHost = "localhost";
|
||||||
serverSslCtx = SslContextBuilder.forServer(serverCrtFile, serverKeyFile, null)
|
serverSslCtx = SslContextBuilder.forServer(serverCrtFile, serverKeyFile, null)
|
||||||
.sslProvider(sslServerProvider())
|
.sslProvider(sslServerProvider())
|
||||||
|
.protocols(protocols())
|
||||||
|
.ciphers(ciphers())
|
||||||
.sslContextProvider(serverSslContextProvider())
|
.sslContextProvider(serverSslContextProvider())
|
||||||
.trustManager(InsecureTrustManagerFactory.INSTANCE)
|
.trustManager(InsecureTrustManagerFactory.INSTANCE)
|
||||||
.ciphers(null, IdentityCipherSuiteFilter.INSTANCE)
|
.ciphers(null, IdentityCipherSuiteFilter.INSTANCE)
|
||||||
@ -785,12 +826,15 @@ public abstract class SSLEngineTest {
|
|||||||
|
|
||||||
clientSslCtx = SslContextBuilder.forClient()
|
clientSslCtx = SslContextBuilder.forClient()
|
||||||
.sslProvider(sslClientProvider())
|
.sslProvider(sslClientProvider())
|
||||||
|
.protocols(protocols())
|
||||||
|
.ciphers(ciphers())
|
||||||
.sslContextProvider(clientSslContextProvider())
|
.sslContextProvider(clientSslContextProvider())
|
||||||
.trustManager(clientTrustCrtFile)
|
.trustManager(clientTrustCrtFile)
|
||||||
.ciphers(null, IdentityCipherSuiteFilter.INSTANCE)
|
.ciphers(null, IdentityCipherSuiteFilter.INSTANCE)
|
||||||
.sessionCacheSize(0)
|
.sessionCacheSize(0)
|
||||||
.sessionTimeout(0)
|
.sessionTimeout(0)
|
||||||
.build();
|
.build();
|
||||||
|
|
||||||
serverConnectedChannel = null;
|
serverConnectedChannel = null;
|
||||||
sb = new ServerBootstrap();
|
sb = new ServerBootstrap();
|
||||||
cb = new Bootstrap();
|
cb = new Bootstrap();
|
||||||
@ -897,24 +941,28 @@ public abstract class SSLEngineTest {
|
|||||||
File servertTrustCrtFile, File serverKeyFile, final File serverCrtFile, String serverKeyPassword,
|
File servertTrustCrtFile, File serverKeyFile, final File serverCrtFile, String serverKeyPassword,
|
||||||
File clientTrustCrtFile, File clientKeyFile, File clientCrtFile, String clientKeyPassword)
|
File clientTrustCrtFile, File clientKeyFile, File clientCrtFile, String clientKeyPassword)
|
||||||
throws InterruptedException, SSLException {
|
throws InterruptedException, SSLException {
|
||||||
serverSslCtx = SslContextBuilder.forServer(serverCrtFile, serverKeyFile, serverKeyPassword)
|
serverSslCtx = configureProtocolForMutualAuth(
|
||||||
|
SslContextBuilder.forServer(serverCrtFile, serverKeyFile, serverKeyPassword)
|
||||||
.sslProvider(sslServerProvider())
|
.sslProvider(sslServerProvider())
|
||||||
.sslContextProvider(serverSslContextProvider())
|
.sslContextProvider(serverSslContextProvider())
|
||||||
|
.protocols(protocols())
|
||||||
|
.ciphers(ciphers())
|
||||||
.trustManager(servertTrustCrtFile)
|
.trustManager(servertTrustCrtFile)
|
||||||
.ciphers(null, IdentityCipherSuiteFilter.INSTANCE)
|
.ciphers(null, IdentityCipherSuiteFilter.INSTANCE)
|
||||||
.sessionCacheSize(0)
|
.sessionCacheSize(0)
|
||||||
.sessionTimeout(0)
|
.sessionTimeout(0)).build();
|
||||||
.build();
|
clientSslCtx = configureProtocolForMutualAuth(
|
||||||
|
SslContextBuilder.forClient()
|
||||||
clientSslCtx = SslContextBuilder.forClient()
|
|
||||||
.sslProvider(sslClientProvider())
|
.sslProvider(sslClientProvider())
|
||||||
.sslContextProvider(clientSslContextProvider())
|
.sslContextProvider(clientSslContextProvider())
|
||||||
|
.protocols(protocols())
|
||||||
|
.ciphers(ciphers())
|
||||||
.trustManager(clientTrustCrtFile)
|
.trustManager(clientTrustCrtFile)
|
||||||
.keyManager(clientCrtFile, clientKeyFile, clientKeyPassword)
|
.keyManager(clientCrtFile, clientKeyFile, clientKeyPassword)
|
||||||
.ciphers(null, IdentityCipherSuiteFilter.INSTANCE)
|
.ciphers(null, IdentityCipherSuiteFilter.INSTANCE)
|
||||||
.sessionCacheSize(0)
|
.sessionCacheSize(0)
|
||||||
.sessionTimeout(0)
|
.sessionTimeout(0)).build();
|
||||||
.build();
|
|
||||||
serverConnectedChannel = null;
|
serverConnectedChannel = null;
|
||||||
sb = new ServerBootstrap();
|
sb = new ServerBootstrap();
|
||||||
cb = new Bootstrap();
|
cb = new Bootstrap();
|
||||||
@ -930,6 +978,7 @@ public abstract class SSLEngineTest {
|
|||||||
SSLEngine engine = serverSslCtx.newEngine(ch.alloc());
|
SSLEngine engine = serverSslCtx.newEngine(ch.alloc());
|
||||||
engine.setUseClientMode(false);
|
engine.setUseClientMode(false);
|
||||||
engine.setNeedClientAuth(true);
|
engine.setNeedClientAuth(true);
|
||||||
|
|
||||||
p.addLast(new SslHandler(engine));
|
p.addLast(new SslHandler(engine));
|
||||||
p.addLast(new MessageDelegatorChannelHandler(serverReceiver, serverLatch));
|
p.addLast(new MessageDelegatorChannelHandler(serverReceiver, serverLatch));
|
||||||
p.addLast(new ChannelInboundHandlerAdapter() {
|
p.addLast(new ChannelInboundHandlerAdapter() {
|
||||||
@ -986,13 +1035,14 @@ public abstract class SSLEngineTest {
|
|||||||
protected void initChannel(Channel ch) throws Exception {
|
protected void initChannel(Channel ch) throws Exception {
|
||||||
ch.config().setAllocator(new TestByteBufAllocator(ch.config().getAllocator(), type));
|
ch.config().setAllocator(new TestByteBufAllocator(ch.config().getAllocator(), type));
|
||||||
|
|
||||||
|
SslHandler handler = clientSslCtx.newHandler(ch.alloc());
|
||||||
|
handler.engine().setNeedClientAuth(true);
|
||||||
ChannelPipeline p = ch.pipeline();
|
ChannelPipeline p = ch.pipeline();
|
||||||
p.addLast(clientSslCtx.newHandler(ch.alloc()));
|
p.addLast(handler);
|
||||||
p.addLast(new MessageDelegatorChannelHandler(clientReceiver, clientLatch));
|
p.addLast(new MessageDelegatorChannelHandler(clientReceiver, clientLatch));
|
||||||
p.addLast(new ChannelInboundHandlerAdapter() {
|
p.addLast(new ChannelInboundHandlerAdapter() {
|
||||||
@Override
|
@Override
|
||||||
public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
|
public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
|
||||||
cause.printStackTrace();
|
|
||||||
if (cause.getCause() instanceof SSLHandshakeException) {
|
if (cause.getCause() instanceof SSLHandshakeException) {
|
||||||
clientException = cause.getCause();
|
clientException = cause.getCause();
|
||||||
clientLatch.countDown();
|
clientLatch.countDown();
|
||||||
@ -1081,11 +1131,15 @@ public abstract class SSLEngineTest {
|
|||||||
.trustManager(InsecureTrustManagerFactory.INSTANCE)
|
.trustManager(InsecureTrustManagerFactory.INSTANCE)
|
||||||
.sslProvider(sslClientProvider())
|
.sslProvider(sslClientProvider())
|
||||||
.sslContextProvider(clientSslContextProvider())
|
.sslContextProvider(clientSslContextProvider())
|
||||||
|
.protocols(protocols())
|
||||||
|
.ciphers(ciphers())
|
||||||
.build();
|
.build();
|
||||||
SelfSignedCertificate ssc = new SelfSignedCertificate();
|
SelfSignedCertificate ssc = new SelfSignedCertificate();
|
||||||
serverSslCtx = SslContextBuilder.forServer(ssc.certificate(), ssc.privateKey())
|
serverSslCtx = SslContextBuilder.forServer(ssc.certificate(), ssc.privateKey())
|
||||||
.sslProvider(sslServerProvider())
|
.sslProvider(sslServerProvider())
|
||||||
.sslContextProvider(serverSslContextProvider())
|
.sslContextProvider(serverSslContextProvider())
|
||||||
|
.protocols(protocols())
|
||||||
|
.ciphers(ciphers())
|
||||||
.build();
|
.build();
|
||||||
SSLEngine clientEngine = null;
|
SSLEngine clientEngine = null;
|
||||||
SSLEngine serverEngine = null;
|
SSLEngine serverEngine = null;
|
||||||
@ -1110,11 +1164,15 @@ public abstract class SSLEngineTest {
|
|||||||
clientSslCtx = SslContextBuilder.forClient()
|
clientSslCtx = SslContextBuilder.forClient()
|
||||||
.trustManager(InsecureTrustManagerFactory.INSTANCE)
|
.trustManager(InsecureTrustManagerFactory.INSTANCE)
|
||||||
.sslProvider(sslClientProvider())
|
.sslProvider(sslClientProvider())
|
||||||
|
// This test only works for non TLSv1.3 for now
|
||||||
|
.protocols(PROTOCOL_TLS_V1_2)
|
||||||
.sslContextProvider(clientSslContextProvider())
|
.sslContextProvider(clientSslContextProvider())
|
||||||
.build();
|
.build();
|
||||||
SelfSignedCertificate ssc = new SelfSignedCertificate();
|
SelfSignedCertificate ssc = new SelfSignedCertificate();
|
||||||
serverSslCtx = SslContextBuilder.forServer(ssc.certificate(), ssc.privateKey())
|
serverSslCtx = SslContextBuilder.forServer(ssc.certificate(), ssc.privateKey())
|
||||||
.sslProvider(sslServerProvider())
|
.sslProvider(sslServerProvider())
|
||||||
|
// This test only works for non TLSv1.3 for now
|
||||||
|
.protocols(PROTOCOL_TLS_V1_2)
|
||||||
.sslContextProvider(serverSslContextProvider())
|
.sslContextProvider(serverSslContextProvider())
|
||||||
.build();
|
.build();
|
||||||
SSLEngine clientEngine = null;
|
SSLEngine clientEngine = null;
|
||||||
@ -1146,7 +1204,10 @@ public abstract class SSLEngineTest {
|
|||||||
final SelfSignedCertificate ssc = new SelfSignedCertificate();
|
final SelfSignedCertificate ssc = new SelfSignedCertificate();
|
||||||
serverSslCtx = SslContextBuilder.forServer(ssc.certificate(), ssc.privateKey())
|
serverSslCtx = SslContextBuilder.forServer(ssc.certificate(), ssc.privateKey())
|
||||||
.sslProvider(sslServerProvider())
|
.sslProvider(sslServerProvider())
|
||||||
.sslContextProvider(serverSslContextProvider()).build();
|
.sslContextProvider(serverSslContextProvider())
|
||||||
|
.protocols(protocols())
|
||||||
|
.ciphers(ciphers())
|
||||||
|
.build();
|
||||||
sb = new ServerBootstrap()
|
sb = new ServerBootstrap()
|
||||||
.group(new NioEventLoopGroup(1))
|
.group(new NioEventLoopGroup(1))
|
||||||
.channel(NioServerSocketChannel.class)
|
.channel(NioServerSocketChannel.class)
|
||||||
@ -1196,8 +1257,12 @@ public abstract class SSLEngineTest {
|
|||||||
serverChannel = sb.bind(new InetSocketAddress(0)).syncUninterruptibly().channel();
|
serverChannel = sb.bind(new InetSocketAddress(0)).syncUninterruptibly().channel();
|
||||||
|
|
||||||
clientSslCtx = SslContextBuilder.forClient()
|
clientSslCtx = SslContextBuilder.forClient()
|
||||||
.sslProvider(SslProvider.JDK) // OpenSslEngine doesn't support renegotiation on client side
|
// OpenSslEngine doesn't support renegotiation on client side
|
||||||
.trustManager(InsecureTrustManagerFactory.INSTANCE).build();
|
.sslProvider(SslProvider.JDK)
|
||||||
|
.trustManager(InsecureTrustManagerFactory.INSTANCE)
|
||||||
|
.protocols(protocols())
|
||||||
|
.ciphers(ciphers())
|
||||||
|
.build();
|
||||||
|
|
||||||
cb = new Bootstrap();
|
cb = new Bootstrap();
|
||||||
cb.group(new NioEventLoopGroup(1))
|
cb.group(new NioEventLoopGroup(1))
|
||||||
@ -1259,6 +1324,8 @@ public abstract class SSLEngineTest {
|
|||||||
serverSslCtx = SslContextBuilder.forServer(serverCrtFile, serverKeyFile)
|
serverSslCtx = SslContextBuilder.forServer(serverCrtFile, serverKeyFile)
|
||||||
.sslProvider(sslServerProvider())
|
.sslProvider(sslServerProvider())
|
||||||
.sslContextProvider(serverSslContextProvider())
|
.sslContextProvider(serverSslContextProvider())
|
||||||
|
.protocols(protocols())
|
||||||
|
.ciphers(ciphers())
|
||||||
.build();
|
.build();
|
||||||
|
|
||||||
sslEngine = wrapEngine(serverSslCtx.newEngine(UnpooledByteBufAllocator.DEFAULT));
|
sslEngine = wrapEngine(serverSslCtx.newEngine(UnpooledByteBufAllocator.DEFAULT));
|
||||||
@ -1338,7 +1405,10 @@ public abstract class SSLEngineTest {
|
|||||||
cTOsPos = cTOs.position();
|
cTOsPos = cTOs.position();
|
||||||
sTOcPos = sTOc.position();
|
sTOcPos = sTOc.position();
|
||||||
|
|
||||||
if (!clientHandshakeFinished) {
|
if (!clientHandshakeFinished ||
|
||||||
|
// After the handshake completes it is possible we have more data that was send by the server as
|
||||||
|
// the server will send session updates after the handshake. In this case continue to unwrap.
|
||||||
|
SslUtils.PROTOCOL_TLS_V1_3.equals(clientEngine.getSession().getProtocol())) {
|
||||||
int clientAppReadBufferPos = clientAppReadBuffer.position();
|
int clientAppReadBufferPos = clientAppReadBuffer.position();
|
||||||
clientResult = clientEngine.unwrap(sTOc, clientAppReadBuffer);
|
clientResult = clientEngine.unwrap(sTOc, clientAppReadBuffer);
|
||||||
|
|
||||||
@ -1350,7 +1420,7 @@ public abstract class SSLEngineTest {
|
|||||||
clientHandshakeFinished = true;
|
clientHandshakeFinished = true;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
assertFalse(sTOc.hasRemaining());
|
assertEquals(0, sTOc.remaining());
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!serverHandshakeFinished) {
|
if (!serverHandshakeFinished) {
|
||||||
@ -1433,24 +1503,35 @@ public abstract class SSLEngineTest {
|
|||||||
SelfSignedCertificate ssc = new SelfSignedCertificate();
|
SelfSignedCertificate ssc = new SelfSignedCertificate();
|
||||||
|
|
||||||
try {
|
try {
|
||||||
setupHandlers(SslContextBuilder.forServer(ssc.certificate(), ssc.privateKey(), null)
|
SslContextBuilder serverCtxBuilder = SslContextBuilder.forServer(ssc.certificate(), ssc.privateKey(), null)
|
||||||
.sslProvider(sslServerProvider())
|
.sslProvider(sslServerProvider())
|
||||||
.sslContextProvider(serverSslContextProvider())
|
.sslContextProvider(serverSslContextProvider())
|
||||||
.ciphers(null, IdentityCipherSuiteFilter.INSTANCE)
|
.ciphers(null, IdentityCipherSuiteFilter.INSTANCE)
|
||||||
.applicationProtocolConfig(serverApn)
|
.applicationProtocolConfig(serverApn)
|
||||||
.sessionCacheSize(0)
|
.sessionCacheSize(0)
|
||||||
.sessionTimeout(0)
|
.sessionTimeout(0);
|
||||||
.build(),
|
if (serverApn.protocol() == Protocol.NPN || serverApn.protocol() == Protocol.NPN_AND_ALPN) {
|
||||||
|
// NPN is not really well supported with TLSv1.3 so force to use TLSv1.2
|
||||||
|
// See https://github.com/openssl/openssl/issues/3665
|
||||||
|
serverCtxBuilder.protocols(PROTOCOL_TLS_V1_2);
|
||||||
|
}
|
||||||
|
|
||||||
SslContextBuilder.forClient()
|
SslContextBuilder clientCtxBuilder = SslContextBuilder.forClient()
|
||||||
.sslProvider(sslClientProvider())
|
.sslProvider(sslClientProvider())
|
||||||
.sslContextProvider(clientSslContextProvider())
|
.sslContextProvider(clientSslContextProvider())
|
||||||
.applicationProtocolConfig(clientApn)
|
.applicationProtocolConfig(clientApn)
|
||||||
.trustManager(InsecureTrustManagerFactory.INSTANCE)
|
.trustManager(InsecureTrustManagerFactory.INSTANCE)
|
||||||
.ciphers(null, IdentityCipherSuiteFilter.INSTANCE)
|
.ciphers(null, IdentityCipherSuiteFilter.INSTANCE)
|
||||||
.sessionCacheSize(0)
|
.sessionCacheSize(0)
|
||||||
.sessionTimeout(0)
|
.sessionTimeout(0);
|
||||||
.build());
|
|
||||||
|
if (clientApn.protocol() == Protocol.NPN || clientApn.protocol() == Protocol.NPN_AND_ALPN) {
|
||||||
|
// NPN is not really well supported with TLSv1.3 so force to use TLSv1.2
|
||||||
|
// See https://github.com/openssl/openssl/issues/3665
|
||||||
|
clientCtxBuilder.protocols(PROTOCOL_TLS_V1_2);
|
||||||
|
}
|
||||||
|
|
||||||
|
setupHandlers(serverCtxBuilder.build(), clientCtxBuilder.build());
|
||||||
} finally {
|
} finally {
|
||||||
ssc.delete();
|
ssc.delete();
|
||||||
}
|
}
|
||||||
@ -1511,6 +1592,11 @@ public abstract class SSLEngineTest {
|
|||||||
ctx.fireExceptionCaught(cause);
|
ctx.fireExceptionCaught(cause);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void channelInactive(ChannelHandlerContext ctx) throws Exception {
|
||||||
|
clientLatch.countDown();
|
||||||
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@ -1524,12 +1610,15 @@ public abstract class SSLEngineTest {
|
|||||||
|
|
||||||
@Test(timeout = 30000)
|
@Test(timeout = 30000)
|
||||||
public void testMutualAuthSameCertChain() throws Exception {
|
public void testMutualAuthSameCertChain() throws Exception {
|
||||||
serverSslCtx = SslContextBuilder.forServer(
|
serverSslCtx = configureProtocolForMutualAuth(
|
||||||
|
SslContextBuilder.forServer(
|
||||||
new ByteArrayInputStream(X509_CERT_PEM.getBytes(CharsetUtil.UTF_8)),
|
new ByteArrayInputStream(X509_CERT_PEM.getBytes(CharsetUtil.UTF_8)),
|
||||||
new ByteArrayInputStream(PRIVATE_KEY_PEM.getBytes(CharsetUtil.UTF_8)))
|
new ByteArrayInputStream(PRIVATE_KEY_PEM.getBytes(CharsetUtil.UTF_8)))
|
||||||
.trustManager(new ByteArrayInputStream(X509_CERT_PEM.getBytes(CharsetUtil.UTF_8)))
|
.trustManager(new ByteArrayInputStream(X509_CERT_PEM.getBytes(CharsetUtil.UTF_8)))
|
||||||
.clientAuth(ClientAuth.REQUIRE).sslProvider(sslServerProvider())
|
.clientAuth(ClientAuth.REQUIRE).sslProvider(sslServerProvider())
|
||||||
.sslContextProvider(serverSslContextProvider()).build();
|
.sslContextProvider(serverSslContextProvider())
|
||||||
|
.protocols(protocols())
|
||||||
|
.ciphers(ciphers())).build();
|
||||||
|
|
||||||
sb = new ServerBootstrap();
|
sb = new ServerBootstrap();
|
||||||
sb.group(new NioEventLoopGroup(), new NioEventLoopGroup());
|
sb.group(new NioEventLoopGroup(), new NioEventLoopGroup());
|
||||||
@ -1580,13 +1669,14 @@ public abstract class SSLEngineTest {
|
|||||||
}
|
}
|
||||||
}).bind(new InetSocketAddress(0)).syncUninterruptibly().channel();
|
}).bind(new InetSocketAddress(0)).syncUninterruptibly().channel();
|
||||||
|
|
||||||
clientSslCtx = SslContextBuilder.forClient()
|
clientSslCtx = configureProtocolForMutualAuth(
|
||||||
.keyManager(
|
SslContextBuilder.forClient().keyManager(
|
||||||
new ByteArrayInputStream(CLIENT_X509_CERT_CHAIN_PEM.getBytes(CharsetUtil.UTF_8)),
|
new ByteArrayInputStream(CLIENT_X509_CERT_CHAIN_PEM.getBytes(CharsetUtil.UTF_8)),
|
||||||
new ByteArrayInputStream(CLIENT_PRIVATE_KEY_PEM.getBytes(CharsetUtil.UTF_8)))
|
new ByteArrayInputStream(CLIENT_PRIVATE_KEY_PEM.getBytes(CharsetUtil.UTF_8)))
|
||||||
.trustManager(new ByteArrayInputStream(X509_CERT_PEM.getBytes(CharsetUtil.UTF_8)))
|
.trustManager(new ByteArrayInputStream(X509_CERT_PEM.getBytes(CharsetUtil.UTF_8)))
|
||||||
.sslProvider(sslClientProvider())
|
.sslProvider(sslClientProvider())
|
||||||
.sslContextProvider(clientSslContextProvider()).build();
|
.sslContextProvider(clientSslContextProvider())
|
||||||
|
.protocols(protocols()).ciphers(ciphers())).build();
|
||||||
cb = new Bootstrap();
|
cb = new Bootstrap();
|
||||||
cb.group(new NioEventLoopGroup());
|
cb.group(new NioEventLoopGroup());
|
||||||
cb.channel(NioSocketChannel.class);
|
cb.channel(NioSocketChannel.class);
|
||||||
@ -1610,12 +1700,16 @@ public abstract class SSLEngineTest {
|
|||||||
.forClient()
|
.forClient()
|
||||||
.trustManager(cert.cert())
|
.trustManager(cert.cert())
|
||||||
.sslProvider(sslClientProvider())
|
.sslProvider(sslClientProvider())
|
||||||
|
.protocols(protocols())
|
||||||
|
.ciphers(ciphers())
|
||||||
.build();
|
.build();
|
||||||
SSLEngine client = wrapEngine(clientSslCtx.newEngine(UnpooledByteBufAllocator.DEFAULT));
|
SSLEngine client = wrapEngine(clientSslCtx.newEngine(UnpooledByteBufAllocator.DEFAULT));
|
||||||
|
|
||||||
serverSslCtx = SslContextBuilder
|
serverSslCtx = SslContextBuilder
|
||||||
.forServer(cert.certificate(), cert.privateKey())
|
.forServer(cert.certificate(), cert.privateKey())
|
||||||
.sslProvider(sslServerProvider())
|
.sslProvider(sslServerProvider())
|
||||||
|
.protocols(protocols())
|
||||||
|
.ciphers(ciphers())
|
||||||
.build();
|
.build();
|
||||||
SSLEngine server = wrapEngine(serverSslCtx.newEngine(UnpooledByteBufAllocator.DEFAULT));
|
SSLEngine server = wrapEngine(serverSslCtx.newEngine(UnpooledByteBufAllocator.DEFAULT));
|
||||||
|
|
||||||
@ -1790,12 +1884,16 @@ public abstract class SSLEngineTest {
|
|||||||
.forClient()
|
.forClient()
|
||||||
.trustManager(cert.cert())
|
.trustManager(cert.cert())
|
||||||
.sslProvider(sslClientProvider())
|
.sslProvider(sslClientProvider())
|
||||||
|
.protocols(protocols())
|
||||||
|
.ciphers(ciphers())
|
||||||
.build();
|
.build();
|
||||||
SSLEngine client = wrapEngine(clientSslCtx.newEngine(UnpooledByteBufAllocator.DEFAULT));
|
SSLEngine client = wrapEngine(clientSslCtx.newEngine(UnpooledByteBufAllocator.DEFAULT));
|
||||||
|
|
||||||
serverSslCtx = SslContextBuilder
|
serverSslCtx = SslContextBuilder
|
||||||
.forServer(cert.certificate(), cert.privateKey())
|
.forServer(cert.certificate(), cert.privateKey())
|
||||||
.sslProvider(sslServerProvider())
|
.sslProvider(sslServerProvider())
|
||||||
|
.protocols(protocols())
|
||||||
|
.ciphers(ciphers())
|
||||||
.build();
|
.build();
|
||||||
SSLEngine server = wrapEngine(serverSslCtx.newEngine(UnpooledByteBufAllocator.DEFAULT));
|
SSLEngine server = wrapEngine(serverSslCtx.newEngine(UnpooledByteBufAllocator.DEFAULT));
|
||||||
|
|
||||||
@ -1829,6 +1927,8 @@ public abstract class SSLEngineTest {
|
|||||||
clientSslCtx = SslContextBuilder
|
clientSslCtx = SslContextBuilder
|
||||||
.forClient()
|
.forClient()
|
||||||
.sslProvider(sslClientProvider())
|
.sslProvider(sslClientProvider())
|
||||||
|
.protocols(protocols())
|
||||||
|
.ciphers(ciphers())
|
||||||
.build();
|
.build();
|
||||||
SSLEngine client = wrapEngine(clientSslCtx.newEngine(UnpooledByteBufAllocator.DEFAULT));
|
SSLEngine client = wrapEngine(clientSslCtx.newEngine(UnpooledByteBufAllocator.DEFAULT));
|
||||||
|
|
||||||
@ -1857,6 +1957,8 @@ public abstract class SSLEngineTest {
|
|||||||
clientSslCtx = SslContextBuilder
|
clientSslCtx = SslContextBuilder
|
||||||
.forClient()
|
.forClient()
|
||||||
.sslProvider(sslClientProvider())
|
.sslProvider(sslClientProvider())
|
||||||
|
.protocols(protocols())
|
||||||
|
.ciphers(ciphers())
|
||||||
.build();
|
.build();
|
||||||
SSLEngine client = wrapEngine(clientSslCtx.newEngine(UnpooledByteBufAllocator.DEFAULT));
|
SSLEngine client = wrapEngine(clientSslCtx.newEngine(UnpooledByteBufAllocator.DEFAULT));
|
||||||
|
|
||||||
@ -1881,12 +1983,16 @@ public abstract class SSLEngineTest {
|
|||||||
clientSslCtx = SslContextBuilder
|
clientSslCtx = SslContextBuilder
|
||||||
.forClient()
|
.forClient()
|
||||||
.sslProvider(sslClientProvider())
|
.sslProvider(sslClientProvider())
|
||||||
|
.protocols(protocols())
|
||||||
|
.ciphers(ciphers())
|
||||||
.build();
|
.build();
|
||||||
SSLEngine client = wrapEngine(clientSslCtx.newEngine(UnpooledByteBufAllocator.DEFAULT));
|
SSLEngine client = wrapEngine(clientSslCtx.newEngine(UnpooledByteBufAllocator.DEFAULT));
|
||||||
|
|
||||||
serverSslCtx = SslContextBuilder
|
serverSslCtx = SslContextBuilder
|
||||||
.forServer(cert.certificate(), cert.privateKey())
|
.forServer(cert.certificate(), cert.privateKey())
|
||||||
.sslProvider(sslServerProvider())
|
.sslProvider(sslServerProvider())
|
||||||
|
.protocols(protocols())
|
||||||
|
.ciphers(ciphers())
|
||||||
.build();
|
.build();
|
||||||
SSLEngine server = wrapEngine(serverSslCtx.newEngine(UnpooledByteBufAllocator.DEFAULT));
|
SSLEngine server = wrapEngine(serverSslCtx.newEngine(UnpooledByteBufAllocator.DEFAULT));
|
||||||
|
|
||||||
@ -1928,12 +2034,16 @@ public abstract class SSLEngineTest {
|
|||||||
clientSslCtx = SslContextBuilder
|
clientSslCtx = SslContextBuilder
|
||||||
.forClient()
|
.forClient()
|
||||||
.sslProvider(sslClientProvider())
|
.sslProvider(sslClientProvider())
|
||||||
|
.protocols(protocols())
|
||||||
|
.ciphers(ciphers())
|
||||||
.build();
|
.build();
|
||||||
SSLEngine client = wrapEngine(clientSslCtx.newEngine(UnpooledByteBufAllocator.DEFAULT));
|
SSLEngine client = wrapEngine(clientSslCtx.newEngine(UnpooledByteBufAllocator.DEFAULT));
|
||||||
|
|
||||||
serverSslCtx = SslContextBuilder
|
serverSslCtx = SslContextBuilder
|
||||||
.forServer(cert.certificate(), cert.privateKey())
|
.forServer(cert.certificate(), cert.privateKey())
|
||||||
.sslProvider(sslServerProvider())
|
.sslProvider(sslServerProvider())
|
||||||
|
.protocols(protocols())
|
||||||
|
.ciphers(ciphers())
|
||||||
.build();
|
.build();
|
||||||
SSLEngine server = wrapEngine(serverSslCtx.newEngine(UnpooledByteBufAllocator.DEFAULT));
|
SSLEngine server = wrapEngine(serverSslCtx.newEngine(UnpooledByteBufAllocator.DEFAULT));
|
||||||
|
|
||||||
@ -1965,12 +2075,16 @@ public abstract class SSLEngineTest {
|
|||||||
.forClient()
|
.forClient()
|
||||||
.trustManager(cert.cert())
|
.trustManager(cert.cert())
|
||||||
.sslProvider(sslClientProvider())
|
.sslProvider(sslClientProvider())
|
||||||
|
// This test only works for non TLSv1.3 for now
|
||||||
|
.protocols(PROTOCOL_TLS_V1_2)
|
||||||
.build();
|
.build();
|
||||||
SSLEngine client = wrapEngine(clientSslCtx.newEngine(UnpooledByteBufAllocator.DEFAULT));
|
SSLEngine client = wrapEngine(clientSslCtx.newEngine(UnpooledByteBufAllocator.DEFAULT));
|
||||||
|
|
||||||
serverSslCtx = SslContextBuilder
|
serverSslCtx = SslContextBuilder
|
||||||
.forServer(cert.certificate(), cert.privateKey())
|
.forServer(cert.certificate(), cert.privateKey())
|
||||||
.sslProvider(sslServerProvider())
|
.sslProvider(sslServerProvider())
|
||||||
|
// This test only works for non TLSv1.3 for now
|
||||||
|
.protocols(PROTOCOL_TLS_V1_2)
|
||||||
.build();
|
.build();
|
||||||
SSLEngine server = wrapEngine(serverSslCtx.newEngine(UnpooledByteBufAllocator.DEFAULT));
|
SSLEngine server = wrapEngine(serverSslCtx.newEngine(UnpooledByteBufAllocator.DEFAULT));
|
||||||
|
|
||||||
@ -2032,6 +2146,7 @@ public abstract class SSLEngineTest {
|
|||||||
|
|
||||||
result = server.wrap(empty, encryptedServerToClient);
|
result = server.wrap(empty, encryptedServerToClient);
|
||||||
encryptedServerToClient.flip();
|
encryptedServerToClient.flip();
|
||||||
|
|
||||||
assertEquals(SSLEngineResult.Status.CLOSED, result.getStatus());
|
assertEquals(SSLEngineResult.Status.CLOSED, result.getStatus());
|
||||||
// UNWRAP/WRAP are not expected after this point
|
// UNWRAP/WRAP are not expected after this point
|
||||||
assertEquals(SSLEngineResult.HandshakeStatus.NOT_HANDSHAKING, result.getHandshakeStatus());
|
assertEquals(SSLEngineResult.HandshakeStatus.NOT_HANDSHAKING, result.getHandshakeStatus());
|
||||||
@ -2046,6 +2161,7 @@ public abstract class SSLEngineTest {
|
|||||||
assertTrue(server.isInboundDone());
|
assertTrue(server.isInboundDone());
|
||||||
|
|
||||||
result = client.unwrap(encryptedServerToClient, plainClientOut);
|
result = client.unwrap(encryptedServerToClient, plainClientOut);
|
||||||
|
|
||||||
plainClientOut.flip();
|
plainClientOut.flip();
|
||||||
assertEquals(SSLEngineResult.Status.CLOSED, result.getStatus());
|
assertEquals(SSLEngineResult.Status.CLOSED, result.getStatus());
|
||||||
// UNWRAP/WRAP are not expected after this point
|
// UNWRAP/WRAP are not expected after this point
|
||||||
@ -2106,12 +2222,16 @@ public abstract class SSLEngineTest {
|
|||||||
.forClient()
|
.forClient()
|
||||||
.trustManager(cert.cert())
|
.trustManager(cert.cert())
|
||||||
.sslProvider(sslClientProvider())
|
.sslProvider(sslClientProvider())
|
||||||
|
.protocols(protocols())
|
||||||
|
.ciphers(ciphers())
|
||||||
.build();
|
.build();
|
||||||
SSLEngine client = wrapEngine(clientSslCtx.newEngine(UnpooledByteBufAllocator.DEFAULT));
|
SSLEngine client = wrapEngine(clientSslCtx.newEngine(UnpooledByteBufAllocator.DEFAULT));
|
||||||
|
|
||||||
serverSslCtx = SslContextBuilder
|
serverSslCtx = SslContextBuilder
|
||||||
.forServer(cert.certificate(), cert.privateKey())
|
.forServer(cert.certificate(), cert.privateKey())
|
||||||
.sslProvider(sslServerProvider())
|
.sslProvider(sslServerProvider())
|
||||||
|
.protocols(protocols())
|
||||||
|
.ciphers(ciphers())
|
||||||
.build();
|
.build();
|
||||||
SSLEngine server = wrapEngine(serverSslCtx.newEngine(UnpooledByteBufAllocator.DEFAULT));
|
SSLEngine server = wrapEngine(serverSslCtx.newEngine(UnpooledByteBufAllocator.DEFAULT));
|
||||||
|
|
||||||
@ -2145,12 +2265,16 @@ public abstract class SSLEngineTest {
|
|||||||
.forClient()
|
.forClient()
|
||||||
.trustManager(cert.cert())
|
.trustManager(cert.cert())
|
||||||
.sslProvider(sslClientProvider())
|
.sslProvider(sslClientProvider())
|
||||||
|
.protocols(protocols())
|
||||||
|
.ciphers(ciphers())
|
||||||
.build();
|
.build();
|
||||||
SSLEngine client = wrapEngine(clientSslCtx.newEngine(UnpooledByteBufAllocator.DEFAULT));
|
SSLEngine client = wrapEngine(clientSslCtx.newEngine(UnpooledByteBufAllocator.DEFAULT));
|
||||||
|
|
||||||
serverSslCtx = SslContextBuilder
|
serverSslCtx = SslContextBuilder
|
||||||
.forServer(cert.certificate(), cert.privateKey())
|
.forServer(cert.certificate(), cert.privateKey())
|
||||||
.sslProvider(sslServerProvider())
|
.sslProvider(sslServerProvider())
|
||||||
|
.protocols(protocols())
|
||||||
|
.ciphers(ciphers())
|
||||||
.build();
|
.build();
|
||||||
SSLEngine server = wrapEngine(serverSslCtx.newEngine(UnpooledByteBufAllocator.DEFAULT));
|
SSLEngine server = wrapEngine(serverSslCtx.newEngine(UnpooledByteBufAllocator.DEFAULT));
|
||||||
|
|
||||||
@ -2220,12 +2344,16 @@ public abstract class SSLEngineTest {
|
|||||||
.forClient()
|
.forClient()
|
||||||
.trustManager(cert.cert())
|
.trustManager(cert.cert())
|
||||||
.sslProvider(sslClientProvider())
|
.sslProvider(sslClientProvider())
|
||||||
|
.protocols(protocols())
|
||||||
|
.ciphers(ciphers())
|
||||||
.build();
|
.build();
|
||||||
SSLEngine client = wrapEngine(clientSslCtx.newEngine(UnpooledByteBufAllocator.DEFAULT));
|
SSLEngine client = wrapEngine(clientSslCtx.newEngine(UnpooledByteBufAllocator.DEFAULT));
|
||||||
|
|
||||||
serverSslCtx = SslContextBuilder
|
serverSslCtx = SslContextBuilder
|
||||||
.forServer(cert.certificate(), cert.privateKey())
|
.forServer(cert.certificate(), cert.privateKey())
|
||||||
.sslProvider(sslServerProvider())
|
.sslProvider(sslServerProvider())
|
||||||
|
.protocols(protocols())
|
||||||
|
.ciphers(ciphers())
|
||||||
.build();
|
.build();
|
||||||
SSLEngine server = wrapEngine(serverSslCtx.newEngine(UnpooledByteBufAllocator.DEFAULT));
|
SSLEngine server = wrapEngine(serverSslCtx.newEngine(UnpooledByteBufAllocator.DEFAULT));
|
||||||
|
|
||||||
@ -2240,21 +2368,35 @@ public abstract class SSLEngineTest {
|
|||||||
int srcLen = plainClientOut.remaining();
|
int srcLen = plainClientOut.remaining();
|
||||||
SSLEngineResult result;
|
SSLEngineResult result;
|
||||||
|
|
||||||
while (encClientToServer.position() <= server.getSession().getPacketBufferSize()) {
|
int count = 0;
|
||||||
|
do {
|
||||||
|
int plainClientOutPosition = plainClientOut.position();
|
||||||
|
int encClientToServerPosition = encClientToServer.position();
|
||||||
result = client.wrap(plainClientOut, encClientToServer);
|
result = client.wrap(plainClientOut, encClientToServer);
|
||||||
|
if (result.getStatus() == Status.BUFFER_OVERFLOW) {
|
||||||
|
// We did not have enough room to wrap
|
||||||
|
assertEquals(plainClientOutPosition, plainClientOut.position());
|
||||||
|
assertEquals(encClientToServerPosition, encClientToServer.position());
|
||||||
|
break;
|
||||||
|
}
|
||||||
assertEquals(SSLEngineResult.Status.OK, result.getStatus());
|
assertEquals(SSLEngineResult.Status.OK, result.getStatus());
|
||||||
assertEquals(srcLen, result.bytesConsumed());
|
assertEquals(srcLen, result.bytesConsumed());
|
||||||
assertTrue(result.bytesProduced() > 0);
|
assertTrue(result.bytesProduced() > 0);
|
||||||
|
|
||||||
plainClientOut.clear();
|
plainClientOut.clear();
|
||||||
}
|
|
||||||
|
|
||||||
|
++count;
|
||||||
|
} while (encClientToServer.position() < server.getSession().getPacketBufferSize());
|
||||||
|
|
||||||
|
// Check that we were able to wrap multiple times.
|
||||||
|
assertTrue(count >= 2);
|
||||||
encClientToServer.flip();
|
encClientToServer.flip();
|
||||||
|
|
||||||
result = server.unwrap(encClientToServer, plainServerOut);
|
result = server.unwrap(encClientToServer, plainServerOut);
|
||||||
assertEquals(SSLEngineResult.Status.OK, result.getStatus());
|
assertEquals(SSLEngineResult.Status.OK, result.getStatus());
|
||||||
assertTrue(result.bytesConsumed() > 0);
|
assertTrue(result.bytesConsumed() > 0);
|
||||||
assertTrue(result.bytesProduced() > 0);
|
assertTrue(result.bytesProduced() > 0);
|
||||||
|
assertTrue(encClientToServer.hasRemaining());
|
||||||
} finally {
|
} finally {
|
||||||
cert.delete();
|
cert.delete();
|
||||||
cleanupClientSslEngine(client);
|
cleanupClientSslEngine(client);
|
||||||
@ -2270,12 +2412,16 @@ public abstract class SSLEngineTest {
|
|||||||
.forClient()
|
.forClient()
|
||||||
.trustManager(cert.cert())
|
.trustManager(cert.cert())
|
||||||
.sslProvider(sslClientProvider())
|
.sslProvider(sslClientProvider())
|
||||||
|
.protocols(protocols())
|
||||||
|
.ciphers(ciphers())
|
||||||
.build();
|
.build();
|
||||||
SSLEngine client = wrapEngine(clientSslCtx.newEngine(UnpooledByteBufAllocator.DEFAULT));
|
SSLEngine client = wrapEngine(clientSslCtx.newEngine(UnpooledByteBufAllocator.DEFAULT));
|
||||||
|
|
||||||
serverSslCtx = SslContextBuilder
|
serverSslCtx = SslContextBuilder
|
||||||
.forServer(cert.certificate(), cert.privateKey())
|
.forServer(cert.certificate(), cert.privateKey())
|
||||||
.sslProvider(sslServerProvider())
|
.sslProvider(sslServerProvider())
|
||||||
|
.protocols(protocols())
|
||||||
|
.ciphers(ciphers())
|
||||||
.build();
|
.build();
|
||||||
SSLEngine server = wrapEngine(serverSslCtx.newEngine(UnpooledByteBufAllocator.DEFAULT));
|
SSLEngine server = wrapEngine(serverSslCtx.newEngine(UnpooledByteBufAllocator.DEFAULT));
|
||||||
|
|
||||||
@ -2341,12 +2487,16 @@ public abstract class SSLEngineTest {
|
|||||||
.forClient()
|
.forClient()
|
||||||
.trustManager(cert.cert())
|
.trustManager(cert.cert())
|
||||||
.sslProvider(sslClientProvider())
|
.sslProvider(sslClientProvider())
|
||||||
|
.protocols(protocols())
|
||||||
|
.ciphers(ciphers())
|
||||||
.build();
|
.build();
|
||||||
SSLEngine client = wrapEngine(clientSslCtx.newEngine(UnpooledByteBufAllocator.DEFAULT));
|
SSLEngine client = wrapEngine(clientSslCtx.newEngine(UnpooledByteBufAllocator.DEFAULT));
|
||||||
|
|
||||||
serverSslCtx = SslContextBuilder
|
serverSslCtx = SslContextBuilder
|
||||||
.forServer(cert.certificate(), cert.privateKey())
|
.forServer(cert.certificate(), cert.privateKey())
|
||||||
.sslProvider(sslServerProvider())
|
.sslProvider(sslServerProvider())
|
||||||
|
.protocols(protocols())
|
||||||
|
.ciphers(ciphers())
|
||||||
.build();
|
.build();
|
||||||
SSLEngine server = wrapEngine(serverSslCtx.newEngine(UnpooledByteBufAllocator.DEFAULT));
|
SSLEngine server = wrapEngine(serverSslCtx.newEngine(UnpooledByteBufAllocator.DEFAULT));
|
||||||
|
|
||||||
@ -2393,6 +2543,8 @@ public abstract class SSLEngineTest {
|
|||||||
SslContext ctx = SslContextBuilder
|
SslContext ctx = SslContextBuilder
|
||||||
.forServer(cert.certificate(), cert.privateKey())
|
.forServer(cert.certificate(), cert.privateKey())
|
||||||
.sslProvider(sslServerProvider())
|
.sslProvider(sslServerProvider())
|
||||||
|
.protocols(protocols())
|
||||||
|
.ciphers(ciphers())
|
||||||
.build();
|
.build();
|
||||||
SSLEngine server = wrapEngine(ctx.newEngine(UnpooledByteBufAllocator.DEFAULT));
|
SSLEngine server = wrapEngine(ctx.newEngine(UnpooledByteBufAllocator.DEFAULT));
|
||||||
|
|
||||||
@ -2495,4 +2647,12 @@ public abstract class SSLEngineTest {
|
|||||||
protected SSLEngine wrapEngine(SSLEngine engine) {
|
protected SSLEngine wrapEngine(SSLEngine engine) {
|
||||||
return engine;
|
return engine;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected List<String> ciphers() {
|
||||||
|
return Collections.singletonList(protocolCipherCombo.cipher);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected String[] protocols() {
|
||||||
|
return new String[] { protocolCipherCombo.protocol };
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -15,18 +15,19 @@
|
|||||||
*/
|
*/
|
||||||
package io.netty.handler.ssl;
|
package io.netty.handler.ssl;
|
||||||
|
|
||||||
import static org.junit.Assert.assertFalse;
|
|
||||||
import static org.junit.Assert.assertTrue;
|
|
||||||
|
|
||||||
import io.netty.buffer.UnpooledByteBufAllocator;
|
import io.netty.buffer.UnpooledByteBufAllocator;
|
||||||
import io.netty.handler.ssl.util.SelfSignedCertificate;
|
import io.netty.handler.ssl.util.SelfSignedCertificate;
|
||||||
import org.junit.Assume;
|
import org.junit.Assume;
|
||||||
|
import org.junit.Ignore;
|
||||||
|
import org.junit.Rule;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
|
|
||||||
import javax.net.ssl.SSLEngine;
|
import javax.net.ssl.SSLEngine;
|
||||||
import javax.net.ssl.SSLException;
|
import javax.net.ssl.SSLException;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
|
|
||||||
|
import static org.junit.Assert.*;
|
||||||
|
|
||||||
public class SslContextBuilderTest {
|
public class SslContextBuilderTest {
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@ -79,10 +80,19 @@ public class SslContextBuilderTest {
|
|||||||
testInvalidCipher(SslProvider.JDK);
|
testInvalidCipher(SslProvider.JDK);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test(expected = SSLException.class)
|
@Test
|
||||||
public void testInvalidCipherOpenSSL() throws Exception {
|
public void testInvalidCipherOpenSSL() throws Exception {
|
||||||
Assume.assumeTrue(OpenSsl.isAvailable());
|
Assume.assumeTrue(OpenSsl.isAvailable());
|
||||||
|
try {
|
||||||
|
// This may fail or not depending on the OpenSSL version used
|
||||||
|
// See https://github.com/openssl/openssl/issues/7196
|
||||||
testInvalidCipher(SslProvider.OPENSSL);
|
testInvalidCipher(SslProvider.OPENSSL);
|
||||||
|
if (!OpenSsl.versionString().contains("1.1.1")) {
|
||||||
|
fail();
|
||||||
|
}
|
||||||
|
} catch (SSLException expected) {
|
||||||
|
// ok
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void testInvalidCipher(SslProvider provider) throws Exception {
|
private static void testInvalidCipher(SslProvider provider) throws Exception {
|
||||||
|
@ -124,7 +124,8 @@ public class SslErrorTest {
|
|||||||
Assume.assumeTrue(OpenSsl.isAvailable());
|
Assume.assumeTrue(OpenSsl.isAvailable());
|
||||||
|
|
||||||
SelfSignedCertificate ssc = new SelfSignedCertificate();
|
SelfSignedCertificate ssc = new SelfSignedCertificate();
|
||||||
final SslContext sslServerCtx = SslContextBuilder.forServer(ssc.certificate(), ssc.privateKey())
|
final SslContext sslServerCtx = OpenSslTestUtils.configureProtocolForMutualAuth(
|
||||||
|
SslContextBuilder.forServer(ssc.certificate(), ssc.privateKey())
|
||||||
.sslProvider(serverProvider)
|
.sslProvider(serverProvider)
|
||||||
.trustManager(new SimpleTrustManagerFactory() {
|
.trustManager(new SimpleTrustManagerFactory() {
|
||||||
@Override
|
@Override
|
||||||
@ -154,13 +155,13 @@ public class SslErrorTest {
|
|||||||
}
|
}
|
||||||
} };
|
} };
|
||||||
}
|
}
|
||||||
}).clientAuth(ClientAuth.REQUIRE).build();
|
}).clientAuth(ClientAuth.REQUIRE), clientProvider, serverProvider).build();
|
||||||
|
|
||||||
final SslContext sslClientCtx = SslContextBuilder.forClient()
|
final SslContext sslClientCtx = OpenSslTestUtils.configureProtocolForMutualAuth(SslContextBuilder.forClient()
|
||||||
.trustManager(InsecureTrustManagerFactory.INSTANCE)
|
.trustManager(InsecureTrustManagerFactory.INSTANCE)
|
||||||
.keyManager(new File(getClass().getResource("test.crt").getFile()),
|
.keyManager(new File(getClass().getResource("test.crt").getFile()),
|
||||||
new File(getClass().getResource("test_unencrypted.pem").getFile()))
|
new File(getClass().getResource("test_unencrypted.pem").getFile()))
|
||||||
.sslProvider(clientProvider).build();
|
.sslProvider(clientProvider), clientProvider, serverProvider).build();
|
||||||
|
|
||||||
Channel serverChannel = null;
|
Channel serverChannel = null;
|
||||||
Channel clientChannel = null;
|
Channel clientChannel = null;
|
||||||
|
@ -28,6 +28,7 @@ import java.security.NoSuchAlgorithmException;
|
|||||||
|
|
||||||
import static io.netty.handler.ssl.SslUtils.getEncryptedPacketLength;
|
import static io.netty.handler.ssl.SslUtils.getEncryptedPacketLength;
|
||||||
import static org.junit.Assert.assertEquals;
|
import static org.junit.Assert.assertEquals;
|
||||||
|
import static org.junit.Assert.assertFalse;
|
||||||
import static org.junit.Assert.assertTrue;
|
import static org.junit.Assert.assertTrue;
|
||||||
|
|
||||||
public class SslUtilsTest {
|
public class SslUtilsTest {
|
||||||
@ -63,4 +64,15 @@ public class SslUtilsTest {
|
|||||||
engine.beginHandshake();
|
engine.beginHandshake();
|
||||||
return engine;
|
return engine;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testIsTLSv13Cipher() {
|
||||||
|
assertTrue(SslUtils.isTLSv13Cipher("TLS_AES_128_GCM_SHA256"));
|
||||||
|
assertTrue(SslUtils.isTLSv13Cipher("TLS_AES_256_GCM_SHA384"));
|
||||||
|
assertTrue(SslUtils.isTLSv13Cipher("TLS_CHACHA20_POLY1305_SHA256"));
|
||||||
|
assertTrue(SslUtils.isTLSv13Cipher("TLS_AES_128_CCM_SHA256"));
|
||||||
|
assertTrue(SslUtils.isTLSv13Cipher("TLS_AES_128_CCM_8_SHA256"));
|
||||||
|
assertFalse(SslUtils.isTLSv13Cipher("TLS_DHE_RSA_WITH_AES_128_GCM_SHA256"));
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
2
pom.xml
2
pom.xml
@ -241,7 +241,7 @@
|
|||||||
<!-- Fedora-"like" systems. This is currently only used for the netty-tcnative dependency -->
|
<!-- Fedora-"like" systems. This is currently only used for the netty-tcnative dependency -->
|
||||||
<os.detection.classifierWithLikes>fedora</os.detection.classifierWithLikes>
|
<os.detection.classifierWithLikes>fedora</os.detection.classifierWithLikes>
|
||||||
<tcnative.artifactId>netty-tcnative</tcnative.artifactId>
|
<tcnative.artifactId>netty-tcnative</tcnative.artifactId>
|
||||||
<tcnative.version>2.0.17.Final</tcnative.version>
|
<tcnative.version>2.0.18.Final</tcnative.version>
|
||||||
<tcnative.classifier>${os.detected.classifier}</tcnative.classifier>
|
<tcnative.classifier>${os.detected.classifier}</tcnative.classifier>
|
||||||
<conscrypt.groupId>org.conscrypt</conscrypt.groupId>
|
<conscrypt.groupId>org.conscrypt</conscrypt.groupId>
|
||||||
<conscrypt.artifactId>conscrypt-openjdk-uber</conscrypt.artifactId>
|
<conscrypt.artifactId>conscrypt-openjdk-uber</conscrypt.artifactId>
|
||||||
|
@ -138,7 +138,8 @@ public class SocketSslClientRenegotiateTest extends AbstractSocketTest {
|
|||||||
public void initChannel(Channel sch) throws Exception {
|
public void initChannel(Channel sch) throws Exception {
|
||||||
serverChannel = sch;
|
serverChannel = sch;
|
||||||
serverSslHandler = serverCtx.newHandler(sch.alloc());
|
serverSslHandler = serverCtx.newHandler(sch.alloc());
|
||||||
|
// As we test renegotiation we should use a protocol that support it.
|
||||||
|
serverSslHandler.engine().setEnabledProtocols(new String[] { "TLSv1.2" });
|
||||||
sch.pipeline().addLast("ssl", serverSslHandler);
|
sch.pipeline().addLast("ssl", serverSslHandler);
|
||||||
sch.pipeline().addLast("handler", serverHandler);
|
sch.pipeline().addLast("handler", serverHandler);
|
||||||
}
|
}
|
||||||
@ -150,7 +151,8 @@ public class SocketSslClientRenegotiateTest extends AbstractSocketTest {
|
|||||||
public void initChannel(Channel sch) throws Exception {
|
public void initChannel(Channel sch) throws Exception {
|
||||||
clientChannel = sch;
|
clientChannel = sch;
|
||||||
clientSslHandler = clientCtx.newHandler(sch.alloc());
|
clientSslHandler = clientCtx.newHandler(sch.alloc());
|
||||||
|
// As we test renegotiation we should use a protocol that support it.
|
||||||
|
clientSslHandler.engine().setEnabledProtocols(new String[] { "TLSv1.2" });
|
||||||
sch.pipeline().addLast("ssl", clientSslHandler);
|
sch.pipeline().addLast("ssl", clientSslHandler);
|
||||||
sch.pipeline().addLast("handler", clientHandler);
|
sch.pipeline().addLast("handler", clientHandler);
|
||||||
}
|
}
|
||||||
|
@ -123,17 +123,33 @@ public class SocketSslEchoTest extends AbstractSocketTest {
|
|||||||
"autoRead = {5}, useChunkedWriteHandler = {6}, useCompositeByteBuf = {7}")
|
"autoRead = {5}, useChunkedWriteHandler = {6}, useCompositeByteBuf = {7}")
|
||||||
public static Collection<Object[]> data() throws Exception {
|
public static Collection<Object[]> data() throws Exception {
|
||||||
List<SslContext> serverContexts = new ArrayList<SslContext>();
|
List<SslContext> serverContexts = new ArrayList<SslContext>();
|
||||||
serverContexts.add(SslContextBuilder.forServer(CERT_FILE, KEY_FILE).sslProvider(SslProvider.JDK).build());
|
serverContexts.add(SslContextBuilder.forServer(CERT_FILE, KEY_FILE)
|
||||||
|
.sslProvider(SslProvider.JDK)
|
||||||
|
// As we test renegotiation we should use a protocol that support it.
|
||||||
|
.protocols("TLSv1.2")
|
||||||
|
.build());
|
||||||
|
|
||||||
List<SslContext> clientContexts = new ArrayList<SslContext>();
|
List<SslContext> clientContexts = new ArrayList<SslContext>();
|
||||||
clientContexts.add(SslContextBuilder.forClient().sslProvider(SslProvider.JDK).trustManager(CERT_FILE).build());
|
clientContexts.add(SslContextBuilder.forClient()
|
||||||
|
.sslProvider(SslProvider.JDK)
|
||||||
|
.trustManager(CERT_FILE)
|
||||||
|
// As we test renegotiation we should use a protocol that support it.
|
||||||
|
.protocols("TLSv1.2")
|
||||||
|
.build());
|
||||||
|
|
||||||
boolean hasOpenSsl = OpenSsl.isAvailable();
|
boolean hasOpenSsl = OpenSsl.isAvailable();
|
||||||
if (hasOpenSsl) {
|
if (hasOpenSsl) {
|
||||||
serverContexts.add(SslContextBuilder.forServer(CERT_FILE, KEY_FILE)
|
serverContexts.add(SslContextBuilder.forServer(CERT_FILE, KEY_FILE)
|
||||||
.sslProvider(SslProvider.OPENSSL).build());
|
.sslProvider(SslProvider.OPENSSL)
|
||||||
clientContexts.add(SslContextBuilder.forClient().sslProvider(SslProvider.OPENSSL)
|
// As we test renegotiation we should use a protocol that support it.
|
||||||
.trustManager(CERT_FILE).build());
|
.protocols("TLSv1.2")
|
||||||
|
.build());
|
||||||
|
clientContexts.add(SslContextBuilder.forClient()
|
||||||
|
.sslProvider(SslProvider.OPENSSL)
|
||||||
|
.trustManager(CERT_FILE)
|
||||||
|
// As we test renegotiation we should use a protocol that support it.
|
||||||
|
.protocols("TLSv1.2")
|
||||||
|
.build());
|
||||||
} else {
|
} else {
|
||||||
logger.warn("OpenSSL is unavailable and thus will not be tested.", OpenSsl.unavailabilityCause());
|
logger.warn("OpenSSL is unavailable and thus will not be tested.", OpenSsl.unavailabilityCause());
|
||||||
}
|
}
|
||||||
|
@ -98,7 +98,7 @@ public class SocketSslSessionReuseTest extends AbstractSocketTest {
|
|||||||
public void testSslSessionReuse(ServerBootstrap sb, Bootstrap cb) throws Throwable {
|
public void testSslSessionReuse(ServerBootstrap sb, Bootstrap cb) throws Throwable {
|
||||||
final ReadAndDiscardHandler sh = new ReadAndDiscardHandler(true, true);
|
final ReadAndDiscardHandler sh = new ReadAndDiscardHandler(true, true);
|
||||||
final ReadAndDiscardHandler ch = new ReadAndDiscardHandler(false, true);
|
final ReadAndDiscardHandler ch = new ReadAndDiscardHandler(false, true);
|
||||||
final String[] protocols = new String[]{ "TLSv1", "TLSv1.1", "TLSv1.2" };
|
final String[] protocols = { "TLSv1", "TLSv1.1", "TLSv1.2" };
|
||||||
|
|
||||||
sb.childHandler(new ChannelInitializer<SocketChannel>() {
|
sb.childHandler(new ChannelInitializer<SocketChannel>() {
|
||||||
@Override
|
@Override
|
||||||
|
Loading…
Reference in New Issue
Block a user