RFR: 8253821: Improve ByteBuffer performance with GCM [v2]
Anthony Scarpino
ascarpino at openjdk.java.net
Thu Oct 8 06:56:44 UTC 2020
On Wed, 7 Oct 2020 22:38:21 GMT, Valerie Peng <valeriep at openjdk.org> wrote:
>> Anthony Scarpino has updated the pull request incrementally with one additional commit since the last revision:
>>
>> Xuelei comments
>
> src/java.base/share/classes/com/sun/crypto/provider/CipherCore.java line 939:
>
>> 937: // if the size of specified output buffer is less than
>> 938: // the length of the cipher text, then the current
>> 939: // content of cipher has to be preserved in order for
>
> This change is somewhat dangerous. When using the supplied output buffer directly, you may corrupt its content w/
> padding bytes. This optimization should only be applied when no padding is involved. In addition, input and output can
> point to the same buffer with all sorts of index combinations, i.e. inOfs == outOfs, inOfs < outOfs, inOfs > outOfs.
> With "outWithPadding" approach, no need to check. However, for "internalOutput", data corruption may happen. This kind
> of problem can be very hard to diagnose. Have to be very very careful here as this code may impact all ciphers...
- I do not understand where the corruption comes from. The user provides a buffer that output is suppose to be placed
into, what could it be corrupting? The existing tests (SameBuffer, in particular) works fine with this and the
ByteBuffer calls. I spent a lot of time trying to get those same buffer tests to pass.
- It was my expectation that checkOutputCapacity() is making sure all the inOfs ==<> outOfs are going to work. Does that
not catch all cases?
- outWithPadding" is excessive because it doubles the allocation for every operation followed by a copy to the original
buffer, even if the original buffer was adequate. I'm ok with doing the extra alloc & copy in certain situations, but
not everytime. Can you be more specific what things may fail that we don't already check for in the regression tests?
> src/java.base/share/classes/com/sun/crypto/provider/AESCipher.java line 658:
>
>> 656: BadPaddingException {
>> 657: return bufferCrypt(input, output, false);
>> 658: }
>
> Is the override of this method for using a different bufferCrypt impl? There is also engineUpdate(ByteBuffer,
> ByteBuffer) in CipherSpi, is there a reason for not overriding that here?
Yes. thanks.. The IDE covered that up by going to the one in CipherSpi and I thought it was calling the AES one. TLS
doesn't use update() so the perf numbers won't change. I'll have to run the tests again.
> src/java.base/share/classes/com/sun/crypto/provider/AESCipher.java line 744:
>
>> 742: } else {
>> 743: return core.doFinal(input, output);
>> 744: }
>
> It seems this block is the only difference between this method and CipherSpi.bufferCrypt(). Have you considered moving
> this special handling to the overridden engineDoFinal(...) method and not duplicating the whole CipherSpi.bufferCrypt()
> method here? BTW, instead of using the generic update/doFinal name and then commenting them for GCM usage only, perhaps
> it's more enticing to name them as gcmUpdate/gcmDoFinal?
I didn't see a way to override this because CipherSpi is a public class, any methods I added would become a new API.
Also bufferCrypt is private, so I had to copy it. CipherSpi does not know which mode is being used, but AESCipher
does. Maybe I'm missing something, I'd rather it not be a copy, but I couldn't see a better way. If you have a
specific idea, please give me details.
-------------
PR: https://git.openjdk.java.net/jdk/pull/411
More information about the security-dev
mailing list