AEAD byte counters add a spurious carry for writes of 4 GiB or more
Closed, ResolvedPublic

Assigned To
None
Authored By
werner
Tue, Aug 4, 4:53 PM
Subscribers

Description

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.

Related Objects

StatusAssignedTask
ResolvedNone

Event Timeline

werner triaged this task as Normal priority.Tue, Aug 4, 4:53 PM
werner created this task.
werner created this object with visibility "Public (No Login Required)".
werner created this object with edit policy "Contributor (Project)".

Internal comment by jk: Wrong calculation in GCM if input buffer is 4GiB+ in one operation call. Should be fixed.

werner shifted this object from the Restricted Space space to the S1 Public space.