Reduce memory usage when AEAD en/decrypting large messages #259
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
The AEAD code buffered the data to be en/decrypted at multiple points. Firstly, when decrypting, the ciphertext was buffered in order to not pre-allocate the chunk size. However, given RFC9580 caps the chunk size at 4MiB, and most (all?) OSes reuse empty pages, the overhead of allocating the the entire chunk size (256KiB by default in our implementation) is not that large. This leads to a large reduction in memory usage when decrypting large messages, at the cost of somewhat increased memory usage when decrypting small messages. For an added reduction, the ciphertext buffer can be reused for the plaintext, and also for the buffered plaintext when it's read across multiple calls to
Read()
.Similarly, we can reduce the memory usage when encrypting large messages (though not by as much) by manually buffering the plaintext to be encrypted carefully to reserve space for the tag. That way, the plaintext buffer can be reused for the ciphertext.
Finally, fix OCB en/decryption when reusing the buffer.
Before (chunk size = 256KiB):
After (chunk size = 256KiB):
After (chunk size = 4MiB):
After (chunk size = message size):
Because of the above results, it may be worth setting the chunk size to the message size when known (e.g. in gopenpgp).