From: Dmitry Belyavskiy Date: Wed, 28 Apr 2021 18:43:35 +0000 (+0300) Subject: Try to parse private key as PKCS#8 first, fallback afterwards X-Git-Tag: OpenSSL_1_1_1l~87 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=fffb067b468f8e6ffd003b346d7aba558f205c23;p=thirdparty%2Fopenssl.git Try to parse private key as PKCS#8 first, fallback afterwards Fixes #15022 Reviewed-by: Tomas Mraz (Merged from https://github.com/openssl/openssl/pull/15075) --- diff --git a/crypto/asn1/d2i_pr.c b/crypto/asn1/d2i_pr.c index 7b127d2092f..091b6e72162 100644 --- a/crypto/asn1/d2i_pr.c +++ b/crypto/asn1/d2i_pr.c @@ -78,13 +78,53 @@ EVP_PKEY *d2i_PrivateKey(int type, EVP_PKEY **a, const unsigned char **pp, * type */ +static EVP_PKEY *key_as_pkcs8(const unsigned char **pp, long length, int *carry_on) +{ + const unsigned char *p = *pp; + PKCS8_PRIV_KEY_INFO *p8 = d2i_PKCS8_PRIV_KEY_INFO(NULL, &p, length); + EVP_PKEY *ret; + + if (p8 == NULL) + return NULL; + + ret = EVP_PKCS82PKEY(p8); + if (ret == NULL) + *carry_on = 0; + + PKCS8_PRIV_KEY_INFO_free(p8); + + if (ret != NULL) + *pp = p; + + return ret; +} + EVP_PKEY *d2i_AutoPrivateKey(EVP_PKEY **a, const unsigned char **pp, long length) { STACK_OF(ASN1_TYPE) *inkey; const unsigned char *p; int keytype; + EVP_PKEY *ret = NULL; + int carry_on = 1; + + ERR_set_mark(); + ret = key_as_pkcs8(pp, length, &carry_on); + if (ret != NULL) { + ERR_clear_last_mark(); + if (a != NULL) + *a = ret; + return ret; + } + + if (carry_on == 0) { + ERR_clear_last_mark(); + ASN1err(ASN1_F_D2I_AUTOPRIVATEKEY, + ASN1_R_UNSUPPORTED_PUBLIC_KEY_TYPE); + return NULL; + } p = *pp; + /* * Dirty trick: read in the ASN1 data into a STACK_OF(ASN1_TYPE): by * analyzing it we can determine the passed structure: this assumes the @@ -100,28 +140,15 @@ EVP_PKEY *d2i_AutoPrivateKey(EVP_PKEY **a, const unsigned char **pp, keytype = EVP_PKEY_DSA; else if (sk_ASN1_TYPE_num(inkey) == 4) keytype = EVP_PKEY_EC; - else if (sk_ASN1_TYPE_num(inkey) == 3) { /* This seems to be PKCS8, not - * traditional format */ - PKCS8_PRIV_KEY_INFO *p8 = d2i_PKCS8_PRIV_KEY_INFO(NULL, &p, length); - EVP_PKEY *ret; - - sk_ASN1_TYPE_pop_free(inkey, ASN1_TYPE_free); - if (!p8) { - ASN1err(ASN1_F_D2I_AUTOPRIVATEKEY, - ASN1_R_UNSUPPORTED_PUBLIC_KEY_TYPE); - return NULL; - } - ret = EVP_PKCS82PKEY(p8); - PKCS8_PRIV_KEY_INFO_free(p8); - if (ret == NULL) - return NULL; - *pp = p; - if (a) { - *a = ret; - } - return ret; - } else + else keytype = EVP_PKEY_RSA; sk_ASN1_TYPE_pop_free(inkey, ASN1_TYPE_free); - return d2i_PrivateKey(keytype, a, pp, length); + + ret = d2i_PrivateKey(keytype, a, pp, length); + if (ret != NULL) + ERR_pop_to_mark(); + else + ERR_clear_last_mark(); + + return ret; }