Skip to content
Snippets Groups Projects
Commit 5daf0666 authored by Goetz Lindenmaier's avatar Goetz Lindenmaier
Browse files

8301379: Verify TLS_ECDH_* cipher suites cannot be negotiated

Reviewed-by: lucy
Backport-of: 9f64a64376c677dbe1358807329b42737ac78ad9
parent e3e79097
No related branches found
No related tags found
No related merge requests found
/* /*
* Copyright (c) 2015, 2018, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2015, 2023, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
...@@ -25,6 +25,7 @@ ...@@ -25,6 +25,7 @@
* @test * @test
* @bug 8076221 8211883 8279164 * @bug 8076221 8211883 8279164
* @summary Check if weak cipher suites are disabled * @summary Check if weak cipher suites are disabled
* @library /javax/net/ssl/templates
* @modules jdk.crypto.ec * @modules jdk.crypto.ec
* @run main/othervm DisabledAlgorithms default * @run main/othervm DisabledAlgorithms default
* @run main/othervm DisabledAlgorithms empty * @run main/othervm DisabledAlgorithms empty
...@@ -35,7 +36,6 @@ import java.io.BufferedOutputStream; ...@@ -35,7 +36,6 @@ import java.io.BufferedOutputStream;
import java.io.IOException; import java.io.IOException;
import java.io.InputStream; import java.io.InputStream;
import java.io.OutputStream; import java.io.OutputStream;
import java.security.NoSuchAlgorithmException;
import java.security.Security; import java.security.Security;
import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeUnit;
import javax.net.ssl.SSLContext; import javax.net.ssl.SSLContext;
...@@ -45,23 +45,27 @@ import javax.net.ssl.SSLServerSocketFactory; ...@@ -45,23 +45,27 @@ import javax.net.ssl.SSLServerSocketFactory;
import javax.net.ssl.SSLSocket; import javax.net.ssl.SSLSocket;
import javax.net.ssl.SSLSocketFactory; import javax.net.ssl.SSLSocketFactory;
/*
* This test verifies that setEnabledProtocols() does not override the
* jdk.tls.disabledAlgorithms property. Both the client and server throw
* an exception when creating a handshake context.
*
* In the TLSWontNegotiateDisabledCipherAlgoos test, one side of the connection
* disables the cipher suites and the other side enables them and verifies
* that the handshake cannot complete successfully.
*/
public class DisabledAlgorithms { public class DisabledAlgorithms {
private static final String pathToStores = "../etc"; public static final SSLContextTemplate.Cert[] CERTIFICATES = {
private static final String keyStoreFile = "keystore"; SSLContextTemplate.Cert.EE_DSA_SHA1_1024,
private static final String trustStoreFile = "truststore"; SSLContextTemplate.Cert.EE_DSA_SHA224_1024,
private static final String passwd = "passphrase"; SSLContextTemplate.Cert.EE_DSA_SHA256_1024,
SSLContextTemplate.Cert.CA_ECDSA_SECP256R1,
private static final String keyFilename = SSLContextTemplate.Cert.CA_RSA_2048
System.getProperty("test.src", "./") + "/" + pathToStores + };
"/" + keyStoreFile;
private static final String trustFilename =
System.getProperty("test.src", "./") + "/" + pathToStores +
"/" + trustStoreFile;
// disabled RC4, NULL, anon, and ECDH cipher suites // disabled RC4, NULL, anon, and ECDH cipher suites
private static final String[] disabled_ciphersuites public static final String[] DISABLED_CIPHERSUITES
= new String[]{ = new String[]{
"TLS_ECDHE_ECDSA_WITH_RC4_128_SHA", "TLS_ECDHE_ECDSA_WITH_RC4_128_SHA",
"TLS_ECDHE_RSA_WITH_RC4_128_SHA", "TLS_ECDHE_RSA_WITH_RC4_128_SHA",
...@@ -114,11 +118,6 @@ public class DisabledAlgorithms { ...@@ -114,11 +118,6 @@ public class DisabledAlgorithms {
throw new RuntimeException("No parameters specified"); throw new RuntimeException("No parameters specified");
} }
System.setProperty("javax.net.ssl.keyStore", keyFilename);
System.setProperty("javax.net.ssl.keyStorePassword", passwd);
System.setProperty("javax.net.ssl.trustStore", trustFilename);
System.setProperty("javax.net.ssl.trustStorePassword", passwd);
switch (args[0]) { switch (args[0]) {
case "default": case "default":
// use default jdk.tls.disabledAlgorithms // use default jdk.tls.disabledAlgorithms
...@@ -126,7 +125,7 @@ public class DisabledAlgorithms { ...@@ -126,7 +125,7 @@ public class DisabledAlgorithms {
+ Security.getProperty("jdk.tls.disabledAlgorithms")); + Security.getProperty("jdk.tls.disabledAlgorithms"));
// check that disabled cipher suites can't be used by default // check that disabled cipher suites can't be used by default
checkFailure(disabled_ciphersuites); checkFailure(DISABLED_CIPHERSUITES);
break; break;
case "empty": case "empty":
// reset jdk.tls.disabledAlgorithms // reset jdk.tls.disabledAlgorithms
...@@ -136,7 +135,7 @@ public class DisabledAlgorithms { ...@@ -136,7 +135,7 @@ public class DisabledAlgorithms {
// check that disabled cipher suites can be used if // check that disabled cipher suites can be used if
// jdk.{tls,certpath}.disabledAlgorithms is empty // jdk.{tls,certpath}.disabledAlgorithms is empty
checkSuccess(disabled_ciphersuites); checkSuccess(DISABLED_CIPHERSUITES);
break; break;
default: default:
throw new RuntimeException("Wrong parameter: " + args[0]); throw new RuntimeException("Wrong parameter: " + args[0]);
...@@ -149,7 +148,7 @@ public class DisabledAlgorithms { ...@@ -149,7 +148,7 @@ public class DisabledAlgorithms {
* Checks if that specified cipher suites cannot be used. * Checks if that specified cipher suites cannot be used.
*/ */
private static void checkFailure(String[] ciphersuites) throws Exception { private static void checkFailure(String[] ciphersuites) throws Exception {
try (SSLServer server = SSLServer.init(ciphersuites)) { try (SSLServer server = new SSLServer(ciphersuites)) {
startNewThread(server); startNewThread(server);
while (!server.isRunning()) { while (!server.isRunning()) {
sleep(); sleep();
...@@ -157,7 +156,7 @@ public class DisabledAlgorithms { ...@@ -157,7 +156,7 @@ public class DisabledAlgorithms {
int port = server.getPort(); int port = server.getPort();
for (String ciphersuite : ciphersuites) { for (String ciphersuite : ciphersuites) {
try (SSLClient client = SSLClient.init(port, ciphersuite)) { try (SSLClient client = new SSLClient(port, ciphersuite)) {
client.connect(); client.connect();
throw new RuntimeException("Expected SSLHandshakeException " throw new RuntimeException("Expected SSLHandshakeException "
+ "not thrown"); + "not thrown");
...@@ -184,7 +183,7 @@ public class DisabledAlgorithms { ...@@ -184,7 +183,7 @@ public class DisabledAlgorithms {
* Checks if specified cipher suites can be used. * Checks if specified cipher suites can be used.
*/ */
private static void checkSuccess(String[] ciphersuites) throws Exception { private static void checkSuccess(String[] ciphersuites) throws Exception {
try (SSLServer server = SSLServer.init(ciphersuites)) { try (SSLServer server = new SSLServer(ciphersuites)) {
startNewThread(server); startNewThread(server);
while (!server.isRunning()) { while (!server.isRunning()) {
sleep(); sleep();
...@@ -192,7 +191,7 @@ public class DisabledAlgorithms { ...@@ -192,7 +191,7 @@ public class DisabledAlgorithms {
int port = server.getPort(); int port = server.getPort();
for (String ciphersuite : ciphersuites) { for (String ciphersuite : ciphersuites) {
try (SSLClient client = SSLClient.init(port, ciphersuite)) { try (SSLClient client = new SSLClient(port, ciphersuite)) {
client.connect(); client.connect();
String negotiated = client.getNegotiatedCipherSuite(); String negotiated = client.getNegotiatedCipherSuite();
System.out.println("Negotiated cipher suite: " System.out.println("Negotiated cipher suite: "
...@@ -231,7 +230,8 @@ public class DisabledAlgorithms { ...@@ -231,7 +230,8 @@ public class DisabledAlgorithms {
} }
} }
static class SSLServer implements Runnable, AutoCloseable { static class SSLServer extends SSLContextTemplate implements Runnable, AutoCloseable {
private final SSLServerSocket ssocket; private final SSLServerSocket ssocket;
private volatile boolean stopped = false; private volatile boolean stopped = false;
...@@ -239,7 +239,19 @@ public class DisabledAlgorithms { ...@@ -239,7 +239,19 @@ public class DisabledAlgorithms {
private volatile boolean sslError = false; private volatile boolean sslError = false;
private volatile boolean otherError = false; private volatile boolean otherError = false;
private SSLServer(SSLServerSocket ssocket) { private SSLServer(String[] ciphersuites) throws Exception {
SSLContext context = createSSLContext(null,
DisabledAlgorithms.CERTIFICATES, getServerContextParameters());
SSLServerSocketFactory ssf = context.getServerSocketFactory();
SSLServerSocket ssocket = (SSLServerSocket)
ssf.createServerSocket(0);
if (ciphersuites != null) {
System.out.println("Server: enable cipher suites: "
+ java.util.Arrays.toString(ciphersuites));
ssocket.setEnabledCipherSuites(ciphersuites);
}
this.ssocket = ssocket; this.ssocket = ssocket;
} }
...@@ -319,29 +331,23 @@ public class DisabledAlgorithms { ...@@ -319,29 +331,23 @@ public class DisabledAlgorithms {
public void close() { public void close() {
stop(); stop();
} }
static SSLServer init(String[] ciphersuites)
throws IOException {
SSLServerSocketFactory ssf = (SSLServerSocketFactory)
SSLServerSocketFactory.getDefault();
SSLServerSocket ssocket = (SSLServerSocket)
ssf.createServerSocket(0);
if (ciphersuites != null) {
System.out.println("Server: enable cipher suites: "
+ java.util.Arrays.toString(ciphersuites));
ssocket.setEnabledCipherSuites(ciphersuites);
}
return new SSLServer(ssocket);
}
} }
static class SSLClient implements AutoCloseable { static class SSLClient extends SSLContextTemplate implements AutoCloseable {
private final SSLSocket socket; private final SSLSocket socket;
private SSLClient(SSLSocket socket) { private SSLClient(int port, String ciphersuite) throws Exception {
SSLContext context = createSSLContext(DisabledAlgorithms.CERTIFICATES,
null, getClientContextParameters());
SSLSocketFactory ssf = context.getSocketFactory();
SSLSocket socket = (SSLSocket) ssf.createSocket("localhost", port);
if (ciphersuite != null) {
System.out.println("Client: enable cipher suite: "
+ ciphersuite);
socket.setEnabledCipherSuites(new String[]{ciphersuite});
}
this.socket = socket; this.socket = socket;
} }
...@@ -381,29 +387,5 @@ public class DisabledAlgorithms { ...@@ -381,29 +387,5 @@ public class DisabledAlgorithms {
} }
} }
} }
static SSLClient init(int port)
throws NoSuchAlgorithmException, IOException {
return init(port, null);
} }
static SSLClient init(int port, String ciphersuite)
throws NoSuchAlgorithmException, IOException {
SSLContext context = SSLContext.getDefault();
SSLSocketFactory ssf = (SSLSocketFactory)
context.getSocketFactory();
SSLSocket socket = (SSLSocket) ssf.createSocket("localhost", port);
if (ciphersuite != null) {
System.out.println("Client: enable cipher suite: "
+ ciphersuite);
socket.setEnabledCipherSuites(new String[] { ciphersuite });
}
return new SSLClient(socket);
}
}
} }
/*
* Copyright (c) 2023, 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.
*/
import javax.net.ssl.*;
import java.io.IOException;
import java.net.Socket;
import java.nio.charset.StandardCharsets;
import java.nio.file.Path;
import java.security.Security;
import java.util.List;
/*
* @test id=Server
* @bug 8301379
* @summary Verify that Java will not negotiate disabled cipher suites when the
* other side of the connection requests them.
*
* @library /javax/net/ssl/templates
* @run main/othervm TLSWontNegotiateDisabledCipherAlgos server true
*/
/*
* @test id=Client
* @bug 8301379
* @summary Verify that Java will not negotiate disabled cipher suites when the
* other side of the connection requests them.
*
* @library /javax/net/ssl/templates
* @run main/othervm TLSWontNegotiateDisabledCipherAlgos server false
*/
public class TLSWontNegotiateDisabledCipherAlgos {
public static void main(String [] args) throws Exception {
boolean useDisabledAlgo = Boolean.parseBoolean(args[1]);
if (useDisabledAlgo) {
Security.setProperty("jdk.tls.disabledAlgorithms", "");
}
if (args[0].equals("server")) {
try (TLSServer server = new TLSServer(useDisabledAlgo)) {
List<String> command = List.of(
Path.of(System.getProperty("java.home"), "bin", "java").toString(),
"TLSWontNegotiateDisabledCipherAlgos",
"client",
Boolean.toString(!useDisabledAlgo),
Integer.toString(server.getListeningPort())
);
ProcessBuilder builder = new ProcessBuilder(command);
Process p = builder.inheritIO().start();
server.run();
p.destroy();
}
} else if (args[0].equals("client")) {
try (TLSClient client = new TLSClient(Integer.parseInt(args[2]), useDisabledAlgo)) {
client.run();
}
}
}
private static class TLSClient extends SSLContextTemplate implements AutoCloseable {
private final SSLSocket socket;
public TLSClient(int portNumber, boolean useDisableAlgo) throws Exception {
SSLContext context = createClientSSLContext();
socket = (SSLSocket)context.getSocketFactory().createSocket("localhost", portNumber);
if (useDisableAlgo) {
socket.setEnabledCipherSuites(DisabledAlgorithms.DISABLED_CIPHERSUITES);
}
}
public void run() throws IOException {
try {
socket.getOutputStream().write("SECRET MESSAGE".getBytes(StandardCharsets.UTF_8));
throw new RuntimeException("SSL handshake completed successfully.");
} catch (SSLHandshakeException exc) {
if (!exc.getMessage().equals("Received fatal alert: handshake_failure")) {
throw new RuntimeException("Expected handshake_failure message. Got: "
+ "\"" + exc.getMessage() + "\" message.", exc);
}
}
}
@Override
public void close() throws Exception {
socket.close();
}
}
private static class TLSServer extends SSLContextTemplate implements AutoCloseable {
private SSLServerSocket serverSocket;
public TLSServer(boolean useDisableAlgo) throws Exception {
SSLContext ctx = createServerSSLContext();
serverSocket = (SSLServerSocket) ctx.getServerSocketFactory().createServerSocket(0);
if (useDisableAlgo) {
serverSocket.setEnabledCipherSuites(DisabledAlgorithms.DISABLED_CIPHERSUITES);
}
}
@Override
public void close() throws Exception {
serverSocket.close();
}
public int getListeningPort() {
return serverSocket.getLocalPort();
}
public void run() throws IOException {
try (Socket clientSocket = serverSocket.accept()) {
try {
byte[] bytes = clientSocket.getInputStream().readAllBytes();
throw new RuntimeException("The expected SSLHandshakeException was not thrown.");
} catch (SSLHandshakeException exc) {
if (!exc.getMessage().contains("no cipher suites in common")) {
throw exc;
} else {
System.out.println("Success: The connection could not be negotiated (as expected.)");
}
}
}
}
}
}
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment