Offhand, sounds like a bug to me. I've filed:
https://bugs.openjdk.java.net/browse/JDK-8283577
to track.
It's possible an optimization might have been done using an in-place
en/decryption, but it should work.
By chance, do you have a simple reproducer handy? If not, we should be
able to come up with one if it is what I think it is.
Brad
On 3/23/2022 9:54 AM, Chris Vest wrote:
Hi,
In Netty we've been trying to design some safer APIs, and attempted to
make more use of read-only ByteBuffers.
We discovered that SSLEngine.unwrap does not like read-only input
buffers, even though the input buffers should in theory only be read
from. We obviously make sure that the output buffers are writable.
By my reading of the javadoc, and the code, I believe this was intended
to work - or at least not intended to not work - but probably wasn't
tested directly.
When we try we get this stack trace on adopt-openjdk-11.0.7:
javax.net.ssl.SSLProtocolException: null
at java.base/sun.security.ssl.Alert.createSSLException(Alert.java:129)
at
java.base/sun.security.ssl.TransportContext.fatal(TransportContext.java:326)
at
java.base/sun.security.ssl.TransportContext.fatal(TransportContext.java:269)
at
java.base/sun.security.ssl.TransportContext.fatal(TransportContext.java:264)
at java.base/sun.security.ssl.SSLTransport.decode(SSLTransport.java:118)
at
java.base/sun.security.ssl.SSLEngineImpl.decode(SSLEngineImpl.java:668)
at
java.base/sun.security.ssl.SSLEngineImpl.readRecord(SSLEngineImpl.java:623)
at
java.base/sun.security.ssl.SSLEngineImpl.unwrap(SSLEngineImpl.java:441)
at
java.base/sun.security.ssl.SSLEngineImpl.unwrap(SSLEngineImpl.java:420)
at java.base/javax.net.ssl.SSLEngine.unwrap(SSLEngine.java:674)
at io.netty5.handler.ssl.EngineWrapper.unwrap(EngineWrapper.java:100)
at io.netty5.handler.ssl.SslHandler.unwrap(SslHandler.java:1227)
at
io.netty5.handler.ssl.SslHandler.decodeJdkCompatible(SslHandler.java:1105)
at io.netty5.handler.ssl.SslHandler.decode(SslHandler.java:1165)
at
io.netty5.handler.codec.ByteToMessageDecoderForBuffer.decodeRemovalReentryProtection(ByteToMessageDecoderForBuffer.java:384)
at
io.netty5.handler.codec.ByteToMessageDecoderForBuffer.callDecode(ByteToMessageDecoderForBuffer.java:327)
... 20 common frames omitted
Caused by: java.nio.ReadOnlyBufferException: null
at java.base/javax.crypto.Cipher.doFinal(Cipher.java:2493)
at
java.base/sun.security.ssl.SSLCipher$T12GcmReadCipherGenerator$GcmReadCipher.decrypt(SSLCipher.java:1629)
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)
... 31 common frames omitted
I also tried this on a panama-preview snapshot JDK I have, and got a
similar stack trace:
% java -version
openjdk version "19-internal" 2022-09-20
OpenJDK Runtime Environment (fastdebug build
19-internal-adhoc.chris.panama-foreign)
OpenJDK 64-Bit Server VM (fastdebug build
19-internal-adhoc.chris.panama-foreign, mixed mode)
% git show
commit 144af9f43cd2d6f88b675b8c85e4034e5b9d6695 (HEAD ->
foreign-preview, origin/foreign-preview)
javax.net.ssl.SSLProtocolException: null
at java.base/sun.security.ssl.Alert.createSSLException(Alert.java:129)
at
java.base/sun.security.ssl.TransportContext.fatal(TransportContext.java:371)
at
java.base/sun.security.ssl.TransportContext.fatal(TransportContext.java:314)
at
java.base/sun.security.ssl.TransportContext.fatal(TransportContext.java:309)
at java.base/sun.security.ssl.SSLTransport.decode(SSLTransport.java:121)
at
java.base/sun.security.ssl.SSLEngineImpl.decode(SSLEngineImpl.java:736)
at
java.base/sun.security.ssl.SSLEngineImpl.readRecord(SSLEngineImpl.java:691)
at
java.base/sun.security.ssl.SSLEngineImpl.unwrap(SSLEngineImpl.java:506)
at
java.base/sun.security.ssl.SSLEngineImpl.unwrap(SSLEngineImpl.java:482)
at java.base/javax.net.ssl.SSLEngine.unwrap(SSLEngine.java:719)
at io.netty5.handler.ssl.EngineWrapper.unwrap(EngineWrapper.java:100)
at io.netty5.handler.ssl.SslHandler.unwrap(SslHandler.java:1227)
at
io.netty5.handler.ssl.SslHandler.decodeJdkCompatible(SslHandler.java:1105)
at io.netty5.handler.ssl.SslHandler.decode(SslHandler.java:1165)
at
io.netty5.handler.codec.ByteToMessageDecoderForBuffer.decodeRemovalReentryProtection(ByteToMessageDecoderForBuffer.java:384)
at
io.netty5.handler.codec.ByteToMessageDecoderForBuffer.callDecode(ByteToMessageDecoderForBuffer.java:327)
... 20 common frames omitted
Caused by: java.nio.ReadOnlyBufferException: null
at java.base/javax.crypto.Cipher.doFinal(Cipher.java:2497)
at
java.base/sun.security.ssl.SSLCipher$T13GcmReadCipherGenerator$GcmReadCipher.decrypt(SSLCipher.java:1933)
at
java.base/sun.security.ssl.SSLEngineInputRecord.decodeInputRecord(SSLEngineInputRecord.java:239)
at
java.base/sun.security.ssl.SSLEngineInputRecord.decode(SSLEngineInputRecord.java:196)
at
java.base/sun.security.ssl.SSLEngineInputRecord.decode(SSLEngineInputRecord.java:159)
at java.base/sun.security.ssl.SSLTransport.decode(SSLTransport.java:111)
... 31 common frames omitted
We can work around this in Netty since we need to support JDK versions
that has this issue anyway, but I think it's a bug that should be fixed
at some point.
Thanks,
Chris