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: Richard Levitte <levitte@openssl.org>
This commit is contained in:
parent
ce7e647bc2
commit
74924dcb38
5
CHANGES
5
CHANGES
@ -126,6 +126,11 @@
|
|||||||
NULL. Remove the non-null checks from callers. Save much code.
|
NULL. Remove the non-null checks from callers. Save much code.
|
||||||
[Rich Salz]
|
[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,
|
*) Experimental support for a new, fast, unbiased prime candidate generator,
|
||||||
bn_probable_prime_dh_coprime(). Not currently used by any prime generator.
|
bn_probable_prime_dh_coprime(). Not currently used by any prime generator.
|
||||||
[Felix Laurie von Massenbach <felix@erbridge.co.uk>]
|
[Felix Laurie von Massenbach <felix@erbridge.co.uk>]
|
||||||
|
@ -36,10 +36,10 @@ LIB= $(TOP)/libcrypto.a
|
|||||||
SHARED_LIB= libcrypto$(SHLIB_EXT)
|
SHARED_LIB= libcrypto$(SHLIB_EXT)
|
||||||
LIBSRC= cryptlib.c mem.c mem_clr.c mem_dbg.c cversion.c ex_data.c cpt_err.c \
|
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 \
|
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 \
|
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 \
|
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)
|
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/opensslconf.h ../include/openssl/opensslv.h
|
||||||
o_time.o: ../include/openssl/ossl_typ.h ../include/openssl/safestack.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
|
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: ../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/crypto.h ../include/openssl/e_os2.h
|
||||||
thr_id.o: ../include/openssl/err.h ../include/openssl/lhash.h
|
thr_id.o: ../include/openssl/err.h ../include/openssl/lhash.h
|
||||||
|
@ -72,12 +72,15 @@
|
|||||||
#define BN_SENSITIVE 1
|
#define BN_SENSITIVE 1
|
||||||
|
|
||||||
static int bn_new(ASN1_VALUE **pval, const ASN1_ITEM *it);
|
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 void bn_free(ASN1_VALUE **pval, const ASN1_ITEM *it);
|
||||||
|
|
||||||
static int bn_i2c(ASN1_VALUE **pval, unsigned char *cont, int *putype,
|
static int bn_i2c(ASN1_VALUE **pval, unsigned char *cont, int *putype,
|
||||||
const ASN1_ITEM *it);
|
const ASN1_ITEM *it);
|
||||||
static int bn_c2i(ASN1_VALUE **pval, const unsigned char *cont, int len,
|
static int bn_c2i(ASN1_VALUE **pval, const unsigned char *cont, int len,
|
||||||
int utype, char *free_cont, const ASN1_ITEM *it);
|
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 = {
|
static ASN1_PRIMITIVE_FUNCS bignum_pf = {
|
||||||
NULL, 0,
|
NULL, 0,
|
||||||
@ -88,12 +91,21 @@ static ASN1_PRIMITIVE_FUNCS bignum_pf = {
|
|||||||
bn_i2c
|
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_ITEM_start(BIGNUM)
|
||||||
ASN1_ITYPE_PRIMITIVE, V_ASN1_INTEGER, NULL, 0, &bignum_pf, 0, "BIGNUM"
|
ASN1_ITYPE_PRIMITIVE, V_ASN1_INTEGER, NULL, 0, &bignum_pf, 0, "BIGNUM"
|
||||||
ASN1_ITEM_end(BIGNUM)
|
ASN1_ITEM_end(BIGNUM)
|
||||||
|
|
||||||
ASN1_ITEM_start(CBIGNUM)
|
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)
|
ASN1_ITEM_end(CBIGNUM)
|
||||||
|
|
||||||
static int bn_new(ASN1_VALUE **pval, const ASN1_ITEM *it)
|
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;
|
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)
|
static void bn_free(ASN1_VALUE **pval, const ASN1_ITEM *it)
|
||||||
{
|
{
|
||||||
if (!*pval)
|
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)
|
int utype, char *free_cont, const ASN1_ITEM *it)
|
||||||
{
|
{
|
||||||
BIGNUM *bn;
|
BIGNUM *bn;
|
||||||
|
|
||||||
if (!*pval)
|
if (!*pval)
|
||||||
bn_new(pval, it);
|
bn_new(pval, it);
|
||||||
bn = (BIGNUM *)*pval;
|
bn = (BIGNUM *)*pval;
|
||||||
@ -150,3 +172,11 @@ static int bn_c2i(ASN1_VALUE **pval, const unsigned char *cont, int len,
|
|||||||
}
|
}
|
||||||
return 1;
|
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);
|
||||||
|
}
|
||||||
|
@ -67,6 +67,7 @@ static int mem_puts(BIO *h, const char *str);
|
|||||||
static int mem_gets(BIO *h, char *str, int size);
|
static int mem_gets(BIO *h, char *str, int size);
|
||||||
static long mem_ctrl(BIO *h, int cmd, long arg1, void *arg2);
|
static long mem_ctrl(BIO *h, int cmd, long arg1, void *arg2);
|
||||||
static int mem_new(BIO *h);
|
static int mem_new(BIO *h);
|
||||||
|
static int secmem_new(BIO *h);
|
||||||
static int mem_free(BIO *data);
|
static int mem_free(BIO *data);
|
||||||
static BIO_METHOD mem_method = {
|
static BIO_METHOD mem_method = {
|
||||||
BIO_TYPE_MEM,
|
BIO_TYPE_MEM,
|
||||||
@ -80,6 +81,18 @@ static BIO_METHOD mem_method = {
|
|||||||
mem_free,
|
mem_free,
|
||||||
NULL,
|
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,
|
* 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);
|
return (&mem_method);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
BIO_METHOD *BIO_s_secmem(void)
|
||||||
|
{
|
||||||
|
return(&secmem_method);
|
||||||
|
}
|
||||||
|
|
||||||
BIO *BIO_new_mem_buf(void *buf, int len)
|
BIO *BIO_new_mem_buf(void *buf, int len)
|
||||||
{
|
{
|
||||||
BIO *ret;
|
BIO *ret;
|
||||||
@ -114,17 +132,27 @@ BIO *BIO_new_mem_buf(void *buf, int len)
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int mem_new(BIO *bi)
|
static int mem_init(BIO *bi, unsigned long flags)
|
||||||
{
|
{
|
||||||
BUF_MEM *b;
|
BUF_MEM *b;
|
||||||
|
|
||||||
if ((b = BUF_MEM_new()) == NULL)
|
if ((b = BUF_MEM_new_ex(flags)) == NULL)
|
||||||
return (0);
|
return(0);
|
||||||
bi->shutdown = 1;
|
bi->shutdown = 1;
|
||||||
bi->init = 1;
|
bi->init = 1;
|
||||||
bi->num = -1;
|
bi->num = -1;
|
||||||
bi->ptr = (char *)b;
|
bi->ptr = (char *)b;
|
||||||
return (1);
|
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)
|
static int mem_free(BIO *a)
|
||||||
|
@ -103,7 +103,7 @@ typedef struct bignum_pool {
|
|||||||
} BN_POOL;
|
} BN_POOL;
|
||||||
static void BN_POOL_init(BN_POOL *);
|
static void BN_POOL_init(BN_POOL *);
|
||||||
static void BN_POOL_finish(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);
|
static void BN_POOL_release(BN_POOL *, unsigned int);
|
||||||
|
|
||||||
/************/
|
/************/
|
||||||
@ -138,6 +138,8 @@ struct bignum_ctx {
|
|||||||
int err_stack;
|
int err_stack;
|
||||||
/* Block "gets" until an "end" (compatibility behaviour) */
|
/* Block "gets" until an "end" (compatibility behaviour) */
|
||||||
int too_many;
|
int too_many;
|
||||||
|
/* Flags. */
|
||||||
|
int flags;
|
||||||
};
|
};
|
||||||
|
|
||||||
/* Enable this to find BN_CTX bugs */
|
/* 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 *BN_CTX_new(void)
|
||||||
{
|
{
|
||||||
BN_CTX *ret = OPENSSL_malloc(sizeof(*ret));
|
BN_CTX *ret;
|
||||||
if (!ret) {
|
|
||||||
|
if ((ret = OPENSSL_malloc(sizeof(*ret))) == NULL) {
|
||||||
BNerr(BN_F_BN_CTX_NEW, ERR_R_MALLOC_FAILURE);
|
BNerr(BN_F_BN_CTX_NEW, ERR_R_MALLOC_FAILURE);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
@ -197,6 +200,16 @@ BN_CTX *BN_CTX_new(void)
|
|||||||
ret->used = 0;
|
ret->used = 0;
|
||||||
ret->err_stack = 0;
|
ret->err_stack = 0;
|
||||||
ret->too_many = 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;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -258,10 +271,11 @@ void BN_CTX_end(BN_CTX *ctx)
|
|||||||
BIGNUM *BN_CTX_get(BN_CTX *ctx)
|
BIGNUM *BN_CTX_get(BN_CTX *ctx)
|
||||||
{
|
{
|
||||||
BIGNUM *ret;
|
BIGNUM *ret;
|
||||||
|
|
||||||
CTXDBG_ENTRY("BN_CTX_get", ctx);
|
CTXDBG_ENTRY("BN_CTX_get", ctx);
|
||||||
if (ctx->err_stack || ctx->too_many)
|
if (ctx->err_stack || ctx->too_many)
|
||||||
return NULL;
|
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
|
* Setting too_many prevents repeated "get" attempts from cluttering
|
||||||
* the error stack.
|
* the error stack.
|
||||||
@ -289,26 +303,23 @@ static void BN_STACK_init(BN_STACK *st)
|
|||||||
|
|
||||||
static void BN_STACK_finish(BN_STACK *st)
|
static void BN_STACK_finish(BN_STACK *st)
|
||||||
{
|
{
|
||||||
if (st->size)
|
OPENSSL_free(st->indexes);
|
||||||
OPENSSL_free(st->indexes);
|
st->indexes = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static int BN_STACK_push(BN_STACK *st, unsigned int idx)
|
static int BN_STACK_push(BN_STACK *st, unsigned int idx)
|
||||||
{
|
{
|
||||||
if (st->depth == st->size)
|
if (st->depth == st->size) {
|
||||||
/* Need to expand */
|
/* Need to expand */
|
||||||
{
|
unsigned int newsize =
|
||||||
unsigned int newsize = (st->size ?
|
st->size ? (st->size * 3 / 2) : BN_CTX_START_FRAMES;
|
||||||
(st->size * 3 / 2) : BN_CTX_START_FRAMES);
|
unsigned int *newitems = OPENSSL_malloc(sizeof(*newitems) * newsize);
|
||||||
unsigned int *newitems = OPENSSL_malloc(newsize *
|
if (newitems == NULL)
|
||||||
sizeof(unsigned int));
|
|
||||||
if (!newitems)
|
|
||||||
return 0;
|
return 0;
|
||||||
if (st->depth)
|
if (st->depth)
|
||||||
memcpy(newitems, st->indexes, st->depth * sizeof(unsigned int));
|
memcpy(newitems, st->indexes, sizeof(*newitems) * st->depth);
|
||||||
if (st->size)
|
OPENSSL_free(st->indexes);
|
||||||
OPENSSL_free(st->indexes);
|
|
||||||
st->indexes = newitems;
|
st->indexes = newitems;
|
||||||
st->size = newsize;
|
st->size = newsize;
|
||||||
}
|
}
|
||||||
@ -333,14 +344,13 @@ static void BN_POOL_init(BN_POOL *p)
|
|||||||
|
|
||||||
static void BN_POOL_finish(BN_POOL *p)
|
static void BN_POOL_finish(BN_POOL *p)
|
||||||
{
|
{
|
||||||
|
unsigned int loop;
|
||||||
|
BIGNUM *bn;
|
||||||
|
|
||||||
while (p->head) {
|
while (p->head) {
|
||||||
unsigned int loop = 0;
|
for (loop = 0, bn = p->head->vals; loop++ < BN_CTX_POOL_SIZE; bn++)
|
||||||
BIGNUM *bn = p->head->vals;
|
|
||||||
while (loop++ < BN_CTX_POOL_SIZE) {
|
|
||||||
if (bn->d)
|
if (bn->d)
|
||||||
BN_clear_free(bn);
|
BN_clear_free(bn);
|
||||||
bn++;
|
|
||||||
}
|
|
||||||
p->current = p->head->next;
|
p->current = p->head->next;
|
||||||
OPENSSL_free(p->head);
|
OPENSSL_free(p->head);
|
||||||
p->head = p->current;
|
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)
|
||||||
{
|
{
|
||||||
|
BIGNUM *bn;
|
||||||
|
unsigned int loop;
|
||||||
|
|
||||||
|
/* Full; allocate a new pool item and link it in. */
|
||||||
if (p->used == p->size) {
|
if (p->used == p->size) {
|
||||||
BIGNUM *bn;
|
|
||||||
unsigned int loop = 0;
|
|
||||||
BN_POOL_ITEM *item = OPENSSL_malloc(sizeof(*item));
|
BN_POOL_ITEM *item = OPENSSL_malloc(sizeof(*item));
|
||||||
if (!item)
|
if (item == NULL)
|
||||||
return NULL;
|
return NULL;
|
||||||
/* Initialise the structure */
|
for (loop = 0, bn = item->vals; loop++ < BN_CTX_POOL_SIZE; bn++) {
|
||||||
bn = item->vals;
|
BN_init(bn);
|
||||||
while (loop++ < BN_CTX_POOL_SIZE)
|
if ((flag & BN_FLG_SECURE) != 0)
|
||||||
BN_init(bn++);
|
BN_set_flags(bn, BN_FLG_SECURE);
|
||||||
|
}
|
||||||
item->prev = p->tail;
|
item->prev = p->tail;
|
||||||
item->next = NULL;
|
item->next = NULL;
|
||||||
/* Link it in */
|
|
||||||
if (!p->head)
|
if (p->head == NULL)
|
||||||
p->head = p->current = p->tail = item;
|
p->head = p->current = p->tail = item;
|
||||||
else {
|
else {
|
||||||
p->tail->next = item;
|
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 the first bignum from the new pool */
|
||||||
return item->vals;
|
return item->vals;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!p->used)
|
if (!p->used)
|
||||||
p->current = p->head;
|
p->current = p->head;
|
||||||
else if ((p->used % BN_CTX_POOL_SIZE) == 0)
|
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)
|
static void BN_POOL_release(BN_POOL *p, unsigned int num)
|
||||||
{
|
{
|
||||||
unsigned int offset = (p->used - 1) % BN_CTX_POOL_SIZE;
|
unsigned int offset = (p->used - 1) % BN_CTX_POOL_SIZE;
|
||||||
|
|
||||||
p->used -= num;
|
p->used -= num;
|
||||||
while (num--) {
|
while (num--) {
|
||||||
bn_check_top(p->current->vals + offset);
|
bn_check_top(p->current->vals + offset);
|
||||||
if (!offset) {
|
if (offset == 0) {
|
||||||
offset = BN_CTX_POOL_SIZE - 1;
|
offset = BN_CTX_POOL_SIZE - 1;
|
||||||
p->current = p->current->prev;
|
p->current = p->current->prev;
|
||||||
} else
|
} else
|
||||||
|
@ -232,8 +232,12 @@ void BN_clear_free(BIGNUM *a)
|
|||||||
bn_check_top(a);
|
bn_check_top(a);
|
||||||
if (a->d != NULL) {
|
if (a->d != NULL) {
|
||||||
OPENSSL_cleanse(a->d, a->dmax * sizeof(a->d[0]));
|
OPENSSL_cleanse(a->d, a->dmax * sizeof(a->d[0]));
|
||||||
if (!(BN_get_flags(a, BN_FLG_STATIC_DATA)))
|
if (!(BN_get_flags(a, BN_FLG_STATIC_DATA))) {
|
||||||
OPENSSL_free(a->d);
|
if (BN_get_flags(a,BN_FLG_SECURE))
|
||||||
|
OPENSSL_secure_free(a->d);
|
||||||
|
else
|
||||||
|
OPENSSL_free(a->d);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
i = BN_get_flags(a, BN_FLG_MALLOCED);
|
i = BN_get_flags(a, BN_FLG_MALLOCED);
|
||||||
OPENSSL_cleanse(a, sizeof(BIGNUM));
|
OPENSSL_cleanse(a, sizeof(BIGNUM));
|
||||||
@ -247,7 +251,12 @@ void BN_free(BIGNUM *a)
|
|||||||
return;
|
return;
|
||||||
bn_check_top(a);
|
bn_check_top(a);
|
||||||
if (!BN_get_flags(a, BN_FLG_STATIC_DATA))
|
if (!BN_get_flags(a, BN_FLG_STATIC_DATA))
|
||||||
OPENSSL_free(a->d);
|
if ((a->d != NULL) && !(BN_get_flags(a, BN_FLG_STATIC_DATA))) {
|
||||||
|
if (BN_get_flags(a, BN_FLG_SECURE))
|
||||||
|
OPENSSL_secure_free(a->d);
|
||||||
|
else
|
||||||
|
OPENSSL_free(a->d);
|
||||||
|
}
|
||||||
if (a->flags & BN_FLG_MALLOCED)
|
if (a->flags & BN_FLG_MALLOCED)
|
||||||
OPENSSL_free(a);
|
OPENSSL_free(a);
|
||||||
else {
|
else {
|
||||||
@ -281,6 +290,14 @@ BIGNUM *BN_new(void)
|
|||||||
return (ret);
|
return (ret);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
BIGNUM *BN_secure_new(void)
|
||||||
|
{
|
||||||
|
BIGNUM *ret = BN_new();
|
||||||
|
if (ret)
|
||||||
|
ret->flags |= BN_FLG_SECURE;
|
||||||
|
return (ret);
|
||||||
|
}
|
||||||
|
|
||||||
/* This is used both by bn_expand2() and bn_dup_expand() */
|
/* This is used both by bn_expand2() and bn_dup_expand() */
|
||||||
/* The caller MUST check that words > b->dmax before calling this */
|
/* The caller MUST check that words > b->dmax before calling this */
|
||||||
static BN_ULONG *bn_expand_internal(const BIGNUM *b, int words)
|
static BN_ULONG *bn_expand_internal(const BIGNUM *b, int words)
|
||||||
@ -299,7 +316,10 @@ static BN_ULONG *bn_expand_internal(const BIGNUM *b, int words)
|
|||||||
BNerr(BN_F_BN_EXPAND_INTERNAL, BN_R_EXPAND_ON_STATIC_BIGNUM_DATA);
|
BNerr(BN_F_BN_EXPAND_INTERNAL, BN_R_EXPAND_ON_STATIC_BIGNUM_DATA);
|
||||||
return (NULL);
|
return (NULL);
|
||||||
}
|
}
|
||||||
a = A = OPENSSL_malloc(sizeof(*a) * words);
|
if (BN_get_flags(b,BN_FLG_SECURE))
|
||||||
|
a = A = OPENSSL_secure_malloc(words * sizeof(*a));
|
||||||
|
else
|
||||||
|
a = A = OPENSSL_malloc(words * sizeof(*a));
|
||||||
if (A == NULL) {
|
if (A == NULL) {
|
||||||
BNerr(BN_F_BN_EXPAND_INTERNAL, ERR_R_MALLOC_FAILURE);
|
BNerr(BN_F_BN_EXPAND_INTERNAL, ERR_R_MALLOC_FAILURE);
|
||||||
return (NULL);
|
return (NULL);
|
||||||
@ -378,7 +398,12 @@ BIGNUM *bn_expand2(BIGNUM *b, int words)
|
|||||||
BN_ULONG *a = bn_expand_internal(b, words);
|
BN_ULONG *a = bn_expand_internal(b, words);
|
||||||
if (!a)
|
if (!a)
|
||||||
return NULL;
|
return NULL;
|
||||||
OPENSSL_free(b->d);
|
if (b->d) {
|
||||||
|
if (BN_get_flags(b,BN_FLG_SECURE))
|
||||||
|
OPENSSL_secure_free(b->d);
|
||||||
|
else
|
||||||
|
OPENSSL_free(b->d);
|
||||||
|
}
|
||||||
b->d = a;
|
b->d = a;
|
||||||
b->dmax = words;
|
b->dmax = words;
|
||||||
}
|
}
|
||||||
@ -395,7 +420,7 @@ BIGNUM *BN_dup(const BIGNUM *a)
|
|||||||
return NULL;
|
return NULL;
|
||||||
bn_check_top(a);
|
bn_check_top(a);
|
||||||
|
|
||||||
t = BN_new();
|
t = BN_get_flags(a, BN_FLG_SECURE) ? BN_secure_new() : BN_new();
|
||||||
if (t == NULL)
|
if (t == NULL)
|
||||||
return NULL;
|
return NULL;
|
||||||
if (!BN_copy(t, a)) {
|
if (!BN_copy(t, a)) {
|
||||||
|
@ -67,6 +67,16 @@
|
|||||||
*/
|
*/
|
||||||
#define LIMIT_BEFORE_EXPANSION 0x5ffffffc
|
#define LIMIT_BEFORE_EXPANSION 0x5ffffffc
|
||||||
|
|
||||||
|
BUF_MEM *BUF_MEM_new_ex(unsigned long flags)
|
||||||
|
{
|
||||||
|
BUF_MEM *ret;
|
||||||
|
|
||||||
|
ret = BUF_MEM_new();
|
||||||
|
if (ret != NULL)
|
||||||
|
ret->flags = flags;
|
||||||
|
return (ret);
|
||||||
|
}
|
||||||
|
|
||||||
BUF_MEM *BUF_MEM_new(void)
|
BUF_MEM *BUF_MEM_new(void)
|
||||||
{
|
{
|
||||||
BUF_MEM *ret;
|
BUF_MEM *ret;
|
||||||
@ -76,6 +86,7 @@ BUF_MEM *BUF_MEM_new(void)
|
|||||||
BUFerr(BUF_F_BUF_MEM_NEW, ERR_R_MALLOC_FAILURE);
|
BUFerr(BUF_F_BUF_MEM_NEW, ERR_R_MALLOC_FAILURE);
|
||||||
return (NULL);
|
return (NULL);
|
||||||
}
|
}
|
||||||
|
ret->flags = 0;
|
||||||
ret->length = 0;
|
ret->length = 0;
|
||||||
ret->max = 0;
|
ret->max = 0;
|
||||||
ret->data = NULL;
|
ret->data = NULL;
|
||||||
@ -88,11 +99,30 @@ void BUF_MEM_free(BUF_MEM *a)
|
|||||||
return;
|
return;
|
||||||
|
|
||||||
if (a->data != NULL) {
|
if (a->data != NULL) {
|
||||||
OPENSSL_clear_free(a->data, a->max);
|
memset(a->data, 0, (unsigned int)a->max);
|
||||||
|
if (a->flags & BUF_MEM_FLAG_SECURE)
|
||||||
|
OPENSSL_secure_free(a->data);
|
||||||
|
else
|
||||||
|
OPENSSL_clear_free(a->data, a->max);
|
||||||
}
|
}
|
||||||
OPENSSL_free(a);
|
OPENSSL_free(a);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Allocate a block of secure memory; copy over old data if there
|
||||||
|
* was any, and then free it. */
|
||||||
|
static char *sec_alloc_realloc(BUF_MEM *str, size_t len)
|
||||||
|
{
|
||||||
|
char *ret;
|
||||||
|
|
||||||
|
ret = OPENSSL_secure_malloc(len);
|
||||||
|
if (str->data != NULL) {
|
||||||
|
if (ret != NULL)
|
||||||
|
memcpy(ret, str->data, str->length);
|
||||||
|
OPENSSL_secure_free(str->data);
|
||||||
|
}
|
||||||
|
return (ret);
|
||||||
|
}
|
||||||
|
|
||||||
size_t BUF_MEM_grow(BUF_MEM *str, size_t len)
|
size_t BUF_MEM_grow(BUF_MEM *str, size_t len)
|
||||||
{
|
{
|
||||||
char *ret;
|
char *ret;
|
||||||
@ -113,7 +143,10 @@ size_t BUF_MEM_grow(BUF_MEM *str, size_t len)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
n = (len + 3) / 3 * 4;
|
n = (len + 3) / 3 * 4;
|
||||||
ret = OPENSSL_realloc(str->data, n);
|
if ((str->flags & BUF_MEM_FLAG_SECURE))
|
||||||
|
ret = sec_alloc_realloc(str, n);
|
||||||
|
else
|
||||||
|
ret = OPENSSL_realloc(str->data, n);
|
||||||
if (ret == NULL) {
|
if (ret == NULL) {
|
||||||
BUFerr(BUF_F_BUF_MEM_GROW, ERR_R_MALLOC_FAILURE);
|
BUFerr(BUF_F_BUF_MEM_GROW, ERR_R_MALLOC_FAILURE);
|
||||||
len = 0;
|
len = 0;
|
||||||
@ -147,7 +180,10 @@ size_t BUF_MEM_grow_clean(BUF_MEM *str, size_t len)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
n = (len + 3) / 3 * 4;
|
n = (len + 3) / 3 * 4;
|
||||||
ret = OPENSSL_realloc_clean(str->data, str->max, n);
|
if ((str->flags & BUF_MEM_FLAG_SECURE))
|
||||||
|
ret = sec_alloc_realloc(str, n);
|
||||||
|
else
|
||||||
|
ret = OPENSSL_realloc_clean(str->data, str->max, n);
|
||||||
if (ret == NULL) {
|
if (ret == NULL) {
|
||||||
BUFerr(BUF_F_BUF_MEM_GROW_CLEAN, ERR_R_MALLOC_FAILURE);
|
BUFerr(BUF_F_BUF_MEM_GROW_CLEAN, ERR_R_MALLOC_FAILURE);
|
||||||
len = 0;
|
len = 0;
|
||||||
|
@ -228,7 +228,8 @@ static int dh_priv_decode(EVP_PKEY *pkey, PKCS8_PRIV_KEY_INFO *p8)
|
|||||||
goto decerr;
|
goto decerr;
|
||||||
|
|
||||||
/* We have parameters now set private key */
|
/* We have parameters now set private key */
|
||||||
if ((dh->priv_key = ASN1_INTEGER_to_BN(privkey, NULL)) == NULL) {
|
if ((dh->priv_key = BN_secure_new()) == NULL
|
||||||
|
|| !ASN1_INTEGER_to_BN(privkey, dh->priv_key)) {
|
||||||
DHerr(DH_F_DH_PRIV_DECODE, DH_R_BN_ERROR);
|
DHerr(DH_F_DH_PRIV_DECODE, DH_R_BN_ERROR);
|
||||||
goto dherr;
|
goto dherr;
|
||||||
}
|
}
|
||||||
|
@ -125,7 +125,7 @@ static int generate_key(DH *dh)
|
|||||||
goto err;
|
goto err;
|
||||||
|
|
||||||
if (dh->priv_key == NULL) {
|
if (dh->priv_key == NULL) {
|
||||||
priv_key = BN_new();
|
priv_key = BN_secure_new();
|
||||||
if (priv_key == NULL)
|
if (priv_key == NULL)
|
||||||
goto err;
|
goto err;
|
||||||
generate_new_key = 1;
|
generate_new_key = 1;
|
||||||
|
@ -245,7 +245,8 @@ static int dsa_priv_decode(EVP_PKEY *pkey, PKCS8_PRIV_KEY_INFO *p8)
|
|||||||
if ((dsa = d2i_DSAparams(NULL, &pm, pmlen)) == NULL)
|
if ((dsa = d2i_DSAparams(NULL, &pm, pmlen)) == NULL)
|
||||||
goto decerr;
|
goto decerr;
|
||||||
/* We have parameters now set private key */
|
/* We have parameters now set private key */
|
||||||
if ((dsa->priv_key = ASN1_INTEGER_to_BN(privkey, NULL)) == NULL) {
|
if ((dsa->priv_key = BN_secure_new()) == NULL
|
||||||
|
|| !ASN1_INTEGER_to_BN(privkey, dsa->priv_key)) {
|
||||||
DSAerr(DSA_F_DSA_PRIV_DECODE, DSA_R_BN_ERROR);
|
DSAerr(DSA_F_DSA_PRIV_DECODE, DSA_R_BN_ERROR);
|
||||||
goto dsaerr;
|
goto dsaerr;
|
||||||
}
|
}
|
||||||
|
@ -113,7 +113,7 @@ ASN1_SEQUENCE_cb(DSAPrivateKey, dsa_cb) = {
|
|||||||
ASN1_SIMPLE(DSA, q, BIGNUM),
|
ASN1_SIMPLE(DSA, q, BIGNUM),
|
||||||
ASN1_SIMPLE(DSA, g, BIGNUM),
|
ASN1_SIMPLE(DSA, g, BIGNUM),
|
||||||
ASN1_SIMPLE(DSA, pub_key, BIGNUM),
|
ASN1_SIMPLE(DSA, pub_key, BIGNUM),
|
||||||
ASN1_SIMPLE(DSA, priv_key, BIGNUM)
|
ASN1_SIMPLE(DSA, priv_key, CBIGNUM)
|
||||||
} ASN1_SEQUENCE_END_cb(DSA, DSAPrivateKey)
|
} ASN1_SEQUENCE_END_cb(DSA, DSAPrivateKey)
|
||||||
|
|
||||||
IMPLEMENT_ASN1_ENCODE_FUNCTIONS_const_fname(DSA, DSAPrivateKey, DSAPrivateKey)
|
IMPLEMENT_ASN1_ENCODE_FUNCTIONS_const_fname(DSA, DSAPrivateKey, DSAPrivateKey)
|
||||||
|
@ -82,7 +82,7 @@ static int dsa_builtin_keygen(DSA *dsa)
|
|||||||
goto err;
|
goto err;
|
||||||
|
|
||||||
if (dsa->priv_key == NULL) {
|
if (dsa->priv_key == NULL) {
|
||||||
if ((priv_key = BN_new()) == NULL)
|
if ((priv_key = BN_secure_new()) == NULL)
|
||||||
goto err;
|
goto err;
|
||||||
} else
|
} else
|
||||||
priv_key = dsa->priv_key;
|
priv_key = dsa->priv_key;
|
||||||
|
@ -1023,6 +1023,8 @@ EC_KEY *d2i_ECPrivateKey(EC_KEY **a, const unsigned char **in, long len)
|
|||||||
ret->version = priv_key->version;
|
ret->version = priv_key->version;
|
||||||
|
|
||||||
if (priv_key->privateKey) {
|
if (priv_key->privateKey) {
|
||||||
|
if (ret->priv_key == NULL)
|
||||||
|
ret->priv_key = BN_secure_new();
|
||||||
ret->priv_key = BN_bin2bn(ASN1_STRING_data(priv_key->privateKey),
|
ret->priv_key = BN_bin2bn(ASN1_STRING_data(priv_key->privateKey),
|
||||||
ASN1_STRING_length(priv_key->privateKey),
|
ASN1_STRING_length(priv_key->privateKey),
|
||||||
ret->priv_key);
|
ret->priv_key);
|
||||||
|
73
crypto/mem.c
73
crypto/mem.c
@ -94,6 +94,15 @@ static void *(*realloc_ex_func) (void *, size_t, const char *file, int line)
|
|||||||
|
|
||||||
static void (*free_func) (void *) = free;
|
static void (*free_func) (void *) = free;
|
||||||
|
|
||||||
|
static void *(*malloc_secure_func)(size_t) = malloc;
|
||||||
|
static void *default_malloc_secure_ex(size_t num, const char *file, int line)
|
||||||
|
{
|
||||||
|
return malloc_secure_func(num);
|
||||||
|
}
|
||||||
|
static void *(*malloc_secure_ex_func)(size_t, const char *file, int line)
|
||||||
|
= default_malloc_secure_ex;
|
||||||
|
static void (*free_secure_func)(void *) = free;
|
||||||
|
|
||||||
static void *(*malloc_locked_func) (size_t) = malloc;
|
static void *(*malloc_locked_func) (size_t) = malloc;
|
||||||
static void *default_malloc_locked_ex(size_t num, const char *file, int line)
|
static void *default_malloc_locked_ex(size_t num, const char *file, int line)
|
||||||
{
|
{
|
||||||
@ -145,6 +154,11 @@ int CRYPTO_set_mem_functions(void *(*m) (size_t), void *(*r) (void *, size_t),
|
|||||||
realloc_func = r;
|
realloc_func = r;
|
||||||
realloc_ex_func = default_realloc_ex;
|
realloc_ex_func = default_realloc_ex;
|
||||||
free_func = f;
|
free_func = f;
|
||||||
|
/* If user wants to intercept the secure or locked functions, do it
|
||||||
|
* after the basic functions. */
|
||||||
|
malloc_secure_func = m;
|
||||||
|
malloc_secure_ex_func = default_malloc_secure_ex;
|
||||||
|
free_secure_func = f;
|
||||||
malloc_locked_func = m;
|
malloc_locked_func = m;
|
||||||
malloc_locked_ex_func = default_malloc_locked_ex;
|
malloc_locked_ex_func = default_malloc_locked_ex;
|
||||||
free_locked_func = f;
|
free_locked_func = f;
|
||||||
@ -164,6 +178,44 @@ int CRYPTO_set_mem_ex_functions(void *(*m) (size_t, const char *, int),
|
|||||||
realloc_func = 0;
|
realloc_func = 0;
|
||||||
realloc_ex_func = r;
|
realloc_ex_func = r;
|
||||||
free_func = f;
|
free_func = f;
|
||||||
|
malloc_secure_func = 0;
|
||||||
|
malloc_secure_ex_func = m;
|
||||||
|
free_secure_func = f;
|
||||||
|
malloc_locked_func = 0;
|
||||||
|
malloc_locked_ex_func = m;
|
||||||
|
free_locked_func = f;
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
int CRYPTO_set_secure_mem_functions(void *(*m)(size_t), void (*f)(void *))
|
||||||
|
{
|
||||||
|
/* Dummy call just to ensure OPENSSL_init() gets linked in */
|
||||||
|
OPENSSL_init();
|
||||||
|
if (!allow_customize)
|
||||||
|
return 0;
|
||||||
|
if ((m == 0) || (f == 0))
|
||||||
|
return 0;
|
||||||
|
malloc_secure_func = m;
|
||||||
|
malloc_secure_ex_func = default_malloc_secure_ex;
|
||||||
|
free_secure_func = f;
|
||||||
|
/* If user wants to intercept the locked functions, do it after
|
||||||
|
* the secure functions. */
|
||||||
|
malloc_locked_func = m;
|
||||||
|
malloc_locked_ex_func = default_malloc_secure_ex;
|
||||||
|
free_locked_func = f;
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
int CRYPTO_set_secure_mem_ex_functions(void *(*m)(size_t, const char *, int),
|
||||||
|
void (*f)(void *))
|
||||||
|
{
|
||||||
|
if (!allow_customize)
|
||||||
|
return 0;
|
||||||
|
if ((m == NULL) || (f == NULL))
|
||||||
|
return 0;
|
||||||
|
malloc_secure_func = 0;
|
||||||
|
malloc_secure_ex_func = m;
|
||||||
|
free_secure_func = f;
|
||||||
malloc_locked_func = 0;
|
malloc_locked_func = 0;
|
||||||
malloc_locked_ex_func = m;
|
malloc_locked_ex_func = m;
|
||||||
free_locked_func = f;
|
free_locked_func = f;
|
||||||
@ -191,7 +243,7 @@ int CRYPTO_set_locked_mem_ex_functions(void *(*m) (size_t, const char *, int),
|
|||||||
return 0;
|
return 0;
|
||||||
malloc_locked_func = 0;
|
malloc_locked_func = 0;
|
||||||
malloc_locked_ex_func = m;
|
malloc_locked_ex_func = m;
|
||||||
free_func = f;
|
free_locked_func = f;
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -236,6 +288,25 @@ void CRYPTO_get_mem_ex_functions(void *(**m) (size_t, const char *, int),
|
|||||||
*f = free_func;
|
*f = free_func;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void CRYPTO_get_secure_mem_functions(void *(**m)(size_t), void (**f)(void *))
|
||||||
|
{
|
||||||
|
if (m != NULL)
|
||||||
|
*m = (malloc_secure_ex_func == default_malloc_secure_ex) ?
|
||||||
|
malloc_secure_func : 0;
|
||||||
|
if (f != NULL)
|
||||||
|
*f=free_secure_func;
|
||||||
|
}
|
||||||
|
|
||||||
|
void CRYPTO_get_secure_mem_ex_functions(void *(**m)(size_t,const char *,int),
|
||||||
|
void (**f)(void *))
|
||||||
|
{
|
||||||
|
if (m != NULL)
|
||||||
|
*m = (malloc_secure_ex_func != default_malloc_secure_ex) ?
|
||||||
|
malloc_secure_ex_func : 0;
|
||||||
|
if (f != NULL)
|
||||||
|
*f=free_secure_func;
|
||||||
|
}
|
||||||
|
|
||||||
void CRYPTO_get_locked_mem_functions(void *(**m) (size_t),
|
void CRYPTO_get_locked_mem_functions(void *(**m) (size_t),
|
||||||
void (**f) (void *))
|
void (**f) (void *))
|
||||||
{
|
{
|
||||||
|
@ -85,12 +85,12 @@ ASN1_SEQUENCE_cb(RSAPrivateKey, rsa_cb) = {
|
|||||||
ASN1_SIMPLE(RSA, version, LONG),
|
ASN1_SIMPLE(RSA, version, LONG),
|
||||||
ASN1_SIMPLE(RSA, n, BIGNUM),
|
ASN1_SIMPLE(RSA, n, BIGNUM),
|
||||||
ASN1_SIMPLE(RSA, e, BIGNUM),
|
ASN1_SIMPLE(RSA, e, BIGNUM),
|
||||||
ASN1_SIMPLE(RSA, d, BIGNUM),
|
ASN1_SIMPLE(RSA, d, CBIGNUM),
|
||||||
ASN1_SIMPLE(RSA, p, BIGNUM),
|
ASN1_SIMPLE(RSA, p, CBIGNUM),
|
||||||
ASN1_SIMPLE(RSA, q, BIGNUM),
|
ASN1_SIMPLE(RSA, q, CBIGNUM),
|
||||||
ASN1_SIMPLE(RSA, dmp1, BIGNUM),
|
ASN1_SIMPLE(RSA, dmp1, CBIGNUM),
|
||||||
ASN1_SIMPLE(RSA, dmq1, BIGNUM),
|
ASN1_SIMPLE(RSA, dmq1, CBIGNUM),
|
||||||
ASN1_SIMPLE(RSA, iqmp, BIGNUM)
|
ASN1_SIMPLE(RSA, iqmp, CBIGNUM)
|
||||||
} ASN1_SEQUENCE_END_cb(RSA, RSAPrivateKey)
|
} ASN1_SEQUENCE_END_cb(RSA, RSAPrivateKey)
|
||||||
|
|
||||||
|
|
||||||
|
@ -117,19 +117,19 @@ static int rsa_builtin_keygen(RSA *rsa, int bits, BIGNUM *e_value,
|
|||||||
/* We need the RSA components non-NULL */
|
/* We need the RSA components non-NULL */
|
||||||
if (!rsa->n && ((rsa->n = BN_new()) == NULL))
|
if (!rsa->n && ((rsa->n = BN_new()) == NULL))
|
||||||
goto err;
|
goto err;
|
||||||
if (!rsa->d && ((rsa->d = BN_new()) == NULL))
|
if (!rsa->d && ((rsa->d = BN_secure_new()) == NULL))
|
||||||
goto err;
|
goto err;
|
||||||
if (!rsa->e && ((rsa->e = BN_new()) == NULL))
|
if (!rsa->e && ((rsa->e = BN_new()) == NULL))
|
||||||
goto err;
|
goto err;
|
||||||
if (!rsa->p && ((rsa->p = BN_new()) == NULL))
|
if (!rsa->p && ((rsa->p = BN_secure_new()) == NULL))
|
||||||
goto err;
|
goto err;
|
||||||
if (!rsa->q && ((rsa->q = BN_new()) == NULL))
|
if (!rsa->q && ((rsa->q = BN_secure_new()) == NULL))
|
||||||
goto err;
|
goto err;
|
||||||
if (!rsa->dmp1 && ((rsa->dmp1 = BN_new()) == NULL))
|
if (!rsa->dmp1 && ((rsa->dmp1 = BN_secure_new()) == NULL))
|
||||||
goto err;
|
goto err;
|
||||||
if (!rsa->dmq1 && ((rsa->dmq1 = BN_new()) == NULL))
|
if (!rsa->dmq1 && ((rsa->dmq1 = BN_secure_new()) == NULL))
|
||||||
goto err;
|
goto err;
|
||||||
if (!rsa->iqmp && ((rsa->iqmp = BN_new()) == NULL))
|
if (!rsa->iqmp && ((rsa->iqmp = BN_secure_new()) == NULL))
|
||||||
goto err;
|
goto err;
|
||||||
|
|
||||||
BN_copy(rsa->e, e_value);
|
BN_copy(rsa->e, e_value);
|
||||||
|
513
crypto/sec_mem.c
Normal file
513
crypto/sec_mem.c
Normal file
@ -0,0 +1,513 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2004-2014, Akamai Technologies. All Rights Reserved.
|
||||||
|
* This file is distributed under the terms of the OpenSSL license.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This file is in two halves. The first half implements the public API
|
||||||
|
* to be used by external consumers, and to be used by OpenSSL to store
|
||||||
|
* data in a "secure arena." The second half implements the secure arena.
|
||||||
|
* For details on that implementation, see below (look for uppercase
|
||||||
|
* "SECURE HEAP IMPLEMENTATION").
|
||||||
|
*/
|
||||||
|
#include <openssl/crypto.h>
|
||||||
|
#include <e_os.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <assert.h>
|
||||||
|
|
||||||
|
#if defined(OPENSSL_SYS_LINUX) || defined(OPENSSL_SYS_UNIX)
|
||||||
|
# define IMPLEMENTED
|
||||||
|
# include <sys/mman.h>
|
||||||
|
# include <sys/param.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define LOCK() CRYPTO_w_lock(CRYPTO_LOCK_MALLOC)
|
||||||
|
#define UNLOCK() CRYPTO_w_unlock(CRYPTO_LOCK_MALLOC)
|
||||||
|
#define CLEAR(p, s) OPENSSL_cleanse(p, s)
|
||||||
|
#define PAGE_SIZE 4096
|
||||||
|
|
||||||
|
#ifdef IMPLEMENTED
|
||||||
|
size_t secure_mem_used;
|
||||||
|
|
||||||
|
static int secure_mem_initialized;
|
||||||
|
static int too_late;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* These are the functions that must be implemented by a secure heap (sh).
|
||||||
|
*/
|
||||||
|
static int sh_init(size_t size, int minsize);
|
||||||
|
static char *sh_malloc(size_t size);
|
||||||
|
static void sh_free(char *ptr);
|
||||||
|
static void sh_done(void);
|
||||||
|
static int sh_actual_size(char *ptr);
|
||||||
|
static int sh_allocated(const char *ptr);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
int CRYPTO_secure_malloc_init(size_t size, int minsize)
|
||||||
|
{
|
||||||
|
#ifdef IMPLEMENTED
|
||||||
|
int ret = 0;
|
||||||
|
|
||||||
|
if (too_late)
|
||||||
|
return ret;
|
||||||
|
LOCK();
|
||||||
|
OPENSSL_assert(!secure_mem_initialized);
|
||||||
|
if (!secure_mem_initialized) {
|
||||||
|
ret = sh_init(size, minsize);
|
||||||
|
secure_mem_initialized = 1;
|
||||||
|
}
|
||||||
|
UNLOCK();
|
||||||
|
return ret;
|
||||||
|
#else
|
||||||
|
return 0;
|
||||||
|
#endif /* IMPLEMENTED */
|
||||||
|
}
|
||||||
|
|
||||||
|
void CRYPTO_secure_malloc_done()
|
||||||
|
{
|
||||||
|
#ifdef IMPLEMENTED
|
||||||
|
LOCK();
|
||||||
|
sh_done();
|
||||||
|
secure_mem_initialized = 0;
|
||||||
|
UNLOCK();
|
||||||
|
#endif /* IMPLEMENTED */
|
||||||
|
}
|
||||||
|
|
||||||
|
int CRYPTO_secure_malloc_initialized()
|
||||||
|
{
|
||||||
|
#ifdef IMPLEMENTED
|
||||||
|
return secure_mem_initialized;
|
||||||
|
#else
|
||||||
|
return 0;
|
||||||
|
#endif /* IMPLEMENTED */
|
||||||
|
}
|
||||||
|
|
||||||
|
void *CRYPTO_secure_malloc(int num, const char *file, int line)
|
||||||
|
{
|
||||||
|
#ifdef IMPLEMENTED
|
||||||
|
void *ret;
|
||||||
|
size_t actual_size;
|
||||||
|
|
||||||
|
if (!secure_mem_initialized) {
|
||||||
|
too_late = 1;
|
||||||
|
return CRYPTO_malloc(num, file, line);
|
||||||
|
}
|
||||||
|
LOCK();
|
||||||
|
ret = sh_malloc(num);
|
||||||
|
actual_size = ret ? sh_actual_size(ret) : 0;
|
||||||
|
secure_mem_used += actual_size;
|
||||||
|
UNLOCK();
|
||||||
|
return ret;
|
||||||
|
#else
|
||||||
|
return CRYPTO_malloc(num, file, line);
|
||||||
|
#endif /* IMPLEMENTED */
|
||||||
|
}
|
||||||
|
|
||||||
|
void CRYPTO_secure_free(void *ptr)
|
||||||
|
{
|
||||||
|
#ifdef IMPLEMENTED
|
||||||
|
size_t actual_size;
|
||||||
|
|
||||||
|
if (ptr == NULL)
|
||||||
|
return;
|
||||||
|
if (!secure_mem_initialized) {
|
||||||
|
CRYPTO_free(ptr);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
LOCK();
|
||||||
|
actual_size = sh_actual_size(ptr);
|
||||||
|
CLEAR(ptr, actual_size);
|
||||||
|
secure_mem_used -= actual_size;
|
||||||
|
sh_free(ptr);
|
||||||
|
UNLOCK();
|
||||||
|
#else
|
||||||
|
CRYPTO_free(ptr);
|
||||||
|
#endif /* IMPLEMENTED */
|
||||||
|
}
|
||||||
|
|
||||||
|
int CRYPTO_secure_allocated(const void *ptr)
|
||||||
|
{
|
||||||
|
#ifdef IMPLEMENTED
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
if (!secure_mem_initialized)
|
||||||
|
return 0;
|
||||||
|
LOCK();
|
||||||
|
ret = sh_allocated(ptr);
|
||||||
|
UNLOCK();
|
||||||
|
return ret;
|
||||||
|
#else
|
||||||
|
return 0;
|
||||||
|
#endif /* IMPLEMENTED */
|
||||||
|
}
|
||||||
|
|
||||||
|
/* END OF PAGE ...
|
||||||
|
|
||||||
|
... START OF PAGE */
|
||||||
|
|
||||||
|
/*
|
||||||
|
* SECURE HEAP IMPLEMENTATION
|
||||||
|
*/
|
||||||
|
#ifdef IMPLEMENTED
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* The implementation provided here uses a fixed-sized mmap() heap,
|
||||||
|
* which is locked into memory, not written to core files, and protected
|
||||||
|
* on either side by an unmapped page, which will catch pointer overruns
|
||||||
|
* (or underruns) and an attempt to read data out of the secure heap.
|
||||||
|
* Free'd memory is zero'd or otherwise cleansed.
|
||||||
|
*
|
||||||
|
* This is a pretty standard buddy allocator. We keep areas in a multiple
|
||||||
|
* of "sh.minsize" units. The freelist and bitmaps are kept separately,
|
||||||
|
* so all (and only) data is kept in the mmap'd heap.
|
||||||
|
*
|
||||||
|
* This code assumes eight-bit bytes. The numbers 3 and 7 are all over the
|
||||||
|
* place.
|
||||||
|
*/
|
||||||
|
|
||||||
|
# define TESTBIT(t, b) (t[(b) >> 3] & (1 << ((b) & 7)))
|
||||||
|
# define SETBIT(t, b) (t[(b) >> 3] |= (1 << ((b) & 7)))
|
||||||
|
# define CLEARBIT(t, b) (t[(b) >> 3] &= (0xFF & ~(1 << ((b) & 7))))
|
||||||
|
|
||||||
|
#define WITHIN_ARENA(p) \
|
||||||
|
((char*)(p) >= sh.arena && (char*)(p) < &sh.arena[sh.arena_size])
|
||||||
|
#define WITHIN_FREELIST(p) \
|
||||||
|
((char*)(p) >= (char*)sh.freelist && (char*)(p) < (char*)&sh.freelist[sh.freelist_size])
|
||||||
|
|
||||||
|
|
||||||
|
typedef struct sh_list_st
|
||||||
|
{
|
||||||
|
struct sh_list_st *next;
|
||||||
|
struct sh_list_st **p_next;
|
||||||
|
} SH_LIST;
|
||||||
|
|
||||||
|
typedef struct sh_st
|
||||||
|
{
|
||||||
|
char* map_result;
|
||||||
|
size_t map_size;
|
||||||
|
char *arena;
|
||||||
|
int arena_size;
|
||||||
|
char **freelist;
|
||||||
|
int freelist_size;
|
||||||
|
int minsize;
|
||||||
|
unsigned char *bittable;
|
||||||
|
unsigned char *bitmalloc;
|
||||||
|
int bittable_size; /* size in bits */
|
||||||
|
} SH;
|
||||||
|
|
||||||
|
static SH sh;
|
||||||
|
|
||||||
|
static int sh_getlist(char *ptr)
|
||||||
|
{
|
||||||
|
int list = sh.freelist_size - 1;
|
||||||
|
int bit = (sh.arena_size + ptr - sh.arena) / sh.minsize;
|
||||||
|
|
||||||
|
for (; bit; bit >>= 1, list--) {
|
||||||
|
if (TESTBIT(sh.bittable, bit))
|
||||||
|
break;
|
||||||
|
OPENSSL_assert((bit & 1) == 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
return list;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static int sh_testbit(char *ptr, int list, unsigned char *table)
|
||||||
|
{
|
||||||
|
int bit;
|
||||||
|
|
||||||
|
OPENSSL_assert(list >= 0 && list < sh.freelist_size);
|
||||||
|
OPENSSL_assert(((ptr - sh.arena) & ((sh.arena_size >> list) - 1)) == 0);
|
||||||
|
bit = (1 << list) + ((ptr - sh.arena) / (sh.arena_size >> list));
|
||||||
|
OPENSSL_assert(bit > 0 && bit < sh.bittable_size);
|
||||||
|
return TESTBIT(table, bit);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void sh_clearbit(char *ptr, int list, unsigned char *table)
|
||||||
|
{
|
||||||
|
int bit;
|
||||||
|
|
||||||
|
OPENSSL_assert(list >= 0 && list < sh.freelist_size);
|
||||||
|
OPENSSL_assert(((ptr - sh.arena) & ((sh.arena_size >> list) - 1)) == 0);
|
||||||
|
bit = (1 << list) + ((ptr - sh.arena) / (sh.arena_size >> list));
|
||||||
|
OPENSSL_assert(bit > 0 && bit < sh.bittable_size);
|
||||||
|
OPENSSL_assert(TESTBIT(table, bit));
|
||||||
|
CLEARBIT(table, bit);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void sh_setbit(char *ptr, int list, unsigned char *table)
|
||||||
|
{
|
||||||
|
int bit;
|
||||||
|
|
||||||
|
OPENSSL_assert(list >= 0 && list < sh.freelist_size);
|
||||||
|
OPENSSL_assert(((ptr - sh.arena) & ((sh.arena_size >> list) - 1)) == 0);
|
||||||
|
bit = (1 << list) + ((ptr - sh.arena) / (sh.arena_size >> list));
|
||||||
|
OPENSSL_assert(bit > 0 && bit < sh.bittable_size);
|
||||||
|
OPENSSL_assert(!TESTBIT(table, bit));
|
||||||
|
SETBIT(table, bit);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void sh_add_to_list(char **list, char *ptr)
|
||||||
|
{
|
||||||
|
SH_LIST *temp;
|
||||||
|
|
||||||
|
OPENSSL_assert(WITHIN_FREELIST(list));
|
||||||
|
OPENSSL_assert(WITHIN_ARENA(ptr));
|
||||||
|
|
||||||
|
temp = (SH_LIST *)ptr;
|
||||||
|
temp->next = *(SH_LIST **)list;
|
||||||
|
OPENSSL_assert(temp->next == NULL || WITHIN_ARENA(temp->next));
|
||||||
|
temp->p_next = (SH_LIST **)list;
|
||||||
|
|
||||||
|
if (temp->next != NULL) {
|
||||||
|
OPENSSL_assert((char **)temp->next->p_next == list);
|
||||||
|
temp->next->p_next = &(temp->next);
|
||||||
|
}
|
||||||
|
|
||||||
|
*list = ptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void sh_remove_from_list(char *ptr, char *list)
|
||||||
|
{
|
||||||
|
SH_LIST *temp, *temp2;
|
||||||
|
|
||||||
|
temp = (SH_LIST *)ptr;
|
||||||
|
if (temp->next != NULL)
|
||||||
|
temp->next->p_next = temp->p_next;
|
||||||
|
*temp->p_next = temp->next;
|
||||||
|
if (temp->next == NULL)
|
||||||
|
return;
|
||||||
|
|
||||||
|
temp2 = temp->next;
|
||||||
|
OPENSSL_assert(WITHIN_FREELIST(temp2->p_next) || WITHIN_ARENA(temp2->p_next));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static int sh_init(size_t size, int minsize)
|
||||||
|
{
|
||||||
|
int i, ret;
|
||||||
|
size_t pgsize;
|
||||||
|
size_t aligned;
|
||||||
|
|
||||||
|
memset(&sh, 0, sizeof sh);
|
||||||
|
|
||||||
|
/* make sure size and minsize are powers of 2 */
|
||||||
|
OPENSSL_assert(size > 0);
|
||||||
|
OPENSSL_assert((size & (size - 1)) == 0);
|
||||||
|
OPENSSL_assert(minsize > 0);
|
||||||
|
OPENSSL_assert((minsize & (minsize - 1)) == 0);
|
||||||
|
if (size <= 0 || (size & (size - 1)) != 0)
|
||||||
|
goto err;
|
||||||
|
if (minsize <= 0 || (minsize & (minsize - 1)) != 0)
|
||||||
|
goto err;
|
||||||
|
|
||||||
|
sh.arena_size = size;
|
||||||
|
sh.minsize = minsize;
|
||||||
|
sh.bittable_size = (sh.arena_size / sh.minsize) * 2;
|
||||||
|
|
||||||
|
sh.freelist_size = -1;
|
||||||
|
for (i = sh.bittable_size; i; i >>= 1)
|
||||||
|
sh.freelist_size++;
|
||||||
|
|
||||||
|
sh.freelist = OPENSSL_malloc(sh.freelist_size * sizeof (char *));
|
||||||
|
OPENSSL_assert(sh.freelist != NULL);
|
||||||
|
if (sh.freelist == NULL)
|
||||||
|
goto err;
|
||||||
|
memset(sh.freelist, 0, sh.freelist_size * sizeof (char *));
|
||||||
|
|
||||||
|
sh.bittable = OPENSSL_malloc(sh.bittable_size >> 3);
|
||||||
|
OPENSSL_assert(sh.bittable != NULL);
|
||||||
|
if (sh.bittable == NULL)
|
||||||
|
goto err;
|
||||||
|
memset(sh.bittable, 0, sh.bittable_size >> 3);
|
||||||
|
|
||||||
|
sh.bitmalloc = OPENSSL_malloc(sh.bittable_size >> 3);
|
||||||
|
OPENSSL_assert(sh.bitmalloc != NULL);
|
||||||
|
if (sh.bitmalloc == NULL)
|
||||||
|
goto err;
|
||||||
|
memset(sh.bitmalloc, 0, sh.bittable_size >> 3);
|
||||||
|
|
||||||
|
/* Allocate space for heap, and two extra pages as guards */
|
||||||
|
#ifdef _SC_PAGE_SIZE
|
||||||
|
pgsize = (size_t)sysconf(_SC_PAGE_SIZE);
|
||||||
|
#else
|
||||||
|
pgsize = PAGE_SIZE;
|
||||||
|
#endif
|
||||||
|
sh.map_size = pgsize + sh.arena_size + pgsize;
|
||||||
|
sh.map_result = mmap(NULL, sh.map_size,
|
||||||
|
PROT_READ|PROT_WRITE, MAP_ANON|MAP_PRIVATE, -1, 0);
|
||||||
|
OPENSSL_assert(sh.map_result != MAP_FAILED);
|
||||||
|
if (sh.map_result == MAP_FAILED)
|
||||||
|
goto err;
|
||||||
|
sh.arena = (char *)(sh.map_result + pgsize);
|
||||||
|
sh_setbit(sh.arena, 0, sh.bittable);
|
||||||
|
sh_add_to_list(&sh.freelist[0], sh.arena);
|
||||||
|
|
||||||
|
/* Now try to add guard pages and lock into memory. */
|
||||||
|
ret = 1;
|
||||||
|
|
||||||
|
/* Starting guard is already aligned from mmap. */
|
||||||
|
if (mprotect(sh.map_result, pgsize, PROT_NONE) < 0)
|
||||||
|
ret = 2;
|
||||||
|
|
||||||
|
/* Ending guard page - need to round up to page boundary */
|
||||||
|
aligned = (pgsize + sh.arena_size + (pgsize - 1)) & ~(pgsize - 1);
|
||||||
|
if (mprotect(sh.map_result + aligned, pgsize, PROT_NONE) < 0)
|
||||||
|
ret = 2;
|
||||||
|
|
||||||
|
if (mlock(sh.arena, sh.arena_size) < 0)
|
||||||
|
ret = 2;
|
||||||
|
#ifdef MADV_DONTDUMP
|
||||||
|
if (madvise(sh.arena, sh.arena_size, MADV_DONTDUMP) < 0)
|
||||||
|
ret = 2;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
|
||||||
|
err:
|
||||||
|
sh_done();
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void sh_done()
|
||||||
|
{
|
||||||
|
OPENSSL_free(sh.freelist);
|
||||||
|
OPENSSL_free(sh.bittable);
|
||||||
|
OPENSSL_free(sh.bitmalloc);
|
||||||
|
if (sh.map_result != NULL && sh.map_size)
|
||||||
|
munmap(sh.map_result, sh.map_size);
|
||||||
|
memset(&sh, 0, sizeof sh);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int sh_allocated(const char *ptr)
|
||||||
|
{
|
||||||
|
return WITHIN_ARENA(ptr) ? 1 : 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static char *sh_find_my_buddy(char *ptr, int list)
|
||||||
|
{
|
||||||
|
int bit;
|
||||||
|
char *chunk = NULL;
|
||||||
|
|
||||||
|
bit = (1 << list) + (ptr - sh.arena) / (sh.arena_size >> list);
|
||||||
|
bit ^= 1;
|
||||||
|
|
||||||
|
if (TESTBIT(sh.bittable, bit) && !TESTBIT(sh.bitmalloc, bit))
|
||||||
|
chunk = sh.arena + ((bit & ((1 << list) - 1)) * (sh.arena_size >> list));
|
||||||
|
|
||||||
|
return chunk;
|
||||||
|
}
|
||||||
|
|
||||||
|
static char *sh_malloc(size_t size)
|
||||||
|
{
|
||||||
|
int list, slist;
|
||||||
|
size_t i;
|
||||||
|
char *chunk;
|
||||||
|
|
||||||
|
list = sh.freelist_size - 1;
|
||||||
|
for (i = sh.minsize; i < size; i <<= 1)
|
||||||
|
list--;
|
||||||
|
if (list < 0)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
/* try to find a larger entry to split */
|
||||||
|
for (slist = list; slist >= 0; slist--)
|
||||||
|
if (sh.freelist[slist] != NULL)
|
||||||
|
break;
|
||||||
|
if (slist < 0)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
/* split larger entry */
|
||||||
|
while (slist != list) {
|
||||||
|
char *temp = sh.freelist[slist];
|
||||||
|
|
||||||
|
/* remove from bigger list */
|
||||||
|
OPENSSL_assert(!sh_testbit(temp, slist, sh.bitmalloc));
|
||||||
|
sh_clearbit(temp, slist, sh.bittable);
|
||||||
|
sh_remove_from_list(temp, sh.freelist[slist]);
|
||||||
|
OPENSSL_assert(temp != sh.freelist[slist]);
|
||||||
|
|
||||||
|
/* done with bigger list */
|
||||||
|
slist++;
|
||||||
|
|
||||||
|
/* add to smaller list */
|
||||||
|
OPENSSL_assert(!sh_testbit(temp, slist, sh.bitmalloc));
|
||||||
|
sh_setbit(temp, slist, sh.bittable);
|
||||||
|
sh_add_to_list(&sh.freelist[slist], temp);
|
||||||
|
OPENSSL_assert(sh.freelist[slist] == temp);
|
||||||
|
|
||||||
|
/* split in 2 */
|
||||||
|
temp += sh.arena_size >> slist;
|
||||||
|
OPENSSL_assert(!sh_testbit(temp, slist, sh.bitmalloc));
|
||||||
|
sh_setbit(temp, slist, sh.bittable);
|
||||||
|
sh_add_to_list(&sh.freelist[slist], temp);
|
||||||
|
OPENSSL_assert(sh.freelist[slist] == temp);
|
||||||
|
|
||||||
|
OPENSSL_assert(temp-(sh.arena_size >> slist) == sh_find_my_buddy(temp, slist));
|
||||||
|
}
|
||||||
|
|
||||||
|
/* peel off memory to hand back */
|
||||||
|
chunk = sh.freelist[list];
|
||||||
|
OPENSSL_assert(sh_testbit(chunk, list, sh.bittable));
|
||||||
|
sh_setbit(chunk, list, sh.bitmalloc);
|
||||||
|
sh_remove_from_list(chunk, sh.freelist[list]);
|
||||||
|
|
||||||
|
OPENSSL_assert(WITHIN_ARENA(chunk));
|
||||||
|
|
||||||
|
return chunk;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void sh_free(char *ptr)
|
||||||
|
{
|
||||||
|
int list;
|
||||||
|
char *buddy;
|
||||||
|
|
||||||
|
if (ptr == NULL)
|
||||||
|
return;
|
||||||
|
OPENSSL_assert(WITHIN_ARENA(ptr));
|
||||||
|
if (!WITHIN_ARENA(ptr))
|
||||||
|
return;
|
||||||
|
|
||||||
|
list = sh_getlist(ptr);
|
||||||
|
OPENSSL_assert(sh_testbit(ptr, list, sh.bittable));
|
||||||
|
sh_clearbit(ptr, list, sh.bitmalloc);
|
||||||
|
sh_add_to_list(&sh.freelist[list], ptr);
|
||||||
|
|
||||||
|
/* Try to coalesce two adjacent free areas. */
|
||||||
|
while ((buddy = sh_find_my_buddy(ptr, list)) != NULL) {
|
||||||
|
OPENSSL_assert(ptr == sh_find_my_buddy(buddy, list));
|
||||||
|
OPENSSL_assert(ptr != NULL);
|
||||||
|
OPENSSL_assert(!sh_testbit(ptr, list, sh.bitmalloc));
|
||||||
|
sh_clearbit(ptr, list, sh.bittable);
|
||||||
|
sh_remove_from_list(ptr, sh.freelist[list]);
|
||||||
|
OPENSSL_assert(!sh_testbit(ptr, list, sh.bitmalloc));
|
||||||
|
sh_clearbit(buddy, list, sh.bittable);
|
||||||
|
sh_remove_from_list(buddy, sh.freelist[list]);
|
||||||
|
|
||||||
|
list--;
|
||||||
|
|
||||||
|
if (ptr > buddy)
|
||||||
|
ptr = buddy;
|
||||||
|
|
||||||
|
OPENSSL_assert(!sh_testbit(ptr, list, sh.bitmalloc));
|
||||||
|
sh_setbit(ptr, list, sh.bittable);
|
||||||
|
sh_add_to_list(&sh.freelist[list], ptr);
|
||||||
|
OPENSSL_assert(sh.freelist[list] == ptr);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static int sh_actual_size(char *ptr)
|
||||||
|
{
|
||||||
|
int list;
|
||||||
|
|
||||||
|
OPENSSL_assert(WITHIN_ARENA(ptr));
|
||||||
|
if (!WITHIN_ARENA(ptr))
|
||||||
|
return 0;
|
||||||
|
list = sh_getlist(ptr);
|
||||||
|
OPENSSL_assert(sh_testbit(ptr, list, sh.bittable));
|
||||||
|
return sh.arena_size / (1 << list);
|
||||||
|
}
|
||||||
|
#endif /* IMPLEMENTED */
|
@ -10,6 +10,7 @@ BIO_get_mem_ptr, BIO_new_mem_buf - memory BIO
|
|||||||
#include <openssl/bio.h>
|
#include <openssl/bio.h>
|
||||||
|
|
||||||
BIO_METHOD * BIO_s_mem(void);
|
BIO_METHOD * BIO_s_mem(void);
|
||||||
|
BIO_METHOD * BIO_s_secmem(void);
|
||||||
|
|
||||||
BIO_set_mem_eof_return(BIO *b,int v)
|
BIO_set_mem_eof_return(BIO *b,int v)
|
||||||
long BIO_get_mem_data(BIO *b, char **pp)
|
long BIO_get_mem_data(BIO *b, char **pp)
|
||||||
@ -26,6 +27,9 @@ A memory BIO is a source/sink BIO which uses memory for its I/O. Data
|
|||||||
written to a memory BIO is stored in a BUF_MEM structure which is extended
|
written to a memory BIO is stored in a BUF_MEM structure which is extended
|
||||||
as appropriate to accommodate the stored data.
|
as appropriate to accommodate the stored data.
|
||||||
|
|
||||||
|
BIO_s_secmem() is like BIO_s_mem() except that the secure heap is used
|
||||||
|
for buffer storage.
|
||||||
|
|
||||||
Any data written to a memory BIO can be recalled by reading from it.
|
Any data written to a memory BIO can be recalled by reading from it.
|
||||||
Unless the memory BIO is read only any data read from it is deleted from
|
Unless the memory BIO is read only any data read from it is deleted from
|
||||||
the BIO.
|
the BIO.
|
||||||
@ -79,6 +83,9 @@ read in small chunks the operation can be very slow. The use of a read only
|
|||||||
memory BIO avoids this problem. If the BIO must be read write then adding
|
memory BIO avoids this problem. If the BIO must be read write then adding
|
||||||
a buffering BIO to the chain will speed up the process.
|
a buffering BIO to the chain will speed up the process.
|
||||||
|
|
||||||
|
Calling BIO_set_mem_buf() on a BIO created with BIO_new_secmem() will
|
||||||
|
give undefined results, including perhaps a program crash.
|
||||||
|
|
||||||
=head1 BUGS
|
=head1 BUGS
|
||||||
|
|
||||||
There should be an option to set the maximum size of a memory BIO.
|
There should be an option to set the maximum size of a memory BIO.
|
||||||
|
@ -2,7 +2,7 @@
|
|||||||
|
|
||||||
=head1 NAME
|
=head1 NAME
|
||||||
|
|
||||||
BN_CTX_new, BN_CTX_init, BN_CTX_free - allocate and free BN_CTX structures
|
BN_CTX_new, BN_CTX_secure_new, BN_CTX_init, BN_CTX_free - allocate and free BN_CTX structures
|
||||||
|
|
||||||
=head1 SYNOPSIS
|
=head1 SYNOPSIS
|
||||||
|
|
||||||
@ -10,6 +10,8 @@ BN_CTX_new, BN_CTX_init, BN_CTX_free - allocate and free BN_CTX structures
|
|||||||
|
|
||||||
BN_CTX *BN_CTX_new(void);
|
BN_CTX *BN_CTX_new(void);
|
||||||
|
|
||||||
|
BN_CTX *BN_CTX_secure_new(void);
|
||||||
|
|
||||||
void BN_CTX_free(BN_CTX *c);
|
void BN_CTX_free(BN_CTX *c);
|
||||||
|
|
||||||
=head1 DESCRIPTION
|
=head1 DESCRIPTION
|
||||||
@ -19,8 +21,10 @@ library functions. Since dynamic memory allocation to create B<BIGNUM>s
|
|||||||
is rather expensive when used in conjunction with repeated subroutine
|
is rather expensive when used in conjunction with repeated subroutine
|
||||||
calls, the B<BN_CTX> structure is used.
|
calls, the B<BN_CTX> structure is used.
|
||||||
|
|
||||||
BN_CTX_new() allocates and initializes a B<BN_CTX>
|
BN_CTX_new() allocates and initializes a B<BN_CTX> structure.
|
||||||
structure.
|
BN_CTX_secure_new() allocates and initializes a B<BN_CTX> structure
|
||||||
|
but uses the secure heap (see L<CRYPTO_secure_malloc(3)>) to hold the
|
||||||
|
B<BIGNUM>s.
|
||||||
|
|
||||||
BN_CTX_free() frees the components of the B<BN_CTX>, and if it was
|
BN_CTX_free() frees the components of the B<BN_CTX>, and if it was
|
||||||
created by BN_CTX_new(), also the structure itself.
|
created by BN_CTX_new(), also the structure itself.
|
||||||
@ -31,8 +35,9 @@ If B<c> is NULL, nothing is done.
|
|||||||
|
|
||||||
=head1 RETURN VALUES
|
=head1 RETURN VALUES
|
||||||
|
|
||||||
BN_CTX_new() returns a pointer to the B<BN_CTX>. If the allocation fails,
|
BN_CTX_new() and BN_CTX_secure_new() return a pointer to the B<BN_CTX>.
|
||||||
it returns B<NULL> and sets an error code that can be obtained by
|
If the allocation fails,
|
||||||
|
they return B<NULL> and sets an error code that can be obtained by
|
||||||
L<ERR_get_error(3)|ERR_get_error(3)>.
|
L<ERR_get_error(3)|ERR_get_error(3)>.
|
||||||
|
|
||||||
BN_CTX_free() has no return values.
|
BN_CTX_free() has no return values.
|
||||||
|
91
doc/crypto/CRYPTO_secure_malloc.pod
Normal file
91
doc/crypto/CRYPTO_secure_malloc.pod
Normal file
@ -0,0 +1,91 @@
|
|||||||
|
=pod
|
||||||
|
|
||||||
|
=head1 NAME
|
||||||
|
|
||||||
|
CRYPTO_secure_malloc_init, CRYPTO_secure_malloc_done, OPENSSL_secure_malloc, OPENSSL_secure_free, OPENSSL_secure_allocated - use secure heap storage
|
||||||
|
|
||||||
|
=head1 SYNOPSIS
|
||||||
|
|
||||||
|
#include <openssl/crypto.h>
|
||||||
|
|
||||||
|
int CRYPTO_secure_malloc_init(size_t size, int minsize);
|
||||||
|
|
||||||
|
int CRYPTO_secure_malloc_initialized();
|
||||||
|
|
||||||
|
void CRYPTO_secure_malloc_done();
|
||||||
|
|
||||||
|
void *OPENSSL_secure_malloc(int num);
|
||||||
|
|
||||||
|
void OPENSSL_secure_free(void* ptr);
|
||||||
|
|
||||||
|
int OPENSSL_secure_allocated(const void* ptr);
|
||||||
|
|
||||||
|
=head1 DESCRIPTION
|
||||||
|
|
||||||
|
In order to help protect applications (particularly long-running servers)
|
||||||
|
from pointer overruns or underruns that could return arbitrary data from
|
||||||
|
the program's dynamic memory area, where keys and other sensitive
|
||||||
|
information might be stored, OpenSSL supports the concept of a "secure heap."
|
||||||
|
The level and type of security guarantees depend on the operating system.
|
||||||
|
It is a good idea to review the code and see if it addresses your
|
||||||
|
threat model and concerns.
|
||||||
|
|
||||||
|
If a secure heap is used, then private key B<BIGNUM> values are stored there.
|
||||||
|
This protects long-term storage of private keys, but will not necessarily
|
||||||
|
put all intermediate values and computations there.
|
||||||
|
|
||||||
|
B<CRYPTO_secure_malloc_init> creates the secure heap, with the specified
|
||||||
|
C<size> in bytes. The C<minsize> parameter is the minimum size to
|
||||||
|
allocate from the heap. Both C<size> and C<minsize> must be a power
|
||||||
|
of two. It is an error to call this after any B<OPENSSL_secure_malloc>
|
||||||
|
calls have been made.
|
||||||
|
|
||||||
|
B<CRYPTO_secure_malloc_initialized> indicates whether or not the secure
|
||||||
|
heap as been initialized and is available.
|
||||||
|
|
||||||
|
B<CRYPTO_secure_malloc_done> releases the heap and makes the memory unavailable
|
||||||
|
to the process. It can take noticeably long to complete.
|
||||||
|
|
||||||
|
B<OPENSSL_secure_malloc> allocates C<num> bytes from the heap.
|
||||||
|
If B<CRYPTO_secure_malloc_init> is not called, this is equivalent to
|
||||||
|
calling B<OPENSSL_malloc>.
|
||||||
|
|
||||||
|
B<OPENSSL_secure_free> releases the memory at C<ptr> back to the heap.
|
||||||
|
It must be called with a value previously obtained from
|
||||||
|
B<OPENSSL_secure_malloc>.
|
||||||
|
If B<CRYPTO_secure_malloc_init> is not called, this is equivalent to
|
||||||
|
calling B<OPENSSL_free>.
|
||||||
|
|
||||||
|
B<OPENSSL_secure_allocated> tells whether or not a pointer is within
|
||||||
|
the secure heap.
|
||||||
|
|
||||||
|
=head1 RETURN VALUES
|
||||||
|
|
||||||
|
B<CRYPTO_secure_malloc_init> returns 0 on failure, 1 if successful,
|
||||||
|
and 2 if successful but the heap could not be protected by memory
|
||||||
|
mapping.
|
||||||
|
|
||||||
|
B<CRYPTO_secure_malloc_initialized> returns 1 if the secure heap is
|
||||||
|
available (that is, if B<CRYPTO_secure_malloc_init> has been called,
|
||||||
|
but B<CRYPTO_secure_malloc_done> has not) or 0 if not.
|
||||||
|
|
||||||
|
B<OPENSSL_secure_malloc> returns a pointer into the secure heap of
|
||||||
|
the requested size, or C<NULL> if memory could not be allocated.
|
||||||
|
|
||||||
|
B<CRYPTO_secure_allocated> returns 1 if the pointer is in the
|
||||||
|
the secure heap, or 0 if not.
|
||||||
|
|
||||||
|
B<CRYPTO_secure_malloc_done> and B<OPENSSL_secure_free>
|
||||||
|
return no values.
|
||||||
|
|
||||||
|
=head1 SEE ALSO
|
||||||
|
|
||||||
|
L<BN_new(3)|BN_new(3)>,
|
||||||
|
L<bn_internal(3)|bn_internal(3)>
|
||||||
|
|
||||||
|
=head1 HISTORY
|
||||||
|
|
||||||
|
These functions were contributed to the OpenSSL project by
|
||||||
|
Akamai Technologies in April, 2014.
|
||||||
|
|
||||||
|
=cut
|
@ -49,6 +49,7 @@ L<BIO_push(3)|BIO_push(3)>, L<BIO_read(3)|BIO_read(3)>,
|
|||||||
L<BIO_s_accept(3)|BIO_s_accept(3)>, L<BIO_s_bio(3)|BIO_s_bio(3)>,
|
L<BIO_s_accept(3)|BIO_s_accept(3)>, L<BIO_s_bio(3)|BIO_s_bio(3)>,
|
||||||
L<BIO_s_connect(3)|BIO_s_connect(3)>, L<BIO_s_fd(3)|BIO_s_fd(3)>,
|
L<BIO_s_connect(3)|BIO_s_connect(3)>, L<BIO_s_fd(3)|BIO_s_fd(3)>,
|
||||||
L<BIO_s_file(3)|BIO_s_file(3)>, L<BIO_s_mem(3)|BIO_s_mem(3)>,
|
L<BIO_s_file(3)|BIO_s_file(3)>, L<BIO_s_mem(3)|BIO_s_mem(3)>,
|
||||||
|
L<BIO_s_secmem(3)|BIO_s_mem(3)>,
|
||||||
L<BIO_s_null(3)|BIO_s_null(3)>, L<BIO_s_socket(3)|BIO_s_socket(3)>,
|
L<BIO_s_null(3)|BIO_s_null(3)>, L<BIO_s_socket(3)|BIO_s_socket(3)>,
|
||||||
L<BIO_set_callback(3)|BIO_set_callback(3)>,
|
L<BIO_set_callback(3)|BIO_set_callback(3)>,
|
||||||
L<BIO_should_retry(3)|BIO_should_retry(3)>
|
L<BIO_should_retry(3)|BIO_should_retry(3)>
|
||||||
|
@ -14,6 +14,7 @@ bn - multiprecision integer arithmetics
|
|||||||
void BN_clear_free(BIGNUM *a);
|
void BN_clear_free(BIGNUM *a);
|
||||||
|
|
||||||
BN_CTX *BN_CTX_new(void);
|
BN_CTX *BN_CTX_new(void);
|
||||||
|
BN_CTX *BN_CTX_secure_new(void);
|
||||||
void BN_CTX_free(BN_CTX *c);
|
void BN_CTX_free(BN_CTX *c);
|
||||||
|
|
||||||
BIGNUM *BN_copy(BIGNUM *a, const BIGNUM *b);
|
BIGNUM *BN_copy(BIGNUM *a, const BIGNUM *b);
|
||||||
|
@ -11,6 +11,10 @@ character arrays structure
|
|||||||
|
|
||||||
BUF_MEM *BUF_MEM_new(void);
|
BUF_MEM *BUF_MEM_new(void);
|
||||||
|
|
||||||
|
#define BUF_MEM_FLAG_SECURE
|
||||||
|
|
||||||
|
BUF_MEM * BUF_MEM_new_ex(unsigned long flags);
|
||||||
|
|
||||||
void BUF_MEM_free(BUF_MEM *a);
|
void BUF_MEM_free(BUF_MEM *a);
|
||||||
|
|
||||||
int BUF_MEM_grow(BUF_MEM *str, int len);
|
int BUF_MEM_grow(BUF_MEM *str, int len);
|
||||||
@ -37,6 +41,10 @@ and one "miscellaneous" function.
|
|||||||
|
|
||||||
BUF_MEM_new() allocates a new buffer of zero size.
|
BUF_MEM_new() allocates a new buffer of zero size.
|
||||||
|
|
||||||
|
BUF_MEM_new_ex() allocates a buffer with the specified flags.
|
||||||
|
The flag B<BUF_MEM_FLAG_SECURE> specifies that the B<data> pointer
|
||||||
|
should be allocated on the secure heap; see L<CRYPTO_secure_malloc(3)>.
|
||||||
|
|
||||||
BUF_MEM_free() frees up an already existing buffer. The data is zeroed
|
BUF_MEM_free() frees up an already existing buffer. The data is zeroed
|
||||||
before freeing up in case the buffer contains sensitive data.
|
before freeing up in case the buffer contains sensitive data.
|
||||||
|
|
||||||
@ -63,11 +71,15 @@ BUF_MEM_grow() returns zero on error or the new size (i.e. B<len>).
|
|||||||
|
|
||||||
=head1 SEE ALSO
|
=head1 SEE ALSO
|
||||||
|
|
||||||
L<bio(3)|bio(3)>
|
L<bio(3)|bio(3)>,
|
||||||
|
L<CRYPTO_secure_malloc(3)>.
|
||||||
|
|
||||||
=head1 HISTORY
|
=head1 HISTORY
|
||||||
|
|
||||||
BUF_MEM_new(), BUF_MEM_free() and BUF_MEM_grow() are available in all
|
BUF_MEM_new(), BUF_MEM_free() and BUF_MEM_grow() are available in all
|
||||||
versions of SSLeay and OpenSSL. BUF_strdup() was added in SSLeay 0.8.
|
versions of SSLeay and OpenSSL. BUF_strdup() was added in SSLeay 0.8.
|
||||||
|
|
||||||
|
BUF_MEM_new_ex() was contributed to OpenSSL by Akamai Technologies
|
||||||
|
in May, 2014.
|
||||||
|
|
||||||
=cut
|
=cut
|
||||||
|
@ -670,6 +670,7 @@ long BIO_debug_callback(BIO *bio, int cmd, const char *argp, int argi,
|
|||||||
long argl, long ret);
|
long argl, long ret);
|
||||||
|
|
||||||
BIO_METHOD *BIO_s_mem(void);
|
BIO_METHOD *BIO_s_mem(void);
|
||||||
|
BIO_METHOD *BIO_s_secmem(void);
|
||||||
BIO *BIO_new_mem_buf(void *buf, int len);
|
BIO *BIO_new_mem_buf(void *buf, int len);
|
||||||
BIO_METHOD *BIO_s_socket(void);
|
BIO_METHOD *BIO_s_socket(void);
|
||||||
BIO_METHOD *BIO_s_connect(void);
|
BIO_METHOD *BIO_s_connect(void);
|
||||||
|
@ -268,6 +268,7 @@ extern "C" {
|
|||||||
* BN_mod_inverse() will call BN_mod_inverse_no_branch.
|
* BN_mod_inverse() will call BN_mod_inverse_no_branch.
|
||||||
*/
|
*/
|
||||||
# define BN_FLG_CONSTTIME 0x04
|
# define BN_FLG_CONSTTIME 0x04
|
||||||
|
# define BN_FLG_SECURE 0x08
|
||||||
|
|
||||||
# ifdef OPENSSL_USE_DEPRECATED
|
# ifdef OPENSSL_USE_DEPRECATED
|
||||||
/* deprecated name for the flag */
|
/* deprecated name for the flag */
|
||||||
@ -349,6 +350,7 @@ void BN_zero_ex(BIGNUM *a);
|
|||||||
const BIGNUM *BN_value_one(void);
|
const BIGNUM *BN_value_one(void);
|
||||||
char *BN_options(void);
|
char *BN_options(void);
|
||||||
BN_CTX *BN_CTX_new(void);
|
BN_CTX *BN_CTX_new(void);
|
||||||
|
BN_CTX *BN_CTX_secure_new(void);
|
||||||
void BN_CTX_free(BN_CTX *c);
|
void BN_CTX_free(BN_CTX *c);
|
||||||
void BN_CTX_start(BN_CTX *ctx);
|
void BN_CTX_start(BN_CTX *ctx);
|
||||||
BIGNUM *BN_CTX_get(BN_CTX *ctx);
|
BIGNUM *BN_CTX_get(BN_CTX *ctx);
|
||||||
@ -361,6 +363,7 @@ int BN_num_bits(const BIGNUM *a);
|
|||||||
int BN_num_bits_word(BN_ULONG l);
|
int BN_num_bits_word(BN_ULONG l);
|
||||||
int BN_security_bits(int L, int N);
|
int BN_security_bits(int L, int N);
|
||||||
BIGNUM *BN_new(void);
|
BIGNUM *BN_new(void);
|
||||||
|
BIGNUM *BN_secure_new(void);
|
||||||
void BN_clear_free(BIGNUM *a);
|
void BN_clear_free(BIGNUM *a);
|
||||||
BIGNUM *BN_copy(BIGNUM *a, const BIGNUM *b);
|
BIGNUM *BN_copy(BIGNUM *a, const BIGNUM *b);
|
||||||
void BN_swap(BIGNUM *a, BIGNUM *b);
|
void BN_swap(BIGNUM *a, BIGNUM *b);
|
||||||
|
@ -78,9 +78,13 @@ struct buf_mem_st {
|
|||||||
size_t length; /* current number of bytes */
|
size_t length; /* current number of bytes */
|
||||||
char *data;
|
char *data;
|
||||||
size_t max; /* size of buffer */
|
size_t max; /* size of buffer */
|
||||||
|
unsigned long flags;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
# define BUF_MEM_FLAG_SECURE 0x01
|
||||||
|
|
||||||
BUF_MEM *BUF_MEM_new(void);
|
BUF_MEM *BUF_MEM_new(void);
|
||||||
|
BUF_MEM *BUF_MEM_new_ex(unsigned long flags);
|
||||||
void BUF_MEM_free(BUF_MEM *a);
|
void BUF_MEM_free(BUF_MEM *a);
|
||||||
size_t BUF_MEM_grow(BUF_MEM *str, size_t len);
|
size_t BUF_MEM_grow(BUF_MEM *str, size_t len);
|
||||||
size_t BUF_MEM_grow_clean(BUF_MEM *str, size_t len);
|
size_t BUF_MEM_grow_clean(BUF_MEM *str, size_t len);
|
||||||
|
@ -491,12 +491,12 @@ void (*CRYPTO_get_dynlock_destroy_callback(void)) (struct CRYPTO_dynlock_value
|
|||||||
int CRYPTO_set_mem_functions(void *(*m) (size_t), void *(*r) (void *, size_t),
|
int CRYPTO_set_mem_functions(void *(*m) (size_t), void *(*r) (void *, size_t),
|
||||||
void (*f) (void *));
|
void (*f) (void *));
|
||||||
int CRYPTO_set_locked_mem_functions(void *(*m) (size_t),
|
int CRYPTO_set_locked_mem_functions(void *(*m) (size_t),
|
||||||
void (*free_func) (void *));
|
void (*f) (void *));
|
||||||
int CRYPTO_set_mem_ex_functions(void *(*m) (size_t, const char *, int),
|
int CRYPTO_set_mem_ex_functions(void *(*m) (size_t, const char *, int),
|
||||||
void *(*r) (void *, size_t, const char *,
|
void *(*r) (void *, size_t, const char *,
|
||||||
int), void (*f) (void *));
|
int), void (*f) (void *));
|
||||||
int CRYPTO_set_locked_mem_ex_functions(void *(*m) (size_t, const char *, int),
|
int CRYPTO_set_locked_mem_ex_functions(void *(*m) (size_t, const char *, int),
|
||||||
void (*free_func) (void *));
|
void (*f) (void *));
|
||||||
int CRYPTO_set_mem_debug_functions(void (*m)
|
int CRYPTO_set_mem_debug_functions(void (*m)
|
||||||
(void *, int, const char *, int, int),
|
(void *, int, const char *, int, int),
|
||||||
void (*r) (void *, void *, int,
|
void (*r) (void *, void *, int,
|
||||||
@ -532,6 +532,25 @@ void *CRYPTO_realloc_clean(void *addr, int old_num, int num, const char *file,
|
|||||||
int line);
|
int line);
|
||||||
void *CRYPTO_remalloc(void *addr, int num, const char *file, int line);
|
void *CRYPTO_remalloc(void *addr, int num, const char *file, int line);
|
||||||
|
|
||||||
|
# define OPENSSL_secure_malloc(num) \
|
||||||
|
CRYPTO_secure_malloc((int)num,__FILE__,__LINE__)
|
||||||
|
# define OPENSSL_secure_free(addr) \
|
||||||
|
CRYPTO_secure_free(addr)
|
||||||
|
|
||||||
|
int CRYPTO_secure_malloc_init(size_t sz, int minsize);
|
||||||
|
void CRYPTO_secure_malloc_done(void);
|
||||||
|
void *CRYPTO_secure_malloc(int num, const char *file, int line);
|
||||||
|
void CRYPTO_secure_free(void *ptr);
|
||||||
|
int CRYPTO_secure_allocated(const void *ptr);
|
||||||
|
int CRYPTO_secure_malloc_initialized(void);
|
||||||
|
|
||||||
|
int CRYPTO_set_secure_mem_functions(void *(*m)(size_t), void (*f)(void *));
|
||||||
|
int CRYPTO_set_secure_mem_ex_functions(void *(*m)(size_t,const char *,int),
|
||||||
|
void (*f)(void *));
|
||||||
|
void CRYPTO_get_secure_mem_functions(void *(**m)(size_t), void (**f)(void *));
|
||||||
|
void CRYPTO_get_secure_mem_ex_functions(void *(**m)(size_t,const char *,int),
|
||||||
|
void (**f)(void *));
|
||||||
|
|
||||||
void OPENSSL_cleanse(void *ptr, size_t len);
|
void OPENSSL_cleanse(void *ptr, size_t len);
|
||||||
|
|
||||||
void CRYPTO_set_mem_debug_options(long bits);
|
void CRYPTO_set_mem_debug_options(long bits);
|
||||||
|
@ -63,6 +63,7 @@ EVPEXTRATEST=evp_extra_test
|
|||||||
P5_CRPT2_TEST= p5_crpt2_test
|
P5_CRPT2_TEST= p5_crpt2_test
|
||||||
IGETEST= igetest
|
IGETEST= igetest
|
||||||
JPAKETEST= jpaketest
|
JPAKETEST= jpaketest
|
||||||
|
SECMEMTEST= secmemtest
|
||||||
SRPTEST= srptest
|
SRPTEST= srptest
|
||||||
V3NAMETEST= v3nametest
|
V3NAMETEST= v3nametest
|
||||||
HEARTBEATTEST= heartbeat_test
|
HEARTBEATTEST= heartbeat_test
|
||||||
@ -80,7 +81,8 @@ EXE= $(BNTEST)$(EXE_EXT) $(ECTEST)$(EXE_EXT) $(ECDSATEST)$(EXE_EXT) $(ECDHTEST)
|
|||||||
$(BFTEST)$(EXE_EXT) $(CASTTEST)$(EXE_EXT) $(SSLTEST)$(EXE_EXT) \
|
$(BFTEST)$(EXE_EXT) $(CASTTEST)$(EXE_EXT) $(SSLTEST)$(EXE_EXT) \
|
||||||
$(EXPTEST)$(EXE_EXT) $(DSATEST)$(EXE_EXT) $(RSATEST)$(EXE_EXT) \
|
$(EXPTEST)$(EXE_EXT) $(DSATEST)$(EXE_EXT) $(RSATEST)$(EXE_EXT) \
|
||||||
$(EVPTEST)$(EXE_EXT) $(EVPEXTRATEST)$(EXE_EXT) $(IGETEST)$(EXE_EXT) \
|
$(EVPTEST)$(EXE_EXT) $(EVPEXTRATEST)$(EXE_EXT) $(IGETEST)$(EXE_EXT) \
|
||||||
$(JPAKETEST)$(EXE_EXT) $(SRPTEST)$(EXE_EXT) $(V3NAMETEST)$(EXE_EXT) \
|
$(JPAKETEST)$(EXE_EXT) $(SECMEMTEST)$(EXE_EXT) \
|
||||||
|
$(SRPTEST)$(EXE_EXT) $(V3NAMETEST)$(EXE_EXT) \
|
||||||
$(HEARTBEATTEST)$(EXE_EXT) $(P5_CRPT2_TEST)$(EXE_EXT) \
|
$(HEARTBEATTEST)$(EXE_EXT) $(P5_CRPT2_TEST)$(EXE_EXT) \
|
||||||
$(CONSTTIMETEST)$(EXE_EXT)
|
$(CONSTTIMETEST)$(EXE_EXT)
|
||||||
|
|
||||||
@ -145,7 +147,8 @@ alltests: \
|
|||||||
test_enc test_x509 test_rsa test_crl test_sid \
|
test_enc test_x509 test_rsa test_crl test_sid \
|
||||||
test_gen test_req test_pkcs7 test_verify test_dh test_dsa \
|
test_gen test_req test_pkcs7 test_verify test_dh test_dsa \
|
||||||
test_ss test_ca test_engine test_evp test_evp_extra test_ssl test_tsa \
|
test_ss test_ca test_engine test_evp test_evp_extra test_ssl test_tsa \
|
||||||
test_ige test_jpake test_srp test_cms test_v3name test_ocsp \
|
test_ige test_jpake test_secmem \
|
||||||
|
test_srp test_cms test_v3name test_ocsp \
|
||||||
test_gost2814789 test_heartbeat test_p5_crpt2 \
|
test_gost2814789 test_heartbeat test_p5_crpt2 \
|
||||||
test_constant_time
|
test_constant_time
|
||||||
|
|
||||||
@ -372,6 +375,10 @@ test_cms: ../apps/openssl$(EXE_EXT) cms-test.pl smcont.txt
|
|||||||
@echo $(START) $@
|
@echo $(START) $@
|
||||||
$(PERL) cms-test.pl
|
$(PERL) cms-test.pl
|
||||||
|
|
||||||
|
test_secmem: $(SECMEMTEST)$(EXE_EXT)
|
||||||
|
@echo $(START) $@
|
||||||
|
../util/shlib_wrap.sh ./secmemtest
|
||||||
|
|
||||||
test_srp: $(SRPTEST)$(EXE_EXT)
|
test_srp: $(SRPTEST)$(EXE_EXT)
|
||||||
@echo $(START) $@
|
@echo $(START) $@
|
||||||
../util/shlib_wrap.sh ./srptest
|
../util/shlib_wrap.sh ./srptest
|
||||||
@ -564,6 +571,9 @@ $(IGETEST)$(EXE_EXT): $(IGETEST).o $(DLIBCRYPTO)
|
|||||||
$(JPAKETEST)$(EXE_EXT): $(JPAKETEST).o $(DLIBCRYPTO)
|
$(JPAKETEST)$(EXE_EXT): $(JPAKETEST).o $(DLIBCRYPTO)
|
||||||
@target=$(JPAKETEST); $(BUILD_CMD)
|
@target=$(JPAKETEST); $(BUILD_CMD)
|
||||||
|
|
||||||
|
$(SECMEMTEST)$(EXE_EXT): $(SECMEMTEST).o $(DLIBCRYPTO)
|
||||||
|
@target=$(SECMEMTEST); $(BUILD_CMD)
|
||||||
|
|
||||||
$(SRPTEST)$(EXE_EXT): $(SRPTEST).o $(DLIBCRYPTO)
|
$(SRPTEST)$(EXE_EXT): $(SRPTEST).o $(DLIBCRYPTO)
|
||||||
@target=$(SRPTEST); $(BUILD_CMD)
|
@target=$(SRPTEST); $(BUILD_CMD)
|
||||||
|
|
||||||
|
34
test/secmemtest.c
Normal file
34
test/secmemtest.c
Normal file
@ -0,0 +1,34 @@
|
|||||||
|
|
||||||
|
#include <openssl/crypto.h>
|
||||||
|
|
||||||
|
int main(int argc, char **argv)
|
||||||
|
{
|
||||||
|
#if defined(OPENSSL_SYS_LINUX) || defined(OPENSSL_SYS_UNIX)
|
||||||
|
char *p = NULL, *q = NULL;
|
||||||
|
|
||||||
|
if (!CRYPTO_secure_malloc_init(4096, 32)) {
|
||||||
|
perror("failed");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
p = OPENSSL_secure_malloc(20);
|
||||||
|
if (!CRYPTO_secure_allocated(p)) {
|
||||||
|
perror("failed 1");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
q = OPENSSL_malloc(20);
|
||||||
|
if (CRYPTO_secure_allocated(q)) {
|
||||||
|
perror("failed 1");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
CRYPTO_secure_free(p);
|
||||||
|
CRYPTO_free(q);
|
||||||
|
CRYPTO_secure_malloc_done();
|
||||||
|
#else
|
||||||
|
/* Should fail. */
|
||||||
|
if (CRYPTO_secure_malloc_init(4096, 32)) {
|
||||||
|
perror("failed");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
return 0;
|
||||||
|
}
|
@ -4573,3 +4573,17 @@ PKCS5_pbe2_set_scrypt 4931 EXIST::FUNCTION:
|
|||||||
PKCS8_set0_pbe 4932 EXIST::FUNCTION:
|
PKCS8_set0_pbe 4932 EXIST::FUNCTION:
|
||||||
DH_bits 4933 EXIST::FUNCTION:DH
|
DH_bits 4933 EXIST::FUNCTION:DH
|
||||||
RSA_bits 4934 EXIST::FUNCTION:RSA
|
RSA_bits 4934 EXIST::FUNCTION:RSA
|
||||||
|
CRYPTO_set_secure_mem_ex_functions 4935 EXIST::FUNCTION:
|
||||||
|
CRYPTO_secure_allocated 4936 EXIST::FUNCTION:
|
||||||
|
BN_CTX_secure_new 4937 EXIST::FUNCTION:
|
||||||
|
CRYPTO_secure_malloc 4938 EXIST::FUNCTION:
|
||||||
|
CRYPTO_secure_malloc_done 4939 EXIST::FUNCTION:
|
||||||
|
BUF_MEM_new_ex 4940 EXIST::FUNCTION:
|
||||||
|
CRYPTO_secure_malloc_initialized 4941 EXIST::FUNCTION:
|
||||||
|
CRYPTO_secure_malloc_init 4942 EXIST::FUNCTION:
|
||||||
|
CRYPTO_get_secure_mem_functions 4943 EXIST::FUNCTION:
|
||||||
|
BN_secure_new 4944 EXIST::FUNCTION:
|
||||||
|
CRYPTO_secure_free 4945 EXIST::FUNCTION:
|
||||||
|
BIO_s_secmem 4946 EXIST::FUNCTION:
|
||||||
|
CRYPTO_get_secure_mem_ex_functions 4947 EXIST::FUNCTION:
|
||||||
|
CRYPTO_set_secure_mem_functions 4948 EXIST::FUNCTION:
|
||||||
|
Loading…
x
Reference in New Issue
Block a user