From 4f0831b837e97504d4cfbfecfca069c527be4a2b Mon Sep 17 00:00:00 2001 From: Tomas Mraz Date: Tue, 23 Mar 2021 16:40:53 +0100 Subject: [PATCH] EVP_PKCS82PKEY: Create provided keys if possible Use OSSL_DECODER to decode the PKCS8 data to create provided keys. If that fails fallback to the legacy implementation. Fixes #14302 Reviewed-by: Richard Levitte (Merged from https://github.com/openssl/openssl/pull/14659) --- crypto/asn1/d2i_pr.c | 4 ++-- crypto/evp/evp_pkey.c | 33 +++++++++++++++++++++++++++++++-- include/crypto/evp.h | 2 ++ test/endecode_test.c | 2 ++ 4 files changed, 37 insertions(+), 4 deletions(-) diff --git a/crypto/asn1/d2i_pr.c b/crypto/asn1/d2i_pr.c index 5d95c9e042..fb0ae08356 100644 --- a/crypto/asn1/d2i_pr.c +++ b/crypto/asn1/d2i_pr.c @@ -106,7 +106,7 @@ d2i_PrivateKey_legacy(int keytype, EVP_PKEY **a, const unsigned char **pp, ERR_clear_last_mark(); goto err; } - tmp = EVP_PKCS82PKEY_ex(p8, libctx, propq); + tmp = evp_pkcs82pkey_legacy(p8, libctx, propq); PKCS8_PRIV_KEY_INFO_free(p8); if (tmp == NULL) { ERR_clear_last_mark(); @@ -190,7 +190,7 @@ static EVP_PKEY *d2i_AutoPrivateKey_legacy(EVP_PKEY **a, ERR_raise(ERR_LIB_ASN1, ASN1_R_UNSUPPORTED_PUBLIC_KEY_TYPE); return NULL; } - ret = EVP_PKCS82PKEY_ex(p8, libctx, propq); + ret = evp_pkcs82pkey_legacy(p8, libctx, propq); PKCS8_PRIV_KEY_INFO_free(p8); if (ret == NULL) return NULL; diff --git a/crypto/evp/evp_pkey.c b/crypto/evp/evp_pkey.c index 9879392114..7aafd76822 100644 --- a/crypto/evp/evp_pkey.c +++ b/crypto/evp/evp_pkey.c @@ -13,6 +13,7 @@ #include #include #include +#include #include "internal/provider.h" #include "crypto/asn1.h" #include "crypto/evp.h" @@ -20,8 +21,8 @@ /* Extract a private key from a PKCS8 structure */ -EVP_PKEY *EVP_PKCS82PKEY_ex(const PKCS8_PRIV_KEY_INFO *p8, OSSL_LIB_CTX *libctx, - const char *propq) +EVP_PKEY *evp_pkcs82pkey_legacy(const PKCS8_PRIV_KEY_INFO *p8, OSSL_LIB_CTX *libctx, + const char *propq) { EVP_PKEY *pkey = NULL; const ASN1_OBJECT *algoid; @@ -62,6 +63,34 @@ EVP_PKEY *EVP_PKCS82PKEY_ex(const PKCS8_PRIV_KEY_INFO *p8, OSSL_LIB_CTX *libctx, return NULL; } +EVP_PKEY *EVP_PKCS82PKEY_ex(const PKCS8_PRIV_KEY_INFO *p8, OSSL_LIB_CTX *libctx, + const char *propq) +{ + EVP_PKEY *pkey = NULL; + const unsigned char *p8_data = NULL; + unsigned char *encoded_data = NULL; + int encoded_len; + size_t len; + OSSL_DECODER_CTX *dctx = NULL; + + if ((encoded_len = i2d_PKCS8_PRIV_KEY_INFO(p8, &encoded_data)) <= 0) + goto end; + + p8_data = encoded_data; + len = encoded_len; + dctx = OSSL_DECODER_CTX_new_for_pkey(&pkey, "DER", "pkcs8", EVP_PKEY_NONE, + 0, libctx, propq); + if (dctx == NULL + || !OSSL_DECODER_from_data(dctx, &p8_data, &len)) + /* try legacy */ + pkey = evp_pkcs82pkey_legacy(p8, libctx, propq); + + end: + OPENSSL_clear_free(encoded_data, encoded_len); + OSSL_DECODER_CTX_free(dctx); + return pkey; +} + EVP_PKEY *EVP_PKCS82PKEY(const PKCS8_PRIV_KEY_INFO *p8) { return EVP_PKCS82PKEY_ex(p8, NULL, NULL); diff --git a/include/crypto/evp.h b/include/crypto/evp.h index 18c50cdd33..2089b8b913 100644 --- a/include/crypto/evp.h +++ b/include/crypto/evp.h @@ -727,6 +727,8 @@ void *evp_pkey_export_to_provider(EVP_PKEY *pk, OSSL_LIB_CTX *libctx, int evp_pkey_copy_downgraded(EVP_PKEY **dest, const EVP_PKEY *src); void *evp_pkey_get_legacy(EVP_PKEY *pk); void evp_pkey_free_legacy(EVP_PKEY *x); +EVP_PKEY *evp_pkcs82pkey_legacy(const PKCS8_PRIV_KEY_INFO *p8inf, + OSSL_LIB_CTX *libctx, const char *propq); #endif /* diff --git a/test/endecode_test.c b/test/endecode_test.c index 50b33ce057..ab4b631a8f 100644 --- a/test/endecode_test.c +++ b/test/endecode_test.c @@ -21,6 +21,7 @@ #include "internal/cryptlib.h" /* ossl_assert */ #include "crypto/pem.h" /* For PVK and "blob" PEM headers */ +#include "crypto/evp.h" /* For evp_pkey_is_provided() */ #include "helpers/predefined_dhparams.h" #include "testutil.h" @@ -498,6 +499,7 @@ static int check_unprotected_PKCS8_DER(const char *file, const int line, TEST_note("%s isn't any of %s", type, namelist); OPENSSL_free(namelist); } + ok = ok && TEST_FL_true(evp_pkey_is_provided(pkey)); EVP_PKEY_free(pkey); } } -- 2.34.1