JDK-8224997 : ChaCha20-Poly1305 TLS cipher suite decryption throws ShortBufferException
  • Type: Bug
  • Component: security-libs
  • Sub-Component: javax.net.ssl
  • Affected Version: 11,12,13
  • Priority: P3
  • Status: Resolved
  • Resolution: Fixed
  • Submitted: 2019-05-29
  • Updated: 2020-07-30
  • Resolved: 2020-07-22
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 13 JDK 14
11.0.10-oracleFixed 13.0.4Fixed 14Fixed
Related Reports
Duplicate :  
Duplicate :  
Relates :  
Description
When decrypting a large TLS application data record coming through a websocket, the ChaCha20-Poly1305 AEAD decryption code is throwing a ShortBufferException:

io.netty.handler.codec.DecoderException: javax.net.ssl.SSLException: Fail to unwrap network record
	at io.netty.handler.codec.ByteToMessageDecoder.callDecode(ByteToMessageDecoder.java:472)
	at io.netty.handler.codec.ByteToMessageDecoder.channelRead(ByteToMessageDecoder.java:278)
	at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:374)
	at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:360)
	at io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:352)
	at io.netty.channel.DefaultChannelPipeline$HeadContext.channelRead(DefaultChannelPipeline.java:1408)
	at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:374)
	at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:360)
	at io.netty.channel.DefaultChannelPipeline.fireChannelRead(DefaultChannelPipeline.java:930)
	at io.netty.channel.nio.AbstractNioByteChannel$NioByteUnsafe.read(AbstractNioByteChannel.java:163)
	at io.netty.channel.nio.NioEventLoop.processSelectedKey(NioEventLoop.java:682)
	at io.netty.channel.nio.NioEventLoop.processSelectedKeysOptimized(NioEventLoop.java:617)
	at io.netty.channel.nio.NioEventLoop.processSelectedKeys(NioEventLoop.java:534)
	at io.netty.channel.nio.NioEventLoop.run(NioEventLoop.java:496)
	at io.netty.util.concurrent.SingleThreadEventExecutor$5.run(SingleThreadEventExecutor.java:906)
	at io.netty.util.internal.ThreadExecutorMap$2.run(ThreadExecutorMap.java:74)
	at io.netty.util.concurrent.FastThreadLocalRunnable.run(FastThreadLocalRunnable.java:30)
	at java.base/java.lang.Thread.run(Thread.java:835)
Caused by: javax.net.ssl.SSLException: Fail to unwrap network record
	at java.base/sun.security.ssl.Alert.createSSLException(Alert.java:133)
	at java.base/sun.security.ssl.TransportContext.fatal(TransportContext.java:320)
	at java.base/sun.security.ssl.TransportContext.fatal(TransportContext.java:263)
	at java.base/sun.security.ssl.SSLEngineImpl.unwrap(SSLEngineImpl.java:470)
	at java.base/sun.security.ssl.SSLEngineImpl.unwrap(SSLEngineImpl.java:433)
	at java.base/javax.net.ssl.SSLEngine.unwrap(SSLEngine.java:634)
	at io.netty.handler.ssl.SslHandler$SslEngineType$3.unwrap(SslHandler.java:295)
	at io.netty.handler.ssl.SslHandler.unwrap(SslHandler.java:1332)
	at io.netty.handler.ssl.SslHandler.decodeJdkCompatible(SslHandler.java:1227)
	at io.netty.handler.ssl.SslHandler.decode(SslHandler.java:1274)
	at io.netty.handler.codec.ByteToMessageDecoder.decodeRemovalReentryProtection(ByteToMessageDecoder.java:502)
	at io.netty.handler.codec.ByteToMessageDecoder.callDecode(ByteToMessageDecoder.java:441)
	... 17 common frames omitted
Caused by: java.lang.RuntimeException: javax.crypto.ShortBufferException: Output buffer too small
	at java.base/com.sun.crypto.provider.ChaCha20Cipher.engineDoFinal(ChaCha20Cipher.java:703)
	at java.base/javax.crypto.CipherSpi.bufferCrypt(CipherSpi.java:826)
	at java.base/javax.crypto.CipherSpi.engineDoFinal(CipherSpi.java:730)
	at java.base/javax.crypto.Cipher.doFinal(Cipher.java:2503)
	at java.base/sun.security.ssl.SSLCipher$T12CC20P1305ReadCipherGenerator$CC20P1305ReadCipher.decrypt(SSLCipher.java:2188)
	at java.base/sun.security.ssl.SSLEngineInputRecord.decodeInputRecord(SSLEngineInputRecord.java:240)
	at java.base/sun.security.ssl.SSLEngineInputRecord.decode(SSLEngineInputRecord.java:197)
	at java.base/sun.security.ssl.SSLEngineInputRecord.decode(SSLEngineInputRecord.java:160)
	at java.base/sun.security.ssl.SSLTransport.decode(SSLTransport.java:108)
	at java.base/sun.security.ssl.SSLEngineImpl.decode(SSLEngineImpl.java:681)
	at java.base/sun.security.ssl.SSLEngineImpl.readRecord(SSLEngineImpl.java:636)
	at java.base/sun.security.ssl.SSLEngineImpl.unwrap(SSLEngineImpl.java:454)
	... 25 common frames omitted
Caused by: javax.crypto.ShortBufferException: Output buffer too small
	at java.base/com.sun.crypto.provider.ChaCha20Cipher$EngineAEADDec.doFinal(ChaCha20Cipher.java:1360)
	at java.base/com.sun.crypto.provider.ChaCha20Cipher.engineDoFinal(ChaCha20Cipher.java:701)
	... 36 common frames omitted
Comments
Fix request (13u) The patch applies cleanly. The test fails without fix and passes with the fix.
14-05-2020

Fix Request (11u) This fixes the day 1 problem with ChaCha20 cipher. Patch applies cleanly to 11u, new test fails without the product patch, passes with it. Patched JDK passes tier{1,2,3} suite.
14-02-2020

This actually looks like introduced in 11 by JDK-8153029? New test fails there as well, and passes with this fix.
14-02-2020

URL: https://hg.openjdk.java.net/jdk/jdk/rev/34bbd91b1522 User: jnimeh Date: 2019-08-17 13:21:28 +0000
19-08-2019

I have isolated the problem to a specific set of conditions. The problem is not in sun.security.ssl at all. It is in the ChaCha20-Poly1305 implementation. This only occurs when the following conditions all apply: 1) doFinal(ByteBuffer, ByteBuffer) is called using ChaCha20-Poly1305 in decrypt mode 2) the input length exceeds 4000 bytes 3) both the input and output ByteBuffers are direct (that is, they have no backing array) This set of events causes the chunking code in CipherSpi.bufferCrypt to pass the data to ChaCha20-Poly1305 in 4k chunks. The handling of the last chunk in the ChaCha20-Poly1305 implementation doesn't deal with the lengths properly and that causes the ShortBufferException to be thrown. I'm still going through the code to determine why this doesn't fail when either input or output buffers are array-backed.
08-08-2019

With the use of the Jetty HttpClient, I am able to hit my own Apache server and with pages of a certain size I can make the issue happen. If the application_data record is 7455 bytes in length and a ChaCha20-Poly1305 cipher suite is in use, it will hit this issue. This occurs with 12.0.1 and 12.0.2, but interestingly enough it will not run into this in the latest jdk/jdk. I am looking into why it does not occur in jdk/jdk.
01-08-2019

Source of the issue from the Netty folks: https://github.com/netty/netty/issues/9150 Some debug output with -Djavax.net.debug=ssl:all: https://hasteb.in/ucalevob.makefile
29-05-2019