Commit 74924dcb authored by Rich Salz's avatar Rich Salz Committed by Rich Salz
Browse files

More secure storage of key material.



Add secure heap for storage of private keys (when possible).
Add BIO_s_secmem(), CBIGNUM, etc.
Add BIO_CTX_secure_new so all BIGNUM's in the context are secure.
Contributed by Akamai Technologies under the Corporate CLA.

Reviewed-by: default avatarRichard Levitte <levitte@openssl.org>
parent ce7e647b
Loading
Loading
Loading
Loading
+5 −0
Original line number Diff line number Diff line
@@ -126,6 +126,11 @@
        NULL.  Remove the non-null checks from callers.  Save much code.
     [Rich Salz]

  *) Add secure heap for storage of private keys (when possible).
     Add BIO_s_secmem(), CBIGNUM, etc.
     Contributed by Akamai Technologies under our Corporate CLA.
     [Rich Salz]

  *) Experimental support for a new, fast, unbiased prime candidate generator,
     bn_probable_prime_dh_coprime(). Not currently used by any prime generator.
     [Felix Laurie von Massenbach <felix@erbridge.co.uk>]
+6 −2
Original line number Diff line number Diff line
@@ -36,10 +36,10 @@ 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 thr_id.c lock.c fips_ers.c \
	o_init.c o_fips.c
	o_init.c o_fips.c sec_mem.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 thr_id.o lock.o fips_ers.o \
	o_init.o o_fips.o $(CPUID_OBJ)
	o_init.o o_fips.o sec_mem.o $(CPUID_OBJ)

SRC= $(LIBSRC)

@@ -208,6 +208,10 @@ o_time.o: ../include/openssl/crypto.h ../include/openssl/e_os2.h
o_time.o: ../include/openssl/opensslconf.h ../include/openssl/opensslv.h
o_time.o: ../include/openssl/ossl_typ.h ../include/openssl/safestack.h
o_time.o: ../include/openssl/stack.h ../include/openssl/symhacks.h o_time.c
sec_mem.o: ../e_os.h ../include/openssl/crypto.h ../include/openssl/e_os2.h
sec_mem.o: ../include/openssl/opensslconf.h ../include/openssl/opensslv.h
sec_mem.o: ../include/openssl/ossl_typ.h ../include/openssl/safestack.h
sec_mem.o: ../include/openssl/stack.h ../include/openssl/symhacks.h sec_mem.c
thr_id.o: ../e_os.h ../include/openssl/bio.h ../include/openssl/buffer.h
thr_id.o: ../include/openssl/crypto.h ../include/openssl/e_os2.h
thr_id.o: ../include/openssl/err.h ../include/openssl/lhash.h
+31 −1
Original line number Diff line number Diff line
@@ -72,12 +72,15 @@
#define BN_SENSITIVE    1

static int bn_new(ASN1_VALUE **pval, const ASN1_ITEM *it);
static int bn_secure_new(ASN1_VALUE **pval, const ASN1_ITEM *it);
static void bn_free(ASN1_VALUE **pval, const ASN1_ITEM *it);

static int bn_i2c(ASN1_VALUE **pval, unsigned char *cont, int *putype,
                  const ASN1_ITEM *it);
static int bn_c2i(ASN1_VALUE **pval, const unsigned char *cont, int len,
                  int utype, char *free_cont, const ASN1_ITEM *it);
static int bn_secure_c2i(ASN1_VALUE **pval, const unsigned char *cont, int len,
                         int utype, char *free_cont, const ASN1_ITEM *it);

static ASN1_PRIMITIVE_FUNCS bignum_pf = {
    NULL, 0,
@@ -88,12 +91,21 @@ static ASN1_PRIMITIVE_FUNCS bignum_pf = {
    bn_i2c
};

static ASN1_PRIMITIVE_FUNCS cbignum_pf = {
    NULL, 0,
    bn_secure_new,
    bn_free,
    0,
    bn_secure_c2i,
    bn_i2c
};

ASN1_ITEM_start(BIGNUM)
        ASN1_ITYPE_PRIMITIVE, V_ASN1_INTEGER, NULL, 0, &bignum_pf, 0, "BIGNUM"
ASN1_ITEM_end(BIGNUM)

ASN1_ITEM_start(CBIGNUM)
        ASN1_ITYPE_PRIMITIVE, V_ASN1_INTEGER, NULL, 0, &bignum_pf, BN_SENSITIVE, "BIGNUM"
        ASN1_ITYPE_PRIMITIVE, V_ASN1_INTEGER, NULL, 0, &cbignum_pf, BN_SENSITIVE, "CBIGNUM"
ASN1_ITEM_end(CBIGNUM)

static int bn_new(ASN1_VALUE **pval, const ASN1_ITEM *it)
@@ -105,6 +117,15 @@ static int bn_new(ASN1_VALUE **pval, const ASN1_ITEM *it)
        return 0;
}

