Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

8298867: Basics.java fails with SSL handshake exception #1800

Closed
wants to merge 1 commit into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
1 change: 0 additions & 1 deletion test/jdk/ProblemList.txt
Expand Up @@ -640,7 +640,6 @@ javax/net/ssl/SSLEngine/IllegalRecordVersion.java 8298873 generic-
javax/net/ssl/SSLEngine/EngineCloseOnAlert.java 8298868 generic-all
javax/net/ssl/SSLEngine/ConnectionTest.java 8298869 generic-all
javax/net/ssl/SSLEngine/CheckStatus.java 8298872 generic-all
javax/net/ssl/SSLEngine/Basics.java 8298867 generic-all

sun/security/smartcardio/TestChannel.java 8039280 generic-all
sun/security/smartcardio/TestConnect.java 8039280 generic-all
Expand Down
156 changes: 92 additions & 64 deletions test/jdk/javax/net/ssl/SSLEngine/Basics.java
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2003, 2021, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2003, 2022, 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
Expand All @@ -26,41 +26,53 @@
* @bug 4495742
* @summary Add non-blocking SSL/TLS functionality, usable with any
* I/O abstraction
*
* This is intended to test many of the basic API calls to the SSLEngine
* interface. This doesn't really exercise much of the SSL code.
*
* @library /test/lib
* @author Brad Wetmore
* @run main/othervm Basics
*/

import java.security.*;
import java.io.*;
import java.nio.*;
import java.util.Arrays;
import javax.net.ssl.*;
import javax.net.ssl.SSLEngineResult.*;

import jdk.test.lib.security.SecurityUtils;

