From: Dr. Stephen Henson Date: Thu, 18 Feb 2016 13:09:24 +0000 (+0000) Subject: Remove broken DSA private key workarounds. X-Git-Tag: OpenSSL_1_1_0-pre4~587 X-Git-Url: https://git.openssl.org/?p=openssl.git;a=commitdiff_plain;h=ab4a81f69ec88d06c9d8de15326b9296d7f498ed 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: Emilia Käsper --- diff --git a/crypto/dsa/dsa_ameth.c b/crypto/dsa/dsa_ameth.c index e76da93b22..459a733b98 100644 --- a/crypto/dsa/dsa_ameth.c +++ b/crypto/dsa/dsa_ameth.c @@ -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,53 +192,26 @@ 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) { - p8->broken = PKCS8_NEG_PRIVKEY; - ASN1_STRING_clear_free(privkey); - if ((privkey = d2i_ASN1_UINTEGER(NULL, &q, pklen)) == NULL) - goto decerr; - } - if (ptype != V_ASN1_SEQUENCE) + if ((privkey = d2i_ASN1_INTEGER(NULL, &p, pklen)) == NULL) + goto decerr; + if (privkey->type == V_ASN1_NEG_INTEGER) { + p8->broken = PKCS8_NEG_PRIVKEY; + ASN1_STRING_clear_free(privkey); + if ((privkey = d2i_ASN1_UINTEGER(NULL, &q, pklen)) == NULL) goto decerr; } + 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)