summaryrefslogtreecommitdiffstats
path: root/crypto
diff options
context:
space:
mode:
authorTomas Mraz <tomas@openssl.org>2021-03-23 16:40:53 +0100
committerTomas Mraz <tomas@openssl.org>2021-03-25 15:24:00 +0100
commit4f0831b837e97504d4cfbfecfca069c527be4a2b (patch)
tree90411cdb7d183a26a30e84f5f5b94add560f7e39 /crypto
parent468d9d556409a53da2c5d16961f9531dd10a6e1b (diff)
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 <levitte@openssl.org> (Merged from https://github.com/openssl/openssl/pull/14659)
Diffstat (limited to 'crypto')
-rw-r--r--crypto/asn1/d2i_pr.c4
-rw-r--r--crypto/evp/evp_pkey.c33
2 files changed, 33 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 <openssl/x509.h>
#include <openssl/rand.h>
#include <openssl/encoder.h>
+#include <openssl/decoder.h>
#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);