JDK-8244932 : javax.net.ssl.SSLHandshakeException when client authentication is enabled
  • Type: Bug
  • Component: security-libs
  • Sub-Component: javax.net.ssl
  • Affected Version: 11,14
  • Priority: P3
  • Status: Closed
  • Resolution: Duplicate
  • OS: windows_10
  • CPU: x86_64
  • Submitted: 2020-05-11
  • Updated: 2021-08-03
  • Resolved: 2020-07-01
Related Reports
Duplicate :  
Description
ADDITIONAL SYSTEM INFORMATION :
The issue occurs on Oracle JDK 11+, as TLS 1.3 is not yet supported by previous version of Oracle JDK (I tested 11.0.6, 11.0.7, and 14.0.1) on Windows 10.

A DESCRIPTION OF THE PROBLEM :
When client authentication is enabled, the issue reported in JDK-8236039 arises. This can be tested by running the Go application attached to JDK-8236039 with switch "-A NEEDVFY", and connect to it with a JSSE client with TLS1.3 and client authentication configured.

The issue happened on Oracle JDK. I tested it with Zulu JDK without any issue.

STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
1) Run the Go application attached to JDK-8236039 with switch "-A NEEDVFY".
2) Create a JSSE client with client authentication properly configured:

SSLContext sslContext = SSLContextBuilder
                .create()
                .loadKeyMaterial(keyStore, keyStoreIntegrityKey, entryConfidentialityKey)
                .loadTrustMaterial(trustStore, trustStoreIntegrityKey)
                .build();

EXPECTED VERSUS ACTUAL BEHAVIOR :
EXPECTED -
I expected the JSSE client to handshake properly with the server.
ACTUAL -
I received the following exception:

Exception in thread "main" javax.net.ssl.SSLHandshakeException: extension (5) should not be presented in certificate_request
	at java.base/sun.security.ssl.Alert.createSSLException(Alert.java:131)
	at java.base/sun.security.ssl.Alert.createSSLException(Alert.java:117)
	at java.base/sun.security.ssl.TransportContext.fatal(TransportContext.java:314)
	at java.base/sun.security.ssl.TransportContext.fatal(TransportContext.java:270)
	at java.base/sun.security.ssl.TransportContext.fatal(TransportContext.java:261)
	at java.base/sun.security.ssl.SSLExtensions.<init>(SSLExtensions.java:89)
	at java.base/sun.security.ssl.CertificateRequest$T13CertificateRequestMessage.<init>(CertificateRequest.java:818)
	at java.base/sun.security.ssl.CertificateRequest$T13CertificateRequestConsumer.consume(CertificateRequest.java:922)
	at java.base/sun.security.ssl.SSLHandshake.consume(SSLHandshake.java:392)
	at java.base/sun.security.ssl.HandshakeContext.dispatch(HandshakeContext.java:451)
	at java.base/sun.security.ssl.HandshakeContext.dispatch(HandshakeContext.java:428)
	at java.base/sun.security.ssl.TransportContext.dispatch(TransportContext.java:184)
	at java.base/sun.security.ssl.SSLTransport.decode(SSLTransport.java:164)
	at java.base/sun.security.ssl.SSLSocketImpl.decode(SSLSocketImpl.java:1151)
	at java.base/sun.security.ssl.SSLSocketImpl.readHandshakeRecord(SSLSocketImpl.java:1062)
	at java.base/sun.security.ssl.SSLSocketImpl.startHandshake(SSLSocketImpl.java:402)
        ......

---------- BEGIN SOURCE ----------
import javax.net.ssl.*;
import java.io.File;
import java.security.KeyStore;
import java.security.SecureRandom;

public class SSLSocketClient {

    public static void main(String[] args) throws Exception {
        File trustStore = new File("trustStore.p12");
        File keyStore = new File("keyStore.p12");
        char[] password = "123".toCharArray();

        KeyManagerFactory kmf = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm());
        KeyStore ks = KeyStore.getInstance(keyStore, password);
        kmf.init(ks, password);

        TrustManagerFactory tmf = TrustManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm());
        KeyStore ts = KeyStore.getInstance(trustStore, password);
        tmf.init(ts);

        SSLContext sslContext = SSLContext.getInstance("TLSv1.3");
        sslContext.init(kmf.getKeyManagers(), tmf.getTrustManagers(), new SecureRandom());

        SSLSocketFactory factory = sslContext.getSocketFactory();
        SSLSocket socket = (SSLSocket) factory.createSocket("localhost", 443);
        socket.startHandshake();
    }
}
---------- END SOURCE ----------

CUSTOMER SUBMITTED WORKAROUND :
I used Zulu JDK to compile my program, and it worked OK.

FREQUENCY : always



Comments
This issue is a duplicate of JDK-8236039. It was already fixed in OracleJDK 11.0.8 and is now set to be part of OracleJDK 14.0.2 and just went into OpenJDK 14u: https://hg.openjdk.java.net/jdk-updates/jdk14u/rev/452c05ce40d2 There are no plans at this time to backport this to Oracle JDK 13.
22-06-2020

Just tried this with the latest JDK using both -A NEEDVFY and -A WANT and a JSSE client (not the one in the bug description) both with and without certificates. The only failure cases I have run into so far have been cases where client authentication was required and no certificates were provided. But that is a different problem than is being described here. For the other cases, I can see the JSSE client not crashing on the CertificateRequest message with status_request in it. I still need to rerun the same tests against some of the other JDK 11 releases cited in this bug to see if I can reproduce it there. I will also try with the client POC provided in the description.
27-05-2020

The SSLExtension.CR_STATUS_REQUEST does not define the handshake type, and then SSLExtension.valueOf(handshakeType, extId) may not work as expected. Maybe, we could have a simple fix so that this extension could be ignored, or considering to support status_request in CR.
22-05-2020