Bug 63892 - TLS 1.3 with client auth fails with NOT_HANDSHAKING during handshake
Summary: TLS 1.3 with client auth fails with NOT_HANDSHAKING during handshake
Status: RESOLVED INVALID
Alias: None
Product: Tomcat 9
Classification: Unclassified
Component: Connectors (show other bugs)
Version: 9.0.x
Hardware: PC All
: P2 normal (vote)
Target Milestone: -----
Assignee: Tomcat Developers Mailing List
URL:
Keywords:
Depends on:
Blocks:
 
Reported: 2019-10-30 10:20 UTC by Mathias
Modified: 2019-11-06 09:20 UTC (History)
0 users



Attachments
keystores for testing (5.53 KB, application/x-zip-compressed)
2019-11-05 09:00 UTC, Mathias
Details
tomcat 9.0.27 logfile (35.67 KB, text/plain)
2019-11-05 09:01 UTC, Mathias
Details

Note You need to log in before you can comment on or make changes to this bug.
Description Mathias 2019-10-30 10:20:33 UTC
As discussed in 
http://mail-archives.apache.org/mod_mbox/tomcat-users/201910.mbox/%3Cee96a553-81ea-ad01-f51b-f638de934600%40apache.org%3E


I installed Tomcat 9.0.27 on my Windows 7 machine and using the following java runtime to get support for TLSv1.3

Server built:          Oct 7 2019 09:57:22 UTC
Server version number: 9.0.27.0
Architecture:          amd64
JVM Version:           13.0.1+9
JVM Vendor:            Oracle Corporation


My TLS connector is configured with client auth.
	<Connector port="8443" protocol="org.apache.coyote.http11.Http11NioProtocol"
		   maxThreads="150" SSLEnabled="true" sslImplementationName="org.apache.tomcat.util.net.jsse.JSSEImplementation"
		   keystoreFile="conf/keys/server.jks" keystoreType="JKS" keystorePass="" keyAlias="server"
		   clientAuth="true" truststoreFile="conf/keys/clients.jks" truststorePass="" sslProtocol="TLS">
   </Connector>

If i connect with a browser i can choose my client key but get an error afterwards.

The following error happens in SecureNioChannel:
28-Oct-2019 10:04:27.939 FINE [https-jsse-nio-8443-exec-4] org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun Error during SSL handshake
	java.io.IOException: NOT_HANDSHAKING during handshake
		at org.apache.tomcat.util.net.SecureNioChannel.handshake(SecureNioChannel.java:193)
		at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1556)
		at org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:49)
		at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1128)
		at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:628)
		at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61)
		at java.base/java.lang.Thread.run(Thread.java:830)

With java runtime 8 everything works fine but i do not have TLSv1.3 there, so only a TLSv1.2 handshake is done.

Please note that the problem also occur with 8.5.x.
Comment 1 Mark Thomas 2019-11-04 09:13:37 UTC
The Tomcat unit tests include a test for this that has been passing for quite some time.

I am unable to re-create this issue using the same configuration but my own keys / certificates with OpekJDK 13.0.1+9

At this point I suspect a client issue and/or configuration issue. Please provide:

a) full version information for the client used to re-create this issue

b) a set of keys/certificates we can use to re-create the issue.
Comment 2 Mathias 2019-11-05 09:00:29 UTC
Created attachment 36871 [details]
keystores for testing
Comment 3 Mathias 2019-11-05 09:01:06 UTC
Find attached the following keystores:

client.p12 for import in Firefox 70.0.1.

localhost.jks for the tomcat keystoreFile parameter

client_certs.jks for the tomcat truststoreFile parameter

No password needed for all of them.

I always open a new private tab for testing with url https://localhost:8443/
Comment 4 Mathias 2019-11-05 09:01:47 UTC
Created attachment 36872 [details]
tomcat 9.0.27 logfile
Comment 5 Remy Maucherat 2019-11-05 10:16:56 UTC
Looking at it, it seems to do the same on Java 11, so the BZ is likely misleading.

After unwrap there's a task being run, after the task is run in the tasks() method, the handshake status is returned as NOT_HANDSHAKING by the SSL engine. I don't understand what is going on or what the failure is at this point, but it might not be a Tomcat issue.

We could probably add additional debug logging in SecureNio(2)Channel to trace the  processing of handshake() when needed.

