Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 11 additions & 0 deletions native/com_wolfssl_WolfSSLSession.c
Original file line number Diff line number Diff line change
Expand Up @@ -5874,6 +5874,17 @@ JNIEXPORT jint JNICALL Java_com_wolfssl_WolfSSLSession_hasTicket
#endif
}

JNIEXPORT jint JNICALL Java_com_wolfssl_WolfSSLSession_useClientSuites
(JNIEnv* jenv, jobject jcl, jlong sslPtr)
{
(void)jcl;
WOLFSSL* ssl = (WOLFSSL*)(uintptr_t)sslPtr;
if (jenv == NULL || ssl == NULL) {
return WOLFSSL_FAILURE;
}
return (jint)wolfSSL_UseClientSuites(ssl);
}

JNIEXPORT jint JNICALL Java_com_wolfssl_WolfSSLSession_interruptBlockedIO
(JNIEnv* jenv, jobject jcl, jlong sslPtr)
{
Expand Down
8 changes: 8 additions & 0 deletions native/com_wolfssl_WolfSSLSession.h

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

21 changes: 21 additions & 0 deletions src/java/com/wolfssl/WolfSSLSession.java
Original file line number Diff line number Diff line change
Expand Up @@ -693,6 +693,7 @@ private native int setTlsHmacInner(long ssl, byte[] inner, long sz,
private native int useSupportedCurve(long ssl, int name);
private native int disableExtendedMasterSecret(long ssl);
private native int hasTicket(long session);
private native int useClientSuites(long ssl);
private native int interruptBlockedIO(long ssl);
private native int getThreadsBlockedInPoll(long ssl);
private native int setMTU(long ssl, int mtu);
Expand Down Expand Up @@ -2476,6 +2477,26 @@ public long getTimeout() throws IllegalStateException {
}
}

/**
* Set SSL session to use Client cipher suite order preference.
* @return <code>SSL_SUCCESS</code> upon success. <code>
* SSL_FAILURE</code> upon failure.
* @throws IllegalStateException WolfSSLSession has been freed
*
*/
public int useClientSuites() throws IllegalStateException {

confirmObjectIsActive();

synchronized (sslLock) {
WolfSSLDebug.log(getClass(), WolfSSLDebug.Component.JNI,
WolfSSLDebug.INFO, this.sslPtr,
() -> "entered useClientSuites()");

return useClientSuites(this.sslPtr);
}
}

/**
* Sets the cipher suite list for a given SSL session.
* The ciphers in the list should be sorted in order of preference from
Expand Down
5 changes: 5 additions & 0 deletions src/java/com/wolfssl/provider/jsse/WolfSSLEngineHelper.java
Original file line number Diff line number Diff line change
Expand Up @@ -759,6 +759,11 @@ private void setLocalCiphers(String[] suites)
}
}

if (this.ssl.getSide() == WolfSSL.WOLFSSL_SERVER_END &&
!this.params.getUseCipherSuitesOrder()) {
this.ssl.useClientSuites();
}

} catch (IllegalStateException e) {
throw new IllegalArgumentException(e);
}
Expand Down
54 changes: 44 additions & 10 deletions src/java/com/wolfssl/provider/jsse/WolfSSLParametersHelper.java
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,8 @@ public class WolfSSLParametersHelper
private static Method setSNIMatchers = null;
private static Method getMaximumPacketSize = null;
private static Method setMaximumPacketSize = null;
private static Method setUseCipherSuitesOrder = null;
private static Method getUseCipherSuitesOrder = null;

/** Default WolfSSLParametersHelper constructor */
public WolfSSLParametersHelper() { }
Expand Down Expand Up @@ -91,6 +93,12 @@ public Object run() {
case "setMaximumPacketSize":
setMaximumPacketSize = m;
continue;
case "setUseCipherSuitesOrder":
setUseCipherSuitesOrder = m;
continue;
case "getUseCipherSuitesOrder":
getUseCipherSuitesOrder = m;
continue;
default:
continue;
}
Expand Down Expand Up @@ -134,7 +142,8 @@ protected static SSLParameters decoupleParams(WolfSSLParameters in) {
* do not existing in older JDKs. Since older JDKs will not have them,
* use Java reflection to detect availability in helper class. */
if (setServerNames != null || setApplicationProtocols != null ||
setEndpointIdentificationAlgorithm != null || setSNIMatchers != null) {
setEndpointIdentificationAlgorithm != null ||
setSNIMatchers != null || setUseCipherSuitesOrder != null) {

try {
/* load WolfSSLJDK8Helper at runtime, not compiled
Expand Down Expand Up @@ -167,6 +176,11 @@ protected static SSLParameters decoupleParams(WolfSSLParameters in) {
mth = cls.getDeclaredMethod("setSNIMatchers", paramList);
mth.invoke(obj, ret, setSNIMatchers, in);
}
if (setUseCipherSuitesOrder != null) {
mth = cls.getDeclaredMethod("setUseCipherSuitesOrder",
paramList);
mth.invoke(obj, ret, setUseCipherSuitesOrder, in);
}

} catch (Exception e) {
/* ignore, class not found */
Expand All @@ -193,15 +207,20 @@ protected static SSLParameters decoupleParams(WolfSSLParameters in) {
/* Not available, just ignore and continue */
}

try {
if (setUseCipherSuitesOrder != null) {
ret.setUseCipherSuitesOrder(in.getUseCipherSuitesOrder());
}
} catch (Exception e) {
/* Not available, just ignore and continue */
}

/* The following SSLParameters features are not yet supported
* by wolfJSSE (see Android API 23 note above). They are supported
* with newer versions of SSLParameters, but will need to be added
* conditionally to wolfJSSE when supported. */
/*ret.setAlgorithmConstraints(in.getAlgorithmConstraints());
ret.setEnableRetransmissions(in.getEnableRetransmissions());
ret.setMaximumPacketSize(in.getMaximumPacketSize());
ret.setSNIMatchers(in.getSNIMatchers());
ret.setUseCipherSuitesOrder(in.getUseCipherSuitesOrder());
*/

return ret;
Expand Down Expand Up @@ -242,7 +261,8 @@ protected static void importParams(SSLParameters in,
* do not existing in older JDKs. Since older JDKs will not have them,
* use Java reflection to detect availability in helper class. */
if (getServerNames != null || getApplicationProtocols != null ||
getEndpointIdentificationAlgorithm != null || getSNIMatchers != null) {
getEndpointIdentificationAlgorithm != null ||
getSNIMatchers != null || getUseCipherSuitesOrder != null) {
try {
/* load WolfSSLJDK8Helper at runtime, not compiled on older JDKs */
Class<?> cls = Class.forName(
Expand All @@ -267,10 +287,15 @@ protected static void importParams(SSLParameters in,
"getEndpointIdentificationAlgorithm", paramList);
mth.invoke(obj, in, out);
}
if (getSNIMatchers != null){
if (getSNIMatchers != null) {
mth = cls.getDeclaredMethod("getSNIMatchers", paramList);
mth.invoke(obj, in, out);
}
if (getUseCipherSuitesOrder != null) {
mth = cls.getDeclaredMethod("getUseCipherSuitesOrder",
paramList);
mth.invoke(obj, in, out);
}

} catch (Exception e) {
/* ignore, class not found */
Expand All @@ -296,12 +321,21 @@ protected static void importParams(SSLParameters in,
* conditionally to wolfJSSE when supported. */
/*out.setAlgorithmConstraints(in.getAlgorithmConstraints());
out.setEnableRetransmissions(in.getEnableRetransmissions());
out.setMaximumPacketSize(in.getMaximumPacketSize());
out.setSNIMatchers(in.getSNIMatchers());
out.setUseCipherSuitesOrder(in.getUseCipherSuitesOrder());
*/

out.setSNIMatchers(in.getSNIMatchers());
try {
out.setSNIMatchers(in.getSNIMatchers());
} catch (Exception e) {
/* Not available, just ignore and continue */
Comment thread
cconlon marked this conversation as resolved.
}

try {
if (getUseCipherSuitesOrder != null) {
out.setUseCipherSuitesOrder(in.getUseCipherSuitesOrder());
}
} catch (Exception e) {
/* Not available, just ignore and continue */
}

}
}
Expand Down
111 changes: 102 additions & 9 deletions src/test/com/wolfssl/provider/jsse/test/WolfSSLSocketTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -179,7 +179,7 @@ public static void testSetupSocketFactory() throws NoSuchProviderException,
try {
tf = new WolfSSLTestFactory();
} catch (WolfSSLException e) {
// TODO Auto-generated catch block
/* TODO Auto-generated catch block */
e.printStackTrace();
}

Expand Down Expand Up @@ -321,6 +321,99 @@ public void testGetSetEnabledCipherSuites()
System.out.println("\t... passed");
}

@Test
public void testServerUsesClientCipherSuitePreference() throws Exception {

System.out.print("\tTesting client suite preference");

this.ctx = tf.createSSLContext("TLS", "wolfJSSE");

String[] serverSuites = {
"TLS_AES_256_GCM_SHA384",
"TLS_AES_128_GCM_SHA256"
};

String[] clientSuites = {
"TLS_AES_128_GCM_SHA256",
"TLS_AES_256_GCM_SHA384"
};

/* --- Case 1: default (server order) --- */
SSLServerSocket ss1 = (SSLServerSocket)ctx.getServerSocketFactory()
.createServerSocket(0);
ss1.setEnabledCipherSuites(serverSuites);

SSLSocket cs1 = (SSLSocket)ctx.getSocketFactory().createSocket();
cs1.setEnabledCipherSuites(clientSuites);
cs1.connect(new InetSocketAddress(ss1.getLocalPort()));

final SSLSocket server1 = (SSLSocket)ss1.accept();

ExecutorService es = Executors.newSingleThreadExecutor();
Future<Void> f1 = es.submit(() -> {
server1.startHandshake();
return null;
});

cs1.startHandshake();
f1.get();

String chosen1 = cs1.getSession().getCipherSuite();
/* Note: WolfSSL may report TLS 1.3 ciphers in IANA standard or wolfSSL
* alias depending on wolfSSL configuration. */
if (!"TLS_AES_256_GCM_SHA384".equals(chosen1) &&
!"TLS13-AES256-GCM-SHA384".equals(chosen1)) {
System.out.println("\t... failed");
fail("Expected server preference cipher (AES_256), got "
+ chosen1);
}

cs1.close();
server1.close();
ss1.close();

/* --- Case 2: server honors client order --- */
SSLServerSocket ss2 = (SSLServerSocket)ctx.getServerSocketFactory()
.createServerSocket(0);
ss2.setEnabledCipherSuites(serverSuites);

/* Do not honor local cipher suites preference */
SSLParameters ss2Params = ss2.getSSLParameters();
ss2Params.setUseCipherSuitesOrder(false);
ss2.setSSLParameters(ss2Params);

SSLSocket cs2 = (SSLSocket)ctx.getSocketFactory().createSocket();
cs2.setEnabledCipherSuites(clientSuites);
cs2.connect(new InetSocketAddress(ss2.getLocalPort()));

final SSLSocket server2 = (SSLSocket)ss2.accept();

Future<Void> f2 = es.submit(() -> {
server2.startHandshake();
return null;
});

cs2.startHandshake();
f2.get();

String chosen2 = cs2.getSession().getCipherSuite();
/* Note: WolfSSL may report TLS 1.3 ciphers in IANA standard or wolfSSL
* alias depending on wolfSSL configuration. */
if (!"TLS_AES_128_GCM_SHA256".equals(chosen2) &&
!"TLS13-AES128-GCM-SHA256".equals(chosen2)) {
System.out.println("\t... failed");
fail("Expected client preference cipher (AES_128), got "
+ chosen2);
}

cs2.close();
server2.close();
ss2.close();
es.shutdown();

System.out.println("\t... passed");
}

@Test
public void testGetSupportedProtocols()
throws NoSuchProviderException, NoSuchAlgorithmException {
Expand Down Expand Up @@ -659,7 +752,7 @@ public void testEnabledSupportedCurvesProperty() throws Exception {

try {
client.join(1000);
//server.join(1000);
/* server.join(1000); */

} catch (InterruptedException e) {
System.out.println("interrupt happened");
Expand Down Expand Up @@ -3402,14 +3495,14 @@ public void testAutoSNIProperty() throws Exception {
public void testSNIMatchers() throws Exception {

System.out.print("\tTesting SNI Matchers");

/* create new CTX */
this.ctx = tf.createSSLContext("TLS", ctxProvider);

/* create SSLServerSocket first to get ephemeral port */
final SSLServerSocket ss = (SSLServerSocket)ctx.getServerSocketFactory()
.createServerSocket(0);

/* Configure SNI matcher for server*/
SNIMatcher matcher = SNIHostName.createSNIMatcher("www\\.example\\.com");
Collection<SNIMatcher> matchers = new ArrayList<>();
Expand All @@ -3436,7 +3529,7 @@ public void testSNIMatchers() throws Exception {
cs.setSSLParameters(cp);

final SSLSocket serverMatched = (SSLSocket)ss.accept();

ExecutorService es = Executors.newSingleThreadExecutor();
Future<Void> serverFuture = es.submit(new Callable<Void>() {
@Override
Expand All @@ -3451,10 +3544,10 @@ public Void call() throws Exception {
return null;
}
});

cs.startHandshake();
cs.close();

es.shutdown();
serverFuture.get();

Expand All @@ -3473,7 +3566,7 @@ public Void call() throws Exception {
cs.setSSLParameters(cp);

final SSLSocket serverUnmatched = (SSLSocket)ss.accept();

es = Executors.newSingleThreadExecutor();
serverFuture = es.submit(() -> {
try {
Expand Down
Loading