Commit 83b4049a authored by Bernd Edlinger's avatar Bernd Edlinger Committed by Richard Levitte
Browse files

Combined patch against master branch for the following issues:



Fixed a memory leak in ASN1_digest and ASN1_item_digest.
Reworked error handling in asn1_item_embed_new.
Fixed error handling in int_ctx_new and EVP_PKEY_CTX_dup.
Fixed a memory leak in CRYPTO_free_ex_data.
Reworked error handing in x509_name_ex_d2i, x509_name_encode and x509_name_canon.
Check for null pointer in tls_process_cert_verify.

Fixes #2103 #2104 #2105 #2109 #2111 #2115

Reviewed-by: default avatarRich Salz <rsalz@openssl.org>
Reviewed-by: default avatarRichard Levitte <levitte@openssl.org>
(Merged from https://github.com/openssl/openssl/pull/2342)
parent 21f198ec
Loading
Loading
Loading
Loading
+6 −2
Original line number Diff line number Diff line
@@ -37,8 +37,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);
}
@@ -55,8 +57,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);
}
+8 −5
Original line number Diff line number Diff line
@@ -100,7 +100,7 @@ int asn1_item_embed_new(ASN1_VALUE **pval, const ASN1_ITEM *it, int embed)
        }
        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:
@@ -125,15 +125,15 @@ int asn1_item_embed_new(ASN1_VALUE **pval, const ASN1_ITEM *it, int embed)
        }
        /* 0 : init. lock */
        if (asn1_do_lock(pval, 0, it) < 0)
            goto memerr;
            goto memerr2;
        asn1_enc_init(pval, 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;
    }
#ifndef OPENSSL_NO_CRYPTO_MDEBUG
@@ -141,6 +141,8 @@ int asn1_item_embed_new(ASN1_VALUE **pval, const ASN1_ITEM *it, int embed)
#endif
    return 1;

 memerr2:
    ASN1_item_ex_free(pval, it);
 memerr:
    ASN1err(ASN1_F_ASN1_ITEM_EMBED_NEW, ERR_R_MALLOC_FAILURE);
#ifndef OPENSSL_NO_CRYPTO_MDEBUG
@@ -148,9 +150,10 @@ int asn1_item_embed_new(ASN1_VALUE **pval, const ASN1_ITEM *it, int embed)
#endif
    return 0;

 auxerr2:
    ASN1_item_ex_free(pval, it);
 auxerr:
    ASN1err(ASN1_F_ASN1_ITEM_EMBED_NEW, ASN1_R_AUX_ERROR);
    ASN1_item_ex_free(pval, it);
#ifndef OPENSSL_NO_CRYPTO_MDEBUG
    OPENSSL_mem_debug_pop();
#endif
+2 −0
Original line number Diff line number Diff line
@@ -142,6 +142,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;
        }
@@ -267,6 +268,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;

+12 −8
Original line number Diff line number Diff line
@@ -307,11 +307,12 @@ void CRYPTO_free_ex_data(int class_index, void *obj, CRYPTO_EX_DATA *ad)
    int mx, i;
    EX_CALLBACKS *ip;
    void *ptr;
    EX_CALLBACK *f;
    EX_CALLBACK *stack[10];
    EX_CALLBACK **storage = NULL;

    if ((ip = get_and_lock(class_index)) == NULL)
        return;
        goto err;

    mx = sk_EX_CALLBACK_num(ip->meth);
    if (mx > 0) {
@@ -325,20 +326,23 @@ void CRYPTO_free_ex_data(int class_index, void *obj, CRYPTO_EX_DATA *ad)
    }
    CRYPTO_THREAD_unlock(ex_data_lock);

    if (mx > 0 && storage == NULL) {
        CRYPTOerr(CRYPTO_F_CRYPTO_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_THREAD_write_lock(ex_data_lock);
            f = sk_EX_CALLBACK_value(ip->meth, i);
            CRYPTO_THREAD_unlock(ex_data_lock);
        }
        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 != stack)
        OPENSSL_free(storage);
 err:
    sk_void_free(ad->sk);
    ad->sk = NULL;
}
+20 −30
Original line number Diff line number Diff line
@@ -125,9 +125,14 @@ static void x509_name_ex_free(ASN1_VALUE **pval, const ASN1_ITEM *it)
    *pval = NULL;
}

static void name_entry_stack_free(STACK_OF(X509_NAME_ENTRY) *ents)
static void local_sk_X509_NAME_ENTRY_free(STACK_OF(X509_NAME_ENTRY) *ne)
{
    sk_X509_NAME_ENTRY_pop_free(ents, X509_NAME_ENTRY_free);
    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,
@@ -180,33 +185,24 @@ 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);
        }
    }
    /*
     * All entries have now been pushed to nm->x.entries
     * free up the stacks in intname.s but not the entries
     * themselves.
     */
    sk_STACK_OF_X509_NAME_ENTRY_pop_free(intname.s, sk_X509_NAME_ENTRY_free);
    intname.s = NULL;
    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 intname.s is not NULL only some entries exist in nm->x.entries:
     * zero references in nm->x.entries list. Since all entries exist
     * in intname.s we can free them all there
     */
    if (intname.s != NULL) {
        sk_X509_NAME_ENTRY_zero(nm.x->entries);
        sk_STACK_OF_X509_NAME_ENTRY_pop_free(intname.s, name_entry_stack_free);
    }
    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;
}
@@ -232,16 +228,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 {
@@ -264,8 +250,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))
@@ -333,8 +321,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();
Loading