Created
April 12, 2014 20:13
-
-
Save hausdorff/10554471 to your computer and use it in GitHub Desktop.
Akamai OpenSSL patch
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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 |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment