Skip to content

Commit

Permalink
Combined patch for the more or less obvious issues
Browse files Browse the repository at this point in the history
Fixed a memory leak in ASN1_digest and ASN1_item_digest.

asn1_template_noexp_d2i call ASN1_item_ex_free(&skfield,...) on error.

Reworked error handling in asn1_item_ex_combine_new:
- call ASN1_item_ex_free and return the correct error code if ASN1_template_new failed.
- dont call ASN1_item_ex_free if ASN1_OP_NEW_PRE failed.

Reworked error handing in x509_name_ex_d2i and x509_name_encode.

Fixed error handling in int_ctx_new and EVP_PKEY_CTX_dup.

Fixed a memory leak in def_get_class if lh_EX_CLASS_ITEM_insert fails due to OOM:
- to figure out if the insertion succeeded, use lh_EX_CLASS_ITEM_retrieve again.
- on error, p will be NULL, and gen needs to be cleaned up again.

int_free_ex_data needs to have a fallback solution if unable to allocate "storage":
- if free_func is non-zero this must be called to clean up all memory.

Fixed error handling in pkey_hmac_copy.

Fixed error handling in ssleay_rand_add and ssleay_rand_bytes.

Fixed error handling in X509_STORE_new.

Fixed a memory leak in ssl3_get_key_exchange.

Check for null pointer in ssl3_write_bytes.

Check for null pointer in ssl3_get_cert_verify.

Fixed a memory leak in ssl_cert_dup.

Fixes #2087 #2094 #2103 #2104 #2105 #2106 #2107 #2108 #2110 #2111 #2112 #2115

