# HG changeset patch # User jnimeh # Date 1534804667 25200 # Node ID e4ba2cfcfa92778b1eb71ec1fafe8388b63a4694 # Parent d96e6839e83ddc35bdacc6c6090ebe6874bc5d45 8208350: Disable all DES cipher suites Reviewed-by: xuelei, mullan diff -r d96e6839e83d -r e4ba2cfcfa92 src/java.base/share/classes/sun/security/ssl/CipherSuite.java --- a/src/java.base/share/classes/sun/security/ssl/CipherSuite.java Mon Aug 20 14:19:30 2018 -0700 +++ b/src/java.base/share/classes/sun/security/ssl/CipherSuite.java Mon Aug 20 15:37:47 2018 -0700 @@ -435,12 +435,12 @@ 0x0003, false, "SSL_RSA_EXPORT_WITH_RC4_40_MD5", "TLS_RSA_EXPORT_WITH_RC4_40_MD5", ProtocolVersion.PROTOCOLS_TO_10, - K_RSA_EXPORT, B_DES_40, M_MD5, H_NONE), + K_RSA_EXPORT, B_RC4_40, M_MD5, H_NONE), SSL_DH_anon_EXPORT_WITH_RC4_40_MD5( 0x0017, false, "SSL_DH_anon_EXPORT_WITH_RC4_40_MD5", "TLS_DH_anon_EXPORT_WITH_RC4_40_MD5", ProtocolVersion.PROTOCOLS_TO_10, - K_DH_ANON, B_DES_40, M_MD5, H_NONE), + K_DH_ANON, B_RC4_40, M_MD5, H_NONE), // no traffic encryption cipher suites TLS_RSA_WITH_NULL_SHA256( diff -r d96e6839e83d -r e4ba2cfcfa92 src/java.base/share/conf/security/java.security --- a/src/java.base/share/conf/security/java.security Mon Aug 20 14:19:30 2018 -0700 +++ b/src/java.base/share/conf/security/java.security Mon Aug 20 15:37:47 2018 -0700 @@ -675,8 +675,8 @@ # # Example: # jdk.tls.disabledAlgorithms=MD5, SSLv3, DSA, RSA keySize < 2048 -jdk.tls.disabledAlgorithms=SSLv3, RC4, MD5withRSA, DH keySize < 1024, \ - EC keySize < 224, DES40_CBC, RC4_40, 3DES_EDE_CBC +jdk.tls.disabledAlgorithms=SSLv3, RC4, DES, MD5withRSA, DH keySize < 1024, \ + EC keySize < 224, 3DES_EDE_CBC # # Legacy algorithms for Secure Socket Layer/Transport Layer Security (SSL/TLS) diff -r d96e6839e83d -r e4ba2cfcfa92 test/jdk/sun/security/ssl/CipherSuite/NoDesRC4CiphSuite.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/jdk/sun/security/ssl/CipherSuite/NoDesRC4CiphSuite.java Mon Aug 20 15:37:47 2018 -0700 @@ -0,0 +1,346 @@ +/* + * Copyright (c) 2018, Oracle and/or its affiliates. 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 8208350 + * @summary Disable all DES cipher suites + * @run main/othervm NoDesRC4CiphSuite + */ + +/* + * SunJSSE does not support dynamic system properties, no way to re-use + * system properties in samevm/agentvm mode. + */ + +import java.security.Security; +import javax.net.ssl.*; +import javax.net.ssl.SSLEngineResult.HandshakeStatus; +import java.io.IOException; +import java.nio.ByteBuffer; +import java.security.GeneralSecurityException; +import java.util.List; +import java.util.ArrayList; +import java.util.Arrays; + +public class NoDesRC4CiphSuite { + + private static final boolean DEBUG = false; + + private static final byte RECTYPE_HS = 0x16; + private static final byte HSMSG_CLIHELLO = 0x01; + + // These are some groups of Cipher Suites by names and IDs + private static final List DES_CS_LIST = Arrays.asList( + 0x0009, 0x0015, 0x0012, 0x001A, 0x0008, 0x0014, 0x0011, 0x0019 + ); + private static final String[] DES_CS_LIST_NAMES = new String[] { + "SSL_RSA_WITH_DES_CBC_SHA", + "SSL_DHE_RSA_WITH_DES_CBC_SHA", + "SSL_DHE_DSS_WITH_DES_CBC_SHA", + "SSL_DH_anon_WITH_DES_CBC_SHA", + "SSL_RSA_EXPORT_WITH_DES40_CBC_SHA", + "SSL_DHE_RSA_EXPORT_WITH_DES40_CBC_SHA", + "SSL_DHE_DSS_EXPORT_WITH_DES40_CBC_SHA", + "SSL_DH_anon_EXPORT_WITH_DES40_CBC_SHA" + }; + private static final List RC4_CS_LIST = Arrays.asList( + 0xC007, 0xC011, 0x0005, 0xC002, 0xC00C, 0x0004, 0xC016, 0x0018, + 0x0003, 0x0017 + ); + private static final String[] RC4_CS_LIST_NAMES = new String[] { + "TLS_ECDHE_ECDSA_WITH_RC4_128_SHA", + "TLS_ECDHE_RSA_WITH_RC4_128_SHA", + "SSL_RSA_WITH_RC4_128_SHA", + "TLS_ECDH_ECDSA_WITH_RC4_128_SHA", + "TLS_ECDH_RSA_WITH_RC4_128_SHA", + "SSL_RSA_WITH_RC4_128_MD5", + "TLS_ECDH_anon_WITH_RC4_128_SHA", + "SSL_DH_anon_WITH_RC4_128_MD5", + "SSL_RSA_EXPORT_WITH_RC4_40_MD5", + "SSL_DH_anon_EXPORT_WITH_RC4_40_MD5" + }; + + private static final ByteBuffer CLIOUTBUF = + ByteBuffer.wrap("Client Side".getBytes()); + + public static void main(String[] args) throws Exception { + boolean allGood = true; + String disAlg = Security.getProperty("jdk.tls.disabledAlgorithms"); + System.err.println("Disabled Algs: " + disAlg); + + // Disabled DES tests + allGood &= testDefaultCase(DES_CS_LIST); + allGood &= testEngAddDisabled(DES_CS_LIST_NAMES, DES_CS_LIST); + allGood &= testEngOnlyDisabled(DES_CS_LIST_NAMES); + + // Disabled RC4 tests + allGood &= testDefaultCase(RC4_CS_LIST); + allGood &= testEngAddDisabled(RC4_CS_LIST_NAMES, RC4_CS_LIST); + allGood &= testEngOnlyDisabled(RC4_CS_LIST_NAMES); + + if (allGood) { + System.err.println("All tests passed"); + } else { + throw new RuntimeException("One or more tests failed"); + } + } + + /** + * Create an engine with the default set of cipher suites enabled and make + * sure none of the disabled suites are present in the client hello. + * + * @param disabledSuiteIds the {@code List} of disabled cipher suite IDs + * to be checked for. + * + * @return true if the test passed (No disabled suites), false otherwise + */ + private static boolean testDefaultCase(List disabledSuiteIds) + throws Exception { + System.err.println("\nTest: Default SSLEngine suite set"); + SSLEngine ssle = makeEngine(); + if (DEBUG) { + listCiphers("Suite set upon creation", ssle); + } + SSLEngineResult clientResult; + ByteBuffer cTOs = makeClientBuf(ssle); + clientResult = ssle.wrap(CLIOUTBUF, cTOs); + if (DEBUG) { + dumpResult("ClientHello: ", clientResult); + } + cTOs.flip(); + boolean foundSuite = areSuitesPresentCH(cTOs, disabledSuiteIds); + if (foundSuite) { + System.err.println("FAIL: Found disabled suites!"); + return false; + } else { + System.err.println("PASS: No disabled suites found."); + return true; + } + } + + /** + * Create an engine and set only disabled cipher suites. + * The engine should not create the client hello message since the only + * available suites to assert in the client hello are disabled ones. + * + * @param disabledSuiteNames an array of cipher suite names that + * should be disabled cipher suites. + * + * @return true if the engine throws SSLHandshakeException during client + * hello creation, false otherwise. + */ + private static boolean testEngOnlyDisabled(String[] disabledSuiteNames) + throws Exception { + System.err.println( + "\nTest: SSLEngine configured with only disabled suites"); + try { + SSLEngine ssle = makeEngine(); + ssle.setEnabledCipherSuites(disabledSuiteNames); + if (DEBUG) { + listCiphers("Suite set upon creation", ssle); + } + SSLEngineResult clientResult; + ByteBuffer cTOs = makeClientBuf(ssle); + clientResult = ssle.wrap(CLIOUTBUF, cTOs); + if (DEBUG) { + dumpResult("ClientHello: ", clientResult); + } + cTOs.flip(); + } catch (SSLHandshakeException shse) { + System.err.println("PASS: Caught expected exception: " + shse); + return true; + } + System.err.println("FAIL: Expected SSLHandshakeException not thrown"); + return false; + } + + /** + * Create an engine and add some disabled suites to the default + * set of cipher suites. Make sure none of the disabled suites show up + * in the client hello even though they were explicitly added. + * + * @param disabledSuiteNames an array of cipher suite names that + * should be disabled cipher suites. + * @param disabledIds the {@code List} of disabled cipher suite IDs + * to be checked for. + * + * @return true if the test passed (No disabled suites), false otherwise + */ + private static boolean testEngAddDisabled(String[] disabledNames, + List disabledIds) throws Exception { + System.err.println("\nTest: SSLEngine with disabled suites added"); + SSLEngine ssle = makeEngine(); + + // Add disabled suites to the existing engine's set of enabled suites + String[] initialSuites = ssle.getEnabledCipherSuites(); + String[] plusDisSuites = Arrays.copyOf(initialSuites, + initialSuites.length + disabledNames.length); + System.arraycopy(disabledNames, 0, plusDisSuites, + initialSuites.length, disabledNames.length); + ssle.setEnabledCipherSuites(plusDisSuites); + + if (DEBUG) { + listCiphers("Suite set upon creation", ssle); + } + SSLEngineResult clientResult; + ByteBuffer cTOs = makeClientBuf(ssle); + clientResult = ssle.wrap(CLIOUTBUF, cTOs); + if (DEBUG) { + dumpResult("ClientHello: ", clientResult); + } + cTOs.flip(); + boolean foundDisabled = areSuitesPresentCH(cTOs, disabledIds); + if (foundDisabled) { + System.err.println("FAIL: Found disabled suites!"); + return false; + } else { + System.err.println("PASS: No disabled suites found."); + return true; + } + } + + private static SSLEngine makeEngine() throws GeneralSecurityException { + SSLContext ctx = SSLContext.getInstance("TLSv1.2"); + ctx.init(null, null, null); + return ctx.createSSLEngine(); + } + + private static ByteBuffer makeClientBuf(SSLEngine ssle) { + ssle.setUseClientMode(true); + ssle.setNeedClientAuth(false); + SSLSession sess = ssle.getSession(); + ByteBuffer cTOs = ByteBuffer.allocateDirect(sess.getPacketBufferSize()); + return cTOs; + } + + private static void listCiphers(String prefix, SSLEngine ssle) { + System.err.println(prefix + "\n---------------"); + String[] suites = ssle.getEnabledCipherSuites(); + for (String suite : suites) { + System.err.println(suite); + } + System.err.println("---------------"); + } + + /** + * Walk a TLS 1.2 or earlier ClientHello looking for any of the suites + * in the suiteIdList. + * + * @param clientHello a ByteBuffer containing the ClientHello message as + * a complete TLS record. The position of the buffer should be + * at the first byte of the TLS record header. + * @param suiteIdList a List of integer values corresponding to + * TLS cipher suite identifiers. + * + * @return true if at least one of the suites in {@code suiteIdList} + * is found in the ClientHello's cipher suite list + * + * @throws IOException if the data in the {@code clientHello} + * buffer is not a TLS handshake message or is not a client hello. + */ + private static boolean areSuitesPresentCH(ByteBuffer clientHello, + List suiteIdList) throws IOException { + byte val; + + // Process the TLS Record + val = clientHello.get(); + if (val != RECTYPE_HS) { + throw new IOException( + "Not a handshake record, type = " + val); + } + + // Just skip over the version and length + clientHello.position(clientHello.position() + 4); + + // Check the handshake message type + val = clientHello.get(); + if (val != HSMSG_CLIHELLO) { + throw new IOException( + "Not a ClientHello handshake message, type = " + val); + } + + // Skip over the length + clientHello.position(clientHello.position() + 3); + + // Skip over the protocol version (2) and random (32); + clientHello.position(clientHello.position() + 34); + + // Skip past the session ID (variable length <= 32) + int len = Byte.toUnsignedInt(clientHello.get()); + if (len > 32) { + throw new IOException("Session ID is too large, len = " + len); + } + clientHello.position(clientHello.position() + len); + + // Finally, we are at the cipher suites. Walk the list and place them + // into a List. + int csLen = Short.toUnsignedInt(clientHello.getShort()); + if (csLen % 2 != 0) { + throw new IOException("CipherSuite length is invalid, len = " + + csLen); + } + int csCount = csLen / 2; + List csSuiteList = new ArrayList<>(csCount); + log("Found following suite IDs in hello:"); + for (int i = 0; i < csCount; i++) { + int curSuite = Short.toUnsignedInt(clientHello.getShort()); + log(String.format("Suite ID: 0x%04x", curSuite)); + csSuiteList.add(curSuite); + } + + // Now check to see if any of the suites passed in match what is in + // the suite list. + boolean foundMatch = false; + for (Integer cs : suiteIdList) { + if (csSuiteList.contains(cs)) { + System.err.format("Found match for suite ID 0x%04x\n", cs); + foundMatch = true; + break; + } + } + + // We don't care about the rest of the ClientHello message. + // Rewind and return whether we found a match or not. + clientHello.rewind(); + return foundMatch; + } + + private static void dumpResult(String str, SSLEngineResult result) { + System.err.println("The format of the SSLEngineResult is: \n" + + "\t\"getStatus() / getHandshakeStatus()\" +\n" + + "\t\"bytesConsumed() / bytesProduced()\"\n"); + HandshakeStatus hsStatus = result.getHandshakeStatus(); + System.err.println(str + result.getStatus() + "/" + hsStatus + ", " + + result.bytesConsumed() + "/" + result.bytesProduced() + " bytes"); + if (hsStatus == HandshakeStatus.FINISHED) { + System.err.println("\t...ready for application data"); + } + } + + private static void log(String str) { + if (DEBUG) { + System.err.println(str); + } + } +} diff -r d96e6839e83d -r e4ba2cfcfa92 test/jdk/sun/security/ssl/SSLContextImpl/CustomizedCipherSuites.java --- a/test/jdk/sun/security/ssl/SSLContextImpl/CustomizedCipherSuites.java Mon Aug 20 14:19:30 2018 -0700 +++ b/test/jdk/sun/security/ssl/SSLContextImpl/CustomizedCipherSuites.java Mon Aug 20 15:37:47 2018 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2016, 2018, Oracle and/or its affiliates. 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 @@ -31,47 +31,47 @@ * @run main/othervm * CustomizedCipherSuites Default true * TLS_RSA_WITH_AES_128_CBC_SHA - * SSL_RSA_WITH_DES_CBC_SHA + * TLS_ECDH_anon_WITH_AES_128_CBC_SHA * @run main/othervm * -Djdk.tls.client.cipherSuites="unknown" * CustomizedCipherSuites Default true * TLS_RSA_WITH_AES_128_CBC_SHA - * SSL_RSA_WITH_DES_CBC_SHA + * TLS_ECDH_anon_WITH_AES_128_CBC_SHA * @run main/othervm * -Djdk.tls.client.cipherSuites="" * CustomizedCipherSuites Default true * TLS_RSA_WITH_AES_128_CBC_SHA - * SSL_RSA_WITH_DES_CBC_SHA + * TLS_ECDH_anon_WITH_AES_128_CBC_SHA * @run main/othervm - * -Djdk.tls.client.cipherSuites="SSL_RSA_WITH_DES_CBC_SHA" + * -Djdk.tls.client.cipherSuites="TLS_ECDH_anon_WITH_AES_128_CBC_SHA" * CustomizedCipherSuites Default true - * SSL_RSA_WITH_DES_CBC_SHA + * TLS_ECDH_anon_WITH_AES_128_CBC_SHA * TLS_RSA_WITH_AES_128_CBC_SHA * @run main/othervm - * -Djdk.tls.server.cipherSuites="SSL_RSA_WITH_DES_CBC_SHA" + * -Djdk.tls.server.cipherSuites="TLS_ECDH_anon_WITH_AES_128_CBC_SHA" * CustomizedCipherSuites Default false - * SSL_RSA_WITH_DES_CBC_SHA + * TLS_ECDH_anon_WITH_AES_128_CBC_SHA * TLS_RSA_WITH_AES_128_CBC_SHA * @run main/othervm - * -Djdk.tls.client.cipherSuites="TLS_RSA_WITH_AES_128_CBC_SHA,unknown,SSL_RSA_WITH_DES_CBC_SHA" + * -Djdk.tls.client.cipherSuites="TLS_RSA_WITH_AES_128_CBC_SHA,unknown,TLS_ECDH_anon_WITH_AES_128_CBC_SHA" * CustomizedCipherSuites Default true - * SSL_RSA_WITH_DES_CBC_SHA + * TLS_ECDH_anon_WITH_AES_128_CBC_SHA * "" * @run main/othervm - * -Djdk.tls.server.cipherSuites="TLS_RSA_WITH_AES_128_CBC_SHA,unknown,SSL_RSA_WITH_DES_CBC_SHA" + * -Djdk.tls.server.cipherSuites="TLS_RSA_WITH_AES_128_CBC_SHA,unknown,TLS_ECDH_anon_WITH_AES_128_CBC_SHA" * CustomizedCipherSuites Default false * TLS_RSA_WITH_AES_128_CBC_SHA * "" * @run main/othervm - * -Djdk.tls.server.cipherSuites="SSL_RSA_WITH_DES_CBC_SHA" + * -Djdk.tls.server.cipherSuites="TLS_ECDH_anon_WITH_AES_128_CBC_SHA" * CustomizedCipherSuites Default true * TLS_RSA_WITH_AES_128_CBC_SHA - * SSL_RSA_WITH_DES_CBC_SHA + * TLS_ECDH_anon_WITH_AES_128_CBC_SHA * @run main/othervm - * -Djdk.tls.client.cipherSuites="SSL_RSA_WITH_DES_CBC_SHA" + * -Djdk.tls.client.cipherSuites="TLS_ECDH_anon_WITH_AES_128_CBC_SHA" * CustomizedCipherSuites Default false * TLS_RSA_WITH_AES_128_CBC_SHA - * SSL_RSA_WITH_DES_CBC_SHA + * TLS_ECDH_anon_WITH_AES_128_CBC_SHA */ import javax.net.ssl.*; @@ -79,7 +79,7 @@ /** * Test the customized default cipher suites. * - * This test is based on the behavior that SSL_RSA_WITH_DES_CBC_SHA is + * This test is based on the behavior that TLS_ECDH_anon_WITH_AES_128_CBC_SHA is * disabled by default, and TLS_RSA_WITH_AES_128_CBC_SHA is enabled by * default in JDK. If the behavior is changed in the future, please * update the test cases above accordingly.