Skip to content
Open
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
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
/*
* Copyright (c) 2015, 2020, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2026, IBM Corporation. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
Expand Down Expand Up @@ -172,9 +173,18 @@ private Set<String> decomposes(SSLCipher bulkCipher) {
case B_AES_128_GCM:
components.add("AES_128_GCM");
break;
case B_AES_128_GCM_IV:
components.add("AES_128_GCM");
break;
case B_AES_256_GCM:
components.add("AES_256_GCM");
break;
case B_AES_256_GCM_IV:
components.add("AES_256_GCM");
break;
case B_CC20_P1305:
components.add("CHACHA20_POLY1305");
break;
}

return components;
Expand Down
197 changes: 197 additions & 0 deletions test/jdk/javax/net/ssl/ciphersuites/BulkCipherDisabledAlgorithms.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,197 @@
/*
* Copyright (c) 2026, IBM Corporation. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/

/*
* @test
* @bug 8387124
* @summary Verify that disabling bulk cipher algorithms in
* jdk.tls.disabledAlgorithms disables associated TLS cipher suites.
* @library /test/lib
* /javax/net/ssl/TLSCommon
* /javax/net/ssl/templates
*/

import java.security.NoSuchAlgorithmException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;

import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLHandshakeException;
import javax.net.ssl.SSLEngine;
import javax.net.ssl.SSLServerSocket;
import javax.net.ssl.SSLSocket;

import jdk.test.lib.process.Proc;

