Commit ab4a81f6 authored by Dr. Stephen Henson's avatar Dr. Stephen Henson
Browse files

Remove broken DSA private key workarounds.



Remove old code that handled various invalid DSA formats in ancient
software.

This also fixes a double free bug when parsing malformed DSA private keys.

Thanks to Adam Langley (Google/BoringSSL) for discovering this bug using
libFuzzer.

CVE-2016-0705

Reviewed-by: default avatarEmilia Käsper <emilia@openssl.org>
parent aa474d1f
Loading
Loading
Loading
Loading
+17 −48
Original line number Diff line number Diff line
@@ -183,7 +183,7 @@ static int dsa_pub_encode(X509_PUBKEY *pk, const EVP_PKEY *pkey)

static int dsa_priv_decode(EVP_PKEY *pkey, PKCS8_PRIV_KEY_INFO *p8)
{
    const unsigned char *p, *pm;
    const unsigned char *p, *q, *pm;
    int pklen, pmlen;
    int ptype;
    void *pval;
@@ -192,42 +192,16 @@ static int dsa_priv_decode(EVP_PKEY *pkey, PKCS8_PRIV_KEY_INFO *p8)
    ASN1_INTEGER *privkey = NULL;
    BN_CTX *ctx = NULL;

    STACK_OF(ASN1_TYPE) *ndsa = NULL;
    DSA *dsa = NULL;

    int ret = 0;

    if (!PKCS8_pkey_get0(NULL, &p, &pklen, &palg, p8))
        return 0;
    X509_ALGOR_get0(NULL, &ptype, &pval, palg);

    /* Check for broken DSA PKCS#8, UGH! */
    if (*p == (V_ASN1_SEQUENCE | V_ASN1_CONSTRUCTED)) {
        ASN1_TYPE *t1, *t2;
        if ((ndsa = d2i_ASN1_SEQUENCE_ANY(NULL, &p, pklen)) == NULL)
            goto decerr;
        if (sk_ASN1_TYPE_num(ndsa) != 2)
            goto decerr;
        /*-
         * Handle Two broken types:
         * SEQUENCE {parameters, priv_key}
         * SEQUENCE {pub_key, priv_key}
         */

        t1 = sk_ASN1_TYPE_value(ndsa, 0);
        t2 = sk_ASN1_TYPE_value(ndsa, 1);
        if (t1->type == V_ASN1_SEQUENCE) {
            p8->broken = PKCS8_EMBEDDED_PARAM;
            pval = t1->value.ptr;
        } else if (ptype == V_ASN1_SEQUENCE)
            p8->broken = PKCS8_NS_DB;
        else
            goto decerr;

        if (t2->type != V_ASN1_INTEGER)
            goto decerr;
    q = p;

        privkey = t2->value.integer;
    } else {
        const unsigned char *q = p;
    if ((privkey = d2i_ASN1_INTEGER(NULL, &p, pklen)) == NULL)
        goto decerr;
    if (privkey->type == V_ASN1_NEG_INTEGER) {
@@ -238,7 +212,6 @@ static int dsa_priv_decode(EVP_PKEY *pkey, PKCS8_PRIV_KEY_INFO *p8)
    }
    if (ptype != V_ASN1_SEQUENCE)
        goto decerr;
    }

    pstr = pval;
    pm = pstr->data;
@@ -267,22 +240,18 @@ static int dsa_priv_decode(EVP_PKEY *pkey, PKCS8_PRIV_KEY_INFO *p8)
    }

    EVP_PKEY_assign_DSA(pkey, dsa);
    BN_CTX_free(ctx);
    if (ndsa)
        sk_ASN1_TYPE_pop_free(ndsa, ASN1_TYPE_free);
    else
        ASN1_STRING_clear_free(privkey);

    return 1;
    ret = 1;
    goto done;

 decerr:
    DSAerr(DSA_F_DSA_PRIV_DECODE, DSA_R_DECODE_ERROR);
 dsaerr:
    DSA_free(dsa);
 done:
    BN_CTX_free(ctx);
    ASN1_STRING_clear_free(privkey);
    sk_ASN1_TYPE_pop_free(ndsa, ASN1_TYPE_free);
    DSA_free(dsa);
    return 0;
    return ret;
}

static int dsa_priv_encode(PKCS8_PRIV_KEY_INFO *p8, const EVP_PKEY *pkey)