JDK-8241360 : BoringSSL rejects JSSE TLS 1.3 https connections when status_request extension is disabled
  • Type: Bug
  • Component: security-libs
  • Sub-Component: javax.net.ssl
  • Affected Version: 8u261,11
  • Priority: P4
  • Status: Open
  • Resolution: Unresolved
  • OS: generic
  • CPU: generic
  • Submitted: 2020-03-20
  • Updated: 2021-07-19
Related Reports
Relates :  
Sub Tasks
JDK-8244655 :  
JDK TLS compatibility issue with Google & Youtube server TLS implementation.

Problematic Protocol: TLSv1.3
Host: www.google.com, www.youtube.com
Cipher Suites - TLS_AES_128_GCM_SHA256, TLS_AES_256_GCM_SHA384

Regression Details : Test case works fine with JDK8u TLS1.3 EA build JDK8u261 b90, but doesn't work with JDK8u261 b91. So it's regression from b91 onwards. This issue is not reproducible in JDK11.0.8(personal build) and JDK15(build 15)

Attached the test case TestHttpsClient.java and failed(JDK8u261 b91) & passed(JDK8u261 b90) debug logs.
From log we can see, it fails with "Received fatal alert: protocol_version" just after ClientHello.

Stack trace(attached the full logs):
javax.net.ssl|SEVERE|01|main|2020-03-20 18:31:52.106 IST|TransportContext.java:319|Fatal (PROTOCOL_VERSION): Received fatal alert: protocol_version (
"throwable" : {
  javax.net.ssl.SSLHandshakeException: Received fatal alert: protocol_version
  	at sun.security.ssl.Alert.createSSLException(Alert.java:131)
  	at sun.security.ssl.Alert.createSSLException(Alert.java:117)
  	at sun.security.ssl.TransportContext.fatal(TransportContext.java:314)
  	at sun.security.ssl.Alert$AlertConsumer.consume(Alert.java:293)
  	at sun.security.ssl.TransportContext.dispatch(TransportContext.java:187)
  	at sun.security.ssl.SSLTransport.decode(SSLTransport.java:150)
  	at sun.security.ssl.SSLSocketImpl.decode(SSLSocketImpl.java:1177)
  	at sun.security.ssl.SSLSocketImpl.readHandshakeRecord(SSLSocketImpl.java:1088)
  	at sun.security.ssl.SSLSocketImpl.startHandshake(SSLSocketImpl.java:396)
  	at sun.net.www.protocol.https.HttpsClient.afterConnect(HttpsClient.java:559)
  	at sun.net.www.protocol.https.AbstractDelegateHttpsURLConnection.connect(AbstractDelegateHttpsURLConnection.java:185)
  	at sun.net.www.protocol.http.HttpURLConnection.getInputStream0(HttpURLConnection.java:1570)
  	at sun.net.www.protocol.http.HttpURLConnection.getInputStream(HttpURLConnection.java:1498)
  	at java.net.HttpURLConnection.getResponseCode(HttpURLConnection.java:480)
  	at sun.net.www.protocol.https.HttpsURLConnectionImpl.getResponseCode(HttpsURLConnectionImpl.java:352)
  	at TestHttpsClient.testIt(TestHttpsClient.java:43)
  	at TestHttpsClient.main(TestHttpsClient.java:17)}

Issue is not limited to status_request. Google/BoringSSL is treating JDK's TLSv1.3 handshake request separately (https://github.com/google/boringssl/blob/master/ssl/handshake_server.cc#L405), Here are the combinations, we found with different JDK versions client and google server. 1. We observe successful handshake in both 8u and 11u, if we remove signature_algorithms_cert extension from ClientHello through code and result not impacted by status_request enable/disable. 2. We observe handshake failure in both 8u and 11u, If signature_algorithms_cert extention is part of ClientHello and status_request extension is not part of ClientHello(jdk.tls.client.enableStatusRequestExtension=false) 3. With JDK 15 client, if TLS_CHACHA20_POLY1305_SHA256 is part of ciphersuites in ClientHello, we observe successful handshake 4. With JDK 15 client, if x25519 is mutually agreed supported_groups, we observe successful handshake 5. With JDK 15 client, if TLS_CHACHA20_POLY1305_SHA256 and x25519 are not available, we observe same behavior like 8u and 11u mentioned in 1 & 2. and, With all JDK versions client, we observe successful handshake if multiple supported_versions in ClientHello, "supported_versions (43)": { "versions": [TLSv1.3, TLSv1.2, TLSv1.1] } with all our observations, issue tuned out to be a very corner case, hence reducing the priority to P4. We decided to raise an issue against google/BoringSSL.

A workaround in BoringSSL for JDK-8211806 is being triggered by these different failure cases described above. In JDK-8211806, filed back in early JDK 11 timeframe, JSSE was not providing the SNI extension on resumed sessions. The is_probably_jdk11_with_tls13() function is used to fingerprint the ClientHello message to detect JDK 11. When any ClientHello matches the criteria in this function, BoringSSL will not negotiate the TLS 1.3 protocol. Most of the variants that alter extension values, cipher suites, etc. cause the checks in this function to register the hello as something other than JDK 11 and since JDK-8211806 has been fixed since 11.0.2 the TLS connection can proceed normally. However, if TLS 1.3 is the only supported_version value in the ClientHello, a common thread through all the failure cases we've seen, BoringSSL thinks this is JDK 11 and the server is forced to return Alert/fatal/protocol_version.

This issue is only seen *if* TLSv1.3 is the only protocol offered in ClientHello (coupled with rest of conditions highlighted above) As a developer reference help, any example docs/bugs for TLSv1.3 should include multiple protocols when overriding default settings. e.g. * https.protocols="TLSv1.3,TLSv1.2" * jdk.tls.client.protocols=TLSv1.3,TLSv1.2