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