[prev in list] [next in list] [prev in thread] [next in thread] 

List:       openssl-users
Subject:    Secure storage of private (RSA) keys
From:       "Salz, Rich" <rsalz () akamai ! com>
Date:       2014-04-11 17:22:21
Message-ID: 2A0EFB9C05D0164E98F19BB0AF3708C7120B48FB4C () USMBX1 ! msg ! corp ! akamai ! com
[Download RAW message or body]

[Attachment #2 (multipart/alternative)]


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 i=
s 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 decad=
e.



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 n=
ot 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 s=
everal significant contributions in the near future.



Thanks.



                /r$


--
Principal Security Engineer
Akamai Technology
Cambridge, MA



[Attachment #5 (text/html)]

<html xmlns:v="urn:schemas-microsoft-com:vml" \
xmlns:o="urn:schemas-microsoft-com:office:office" \
xmlns:w="urn:schemas-microsoft-com:office:word" \
xmlns:m="http://schemas.microsoft.com/office/2004/12/omml" \
xmlns="http://www.w3.org/TR/REC-html40"><head><meta http-equiv=Content-Type \
content="text/html; charset=us-ascii"><meta name=Generator content="Microsoft Word 14 \
(filtered medium)"><style><!-- /* Font Definitions */
@font-face
	{font-family:Calibri;
	panose-1:2 15 5 2 2 2 4 3 2 4;}
/* Style Definitions */
p.MsoNormal, li.MsoNormal, div.MsoNormal
	{margin:0in;
	margin-bottom:.0001pt;
	font-size:11.0pt;
	font-family:"Calibri","sans-serif";}
a:link, span.MsoHyperlink
	{mso-style-priority:99;
	color:blue;
	text-decoration:underline;}
a:visited, span.MsoHyperlinkFollowed
	{mso-style-priority:99;
	color:purple;
	text-decoration:underline;}
p.MsoPlainText, li.MsoPlainText, div.MsoPlainText
	{mso-style-priority:99;
	mso-style-link:"Plain Text Char";
	margin:0in;
	margin-bottom:.0001pt;
	font-size:11.0pt;
	font-family:"Calibri","sans-serif";}
span.EmailStyle17
	{mso-style-type:personal-compose;
	font-family:"Calibri","sans-serif";
	color:windowtext;}
span.PlainTextChar
	{mso-style-name:"Plain Text Char";
	mso-style-priority:99;
	mso-style-link:"Plain Text";
	font-family:"Calibri","sans-serif";}
.MsoChpDefault
	{mso-style-type:export-only;
	font-family:"Calibri","sans-serif";}
@page WordSection1
	{size:8.5in 11.0in;
	margin:1.0in 1.0in 1.0in 1.0in;}
div.WordSection1
	{page:WordSection1;}
--></style><!--[if gte mso 9]><xml>
<o:shapedefaults v:ext="edit" spidmax="1026" />
</xml><![endif]--><!--[if gte mso 9]><xml>
<o:shapelayout v:ext="edit">
<o:idmap v:ext="edit" data="1" />
</o:shapelayout></xml><![endif]--></head><body lang=EN-US link=blue vlink=purple><div \
class=WordSection1><p class=MsoPlainText>Akamai Technologies is pleased to offer the \
following patch to OpenSSL. It adds a &quot;secure arena&quot; that is used to store \
RSA private keys.&nbsp; 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.&nbsp; \
This patch is a variant of what we've been using to help protect customer keys for a \
decade.<o:p></o:p></p><p class=MsoPlainText><o:p>&nbsp;</o:p></p><p \
class=MsoPlainText>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.&nbsp; Let me restate that: *<b>do not just take this \
patch and put it into production without careful review.</b>*<o:p></o:p></p><p \
class=MsoPlainText><o:p>&nbsp;</o:p></p><p class=MsoPlainText>OpenSSL is important to \
us, and this is the first of what we hope will be several significant contributions \
in the near future.<o:p></o:p></p><p class=MsoPlainText><o:p>&nbsp;</o:p></p><p \
class=MsoPlainText>Thanks.<o:p></o:p></p><p \
class=MsoPlainText><o:p>&nbsp;</o:p></p><p \
class=MsoPlainText>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; \
/r$<o:p></o:p></p><p class=MsoPlainText><o:p>&nbsp;</o:p></p><p \
class=MsoNormal>--&nbsp; <o:p></o:p></p><p class=MsoNormal>Principal Security \
Engineer<o:p></o:p></p><p class=MsoNormal>Akamai Technology<o:p></o:p></p><p \
class=MsoNormal>Cambridge, MA<o:p></o:p></p><p \
class=MsoNormal><o:p>&nbsp;</o:p></p><p \
class=MsoNormal><o:p>&nbsp;</o:p></p></div></body></html>


["akamai-secure-arena.txt" (text/plain)]

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


______________________________________________________________________
OpenSSL Project                                 http://www.openssl.org
User Support Mailing List                    openssl-users@openssl.org
Automated List Manager                           majordomo@openssl.org

[prev in list] [next in list] [prev in thread] [next in thread] 

Configure | About | News | Add a list | Sponsored by KoreLogic