05-Nov-2019 11:09:26.157 FINE [https-jsse-nio-8443-exec-1] org.apache.tomcat.util.net.SecureNioChannel.handshake handshakeStatus: NEED_UNWRAP
Run task: sun.security.ssl.SSLEngineImpl$DelegatedTask@4de31d09
sslEngine.getHandshakeStatus() after tasks: NEED_WRAP
05-Nov-2019 11:09:26.236 FINE [https-jsse-nio-8443-exec-1] org.apache.tomcat.util.net.SecureNioChannel.handshake handshakeStatus: NEED_WRAP
05-Nov-2019 11:09:26.237 FINE [https-jsse-nio-8443-exec-1] org.apache.tomcat.util.net.NioEndpoint$NioSocketWrapper.registerWriteInterest Registered write interest for [org.apache.tomcat.util.net.NioEndpoint$NioSocketWrapper@1184d389:org.apache.tomcat.util.net.SecureNioChannel@1ebc5f1c:java.nio.channels.SocketChannel[connected local=/0:0:0:0:0:0:0:1:8443 remote=/0:0:0:0:0:0:0:1:57612]]
05-Nov-2019 11:09:26.237 FINE [https-jsse-nio-8443-exec-2] org.apache.tomcat.util.net.SecureNioChannel.handshake handshakeStatus: NEED_WRAP
05-Nov-2019 11:09:26.238 FINE [https-jsse-nio-8443-exec-2] org.apache.tomcat.util.net.NioEndpoint$NioSocketWrapper.registerWriteInterest Registered write interest for [org.apache.tomcat.util.net.NioEndpoint$NioSocketWrapper@1184d389:org.apache.tomcat.util.net.SecureNioChannel@1ebc5f1c:java.nio.channels.SocketChannel[connected local=/0:0:0:0:0:0:0:1:8443 remote=/0:0:0:0:0:0:0:1:57612]]
05-Nov-2019 11:09:26.238 FINE [https-jsse-nio-8443-exec-3] org.apache.tomcat.util.net.SecureNioChannel.handshake handshakeStatus: NEED_WRAP
05-Nov-2019 11:09:26.247 FINE [https-jsse-nio-8443-exec-3] org.apache.tomcat.util.net.NioEndpoint$NioSocketWrapper.registerReadInterest Registered read interest for [org.apache.tomcat.util.net.NioEndpoint$NioSocketWrapper@1184d389:org.apache.tomcat.util.net.SecureNioChannel@1ebc5f1c:java.nio.channels.SocketChannel[connected local=/0:0:0:0:0:0:0:1:8443 remote=/0:0:0:0:0:0:0:1:57612]]
05-Nov-2019 11:09:26.251 FINE [https-jsse-nio-8443-exec-4] org.apache.tomcat.util.net.SecureNioChannel.handshake handshakeStatus: NEED_UNWRAP
Run task: sun.security.ssl.SSLEngineImpl$DelegatedTask@427c714f
sslEngine.getHandshakeStatus() after tasks: NOT_HANDSHAKING
Comment 6 Mark Thomas 2019-11-05 13:36:47 UTC
Interesting. The private browsing part is important. I can re-create this with the standard Tomcat certs we use in the unit tests now. Also seen on Linux and Firefox 70.0.

I only see this with JSSE, not with OpenSSL.

I'm going to capture a couple of network traces to see if I can see a difference.
Comment 7 Mark Thomas 2019-11-05 16:17:34 UTC
This looks like a JVM bug to me.

When Firefox's private browsing is enabled the penultimate handshake status is NEED_TASK. Immediately after calling tasks() the handshake status is NOT_HANDSHAKING rather than finished.

I'll write this up as an OpenJDK bug. I'll link to it here when that is done.

We could work around it but it seems rare enough (at this point) that a workaround of "use OpenSSL if you need TLS 1.3 and are hitting this bug" is sufficient.
Comment 8 Remy Maucherat 2019-11-05 16:29:54 UTC
+1

I don't see how it can be a Tomcat issue at this point since the NOT_HANDSHAKING status occurs after running the task run(), without errors and without further wrapping or unwrapping.

Working around it didn't work for me, I tried to return 0 (handshake complete) but then the engine is really not in "handshake finished" status so it fails. There's probably no way to escape this NOT_HANDSHAKING status once you go into it.
Comment 9 Mark Thomas 2019-11-05 17:08:10 UTC
https://bugs.openjdk.java.net/browse/JDK-8233619

I am resolving this Tomcat bug as invalid on the basis the root cause is a JVM TLSv1.3 bug. If the OpenJDK folks indicate that Tomcat is doing something wrong, we can re-open this bug and investigate further.
Comment 10 Christopher Schultz 2019-11-05 23:38:11 UTC
Wild guess based only upon comments here: Java's TLSv1.3 implementation does not support TLS ESNI (encrypted SNI) extension.

Usually, SNI is sent with initial TLS handshake. When the browser is in "private" mode, perhaps ESNI is used.

Again, a wild guess. But it might explain what is happening, here.
Comment 11 Mark Thomas 2019-11-06 09:20:40 UTC
(In reply to Christopher Schultz from comment #10)

> Again, a wild guess. But it might explain what is happening, here.

It doesn't. The failure happens right at the end of the handshake more details of exactly where in the JDK bug report.