The function `mpi_set_secure' is used by `gcry_mpi_set_flag' to convert
an integer so as to use `secure' (i.e., locked, non-swappable) memory.
The code allocates enough secure memory for the active limbs, copies
them from the existing buffer, and stores a pointer to the new buffer --
all without reducing the separate count of the number of allocated
limbs. In particular, when the securified integer is freed,
`_gcry_mpi_free' calls `_gcry_mpi_free_limb_space' to release the limb
buffer, giving it the allocated size, and the latter attempts to zeroize
the storage, leading to a heap corruption.
The patch fixes the problem. I've not thought deeply about the
performance effects: maybe it'd be better to allocate the same total
limb buffer rather than just the active size, but this patch is simple
and obviously right.
> The patch fixes the problem. I've not thought deeply about the
> performance effects: maybe it'd be better to allocate the same total
> limb buffer rather than just the active size, but this patch is simple
> and obviously right.
Yes. While the patch is right, I followed the suggestion for less
While there is the API, I don't know the real use case. So, I did
* mpi/mpiutil.c (mpi_set_secure): Allocate by ->alloced.
The code was simply wrong. The question is if (1) it allocates
(possibly) more or (2) modifi ->alloced. The choice is (1).
Because we have routines of mpi_set_cond and mpi_swap_cond which
assume no change for the allocated length of limbs, no surprise is
better. See _gcry_mpi_ec_mul_point for concrete example for those
routines. That's for constant-time computation.
Alas not. I found this bug because seccure-0.5_1 broke on amd64 (and I
couldn't mount my backup disks again until I fixed it). What happened
is that `gcry_mpi_scan' returned a bignum with alloced = 5 and nlimbs =
4; zeroizing the limb vector clobbered the secure-memory pool structure
in a way I didn't investigate too carefully, but the result was that
`mb_get_new' thought that the pool was full and `gcry_malloc_secure'
failed. As far as I can make out, `seccure-decrypt' can't decrypt
anything at all on amd64.