diff --git a/crypto/evp/evp_pkey.c b/crypto/evp/evp_pkey.c index 3ec88be67f..97237e01ab 100644 --- a/crypto/evp/evp_pkey.c +++ b/crypto/evp/evp_pkey.c @@ -15,6 +15,7 @@ #include #include #include "internal/provider.h" +#include "internal/sizes.h" #include "crypto/asn1.h" #include "crypto/evp.h" #include "crypto/x509.h" @@ -73,6 +74,13 @@ EVP_PKEY *EVP_PKCS82PKEY_ex(const PKCS8_PRIV_KEY_INFO *p8, OSSL_LIB_CTX *libctx, int selection; size_t len; OSSL_DECODER_CTX *dctx = NULL; + const ASN1_OBJECT *algoid = NULL; + char keytype[OSSL_MAX_NAME_SIZE]; + + if (p8 == NULL + || !PKCS8_pkey_get0(&algoid, NULL, NULL, NULL, p8) + || !OBJ_obj2txt(keytype, sizeof(keytype), algoid, 0)) + return NULL; if ((encoded_len = i2d_PKCS8_PRIV_KEY_INFO(p8, &encoded_data)) <= 0 || encoded_data == NULL) @@ -82,7 +90,20 @@ EVP_PKEY *EVP_PKCS82PKEY_ex(const PKCS8_PRIV_KEY_INFO *p8, OSSL_LIB_CTX *libctx, len = encoded_len; selection = EVP_PKEY_KEYPAIR | EVP_PKEY_KEY_PARAMETERS; dctx = OSSL_DECODER_CTX_new_for_pkey(&pkey, "DER", "PrivateKeyInfo", - NULL, selection, libctx, propq); + keytype, selection, libctx, propq); + + if (dctx != NULL && OSSL_DECODER_CTX_get_num_decoders(dctx) == 0) { + OSSL_DECODER_CTX_free(dctx); + + /* + * This could happen if OBJ_obj2txt() returned a text OID and the + * decoder has not got that OID as an alias. We fall back to a NULL + * keytype + */ + dctx = OSSL_DECODER_CTX_new_for_pkey(&pkey, "DER", "PrivateKeyInfo", + NULL, selection, libctx, propq); + } + if (dctx == NULL || !OSSL_DECODER_from_data(dctx, &p8_data, &len)) /* try legacy */