Reviewed-by: Richard Levitte <levitte@openssl.org>
Reviewed-by: Rich Salz <rsalz@openssl.org>
(Merged from #2127)
  • Loading branch information
bernd-edlinger authored and Rich Salz committed Feb 6, 2017
1 parent efe8398 commit 748cb9a
Show file tree
Hide file tree
Showing 13 changed files with 138 additions and 72 deletions.
8 changes: 6 additions & 2 deletions crypto/asn1/a_digest.c
Expand Up @@ -86,8 +86,10 @@ int ASN1_digest(i2d_of_void *i2d, const EVP_MD *type, char *data,
p = str;
i2d(data, &p);

if (!EVP_Digest(str, i, md, len, type, NULL))
if (!EVP_Digest(str, i, md, len, type, NULL)) {
OPENSSL_free(str);
return 0;
}
OPENSSL_free(str);
return (1);
}
Expand All @@ -104,8 +106,10 @@ int ASN1_item_digest(const ASN1_ITEM *it, const EVP_MD *type, void *asn,
if (!str)
return (0);

if (!EVP_Digest(str, i, md, len, type, NULL))
if (!EVP_Digest(str, i, md, len, type, NULL)) {
OPENSSL_free(str);
return 0;
}
OPENSSL_free(str);
return (1);
}
1 change: 1 addition & 0 deletions crypto/asn1/tasn_dec.c
Expand Up @@ -673,6 +673,7 @@ static int asn1_template_noexp_d2i(ASN1_VALUE **val,
}
len -= p - q;
if (!sk_ASN1_VALUE_push((STACK_OF(ASN1_VALUE) *)*val, skfield)) {
ASN1_item_ex_free(&skfield, ASN1_ITEM_ptr(tt->item));
ASN1err(ASN1_F_ASN1_TEMPLATE_NOEXP_D2I, ERR_R_MALLOC_FAILURE);
goto err;
}
Expand Down
11 changes: 7 additions & 4 deletions crypto/asn1/tasn_new.c
Expand Up @@ -158,7 +158,7 @@ static int asn1_item_ex_combine_new(ASN1_VALUE **pval, const ASN1_ITEM *it,
}
asn1_set_choice_selector(pval, -1, it);
if (asn1_cb && !asn1_cb(ASN1_OP_NEW_POST, pval, it, NULL))
goto auxerr;
goto auxerr2;
break;

case ASN1_ITYPE_NDEF_SEQUENCE:
Expand Down Expand Up @@ -186,10 +186,10 @@ static int asn1_item_ex_combine_new(ASN1_VALUE **pval, const ASN1_ITEM *it,
for (i = 0, tt = it->templates; i < it->tcount; tt++, i++) {
pseqval = asn1_get_field_ptr(pval, tt);
if (!ASN1_template_new(pseqval, tt))
goto memerr;
goto memerr2;
}
if (asn1_cb && !asn1_cb(ASN1_OP_NEW_POST, pval, it, NULL))
goto auxerr;
goto auxerr2;
break;
}
#ifdef CRYPTO_MDEBUG
Expand All @@ -198,6 +198,8 @@ static int asn1_item_ex_combine_new(ASN1_VALUE **pval, const ASN1_ITEM *it,
#endif
return 1;

memerr2:
ASN1_item_ex_free(pval, it);
memerr:
ASN1err(ASN1_F_ASN1_ITEM_EX_COMBINE_NEW, ERR_R_MALLOC_FAILURE);
#ifdef CRYPTO_MDEBUG
Expand All @@ -206,9 +208,10 @@ static int asn1_item_ex_combine_new(ASN1_VALUE **pval, const ASN1_ITEM *it,
#endif
return 0;

auxerr2:
ASN1_item_ex_free(pval, it);
auxerr:
ASN1err(ASN1_F_ASN1_ITEM_EX_COMBINE_NEW, ASN1_R_AUX_ERROR);
ASN1_item_ex_free(pval, it);
#ifdef CRYPTO_MDEBUG
if (it->sname)
CRYPTO_pop_info();
Expand Down
35 changes: 21 additions & 14 deletions crypto/asn1/x_name.c
Expand Up @@ -178,6 +178,16 @@ static void x509_name_ex_free(ASN1_VALUE **pval, const ASN1_ITEM *it)
*pval = NULL;
}

static void local_sk_X509_NAME_ENTRY_free(STACK_OF(X509_NAME_ENTRY) *ne)
{
sk_X509_NAME_ENTRY_free(ne);
}

static void local_sk_X509_NAME_ENTRY_pop_free(STACK_OF(X509_NAME_ENTRY) *ne)
{
sk_X509_NAME_ENTRY_pop_free(ne, X509_NAME_ENTRY_free);
}

static int x509_name_ex_d2i(ASN1_VALUE **val,
const unsigned char **in, long len,
const ASN1_ITEM *it, int tag, int aclass,
Expand Down Expand Up @@ -228,20 +238,23 @@ static int x509_name_ex_d2i(ASN1_VALUE **val,
entry->set = i;
if (!sk_X509_NAME_ENTRY_push(nm.x->entries, entry))
goto err;
sk_X509_NAME_ENTRY_set(entries, j, NULL);
}
sk_X509_NAME_ENTRY_free(entries);
}
sk_STACK_OF_X509_NAME_ENTRY_free(intname.s);
ret = x509_name_canon(nm.x);
if (!ret)
goto err;
sk_STACK_OF_X509_NAME_ENTRY_pop_free(intname.s,
local_sk_X509_NAME_ENTRY_free);
nm.x->modified = 0;
*val = nm.a;
*in = p;
return ret;
err:
if (nm.x != NULL)
X509_NAME_free(nm.x);
sk_STACK_OF_X509_NAME_ENTRY_pop_free(intname.s,
local_sk_X509_NAME_ENTRY_pop_free);
ASN1err(ASN1_F_X509_NAME_EX_D2I, ERR_R_NESTED_ASN1_ERROR);
return 0;
}
Expand All @@ -267,16 +280,6 @@ static int x509_name_ex_i2d(ASN1_VALUE **val, unsigned char **out,
return ret;
}

static void local_sk_X509_NAME_ENTRY_free(STACK_OF(X509_NAME_ENTRY) *ne)
{
sk_X509_NAME_ENTRY_free(ne);
}

static void local_sk_X509_NAME_ENTRY_pop_free(STACK_OF(X509_NAME_ENTRY) *ne)
{
sk_X509_NAME_ENTRY_pop_free(ne, X509_NAME_ENTRY_free);
}

static int x509_name_encode(X509_NAME *a)
{
union {
Expand All @@ -299,8 +302,10 @@ static int x509_name_encode(X509_NAME *a)
entries = sk_X509_NAME_ENTRY_new_null();
if (!entries)
goto memerr;
if (!sk_STACK_OF_X509_NAME_ENTRY_push(intname.s, entries))
if (!sk_STACK_OF_X509_NAME_ENTRY_push(intname.s, entries)) {
sk_X509_NAME_ENTRY_free(entries);
goto memerr;
}
set = entry->set;
}
if (!sk_X509_NAME_ENTRY_push(entries, entry))
Expand Down Expand Up @@ -370,8 +375,10 @@ static int x509_name_canon(X509_NAME *a)
entries = sk_X509_NAME_ENTRY_new_null();
if (!entries)
goto err;
if (!sk_STACK_OF_X509_NAME_ENTRY_push(intname, entries))
if (!sk_STACK_OF_X509_NAME_ENTRY_push(intname, entries)) {
sk_X509_NAME_ENTRY_free(entries);
goto err;
}
set = entry->set;
}
tmpentry = X509_NAME_ENTRY_new();
Expand Down
2 changes: 2 additions & 0 deletions crypto/evp/pmeth_lib.c
Expand Up @@ -188,6 +188,7 @@ static EVP_PKEY_CTX *int_ctx_new(EVP_PKEY *pkey, ENGINE *e, int id)

if (pmeth->init) {
if (pmeth->init(ret) <= 0) {
ret->pmeth = NULL;
EVP_PKEY_CTX_free(ret);
return NULL;
}
Expand Down Expand Up @@ -315,6 +316,7 @@ EVP_PKEY_CTX *EVP_PKEY_CTX_dup(EVP_PKEY_CTX *pctx)
if (pctx->pmeth->copy(rctx, pctx) > 0)
return rctx;

rctx->pmeth = NULL;
EVP_PKEY_CTX_free(rctx);
return NULL;

Expand Down
37 changes: 21 additions & 16 deletions crypto/ex_data.c
Expand Up @@ -331,7 +331,11 @@ static EX_CLASS_ITEM *def_get_class(int class_index)
* from the insert will be NULL
*/
(void)lh_EX_CLASS_ITEM_insert(ex_data, gen);
p = gen;
p = lh_EX_CLASS_ITEM_retrieve(ex_data, &d);
if (p != gen) {
sk_CRYPTO_EX_DATA_FUNCS_free(gen->meth);
OPENSSL_free(gen);
}
}
}
}
Expand Down Expand Up @@ -499,11 +503,12 @@ static void int_free_ex_data(int class_index, void *obj, CRYPTO_EX_DATA *ad)
int mx, i;
EX_CLASS_ITEM *item;
void *ptr;
CRYPTO_EX_DATA_FUNCS *f;
CRYPTO_EX_DATA_FUNCS **storage = NULL;
if (ex_data == NULL)
return;
goto err;
if ((item = def_get_class(class_index)) == NULL)
return;
goto err;
CRYPTO_r_lock(CRYPTO_LOCK_EX_DATA);
mx = sk_CRYPTO_EX_DATA_FUNCS_num(item->meth);
if (mx > 0) {
Expand All @@ -515,23 +520,23 @@ static void int_free_ex_data(int class_index, void *obj, CRYPTO_EX_DATA *ad)
}
skip:
CRYPTO_r_unlock(CRYPTO_LOCK_EX_DATA);
if ((mx > 0) && !storage) {
CRYPTOerr(CRYPTO_F_INT_FREE_EX_DATA, ERR_R_MALLOC_FAILURE);
return;
}
for (i = 0; i < mx; i++) {
if (storage[i] && storage[i]->free_func) {
if (storage != NULL)
f = storage[i];
else {
CRYPTO_r_lock(CRYPTO_LOCK_EX_DATA);
f = sk_CRYPTO_EX_DATA_FUNCS_value(item->meth, i);
CRYPTO_r_unlock(CRYPTO_LOCK_EX_DATA);
}
if (f != NULL && f->free_func != NULL) {
ptr = CRYPTO_get_ex_data(ad, i);
storage[i]->free_func(obj, ptr, ad, i,
storage[i]->argl, storage[i]->argp);
f->free_func(obj, ptr, ad, i, f->argl, f->argp);
}
}
if (storage)
OPENSSL_free(storage);
if (ad->sk) {
sk_void_free(ad->sk);
ad->sk = NULL;
}
OPENSSL_free(storage);
err:
sk_void_free(ad->sk);
ad->sk = NULL;
}

/********************************************************************/
Expand Down
11 changes: 7 additions & 4 deletions crypto/hmac/hm_pmeth.c
Expand Up @@ -99,15 +99,18 @@ static int pkey_hmac_copy(EVP_PKEY_CTX *dst, EVP_PKEY_CTX *src)
sctx = src->data;
dctx = dst->data;
dctx->md = sctx->md;
HMAC_CTX_init(&dctx->ctx);
if (!HMAC_CTX_copy(&dctx->ctx, &sctx->ctx))
return 0;
if (sctx->ktmp.data) {
goto err;
if (sctx->ktmp.data != NULL) {
if (!ASN1_OCTET_STRING_set(&dctx->ktmp,
sctx->ktmp.data, sctx->ktmp.length))
return 0;
goto err;
}
return 1;
err:
HMAC_CTX_cleanup(&dctx->ctx);
OPENSSL_free(dctx);
return 0;
}

static void pkey_hmac_cleanup(EVP_PKEY_CTX *ctx)
Expand Down

0 comments on commit 748cb9a

Please sign in to comment.