Skip to content

Fix max AAD bytes calculation in GCM mode#15102

Open
loganaden wants to merge 1 commit into
pyca:mainfrom
cyberstormdotmu:loganaden-patch-gcm_max_aad
Open

Fix max AAD bytes calculation in GCM mode#15102
loganaden wants to merge 1 commit into
pyca:mainfrom
cyberstormdotmu:loganaden-patch-gcm_max_aad

Conversation

@loganaden

Copy link
Copy Markdown

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"

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

@soatok soatok Jun 26, 2026

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Development

Successfully merging this pull request may close these issues.

2 participants