JSSE: add support for jdk.tls.disabledAlgorithms and disabled SSL/TLS protocol versions
parent
fbafc4c5ad
commit
eb6919e0b5
|
@ -69,9 +69,17 @@ public class WolfSSLContext extends SSLContextSpi {
|
|||
/* Get available wolfSSL cipher suites in IANA format */
|
||||
ciphersIana = WolfSSL.getCiphersAvailableIana(this.currentVersion);
|
||||
|
||||
/* Allow ability for user to hard-code and override version, cipher
|
||||
* suite, and NO_* disable options. Otherwise just sets defaults
|
||||
* into ctxAttr. */
|
||||
WolfSSLCustomUser ctxAttr = WolfSSLCustomUser.GetCtxAttributes
|
||||
(this.currentVersion, ciphersIana);
|
||||
|
||||
/* Explicitly set SSLContext version if overridden by
|
||||
* WolfSSLCustomUser or specific SSLContext version was created
|
||||
* by user. Otherwise use default of SSLv23. Starts at highest TLS
|
||||
* protocol version supported by native wolfSSL then downgrades to
|
||||
* minimum native downgrade version. */
|
||||
if(ctxAttr.version == TLS_VERSION.TLSv1 ||
|
||||
ctxAttr.version == TLS_VERSION.TLSv1_1 ||
|
||||
ctxAttr.version == TLS_VERSION.TLSv1_2 ||
|
||||
|
@ -83,19 +91,29 @@ public class WolfSSLContext extends SSLContextSpi {
|
|||
"Invalid SSL/TLS protocol version");
|
||||
}
|
||||
|
||||
/* Set SSLContext version. To be compatible with SunJSSE behavior,
|
||||
* the enabled protocols are less than or equal to the version
|
||||
* selected */
|
||||
switch (this.currentVersion) {
|
||||
case TLSv1:
|
||||
method = WolfSSL.TLSv1_Method();
|
||||
ctxAttr.noOptions = ctxAttr.noOptions |
|
||||
WolfSSL.SSL_OP_NO_TLSv1_1 | WolfSSL.SSL_OP_NO_TLSv1_2 |
|
||||
WolfSSL.SSL_OP_NO_TLSv1_3;
|
||||
WolfSSLDebug.log(getClass(), WolfSSLDebug.INFO,
|
||||
"creating WolfSSLContext with TLSv1");
|
||||
break;
|
||||
case TLSv1_1:
|
||||
method = WolfSSL.TLSv1_1_Method();
|
||||
ctxAttr.noOptions = ctxAttr.noOptions |
|
||||
WolfSSL.SSL_OP_NO_TLSv1_2 | WolfSSL.SSL_OP_NO_TLSv1_3;
|
||||
WolfSSLDebug.log(getClass(), WolfSSLDebug.INFO,
|
||||
"creating WolfSSLContext with TLSv1_1");
|
||||
break;
|
||||
case TLSv1_2:
|
||||
method = WolfSSL.TLSv1_2_Method();
|
||||
ctxAttr.noOptions = ctxAttr.noOptions |
|
||||
WolfSSL.SSL_OP_NO_TLSv1_3;
|
||||
WolfSSLDebug.log(getClass(), WolfSSLDebug.INFO,
|
||||
"creating WolfSSLContext with TLSv1_2");
|
||||
break;
|
||||
|
@ -130,15 +148,31 @@ public class WolfSSLContext extends SSLContextSpi {
|
|||
throw new IllegalArgumentException(e);
|
||||
}
|
||||
|
||||
/* auto-populate enabled ciphersuites with supported ones */
|
||||
if(ctxAttr.list != null && ctxAttr.list.length > 0) {
|
||||
params.setCipherSuites(ctxAttr.list);
|
||||
ciphersIana = ctxAttr.list;
|
||||
} else {
|
||||
params.setCipherSuites(WolfSSL.getCiphersIana());
|
||||
ciphersIana = WolfSSL.getCiphersIana();
|
||||
}
|
||||
|
||||
/* auto-populate enabled protocols with supported ones */
|
||||
params.setProtocols(this.getProtocolsMask(ctxAttr.noOptions));
|
||||
enforceKeySizeLimitations();
|
||||
|
||||
/* TODO: filter cipher suite list and protocols to conform to
|
||||
* limitations set by jdk.tls.disabledAlgorithms system property
|
||||
* if set */
|
||||
|
||||
/* Auto-populate enabled ciphersuites with supported ones */
|
||||
params.setCipherSuites(ciphersIana);
|
||||
|
||||
/* Auto-populate enabled protocols with supported ones. Protocols
|
||||
* which have been disabled via system property get filtered in
|
||||
* WolfSSLEngineHelper.sanitizeProtocols() */
|
||||
params.setProtocols(WolfSSLUtil.sanitizeProtocols(
|
||||
this.getProtocolsMask(ctxAttr.noOptions)));
|
||||
}
|
||||
|
||||
private void enforceKeySizeLimitations() {
|
||||
/* TODO: call WOLFSSL_CTX APIs to limit key sizes based on
|
||||
* jdk.tls.disabledAlgorithms settings */
|
||||
}
|
||||
|
||||
private void LoadTrustedRootCerts() {
|
||||
|
|
|
@ -23,53 +23,63 @@ package com.wolfssl.provider.jsse;
|
|||
import com.wolfssl.WolfSSL.TLS_VERSION;
|
||||
|
||||
/**
|
||||
* Base class is intended to give some customizing points.
|
||||
* Currently it is limited to be invoked from WolfSSLContext.Create
|
||||
* This class is intended to give some customization points to wolfJSSE
|
||||
* for users who want to hard-code certain limitations for wolfJSSE in terms
|
||||
* of protocol version support, cipher suite list, or native wolfSSL
|
||||
* SSL_NO_* type options.
|
||||
*
|
||||
* Most users will want to take other approaches to limiting these features,
|
||||
* as this approach will require modification of this class and a
|
||||
* recompilation/reinstallation of the wolfJSSE JAR file.
|
||||
*
|
||||
* Currently these limitations are enforced upon invocation of the
|
||||
* WolfSSLContext.init() method (createCtx()).
|
||||
*
|
||||
* @author wolfSSL
|
||||
*/
|
||||
public class WolfSSLCustomUser {
|
||||
/** SSL/TLS version */
|
||||
/** SSL/TLS version to be used with new SSLContext objects. */
|
||||
public TLS_VERSION version;
|
||||
/** String array of allowed cipher suites */
|
||||
/** String array of allowed cipher suites for new SSLContext objects */
|
||||
public String[] list;
|
||||
/** Mask of options to set for the associated WOLFSSL_CTX */
|
||||
/** Mask of options to set for the associated native WOLFSSL_CTX */
|
||||
public long noOptions;
|
||||
|
||||
/** Default WolfSSLCustomUser constructor */
|
||||
public WolfSSLCustomUser() { }
|
||||
|
||||
/**
|
||||
* callback for getting Context attributes before creating context,
|
||||
* TLS protocol and Cipher list
|
||||
* Factory method for getting SSLContext attributes before creating context,
|
||||
* TLS protocol and Cipher list. wolfJSSE calls this internally to get
|
||||
* values set below by the user, or passes defaults through from what
|
||||
* was otherwise going to be used by wolfJSSE when creating the SSLContext.
|
||||
*
|
||||
* WARNING: inappropriate code or use of this callback may cause
|
||||
* serious security issue.
|
||||
* WARNING: Inappropriate code or use of this feature may cause
|
||||
* serious security issues!
|
||||
*
|
||||
* @param version default version of TLS for refernce.
|
||||
* @param list default cipher list for refernce.
|
||||
* @param version Default version of TLS for reference.
|
||||
* @param list Default cipher list for reference.
|
||||
* @return version: TLS protocol version to the context. The value
|
||||
* has to be one compiled in.
|
||||
* list: Cipher list allowed to the context. list has to
|
||||
* contain subset of default cipher list. If it is
|
||||
* null, default list is applied.
|
||||
* needs to be one compiled into native wolfSSL.
|
||||
* list: Cipher list allowed for use in the SSLContext.
|
||||
* list needs to contain a subset of the default cipher
|
||||
* list. If it is null, default list is applied.
|
||||
*/
|
||||
public static WolfSSLCustomUser GetCtxAttributes(TLS_VERSION version,
|
||||
String[] list) {
|
||||
|
||||
WolfSSLCustomUser ctxAttr = new WolfSSLCustomUser();
|
||||
|
||||
/***
|
||||
custom code
|
||||
|
||||
/**
|
||||
Insert custom code here, and remove/modify defaults below.
|
||||
Example:
|
||||
ctxAttr.NoOptions = WolfSSL.SSL_OP_NO_TLSv1 | WolfSSL.SSL_OP_NO_TLSv1_3;
|
||||
|
||||
***/
|
||||
*/
|
||||
|
||||
ctxAttr.version = version;
|
||||
ctxAttr.list = list;
|
||||
ctxAttr.noOptions = 0;
|
||||
|
||||
return ctxAttr;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -24,11 +24,13 @@ import com.wolfssl.WolfSSL;
|
|||
import com.wolfssl.WolfSSLException;
|
||||
import com.wolfssl.WolfSSLSession;
|
||||
import java.util.Arrays;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.net.SocketTimeoutException;
|
||||
import javax.net.ssl.SSLException;
|
||||
import javax.net.ssl.X509TrustManager;
|
||||
import javax.net.ssl.SSLHandshakeException;
|
||||
import java.security.Security;
|
||||
|
||||
/**
|
||||
* This is a helper function to account for similar methods between SSLSocket
|
||||
|
@ -221,7 +223,7 @@ public class WolfSSLEngineHelper {
|
|||
}
|
||||
}
|
||||
|
||||
this.params.setProtocols(p);
|
||||
this.params.setProtocols(WolfSSLUtil.sanitizeProtocols(p));
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -230,16 +232,18 @@ public class WolfSSLEngineHelper {
|
|||
* @return String array of enabled SSL/TLS protocols
|
||||
*/
|
||||
protected String[] getProtocols() {
|
||||
return this.params.getProtocols();
|
||||
return WolfSSLUtil.sanitizeProtocols(this.params.getProtocols());
|
||||
}
|
||||
|
||||
/**
|
||||
* Get all supported SSL/TLS protocols in native wolfSSL library
|
||||
* Get all supported SSL/TLS protocols in native wolfSSL library,
|
||||
* which are also allowed by 'jdk.tls.client.protocols' or
|
||||
* 'jdk.tls.server.protocols' if set.
|
||||
*
|
||||
* @return String array of supported protocols
|
||||
*/
|
||||
protected String[] getAllProtocols() {
|
||||
return WolfSSL.getProtocols();
|
||||
return WolfSSLUtil.sanitizeProtocols(WolfSSL.getProtocols());
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -417,7 +421,9 @@ public class WolfSSLEngineHelper {
|
|||
}
|
||||
|
||||
/* sets the protocol to use with WOLFSSL connections */
|
||||
private void setLocalProtocol(String[] p) {
|
||||
private void setLocalProtocol(String[] p)
|
||||
throws SSLException {
|
||||
|
||||
int i;
|
||||
long mask = 0;
|
||||
boolean[] set = new boolean[5];
|
||||
|
@ -428,6 +434,10 @@ public class WolfSSLEngineHelper {
|
|||
return;
|
||||
}
|
||||
|
||||
if (p.length == 0) {
|
||||
throw new SSLException("No protocols enabled or available");
|
||||
}
|
||||
|
||||
for (i = 0; i < p.length; i++) {
|
||||
if (p[i].equals("TLSv1.3")) {
|
||||
set[0] = true;
|
||||
|
@ -655,9 +665,10 @@ public class WolfSSLEngineHelper {
|
|||
}
|
||||
}
|
||||
|
||||
private void setLocalParams() {
|
||||
private void setLocalParams() throws SSLException {
|
||||
this.setLocalCiphers(this.params.getCipherSuites());
|
||||
this.setLocalProtocol(this.params.getProtocols());
|
||||
this.setLocalProtocol(
|
||||
WolfSSLUtil.sanitizeProtocols(this.params.getProtocols()));
|
||||
this.setLocalAuth();
|
||||
this.setLocalServerNames();
|
||||
this.setLocalSessionTicket();
|
||||
|
|
|
@ -27,12 +27,16 @@ import org.junit.runner.RunWith;
|
|||
import org.junit.runners.JUnit4;
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Arrays;
|
||||
import java.util.ArrayList;
|
||||
|
||||
import com.wolfssl.WolfSSLException;
|
||||
import com.wolfssl.provider.jsse.WolfSSLContext;
|
||||
|
||||
import java.io.FileInputStream;
|
||||
import javax.net.SocketFactory;
|
||||
import javax.net.ssl.SSLSocket;
|
||||
import javax.net.ssl.SSLContext;
|
||||
import javax.net.ssl.SSLSocketFactory;
|
||||
import javax.net.ssl.KeyManagerFactory;
|
||||
|
@ -52,6 +56,7 @@ import java.security.KeyManagementException;
|
|||
import java.security.NoSuchProviderException;
|
||||
import java.security.NoSuchAlgorithmException;
|
||||
|
||||
import com.wolfssl.WolfSSL;
|
||||
import com.wolfssl.provider.jsse.WolfSSLProvider;
|
||||
|
||||
public class WolfSSLContextTest {
|
||||
|
@ -61,9 +66,10 @@ public class WolfSSLContextTest {
|
|||
private static final String ctxProvider = "wolfJSSE";
|
||||
|
||||
private static String[] allProtocols = {
|
||||
"TLSV1",
|
||||
"TLSV1.1",
|
||||
"TLSV1.2",
|
||||
"TLSv1",
|
||||
"TLSv1.1",
|
||||
"TLSv1.2",
|
||||
"TLSv1.3",
|
||||
"TLS"
|
||||
};
|
||||
|
||||
|
@ -95,6 +101,13 @@ public class WolfSSLContextTest {
|
|||
try {
|
||||
SSLContext ctx = SSLContext.getInstance(allProtocols[i],
|
||||
ctxProvider);
|
||||
|
||||
if (WolfSSLTestFactory.securityPropContains(
|
||||
"jdk.tls.disabledAlgorithms", allProtocols[i])) {
|
||||
/* skip adding, protocol has been disabled */
|
||||
continue;
|
||||
}
|
||||
|
||||
enabledProtocols.add(allProtocols[i]);
|
||||
|
||||
} catch (NoSuchAlgorithmException e) {
|
||||
|
@ -388,5 +401,266 @@ public class WolfSSLContextTest {
|
|||
|
||||
System.out.println("\t... passed");
|
||||
}
|
||||
|
||||
/* Returns ArrayList of expected default SSLcontext protocols, assuming
|
||||
* none have been disabled at the system level via system/security
|
||||
* properties. The order of items in the list should also match expected
|
||||
* order. */
|
||||
private ArrayList<String> buildExpectedDefaultProtocolList(
|
||||
String ctxProtocol) {
|
||||
|
||||
ArrayList<String> expected = new ArrayList<String>();
|
||||
|
||||
/* already sorted highest to lowest (ie TLSv1.3, ..., TLSv1.1) */
|
||||
List enabledNativeProtocols = Arrays.asList(WolfSSL.getProtocols());
|
||||
|
||||
if (ctxProtocol == "TLS") {
|
||||
if (enabledNativeProtocols.contains("TLSv1.3")) {
|
||||
expected.add("TLSv1.3");
|
||||
}
|
||||
if (enabledNativeProtocols.contains("TLSv1.2")) {
|
||||
expected.add("TLSv1.2");
|
||||
}
|
||||
if (enabledNativeProtocols.contains("TLSv1.1")) {
|
||||
expected.add("TLSv1.1");
|
||||
}
|
||||
if (enabledNativeProtocols.contains("TLSv1")) {
|
||||
expected.add("TLSv1");
|
||||
}
|
||||
}
|
||||
|
||||
else if (ctxProtocol == "TLSv1.3") {
|
||||
if (enabledNativeProtocols.contains("TLSv1.3")) {
|
||||
expected.add("TLSv1.3");
|
||||
}
|
||||
if (enabledNativeProtocols.contains("TLSv1.2")) {
|
||||
expected.add("TLSv1.2");
|
||||
}
|
||||
if (enabledNativeProtocols.contains("TLSv1.1")) {
|
||||
expected.add("TLSv1.1");
|
||||
}
|
||||
if (enabledNativeProtocols.contains("TLSv1")) {
|
||||
expected.add("TLSv1");
|
||||
}
|
||||
}
|
||||
|
||||
else if (ctxProtocol == "TLSv1.2") {
|
||||
if (enabledNativeProtocols.contains("TLSv1.2")) {
|
||||
expected.add("TLSv1.2");
|
||||
}
|
||||
if (enabledNativeProtocols.contains("TLSv1.1")) {
|
||||
expected.add("TLSv1.1");
|
||||
}
|
||||
if (enabledNativeProtocols.contains("TLSv1")) {
|
||||
expected.add("TLSv1");
|
||||
}
|
||||
}
|
||||
|
||||
else if (ctxProtocol == "TLSv1.1") {
|
||||
if (enabledNativeProtocols.contains("TLSv1.1")) {
|
||||
expected.add("TLSv1.1");
|
||||
}
|
||||
if (enabledNativeProtocols.contains("TLSv1")) {
|
||||
expected.add("TLSv1");
|
||||
}
|
||||
}
|
||||
|
||||
else if (ctxProtocol == "TLSv1") {
|
||||
if (enabledNativeProtocols.contains("TLSv1")) {
|
||||
expected.add("TLSv1");
|
||||
}
|
||||
}
|
||||
|
||||
return expected;
|
||||
}
|
||||
|
||||
/* Tests that disabling protocols using the system property
|
||||
* 'jdk.tls.disabledAlgorithms' works as expected.
|
||||
*/
|
||||
@Test
|
||||
public void testJdkTlsDisabledAlgorithms() throws NoSuchProviderException,
|
||||
NoSuchAlgorithmException, IllegalStateException,
|
||||
KeyManagementException, IOException {
|
||||
|
||||
SSLContext ctx = null;
|
||||
SocketFactory sf = null;
|
||||
SSLSocket sock = null;
|
||||
String[] defaultSSLContextProtocols = null;
|
||||
ArrayList<String> expectedList = null;
|
||||
|
||||
System.out.print("\tjdk.tls.disabledAlgorithms");
|
||||
|
||||
List enabledNativeProtocols = Arrays.asList(WolfSSL.getProtocols());
|
||||
if (enabledNativeProtocols == null) {
|
||||
System.out.println("\t... failed");
|
||||
fail("WolfSSL.getProtocols() returned null");
|
||||
}
|
||||
|
||||
/* Save original property value to reset after test */
|
||||
String originalProperty =
|
||||
Security.getProperty("jdk.tls.disabledAlgorithms");
|
||||
|
||||
/* Test with no protocols disabled */
|
||||
Security.setProperty("jdk.tls.disabledAlgorithms", "");
|
||||
for (int i = 0; i < allProtocols.length; i++) {
|
||||
|
||||
if (!enabledNativeProtocols.contains(allProtocols[i])) {
|
||||
/* protocol not available in native library, skip */
|
||||
continue;
|
||||
}
|
||||
|
||||
ctx = SSLContext.getInstance(allProtocols[i]);
|
||||
ctx.init(null, null, null);
|
||||
|
||||
expectedList = buildExpectedDefaultProtocolList(allProtocols[i]);
|
||||
defaultSSLContextProtocols =
|
||||
ctx.getDefaultSSLParameters().getProtocols();
|
||||
|
||||
if (!Arrays.equals(defaultSSLContextProtocols,
|
||||
expectedList.toArray(new String[expectedList.size()]))) {
|
||||
System.out.print("\t... failed");
|
||||
fail("Default SSLContext protocol list did not " +
|
||||
"match expected");
|
||||
}
|
||||
|
||||
/* Also test SSLSocket.getEnabledProtocols() */
|
||||
sf = ctx.getSocketFactory();
|
||||
sock = (SSLSocket)sf.createSocket();
|
||||
String[] sockEnabledProtocols = sock.getEnabledProtocols();
|
||||
|
||||
if (!Arrays.equals(sockEnabledProtocols,
|
||||
expectedList.toArray(new String[expectedList.size()]))) {
|
||||
System.out.print("\t... failed");
|
||||
fail("Default SSLSocket protocol list did not " +
|
||||
"match expected");
|
||||
}
|
||||
}
|
||||
|
||||
/* Test with each allProtocol disabled individually */
|
||||
for (int i = 0; i < allProtocols.length; i++) {
|
||||
Security.setProperty("jdk.tls.disabledAlgorithms", allProtocols[i]);
|
||||
for (int j = 0; j < allProtocols.length; j++) {
|
||||
|
||||
if (!enabledNativeProtocols.contains(allProtocols[j])) {
|
||||
/* protocol not available in native library, skip */
|
||||
continue;
|
||||
}
|
||||
|
||||
ctx = SSLContext.getInstance(allProtocols[j]);
|
||||
ctx.init(null, null, null);
|
||||
|
||||
expectedList =
|
||||
buildExpectedDefaultProtocolList(allProtocols[j]);
|
||||
/* remove protocol under test */
|
||||
expectedList.remove(allProtocols[i]);
|
||||
defaultSSLContextProtocols =
|
||||
ctx.getDefaultSSLParameters().getProtocols();
|
||||
|
||||
if (!Arrays.equals(defaultSSLContextProtocols,
|
||||
expectedList.toArray(
|
||||
new String[expectedList.size()]))) {
|
||||
System.out.print("\t... failed");
|
||||
fail("Default SSLContext protocol list did not " +
|
||||
"match expected");
|
||||
}
|
||||
|
||||
/* Also test SSLSocket.getEnabledProtocols() */
|
||||
sf = ctx.getSocketFactory();
|
||||
sock = (SSLSocket)sf.createSocket();
|
||||
String[] sockEnabledProtocols = sock.getEnabledProtocols();
|
||||
|
||||
if (!Arrays.equals(sockEnabledProtocols,
|
||||
expectedList.toArray(
|
||||
new String[expectedList.size()]))) {
|
||||
System.out.print("\t... failed");
|
||||
fail("Default SSLSocket protocol list did not " +
|
||||
"match expected");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Test with TLSv1, TLSv1.1 protocols disabled */
|
||||
Security.setProperty("jdk.tls.disabledAlgorithms", "TLSv1, TLSv1.1");
|
||||
for (int i = 0; i < allProtocols.length; i++) {
|
||||
|
||||
if (!enabledNativeProtocols.contains(allProtocols[i])) {
|
||||
/* protocol not available in native library, skip */
|
||||
continue;
|
||||
}
|
||||
|
||||
ctx = SSLContext.getInstance(allProtocols[i]);
|
||||
ctx.init(null, null, null);
|
||||
|
||||
expectedList = buildExpectedDefaultProtocolList(allProtocols[i]);
|
||||
expectedList.remove("TLSv1");
|
||||
expectedList.remove("TLSv1.1");
|
||||
defaultSSLContextProtocols =
|
||||
ctx.getDefaultSSLParameters().getProtocols();
|
||||
|
||||
if (!Arrays.equals(defaultSSLContextProtocols,
|
||||
expectedList.toArray(new String[expectedList.size()]))) {
|
||||
System.out.print("\t... failed");
|
||||
fail("Default SSLContext protocol list did not " +
|
||||
"match expected");
|
||||
}
|
||||
|
||||
/* Also test SSLSocket.getEnabledProtocols() */
|
||||
sf = ctx.getSocketFactory();
|
||||
sock = (SSLSocket)sf.createSocket();
|
||||
String[] sockEnabledProtocols = sock.getEnabledProtocols();
|
||||
|
||||
if (!Arrays.equals(sockEnabledProtocols,
|
||||
expectedList.toArray(
|
||||
new String[expectedList.size()]))) {
|
||||
System.out.print("\t... failed");
|
||||
fail("Default SSLSocket protocol list did not " +
|
||||
"match expected");
|
||||
}
|
||||
}
|
||||
|
||||
/* Test with TLSv1.1, TLSv1.2 protocols disabled */
|
||||
Security.setProperty("jdk.tls.disabledAlgorithms", "TLSv1.1, TLSv1.2");
|
||||
for (int i = 0; i < allProtocols.length; i++) {
|
||||
|
||||
if (!enabledNativeProtocols.contains(allProtocols[i])) {
|
||||
/* protocol not available in native library, skip */
|
||||
continue;
|
||||
}
|
||||
|
||||
ctx = SSLContext.getInstance(allProtocols[i]);
|
||||
ctx.init(null, null, null);
|
||||
|
||||
expectedList = buildExpectedDefaultProtocolList(allProtocols[i]);
|
||||
expectedList.remove("TLSv1.1");
|
||||
expectedList.remove("TLSv1.2");
|
||||
defaultSSLContextProtocols =
|
||||
ctx.getDefaultSSLParameters().getProtocols();
|
||||
|
||||
if (!Arrays.equals(defaultSSLContextProtocols,
|
||||
expectedList.toArray(new String[expectedList.size()]))) {
|
||||
System.out.print("\t... failed");
|
||||
fail("Default SSLContext protocol list did not " +
|
||||
"match expected");
|
||||
}
|
||||
|
||||
/* Also test SSLSocket.getEnabledProtocols() */
|
||||
sf = ctx.getSocketFactory();
|
||||
sock = (SSLSocket)sf.createSocket();
|
||||
String[] sockEnabledProtocols = sock.getEnabledProtocols();
|
||||
|
||||
if (!Arrays.equals(sockEnabledProtocols,
|
||||
expectedList.toArray(
|
||||
new String[expectedList.size()]))) {
|
||||
System.out.print("\t... failed");
|
||||
fail("Default SSLSocket protocol list did not " +
|
||||
"match expected");
|
||||
}
|
||||
}
|
||||
|
||||
/* Restore original system property value */
|
||||
Security.setProperty("jdk.tls.disabledAlgorithms", originalProperty);
|
||||
|
||||
System.out.println("\t... passed");
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -396,6 +396,50 @@ public class WolfSSLSocketTest {
|
|||
System.out.println("\t... failed");
|
||||
fail("SSLSocket.setEnabledProtocols() failed");
|
||||
}
|
||||
|
||||
/* test that removing protocols with jdk.tls.disabledAlgorithms
|
||||
* behaves as expected */
|
||||
String originalProperty =
|
||||
Security.getProperty("jdk.tls.disabledAlgorithms");
|
||||
|
||||
try {
|
||||
Security.setProperty("jdk.tls.disabledAlgorithms", "TLSv1");
|
||||
s.setEnabledProtocols(new String[] {"TLSv1"});
|
||||
System.out.println("\t\t... failed");
|
||||
fail("SSLSocket.setEnabledProtocols() failed");
|
||||
} catch (IllegalArgumentException e) {
|
||||
/* expected */
|
||||
}
|
||||
|
||||
try {
|
||||
Security.setProperty("jdk.tls.disabledAlgorithms", "TLSv1.1");
|
||||
s.setEnabledProtocols(new String[] {"TLSv1.1"});
|
||||
System.out.println("\t\t... failed");
|
||||
fail("SSLSocket.setEnabledProtocols() failed");
|
||||
} catch (IllegalArgumentException e) {
|
||||
/* expected */
|
||||
}
|
||||
|
||||
try {
|
||||
Security.setProperty("jdk.tls.disabledAlgorithms", "TLSv1.2");
|
||||
s.setEnabledProtocols(new String[] {"TLSv1.2"});
|
||||
System.out.println("\t\t... failed");
|
||||
fail("SSLSocket.setEnabledProtocols() failed");
|
||||
} catch (IllegalArgumentException e) {
|
||||
/* expected */
|
||||
}
|
||||
|
||||
try {
|
||||
Security.setProperty("jdk.tls.disabledAlgorithms", "TLSv1.3");
|
||||
s.setEnabledProtocols(new String[] {"TLSv1.3"});
|
||||
System.out.println("\t\t... failed");
|
||||
fail("SSLSocket.setEnabledProtocols() failed");
|
||||
} catch (IllegalArgumentException e) {
|
||||
/* expected */
|
||||
}
|
||||
|
||||
/* restore original property value */
|
||||
System.setProperty("jdk.tls.disabledAlgorithms", originalProperty);
|
||||
}
|
||||
|
||||
System.out.println("\t... passed");
|
||||
|
@ -1206,7 +1250,9 @@ public class WolfSSLSocketTest {
|
|||
System.out.print("\tTLS 1.0 connection test");
|
||||
|
||||
/* skip if TLS 1.0 is not compiled in at native level */
|
||||
if (WolfSSL.TLSv1Enabled() == false) {
|
||||
if (WolfSSL.TLSv1Enabled() == false ||
|
||||
WolfSSLTestFactory.securityPropContains(
|
||||
"jdk.tls.disabledAlgorithms", "TLS")) {
|
||||
System.out.println("\t\t... skipped");
|
||||
return;
|
||||
}
|
||||
|
@ -1220,7 +1266,9 @@ public class WolfSSLSocketTest {
|
|||
System.out.print("\tTLS 1.1 connection test");
|
||||
|
||||
/* skip if TLS 1.1 is not compiled in at native level */
|
||||
if (WolfSSL.TLSv11Enabled() == false) {
|
||||
if (WolfSSL.TLSv11Enabled() == false ||
|
||||
WolfSSLTestFactory.securityPropContains(
|
||||
"jdk.tls.disabledAlgorithms", "TLSv1.1")) {
|
||||
System.out.println("\t\t... skipped");
|
||||
return;
|
||||
}
|
||||
|
@ -1234,7 +1282,9 @@ public class WolfSSLSocketTest {
|
|||
System.out.print("\tTLS 1.2 connection test");
|
||||
|
||||
/* skip if TLS 1.2 is not compiled in at native level */
|
||||
if (WolfSSL.TLSv12Enabled() == false) {
|
||||
if (WolfSSL.TLSv12Enabled() == false ||
|
||||
WolfSSLTestFactory.securityPropContains(
|
||||
"jdk.tls.disabledAlgorithms", "TLSv1.2")) {
|
||||
System.out.println("\t\t... skipped");
|
||||
return;
|
||||
}
|
||||
|
@ -1248,7 +1298,9 @@ public class WolfSSLSocketTest {
|
|||
System.out.print("\tTLS 1.3 connection test");
|
||||
|
||||
/* skip if TLS 1.3 is not compiled in at native level */
|
||||
if (WolfSSL.TLSv13Enabled() == false) {
|
||||
if (WolfSSL.TLSv13Enabled() == false ||
|
||||
WolfSSLTestFactory.securityPropContains(
|
||||
"jdk.tls.disabledAlgorithms", "TLSv1.3")) {
|
||||
System.out.println("\t\t... skipped");
|
||||
return;
|
||||
}
|
||||
|
@ -1301,6 +1353,60 @@ public class WolfSSLSocketTest {
|
|||
System.out.println("\t\t... passed");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testConnectionWithDisabledAlgorithms() throws Exception {
|
||||
|
||||
System.out.print("\tConnection with disabled algorithms");
|
||||
|
||||
/* create new CTX */
|
||||
this.ctx = tf.createSSLContext("TLS", ctxProvider);
|
||||
|
||||
/* save current system property value */
|
||||
String originalProperty =
|
||||
Security.getProperty("jdk.tls.disabledAlgorithms");
|
||||
|
||||
for (int i = 0; i < enabledProtocols.size(); i++) {
|
||||
|
||||
/* skip generic "TLS" */
|
||||
if (enabledProtocols.get(i).equals("TLS")) {
|
||||
continue;
|
||||
}
|
||||
|
||||
/* create SSLServerSocket first to get ephemeral port */
|
||||
SSLServerSocket ss = (SSLServerSocket)ctx.getServerSocketFactory()
|
||||
.createServerSocket(0);
|
||||
|
||||
SSLSocket cs = (SSLSocket)ctx.getSocketFactory().createSocket();
|
||||
/* restrict to single protocol that is being disabled */
|
||||
cs.setEnabledProtocols(new String[] {enabledProtocols.get(i)});
|
||||
|
||||
/* disable protocol after socket setup, should fail connection */
|
||||
Security.setProperty("jdk.tls.disabledAlgorithms",
|
||||
enabledProtocols.get(i));
|
||||
|
||||
/* don't need server since should throw exception before */
|
||||
cs.connect(new InetSocketAddress(ss.getLocalPort()));
|
||||
|
||||
try {
|
||||
cs.startHandshake();
|
||||
System.out.println("\t... failed");
|
||||
fail();
|
||||
|
||||
} catch (SSLException e) {
|
||||
/* expected, should fail with
|
||||
* "No protocols enabled or available" */
|
||||
}
|
||||
|
||||
cs.close();
|
||||
ss.close();
|
||||
}
|
||||
|
||||
/* restore system property */
|
||||
Security.setProperty("jdk.tls.disabledAlgorithms", originalProperty);
|
||||
|
||||
System.out.println("\t... passed");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSessionResumption() throws Exception {
|
||||
|
||||
|
|
|
@ -28,6 +28,7 @@ import java.io.IOException;
|
|||
import java.io.InputStream;
|
||||
import java.nio.ByteBuffer;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.security.Security;
|
||||
import java.security.KeyManagementException;
|
||||
import java.security.KeyStore;
|
||||
import java.security.KeyStoreException;
|
||||
|
@ -36,6 +37,8 @@ import java.security.NoSuchProviderException;
|
|||
import java.security.UnrecoverableKeyException;
|
||||
import java.security.cert.CertificateEncodingException;
|
||||
import java.security.cert.CertificateException;
|
||||
import java.util.List;
|
||||
import java.util.Arrays;
|
||||
import java.util.Enumeration;
|
||||
import java.util.logging.Level;
|
||||
import java.util.logging.Logger;
|
||||
|
@ -787,4 +790,34 @@ class WolfSSLTestFactory {
|
|||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if Security property contains a specific value.
|
||||
*
|
||||
* @param prop System Security property to check
|
||||
* @param needle String value to search for in Security property
|
||||
*
|
||||
* @return true if found, otherwise false
|
||||
*/
|
||||
protected static boolean securityPropContains(String prop, String needle) {
|
||||
|
||||
String secProp = null;
|
||||
List propList = null;
|
||||
|
||||
if (prop == null || needle == null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
/* make sure protocol has not been disabled at system level */
|
||||
secProp = Security.getProperty(prop);
|
||||
/* Remove spaces after commas, split into List */
|
||||
secProp = secProp.replaceAll(", ",",");
|
||||
propList = Arrays.asList(secProp.split(","));
|
||||
|
||||
if (propList.contains(needle)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue