portable method to zeroize memory when destroying a mpz number
Vicente Benjumea
vicente at lcc.uma.es
Fri Mar 21 13:41:24 UTC 2014
Hi,
this is what I have so far:
1.- wait for next GMP release, which brings out new functions for
cryptography.
2.- define my own memory handlers. In this approach, this is what I got:
* POSIX.1-2001 functions 'mlock/munlock' can lock memory pages on RAM,
but it depends on process resource/privilege RLIMIT_MEMLOCK, which it
seems it is not defined by POSIX (it is BSD and Linux specific).
* Non-portable GNU-function 'mallopt(M_PERTURB, ~0)' guarantees to reset
memory bytes to 0xFF before being deallocated
* It seems that resetting the memory in case of reallocation can only be
achieved by either mallopt(M_PERTURB, ~0) or
__malloc_initialize_hook/__free_hook. Both GNU specific.
* It seems that calling 'memset' before 'free' does not guarantee
resetting the memory, since 'memset' could be optimized away.
* I have not found any way to selectively reset the memory. It does it
for every number.
It follows a non-portable possible implementation following this
approach
(function's name safe_memory_mode), which should be called before
any other GMP function.
/*------------------------------------------------------------------------*/
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/mman.h>
#include <sys/resource.h>
#include <malloc.h>
#include <gmp.h>
/*
* POSIX.1-2001 functions 'mlock/munlock' can lock memory pages on
* RAM, but it depends on process resource/privilege RLIMIT_MEMLOCK,
* which it seems it is not defined by POSIX (it is BSD and Linux
* specific).
*
* Non-portable GNU-function 'mallopt(M_PERTURB, ~0)' guarantees to
* reset memory bytes to 0xFF before being deallocated
*
* It seems that resetting the memory in case of reallocation can only
* be achieved by either mallopt(M_PERTURB, ~0) or
* __malloc_initialize_hook/__free_hook. Both GNU specific.
*
* It seems that calling 'memset' before 'free' does not guarantee
* resetting the memory, since 'memset' could be optimized away.
*
* I have not found any way to selectively reset the memory. It does
* it for every number.
*
* It follows a non-portable possible implementation following this
* approach (function's name safe_memory_mode), which should be called
* before any other GMP function.
*/
static void * safe_alloc(size_t alloc_size)
{
void *p = malloc(alloc_size);
if (!p) {
fprintf(stderr, "Memory allocation error\n");
abort(); /* GMP requires to abort in case of failure */
}
#ifdef _POSIX_MEMLOCK_RANGE
mlock(p, alloc_size); /* POSIX.1-2001 */ /* ignore failure */
#endif
return p;
}
static void * safe_realloc(void *ptr, size_t old_size, size_t new_size)
{
void *p = realloc(ptr, new_size);
if (!p) {
fprintf(stderr, "Memory allocation error\n");
abort(); /* GMP requires to abort in case of failure */
}
#ifdef _POSIX_MEMLOCK_RANGE
if (p != ptr) {
munlock(ptr, old_size); /* POSIX.1-2001 */ /* ignore failure */
} else if (new_size < old_size) {
munlock((char*)ptr+new_size, old_size-new_size); /* POSIX.1-2001
*/
}
mlock(p, new_size); /* POSIX.1-2001 */ /* ignore failure */
#endif
return p;
}
static void safe_free(void *ptr, size_t size)
{
#ifdef _POSIX_MEMLOCK_RANGE
munlock(ptr, size); /* POSIX.1-2001 */ /* ignore failure */
#endif
#ifndef M_PERTURB
memset(ptr, 0, size); /* it seems this could be optimized away !!!
*/
#endif
free(ptr);
}
/*
* It returns the bitwise-OR of the following cases:
* 0: no safety mechanisms installed
* 1: all deallocated memory will be reset to 0xFF
* (by mallopt(M_PERTURB))
* 2: allocated memory will be lock into RAM memory (no swapped) up
* to the limit specified by resource RLIMIT_MEMLOCK
* (memlock resource in /etc/security/limits.conf in linux)
*/
int safe_memory_mode()
{
int val = 0;
#if defined _POSIX_MEMLOCK_RANGE && defined RLIMIT_MEMLOCK
struct rlimit rlim;
if (getrlimit(RLIMIT_MEMLOCK, &rlim) == 0) { /* POSIX.1-2001 */
rlim.rlim_cur = rlim.rlim_max;
if (setrlimit(RLIMIT_MEMLOCK, &rlim) == 0) { /* POSIX.1-2001 */
val |= 2;
}
}
#endif
#ifdef M_PERTURB
if (mallopt(M_PERTURB, ~0)) { /* GNU GLibc*/
val |= 1;
}
#endif
mp_set_memory_functions(safe_alloc, safe_realloc, safe_free); /* GMP
*/
return val;
}
/*------------------------------------------------------------------------*/
More information about the gmp-discuss
mailing list