From d00bd4e452e846a610284fe2be3e9358153251e7 Mon Sep 17 00:00:00 2001 From: Daniel Bevenius Date: Mon, 5 Oct 2020 08:14:29 +0200 Subject: [PATCH] Set mark and pop error in d2i_PrivateKey_ex This commit sets the error mark before calling old_priv_decode and if old_priv_decode returns false, and if EVP_PKCS82PKEY is successful, the errors are popped to the previously set mark. The motivation for this is an issue we found when linking Node.js against OpenSSL 3.0. Details can be found in the link below and the test case provided in this commit attempts cover this. Refs: https://github.com/danbev/learning-libcrypto#asn1-wrong-tag-issue Refs: https://github.com/nodejs/node/issues/29817 Reviewed-by: Matt Caswell Reviewed-by: Tomas Mraz (Merged from https://github.com/openssl/openssl/pull/13073) --- crypto/asn1/d2i_pr.c | 13 +++++++++++-- test/evp_extra_test2.c | 23 +++++++++++++++++++++++ 2 files changed, 34 insertions(+), 2 deletions(-) diff --git a/crypto/asn1/d2i_pr.c b/crypto/asn1/d2i_pr.c index 838ce25b907..b478112349d 100644 --- a/crypto/asn1/d2i_pr.c +++ b/crypto/asn1/d2i_pr.c @@ -45,6 +45,7 @@ EVP_PKEY *d2i_PrivateKey_ex(int type, EVP_PKEY **a, const unsigned char **pp, goto err; } + ERR_set_mark(); if (!ret->ameth->old_priv_decode || !ret->ameth->old_priv_decode(ret, &p, length)) { if (ret->ameth->priv_decode != NULL @@ -52,20 +53,28 @@ EVP_PKEY *d2i_PrivateKey_ex(int type, EVP_PKEY **a, const unsigned char **pp, EVP_PKEY *tmp; PKCS8_PRIV_KEY_INFO *p8 = NULL; p8 = d2i_PKCS8_PRIV_KEY_INFO(NULL, &p, length); - if (p8 == NULL) + if (p8 == NULL) { + ERR_clear_last_mark(); goto err; + } tmp = EVP_PKCS82PKEY_ex(p8, libctx, propq); PKCS8_PRIV_KEY_INFO_free(p8); - if (tmp == NULL) + if (tmp == NULL) { + ERR_clear_last_mark(); goto err; + } EVP_PKEY_free(ret); ret = tmp; + ERR_pop_to_mark(); if (EVP_PKEY_type(type) != EVP_PKEY_base_id(ret)) goto err; } else { + ERR_clear_last_mark(); ASN1err(0, ERR_R_ASN1_LIB); goto err; } + } else { + ERR_clear_last_mark(); } *pp = p; if (a != NULL) diff --git a/test/evp_extra_test2.c b/test/evp_extra_test2.c index 63380f878a1..0667a82647b 100644 --- a/test/evp_extra_test2.c +++ b/test/evp_extra_test2.c @@ -15,6 +15,7 @@ */ #include +#include #include #include "testutil.h" #include "internal/nelem.h" @@ -248,6 +249,27 @@ static int test_alternative_default(void) return ok; } +static int test_d2i_PrivateKey_ex(void) { + int ok; + OSSL_PROVIDER *provider; + BIO *key_bio; + EVP_PKEY* pkey; + ok = 0; + + provider = OSSL_PROVIDER_load(NULL, "default"); + key_bio = BIO_new_mem_buf((&keydata[0])->kder, (&keydata)[0]->size); + + ok = TEST_ptr(pkey = PEM_read_bio_PrivateKey(key_bio, NULL, NULL, NULL)); + TEST_int_eq(ERR_peek_error(), 0); + test_openssl_errors(); + + EVP_PKEY_free(pkey); + BIO_free(key_bio); + OSSL_PROVIDER_unload(provider); + + return ok; +} + int setup_tests(void) { mainctx = OPENSSL_CTX_new(); @@ -264,6 +286,7 @@ int setup_tests(void) ADD_TEST(test_alternative_default); ADD_ALL_TESTS(test_d2i_AutoPrivateKey_ex, OSSL_NELEM(keydata)); + ADD_TEST(test_d2i_PrivateKey_ex); return 1; } -- 2.47.3