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.0 -0400
+++ openssl-1.0.1g/crypto/Makefile 2014-04-10 13:02:39.0 -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.0
-0400
+++ openssl-1.0.1g/crypto/asn1/tasn_dec.c 2014-04-10 16:32:23.0
-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();
+