Argon2 parallelism arithmetic underallocates lane storage on 32-bit
Argon2 accepts an arbitrary nonzero 32-bit lane count and performs its geometry and allocation products without checked arithmetic. On a 32-bit build, public KDF parameters such as parallelism = 0x40000001 wrap those products to small allocations while a->lanes retains the original value, so initialization writes beyond both the block buffer and thread-data array.
Vulnerable code
cipher/kdf.c, argon2_init:
c
memory_blocks = m_cost;
if (memory_blocks < 8 * parallelism)
memory_blocks = 8 * parallelism;
segment_length = memory_blocks / (parallelism * 4);
memory_blocks = segment_length * parallelism * 4;
a->passes = t_cost;
a->memory_blocks = memory_blocks;
a->segment_length = segment_length;
a->lane_length = segment_length * 4;
a->lanes = parallelism;
a->block = NULL;
a->thread_data = NULL;
if (U64_C(1024) * memory_blocks > SIZE_MAX)
return GPG_ERR_INV_VALUE;
memory_bytes = 1024 * (size_t)memory_blocks;
block = xtrymalloc (memory_bytes);The later allocation has the same issue:
c thread_data = xtrymalloc (a->lanes * sizeof (struct argon2_thread_data));
Why it matters
This is specific to supported targets with 32-bit size_t; a 64-bit build will normally reject an enormous allocation instead. With m_cost = 1 and the lane count above, the unsigned geometry collapses to eight 1-KiB blocks, yet argon2_fill_first_blocks immediately iterates over more than a billion lanes. The second lane already indexes outside the small block allocation. Applications that forward Argon2 parameters from password records or protocols can therefore be crashed or corrupted deterministically.
Proposed fix
Validate parallelism against the implementation's supported Argon2 lane maximum before any arithmetic. Use checked size_t multiplication for scaled lane counts, memory bytes, and thread-array bytes, and store only that validated count in a->lanes. Add a 32-bit sanitizer regression using 0x40000001 and assert clean GPG_ERR_INV_VALUE before allocation or writes.