static int bn_secure_new(ASN1_VALUE **pval, const ASN1_ITEM *it)
{
    *pval = (ASN1_VALUE *)BN_secure_new();
    if (*pval)
        return 1;
    else
        return 0;
}

static void bn_free(ASN1_VALUE **pval, const ASN1_ITEM *it)
{
    if (!*pval)
@@ -141,6 +162,7 @@ static int bn_c2i(ASN1_VALUE **pval, const unsigned char *cont, int len,
                  int utype, char *free_cont, const ASN1_ITEM *it)
{
    BIGNUM *bn;

    if (!*pval)
        bn_new(pval, it);
    bn = (BIGNUM *)*pval;
@@ -150,3 +172,11 @@ static int bn_c2i(ASN1_VALUE **pval, const unsigned char *cont, int len,
    }
    return 1;
}

static int bn_secure_c2i(ASN1_VALUE **pval, const unsigned char *cont, int len,
                         int utype, char *free_cont, const ASN1_ITEM *it)
{
    if (!*pval)
        bn_secure_new(pval, it);
    return bn_c2i(pval, cont, len, utype, free_cont, it);
}
+32 −4
Original line number Diff line number Diff line
@@ -67,6 +67,7 @@ static int mem_puts(BIO *h, const char *str);
static int mem_gets(BIO *h, char *str, int size);
static long mem_ctrl(BIO *h, int cmd, long arg1, void *arg2);
static int mem_new(BIO *h);
static int secmem_new(BIO *h);
static int mem_free(BIO *data);
static BIO_METHOD mem_method = {
    BIO_TYPE_MEM,
@@ -80,6 +81,18 @@ static BIO_METHOD mem_method = {
    mem_free,
    NULL,
};
static BIO_METHOD secmem_method = {
    BIO_TYPE_MEM,
    "secure memory buffer",
    mem_write,
    mem_read,
    mem_puts,
    mem_gets,
    mem_ctrl,
    secmem_new,
    mem_free,
    NULL,
};

/*
 * bio->num is used to hold the value to return on 'empty', if it is 0,
@@ -91,6 +104,11 @@ BIO_METHOD *BIO_s_mem(void)
    return (&mem_method);
}

BIO_METHOD *BIO_s_secmem(void)
{
    return(&secmem_method);
}

BIO *BIO_new_mem_buf(void *buf, int len)
{
    BIO *ret;
@@ -114,11 +132,11 @@ BIO *BIO_new_mem_buf(void *buf, int len)
    return ret;
}

static int mem_new(BIO *bi)
static int mem_init(BIO *bi, unsigned long flags)
{
    BUF_MEM *b;

    if ((b = BUF_MEM_new()) == NULL)
    if ((b = BUF_MEM_new_ex(flags)) == NULL)
        return(0);
    bi->shutdown = 1;
    bi->init = 1;
@@ -127,6 +145,16 @@ static int mem_new(BIO *bi)
    return(1);
}

static int mem_new(BIO *bi)
{
    return (mem_init(bi, 0L));
}

static int secmem_new(BIO *bi)
{
    return (mem_init(bi, BUF_MEM_FLAG_SECURE));
}

static int mem_free(BIO *a)
{
    if (a == NULL)
+47 −32
Original line number Diff line number Diff line
@@ -103,7 +103,7 @@ typedef struct bignum_pool {
} BN_POOL;
static void BN_POOL_init(BN_POOL *);
static void BN_POOL_finish(BN_POOL *);
static BIGNUM *BN_POOL_get(BN_POOL *);
static BIGNUM *BN_POOL_get(BN_POOL *, int);
static void BN_POOL_release(BN_POOL *, unsigned int);

/************/
@@ -138,6 +138,8 @@ struct bignum_ctx {
    int err_stack;
    /* Block "gets" until an "end" (compatibility behaviour) */
    int too_many;
    /* Flags. */
    int flags;
};

/* Enable this to find BN_CTX bugs */
@@ -186,8 +188,9 @@ static void ctxdbg(BN_CTX *ctx)

BN_CTX *BN_CTX_new(void)
{
    BN_CTX *ret = OPENSSL_malloc(sizeof(*ret));
    if (!ret) {
    BN_CTX *ret;

    if ((ret = OPENSSL_malloc(sizeof(*ret))) == NULL) {
        BNerr(BN_F_BN_CTX_NEW, ERR_R_MALLOC_FAILURE);
        return NULL;
    }
@@ -197,6 +200,16 @@ BN_CTX *BN_CTX_new(void)
    ret->used = 0;
    ret->err_stack = 0;
    ret->too_many = 0;
    ret->flags = 0;
    return ret;
}

BN_CTX *BN_CTX_secure_new(void)
{
    BN_CTX *ret = BN_CTX_new();

    if (ret)
        ret->flags = BN_FLG_SECURE;
    return ret;
}

@@ -258,10 +271,11 @@ void BN_CTX_end(BN_CTX *ctx)
BIGNUM *BN_CTX_get(BN_CTX *ctx)
{
    BIGNUM *ret;

    CTXDBG_ENTRY("BN_CTX_get", ctx);
    if (ctx->err_stack || ctx->too_many)
        return NULL;
    if ((ret = BN_POOL_get(&ctx->pool)) == NULL) {
    if ((ret = BN_POOL_get(&ctx->pool, ctx->flags)) == NULL) {
        /*
         * Setting too_many prevents repeated "get" attempts from cluttering
         * the error stack.
@@ -289,25 +303,22 @@ static void BN_STACK_init(BN_STACK *st)

static void BN_STACK_finish(BN_STACK *st)
{
    if (st->size)
    OPENSSL_free(st->indexes);
    st->indexes = NULL;
}


static int BN_STACK_push(BN_STACK *st, unsigned int idx)
{
    if (st->depth == st->size)
    if (st->depth == st->size) {
        /* Need to expand */
    {
        unsigned int newsize = (st->size ?
                                (st->size * 3 / 2) : BN_CTX_START_FRAMES);
        unsigned int *newitems = OPENSSL_malloc(newsize *
                                                sizeof(unsigned int));
        if (!newitems)
        unsigned int newsize =
            st->size ? (st->size * 3 / 2) : BN_CTX_START_FRAMES;
        unsigned int *newitems = OPENSSL_malloc(sizeof(*newitems) * newsize);
        if (newitems == NULL)
            return 0;
        if (st->depth)
            memcpy(newitems, st->indexes, st->depth * sizeof(unsigned int));
        if (st->size)
            memcpy(newitems, st->indexes, sizeof(*newitems) * st->depth);
        OPENSSL_free(st->indexes);
        st->indexes = newitems;
        st->size = newsize;
@@ -333,14 +344,13 @@ static void BN_POOL_init(BN_POOL *p)

static void BN_POOL_finish(BN_POOL *p)
{
    unsigned int loop;
    BIGNUM *bn;

    while (p->head) {
        unsigned int loop = 0;
        BIGNUM *bn = p->head->vals;
        while (loop++ < BN_CTX_POOL_SIZE) {
        for (loop = 0, bn = p->head->vals; loop++ < BN_CTX_POOL_SIZE; bn++)
            if (bn->d)
                BN_clear_free(bn);
            bn++;
        }
        p->current = p->head->next;
        OPENSSL_free(p->head);
        p->head = p->current;
@@ -348,22 +358,25 @@ static void BN_POOL_finish(BN_POOL *p)
}


static BIGNUM *BN_POOL_get(BN_POOL *p)
static BIGNUM *BN_POOL_get(BN_POOL *p, int flag)
{
    if (p->used == p->size) {
    BIGNUM *bn;
        unsigned int loop = 0;
    unsigned int loop;

    /* Full; allocate a new pool item and link it in. */
    if (p->used == p->size) {
        BN_POOL_ITEM *item = OPENSSL_malloc(sizeof(*item));
        if (!item)
        if (item == NULL)
            return NULL;
        /* Initialise the structure */
        bn = item->vals;
        while (loop++ < BN_CTX_POOL_SIZE)
            BN_init(bn++);
        for (loop = 0, bn = item->vals; loop++ < BN_CTX_POOL_SIZE; bn++) {
            BN_init(bn);
            if ((flag & BN_FLG_SECURE) != 0)
                BN_set_flags(bn, BN_FLG_SECURE);
        }
        item->prev = p->tail;
        item->next = NULL;
        /* Link it in */
        if (!p->head)

        if (p->head == NULL)
            p->head = p->current = p->tail = item;
        else {
            p->tail->next = item;
@@ -375,6 +388,7 @@ static BIGNUM *BN_POOL_get(BN_POOL *p)
        /* Return the first bignum from the new pool */
        return item->vals;
    }

    if (!p->used)
        p->current = p->head;
    else if ((p->used % BN_CTX_POOL_SIZE) == 0)
@@ -385,10 +399,11 @@ static BIGNUM *BN_POOL_get(BN_POOL *p)
static void BN_POOL_release(BN_POOL *p, unsigned int num)
{
    unsigned int offset = (p->used - 1) % BN_CTX_POOL_SIZE;

    p->used -= num;
    while (num--) {
        bn_check_top(p->current->vals + offset);
        if (!offset) {
        if (offset == 0) {
            offset = BN_CTX_POOL_SIZE - 1;
            p->current = p->current->prev;
        } else
Loading