diff options
author | Dr. Stephen Henson <steve@openssl.org> | 2016-02-18 13:09:24 +0000 |
---|---|---|
committer | Dr. Stephen Henson <steve@openssl.org> | 2016-02-19 18:54:50 +0000 |
commit | ab4a81f69ec88d06c9d8de15326b9296d7f498ed (patch) | |
tree | 3e1b182ca19cf61f2e2d2f80efa4dd5d7b09523e /crypto/dsa | |
parent | aa474d1fb172aabb29dad04cb6aaeca601a4378c (diff) | |
download | openssl-ab4a81f69ec88d06c9d8de15326b9296d7f498ed.tar.gz |
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 <emilia@openssl.org>
Diffstat (limited to 'crypto/dsa')
-rw-r--r-- | crypto/dsa/dsa_ameth.c | 65 |
1 files changed, 17 insertions, 48 deletions
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) |