RFR: 8298865: Excessive memory allocation in CipherOutputStream AEAD decryption [v2]
Valerie Peng
valeriep at openjdk.org
Thu Dec 15 22:49:06 UTC 2022
On Thu, 15 Dec 2022 18:06:38 GMT, Daniel Jeliński <djelinski at openjdk.org> wrote:
>> This patch modifies `CipherOutputStream` to avoid pointless memory allocations when decrypting data using AEAD ciphers. This is related to #11597, which fixed a similar issue in `CipherInputStream`.
>>
>> `Cipher.update` does not output any data when doing AEAD decryption; all data is buffered, and is later returned in one shot from `doFinal`. `Cipher.getOutputSize` returns the buffer size required by `doFinal`, which increases after every `update`, triggering new allocation in `ensureCapacity`.
>>
>> This patch addresses the issue by calling the `update` overload that returns the output buffer until one of the update calls returns some data. When that happens, we know that the cipher does not buffer everything until `doFinal`, and revert to original behavior.
>>
>> This PR adds a new benchmark for AES/GCM encryption and decryption using `CipherOutputStream`.
>>
>> Benchmark results before:
>>
>> Benchmark (dataSize) (keyLength) (provider) Mode Cnt Score Error Units
>> AESGCMCipherOutputStream.decrypt 16384 128 thrpt 40 27949,624 ± 301,408 ops/s
>> AESGCMCipherOutputStream.decrypt 1048576 128 thrpt 40 20,730 ± 0,875 ops/s
>> AESGCMCipherOutputStream.encrypt 16384 128 thrpt 40 175358,641 ± 4235,808 ops/s
>> AESGCMCipherOutputStream.encrypt 1048576 128 thrpt 40 2588,111 ± 35,469 ops/s
>>
>>
>> after:
>>
>> Benchmark (dataSize) (keyLength) (provider) Mode Cnt Score Error Units
>> AESGCMCipherOutputStream.decrypt 16384 128 thrpt 40 69644,217 ± 1081,032 ops/s
>> AESGCMCipherOutputStream.decrypt 1048576 128 thrpt 40 949,667 ± 9,431 ops/s
>> AESGCMCipherOutputStream.encrypt 16384 128 thrpt 40 173144,038 ± 3279,149 ops/s
>> AESGCMCipherOutputStream.encrypt 1048576 128 thrpt 40 2514,840 ± 87,935 ops/s
>
> Daniel Jeliński has updated the pull request incrementally with one additional commit since the last revision:
>
> Fix test failure
src/java.base/share/classes/javax/crypto/CipherOutputStream.java line 95:
> 93: *
> 94: * If obuffer is null/zero-sized, do not allocate a new buffer.
> 95: * This reduces allocation for AEAD ciphers that never return data from update
AEAD ciphers do return data for update() calls for encryption. Perhaps we should add "when used for decryption" or some other similar wordings to the above sentence? Same goes for the comment in CipherInputStream class.
-------------
PR: https://git.openjdk.org/jdk/pull/11693
More information about the security-dev
mailing list