JDK-8210334 : TLS 1.3 server fails if ClientHello doesn't have pre_shared_key and psk_key_exchange_modes
  • Type: Bug
  • Component: security-libs
  • Sub-Component: javax.net.ssl
  • Affected Version: 11
  • Priority: P2
  • Status: Closed
  • Resolution: Fixed
  • OS: generic
  • CPU: generic
  • Submitted: 2018-09-03
  • Updated: 2020-11-23
  • Resolved: 2018-09-06
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 8 Other
11.0.2Fixed 8u261Fixed openjdk8u272Fixed
Sub Tasks
JDK-8210918 :  
Description
TLS 1.3 server fails to handle a ClientHello message if both pre_shared_key and psk_key_exchange_modes are absent. The handshake process fails with the following exception:

javax.net.ssl.SSLHandshakeException: pre_shared_key key extension is offered without a psk_key_exchange_modes extension
	at java.base/sun.security.ssl.Alert.createSSLException(Alert.java:128)
	at java.base/sun.security.ssl.Alert.createSSLException(Alert.java:117)
	at java.base/sun.security.ssl.TransportContext.fatal(TransportContext.java:308)
	at java.base/sun.security.ssl.TransportContext.fatal(TransportContext.java:264)
	at java.base/sun.security.ssl.TransportContext.fatal(TransportContext.java:255)
	at java.base/sun.security.ssl.PskKeyExchangeModesExtension$PskKeyExchangeModesOnTradeAbsence.absent(PskKeyExchangeModesExtension.java:327)
	at java.base/sun.security.ssl.SSLExtension.absentOnTrade(SSLExtension.java:572)
	at java.base/sun.security.ssl.SSLExtensions.consumeOnTrade(SSLExtensions.java:180)
	at java.base/sun.security.ssl.ServerHello$T13ServerHelloProducer.produce(ServerHello.java:522)
	at java.base/sun.security.ssl.SSLHandshake.produce(SSLHandshake.java:436)
	at java.base/sun.security.ssl.ClientHello$T13ClientHelloConsumer.goServerHello(ClientHello.java:1189)
	at java.base/sun.security.ssl.ClientHello$T13ClientHelloConsumer.consume(ClientHello.java:1125)
	at java.base/sun.security.ssl.ClientHello$ClientHelloConsumer.onClientHello(ClientHello.java:831)
	at java.base/sun.security.ssl.ClientHello$ClientHelloConsumer.consume(ClientHello.java:792)
	at java.base/sun.security.ssl.SSLHandshake.consume(SSLHandshake.java:392)
	at java.base/sun.security.ssl.HandshakeContext.dispatch(HandshakeContext.java:444)
	at java.base/sun.security.ssl.HandshakeContext.dispatch(HandshakeContext.java:421)
	at java.base/sun.security.ssl.TransportContext.dispatch(TransportContext.java:178)
	at java.base/sun.security.ssl.SSLTransport.decode(SSLTransport.java:164)
	at java.base/sun.security.ssl.SSLSocketImpl.decode(SSLSocketImpl.java:1152)
	at java.base/sun.security.ssl.SSLSocketImpl.readHandshakeRecord(SSLSocketImpl.java:1063)
	at java.base/sun.security.ssl.SSLSocketImpl.startHandshake(SSLSocketImpl.java:402)
	at java.base/sun.security.ssl.SSLSocketImpl.ensureNegotiated(SSLSocketImpl.java:716)
	at java.base/sun.security.ssl.SSLSocketImpl$AppInputStream.read(SSLSocketImpl.java:799)
	at java.base/java.io.BufferedInputStream.fill(BufferedInputStream.java:252)
	at java.base/java.io.BufferedInputStream.read1(BufferedInputStream.java:292)
	at java.base/java.io.BufferedInputStream.read(BufferedInputStream.java:351)
	at java.base/java.io.FilterInputStream.read(FilterInputStream.java:107)
	at com.gypsyengineer.tlsbunny.jsse.SimpleEchoServer.run(SimpleEchoServer.java:72)
	at java.base/java.lang.Thread.run(Thread.java:834)

It's reproducible with OpenJDK 11 b28. Please see details in comments.
Comments
Removed noreg-trivial label as this fix is now tested by JDK-8210918
26-09-2018

