Skip to content

Commit

Permalink
8298867: Basics.java fails with SSL handshake exception
Browse files Browse the repository at this point in the history
Reviewed-by: xuelei, rhalade
  • Loading branch information
mpdonova authored and TheShermanTanker committed Jan 17, 2023
1 parent 859ccd1 commit 06f9374
Show file tree
Hide file tree
Showing 2 changed files with 92 additions and 65 deletions.
1 change: 0 additions & 1 deletion test/jdk/ProblemList.txt
Expand Up @@ -590,7 +590,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/provider/KeyStore/DKSTest.sh 8180266 windows-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

3 comments on commit 06f9374

@openjdk-notifier
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@GoeLin
Copy link
Member

@GoeLin GoeLin commented on 06f9374 Sep 27, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

/backport jdk17u-dev

@openjdk
Copy link

@openjdk openjdk bot commented on 06f9374 Sep 27, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@GoeLin the backport was successfully created on the branch GoeLin-backport-06f9374e in my personal fork of openjdk/jdk17u-dev. To create a pull request with this backport targeting openjdk/jdk17u-dev:master, just click the following link:

➡️ Create pull request

The title of the pull request is automatically filled in correctly and below you find a suggestion for the pull request body:

Hi all,

This pull request contains a backport of commit 06f9374e from the openjdk/jdk repository.

The commit being backported was authored by Matthew Donovan on 17 Jan 2023 and was reviewed by Xue-Lei Andrew Fan and Rajan Halade.

Thanks!

If you need to update the source branch of the pull then run the following commands in a local clone of your personal fork of openjdk/jdk17u-dev:

$ git fetch https://github.com/openjdk-bots/jdk17u-dev.git GoeLin-backport-06f9374e:GoeLin-backport-06f9374e
$ git checkout GoeLin-backport-06f9374e
# make changes
$ git add paths/to/changed/files
$ git commit --message 'Describe additional changes made'
$ git push https://github.com/openjdk-bots/jdk17u-dev.git GoeLin-backport-06f9374e

Please sign in to comment.