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 */
|
/* Get available wolfSSL cipher suites in IANA format */
|
||||||
ciphersIana = WolfSSL.getCiphersAvailableIana(this.currentVersion);
|
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
|
WolfSSLCustomUser ctxAttr = WolfSSLCustomUser.GetCtxAttributes
|
||||||
(this.currentVersion, ciphersIana);
|
(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 ||
|
if(ctxAttr.version == TLS_VERSION.TLSv1 ||
|
||||||
ctxAttr.version == TLS_VERSION.TLSv1_1 ||
|
ctxAttr.version == TLS_VERSION.TLSv1_1 ||
|
||||||
ctxAttr.version == TLS_VERSION.TLSv1_2 ||
|
ctxAttr.version == TLS_VERSION.TLSv1_2 ||
|
||||||
|
@ -83,19 +91,29 @@ public class WolfSSLContext extends SSLContextSpi {
|
||||||
"Invalid SSL/TLS protocol version");
|
"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) {
|
switch (this.currentVersion) {
|
||||||
case TLSv1:
|
case TLSv1:
|
||||||
method = WolfSSL.TLSv1_Method();
|
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,
|
WolfSSLDebug.log(getClass(), WolfSSLDebug.INFO,
|
||||||
"creating WolfSSLContext with TLSv1");
|
"creating WolfSSLContext with TLSv1");
|
||||||
break;
|
break;
|
||||||
case TLSv1_1:
|
case TLSv1_1:
|
||||||
method = WolfSSL.TLSv1_1_Method();
|
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,
|
WolfSSLDebug.log(getClass(), WolfSSLDebug.INFO,
|
||||||
"creating WolfSSLContext with TLSv1_1");
|
"creating WolfSSLContext with TLSv1_1");
|
||||||
break;
|
break;
|
||||||
case TLSv1_2:
|
case TLSv1_2:
|
||||||
method = WolfSSL.TLSv1_2_Method();
|
method = WolfSSL.TLSv1_2_Method();
|
||||||
|
ctxAttr.noOptions = ctxAttr.noOptions |
|
||||||
|
WolfSSL.SSL_OP_NO_TLSv1_3;
|
||||||
WolfSSLDebug.log(getClass(), WolfSSLDebug.INFO,
|
WolfSSLDebug.log(getClass(), WolfSSLDebug.INFO,
|
||||||
"creating WolfSSLContext with TLSv1_2");
|
"creating WolfSSLContext with TLSv1_2");
|
||||||
break;
|
break;
|
||||||
|
@ -130,15 +148,31 @@ public class WolfSSLContext extends SSLContextSpi {
|
||||||
throw new IllegalArgumentException(e);
|
throw new IllegalArgumentException(e);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* auto-populate enabled ciphersuites with supported ones */
|
|
||||||
if(ctxAttr.list != null && ctxAttr.list.length > 0) {
|
if(ctxAttr.list != null && ctxAttr.list.length > 0) {
|
||||||
params.setCipherSuites(ctxAttr.list);
|
ciphersIana = ctxAttr.list;
|
||||||
} else {
|
} else {
|
||||||
params.setCipherSuites(WolfSSL.getCiphersIana());
|
ciphersIana = WolfSSL.getCiphersIana();
|
||||||
}
|
}
|
||||||
|
|
||||||
/* auto-populate enabled protocols with supported ones */
|
enforceKeySizeLimitations();
|
||||||
params.setProtocols(this.getProtocolsMask(ctxAttr.noOptions));
|
|
||||||
|
/* 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() {
|
private void LoadTrustedRootCerts() {
|
||||||
|
|
|
@ -23,53 +23,63 @@ package com.wolfssl.provider.jsse;
|
||||||
import com.wolfssl.WolfSSL.TLS_VERSION;
|
import com.wolfssl.WolfSSL.TLS_VERSION;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Base class is intended to give some customizing points.
|
* This class is intended to give some customization points to wolfJSSE
|
||||||
* Currently it is limited to be invoked from WolfSSLContext.Create
|
* 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
|
* @author wolfSSL
|
||||||
*/
|
*/
|
||||||
public class WolfSSLCustomUser {
|
public class WolfSSLCustomUser {
|
||||||
/** SSL/TLS version */
|
/** SSL/TLS version to be used with new SSLContext objects. */
|
||||||
public TLS_VERSION version;
|
public TLS_VERSION version;
|
||||||
/** String array of allowed cipher suites */
|
/** String array of allowed cipher suites for new SSLContext objects */
|
||||||
public String[] list;
|
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;
|
public long noOptions;
|
||||||
|
|
||||||
/** Default WolfSSLCustomUser constructor */
|
/** Default WolfSSLCustomUser constructor */
|
||||||
public WolfSSLCustomUser() { }
|
public WolfSSLCustomUser() { }
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* callback for getting Context attributes before creating context,
|
* Factory method for getting SSLContext attributes before creating context,
|
||||||
* TLS protocol and Cipher list
|
* 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
|
* WARNING: Inappropriate code or use of this feature may cause
|
||||||
* serious security issue.
|
* serious security issues!
|
||||||
*
|
*
|
||||||
* @param version default version of TLS for refernce.
|
* @param version Default version of TLS for reference.
|
||||||
* @param list default cipher list for refernce.
|
* @param list Default cipher list for reference.
|
||||||
* @return version: TLS protocol version to the context. The value
|
* @return version: TLS protocol version to the context. The value
|
||||||
* has to be one compiled in.
|
* needs to be one compiled into native wolfSSL.
|
||||||
* list: Cipher list allowed to the context. list has to
|
* list: Cipher list allowed for use in the SSLContext.
|
||||||
* contain subset of default cipher list. If it is
|
* list needs to contain a subset of the default cipher
|
||||||
* null, default list is applied.
|
* list. If it is null, default list is applied.
|
||||||
*/
|
*/
|
||||||
public static WolfSSLCustomUser GetCtxAttributes(TLS_VERSION version,
|
public static WolfSSLCustomUser GetCtxAttributes(TLS_VERSION version,
|
||||||
String[] list) {
|
String[] list) {
|
||||||
|
|
||||||
WolfSSLCustomUser ctxAttr = new WolfSSLCustomUser();
|
WolfSSLCustomUser ctxAttr = new WolfSSLCustomUser();
|
||||||
|
|
||||||
/***
|
/**
|
||||||
custom code
|
Insert custom code here, and remove/modify defaults below.
|
||||||
|
|
||||||
Example:
|
Example:
|
||||||
ctxAttr.NoOptions = WolfSSL.SSL_OP_NO_TLSv1 | WolfSSL.SSL_OP_NO_TLSv1_3;
|
ctxAttr.NoOptions = WolfSSL.SSL_OP_NO_TLSv1 | WolfSSL.SSL_OP_NO_TLSv1_3;
|
||||||
|
*/
|
||||||
***/
|
|
||||||
|
|
||||||
ctxAttr.version = version;
|
ctxAttr.version = version;
|
||||||
ctxAttr.list = list;
|
ctxAttr.list = list;
|
||||||
ctxAttr.noOptions = 0;
|
ctxAttr.noOptions = 0;
|
||||||
|
|
||||||
return ctxAttr;
|
return ctxAttr;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -24,11 +24,13 @@ import com.wolfssl.WolfSSL;
|
||||||
import com.wolfssl.WolfSSLException;
|
import com.wolfssl.WolfSSLException;
|
||||||
import com.wolfssl.WolfSSLSession;
|
import com.wolfssl.WolfSSLSession;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.net.SocketTimeoutException;
|
import java.net.SocketTimeoutException;
|
||||||
import javax.net.ssl.SSLException;
|
import javax.net.ssl.SSLException;
|
||||||
import javax.net.ssl.X509TrustManager;
|
import javax.net.ssl.X509TrustManager;
|
||||||
import javax.net.ssl.SSLHandshakeException;
|
import javax.net.ssl.SSLHandshakeException;
|
||||||
|
import java.security.Security;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This is a helper function to account for similar methods between SSLSocket
|
* 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
|
* @return String array of enabled SSL/TLS protocols
|
||||||
*/
|
*/
|
||||||
protected String[] getProtocols() {
|
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
|
* @return String array of supported protocols
|
||||||
*/
|
*/
|
||||||
protected String[] getAllProtocols() {
|
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 */
|
/* sets the protocol to use with WOLFSSL connections */
|
||||||
private void setLocalProtocol(String[] p) {
|
private void setLocalProtocol(String[] p)
|
||||||
|
throws SSLException {
|
||||||
|
|
||||||
int i;
|
int i;
|
||||||
long mask = 0;
|
long mask = 0;
|
||||||
boolean[] set = new boolean[5];
|
boolean[] set = new boolean[5];
|
||||||
|
@ -428,6 +434,10 @@ public class WolfSSLEngineHelper {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (p.length == 0) {
|
||||||
|
throw new SSLException("No protocols enabled or available");
|
||||||
|
}
|
||||||
|
|
||||||
for (i = 0; i < p.length; i++) {
|
for (i = 0; i < p.length; i++) {
|
||||||
if (p[i].equals("TLSv1.3")) {
|
if (p[i].equals("TLSv1.3")) {
|
||||||
set[0] = true;
|
set[0] = true;
|
||||||
|
@ -655,9 +665,10 @@ public class WolfSSLEngineHelper {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void setLocalParams() {
|
private void setLocalParams() throws SSLException {
|
||||||
this.setLocalCiphers(this.params.getCipherSuites());
|
this.setLocalCiphers(this.params.getCipherSuites());
|
||||||
this.setLocalProtocol(this.params.getProtocols());
|
this.setLocalProtocol(
|
||||||
|
WolfSSLUtil.sanitizeProtocols(this.params.getProtocols()));
|
||||||
this.setLocalAuth();
|
this.setLocalAuth();
|
||||||
this.setLocalServerNames();
|
this.setLocalServerNames();
|
||||||
this.setLocalSessionTicket();
|
this.setLocalSessionTicket();
|
||||||
|
|
|
@ -27,12 +27,16 @@ import org.junit.runner.RunWith;
|
||||||
import org.junit.runners.JUnit4;
|
import org.junit.runners.JUnit4;
|
||||||
import static org.junit.Assert.*;
|
import static org.junit.Assert.*;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Arrays;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
|
|
||||||
import com.wolfssl.WolfSSLException;
|
import com.wolfssl.WolfSSLException;
|
||||||
import com.wolfssl.provider.jsse.WolfSSLContext;
|
import com.wolfssl.provider.jsse.WolfSSLContext;
|
||||||
|
|
||||||
import java.io.FileInputStream;
|
import java.io.FileInputStream;
|
||||||
|
import javax.net.SocketFactory;
|
||||||
|
import javax.net.ssl.SSLSocket;
|
||||||
import javax.net.ssl.SSLContext;
|
import javax.net.ssl.SSLContext;
|
||||||
import javax.net.ssl.SSLSocketFactory;
|
import javax.net.ssl.SSLSocketFactory;
|
||||||
import javax.net.ssl.KeyManagerFactory;
|
import javax.net.ssl.KeyManagerFactory;
|
||||||
|
@ -52,6 +56,7 @@ import java.security.KeyManagementException;
|
||||||
import java.security.NoSuchProviderException;
|
import java.security.NoSuchProviderException;
|
||||||
import java.security.NoSuchAlgorithmException;
|
import java.security.NoSuchAlgorithmException;
|
||||||
|
|
||||||
|
import com.wolfssl.WolfSSL;
|
||||||
import com.wolfssl.provider.jsse.WolfSSLProvider;
|
import com.wolfssl.provider.jsse.WolfSSLProvider;
|
||||||
|
|
||||||
public class WolfSSLContextTest {
|
public class WolfSSLContextTest {
|
||||||
|
@ -61,9 +66,10 @@ public class WolfSSLContextTest {
|
||||||
private static final String ctxProvider = "wolfJSSE";
|
private static final String ctxProvider = "wolfJSSE";
|
||||||
|
|
||||||
private static String[] allProtocols = {
|
private static String[] allProtocols = {
|
||||||
"TLSV1",
|
"TLSv1",
|
||||||
"TLSV1.1",
|
"TLSv1.1",
|
||||||
"TLSV1.2",
|
"TLSv1.2",
|
||||||
|
"TLSv1.3",
|
||||||
"TLS"
|
"TLS"
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -95,6 +101,13 @@ public class WolfSSLContextTest {
|
||||||
try {
|
try {
|
||||||
SSLContext ctx = SSLContext.getInstance(allProtocols[i],
|
SSLContext ctx = SSLContext.getInstance(allProtocols[i],
|
||||||
ctxProvider);
|
ctxProvider);
|
||||||
|
|
||||||
|
if (WolfSSLTestFactory.securityPropContains(
|
||||||
|
"jdk.tls.disabledAlgorithms", allProtocols[i])) {
|
||||||
|
/* skip adding, protocol has been disabled */
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
enabledProtocols.add(allProtocols[i]);
|
enabledProtocols.add(allProtocols[i]);
|
||||||
|
|
||||||
} catch (NoSuchAlgorithmException e) {
|
} catch (NoSuchAlgorithmException e) {
|
||||||
|
@ -388,5 +401,266 @@ public class WolfSSLContextTest {
|
||||||
|
|
||||||
System.out.println("\t... passed");
|
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");
|
System.out.println("\t... failed");
|
||||||
fail("SSLSocket.setEnabledProtocols() 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");
|
System.out.println("\t... passed");
|
||||||
|
@ -1206,7 +1250,9 @@ public class WolfSSLSocketTest {
|
||||||
System.out.print("\tTLS 1.0 connection test");
|
System.out.print("\tTLS 1.0 connection test");
|
||||||
|
|
||||||
/* skip if TLS 1.0 is not compiled in at native level */
|
/* 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");
|
System.out.println("\t\t... skipped");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -1220,7 +1266,9 @@ public class WolfSSLSocketTest {
|
||||||
System.out.print("\tTLS 1.1 connection test");
|
System.out.print("\tTLS 1.1 connection test");
|
||||||
|
|
||||||
/* skip if TLS 1.1 is not compiled in at native level */
|
/* 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");
|
System.out.println("\t\t... skipped");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -1234,7 +1282,9 @@ public class WolfSSLSocketTest {
|
||||||
System.out.print("\tTLS 1.2 connection test");
|
System.out.print("\tTLS 1.2 connection test");
|
||||||
|
|
||||||
/* skip if TLS 1.2 is not compiled in at native level */
|
/* 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");
|
System.out.println("\t\t... skipped");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -1248,7 +1298,9 @@ public class WolfSSLSocketTest {
|
||||||
System.out.print("\tTLS 1.3 connection test");
|
System.out.print("\tTLS 1.3 connection test");
|
||||||
|
|
||||||
/* skip if TLS 1.3 is not compiled in at native level */
|
/* 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");
|
System.out.println("\t\t... skipped");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -1301,6 +1353,60 @@ public class WolfSSLSocketTest {
|
||||||
System.out.println("\t\t... passed");
|
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
|
@Test
|
||||||
public void testSessionResumption() throws Exception {
|
public void testSessionResumption() throws Exception {
|
||||||
|
|
||||||
|
|
|
@ -28,6 +28,7 @@ import java.io.IOException;
|
||||||
import java.io.InputStream;
|
import java.io.InputStream;
|
||||||
import java.nio.ByteBuffer;
|
import java.nio.ByteBuffer;
|
||||||
import java.nio.charset.StandardCharsets;
|
import java.nio.charset.StandardCharsets;
|
||||||
|
import java.security.Security;
|
||||||
import java.security.KeyManagementException;
|
import java.security.KeyManagementException;
|
||||||
import java.security.KeyStore;
|
import java.security.KeyStore;
|
||||||
import java.security.KeyStoreException;
|
import java.security.KeyStoreException;
|
||||||
|
@ -36,6 +37,8 @@ import java.security.NoSuchProviderException;
|
||||||
import java.security.UnrecoverableKeyException;
|
import java.security.UnrecoverableKeyException;
|
||||||
import java.security.cert.CertificateEncodingException;
|
import java.security.cert.CertificateEncodingException;
|
||||||
import java.security.cert.CertificateException;
|
import java.security.cert.CertificateException;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Arrays;
|
||||||
import java.util.Enumeration;
|
import java.util.Enumeration;
|
||||||
import java.util.logging.Level;
|
import java.util.logging.Level;
|
||||||
import java.util.logging.Logger;
|
import java.util.logging.Logger;
|
||||||
|
@ -787,4 +790,34 @@ class WolfSSLTestFactory {
|
||||||
}
|
}
|
||||||
return false;
|
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