JDK-8207317 : SSLEngine negotiation fail exception behavior changed from fail-fast to fail-lazy
  • Type: Bug
  • Component: security-libs
  • Sub-Component: javax.net.ssl
  • Affected Version: 11
  • Priority: P1
  • Status: Closed
  • Resolution: Fixed
  • Submitted: 2018-07-14
  • Updated: 2020-11-23
  • Resolved: 2018-08-21
The Version table provides details related to the release that this issue/RFE will be addressed.

Unresolved : Release in which this issue/RFE will be addressed.
Resolved: Release in which this issue/RFE has been resolved.
Fixed : Release in which this issue/RFE has been fixed. The release containing this fix may be available for download as an Early Access Release or a General Availability Release.

To download the current JDK release, click here.
JDK 11 JDK 12 JDK 8 Other
11 b28Fixed 12Fixed 8u261Fixed openjdk8u272Fixed
Description
I found a difference between JDKb20 and JDKb15  in the timing of handshake failure  when the application  protocol negotiation fails.
Specifically, the behavior change is when the *SSLHandshakeException* is thrown, 
 
For TLSv1.2 ( with JDKb15), it is thrown immediately when server encounters the fatal error and *tries to send the fatal error to peer*
For TLSv1.3 or TLSv1.2 (JDKb20),  it is thrown after the server *successfully* sends the fatal error  and *fails during when client receives the fatal error*
 
For TLSv1.2 , In pre-JDKb20 (tested with JDKb15),
1.	Client wraps 264 bytes and goes  to NEED_UNWRAP
2.	Server unwraps 264 bytes and goes  to  NEED_TASK
3.	Server runs delegated tasks and fails with fatal error: no_application_protocol (from logs), but API from java does not throw any error yet, and  status changes to NEED_WRAP
4.	Server tries to wrap and the ���wrap��� call throws  SSLHandshakeException: No matching ALPN values
 
For TLS 1.3/TLSv1.2 (JDKb20),
1.	Client wraps 437 bytes and goes to NEED_UNWRAP
2.	Server unwraps 437 bytes and goes to NEED_TASK
3.	Server runs delegated tasks and fails with Fatal (NO_APPLICATION_PROTOCOL) (from logs), but API from java does not throw any error yet ,and status changes to NEED_WRAP
4.	Server wraps 7 bytes and goes to NOT_HANDSHAKING (over all status to CLOSED) and DOES NOT throw  SSLHandshakeException    -��� THIS IS THE CHANGE IN BEHAVIOR FROM TLSv1.2
5.	Client tries to unwrap 7 bytes and ���unwrap��� call throws  SSLHandshakeException: Received fatal alert: no_application_protocol
 

Comments
Fix request approved
21-08-2018

Fix Request The new TLSv1.3 implementation in JDK 11 changed the behavior of SSLEngine's Exception reporting from delegated tasks from fail-fast to lazy fail, and thus changed the ordering of the output. The original SSLEngine design called for Exceptions to be thrown on a wrap/unwrap immediately following a delegated task generating said exception, which would then allow the user to query up the SSLEngine state and wrap/unwrap the final alert messages before progressing to the completely CLOSED state. The change caused the exception to be returned on a successive wrap/unwrap *AFTER* the alert was wrapped and the SSLEngine's inbound/outbound sides were closed, meaning that existing applications might not know to call the wrap/unwrap again, which would mean the SSLEngine would silently fail. The fix is to revert to the previous behavior, that is, check for thrown exceptions at the beginning of wrap/unwrap calls, and rethrow at that time, rather than wait until all inbound/outbound data is consumed/produced, and then require an extra wrap/unwrap to generate the exception. Initial details reported in: http://mail.openjdk.java.net/pipermail/security-dev/2018-August/017818.html Risk is fairly low, as this is occurring as the connections are on their way down, and shouldn't impact data exchange. We have run all tier1/tier2 tests via mach5, and JCK will do a pass before integration. Discussion of fix/webrev: http://mail.openjdk.java.net/pipermail/security-dev/2018-August/017942.html http://cr.openjdk.java.net/~wetmore/8207317/webrev.00/
20-08-2018

The TLSv1.3 implementation changed the behavior of SSLEngine's Exception reporting from a fail-fast to a lazy fail, and thus changed the ordering of the output. The original SSLEngine design called for Exceptions to be thrown on a wrap/unwrap immediately following a delegated task generating said exception, which would then allow the user to query up the SSLEngine state and wrap/unwrap the final alert messages before progressing to the completely CLOSED state. The change caused the exception to be returned on a successive wrap/unwrap *AFTER* the alert was wrapped and the SSLEngine's inbound/outbound sides were closed, meaning that existing applications might not know to call the wrap/unwrap again, which would mean the SSLEngine would silently fail. Proposed fix is to revert to the previous behavior.
18-08-2018

More involved than originally thought. Exception reporting/handling/recovery model has changed from original implementation.
07-08-2018

Simple reversed case. One character fix.
02-08-2018

Can you please provide a link to the current JCK code for this release, preferably with a simple command line example to run it? Ideally something like: /net/foo/export/jdk11/bin/java SSLEngineALPN Thanks.
27-07-2018