Improve the performance of EVP_PKCS82PKEY_ex

We can easily find out the keytype which should significantly improve
the performance of this function because we don't have to try every loaded
decoder.

Partial fix for #20399

Reviewed-by: Dmitry Belyavskiy <beldmit@gmail.com>
Reviewed-by: Richard Levitte <levitte@openssl.org>
Reviewed-by: Tomas Mraz <tomas@openssl.org>
(Merged from https://github.com/openssl/openssl/pull/20412)
This commit is contained in:
Matt Caswell 2023-03-01 11:14:25 +00:00
parent 10836921e5
commit 52ce351a67

View File

@ -15,6 +15,7 @@
#include <openssl/encoder.h> #include <openssl/encoder.h>
#include <openssl/decoder.h> #include <openssl/decoder.h>
#include "internal/provider.h" #include "internal/provider.h"
#include "internal/sizes.h"
#include "crypto/asn1.h" #include "crypto/asn1.h"
#include "crypto/evp.h" #include "crypto/evp.h"
#include "crypto/x509.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; int selection;
size_t len; size_t len;
OSSL_DECODER_CTX *dctx = NULL; 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 if ((encoded_len = i2d_PKCS8_PRIV_KEY_INFO(p8, &encoded_data)) <= 0
|| encoded_data == NULL) || 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; len = encoded_len;
selection = EVP_PKEY_KEYPAIR | EVP_PKEY_KEY_PARAMETERS; selection = EVP_PKEY_KEYPAIR | EVP_PKEY_KEY_PARAMETERS;
dctx = OSSL_DECODER_CTX_new_for_pkey(&pkey, "DER", "PrivateKeyInfo", 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 if (dctx == NULL
|| !OSSL_DECODER_from_data(dctx, &p8_data, &len)) || !OSSL_DECODER_from_data(dctx, &p8_data, &len))
/* try legacy */ /* try legacy */