public class Basics {

private static String pathToStores = "../etc";
private static String keyStoreFile = "keystore";
private static String trustStoreFile = "truststore";
private static String passwd = "passphrase";
private static final String PATH_TO_STORES = "../etc";
private static final String KEY_STORE_FILE = "keystore";
private static final String TRUSTSTORE_FILE = "truststore";

private static final String KEYSTORE_PATH =
System.getProperty("test.src", "./") + "/" + PATH_TO_STORES +
"/" + KEY_STORE_FILE;
private static final String TRUSTSTORE_PATH =
System.getProperty("test.src", "./") + "/" + PATH_TO_STORES +
"/" + TRUSTSTORE_FILE;

private static String keyFilename =
System.getProperty("test.src", "./") + "/" + pathToStores +
"/" + keyStoreFile;
private static String trustFilename =
System.getProperty("test.src", "./") + "/" + pathToStores +
"/" + trustStoreFile;
public static void main(String[] args) throws Exception {
SecurityUtils.removeFromDisabledTlsAlgs("TLSv1.1");

runTest("TLSv1.3", "TLS_AES_256_GCM_SHA384");
runTest("TLSv1.2", "TLS_RSA_WITH_AES_256_GCM_SHA384");
runTest("TLSv1.1", "TLS_DHE_DSS_WITH_AES_128_CBC_SHA");
}

public static void main(String args[]) throws Exception {
private static void runTest(String protocol, String cipherSuite) throws Exception {
System.out.printf("Testing %s with %s%n", protocol, cipherSuite);

KeyStore ks = KeyStore.getInstance("JKS");
KeyStore ts = KeyStore.getInstance("JKS");
char[] passphrase = "passphrase".toCharArray();

ks.load(new FileInputStream(keyFilename), passphrase);
ts.load(new FileInputStream(trustFilename), passphrase);
ks.load(new FileInputStream(KEYSTORE_PATH), passphrase);
ts.load(new FileInputStream(TRUSTSTORE_PATH), passphrase);

KeyManagerFactory kmf = KeyManagerFactory.getInstance("SunX509");
kmf.init(ks, passphrase);
Expand All @@ -77,75 +89,85 @@ public static void main(String args[]) throws Exception {
System.out.println(ssle);

String [] suites = ssle.getSupportedCipherSuites();
String secondSuite = suites[1];
String [] oneSuites = new String [] { secondSuite };
// sanity check that the ciphersuite we want to use is still supported
Arrays.stream(suites)
.filter(s -> s.equals(cipherSuite))
.findFirst()
.orElseThrow((() ->
new RuntimeException(cipherSuite +
" is not a supported ciphersuite.")));

printStrings("Supported Ciphersuites", suites);
printStrings("Enabled Ciphersuites", ssle.getEnabledCipherSuites());
ssle.setEnabledCipherSuites(oneSuites);
ssle.setEnabledCipherSuites(new String [] { cipherSuite });
printStrings("Set Ciphersuites", ssle.getEnabledCipherSuites());

suites = ssle.getEnabledCipherSuites();
if ((ssle.getEnabledCipherSuites().length != 1) ||
!(suites[0].equals(secondSuite))) {
throw new Exception("set ciphers not what was expected");
!(suites[0].equals(cipherSuite))) {
throw new RuntimeException("set ciphers not what was expected");
}

System.out.println();

String [] protocols = ssle.getSupportedProtocols();
String secondProtocol = protocols[1];
String [] oneProtocols = new String [] { protocols[1] };
// sanity check that the protocol we want is still supported
Arrays.stream(protocols)
.filter(p -> p.equals(protocol))
.findFirst()
.orElseThrow(() ->
new RuntimeException(protocol +
" is not a supported TLS protocol."));

printStrings("Supported Protocols", protocols);
printStrings("Enabled Protocols", ssle.getEnabledProtocols());
ssle.setEnabledProtocols(oneProtocols);
ssle.setEnabledProtocols(new String[]{ protocol });
printStrings("Set Protocols", ssle.getEnabledProtocols());

protocols = ssle.getEnabledProtocols();
if ((ssle.getEnabledProtocols().length != 1) ||
!(protocols[0].equals(secondProtocol))) {
throw new Exception("set protocols not what was expected");
!(protocols[0].equals(protocol))) {
throw new RuntimeException("set protocols not what was expected");
}

System.out.println("Checking get/setUseClientMode");

ssle.setUseClientMode(true);
if (ssle.getUseClientMode() != true) {
throw new Exception("set/getUseClientMode false");
if (!ssle.getUseClientMode()) {
throw new RuntimeException("set/getUseClientMode false");
}

ssle.setUseClientMode(false);
if (ssle.getUseClientMode() != false) {
throw new Exception("set/getUseClientMode true");
if (ssle.getUseClientMode()) {
throw new RuntimeException("set/getUseClientMode true");
}


System.out.println("Checking get/setClientAuth");

ssle.setNeedClientAuth(false);
if (ssle.getNeedClientAuth() != false) {
throw new Exception("set/getNeedClientAuth true");
if (ssle.getNeedClientAuth()) {
throw new RuntimeException("set/getNeedClientAuth true");
}

ssle.setNeedClientAuth(true);
if (ssle.getNeedClientAuth() != true) {
throw new Exception("set/getNeedClientAuth false");
if (!ssle.getNeedClientAuth()) {
throw new RuntimeException("set/getNeedClientAuth false");
}

ssle.setWantClientAuth(true);

if (ssle.getNeedClientAuth() == true) {
throw new Exception("set/getWantClientAuth need = true");
if (ssle.getNeedClientAuth()) {
throw new RuntimeException("set/getWantClientAuth need = true");
}

if (ssle.getWantClientAuth() != true) {
throw new Exception("set/getNeedClientAuth false");
if (!ssle.getWantClientAuth()) {
throw new RuntimeException("set/getNeedClientAuth false");
}

ssle.setWantClientAuth(false);
if (ssle.getWantClientAuth() != false) {
throw new Exception("set/getNeedClientAuth true");
if (ssle.getWantClientAuth()) {
throw new RuntimeException("set/getNeedClientAuth true");
}

/*
Expand All @@ -156,32 +178,27 @@ public static void main(String args[]) throws Exception {
System.out.println("checking session creation");

ssle.setEnableSessionCreation(false);
if (ssle.getEnableSessionCreation() != false) {
throw new Exception("set/getSessionCreation true");
if (ssle.getEnableSessionCreation()) {
throw new RuntimeException("set/getSessionCreation true");
}

ssle.setEnableSessionCreation(true);
if (ssle.getEnableSessionCreation() != true) {
throw new Exception("set/getSessionCreation false");
if (!ssle.getEnableSessionCreation()) {
throw new RuntimeException("set/getSessionCreation false");
}

/* Checking for overflow wrap/unwrap() */
ByteBuffer smallBB = ByteBuffer.allocate(10);

if (ssle.wrap(smallBB, smallBB).getStatus() !=
Status.BUFFER_OVERFLOW) {
throw new Exception("wrap should have overflowed");
throw new RuntimeException("wrap should have overflowed");
}

// For unwrap(), the BUFFER_OVERFLOW will not be generated
// until received SSL/TLS application data.
// Test test/jdk/javax/net/ssl/SSLEngine/LargePacket.java will check
// BUFFER_OVERFLOW/UNDERFLOW for both wrap() and unwrap().
//
//if (ssle.unwrap(smallBB, smallBB).getStatus() !=
// Status.BUFFER_OVERFLOW) {
// throw new Exception("unwrap should have overflowed");
//}

SSLSession ssls = ssle.getSession();

Expand All @@ -196,14 +213,18 @@ public static void main(String args[]) throws Exception {
*/
if (ssle.wrap(appBB, netBB).getHandshakeStatus() !=
HandshakeStatus.NEED_UNWRAP) {
throw new Exception("initial client hello needs unwrap");
throw new RuntimeException("initial client hello needs unwrap");
}

/* Checking for overflow wrap/unwrap() */

if (ssle.wrap(appBB, netBB).getStatus() !=
Status.BUFFER_OVERFLOW) {
throw new Exception("unwrap should have overflowed");
/*
* After the first call to wrap(), the handshake status is
* NEED_UNWRAP and we need to receive data before doing anymore
* handshaking.
*/
SSLEngineResult result = ssle.wrap(appBB, netBB);
if (result.getStatus() != Status.OK
&& result.bytesConsumed() != 0 && result.bytesProduced() != 0) {
throw new RuntimeException("wrap should have returned without doing anything");
}

ByteBuffer ro = appBB.asReadOnlyBuffer();
Expand All @@ -218,7 +239,7 @@ public static void main(String args[]) throws Exception {

try {
ssle.unwrap(netBB, ro);
throw new Exception("unwrap wasn't ReadOnlyBufferException");
throw new RuntimeException("unwrap wasn't ReadOnlyBufferException");
} catch (ReadOnlyBufferException e) {
System.out.println("Caught the ReadOnlyBuffer: " + e);
}
Expand All @@ -233,31 +254,38 @@ public static void main(String args[]) throws Exception {
appBB)).getStatus() !=
Status.BUFFER_UNDERFLOW) {
System.out.println(sslER);
throw new Exception("unwrap should underflow");
throw new RuntimeException("unwrap should underflow");
}

if ((sslER =
ssle.unwrap(ByteBuffer.wrap(incompleteSSLHeader),
appBB)).getStatus() !=
Status.BUFFER_UNDERFLOW) {
System.out.println(sslER);
throw new Exception("unwrap should underflow");
throw new RuntimeException("unwrap should underflow");
}

if ((sslER =
ssle.unwrap(ByteBuffer.wrap(smallv2Header),
appBB)).getStatus() !=
Status.BUFFER_UNDERFLOW) {
System.out.println(sslER);
throw new Exception("unwrap should underflow");
throw new RuntimeException("unwrap should underflow");
}

// junk inbound message
try {
/*
* Exceptions are thrown when:
* - the length field is correct but the data can't be decoded.
* - the length field is larger than max allowed.
*/
ssle.unwrap(ByteBuffer.wrap(gobblydegook), appBB);
throw new Exception("Didn't catch the nasty SSLException");
} catch (SSLException e) {
System.out.println("caught the nasty SSLException: " + e);
throw new RuntimeException("Expected SSLProtocolException was not thrown "
+ "for bad input");
} catch (SSLProtocolException e) {
System.out.println("caught the SSLProtocolException for bad decoding: "
+ e);
}

System.out.println("Test PASSED");
Expand All @@ -278,8 +306,8 @@ public static void main(String args[]) throws Exception {
(byte) 0x00 };

static byte [] gobblydegook = new byte [] {
// "HELLO HELLO"
(byte) 0x48, (byte) 0x45, (byte) 0x4C, (byte) 0x4C, (byte) 0x20,
// bad data but correct record length to cause decryption error
(byte) 0x48, (byte) 0x45, (byte) 0x4C, (byte) 0x00, (byte) 0x04,
(byte) 0x48, (byte) 0x45, (byte) 0x4C, (byte) 0x4C };

static void printStrings(String label, String [] strs) {
Expand Down