/*
* Each test case is executed in a separate JVM because
* jdk.tls.disabledAlgorithms is evaluated during JSSE initialization and
* cannot be reliably reconfigured within the same VM.
*/
public class BulkCipherDisabledAlgorithms {

public static void main(String[] args) throws Exception {
if (args.length == 0) {
// Sanity check: all enabled cipher suites should work before
// applying any jdk.tls.disabledAlgorithms restrictions.
testAllCipherSuitesEnabled();

// Verify that disabling a bulk cipher algorithm disables cipher
// suites that use that algorithm.
Map<String, List<String>> cipherSuitesByBulkCipher = groupCipherSuitesByBulkCipher();

for (Map.Entry<String, List<String>> entry : cipherSuitesByBulkCipher.entrySet()) {
String disabledBulkCipher = entry.getKey();
List<String> disabledCipherSuites = entry.getValue();

// Verify that all cipher suites associated with the disabled
// bulk cipher become unavailable.
Proc p = Proc.create(
BulkCipherDisabledAlgorithms.class.getName())
.args(disabledBulkCipher,
String.join(",", disabledCipherSuites))
.secprop("jdk.tls.disabledAlgorithms", disabledBulkCipher)
.inheritIO();

p.start().waitFor(0);
}

System.out.println("TEST PASS - OK");
return;
}

String disabledBulkCipher = args[0];
List<String> disabledCipherSuites = Arrays.asList(args[1].split(","));

for (String disabledCipherSuite : disabledCipherSuites) {
System.out.println("=================================================");
System.out.println("Testing: suite=" + disabledCipherSuite +
", disabled bulk cipher=" + disabledBulkCipher);

testCipherSuiteDisabled(disabledCipherSuite);
testHandshake(disabledCipherSuite, true);
}
}

private static void testAllCipherSuitesEnabled() throws Exception {
CipherSuite[] suites = getCipherSuites();

for (CipherSuite suite : suites) {
testHandshake(suite.name(), false);
}
}

private static CipherSuite[] getCipherSuites() throws NoSuchAlgorithmException {
SSLEngine engine = SSLContext.getDefault().createSSLEngine();
String[] suites = engine.getEnabledCipherSuites();
return Arrays.stream(suites)
.map(CipherSuite::cipherSuite)
.filter(cs -> cs != CipherSuite.TLS_EMPTY_RENEGOTIATION_INFO_SCSV)
.toArray(CipherSuite[]::new);
}

private static Map<String, List<String>> groupCipherSuitesByBulkCipher() throws NoSuchAlgorithmException {
Map<String, List<String>> cipherSuitesByBulkCipher = new LinkedHashMap<>();
CipherSuite[] suites = getCipherSuites();

for (CipherSuite suite : suites) {
String suiteName = suite.name();
String bulkCipher = extractBulkCipher(suiteName);
List<String> suitesForBulk = cipherSuitesByBulkCipher.get(bulkCipher);

if (suitesForBulk == null) {
suitesForBulk = new ArrayList<>();
cipherSuitesByBulkCipher.put(bulkCipher, suitesForBulk);
}

suitesForBulk.add(suiteName);
}

return cipherSuitesByBulkCipher;
}

/**
* Separator used in TLS cipher suite names to mark the start of
* the bulk cipher component (e.g. TLS_RSA_WITH_AES_128_CBC_SHA).
*/
private static final String WITH = "_WITH_";

private static String extractBulkCipher(String suite) {
if (suite.contains(WITH)) {
String after = suite.substring(suite.indexOf(WITH) + WITH.length());
int last = after.lastIndexOf('_');
return after.substring(0, last);
} else {
int first = suite.indexOf('_');
int last = suite.lastIndexOf('_');
return suite.substring(first + 1, last);
}
}

private static void testCipherSuiteDisabled(String suite) throws NoSuchAlgorithmException {
boolean visible = Arrays.asList(getCipherSuites())
.contains(CipherSuite.cipherSuite(suite));

if (visible) {
throw new RuntimeException(
"Cipher suite '" + suite + "' visible but expected to be disabled");
}
}

private static void testHandshake(String cipherSuite, boolean expectedDisabled) throws Exception {
try {
new TLSHandshakeTest(cipherSuite).run();

if (expectedDisabled) {
throw new RuntimeException(
"Handshake succeeded but should fail: " + cipherSuite);
}
} catch (SSLHandshakeException e) {
if (!expectedDisabled) {
throw new RuntimeException(
"Handshake failed unexpectedly: " + cipherSuite, e);
}
}
}

private static class TLSHandshakeTest extends SSLSocketTemplate {
private final String cipherSuite;

TLSHandshakeTest(String cipherSuite) {
this.cipherSuite = cipherSuite;
}

@Override
protected void configureClientSocket(SSLSocket socket) {
socket.setEnabledCipherSuites(new String[] { cipherSuite });
}

@Override
protected void configureServerSocket(SSLServerSocket socket) {
socket.setEnabledCipherSuites(new String[] { cipherSuite });
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
/*
* Copyright (c) 2026, IBM Corporation. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/

/*
* @test
* @bug 8387124
* @summary Test disabling TLS 1.3 cipher suites with bulk ciphers names
* @run testng/othervm TLS13BulkCipherDisabledCipherSuite
*/

import static org.testng.AssertJUnit.assertTrue;

import org.testng.annotations.BeforeTest;
import org.testng.annotations.Test;

import java.security.Security;
import java.util.List;

public class TLS13BulkCipherDisabledCipherSuite extends AbstractDisableCipherSuites {

private static final String SECURITY_PROPERTY = "jdk.tls.disabledAlgorithms";
private static final String TEST_ALGORITHMS = "AES_256_GCM,"
+ " AES_128_GCM,"
+ " CHACHA20_POLY1305";
private static final String[] CIPHER_SUITES = new String[] {
"TLS_AES_256_GCM_SHA384",
"TLS_AES_128_GCM_SHA256",
"TLS_CHACHA20_POLY1305_SHA256"
};
static final List<Integer> CIPHER_SUITES_IDS = List.of(
0x1301,
0x1302,
0x1303);

@Override
protected String getProtocol() {
return "TLSv1.3";
}

@BeforeTest
void setUp() throws Exception {
Security.setProperty(SECURITY_PROPERTY, TEST_ALGORITHMS);
}

@Test
public void testDefault() throws Exception {
assertTrue(testDefaultCase(CIPHER_SUITES_IDS));
}

@Test
public void testAddDisabled() throws Exception {
assertTrue(testEngAddDisabled(CIPHER_SUITES, CIPHER_SUITES_IDS));
}

@Test
public void testOnlyDisabled() throws Exception {
assertTrue(testEngOnlyDisabled(CIPHER_SUITES));
}
}
Loading