Akamai Technologies is pleased to offer the following patch to OpenSSL. It adds 
a "secure arena" that is used to store RSA private keys.  This arena is mmap'd, 
with guard pages before and after so pointer over- and under-runs won't wander 
into it. It's also locked into memory so it doesn't appear on disk, and when 
possible it's also kept out of core files.  This patch is a variant of what 
we've been using to help protect customer keys for a decade.



This should really be considered more of a proof of concept than something that 
you want to put directly into production. It slides into the ASN1 code rather 
than adding a new API (OPENSSL_secure_allocate et al), the overall code isn't 
portable, and so on. If there is community interest, we would be happy to help 
work on addressing those issues.  Let me restate that: *do not just take this 
patch and put it into production without careful review.*



OpenSSL is important to us, and this is the first of what we hope will be 
several significant contributions in the near future.



Thanks.



                /r$


--
Principal Security Engineer
Akamai Technology
Cambridge, MA


diff -uNr -x'*.[oas]' openssl-1.0.1g.orig/crypto/Makefile 
openssl-1.0.1g/crypto/Makefile
--- openssl-1.0.1g.orig/crypto/Makefile 2014-04-10 13:11:56.000000000 -0400
+++ openssl-1.0.1g/crypto/Makefile      2014-04-10 13:02:39.000000000 -0400
@@ -35,14 +35,16 @@
 LIB= $(TOP)/libcrypto.a
 SHARED_LIB= libcrypto$(SHLIB_EXT)
 LIBSRC=        cryptlib.c mem.c mem_clr.c mem_dbg.c cversion.c ex_data.c 
cpt_err.c \
-       ebcdic.c uid.c o_time.c o_str.c o_dir.c o_fips.c o_init.c fips_ers.c
+       ebcdic.c uid.c o_time.c o_str.c o_dir.c o_fips.c o_init.c fips_ers.c \
+       secure_malloc.c buddy_allocator.c
 LIBOBJ= cryptlib.o mem.o mem_dbg.o cversion.o ex_data.o cpt_err.o ebcdic.o \
-       uid.o o_time.o o_str.o o_dir.o o_fips.o o_init.o fips_ers.o $(CPUID_OBJ)
+       uid.o o_time.o o_str.o o_dir.o o_fips.o o_init.o fips_ers.o 
$(CPUID_OBJ) \
+       secure_malloc.o buddy_allocator.o
 
 SRC= $(LIBSRC)
 
 EXHEADER= crypto.h opensslv.h opensslconf.h ebcdic.h symhacks.h \
-       ossl_typ.h
+       ossl_typ.h secure_malloc.h
 HEADER=        cryptlib.h buildinf.h md32_common.h o_time.h o_str.h o_dir.h 
$(EXHEADER)
 
 ALL=    $(GENERAL) $(SRC) $(HEADER)
diff -uNr -x'*.[oas]' openssl-1.0.1g.orig/crypto/asn1/tasn_dec.c 
openssl-1.0.1g/crypto/asn1/tasn_dec.c
--- openssl-1.0.1g.orig/crypto/asn1/tasn_dec.c  2014-03-17 12:14:20.000000000 
-0400
+++ openssl-1.0.1g/crypto/asn1/tasn_dec.c       2014-04-10 16:32:23.000000000 
-0400
@@ -169,6 +169,11 @@
        int otag;
        int ret = 0;
        ASN1_VALUE **pchptr, *ptmpval;
+
+        int ak_is_rsa_key      = 0; /* Are we parsing an RSA key? */
+        int ak_is_secure_field = 0; /* should this field be allocated from the 
secure arena? */
+        int ak_is_arena_active = 0; /* was the secure arena already activated? 
*/
+
        if (!pval)
                return 0;
        if (aux && aux->asn1_cb)
@@ -407,6 +412,11 @@
                if (asn1_cb && !asn1_cb(ASN1_OP_D2I_PRE, pval, it, NULL))
                                goto auxerr;
 
