summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorWerner Koch <wk@gnupg.org>2000-01-24 11:55:48 +0000
committerWerner Koch <wk@gnupg.org>2000-01-24 11:55:48 +0000
commit57eb8c1b9d58df4cc3e026f82244f2928c008e2b (patch)
treebf97f3b0795a1a10de60ae08255e67d9e578b2c5 /src
parentd5bd6cb82646a4d52870b23d21262c83de77ae47 (diff)
downloadlibgcrypt-57eb8c1b9d58df4cc3e026f82244f2928c008e2b.tar.gz
See ChangeLog: Mon Jan 24 13:04:28 CET 2000 Werner Koch
Diffstat (limited to 'src')
-rw-r--r--src/ChangeLog7
-rw-r--r--src/Makefile.am9
-rw-r--r--src/gcrypt.h14
-rw-r--r--src/global.c40
-rw-r--r--src/mpi.h1
-rw-r--r--src/secmem.c422
-rw-r--r--src/secmem.h35
-rw-r--r--src/sexp.c35
-rw-r--r--src/stdmem.c186
-rw-r--r--src/stdmem.h32
-rw-r--r--src/wrapper.c3
11 files changed, 753 insertions, 31 deletions
diff --git a/src/ChangeLog b/src/ChangeLog
index d59feab9..4c2a5b2f 100644
--- a/src/ChangeLog
+++ b/src/ChangeLog
@@ -1,3 +1,10 @@
+Mon Jan 24 13:04:28 CET 2000 Werner Koch <wk@gnupg.de>
+
+ * secmem.c: Moved from ../util to here.
+ * secmem.h: New.
+ * stdmem.c: New. Based on the old ../util/memory.c.
+ * stdmem.h: New.
+
Wed Dec 8 21:58:32 CET 1999 Werner Koch <wk@gnupg.de>
* gcrypt.m4: New.
diff --git a/src/Makefile.am b/src/Makefile.am
index e88bba14..41174876 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -25,12 +25,15 @@ libgcrypt_la_SOURCES = mpi.h \
global.c \
sexp.c \
wrapper.c \
- memory.c \
- secmem.c
+ stdmem.c \
+ stdmem.h \
+ secmem.c \
+ secmem.h
libgcrypt_la_DEPENDENCIES = libgcrypt.sym
libgcrypt_la_LIBADD = ../cipher/libcipher.la \
- ../mpi/libmpi.la
+ ../mpi/libmpi.la \
+ ../jnlib/libjnlib.la
BUILT_SOURCES = libgcrypt.sym
diff --git a/src/gcrypt.h b/src/gcrypt.h
index 46119181..63715d49 100644
--- a/src/gcrypt.h
+++ b/src/gcrypt.h
@@ -118,6 +118,14 @@ enum gcry_ctl_cmds {
GCRYCTL_SET_DEBUG_FLAGS = 20,
GCRYCTL_CLEAR_DEBUG_FLAGS = 21,
GCRYCTL_USE_SECURE_RNDPOOL= 22,
+ GCRYCTL_DUMP_MEMORY_STATS = 23,
+ GCRYCTL_INIT_SECMEM = 24,
+ GCRYCTL_TERM_SECMEM = 25,
+ GCRYCTL_DISABLE_SECMEM_WARN = 27,
+ GCRYCTL_SUSPEND_SECMEM_WARN = 28,
+ GCRYCTL_RESUME_SECMEM_WARN = 29,
+ GCRYCTL_DROP_PRIVS = 30,
+ GCRYCTL_ENABLE_M_GUARD = 31,
};
int gcry_control( enum gcry_ctl_cmds, ... );
@@ -210,6 +218,8 @@ int gcry_mpi_scan( GCRY_MPI *ret_mpi, enum gcry_mpi_format format,
const char *buffer, size_t *nbytes );
int gcry_mpi_print( enum gcry_mpi_format format,
char *buffer, size_t *nbytes, const GCRY_MPI a );
+int gcry_mpi_aprint( enum gcry_mpi_format format,
+ void **buffer, size_t *nbytes, const GCRY_MPI a );
void gcry_mpi_powm( GCRY_MPI w,
const GCRY_MPI b, const GCRY_MPI e, const GCRY_MPI m );
@@ -324,6 +334,7 @@ int gcry_pk_ctl( int cmd, void *buffer, size_t buflen);
int gcry_pk_algo_info( int algo, int what, void *buffer, size_t *nbytes);
const char *gcry_pk_algo_name( int algo );
int gcry_pk_map_name( const char* name );
+unsigned int gcry_pk_get_nbits( GCRY_SEXP key );
#define gcry_pk_test_algo(a) \
@@ -444,7 +455,8 @@ void *gcry_xmalloc_secure( size_t n );
void *gcry_xcalloc_secure( size_t n, size_t m );
void *gcry_xrealloc( void *a, size_t n );
char *gcry_xstrdup( const char * a);
-void gcry_free( void *p );
+void gcry_free( void *a );
+int gcry_is_secure( const void *a );
#ifndef GCRYPT_NO_MPI_MACROS
diff --git a/src/global.c b/src/global.c
index 1de2bd62..2e84f4b6 100644
--- a/src/global.c
+++ b/src/global.c
@@ -27,7 +27,8 @@
#include <assert.h>
#include "g10lib.h"
-#include "memory.h" /* for the m_* functions */
+#include "stdmem.h" /* our own memory allocator */
+#include "secmem.h" /* our own secmem allocator */
/****************
* flag bits: 0 : general cipher debug
@@ -128,14 +129,47 @@ gcry_control( enum gcry_ctl_cmds cmd, ... )
case GCRYCTL_SET_FATAL_FNC:
break;
#endif
+
+ case GCRYCTL_ENABLE_M_GUARD:
+ g10_private_enable_m_guard();
+ break;
+
case GCRYCTL_DUMP_RANDOM_STATS:
random_dump_stats();
break;
+ case GCRYCTL_DUMP_MEMORY_STATS:
+ /*m_print_stats("[fixme: prefix]");*/
+ break;
+
case GCRYCTL_DUMP_SECMEM_STATS:
secmem_dump_stats();
break;
+ case GCRYCTL_DROP_PRIVS:
+ secmem_init( 0 );
+ break;
+
+ case GCRYCTL_INIT_SECMEM:
+ secmem_init( va_arg( arg_ptr, unsigned int ) );
+ break;
+
+ case GCRYCTL_TERM_SECMEM:
+ secmem_term();
+ break;
+
+ case GCRYCTL_DISABLE_SECMEM_WARN:
+ secmem_set_flags( secmem_get_flags() | 1 );
+ break;
+
+ case GCRYCTL_SUSPEND_SECMEM_WARN:
+ secmem_set_flags( secmem_get_flags() | 2 );
+ break;
+
+ case GCRYCTL_RESUME_SECMEM_WARN:
+ secmem_set_flags( secmem_get_flags() & ~2 );
+ break;
+
case GCRYCTL_USE_SECURE_RNDPOOL:
secure_random_alloc(); /* put random number into secure memory */
break;
@@ -234,11 +268,11 @@ gcry_set_allocation_handler( void *(*new_alloc_func)(size_t n),
* ran out of memory. This handler may do one of these things:
* o free some memory and return true, so that the xmalloc function
* tries again.
- * o Do whatever tit like and return false, so that the xmalloc functions
+ * o Do whatever it like and return false, so that the xmalloc functions
* use the default fatal error handler.
* o Terminate the program and don't return.
*
- * The handler function is called with 3 argiments: The opaque value set with
+ * The handler function is called with 3 arguments: The opaque value set with
* this function, the requested memory size, and a flag with these bits
* currently defined:
* bit 0 set = secure memory has been requested.
diff --git a/src/mpi.h b/src/mpi.h
index 91458d47..e1392887 100644
--- a/src/mpi.h
+++ b/src/mpi.h
@@ -93,7 +93,6 @@ void mpi_swap( MPI a, MPI b);
/*-- mpicoder.c --*/
int mpi_fromstr(MPI val, const char *str);
-int mpi_print( FILE *fp, MPI a, int mode );
void g10_log_mpidump( const char *text, MPI a );
u32 mpi_get_keyid( MPI a, u32 *keyid );
byte *mpi_get_buffer( MPI a, unsigned *nbytes, int *sign );
diff --git a/src/secmem.c b/src/secmem.c
new file mode 100644
index 00000000..7c27de00
--- /dev/null
+++ b/src/secmem.c
@@ -0,0 +1,422 @@
+/* secmem.c - memory allocation from a secure heap
+ * Copyright (C) 1998,1999 Free Software Foundation, Inc.
+ *
+ * This file is part of GnuPG.
+ *
+ * GnuPG is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * GnuPG is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
+ */
+
+#include <config.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <errno.h>
+#include <stdarg.h>
+#include <unistd.h>
+#if defined(HAVE_MLOCK) || defined(HAVE_MMAP)
+ #include <sys/mman.h>
+ #include <sys/types.h>
+ #include <fcntl.h>
+ #ifdef USE_CAPABILITIES
+ #include <sys/capability.h>
+ #endif
+#endif
+
+#include "types.h"
+#include "secmem.h"
+#include "util.h"
+#include "i18n.h"
+
+#if defined(MAP_ANON) && !defined(MAP_ANONYMOUS)
+ #define MAP_ANONYMOUS MAP_ANON
+#endif
+
+#define DEFAULT_POOLSIZE 16384
+
+typedef struct memblock_struct MEMBLOCK;
+struct memblock_struct {
+ unsigned size;
+ union {
+ MEMBLOCK *next;
+ PROPERLY_ALIGNED_TYPE aligned;
+ } u;
+};
+
+
+
+static void *pool;
+static volatile int pool_okay; /* may be checked in an atexit function */
+static int pool_is_mmapped;
+static size_t poolsize; /* allocated length */
+static size_t poollen; /* used length */
+static MEMBLOCK *unused_blocks;
+static unsigned max_alloced;
+static unsigned cur_alloced;
+static unsigned max_blocks;
+static unsigned cur_blocks;
+static int disable_secmem;
+static int show_warning;
+static int no_warning;
+static int suspend_warning;
+
+
+static void
+print_warn(void)
+{
+ if( !no_warning )
+ log_info(_("Warning: using insecure memory!\n"));
+}
+
+
+static void
+lock_pool( void *p, size_t n )
+{
+ #if defined(USE_CAPABILITIES) && defined(HAVE_MLOCK)
+ int err;
+
+ cap_set_proc( cap_from_text("cap_ipc_lock+ep") );
+ err = mlock( p, n );
+ if( err && errno )
+ err = errno;
+ cap_set_proc( cap_from_text("cap_ipc_lock+p") );
+
+ if( err ) {
+ if( errno != EPERM
+ #ifdef EAGAIN /* OpenBSD returns this */
+ && errno != EAGAIN
+ #endif
+ #ifdef ENOSYS /* Some SCOs return this (function not implemented) */
+ && errno != ENOSYS
+ #endif
+ )
+ log_error("can't lock memory: %s\n", strerror(err));
+ show_warning = 1;
+ }
+
+ #elif defined(HAVE_MLOCK)
+ uid_t uid;
+ int err;
+
+ uid = getuid();
+
+ #ifdef HAVE_BROKEN_MLOCK
+ if( uid ) {
+ errno = EPERM;
+ err = errno;
+ }
+ else {
+ err = mlock( p, n );
+ if( err && errno )
+ err = errno;
+ }
+ #else
+ err = mlock( p, n );
+ if( err && errno )
+ err = errno;
+ #endif
+
+ if( uid && !geteuid() ) {
+ if( setuid( uid ) || getuid() != geteuid() )
+ log_fatal("failed to reset uid: %s\n", strerror(errno));
+ }
+
+ if( err ) {
+ if( errno != EPERM
+ #ifdef EAGAIN /* OpenBSD returns this */
+ && errno != EAGAIN
+ #endif
+ #ifdef ENOSYS /* Some SCOs return this (function not implemented) */
+ && errno != ENOSYS
+ #endif
+ )
+ log_error("can't lock memory: %s\n", strerror(err));
+ show_warning = 1;
+ }
+
+ #else
+ log_info("Please note that you don't have secure memory on this system\n");
+ #endif
+}
+
+
+static void
+init_pool( size_t n)
+{
+ size_t pgsize;
+
+ poolsize = n;
+
+ if( disable_secmem )
+ log_bug("secure memory is disabled");
+
+ #ifdef HAVE_GETPAGESIZE
+ pgsize = getpagesize();
+ #else
+ pgsize = 4096;
+ #endif
+
+ #if HAVE_MMAP
+ poolsize = (poolsize + pgsize -1 ) & ~(pgsize-1);
+ #ifdef MAP_ANONYMOUS
+ pool = mmap( 0, poolsize, PROT_READ|PROT_WRITE,
+ MAP_PRIVATE|MAP_ANONYMOUS, -1, 0);
+ #else /* map /dev/zero instead */
+ { int fd;
+
+ fd = open("/dev/zero", O_RDWR);
+ if( fd == -1 ) {
+ log_error("can't open /dev/zero: %s\n", strerror(errno) );
+ pool = (void*)-1;
+ }
+ else {
+ pool = mmap( 0, poolsize, PROT_READ|PROT_WRITE,
+ MAP_PRIVATE, fd, 0);
+ }
+ }
+ #endif
+ if( pool == (void*)-1 )
+ log_info("can't mmap pool of %u bytes: %s - using malloc\n",
+ (unsigned)poolsize, strerror(errno));
+ else {
+ pool_is_mmapped = 1;
+ pool_okay = 1;
+ }
+
+ #endif
+ if( !pool_okay ) {
+ pool = malloc( poolsize );
+ if( !pool )
+ log_fatal("can't allocate memory pool of %u bytes\n",
+ (unsigned)poolsize);
+ else
+ pool_okay = 1;
+ }
+ lock_pool( pool, poolsize );
+ poollen = 0;
+}
+
+
+/* concatenate unused blocks */
+static void
+compress_pool(void)
+{
+ /* fixme: we really should do this */
+}
+
+void
+secmem_set_flags( unsigned flags )
+{
+ int was_susp = suspend_warning;
+
+ no_warning = flags & 1;
+ suspend_warning = flags & 2;
+
+ /* and now issue the warning if it is not longer suspended */
+ if( was_susp && !suspend_warning && show_warning ) {
+ show_warning = 0;
+ print_warn();
+ }
+}
+
+unsigned
+secmem_get_flags(void)
+{
+ unsigned flags;
+
+ flags = no_warning ? 1:0;
+ flags |= suspend_warning ? 2:0;
+ return flags;
+}
+
+void
+secmem_init( size_t n )
+{
+ if( !n ) {
+ #ifdef USE_CAPABILITIES
+ /* drop all capabilities */
+ cap_set_proc( cap_from_text("all-eip") );
+
+ #elif !defined(HAVE_DOSISH_SYSTEM)
+ uid_t uid;
+
+ disable_secmem=1;
+ uid = getuid();
+ if( uid != geteuid() ) {
+ if( setuid( uid ) || getuid() != geteuid() )
+ log_fatal("failed to drop setuid\n" );
+ }
+ #endif
+ }
+ else {
+ if( n < DEFAULT_POOLSIZE )
+ n = DEFAULT_POOLSIZE;
+ if( !pool_okay )
+ init_pool(n);
+ else
+ log_error("Oops, secure memory pool already initialized\n");
+ }
+}
+
+
+void *
+secmem_malloc( size_t size )
+{
+ MEMBLOCK *mb, *mb2;
+ int compressed=0;
+
+ if( !pool_okay ) {
+ log_info(
+ _("operation is not possible without initialized secure memory\n"));
+ log_info(_("(you may have used the wrong program for this task)\n"));
+ exit(2);
+ }
+ if( show_warning && !suspend_warning ) {
+ show_warning = 0;
+ print_warn();
+ }
+
+ /* blocks are always a multiple of 32 */
+ size += sizeof(MEMBLOCK);
+ size = ((size + 31) / 32) * 32;
+
+ retry:
+ /* try to get it from the used blocks */
+ for(mb = unused_blocks,mb2=NULL; mb; mb2=mb, mb = mb->u.next )
+ if( mb->size >= size ) {
+ if( mb2 )
+ mb2->u.next = mb->u.next;
+ else
+ unused_blocks = mb->u.next;
+ goto leave;
+ }
+ /* allocate a new block */
+ if( (poollen + size <= poolsize) ) {
+ mb = (void*)((char*)pool + poollen);
+ poollen += size;
+ mb->size = size;
+ }
+ else if( !compressed ) {
+ compressed=1;
+ compress_pool();
+ goto retry;
+ }
+ else
+ return NULL;
+
+ leave:
+ cur_alloced += mb->size;
+ cur_blocks++;
+ if( cur_alloced > max_alloced )
+ max_alloced = cur_alloced;
+ if( cur_blocks > max_blocks )
+ max_blocks = cur_blocks;
+
+ return &mb->u.aligned.c;
+}
+
+
+void *
+secmem_realloc( void *p, size_t newsize )
+{
+ MEMBLOCK *mb;
+ size_t size;
+ void *a;
+
+ mb = (MEMBLOCK*)((char*)p - ((size_t) &((MEMBLOCK*)0)->u.aligned.c));
+ size = mb->size;
+ if( newsize < size )
+ return p; /* it is easier not to shrink the memory */
+ a = secmem_malloc( newsize );
+ memcpy(a, p, size);
+ memset((char*)a+size, 0, newsize-size);
+ secmem_free(p);
+ return a;
+}
+
+
+void
+secmem_free( void *a )
+{
+ MEMBLOCK *mb;
+ size_t size;
+
+ if( !a )
+ return;
+
+ mb = (MEMBLOCK*)((char*)a - ((size_t) &((MEMBLOCK*)0)->u.aligned.c));
+ size = mb->size;
+ /* This does not make much sense: probably this memory is held in the
+ * cache. We do it anyway: */
+ memset(mb, 0xff, size );
+ memset(mb, 0xaa, size );
+ memset(mb, 0x55, size );
+ memset(mb, 0x00, size );
+ mb->size = size;
+ mb->u.next = unused_blocks;
+ unused_blocks = mb;
+ cur_blocks--;
+ cur_alloced -= size;
+}
+
+
+int
+g10_private_is_secure( const void *p )
+{
+ return p >= pool && p < (void*)((char*)pool+poolsize);
+}
+
+
+
+/****************
+ * Warning: This code might be called by an interrupt handler
+ * and frankly, there should really be such a handler,
+ * to make sure that the memory is wiped out.
+ * We hope that the OS wipes out mlocked memory after
+ * receiving a SIGKILL - it really should do so, otherwise
+ * there is no chance to get the secure memory cleaned.
+ */
+void
+secmem_term()
+{
+ if( !pool_okay )
+ return;
+
+ memset( pool, 0xff, poolsize);
+ memset( pool, 0xaa, poolsize);
+ memset( pool, 0x55, poolsize);
+ memset( pool, 0x00, poolsize);
+ #if HAVE_MMAP
+ if( pool_is_mmapped )
+ munmap( pool, poolsize );
+ #endif
+ pool = NULL;
+ pool_okay = 0;
+ poolsize=0;
+ poollen=0;
+ unused_blocks=NULL;
+}
+
+
+void
+secmem_dump_stats()
+{
+ if( disable_secmem )
+ return;
+ fprintf(stderr,
+ "secmem usage: %u/%u bytes in %u/%u blocks of pool %lu/%lu\n",
+ cur_alloced, max_alloced, cur_blocks, max_blocks,
+ (ulong)poollen, (ulong)poolsize );
+}
+
diff --git a/src/secmem.h b/src/secmem.h
new file mode 100644
index 00000000..e1feedf0
--- /dev/null
+++ b/src/secmem.h
@@ -0,0 +1,35 @@
+/* secmem.h - internal definitions for secmem
+ * Copyright (C) 2000 Free Software Foundation, Inc.
+ *
+ * This file is part of GnuPG.
+ *
+ * GnuPG is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * GnuPG is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
+ */
+
+#ifndef G10_SECMEM_H
+#define G10_SECMEM_H 1
+
+void secmem_init( size_t npool );
+void secmem_term( void );
+void *secmem_malloc( size_t size );
+void *secmem_realloc( void *a, size_t newsize );
+void secmem_free( void *a );
+void secmem_dump_stats(void);
+void secmem_set_flags( unsigned flags );
+unsigned secmem_get_flags(void);
+
+int g10_private_is_secure( const void *p );
+
+#endif /* G10_SECMEM_H */
diff --git a/src/sexp.c b/src/sexp.c
index 4c84448e..915c633d 100644
--- a/src/sexp.c
+++ b/src/sexp.c
@@ -40,15 +40,6 @@
#include "memory.h"
-/* FIXME: We should really have the m_lib functions to allow
- * overriding of the default malloc functions
- * For now use this kludge: */
-#define m_lib_alloc m_alloc
-#define m_lib_alloc_clear m_alloc_clear
-#define m_lib_free m_free
-
-
-
#if 0
struct sexp_node;
@@ -173,11 +164,11 @@ gcry_sexp_new_data( const char *buffer, size_t length )
if( !length )
length = strlen(buffer);
- node = m_alloc_clear( sizeof *node + length );
+ node = g10_xcalloc( 1, sizeof *node + length );
node->type = ntDATA;
node->u.data.len = length;
memcpy(node->u.data.d, buffer, length );
- list = m_alloc_clear( sizeof *list );
+ list = g10_xcalloc( 1, sizeof *list );
list->type = ntLIST;
list->u.list = node;
return list;
@@ -191,10 +182,10 @@ gcry_sexp_new_mpi( GCRY_MPI mpi )
{
NODE list, node;
- node = m_alloc_clear( sizeof *node );
+ node = g10_xcalloc( 1, sizeof *node );
node->type = ntMPI;
node->u.mpi = gcry_mpi_copy( mpi );
- list = m_alloc_clear( sizeof *list );
+ list = g10_xcalloc( 1, sizeof *list );
list->type = ntLIST;
list->u.list = node;
return list;
@@ -254,7 +245,7 @@ gcry_sexp_cons( GCRY_SEXP a, GCRY_SEXP b )
}
- head = m_alloc_clear( sizeof *head );
+ head = g10_xcalloc( 1, sizeof *head );
head->type = ntLIST;
if( !a->u.list->next ) { /* a has only one item */
NODE tmp = a;
@@ -290,7 +281,7 @@ gcry_sexp_vlist( GCRY_SEXP a, ... )
fputs("sexp_vlist: arg 1 is not a list\n", stderr );
return NULL;
}
- head = m_alloc_clear( sizeof *node );
+ head = g10_xcalloc( 1, sizeof *node );
head->type = ntLIST;
if( !a->u.list->next ) { /* a has only one item */
NODE tmp = a;
@@ -645,7 +636,7 @@ gcry_sexp_sscan( GCRY_SEXP *retsexp, const char *buffer,
return -2; /* buffer too short */
}
/* make a new list entry */
- node = m_alloc_clear( sizeof *node + datalen );
+ node = g10_xcalloc( 1, sizeof *node + datalen );
if( first ) { /* stuff it into the first node */
first = 0;
node->up = tail;
@@ -687,7 +678,7 @@ gcry_sexp_sscan( GCRY_SEXP *retsexp, const char *buffer,
*erroff = p - buffer;
return -9; /* open display hint */
}
- node = m_alloc_clear( sizeof *node );
+ node = g10_xcalloc( 1, sizeof *node );
if( !head )
head = node;
else {
@@ -842,30 +833,30 @@ sexp_to_pk( GCRY_SEXP sexp, int want_private, MPI **retarray, int *retalgo)
algo = algos[i].algo;
elems1 = algos[i].common_elements;
elems2 = want_private? algos[i].secret_elements : algos[i].public_elements;
- array = m_lib_alloc_clear( (strlen(elems1)+strlen(elems2)+1) * sizeof *array );
+ array = g10_xcalloc( (strlen(elems1)+strlen(elems2)+1) , sizeof *array );
idx = 0;
for(s=elems1; *s; s++, idx++ ) {
l2 = gcry_sexp_find_token( list, s, 1 );
if( !l2 ) {
- m_lib_free( array );
+ g10_free( array );
return -5; /* required parameter not found */
}
array[idx] = gcry_sexp_cdr_mpi( l2, GCRYMPI_FMT_USG );
if( !array[idx] ) {
- m_lib_free( array );
+ g10_free( array );
return -6; /* required parameter is invalid */
}
}
for(s=elems2; *s; s++, idx++ ) {
l2 = gcry_sexp_find_token( list, s, 1 );
if( !l2 ) {
- m_lib_free( array );
+ g10_free( array );
return -5; /* required parameter not found */
}
/* FIXME: put the MPI in secure memory when needed */
array[idx] = gcry_sexp_cdr_mpi( l2, GCRYMPI_FMT_USG );
if( !array[idx] ) {
- m_lib_free( array );
+ g10_free( array );
return -6; /* required parameter is invalid */
}
}
diff --git a/src/stdmem.c b/src/stdmem.c
new file mode 100644
index 00000000..073c385b
--- /dev/null
+++ b/src/stdmem.c
@@ -0,0 +1,186 @@
+/* stdmem.c - private memory allocator
+ * Copyright (C) 1998, 2000 Free Software Foundation, Inc.
+ *
+ * This file is part of GnuPG.
+ *
+ * GnuPG is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * GnuPG is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
+ */
+
+#include <config.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <stdarg.h>
+
+#include "g10lib.h"
+#include "stdmem.h"
+#include "secmem.h"
+
+
+#define MAGIC_NOR_BYTE 0x55
+#define MAGIC_SEC_BYTE 0xcc
+#define MAGIC_END_BYTE 0xaa
+
+#if SIZEOF_UNSIGNED_LONG == 8
+ #define EXTRA_ALIGN 4
+#else
+ #define EXTRA_ALIGN 0
+#endif
+
+
+static int use_m_guard = 1;
+
+/****************
+ * Warning: Never use this function after any of the functions
+ * here have been used.
+ */
+void
+g10_private_enable_m_guard(void)
+{
+ use_m_guard = 1;
+}
+
+/****************
+ * Allocate memory of size n.
+ * Return NULL if we are out of memory.
+ */
+void *
+g10_private_malloc( size_t n)
+{
+ if( use_m_guard ) {
+ char *p;
+
+ if( !(p = malloc( n + EXTRA_ALIGN+5 )) )
+ return NULL;
+ ((byte*)p)[EXTRA_ALIGN+0] = n;
+ ((byte*)p)[EXTRA_ALIGN+1] = n >> 8 ;
+ ((byte*)p)[EXTRA_ALIGN+2] = n >> 16 ;
+ ((byte*)p)[EXTRA_ALIGN+3] = MAGIC_NOR_BYTE;
+ p[4+EXTRA_ALIGN+n] = MAGIC_END_BYTE;
+ return p+EXTRA_ALIGN+4;
+ }
+ else {
+ return malloc( n );
+ }
+}
+
+/****************
+ * Allocate memory of size n from the secure memory pool.
+ * Return NULL if we are out of memory.
+ */
+void *
+g10_private_malloc_secure( size_t n)
+{
+ if( use_m_guard ) {
+ char *p;
+
+ if( !(p = secmem_malloc( n +EXTRA_ALIGN+ 5 )) )
+ return NULL;
+ ((byte*)p)[EXTRA_ALIGN+0] = n;
+ ((byte*)p)[EXTRA_ALIGN+1] = n >> 8 ;
+ ((byte*)p)[EXTRA_ALIGN+2] = n >> 16 ;
+ ((byte*)p)[EXTRA_ALIGN+3] = MAGIC_SEC_BYTE;
+ p[4+EXTRA_ALIGN+n] = MAGIC_END_BYTE;
+ return p+EXTRA_ALIGN+4;
+ }
+ else {
+ return secmem_malloc( n );
+ }
+}
+
+
+/****************
+ * realloc and clear the old space
+ * Return NULL if there is not enoug memory.
+ */
+void *
+g10_private_realloc( void *a, size_t n )
+{
+ if( use_m_guard ) {
+ unsigned char *p = a;
+ void *b;
+ size_t len;
+
+ g10_private_check_heap(p);
+ len = p[-4];
+ len |= p[-3] << 8;
+ len |= p[-2] << 16;
+ if( len >= n ) /* we don't shrink for now */
+ return a;
+ if( p[-1] == MAGIC_SEC_BYTE )
+ b = g10_private_malloc_secure(n);
+ else
+ b = g10_private_malloc(n);
+ if( !b )
+ return NULL;
+ memcpy(b, a, len );
+ memset(b+len, 0, n-len );
+ g10_private_free( p );
+ return b;
+ }
+ else if( g10_private_is_secure(a) ) {
+ return secmem_realloc( a, n );
+ }
+ else {
+ return realloc( a, n );
+ }
+}
+
+
+void
+g10_private_check_heap( const void *a )
+{
+ if( use_m_guard ) {
+ const byte *p = a;
+ size_t len;
+
+ if( !p )
+ return;
+
+ if( !(p[-1] == MAGIC_NOR_BYTE || p[-1] == MAGIC_SEC_BYTE) )
+ g10_log_fatal("memory at %p corrupted (underflow=%02x)\n", p, p[-1] );
+ len = p[-4];
+ len |= p[-3] << 8;
+ len |= p[-2] << 16;
+ if( p[len] != MAGIC_END_BYTE )
+ g10_log_fatal("memory at %p corrupted (overflow=%02x)\n", p, p[-1] );
+ }
+}
+
+/****************
+ * Free a memory block allocated by this opr the secmem module
+ */
+void
+g10_private_free( void *a )
+{
+ byte *p = a;
+
+ if( !p )
+ return;
+ if( use_m_guard ) {
+ g10_private_check_heap(p);
+ if( g10_private_is_secure(a) )
+ secmem_free(p-EXTRA_ALIGN-4);
+ else {
+ free(p-EXTRA_ALIGN-4);
+ }
+ }
+ else if( g10_private_is_secure(a) )
+ secmem_free(p);
+ else
+ free(p);
+}
+
+
diff --git a/src/stdmem.h b/src/stdmem.h
new file mode 100644
index 00000000..f7e340fa
--- /dev/null
+++ b/src/stdmem.h
@@ -0,0 +1,32 @@
+/* stdmem.h - internal definitions for stdmem
+ * Copyright (C) 2000 Free Software Foundation, Inc.
+ *
+ * This file is part of GnuPG.
+ *
+ * GnuPG is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * GnuPG is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
+ */
+
+#ifndef G10_STDMEM_H
+#define G10_STDMEM_H 1
+
+void g10_private_enable_m_guard(void);
+
+void *g10_private_malloc( size_t n);
+void *g10_private_malloc_secure( size_t n);
+void *g10_private_realloc( void *a, size_t n );
+void g10_private_check_heap( const void *a );
+void g10_private_free( void *a );
+
+#endif /* G10_STDMEM_H */
diff --git a/src/wrapper.c b/src/wrapper.c
index 3b486de6..c38e0a4f 100644
--- a/src/wrapper.c
+++ b/src/wrapper.c
@@ -1,4 +1,4 @@
-/* wrapper.c - wrapper around some inertal functions
+/* wrapper.c - wrapper around the internal functions
* Copyright (C) 1999 Free Software Foundation, Inc.
*
* This file is part of GnuPG.
@@ -38,4 +38,5 @@ void *gcry_xcalloc_secure( size_t n, size_t m )
void *gcry_xrealloc( void *a, size_t n ) { return g10_xrealloc( a, n ); }
char *gcry_xstrdup( const char * a) { return g10_xstrdup( a); }
void gcry_free( void *p ) { g10_free( p ); }
+int gcry_is_secure( const void *p ) { g10_is_secure( p ); }