Fix max AAD bytes calculation in GCM mode#15102
Conversation
https://csrc.nist.rip/groups/ST/toolkit/BCM/documents/proposedmodes/gcm/gcm-spec.pdf "Additional authenticated data (AAD), which is denoted as A. This data is authenticated, but not encrypted, and can have any number of bits between 0 and 2^64"
| name = "GCM" | ||
| _MAX_ENCRYPTED_BYTES = (2**39 - 256) // 8 | ||
| _MAX_AAD_BYTES = (2**64) // 8 | ||
| _MAX_AAD_BYTES = (2**64 - 1) // 8 |
There was a problem hiding this comment.
The maximum AAD length should be 2**64 - 1 bits, which corresponds to 0xFFFFFFFF_FFFFFFFF as the maximum value for the length parameter. This is equivalent to 0x1FFFFFFF_FFFFFFFF bytes.
Note
The ciphertext length and AAD length are each encoded as 8 octets and concatenated in the finalization step. 2**64 doesn't fit in 64 bytes.
Does the 1-bit difference matter in practice?
>>> (2**64) // 8
2305843009213693952
>>> (2**64 - 1) // 8
2305843009213693951
It turns out, yes.
If you can squeeze 2**64 bits into a single AAD, you can exceed the maximum and cause an overflow (2**64 == 0x00000001_00000000_00000000 over 3 bytes, but only two are written to the AAD length field for the final block multiplication. Depending on how this is sliced, this will result in either 0x00000001_00000000 or 0x00000000_00000000 (the latter being the most likely).
Turning this into a more powerful capability requires a bit more thought than I feel like putting towards this change.
The underlying crypto library will probably error before 2**64 is reached in practice, and I don't know how to effectively write a unit test that processes that much data without timing out, but making this change results in the correct behavior.
https://csrc.nist.rip/groups/ST/toolkit/BCM/documents/proposedmodes/gcm/gcm-spec.pdf
"Additional authenticated data (AAD), which is denoted as A. This data is authenticated, but not encrypted, and can have any number of bits between 0 and 2^64"