-
Bug
-
Resolution: Fixed
-
P2
-
None
-
b18
-
generic
-
generic
-
Verified
Issue | Fix Version | Assignee | Priority | Status | Resolution | Resolved In Build |
---|---|---|---|---|---|---|
JDK-8205286 | 11.0.1 | Valerie Peng | P2 | Resolved | Fixed | team |
JDK-8246208 | openjdk8u262 | Valerie Peng | P2 | Resolved | Fixed | b05 |
JDK-8245161 | 8u271 | Sean Coffey | P2 | Resolved | Fixed | b01 |
JDK-8245844 | 8u261 | Valerie Peng | P2 | Resolved | Fixed | b09 |
JDK-8251661 | emb-8u271 | Valerie Peng | P2 | Resolved | Fixed | team |
JDK-8248762 | emb-8u261 | Valerie Peng | P2 | Resolved | Fixed | team |
Existing buffering code inside the javax.crypto.CipherSpi.bufferCrypt method has several shortcomings:
1) does not work well with AES/GCM/NoPadding decryption where data is buffered internally until tag is verified, i.e. when doFinal() method is called
2) high number of buffer re-allocations (see below report from external source)
While running some performance tests and analyzing with Yourkit, Our customer noticed an excessive number of ShortBufferExceptions being thrown. After digging into the back trace provided in Yourkit, it appears that there is a logic flaw in the way that the output buffer is allocated inside the bufferCrypt method.
Near the top of the method, the size needed in the output buffer is calculated with
int outLenNeeded = engineGetOutputSize(inLen);
In the third conditional block identified by the comment "output is not backed by an accessible byte[]", the output buffer is initially allocated with
byte[] outArray = new byte\[getTempArraySize(outLenNeeded)\];
The method "getTempArraySize" is a static method that returns the minimum between outLenNeeded and 4096. As a result, outArray is never bigger than 4096. As a result, if the needed length is greater, then the call to engineDoFinal will fail with ShortBufferException.
Immediately after the exception is thrown, a catch block catches the exception then reallocates the output buffer to the correct size. This new output buffer is resubmitted to the engineDoFinal call. Since it is now big enough, it succeeds.
Then end result is that a buffer is allocated that is known to fail, submitted, the exception caught, then reallocated and resubmitted. Instead, the behavior should be to allocate the correct buffer initially so that the call succeeds on it's first attempt.
Attached is a simulation of the problem. The bufferCrypt method is unmodified from CipherSpi. The supporting methods return values that were observed when stepping thru the code.
1) does not work well with AES/GCM/NoPadding decryption where data is buffered internally until tag is verified, i.e. when doFinal() method is called
2) high number of buffer re-allocations (see below report from external source)
While running some performance tests and analyzing with Yourkit, Our customer noticed an excessive number of ShortBufferExceptions being thrown. After digging into the back trace provided in Yourkit, it appears that there is a logic flaw in the way that the output buffer is allocated inside the bufferCrypt method.
Near the top of the method, the size needed in the output buffer is calculated with
int outLenNeeded = engineGetOutputSize(inLen);
In the third conditional block identified by the comment "output is not backed by an accessible byte[]", the output buffer is initially allocated with
byte[] outArray = new byte\[getTempArraySize(outLenNeeded)\];
The method "getTempArraySize" is a static method that returns the minimum between outLenNeeded and 4096. As a result, outArray is never bigger than 4096. As a result, if the needed length is greater, then the call to engineDoFinal will fail with ShortBufferException.
Immediately after the exception is thrown, a catch block catches the exception then reallocates the output buffer to the correct size. This new output buffer is resubmitted to the engineDoFinal call. Since it is now big enough, it succeeds.
Then end result is that a buffer is allocated that is known to fail, submitted, the exception caught, then reallocated and resubmitted. Instead, the behavior should be to allocate the correct buffer initially so that the call succeeds on it's first attempt.
Attached is a simulation of the problem. The bufferCrypt method is unmodified from CipherSpi. The supporting methods return values that were observed when stepping thru the code.
- backported by
-
JDK-8205286 Problematic ByteBuffer handling in CipherSpi.bufferCrypt method
-
- Resolved
-
-
JDK-8245161 Problematic ByteBuffer handling in CipherSpi.bufferCrypt method
-
- Resolved
-
-
JDK-8245844 Problematic ByteBuffer handling in CipherSpi.bufferCrypt method
-
- Resolved
-
-
JDK-8246208 Problematic ByteBuffer handling in CipherSpi.bufferCrypt method
-
- Resolved
-
-
JDK-8248762 Problematic ByteBuffer handling in CipherSpi.bufferCrypt method
-
- Resolved
-
-
JDK-8251661 Problematic ByteBuffer handling in CipherSpi.bufferCrypt method
-
- Resolved
-
(1 backported by)