AEAD byte counters add a spurious carry for writes of 4 GiB or more
The GCM byte-counter helper adds the high half of a 64-bit size_t, truncates the low addition into u32, then compares that low word with the original 64-bit addend. For any one-shot addend at least 2^32, the comparison necessarily reports a carry even when the low word did not wrap. Copied helpers affect GCM-SIV and ChaCha20-Poly1305 as well.
Vulnerable code
cipher/cipher-gcm.c, gcm_bytecounter_add:
c
if (sizeof(add) > sizeof(u32))
{
u32 high_add = ((add >> 31) >> 1) & 0xffffffff;
ctr[1] += high_add;
}
ctr[0] += add;
if (ctr[0] >= add)
return;
++ctr[1];Why it matters
The exact arithmetic harness showed that adding 4 GiB to zero produces 00000002:00000000 instead of 00000001:00000000. Final authentication length blocks then depend on API chunking, causing non-standard tags and interoperability failure. The caller must supply at least 4 GiB in one operation, which makes exploitation unusual and supports LOW severity.
Proposed fix
Split add into explicit u32 add_lo and add_hi; add the high word separately and detect carry with new_lo < old_lo. Reuse one helper across all three modes. Add regression tests at UINT32_MAX, UINT32_MAX+1, and larger values using an arithmetic test seam or fake input so physical multi-gigabyte allocation is unnecessary.