RFR: 8298249: Excessive memory allocation in CipherInputStream AEAD decryption
    Daniel Jeliński 
    djelinski at openjdk.org
       
    Fri Dec  9 06:55:42 UTC 2022
    
    
  
This patch modifies `CipherInputStream` to avoid pointless memory allocations when decrypting data using AEAD ciphers.
`Cipher.update` on AEAD decryption does not output any data; instead, all data is buffered and returned in one shot from `doFinal` call. On the other hand, the value returned by `getOutputSize` increases after every `update` call, which triggers multiple allocations in the existing implementation.
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.
As long as `doUpdate` returns no data, the new implementation doesn't allocate any memory. As a result, for AEAD ciphers it will only allocate once in the `doFinal` invocation.
There's a similar issue in CipherOutputStream that manifests when doing many small writes; I'll file a separate bug for that.
The PR adds a new benchmark for AES/GCM encryption and decryption using CipherInputStream. That benchmark shows a nice improvement on decryption and comparable results on encryption.
Benchmark results before:
Benchmark                        (dataSize)  (keyLength)  (provider)   Mode  Cnt       Score      Error  Units
AESGCMCipherInputStream.decrypt       16384          128              thrpt   40   24590,604 ± 1169,075  ops/s
AESGCMCipherInputStream.decrypt     1048576          128              thrpt   40      19,159 ±    0,219  ops/s
AESGCMCipherInputStream.encrypt       16384          128              thrpt   40  127135,615 ± 2322,957  ops/s
AESGCMCipherInputStream.encrypt     1048576          128              thrpt   40    2138,727 ±   16,400  ops/s
After:
Benchmark                        (dataSize)  (keyLength)  (provider)   Mode  Cnt       Score      Error  Units
AESGCMCipherInputStream.decrypt       16384          128              thrpt   40   43419,355 ± 3265,238  ops/s
AESGCMCipherInputStream.decrypt     1048576          128              thrpt   40     789,463 ±   89,384  ops/s
AESGCMCipherInputStream.encrypt       16384          128              thrpt   40  123014,294 ± 3302,102  ops/s
AESGCMCipherInputStream.encrypt     1048576          128              thrpt   40    2007,224 ±   88,347  ops/s
-------------
Commit messages:
 - Add benchmark
 - Speed up CipherInputStream on AEAD decryption
Changes: https://git.openjdk.org/jdk/pull/11597/files
 Webrev: https://webrevs.openjdk.org/?repo=jdk&pr=11597&range=00
  Issue: https://bugs.openjdk.org/browse/JDK-8298249
  Stats: 146 lines in 2 files changed: 142 ins; 0 del; 4 mod
  Patch: https://git.openjdk.org/jdk/pull/11597.diff
  Fetch: git fetch https://git.openjdk.org/jdk pull/11597/head:pull/11597
PR: https://git.openjdk.org/jdk/pull/11597
    
    
More information about the security-dev
mailing list