While looking at extended tests of the aead update function (for the associated data), I stumbled on a restriction of gcm_update that is different from most (all?) other update functions in Nettle. According to the docs,
-- Function: void gcm_update (struct gcm_ctx *CTX, const struct gcm_key *KEY, size_t LENGTH, const uint8_t *DATA) Provides associated data to be authenticated. If used, must be called before ‘gcm_encrypt’ or ‘gcm_decrypt’. All but the last call for each message _must_ use a length that is a multiple of the block size.
Would it be worthwhile to drop the restriction of the last sentence, and allow all calls to gcm_update to use any size? This requirement may be particularly surprising when using nettle_aead; then gcm has different requirements for the update function than all other aead algorithms.
I think that might be doable without any ABI break, by the following hack: reuse the ctr field of struct gcm_context as a block buffer, while processing the associated data. The ctr field is clearly needed also for encrypt/decrypt, but we could move initialization for that purpose from gcm_set_iv to the first call to encrypt/decrypt.
Regards, /Niels
Hi Niels :)
Niels Möller nisse@lysator.liu.se writes:
While looking at extended tests of the aead update function (for the associated data), I stumbled on a restriction of gcm_update that is different from most (all?) other update functions in Nettle. According to the docs,
-- Function: void gcm_update (struct gcm_ctx *CTX, const struct gcm_key *KEY, size_t LENGTH, const uint8_t *DATA) Provides associated data to be authenticated. If used, must be called before ‘gcm_encrypt’ or ‘gcm_decrypt’. All but the last call for each message _must_ use a length that is a multiple of the block size.
What happens if that restriction is violated? As the function cannot signal an error, does it lead to silent corruption of the data stream? Or does it assert that restriction?
Would it be worthwhile to drop the restriction of the last sentence, and allow all calls to gcm_update to use any size? This requirement may be particularly surprising when using nettle_aead; then gcm has different requirements for the update function than all other aead algorithms.
In the Rust bindings, we don't check for this, and we also didn't make the function fallible (likely because at the time we bound GCM we were not aware of the limitation), so we're not able to communicate any failures to the user. As such, dropping the requirement would be most welcome for us, because then we wouldn't need to change our interface.
Best, Justus
Justus Winter justus@sequoia-pgp.org writes:
What happens if that restriction is violated? As the function cannot signal an error, does it lead to silent corruption of the data stream? Or does it assert that restriction?
It triggers an assert. Likewise, if you call gcm_update after gcm_encrypt that also triggers an assert. While I think (without checking the code closely) an invalid mix of gcm_encrypt and gcm_decrypt will just result in a garbage digest.
So if you want the bindings to report errors in some friendler way on misuse, you'd need to keep track of the state of the context and check that each call is appropriate for the current state.
Regards, /Niels
Niels Möller nisse@lysator.liu.se writes:
Would it be worthwhile to drop the restriction of the last sentence, and allow all calls to gcm_update to use any size? This requirement may be particularly surprising when using nettle_aead; then gcm has different requirements for the update function than all other aead algorithms.
Actually, it turns out at least eax and ocb have similar requirements. So I'm now leaning towards sticking with the convention that nettle's aead modes should require that if the associated data is passed in several pieces, all pieces but the last must be an integral number of blocks (similarly as for the cleartext and ciphertext inputs).
Relaxing that for gcm adds more code complexity, and it's not clear if it's possible to fix for ocb and eax without an abi break to add additional state to some of the related structs.
Maybe this should be pointed out more explicitly somewere in the manual? (Now it's noted in the docs of resp. _update function, but not for aead in general).
For reference, I've pushed a branch "relax-gcm_update" where I've tried this out (and which fails eax and ocb tests).
Regards, /Niels
nettle-bugs@lists.lysator.liu.se