webrev: http://cr.openjdk.java.net/~xuelei/8210334/webrev.00/
12-09-2018

Here is what TLS 1.3 spec says: https://tools.ietf.org/html/rfc8446#section-4.2.9 ... A client MUST provide a "psk_key_exchange_modes" extension if it offers a "pre_shared_key" extension. If clients offer "pre_shared_key" without a "psk_key_exchange_modes" extension, servers MUST abort the handshake. ... But a client is allowed not to send a pre_shared_key extension, so the handshake should continue even if a ClientHello doesn't contain pre_shared_key and psk_key_exchange_modes extensions. Here is a piece of output with -Djavax.net.debug=all: ... javax.net.ssl|DEBUG|0C|Thread-0|2018-09-03 21:15:31.770 CEST|ClientHello.java:788|Consuming ClientHello handshake message ( "ClientHello": { "client version" : "TLSv1.2", "random" : "60 B4 20 BB 38 51 D9 D4 7A CB 93 3D BE 70 39 9B F6 C9 2D A3 3A F0 1D 4F B7 70 E9 8C 03 25 F4 1D", "session id" : "", "cipher suites" : "[TLS_AES_128_GCM_SHA256(0x1301)]", "compression methods" : "00", "extensions" : [ "supported_versions (43)": { "versions": [TLSv1.3] }, "signature_algorithms (13)": { "signature schemes": [ecdsa_secp256r1_sha256] }, "supported_groups (10)": { "versions": [secp256r1] }, "key_share (51)": { "client_shares": [ { "named group": secp256r1 "key_exchange": { 0000: 04 4D 78 33 24 7A A1 9A F7 FF 06 A7 40 37 9E 65 .Mx3$z......@7.e 0010: 72 4A C2 62 B3 AE D9 9F 9C C0 A0 BD 62 6C 00 65 rJ.b........bl.e 0020: F2 85 D3 1D EE 50 9D 17 15 19 42 5C 4B 4A 2F 5B .....P....B\KJ/[ 0030: 1F 29 DF C4 4E 6C A6 FC B5 34 28 B7 77 79 A5 7F .)..Nl...4(.wy.. 0040: 1D } }, ] } ] } ) javax.net.ssl|DEBUG|0C|Thread-0|2018-09-03 21:15:31.770 CEST|SSLExtensions.java:167|Consumed extension: supported_versions javax.net.ssl|DEBUG|0C|Thread-0|2018-09-03 21:15:31.771 CEST|ClientHello.java:818|Negotiated protocol version: TLSv1.3 javax.net.ssl|DEBUG|0C|Thread-0|2018-09-03 21:15:31.772 CEST|PskKeyExchangeModesExtension.java:294|abort session resumption, no supported psk_dhe_ke PSK key exchange mode javax.net.ssl|DEBUG|0C|Thread-0|2018-09-03 21:15:31.772 CEST|PreSharedKeyExtension.java:765|Handling pre_shared_key absence. javax.net.ssl|DEBUG|0C|Thread-0|2018-09-03 21:15:31.772 CEST|SSLExtensions.java:148|Ignore unavailable extension: server_name javax.net.ssl|DEBUG|0C|Thread-0|2018-09-03 21:15:31.773 CEST|SSLExtensions.java:148|Ignore unavailable extension: max_fragment_length javax.net.ssl|DEBUG|0C|Thread-0|2018-09-03 21:15:31.773 CEST|SSLExtensions.java:148|Ignore unavailable extension: status_request javax.net.ssl|DEBUG|0C|Thread-0|2018-09-03 21:15:31.773 CEST|SSLExtensions.java:167|Consumed extension: supported_groups javax.net.ssl|DEBUG|0C|Thread-0|2018-09-03 21:15:31.774 CEST|SSLExtensions.java:167|Consumed extension: signature_algorithms javax.net.ssl|DEBUG|0C|Thread-0|2018-09-03 21:15:31.774 CEST|SSLExtensions.java:148|Ignore unavailable extension: signature_algorithms_cert javax.net.ssl|DEBUG|0C|Thread-0|2018-09-03 21:15:31.774 CEST|SSLExtensions.java:148|Ignore unavailable extension: cookie javax.net.ssl|DEBUG|0C|Thread-0|2018-09-03 21:15:31.775 CEST|SSLExtensions.java:167|Consumed extension: key_share javax.net.ssl|ALL|0C|Thread-0|2018-09-03 21:15:31.777 CEST|SignatureScheme.java:363|Ignore inactive signature sheme: dsa_sha256 javax.net.ssl|ALL|0C|Thread-0|2018-09-03 21:15:31.778 CEST|SignatureScheme.java:363|Ignore inactive signature sheme: ecdsa_sha224 javax.net.ssl|ALL|0C|Thread-0|2018-09-03 21:15:31.778 CEST|SignatureScheme.java:363|Ignore inactive signature sheme: rsa_sha224 javax.net.ssl|ALL|0C|Thread-0|2018-09-03 21:15:31.778 CEST|SignatureScheme.java:363|Ignore inactive signature sheme: dsa_sha224 javax.net.ssl|ALL|0C|Thread-0|2018-09-03 21:15:31.779 CEST|SignatureScheme.java:363|Ignore inactive signature sheme: dsa_sha1 javax.net.ssl|ALL|0C|Thread-0|2018-09-03 21:15:31.779 CEST|SignatureScheme.java:363|Ignore inactive signature sheme: rsa_md5 javax.net.ssl|ALL|0C|Thread-0|2018-09-03 21:15:31.780 CEST|SSLSessionImpl.java:203|Session initialized: Session(1536002131779|SSL_NULL_WITH_NULL_NULL) javax.net.ssl|DEBUG|0C|Thread-0|2018-09-03 21:15:31.780 CEST|SSLExtensions.java:182|Ignore unavailable extension: server_name javax.net.ssl|DEBUG|0C|Thread-0|2018-09-03 21:15:31.780 CEST|SSLExtensions.java:182|Ignore unavailable extension: max_fragment_length javax.net.ssl|DEBUG|0C|Thread-0|2018-09-03 21:15:31.780 CEST|SSLExtensions.java:182|Ignore unavailable extension: status_request javax.net.ssl|WARNING|0C|Thread-0|2018-09-03 21:15:31.781 CEST|SSLExtensions.java:190|Ignore impact of unsupported extension: supported_groups javax.net.ssl|DEBUG|0C|Thread-0|2018-09-03 21:15:31.781 CEST|SSLExtensions.java:199|Populated with extension: signature_algorithms javax.net.ssl|DEBUG|0C|Thread-0|2018-09-03 21:15:31.781 CEST|SSLExtensions.java:182|Ignore unavailable extension: signature_algorithms_cert javax.net.ssl|DEBUG|0C|Thread-0|2018-09-03 21:15:31.782 CEST|SSLExtensions.java:182|Ignore unavailable extension: application_layer_protocol_negotiation javax.net.ssl|WARNING|0C|Thread-0|2018-09-03 21:15:31.782 CEST|SSLExtensions.java:190|Ignore impact of unsupported extension: supported_versions javax.net.ssl|DEBUG|0C|Thread-0|2018-09-03 21:15:31.782 CEST|SSLExtensions.java:182|Ignore unavailable extension: cookie javax.net.ssl|ERROR|0C|Thread-0|2018-09-03 21:15:31.786 CEST|TransportContext.java:313|Fatal (HANDSHAKE_FAILURE): pre_shared_key key extension is offered without a psk_key_exchange_modes extension ( "throwable" : { javax.net.ssl.SSLHandshakeException: pre_shared_key key extension is offered without a psk_key_exchange_modes extension at java.base/sun.security.ssl.Alert.createSSLException(Alert.java:128) at java.base/sun.security.ssl.Alert.createSSLException(Alert.java:117) ... Steps to reproduce: $ git clone https://github.com/artem-smotrakov/tlsbunny $ cd tlsbunny $ javac -d classes -classpath src/main/java:src/test/java:${JUNIT}/lib/junit-4.12.jar src/test/java/com/gypsyengineer/tlsbunny/jsse/BasicTest.java $ java -classpath classes -Djavax.net.debug=all com.gypsyengineer.tlsbunny.jsse.BasicTest
03-09-2018