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
5 changes: 5 additions & 0 deletions native/com_wolfssl_WolfSSL.c
Original file line number Diff line number Diff line change
Expand Up @@ -2237,6 +2237,11 @@ JNIEXPORT jstring JNICALL Java_com_wolfssl_WolfSSL_getAvailableCipherSuitesIana
}

numCiphers = sk_num(supportedCiphers);
if (numCiphers == 0) {
wolfSSL_free(ssl);
wolfSSL_CTX_free(ctx);
return NULL;
}

for (i = 0; i < numCiphers; i++) {
cipher = (const WOLFSSL_CIPHER*)sk_value(supportedCiphers, i);
Expand Down
4 changes: 2 additions & 2 deletions src/java/com/wolfssl/provider/jsse/WolfSSLContext.java
Original file line number Diff line number Diff line change
Expand Up @@ -180,9 +180,9 @@ private void createCtx() throws WolfSSLException {
if (WolfSSLUtil.isSecurityPropertyStringSet(
"wolfjsse.enabledCipherSuites")) {
/* User is overriding cipher suites, set CTX list */
this.setCtxCiphers(WolfSSLUtil.sanitizeSuites(ciphersIana));
this.setCtxCiphers(WolfSSLUtil.sanitizeSuites(ciphersIana, true));
}
params.setCipherSuites(WolfSSLUtil.sanitizeSuites(ciphersIana));
params.setCipherSuites(WolfSSLUtil.sanitizeSuites(ciphersIana, true));

/* Auto-populate enabled protocols with supported ones. Protocols
* which have been disabled via system property get filtered in
Expand Down
23 changes: 14 additions & 9 deletions src/java/com/wolfssl/provider/jsse/WolfSSLEngineHelper.java
Original file line number Diff line number Diff line change
Expand Up @@ -478,28 +478,33 @@ protected synchronized WolfSSLImplementSSLSession getSession() {
/**
* Get all supported cipher suites in native wolfSSL library, which
* are also allowed by "wolfjsse.enabledCipherSuites" system Security
* property, if set.
* property, if set. Does not auto-filter out anon suites, since this
* returns all supported suites in native wolfSSL.
*
* @return String array of all supported cipher suites
*/
protected static synchronized String[] getAllCiphers() {
return WolfSSLUtil.sanitizeSuites(WolfSSL.getCiphersIana());
return WolfSSLUtil.sanitizeSuites(WolfSSL.getCiphersIana(), false);
}

/**
* Get all enabled cipher suites, and allowed via
* wolfjsse.enabledCipherSuites system Security property (if set).
* Get all enabled cipher suites, filtered by
* wolfjsse.enabledCipherSuites system Security property (if set). Does
* not auto-filter out anon suites, since this returns all enabled suites in
* native wolfSSL.
*
* @return String array of all enabled cipher suites
*/
protected synchronized String[] getCiphers() {
return WolfSSLUtil.sanitizeSuites(this.params.getCipherSuites());
return WolfSSLUtil.sanitizeSuites(this.params.getCipherSuites(), false);
}

/**
* Set cipher suites enabled in WolfSSLParameters
* Set cipher suites enabled in WolfSSLParameters.
*
* Sanitizes input array for invalid suites
* Validates input array against supported cipher suites but does
* not filter anonymous suites, allowing applications to explicitly
* enable them if needed.
*
* @param suites String array of cipher suites to be enabled
*
Expand Down Expand Up @@ -528,7 +533,7 @@ protected synchronized void setCiphers(String[] suites)
}
}

this.params.setCipherSuites(WolfSSLUtil.sanitizeSuites(suites));
this.params.setCipherSuites(WolfSSLUtil.sanitizeSuites(suites, false));
}

/**
Expand Down Expand Up @@ -1251,7 +1256,7 @@ private void setLocalParams(SSLSocket socket, SSLEngine engine)
throws SSLException {

this.setLocalCiphers(
WolfSSLUtil.sanitizeSuites(this.params.getCipherSuites()));
WolfSSLUtil.sanitizeSuites(this.params.getCipherSuites(), false));
this.setLocalProtocol(
WolfSSLUtil.sanitizeProtocols(
this.params.getProtocols(), WolfSSL.TLS_VERSION.INVALID));
Expand Down
9 changes: 5 additions & 4 deletions src/java/com/wolfssl/provider/jsse/WolfSSLServerSocket.java
Original file line number Diff line number Diff line change
Expand Up @@ -160,7 +160,7 @@ synchronized public String[] getEnabledCipherSuites() {
WolfSSLDebug.log(getClass(), WolfSSLDebug.INFO,
() -> "entered getEnabledCipherSuites()");

return WolfSSLUtil.sanitizeSuites(params.getCipherSuites());
return WolfSSLUtil.sanitizeSuites(params.getCipherSuites(), false);
}

@Override
Expand All @@ -178,9 +178,10 @@ synchronized public void setEnabledCipherSuites(String[] suites)
throw new IllegalArgumentException("input array has length zero");
}

/* sanitize cipher array for unsupported strings */
/* validate cipher array for unsupported strings. Not filtering
* anon suites in case user wants to explicitly set. */
List<String> supported = Arrays.asList(
WolfSSLUtil.sanitizeSuites(WolfSSL.getCiphersIana()));
WolfSSLUtil.sanitizeSuites(WolfSSL.getCiphersIana(), false));
for (int i = 0; i < suites.length; i++) {
if (!supported.contains(suites[i])) {
throw new IllegalArgumentException("Unsupported CipherSuite: " +
Expand All @@ -200,7 +201,7 @@ public String[] getSupportedCipherSuites() {
WolfSSLDebug.log(getClass(), WolfSSLDebug.INFO,
() -> "entered getSupportedCipherSuites()");

return WolfSSLUtil.sanitizeSuites(WolfSSL.getCiphersIana());
return WolfSSLUtil.sanitizeSuites(WolfSSL.getCiphersIana(), false);
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,9 @@ public WolfSSLServerSocketFactory(com.wolfssl.WolfSSLContext ctx,
/**
* Returns the default cipher suite list for wolfJSSE.
*
* Filters out anon suites by default. User can explicitly set
* if needed.
*
* @return default array of cipher suite Strings for wolfSSL
*/
@Override
Expand All @@ -70,7 +73,7 @@ public String[] getDefaultCipherSuites() {
WolfSSLDebug.log(getClass(), WolfSSLDebug.INFO,
() -> "entered getDefaultCipherSuites()");

return WolfSSLUtil.sanitizeSuites(WolfSSL.getCiphersIana());
return WolfSSLUtil.sanitizeSuites(WolfSSL.getCiphersIana(), true);
}

/**
Expand All @@ -84,7 +87,8 @@ public String[] getSupportedCipherSuites() {
WolfSSLDebug.log(getClass(), WolfSSLDebug.INFO,
() -> "entered getSupportedCipherSuites()");

return getDefaultCipherSuites();
return WolfSSLUtil.sanitizeSuites(
WolfSSL.getCiphersIana(), false);
}

/**
Expand Down
6 changes: 4 additions & 2 deletions src/java/com/wolfssl/provider/jsse/WolfSSLSocketFactory.java
Original file line number Diff line number Diff line change
Expand Up @@ -118,6 +118,8 @@ private void initDefaultContext() throws WolfSSLException {
/**
* Returns the default cipher suite list for wolfJSSE.
*
* Filters out anon suites by default.
*
* @return default array of cipher suite Strings for wolfSSL
*/
@Override
Expand All @@ -126,7 +128,7 @@ public String[] getDefaultCipherSuites() {
WolfSSLDebug.log(getClass(), WolfSSLDebug.INFO,
() -> "entered getDefaultCipherSuites()");

return WolfSSLUtil.sanitizeSuites(WolfSSL.getCiphersIana());
return WolfSSLUtil.sanitizeSuites(WolfSSL.getCiphersIana(), true);
}

/**
Expand All @@ -140,7 +142,7 @@ public String[] getSupportedCipherSuites() {
WolfSSLDebug.log(getClass(), WolfSSLDebug.INFO,
() -> "entered getSupportedCipherSuites()");

return getDefaultCipherSuites();
return WolfSSLUtil.sanitizeSuites(WolfSSL.getCiphersIana(), false);
}

/**
Expand Down
69 changes: 49 additions & 20 deletions src/java/com/wolfssl/provider/jsse/WolfSSLUtil.java
Original file line number Diff line number Diff line change
Expand Up @@ -125,37 +125,64 @@ protected static String[] sanitizeProtocols(String[] protocols,
* Sanitize or filter SSL/TLS cipher suite list based on custom wolfJSSE
* system property limitations.
*
* Supported system Security properties which limit cipher suite list are:
* - wolfjsse.enabledCipherSuites
* When filterAnon is true, this method filters the default enabled cipher
* suite list, removing anonymous cipher suites to match SunJSSE behavior.
* When filterAnon is false, anonymous cipher suites are preserved, allowing
* applications to explicitly enable them via
* SSLEngine.setEnabledCipherSuites() or SSLSocket.setEnabledCipherSuites().
Comment thread
rlm2002 marked this conversation as resolved.
*
* This security property should contain a comma-separated list of
* values, for example:
* Filtering applied:
*
* 1. If filterAnon is true, anonymous cipher suites (containing
* "_anon_" in IANA name) are removed, matching SunJSSE behavior.
*
* 2. If the wolfjsse.enabledCipherSuites security property is set,
* the list is further filtered to only include suites in that
* property. This should contain a comma-separated list of values,
* for example:
*
* wolfjsse.enabledCipherSuites=
* "TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384, \
* TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256"
*
* Only the cipher suites included in this list will be allowed to be used
* in JSSE TLS connections. Applications can still set cipher suites,
* using for example SSLParameters, but the set cipher suite list will be
* filtered by this function to remove any suites not included in the
* system property mentioned here if it has been set.
*
* @param suites Full list of TLS cipher suites to sanitize/filter,
* should be in format similar to: "SUITE1", "SUITE2", etc.
*
* @return New filtered String array of cipher suites.
* should be in format similar to: "SUITE1", "SUITE2",
* etc.
* @param filterAnon If true, anonymous cipher suites (containing "_anon_"
* in IANA name) will be filtered out. If false, anonymous
* suites are preserved.
*
* @return New filtered String array of cipher suites, or null if input
* is null.
*/
protected static String[] sanitizeSuites(String[] suites) {
protected static String[] sanitizeSuites(String[] suites,
boolean filterAnon) {

ArrayList<String> filtered = new ArrayList<String>();

if (suites == null) {
return null;
}

/* Filter out anonymous cipher suites if requested. SunJSSE also
* excludes them from the default enabled list. Anonymous suites
* contain "_anon_" in IANA format. When filterAnon is false, all
* non-null suites pass through. */
for (int i = 0; i < suites.length; i++) {
if (suites[i] != null) {
if (!filterAnon || !suites[i].contains("_anon_")) {
filtered.add(suites[i]);
}
}
}

String enabledSuites =
Security.getProperty("wolfjsse.enabledCipherSuites");
List<?> enabledList = null;

/* If system property not set, no filtering needed */
/* If system property not set, return filtered list */
if (enabledSuites == null || enabledSuites.isEmpty()) {
return suites;
return filtered.toArray(new String[filtered.size()]);
}

final String tmpSuites = enabledSuites;
Expand All @@ -168,13 +195,15 @@ protected static String[] sanitizeSuites(String[] suites) {
enabledSuites = enabledSuites.replaceAll(", ",",");
enabledList = Arrays.asList(enabledSuites.split(","));

for (int i = 0; i < suites.length; i++) {
if (enabledList.contains(suites[i])) {
filtered.add(suites[i]);
/* Further filter by wolfjsse.enabledCipherSuites property */
ArrayList<String> propFiltered = new ArrayList<String>();
for (int i = 0; i < filtered.size(); i++) {
if (enabledList.contains(filtered.get(i))) {
propFiltered.add(filtered.get(i));
}
}

return filtered.toArray(new String[filtered.size()]);
return propFiltered.toArray(new String[propFiltered.size()]);
}

/**
Expand Down
62 changes: 59 additions & 3 deletions src/test/com/wolfssl/provider/jsse/test/WolfSSLContextTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -796,8 +796,19 @@ public void testWolfJSSEEnabledCipherSuites()
fail("Invalid TLS version");
}

/* String[] of all available native wolfSSL suites for version */
nativeSuites = WolfSSL.getCiphersAvailableIana(version);
/* String[] of all available native wolfSSL suites for version,
* filtered to remove anonymous cipher suites to match what
* SSLContext will return (wolfJSSE filters anon suites) */
String[] rawSuites = WolfSSL.getCiphersAvailableIana(version);
ArrayList<String> nonAnon = new ArrayList<String>();
if (rawSuites != null) {
for (String s : rawSuites) {
if (s != null && !s.contains("_anon_")) {
nonAnon.add(s);
}
}
}
nativeSuites = nonAnon.toArray(new String[nonAnon.size()]);

/* ------------------------------------------------------------- */

Expand Down Expand Up @@ -991,12 +1002,57 @@ public void testSanitizeProtocolsNullInput() {
return;
}

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

} catch (Exception e) {
System.out.println("\t... failed");
fail("Exception during sanitizeProtocols test: " + e.getMessage());
}
}

/* Helper: check if array has any anon suite */
private boolean arrayHasAnonSuite(String[] arr) {
if (arr == null) {
return false;
}
for (String s : arr) {
if (s != null && s.contains("_anon_")) {
return true;
}
}
return false;
}

@Test
public void testContextDefaultParamsExcludeAnon() throws Exception {

System.out.print("\tdefault params exclude anon");

String[] allCiphers = WolfSSL.getCiphersIana();
boolean haveAnon = false;
for (String s : allCiphers) {
if (s != null && s.contains("_anon_")) {
haveAnon = true;
break;
}
}

if (!haveAnon) {
System.out.println("\t... skipped (no anon suites)");
return;
}

Security.setProperty("wolfjsse.enabledCipherSuites", "");
SSLContext ctx = SSLContext.getInstance("TLS", ctxProvider);
ctx.init(null, null, null);

String[] defaults =
ctx.getDefaultSSLParameters().getCipherSuites();
assertNotNull(defaults);
assertFalse("Default params should not contain anon",
arrayHasAnonSuite(defaults));

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

Loading
Loading