+                /* Watch out for this when OpenSSL is upgraded! */
+                /* We have to be sure that it->sname will still be "RSA" */
+                if (it->sname[0] == 'R' && it->sname[1] == 'S' && it->sname[2] 
== 'A' && it->sname[3] == 0)
+                        ak_is_rsa_key = 1;
+
                /* Get each field entry */
                for (i = 0, tt = it->templates; i < it->tcount; i++, tt++)
                        {
@@ -445,8 +455,30 @@
                        /* attempt to read in field, allowing each to be
                         * OPTIONAL */
 
+ 
+                        /* Watch out for this when OpenSSL is upgraded! */
+                        /* We have to be sure that seqtt->field_name will 
still be */
+                        /* "d", "p", and "q" */
+                        ak_is_secure_field = 0;
+                        ak_is_arena_active = 0;
+                        if (ak_is_rsa_key)
+                        {
+                                /* ak_is_rsa_key is set for public keys too */
+                                /* however those don't have these variables */
+                                const char *f = seqtt->field_name;
+                                if ((f[0] == 'd' || f[0] == 'p' || f[0] == 
'q') && f[1] == 0)
+                                {
+                                        ak_is_secure_field = 1;
+                                        ak_is_arena_active = 
start_secure_allocation();
+                                }
+                        }
+
                        ret = asn1_template_ex_d2i(pseqval, &p, len,
                                                        seqtt, isopt, ctx);
+ 
+                        if (ak_is_secure_field && !ak_is_arena_active)
+                                stop_secure_allocation();
+ 
                        if (!ret)
                                {
                                errtt = seqtt;
diff -uNr -x'*.[oas]' openssl-1.0.1g.orig/crypto/buddy_allocator.c 
openssl-1.0.1g/crypto/buddy_allocator.c
--- openssl-1.0.1g.orig/crypto/buddy_allocator.c        1969-12-31 
19:00:00.000000000 -0500
+++ openssl-1.0.1g/crypto/buddy_allocator.c     2014-04-10 16:23:06.000000000 
-0400
@@ -0,0 +1,407 @@
+/*
+ * Memory allocator for secure heap for OpenSSL key storage.
+ * Copyright, 2001-2014, Akamai Technologies. All Rights Reserved.
+ * Distributed under the terms of the OpenSSL license.
+ */
+#include <stdlib.h>  
+#include <assert.h> 
+#include <unistd.h>
+#include <string.h>
+#include <sys/mman.h>
+#include <sys/param.h>
+
+static void *cmm_arena = NULL;
+static void **cmm_free_list = NULL;
+static int cmm_max_free_lists;
+static int mem_arena_size = 0;
+static int Mem_min_unit  = 0;
+static int Overrun_bytes = 0;
+
+typedef unsigned char u_int8;
+
+static u_int8 *cmm_bittable;
+static u_int8 *cmm_bitmalloc;
+/* size in bits */
+static int cmm_bittable_size;
+
+#define SETBIT(_a,_b) ((_a)[(_b)>>3] |= (1<<((_b)&7)))
+#define CLEARBIT(_a,_b) ((_a)[(_b)>>3] &= (0xff&~(1<<((_b)&7))))
+#define TESTBIT(_a,_b) ((_a)[(_b)>>3] & (1<<((_b)&7)))
+
+static void cmm_add_to_list(void **list, void *lamb);
+static void cmm_remove_from_list(void *lamb, void *list);
+static void *mybuddy(void *lamb, int list);
+static int getlist(void *lamb);
+static int testbit(void *lamb, int list, u_int8 *table);
+static void clearbit(void *lamb, int list, u_int8 *table);
+static void set_bit(void *lamb, int list, u_int8 *table);
+
+void *
+cmm_init(int size, int mem_min_unit, int overrun_bytes)
+{
+    int i;
+
+    mem_arena_size = size;
+    Mem_min_unit   = mem_min_unit,
+    Overrun_bytes  = overrun_bytes;
+    /* make sure mem_arena_size and Mem_min_unit are powers of 2 */
+    assert(mem_arena_size > 0);
+    assert(mem_min_unit > 0);
+    assert(0 == ((mem_arena_size-1)&mem_arena_size));
+    assert(0 == ((Mem_min_unit-1)&Mem_min_unit));
+
+    cmm_bittable_size = (mem_arena_size/Mem_min_unit) * 2;
+
+    i = cmm_bittable_size;
+    cmm_max_free_lists = -1;
+    while(i) {
+       i>>=1;
+       cmm_max_free_lists++;
+    }
+
+    cmm_free_list = malloc(cmm_max_free_lists * sizeof(void *));
+    assert(cmm_free_list);
+    memset(cmm_free_list, 0, cmm_max_free_lists*sizeof(void *));
+
+    cmm_bittable = malloc(cmm_bittable_size>>3);
+    assert(cmm_bittable);
+    memset(cmm_bittable, 0, cmm_bittable_size>>3);
+
+    cmm_bitmalloc = malloc(cmm_bittable_size>>3);
+    assert(cmm_bitmalloc);
+    memset(cmm_bitmalloc, 0, cmm_bittable_size>>3);
+
+    cmm_arena = mmap(NULL, mem_arena_size, PROT_READ|PROT_WRITE,
+                    MAP_ANON|MAP_PRIVATE, 0, 0);
+    assert(MAP_FAILED  != cmm_arena);
+    set_bit(cmm_arena, 0, cmm_bittable);
+    cmm_add_to_list(&cmm_free_list[0], cmm_arena);
+
+    /* first bit means that table is in use, multi-arena management */
+    /* SETBIT(cmm_bittable, 0); */
+
+    return cmm_arena;
+}
+
+void *
+cmm_malloc(int size)
+{
+    int i, list, slist;
+    void *chunk = NULL, *temp;
+
+    i = Mem_min_unit; list = cmm_max_free_lists-1;
+    while (i < size + Overrun_bytes) {
+       i<<=1;
+       list--;
+    }
+    if (list < 0) goto out;
+
+    /* try to find a larger entry to split */
+    slist = list;
+    while (slist >= 0) {
+       if (cmm_free_list[slist] != NULL)
+           break;
+       slist--;
+    }
+    if (slist < 0) goto out;
+
+    /* split larger entry */
+    while (slist != list) {
+       temp = cmm_free_list[slist];
+
+       /* remove from bigger list */
+       assert(!testbit(temp, slist, cmm_bitmalloc));
+       clearbit(temp, slist, cmm_bittable);
+       cmm_remove_from_list(temp, cmm_free_list[slist]);
+       assert(temp != cmm_free_list[slist]);
+
+       /* done with bigger list */
+       slist++;
+
+       /* add to smaller list */
+       assert(!testbit(temp, slist, cmm_bitmalloc));
+       set_bit(temp, slist, cmm_bittable);
+       cmm_add_to_list(&cmm_free_list[slist], temp);
+       assert(cmm_free_list[slist] == temp);
+
+       /* split in 2 */
+       temp += mem_arena_size >> slist;
+       assert(!testbit(temp, slist, cmm_bitmalloc));
+       set_bit(temp, slist, cmm_bittable);
+       cmm_add_to_list(&cmm_free_list[slist], temp);
+       assert(cmm_free_list[slist] == temp);
+
+       assert(temp-(mem_arena_size>>slist) == mybuddy(temp, slist));
+    }
+
+    /* peel off memory to hand back */
+    chunk = cmm_free_list[list];
+    assert(testbit(chunk, list, cmm_bittable));
+    set_bit(chunk, list, cmm_bitmalloc);
+    cmm_remove_from_list(chunk, cmm_free_list[list]);
+
+    assert(chunk >= cmm_arena && chunk < cmm_arena+mem_arena_size);
+
+#ifdef CMM_DEBUG
+    for (i = 0; i < cmm_bittable_size; i++) {
+       if (TESTBIT(cmm_bitmalloc,i)) {
+           assert(TESTBIT(cmm_bittable,i));
+       }
+    }
+#endif
+
+ out:
+    return chunk;
+}
+
+static int cmm_free_calls = 0;
+
+int
+cmm_free(void *lamb)
+{
+    int list;
+    void *buddy;
+#ifdef CMM_DEBUG
+    int i;
+#endif
+    cmm_free_calls++;
+
+    assert(lamb >= cmm_arena && lamb < cmm_arena+mem_arena_size);
+
+    list = getlist(lamb);
+    assert(testbit(lamb, list, cmm_bittable));
+    clearbit(lamb, list, cmm_bitmalloc);
+    cmm_add_to_list(&cmm_free_list[list], lamb);
+
+    while (NULL != (buddy = mybuddy(lamb, list))) {
+       assert(lamb == mybuddy(buddy, list));
+
+       assert(lamb);
+       assert(!testbit(lamb, list, cmm_bitmalloc));
+       clearbit(lamb, list, cmm_bittable);
+       cmm_remove_from_list(lamb, cmm_free_list[list]);
+       assert(!testbit(lamb, list, cmm_bitmalloc));
+       clearbit(buddy, list, cmm_bittable);
+       cmm_remove_from_list(buddy, cmm_free_list[list]);
+
+       list--;
+
+       if (lamb > buddy) lamb = buddy;
+
+       assert(!testbit(lamb, list, cmm_bitmalloc));
+       set_bit(lamb, list, cmm_bittable);
+       cmm_add_to_list(&cmm_free_list[list], lamb);
+       assert(cmm_free_list[list] == lamb);
+    }
+
+#ifdef CMM_DEBUG
+    for (i = 0; i < cmm_bittable_size; i++) {
+       if (TESTBIT(cmm_bitmalloc,i)) {
+           assert(TESTBIT(cmm_bittable,i));
+       }
+    }
+#endif
+
+    return 0;
+}
+
+int
+cmm_usable_size(void *lamb)
+{
+    int list = getlist(lamb);
+    int size;
+
+    assert(lamb >= cmm_arena && lamb < cmm_arena+mem_arena_size);
+    assert(testbit(lamb, list, cmm_bittable));
+
+    size = mem_arena_size/(1<<list);
+
+    return size;
+}
+
+void *
+cmm_realloc(void *lamb, int size)
+{
+    void *temp;
+    int oldsize;
+
+    oldsize = cmm_usable_size(lamb);
+
+    if ((size > oldsize/2) && (size <= oldsize))
+        return lamb;
+
+    if ((size < Mem_min_unit) && (Mem_min_unit == oldsize))
+        return lamb;
+
+    temp = lamb;
+    lamb = cmm_malloc(size);
+
+    if (NULL == lamb)
+        return NULL;
+
+    size = MIN(size, oldsize);
+    memcpy(lamb, temp, size);
+
+    cmm_free(temp);
+
+    return lamb;
+}
+
+typedef struct _cmm_list cmm_list;
+struct _cmm_list {
+    cmm_list *next;
+    cmm_list **p_next;
+};
+
+static void
+cmm_add_to_list(void **list, void *lamb)
+{
+    cmm_list *temp;
+#ifdef CMM_DEBUG
+    cmm_list *temp2;
+#endif
+
+    assert(list >= cmm_free_list &&
+          list < cmm_free_list + cmm_max_free_lists);
+    assert(lamb >= cmm_arena &&
+          lamb < cmm_arena + mem_arena_size);
+
+    temp = (cmm_list *)lamb;
+    temp->next = *(cmm_list **)list;
+    assert(temp->next == NULL ||
+          ((void *)temp->next >= cmm_arena &&
+           (void *)temp->next < cmm_arena+mem_arena_size));
+    temp->p_next = (cmm_list **)list;
+
+    if (NULL != temp->next) {
+       assert((void **)temp->next->p_next == list);
+       temp->next->p_next = &(temp->next);
+    }
+
+    *list = lamb;
+
+#ifdef CMM_DEBUG
+    for (temp = *list; temp != NULL; temp = temp->next) {
+       if (NULL != temp->next)
+           assert(temp->next->p_next == &temp->next);
+       if (lamb == temp) temp2 = lamb;
+    }
+    assert (NULL != temp2);
+#endif
+}
+
+static void
+cmm_remove_from_list(void *lamb, void *list)
+{
+    cmm_list *temp, *temp2;
+
+#ifdef CMM_DEBUG
+    temp2 = NULL;
+
+    for (temp = list; temp != NULL; temp = temp->next) {
+       if (NULL != temp->next)
+           assert(temp->next->p_next == &temp->next);
+       if (lamb == temp) temp2 = lamb;
+    }
+    assert (NULL != temp2);
+#endif
+
+    temp = (cmm_list *)lamb;
+    if (NULL != temp->next)
+       temp->next->p_next = temp->p_next;
+    *temp->p_next = temp->next;
+
+    if (NULL == temp->next)
+       return;
+
+    temp2 = temp->next;
+    assert((((void **)temp2->p_next >= cmm_free_list) &&
+           ((void **)temp2->p_next < cmm_free_list + cmm_max_free_lists))
+          ||
+          (((void *)temp2->p_next >= cmm_arena) &&
+           ((void *)temp2->p_next < cmm_arena + mem_arena_size)));
+}
+
+static void *
+mybuddy(void *lamb, int list)
+{
+    int index;
+    void *chunk = NULL;
+
+    index = (1<<list) + ((lamb-cmm_arena)/(mem_arena_size>>list));
+    index ^= 1;
+
+    if (TESTBIT(cmm_bittable,index) &&
+       !TESTBIT(cmm_bitmalloc,index)) {
+       chunk = cmm_arena + ((index & ((1<<list)-1)) * (mem_arena_size>>list));
+    }
+
+    return chunk;
+}
+
+static int
+getlist(void *lamb)
+{
+    int index, list;
+
+    list = cmm_max_free_lists-1;
+    index = (mem_arena_size + lamb - cmm_arena) / Mem_min_unit;
+
+    while (index) {
+       if (TESTBIT(cmm_bittable,index)) {
+           break;
+       }
+       assert(!(index & 1));
+       index >>= 1;
+       list--;
+    }
+
+    return list;
+}
+
+static int
+testbit(void *lamb, int list, u_int8 *table)
+{
+    int index;
+
+    assert(list < cmm_max_free_lists && list >= 0);
+    assert(!((lamb-cmm_arena)&((mem_arena_size>>list)-1)));
+
+    index = (1<<list) + ((lamb - cmm_arena) / (mem_arena_size>>list));
+
+    assert(index > 0 && index < cmm_bittable_size);
+
+    return TESTBIT(table,index);
+}
+
+static void
+clearbit(void *lamb, int list, u_int8 *table)
+{
+    int index;
+
+    assert(list < cmm_max_free_lists && list >= 0);
+    assert(!((lamb-cmm_arena)&((mem_arena_size>>list)-1)));
+
+    index = (1<<list) + ((lamb - cmm_arena) / (mem_arena_size>>list));
+
+    assert(index > 0 && index < cmm_bittable_size);
+
+    assert(TESTBIT(table,index));
+    CLEARBIT(table,index);
+}
+
+static void
+set_bit(void *lamb, int list, u_int8 *table)
+{
+    int index;
+
+    assert(list < cmm_max_free_lists && list >= 0);
+    assert(!((lamb-cmm_arena)&((mem_arena_size>>list)-1)));
+
+    index = (1<<list) + ((lamb - cmm_arena) / (mem_arena_size>>list));
+
+    assert(index > 0 && index < cmm_bittable_size);
+
+    assert(!TESTBIT(table,index));
+    SETBIT(table,index);
+}
diff -uNr -x'*.[oas]' openssl-1.0.1g.orig/crypto/crypto.h 
openssl-1.0.1g/crypto/crypto.h
--- openssl-1.0.1g.orig/crypto/crypto.h 2014-03-17 12:14:20.000000000 -0400
+++ openssl-1.0.1g/crypto/crypto.h      2014-04-10 13:01:08.000000000 -0400
@@ -365,20 +365,16 @@
 #define MemCheck_off() CRYPTO_mem_ctrl(CRYPTO_MEM_CHECK_DISABLE)
 #define is_MemCheck_on() CRYPTO_is_mem_check_on()
 
-#define OPENSSL_malloc(num)    CRYPTO_malloc((int)num,__FILE__,__LINE__)
-#define OPENSSL_strdup(str)    CRYPTO_strdup((str),__FILE__,__LINE__)
-#define OPENSSL_realloc(addr,num) \
-       CRYPTO_realloc((char *)addr,(int)num,__FILE__,__LINE__)
-#define OPENSSL_realloc_clean(addr,old_num,num) \
-       CRYPTO_realloc_clean(addr,old_num,num,__FILE__,__LINE__)
-#define OPENSSL_remalloc(addr,num) \
-       CRYPTO_remalloc((char **)addr,(int)num,__FILE__,__LINE__)
-#define OPENSSL_freeFunc       CRYPTO_free
-#define OPENSSL_free(addr)     CRYPTO_free(addr)
-
-#define OPENSSL_malloc_locked(num) \
-       CRYPTO_malloc_locked((int)num,__FILE__,__LINE__)
-#define OPENSSL_free_locked(addr) CRYPTO_free_locked(addr)
+#include <openssl/secure_malloc.h>
+#define OPENSSL_malloc(s)       secure_malloc(s)
+#define OPENSSL_strdup(str)     secure_strdup(str)
+#define OPENSSL_free(a)         secure_free(a)
+#define OPENSSL_realloc(a,s)    secure_realloc(a,s)
+#define OPENSSL_realloc_clean(a,o,s) secure_realloc_clean(a,o,s)
+#define OPENSSL_remalloc(a,s) (OPENSSL_free(a), OPENSSL_malloc(s))
+#define OPENSSL_freeFunc      secure_free
+#define OPENSSL_malloc_locked(s) OPENSSL_malloc(s)
+#define OPENSSL_free_locked(a) OPENSSL_free(a)
 
 
 const char *SSLeay_version(int type);
diff -uNr -x'*.[oas]' openssl-1.0.1g.orig/crypto/secure_malloc.c 
openssl-1.0.1g/crypto/secure_malloc.c
--- openssl-1.0.1g.orig/crypto/secure_malloc.c  1969-12-31 19:00:00.000000000 
-0500
+++ openssl-1.0.1g/crypto/secure_malloc.c       2014-04-10 16:43:35.000000000 
-0400
@@ -0,0 +1,223 @@
+/*
+ * Memory allocator for secure heap for OpenSSL key storage.
+ * Copyright, 2001-2014, Akamai Technologies. All Rights Reserved.
+ * Distributed under the terms of the OpenSSL license.
+ *
+ * Note that to improve performance and simplfy the code, this allocator
+ * works only in the same thread where we called the init function;
+ * trying to allocate/free blocks from different threads will
+ * just delegate the calls to the standard malloc library. 
+ */
+
+#include <pthread.h>
+#include <string.h>
+#include <sys/mman.h>
+#include <stdlib.h>  
+#include <assert.h>
+
+#include "secure_malloc.h"
+
+extern void OPENSSL_cleanse(void *ptr, size_t len);
+
+/*
+ * Set to 1 when secure_malloc_init() is called successfully.  Can
+ * never be set back to 0
+ */
+int secure_allocation_support = 0;
+
+static pthread_mutex_t secure_allocation_lock = PTHREAD_MUTEX_INITIALIZER;
+
+#define LOCK() pthread_mutex_lock(&secure_allocation_lock)
+#define UNLOCK() pthread_mutex_unlock(&secure_allocation_lock)
+
+static pthread_key_t secure_allocation_key;
+static const int secure_yes = 1;
+static const int secure_no = 0;
+
+static char *arena = NULL;
+static size_t arena_size = 0;
+
+/* The low-level secure heap interface. */
+extern void *cmm_init(int size, int mem_min_unit, int overrun_bytes);
+extern void *cmm_malloc(int size);
+extern int cmm_free(void *lamb);
+extern void *cmm_realloc(void *lamb, int size);
+
+static int secure_allocation_enabled()
+{
+  if (!secure_allocation_support)
+  {
+    return 0;
+  }
+  int* answer = (int*)pthread_getspecific(secure_allocation_key);
+  return answer == &secure_yes;
+}
+
+static void secure_allocation_enable(int status)
+{
+  if (secure_allocation_support)
+  {
+    pthread_setspecific(secure_allocation_key,
+            status ? &secure_yes : &secure_no);
+  }
+}
+
+/*
+ * Start/stop secure allocation.
+ */
+int start_secure_allocation()
+{
+  int ret = secure_allocation_enabled();
+  if (ret == 0)
+  {
+    secure_allocation_enable(1);
+  }
+
+  return ret;
+}
+
+int stop_secure_allocation() 
+{
+  int ret = secure_allocation_enabled();
+  if (ret == 1)
+  {
+    secure_allocation_enable(0);
+  }
+  
+  return ret;
+}
+
+void flush_secure_arena()
+{
+  if (arena)
+    memset(arena, 0, arena_size);
+}
+
+/* Module initialization, returns >0 upon success */
+int secure_malloc_init(size_t size, int mem_min_unit, int overrun_bytes)
+{
+  int ret = 0;
+  arena_size = size;
+
+  LOCK();
+  if (arena)
+  {
+    assert(0);
+  }
+
+  else if ((arena = (char *) cmm_init(arena_size, mem_min_unit, 
overrun_bytes)) == NULL)
+  {
+  }
+  else if (mlock(arena, arena_size))
+  {
+  }
+  else if (pthread_key_create(&secure_allocation_key, 0) != 0)
+  {
+  }
+  else
+  {
+    secure_allocation_support = 1;
+    ret = 1;
+  }
+
+  /* MADV_DONTDUMP is supported from Kernel 3.4 and from glibc 2.16 */
+#ifdef MADV_DONTDUMP
+  if (madvise(arena, arena_size, MADV_DONTDUMP) == 0)
+  {
+    ret = 2;
+  }
+#endif
+
+  UNLOCK();
+  return ret;
+}
+
+/* Helper func to figure out whether a pointer was allocated from the
+   secure chunk. 
+*/
+static int is_secured_ptr(void *ptr)
+{
+  return secure_allocation_support
+      && (char*)ptr >= arena && (char*)ptr < arena + arena_size;
+}
+
+void *secure_calloc(size_t nmemb, size_t size)
+{
+  void *ret;
+  int tot_size = nmemb*size;
+
+  if (!secure_allocation_enabled())
+    return calloc(nmemb,size);
+  LOCK();
+  ret = cmm_malloc(tot_size);
+  if (ret) 
+  {
+    memset(ret,0,tot_size);
+  }
+  UNLOCK();
+  return ret;
+}
+
+void *secure_malloc(size_t size)
+{
+  void *ret;
+
+  if (!secure_allocation_enabled())
+    return malloc(size);
+  LOCK();
+  ret = cmm_malloc(size);
+  UNLOCK();
+  return ret;
+}
+
+void *secure_strdup(const char *str)
+{
+  return strcpy(secure_malloc(strlen(str) + 1), str);
+}
+
+void secure_free(void *ptr)
+{
+  if (secure_allocation_support && is_secured_ptr(ptr))
+  {
+    LOCK();
+    cmm_free(ptr);
+    UNLOCK();
+  }
+  else
+  {
+    free(ptr);
+  }
+
+}
+
+void *secure_realloc(void *ptr, size_t size)
+{
+  void *ret;
+
+  if (secure_allocation_support && is_secured_ptr(ptr))
+  {
+    LOCK();
+    ret = cmm_realloc(ptr,size);
+    UNLOCK();
+  }
+  else 
+  {
+    ret = realloc(ptr,size);
+  }
+  
+  return ret;
+}
+
+void *secure_realloc_clean(void *ptr, int old_len, size_t size)
+{
+  void *ret;
+
+  ret = secure_malloc(size);
+  if (ret)
+    memcpy(ret, ptr, old_len);
+
+  OPENSSL_cleanse(ptr, old_len);
+  secure_free(ptr);
+
+  return ret;
+}
diff -uNr -x'*.[oas]' openssl-1.0.1g.orig/crypto/secure_malloc.h 
openssl-1.0.1g/crypto/secure_malloc.h
--- openssl-1.0.1g.orig/crypto/secure_malloc.h  1969-12-31 19:00:00.000000000 
-0500
+++ openssl-1.0.1g/crypto/secure_malloc.h       2014-04-10 16:40:48.000000000 
-0400
@@ -0,0 +1,45 @@
+/*
+ * Memory allocator for secure heap for OpenSSL key storage.
+ * Copyright, 2001-2014, Akamai Technologies. All Rights Reserved.
+ * Distributed under the terms of the OpenSSL license.
+ */
+
+#ifndef __openssl_secure_malloc_h
+#define __openssl_secure_malloc_h
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* Global flag to designate whether secure malloc support is turned on */ 
+extern int secure_allocation_support;
+
+/* Secure versions of the malloc interface functions */
+extern void *secure_calloc(size_t nmemb, size_t size);
+extern void *secure_malloc(size_t size);
+extern void *secure_strdup(const char *str);
+extern void secure_free(void *ptr);
+extern void *secure_realloc(void *ptr, size_t size);
+extern void *secure_realloc_clean(void *ptr, int old_len, size_t size);
+
+/* Module initialization including setting secure_malloc_support. */
+extern int secure_malloc_init(size_t arena_size, int mem_min_unit, int 
overrun_bytes);
+
+/*
+ * Enabling/Disabling the secure allocation.  Use like this to ensure
+ * proper nesting:
+ *   int x = start_secure_allocation();
+ *   .... do some work, calling OPENSSL_malloc etc ...
+ *   if (x) stop_secure_allocation();
+ */
+extern int start_secure_allocation();
+extern int stop_secure_allocation();
+
+/* Erasing the content of all allocated buffers */
+extern void flush_secure_arena();
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif

Reply via email to