The branch master has been updated via 444b25b1e96fa444ffe3a67671796cfc1b599735 (commit) from f16f363a85baa6338744e20671c5a227844f2847 (commit)
- Log ----------------------------------------------------------------- commit 444b25b1e96fa444ffe3a67671796cfc1b599735 Author: Shane Lontis <shane.lon...@oracle.com> Date: Mon Feb 22 13:03:21 2021 +1000 Add back in legacy paths for d2i_PrivateKey/d2i_AutoPrivateKey. Fixes #14263 If the new decoder code fails, it now falls back to the old legacy code and tries that also. Tested manually using gost engine master. Reviewed-by: Richard Levitte <levi...@openssl.org> Reviewed-by: Paul Dale <pa...@openssl.org> Reviewed-by: Dmitry Belyavskiy <beld...@gmail.com> (Merged from https://github.com/openssl/openssl/pull/14266) ----------------------------------------------------------------------- Summary of changes: crypto/asn1/d2i_pr.c | 84 ++++++++++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 79 insertions(+), 5 deletions(-) diff --git a/crypto/asn1/d2i_pr.c b/crypto/asn1/d2i_pr.c index c657f0f3a7..4da5a0c9be 100644 --- a/crypto/asn1/d2i_pr.c +++ b/crypto/asn1/d2i_pr.c @@ -1,5 +1,5 @@ /* - * Copyright 1995-2020 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 1995-2021 The OpenSSL Project Authors. All Rights Reserved. * * Licensed under the Apache License 2.0 (the "License"). You may not use * this file except in compliance with the License. You can obtain a copy @@ -23,9 +23,9 @@ #include "crypto/evp.h" #include "internal/asn1.h" -EVP_PKEY *d2i_PrivateKey_ex(int keytype, EVP_PKEY **a, const unsigned char **pp, - long length, OSSL_LIB_CTX *libctx, - const char *propq) +static EVP_PKEY * +d2i_PrivateKey_decoder(int keytype, EVP_PKEY **a, const unsigned char **pp, + long length, OSSL_LIB_CTX *libctx, const char *propq) { OSSL_DECODER_CTX *dctx = NULL; size_t len = length; @@ -44,6 +44,8 @@ EVP_PKEY *d2i_PrivateKey_ex(int keytype, EVP_PKEY **a, const unsigned char **pp, ppkey = a; for (i = 0; i < (int)OSSL_NELEM(input_structures); ++i) { + const unsigned char *p = *pp; + dctx = OSSL_DECODER_CTX_new_for_pkey(ppkey, "DER", input_structures[i], key_name, EVP_PKEY_KEYPAIR, libctx, propq); @@ -56,6 +58,7 @@ EVP_PKEY *d2i_PrivateKey_ex(int keytype, EVP_PKEY **a, const unsigned char **pp, if (*ppkey != NULL && evp_keymgmt_util_has(*ppkey, OSSL_KEYMGMT_SELECT_PRIVATE_KEY)) return *ppkey; + *pp = p; goto err; } } @@ -132,12 +135,77 @@ EVP_PKEY *evp_privatekey_from_binary(int keytype, EVP_PKEY **a, return NULL; } +EVP_PKEY *d2i_PrivateKey_ex(int keytype, EVP_PKEY **a, const unsigned char **pp, + long length, OSSL_LIB_CTX *libctx, + const char *propq) +{ + EVP_PKEY *ret; + + ret = d2i_PrivateKey_decoder(keytype, a, pp, length, libctx, propq); + /* try the legacy path if the decoder failed */ + if (ret == NULL) + ret = evp_privatekey_from_binary(keytype, a, pp, length, libctx, propq); + return ret; +} + EVP_PKEY *d2i_PrivateKey(int type, EVP_PKEY **a, const unsigned char **pp, long length) { return d2i_PrivateKey_ex(type, a, pp, length, NULL, NULL); } +static EVP_PKEY *d2i_AutoPrivateKey_legacy(EVP_PKEY **a, + const unsigned char **pp, + long length, + OSSL_LIB_CTX *libctx, + const char *propq) +{ + STACK_OF(ASN1_TYPE) *inkey; + const unsigned char *p; + int keytype; + + 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 + * input is surrounded by an ASN1 SEQUENCE. + */ + inkey = d2i_ASN1_SEQUENCE_ANY(NULL, &p, length); + p = *pp; + /* + * Since we only need to discern "traditional format" RSA and DSA keys we + * can just count the elements. + */ + if (sk_ASN1_TYPE_num(inkey) == 6) { + 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 == NULL) { + ERR_raise(ERR_LIB_ASN1, ASN1_R_UNSUPPORTED_PUBLIC_KEY_TYPE); + return NULL; + } + ret = EVP_PKCS82PKEY_ex(p8, libctx, propq); + PKCS8_PRIV_KEY_INFO_free(p8); + if (ret == NULL) + return NULL; + *pp = p; + if (a) { + *a = ret; + } + return ret; + } else { + keytype = EVP_PKEY_RSA; + } + sk_ASN1_TYPE_pop_free(inkey, ASN1_TYPE_free); + return evp_privatekey_from_binary(keytype, a, pp, length, libctx, propq); +} + /* * This works like d2i_PrivateKey() except it passes the keytype as * EVP_PKEY_NONE, which then figures out the type during decoding. @@ -146,7 +214,13 @@ EVP_PKEY *d2i_AutoPrivateKey_ex(EVP_PKEY **a, const unsigned char **pp, long length, OSSL_LIB_CTX *libctx, const char *propq) { - return d2i_PrivateKey_ex(EVP_PKEY_NONE, a, pp, length, libctx, propq); + EVP_PKEY *ret; + + ret = d2i_PrivateKey_decoder(EVP_PKEY_NONE, a, pp, length, libctx, propq); + /* try the legacy path if the decoder failed */ + if (ret == NULL) + ret = d2i_AutoPrivateKey_legacy(a, pp, length, libctx, propq); + return ret; } EVP_PKEY *d2i_AutoPrivateKey(EVP_PKEY **a, const unsigned char **pp,