]> git.ipfire.org Git - thirdparty/openssl.git/commitdiff
PROV: Add type specific PKCS#8 decoding to the DER->key decoders
authorRichard Levitte <levitte@openssl.org>
Thu, 18 Mar 2021 09:41:53 +0000 (10:41 +0100)
committerRichard Levitte <levitte@openssl.org>
Fri, 19 Mar 2021 15:46:39 +0000 (16:46 +0100)
This required refactoring a number of functions from the diverse
EVP_PKEY_ASN1_METHOD implementations to become shared backend
functions.  It also meant modifying a few of them to return pointers
to our internal RSA / DSA/ DH / EC_KEY, ... structures instead of
manipulating an EVP_PKEY pointer directly, letting the caller do the
latter.

Reviewed-by: Tomas Mraz <tomas@openssl.org>
(Merged from https://github.com/openssl/openssl/pull/14314)

19 files changed:
crypto/dh/dh_ameth.c
crypto/dh/dh_backend.c
crypto/dsa/dsa_ameth.c
crypto/dsa/dsa_backend.c
crypto/ec/ec_ameth.c
crypto/ec/ec_backend.c
crypto/ec/ecx_backend.c
crypto/ec/ecx_meth.c
crypto/rsa/rsa_ameth.c
crypto/rsa/rsa_backend.c
crypto/rsa/rsa_lib.c
include/crypto/dh.h
include/crypto/dsa.h
include/crypto/ec.h
include/crypto/ecx.h
include/crypto/rsa.h
include/crypto/types.h
include/crypto/x509.h
providers/implementations/encode_decode/decode_der2key.c

index 08656877f3dd520f7f98d000bb54128b73e988c9..ffaf41d8022bb8d987fcc933cb28694e11face0d 100644 (file)
@@ -163,53 +163,15 @@ static int dh_pub_encode(X509_PUBKEY *pk, const EVP_PKEY *pkey)
 
 static int dh_priv_decode(EVP_PKEY *pkey, const PKCS8_PRIV_KEY_INFO *p8)
 {
-    const unsigned char *p, *pm;
-    int pklen, pmlen;
-    int ptype;
-    const void *pval;
-    const ASN1_STRING *pstr;
-    const X509_ALGOR *palg;
-    ASN1_INTEGER *privkey = NULL;
-    DH *dh = NULL;
-
-    if (!PKCS8_pkey_get0(NULL, &p, &pklen, &palg, p8))
-        return 0;
-
-    X509_ALGOR_get0(NULL, &ptype, &pval, palg);
-
-    if (ptype != V_ASN1_SEQUENCE)
-        goto decerr;
-    if ((privkey = d2i_ASN1_INTEGER(NULL, &p, pklen)) == NULL)
-        goto decerr;
-
-    pstr = pval;
-    pm = pstr->data;
-    pmlen = pstr->length;
-    if ((dh = d2i_dhp(pkey, &pm, pmlen)) == NULL)
-        goto decerr;
+    int ret = 0;
+    DH *dh = ossl_dh_key_from_pkcs8(p8, NULL, NULL);
 
-    /* We have parameters now set private key */
-    if ((dh->priv_key = BN_secure_new()) == NULL
-        || !ASN1_INTEGER_to_BN(privkey, dh->priv_key)) {
-        ERR_raise(ERR_LIB_DH, DH_R_BN_ERROR);
-        goto dherr;
+    if (dh != NULL) {
+        ret = 1;
+        EVP_PKEY_assign(pkey, pkey->ameth->pkey_id, dh);
     }
-    /* Calculate public key, increments dirty_cnt */
-    if (!DH_generate_key(dh))
-        goto dherr;
-
-    EVP_PKEY_assign(pkey, pkey->ameth->pkey_id, dh);
 
-    ASN1_STRING_clear_free(privkey);
-
-    return 1;
-
- decerr:
-    ERR_raise(ERR_LIB_DH, EVP_R_DECODE_ERROR);
- dherr:
-    DH_free(dh);
-    ASN1_STRING_clear_free(privkey);
-    return 0;
+    return ret;
 }
 
 static int dh_priv_encode(PKCS8_PRIV_KEY_INFO *p8, const EVP_PKEY *pkey)
index c848cb4870185fdf2f4dd40e8a6faa0a9106587f..8da830f9d8efb01132501a930f4d232833bc9146 100644 (file)
@@ -13,6 +13,7 @@
  */
 #include "internal/deprecated.h"
 
+#include <openssl/err.h>
 #include <openssl/core_names.h>
 #include "internal/param_build_set.h"
 #include "crypto/dh.h"
@@ -115,3 +116,68 @@ int ossl_dh_key_todata(DH *dh, OSSL_PARAM_BLD *bld, OSSL_PARAM params[])
 
     return 1;
 }
+
+#ifndef FIPS_MODULE
+DH *ossl_dh_key_from_pkcs8(const PKCS8_PRIV_KEY_INFO *p8inf,
+                           OSSL_LIB_CTX *libctx, const char *propq)
+{
+    const unsigned char *p, *pm;
+    int pklen, pmlen;
+    int ptype;
+    const void *pval;
+    const ASN1_STRING *pstr;
+    const X509_ALGOR *palg;
+    BIGNUM *privkey_bn = NULL;
+    ASN1_INTEGER *privkey = NULL;
+    DH *dh = NULL;
+
+    if (!PKCS8_pkey_get0(NULL, &p, &pklen, &palg, p8inf))
+        return 0;
+
+    X509_ALGOR_get0(NULL, &ptype, &pval, palg);
+
+    if (ptype != V_ASN1_SEQUENCE)
+        goto decerr;
+    if ((privkey = d2i_ASN1_INTEGER(NULL, &p, pklen)) == NULL)
+        goto decerr;
+
+    pstr = pval;
+    pm = pstr->data;
+    pmlen = pstr->length;
+    switch (OBJ_obj2nid(palg->algorithm)) {
+    case NID_dhKeyAgreement:
+        dh = d2i_DHparams(NULL, &pm, pmlen);
+        break;
+    case NID_dhpublicnumber:
+        dh = d2i_DHxparams(NULL, &pm, pmlen);
+        break;
+    default:
+        goto decerr;
+    }
+    if (dh == NULL)
+        goto decerr;
+
+    /* We have parameters now set private key */
+    if ((privkey_bn = BN_secure_new()) == NULL
+        || !ASN1_INTEGER_to_BN(privkey, privkey_bn)) {
+        ERR_raise(ERR_LIB_DH, DH_R_BN_ERROR);
+        goto dherr;
+    }
+    if (!DH_set0_key(dh, NULL, privkey_bn))
+        goto dherr;
+    /* Calculate public key, increments dirty_cnt */
+    if (!DH_generate_key(dh))
+        goto dherr;
+
+    goto done;
+
+ decerr:
+    ERR_raise(ERR_LIB_DH, EVP_R_DECODE_ERROR);
+ dherr:
+    DH_free(dh);
+    dh = NULL;
+ done:
+    ASN1_STRING_clear_free(privkey);
+    return dh;
+}
+#endif
index 50ecd3ed3b9ca9e682f64f810f882fdd404ba49e..e4c739daf91ec51995eb11be0898282520fd27fb 100644 (file)
@@ -149,69 +149,14 @@ static int dsa_pub_encode(X509_PUBKEY *pk, const EVP_PKEY *pkey)
 
 static int dsa_priv_decode(EVP_PKEY *pkey, const PKCS8_PRIV_KEY_INFO *p8)
 {
-    const unsigned char *p, *pm;
-    int pklen, pmlen;
-    int ptype;
-    const void *pval;
-    const ASN1_STRING *pstr;
-    const X509_ALGOR *palg;
-    ASN1_INTEGER *privkey = NULL;
-    BN_CTX *ctx = NULL;
-
-    DSA *dsa = NULL;
-
     int ret = 0;
+    DSA *dsa = ossl_dsa_key_from_pkcs8(p8, NULL, NULL);
 
-    if (!PKCS8_pkey_get0(NULL, &p, &pklen, &palg, p8))
-        return 0;
-    X509_ALGOR_get0(NULL, &ptype, &pval, palg);
-
-    if ((privkey = d2i_ASN1_INTEGER(NULL, &p, pklen)) == NULL)
-        goto decerr;
-    if (privkey->type == V_ASN1_NEG_INTEGER || ptype != V_ASN1_SEQUENCE)
-        goto decerr;
-
-    pstr = pval;
-    pm = pstr->data;
-    pmlen = pstr->length;
-    if ((dsa = d2i_DSAparams(NULL, &pm, pmlen)) == NULL)
-        goto decerr;
-    /* We have parameters now set private key */
-    if ((dsa->priv_key = BN_secure_new()) == NULL
-        || !ASN1_INTEGER_to_BN(privkey, dsa->priv_key)) {
-        ERR_raise(ERR_LIB_DSA, DSA_R_BN_ERROR);
-        goto dsaerr;
-    }
-    /* Calculate public key */
-    if ((dsa->pub_key = BN_new()) == NULL) {
-        ERR_raise(ERR_LIB_DSA, ERR_R_MALLOC_FAILURE);
-        goto dsaerr;
-    }
-    if ((ctx = BN_CTX_new()) == NULL) {
-        ERR_raise(ERR_LIB_DSA, ERR_R_MALLOC_FAILURE);
-        goto dsaerr;
-    }
-
-    BN_set_flags(dsa->priv_key, BN_FLG_CONSTTIME);
-    if (!BN_mod_exp(dsa->pub_key, dsa->params.g, dsa->priv_key, dsa->params.p,
-                    ctx)) {
-        ERR_raise(ERR_LIB_DSA, DSA_R_BN_ERROR);
-        goto dsaerr;
+    if (dsa != NULL) {
+        ret = 1;
+        EVP_PKEY_assign_DSA(pkey, dsa);
     }
 
-    dsa->dirty_cnt++;
-    EVP_PKEY_assign_DSA(pkey, dsa);
-
-    ret = 1;
-    goto done;
-
- decerr:
-    ERR_raise(ERR_LIB_DSA, DSA_R_DECODE_ERROR);
- dsaerr:
-    DSA_free(dsa);
- done:
-    BN_CTX_free(ctx);
-    ASN1_STRING_clear_free(privkey);
     return ret;
 }
 
index e6f8f3645ed02ac1b6895e9567293a5adfb23b5a..f3e54aeb131b0d922419bf6cc58c5c5ebcdc957e 100644 (file)
@@ -14,6 +14,7 @@
 #include "internal/deprecated.h"
 
 #include <openssl/core_names.h>
+#include <openssl/err.h>
 #include "crypto/dsa.h"
 
 /*
@@ -54,3 +55,75 @@ int ossl_dsa_key_fromdata(DSA *dsa, const OSSL_PARAM params[])
     BN_free(pub_key);
     return 0;
 }
+
+#ifndef FIPS_MODULE
+DSA *ossl_dsa_key_from_pkcs8(const PKCS8_PRIV_KEY_INFO *p8inf,
+                             OSSL_LIB_CTX *libctx, const char *propq)
+{
+    const unsigned char *p, *pm;
+    int pklen, pmlen;
+    int ptype;
+    const void *pval;
+    const ASN1_STRING *pstr;
+    const X509_ALGOR *palg;
+    ASN1_INTEGER *privkey = NULL;
+    const BIGNUM *dsa_p, *dsa_g;
+    BIGNUM *dsa_pubkey = NULL, *dsa_privkey = NULL;
+    BN_CTX *ctx = NULL;
+
+    DSA *dsa = NULL;
+
+    if (!PKCS8_pkey_get0(NULL, &p, &pklen, &palg, p8inf))
+        return 0;
+    X509_ALGOR_get0(NULL, &ptype, &pval, palg);
+
+    if ((privkey = d2i_ASN1_INTEGER(NULL, &p, pklen)) == NULL)
+        goto decerr;
+    if (privkey->type == V_ASN1_NEG_INTEGER || ptype != V_ASN1_SEQUENCE)
+        goto decerr;
+
+    pstr = pval;
+    pm = pstr->data;
+    pmlen = pstr->length;
+    if ((dsa = d2i_DSAparams(NULL, &pm, pmlen)) == NULL)
+        goto decerr;
+    /* We have parameters now set private key */
+    if ((dsa_privkey = BN_secure_new()) == NULL
+        || !ASN1_INTEGER_to_BN(privkey, dsa_privkey)) {
+        ERR_raise(ERR_LIB_DSA, DSA_R_BN_ERROR);
+        goto dsaerr;
+    }
+    /* Calculate public key */
+    if ((dsa_pubkey = BN_new()) == NULL) {
+        ERR_raise(ERR_LIB_DSA, ERR_R_MALLOC_FAILURE);
+        goto dsaerr;
+    }
+    if ((ctx = BN_CTX_new()) == NULL) {
+        ERR_raise(ERR_LIB_DSA, ERR_R_MALLOC_FAILURE);
+        goto dsaerr;
+    }
+
+    dsa_p = DSA_get0_p(dsa);
+    dsa_g = DSA_get0_g(dsa);
+    BN_set_flags(dsa_privkey, BN_FLG_CONSTTIME);
+    if (!BN_mod_exp(dsa_pubkey, dsa_g, dsa_privkey, dsa_p, ctx)) {
+        ERR_raise(ERR_LIB_DSA, DSA_R_BN_ERROR);
+        goto dsaerr;
+    }
+    DSA_set0_key(dsa, dsa_pubkey, dsa_privkey);
+
+    goto done;
+
+ decerr:
+    ERR_raise(ERR_LIB_DSA, DSA_R_DECODE_ERROR);
+ dsaerr:
+    BN_free(dsa_privkey);
+    BN_free(dsa_pubkey);
+    DSA_free(dsa);
+    dsa = NULL;
+ done:
+    BN_CTX_free(ctx);
+    ASN1_STRING_clear_free(privkey);
+    return dsa;
+}
+#endif
index d447fa4d1c6df055125fca9bb1afd2b315e8fb70..69370d6bc19749bf653abb2ef460bfc8aef1972c 100644 (file)
@@ -100,59 +100,10 @@ static int eckey_pub_encode(X509_PUBKEY *pk, const EVP_PKEY *pkey)
     return 0;
 }
 
-static EC_KEY *eckey_type2param(int ptype, const void *pval,
-                                OSSL_LIB_CTX *libctx, const char *propq)
-{
-    EC_KEY *eckey = NULL;
-    EC_GROUP *group = NULL;
-
-    if ((eckey = EC_KEY_new_ex(libctx, propq)) == NULL) {
-        ERR_raise(ERR_LIB_EC, ERR_R_MALLOC_FAILURE);
-        goto ecerr;
-    }
-
-    if (ptype == V_ASN1_SEQUENCE) {
-        const ASN1_STRING *pstr = pval;
-        const unsigned char *pm = pstr->data;
-        int pmlen = pstr->length;
-
-
-        if (d2i_ECParameters(&eckey, &pm, pmlen) == NULL) {
-            ERR_raise(ERR_LIB_EC, EC_R_DECODE_ERROR);
-            goto ecerr;
-        }
-    } else if (ptype == V_ASN1_OBJECT) {
-        const ASN1_OBJECT *poid = pval;
-
-        /*
-         * type == V_ASN1_OBJECT => the parameters are given by an asn1 OID
-         */
-
-        group = EC_GROUP_new_by_curve_name_ex(libctx, propq, OBJ_obj2nid(poid));
-        if (group == NULL)
-            goto ecerr;
-        EC_GROUP_set_asn1_flag(group, OPENSSL_EC_NAMED_CURVE);
-        if (EC_KEY_set_group(eckey, group) == 0)
-            goto ecerr;
-        EC_GROUP_free(group);
-    } else {
-        ERR_raise(ERR_LIB_EC, EC_R_DECODE_ERROR);
-        goto ecerr;
-    }
-
-    return eckey;
-
- ecerr:
-    EC_KEY_free(eckey);
-    EC_GROUP_free(group);
-    return NULL;
-}
-
 static int eckey_pub_decode(EVP_PKEY *pkey, const X509_PUBKEY *pubkey)
 {
     const unsigned char *p = NULL;
-    const void *pval;
-    int ptype, pklen;
+    int pklen;
     EC_KEY *eckey = NULL;
     X509_ALGOR *palg;
     OSSL_LIB_CTX *libctx = NULL;
@@ -161,9 +112,7 @@ static int eckey_pub_decode(EVP_PKEY *pkey, const X509_PUBKEY *pubkey)
     if (!ossl_x509_PUBKEY_get0_libctx(&libctx, &propq, pubkey)
         || !X509_PUBKEY_get0_param(NULL, &p, &pklen, &palg, pubkey))
         return 0;
-    X509_ALGOR_get0(NULL, &ptype, &pval, palg);
-
-    eckey = eckey_type2param(ptype, pval, libctx, propq);
+    eckey = ossl_ec_key_param_from_x509_algor(palg, libctx, propq);
 
     if (!eckey)
         return 0;
@@ -202,32 +151,15 @@ static int eckey_pub_cmp(const EVP_PKEY *a, const EVP_PKEY *b)
 static int eckey_priv_decode_ex(EVP_PKEY *pkey, const PKCS8_PRIV_KEY_INFO *p8,
                                 OSSL_LIB_CTX *libctx, const char *propq)
 {
-    const unsigned char *p = NULL;
-    const void *pval;
-    int ptype, pklen;
-    EC_KEY *eckey = NULL;
-    const X509_ALGOR *palg;
-
-    if (!PKCS8_pkey_get0(NULL, &p, &pklen, &palg, p8))
-        return 0;
-    X509_ALGOR_get0(NULL, &ptype, &pval, palg);
-
-    eckey = eckey_type2param(ptype, pval, libctx, propq);
-    if (eckey == NULL)
-        goto err;
+    int ret = 0;
+    EC_KEY *eckey = ossl_ec_key_from_pkcs8(p8, libctx, propq);
 
-    /* We have parameters now set private key */
-    if (!d2i_ECPrivateKey(&eckey, &p, pklen)) {
-        ERR_raise(ERR_LIB_EC, EC_R_DECODE_ERROR);
-        goto err;
+    if (eckey != NULL) {
+        ret = 1;
+        EVP_PKEY_assign_EC_KEY(pkey, eckey);
     }
 
-    EVP_PKEY_assign_EC_KEY(pkey, eckey);
-    return 1;
-
- err:
-    EC_KEY_free(eckey);
-    return 0;
+    return ret;
 }
 
 static int eckey_priv_encode(PKCS8_PRIV_KEY_INFO *p8, const EVP_PKEY *pkey)
index c4a5a81fdafacc10e6df3737d5ed793c0df09add..9716ffc2f265e0782eb6bd8dea30939baa508d63 100644 (file)
@@ -570,3 +570,82 @@ int ossl_ec_pt_format_param2id(const OSSL_PARAM *p, int *id)
     }
     return 0;
 }
+
+#ifndef FIPS_MODULE
+EC_KEY *ossl_ec_key_param_from_x509_algor(const X509_ALGOR *palg,
+                                     OSSL_LIB_CTX *libctx, const char *propq)
+{
+    int ptype = 0;
+    const void *pval = NULL;
+    EC_KEY *eckey = NULL;
+    EC_GROUP *group = NULL;
+
+    X509_ALGOR_get0(NULL, &ptype, &pval, palg);
+    if ((eckey = EC_KEY_new_ex(libctx, propq)) == NULL) {
+        ERR_raise(ERR_LIB_EC, ERR_R_MALLOC_FAILURE);
+        goto ecerr;
+    }
+
+    if (ptype == V_ASN1_SEQUENCE) {
+        const ASN1_STRING *pstr = pval;
+        const unsigned char *pm = pstr->data;
+        int pmlen = pstr->length;
+
+
+        if (d2i_ECParameters(&eckey, &pm, pmlen) == NULL) {
+            ERR_raise(ERR_LIB_EC, EC_R_DECODE_ERROR);
+            goto ecerr;
+        }
+    } else if (ptype == V_ASN1_OBJECT) {
+        const ASN1_OBJECT *poid = pval;
+
+        /*
+         * type == V_ASN1_OBJECT => the parameters are given by an asn1 OID
+         */
+
+        group = EC_GROUP_new_by_curve_name_ex(libctx, propq, OBJ_obj2nid(poid));
+        if (group == NULL)
+            goto ecerr;
+        EC_GROUP_set_asn1_flag(group, OPENSSL_EC_NAMED_CURVE);
+        if (EC_KEY_set_group(eckey, group) == 0)
+            goto ecerr;
+        EC_GROUP_free(group);
+    } else {
+        ERR_raise(ERR_LIB_EC, EC_R_DECODE_ERROR);
+        goto ecerr;
+    }
+
+    return eckey;
+
+ ecerr:
+    EC_KEY_free(eckey);
+    EC_GROUP_free(group);
+    return NULL;
+}
+
+EC_KEY *ossl_ec_key_from_pkcs8(const PKCS8_PRIV_KEY_INFO *p8inf,
+                               OSSL_LIB_CTX *libctx, const char *propq)
+{
+    const unsigned char *p = NULL;
+    int pklen;
+    EC_KEY *eckey = NULL;
+    const X509_ALGOR *palg;
+
+    if (!PKCS8_pkey_get0(NULL, &p, &pklen, &palg, p8inf))
+        return 0;
+    eckey = ossl_ec_key_param_from_x509_algor(palg, libctx, propq);
+    if (eckey == NULL)
+        goto err;
+
+    /* We have parameters now set private key */
+    if (!d2i_ECPrivateKey(&eckey, &p, pklen)) {
+        ERR_raise(ERR_LIB_EC, EC_R_DECODE_ERROR);
+        goto err;
+    }
+
+    return eckey;
+ err:
+    EC_KEY_free(eckey);
+    return NULL;
+}
+#endif
index 17dd507c35cb4b40b3abd32279dc2c2bc92e2e46..8f8fdc7705b8ff16bc94d4fce96528cc87436967 100644 (file)
@@ -7,9 +7,11 @@
  * https://www.openssl.org/source/license.html
  */
 
+#include <string.h>
 #include <openssl/core_names.h>
 #include <openssl/params.h>
 #include <openssl/ec.h>
+#include <openssl/rand.h>
 #include <openssl/err.h>
 #include "crypto/ecx.h"
 #include "ecx_backend.h"
@@ -90,3 +92,110 @@ int ossl_ecx_key_fromdata(ECX_KEY *ecx, const OSSL_PARAM params[],
     return 1;
 }
 
+#ifndef FIPS_MODULE
+ECX_KEY *ossl_ecx_key_op(const X509_ALGOR *palg,
+                         const unsigned char *p, int plen,
+                         int id, ecx_key_op_t op,
+                         OSSL_LIB_CTX *libctx, const char *propq)
+{
+    ECX_KEY *key = NULL;
+    unsigned char *privkey, *pubkey;
+
+    if (op != KEY_OP_KEYGEN) {
+        if (palg != NULL) {
+            int ptype;
+
+            /* Algorithm parameters must be absent */
+            X509_ALGOR_get0(NULL, &ptype, NULL, palg);
+            if (ptype != V_ASN1_UNDEF) {
+                ERR_raise(ERR_LIB_EC, EC_R_INVALID_ENCODING);
+                return 0;
+            }
+            if (id == EVP_PKEY_NONE)
+                id = OBJ_obj2nid(palg->algorithm);
+            else if (id != OBJ_obj2nid(palg->algorithm)) {
+                ERR_raise(ERR_LIB_EC, EC_R_INVALID_ENCODING);
+                return 0;
+            }
+        }
+
+        if (p == NULL || id == EVP_PKEY_NONE || plen != KEYLENID(id)) {
+            ERR_raise(ERR_LIB_EC, EC_R_INVALID_ENCODING);
+            return 0;
+        }
+    }
+
+    key = ossl_ecx_key_new(libctx, KEYNID2TYPE(id), 1, propq);
+    if (key == NULL) {
+        ERR_raise(ERR_LIB_EC, ERR_R_MALLOC_FAILURE);
+        return 0;
+    }
+    pubkey = key->pubkey;
+
+    if (op == KEY_OP_PUBLIC) {
+        memcpy(pubkey, p, plen);
+    } else {
+        privkey = ossl_ecx_key_allocate_privkey(key);
+        if (privkey == NULL) {
+            ERR_raise(ERR_LIB_EC, ERR_R_MALLOC_FAILURE);
+            goto err;
+        }
+        if (op == KEY_OP_KEYGEN) {
+            if (id != EVP_PKEY_NONE) {
+                if (RAND_priv_bytes_ex(libctx, privkey, KEYLENID(id)) <= 0)
+                    goto err;
+                if (id == EVP_PKEY_X25519) {
+                    privkey[0] &= 248;
+                    privkey[X25519_KEYLEN - 1] &= 127;
+                    privkey[X25519_KEYLEN - 1] |= 64;
+                } else if (id == EVP_PKEY_X448) {
+                    privkey[0] &= 252;
+                    privkey[X448_KEYLEN - 1] |= 128;
+                }
+            }
+        } else {
+            memcpy(privkey, p, KEYLENID(id));
+        }
+        if (!ossl_ecx_public_from_private(key)) {
+            ERR_raise(ERR_LIB_EC, EC_R_FAILED_MAKING_PUBLIC_KEY);
+            goto err;
+        }
+    }
+
+    return key;
+ err:
+    ossl_ecx_key_free(key);
+    return NULL;
+}
+
+ECX_KEY *ossl_ecx_key_from_pkcs8(const PKCS8_PRIV_KEY_INFO *p8inf,
+                                 OSSL_LIB_CTX *libctx, const char *propq)
+{
+    ECX_KEY *ecx = NULL;
+    const unsigned char *p;
+    int plen;
+    ASN1_OCTET_STRING *oct = NULL;
+    const X509_ALGOR *palg;
+
+    if (!PKCS8_pkey_get0(NULL, &p, &plen, &palg, p8inf))
+        return 0;
+
+    oct = d2i_ASN1_OCTET_STRING(NULL, &p, plen);
+    if (oct == NULL) {
+        p = NULL;
+        plen = 0;
+    } else {
+        p = ASN1_STRING_get0_data(oct);
+        plen = ASN1_STRING_length(oct);
+    }
+
+    /*
+     * EVP_PKEY_NONE means that ecx_key_op() has to figure out the key type
+     * on its own.
+     */
+    ecx = ossl_ecx_key_op(palg, p, plen, EVP_PKEY_NONE, KEY_OP_PRIVATE,
+                          libctx, propq);
+    ASN1_OCTET_STRING_free(oct);
+    return ecx;
+}
+#endif
index 68f943fc82104eec3c480bee774e3bebea5ede41..d476af0e3c42efd6eb9c230f5560c472db326928 100644 (file)
@@ -16,7 +16,6 @@
 #include <stdio.h>
 #include <openssl/x509.h>
 #include <openssl/ec.h>
-#include <openssl/rand.h>
 #include <openssl/core_names.h>
 #include <openssl/param_build.h>
 #include "internal/cryptlib.h"
 #include "curve448/curve448_local.h"
 #include "ecx_backend.h"
 
-typedef enum {
-    KEY_OP_PUBLIC,
-    KEY_OP_PRIVATE,
-    KEY_OP_KEYGEN
-} ecx_key_op_t;
-
-/* Setup EVP_PKEY using public, private or generation */
-static int ecx_key_op(EVP_PKEY *pkey, int id, const X509_ALGOR *palg,
-                      const unsigned char *p, int plen, ecx_key_op_t op,
-                      OSSL_LIB_CTX *libctx, const char *propq)
-{
-    ECX_KEY *key = NULL;
-    unsigned char *privkey, *pubkey;
-
-    if (op != KEY_OP_KEYGEN) {
-        if (palg != NULL) {
-            int ptype;
-
-            /* Algorithm parameters must be absent */
-            X509_ALGOR_get0(NULL, &ptype, NULL, palg);
-            if (ptype != V_ASN1_UNDEF) {
-                ERR_raise(ERR_LIB_EC, EC_R_INVALID_ENCODING);
-                return 0;
-            }
-        }
-
-        if (p == NULL || plen != KEYLENID(id)) {
-            ERR_raise(ERR_LIB_EC, EC_R_INVALID_ENCODING);
-            return 0;
-        }
-    }
-
-    key = ossl_ecx_key_new(libctx, KEYNID2TYPE(id), 1, propq);
-    if (key == NULL) {
-        ERR_raise(ERR_LIB_EC, ERR_R_MALLOC_FAILURE);
-        return 0;
-    }
-    pubkey = key->pubkey;
-
-    if (op == KEY_OP_PUBLIC) {
-        memcpy(pubkey, p, plen);
-    } else {
-        privkey = ossl_ecx_key_allocate_privkey(key);
-        if (privkey == NULL) {
-            ERR_raise(ERR_LIB_EC, ERR_R_MALLOC_FAILURE);
-            goto err;
-        }
-        if (op == KEY_OP_KEYGEN) {
-            if (RAND_priv_bytes_ex(libctx, privkey, KEYLENID(id)) <= 0)
-                goto err;
-            if (id == EVP_PKEY_X25519) {
-                privkey[0] &= 248;
-                privkey[X25519_KEYLEN - 1] &= 127;
-                privkey[X25519_KEYLEN - 1] |= 64;
-            } else if (id == EVP_PKEY_X448) {
-                privkey[0] &= 252;
-                privkey[X448_KEYLEN - 1] |= 128;
-            }
-        } else {
-            memcpy(privkey, p, KEYLENID(id));
-        }
-        if (!ossl_ecx_public_from_private(key)) {
-            ERR_raise(ERR_LIB_EC, EC_R_FAILED_MAKING_PUBLIC_KEY);
-            goto err;
-        }
-    }
-
-    EVP_PKEY_assign(pkey, id, key);
-    return 1;
- err:
-    ossl_ecx_key_free(key);
-    return 0;
-}
-
 static int ecx_pub_encode(X509_PUBKEY *pk, const EVP_PKEY *pkey)
 {
     const ECX_KEY *ecxkey = pkey->pkey.ecx;
@@ -132,11 +57,18 @@ static int ecx_pub_decode(EVP_PKEY *pkey, const X509_PUBKEY *pubkey)
     const unsigned char *p;
     int pklen;
     X509_ALGOR *palg;
+    ECX_KEY *ecx;
+    int ret = 0;
 
     if (!X509_PUBKEY_get0_param(NULL, &p, &pklen, &palg, pubkey))
         return 0;
-    return ecx_key_op(pkey, pkey->ameth->pkey_id, palg, p, pklen,
-                      KEY_OP_PUBLIC, NULL, NULL);
+    ecx = ossl_ecx_key_op(palg, p, pklen, pkey->ameth->pkey_id,
+                          KEY_OP_PUBLIC, NULL, NULL);
+    if (ecx != NULL) {
+        ret = 1;
+        EVP_PKEY_assign(pkey, pkey->ameth->pkey_id, ecx);
+    }
+    return ret;
 }
 
 static int ecx_pub_cmp(const EVP_PKEY *a, const EVP_PKEY *b)
@@ -153,28 +85,15 @@ static int ecx_pub_cmp(const EVP_PKEY *a, const EVP_PKEY *b)
 static int ecx_priv_decode_ex(EVP_PKEY *pkey, const PKCS8_PRIV_KEY_INFO *p8,
                               OSSL_LIB_CTX *libctx, const char *propq)
 {
-    const unsigned char *p;
-    int plen;
-    ASN1_OCTET_STRING *oct = NULL;
-    const X509_ALGOR *palg;
-    int rv;
-
-    if (!PKCS8_pkey_get0(NULL, &p, &plen, &palg, p8))
-        return 0;
+    int ret = 0;
+    ECX_KEY *ecx = ossl_ecx_key_from_pkcs8(p8, libctx, propq);
 
-    oct = d2i_ASN1_OCTET_STRING(NULL, &p, plen);
-    if (oct == NULL) {
-        p = NULL;
-        plen = 0;
-    } else {
-        p = ASN1_STRING_get0_data(oct);
-        plen = ASN1_STRING_length(oct);
+    if (ecx != NULL) {
+        ret = 1;
+        EVP_PKEY_assign(pkey, pkey->ameth->pkey_id, ecx);
     }
 
-    rv = ecx_key_op(pkey, pkey->ameth->pkey_id, palg, p, plen, KEY_OP_PRIVATE,
-                    libctx, propq);
-    ASN1_STRING_clear_free(oct);
-    return rv;
+    return ret;
 }
 
 static int ecx_priv_encode(PKCS8_PRIV_KEY_INFO *p8, const EVP_PKEY *pkey)
@@ -298,10 +217,16 @@ static int ecx_ctrl(EVP_PKEY *pkey, int op, long arg1, void *arg2)
 {
     switch (op) {
 
-    case ASN1_PKEY_CTRL_SET1_TLS_ENCPT:
-        return ecx_key_op(pkey, pkey->ameth->pkey_id, NULL, arg2, arg1,
-                          KEY_OP_PUBLIC, NULL, NULL);
+    case ASN1_PKEY_CTRL_SET1_TLS_ENCPT: {
+        ECX_KEY *ecx = ossl_ecx_key_op(NULL, arg2, arg1, pkey->ameth->pkey_id,
+                                       KEY_OP_PUBLIC, NULL, NULL);
 
+        if (ecx != NULL) {
+            EVP_PKEY_assign(pkey, pkey->ameth->pkey_id, ecx);
+            return 1;
+        }
+        return 0;
+    }
     case ASN1_PKEY_CTRL_GET1_TLS_ENCPT:
         if (pkey->pkey.ecx != NULL) {
             unsigned char **ppt = arg2;
@@ -336,23 +261,37 @@ static int ecx_set_priv_key(EVP_PKEY *pkey, const unsigned char *priv,
                             size_t len)
 {
     OSSL_LIB_CTX *libctx = NULL;
+    ECX_KEY *ecx = NULL;
 
     if (pkey->keymgmt != NULL)
         libctx = ossl_provider_libctx(EVP_KEYMGMT_provider(pkey->keymgmt));
 
-    return ecx_key_op(pkey, pkey->ameth->pkey_id, NULL, priv, len,
-                       KEY_OP_PRIVATE, libctx, NULL);
+    ecx = ossl_ecx_key_op(NULL, priv, len, pkey->ameth->pkey_id,
+                          KEY_OP_PRIVATE, libctx, NULL);
+
+    if (ecx != NULL) {
+        EVP_PKEY_assign(pkey, pkey->ameth->pkey_id, ecx);
+        return 1;
+    }
+    return 0;
 }
 
 static int ecx_set_pub_key(EVP_PKEY *pkey, const unsigned char *pub, size_t len)
 {
     OSSL_LIB_CTX *libctx = NULL;
+    ECX_KEY *ecx = NULL;
 
     if (pkey->keymgmt != NULL)
         libctx = ossl_provider_libctx(EVP_KEYMGMT_provider(pkey->keymgmt));
 
-    return ecx_key_op(pkey, pkey->ameth->pkey_id, NULL, pub, len,
-                      KEY_OP_PUBLIC, libctx, NULL);
+    ecx = ossl_ecx_key_op(NULL, pub, len, pkey->ameth->pkey_id,
+                          KEY_OP_PUBLIC, libctx, NULL);
+
+    if (ecx != NULL) {
+        EVP_PKEY_assign(pkey, pkey->ameth->pkey_id, ecx);
+        return 1;
+    }
+    return 0;
 }
 
 static int ecx_get_priv_key(const EVP_PKEY *pkey, unsigned char *priv,
@@ -750,8 +689,14 @@ const EVP_PKEY_ASN1_METHOD ossl_ed448_asn1_meth = {
 
 static int pkey_ecx_keygen(EVP_PKEY_CTX *ctx, EVP_PKEY *pkey)
 {
-    return ecx_key_op(pkey, ctx->pmeth->pkey_id, NULL, NULL, 0, KEY_OP_KEYGEN,
-                      NULL, NULL);
+    ECX_KEY *ecx = ossl_ecx_key_op(NULL, NULL, 0, ctx->pmeth->pkey_id,
+                                   KEY_OP_PUBLIC, NULL, NULL);
+
+    if (ecx != NULL) {
+        EVP_PKEY_assign(pkey, ctx->pmeth->pkey_id, ecx);
+        return 1;
+    }
+    return 0;
 }
 
 static int validate_ecx_derive(EVP_PKEY_CTX *ctx, unsigned char *key,
index 9e9366757d4ab66870e264e7fa4740ef6bb861d5..067b7db12dda6c36191ff47a761f8da6f3eef6fe 100644 (file)
@@ -25,9 +25,6 @@
 #include "crypto/rsa.h"
 #include "rsa_local.h"
 
-static RSA_PSS_PARAMS *rsa_pss_decode(const X509_ALGOR *alg);
-static int rsa_sync_to_pss_params_30(RSA *rsa);
-
 /* Set any parameters associated with pkey */
 static int rsa_param_encode(const EVP_PKEY *pkey,
                             ASN1_STRING **pstr, int *pstrtype)
@@ -53,29 +50,6 @@ static int rsa_param_encode(const EVP_PKEY *pkey,
     return 1;
 }
 /* Decode any parameters and set them in RSA structure */
-static int rsa_param_decode(RSA *rsa, const X509_ALGOR *alg)
-{
-    const ASN1_OBJECT *algoid;
-    const void *algp;
-    int algptype;
-
-    X509_ALGOR_get0(&algoid, &algptype, &algp, alg);
-    if (OBJ_obj2nid(algoid) != EVP_PKEY_RSA_PSS)
-        return 1;
-    if (algptype == V_ASN1_UNDEF)
-        return 1;
-    if (algptype != V_ASN1_SEQUENCE) {
-        ERR_raise(ERR_LIB_RSA, RSA_R_INVALID_PSS_PARAMETERS);
-        return 0;
-    }
-    rsa->pss = rsa_pss_decode(alg);
-    if (rsa->pss == NULL)
-        return 0;
-    if (!rsa_sync_to_pss_params_30(rsa))
-        return 0;
-    return 1;
-}
-
 static int rsa_pub_encode(X509_PUBKEY *pk, const EVP_PKEY *pkey)
 {
     unsigned char *penc = NULL;
@@ -107,7 +81,7 @@ static int rsa_pub_decode(EVP_PKEY *pkey, const X509_PUBKEY *pubkey)
         return 0;
     if ((rsa = d2i_RSAPublicKey(NULL, &p, pklen)) == NULL)
         return 0;
-    if (!rsa_param_decode(rsa, alg)) {
+    if (!ossl_rsa_param_decode(rsa, alg)) {
         RSA_free(rsa);
         return 0;
     }
@@ -194,38 +168,14 @@ static int rsa_priv_encode(PKCS8_PRIV_KEY_INFO *p8, const EVP_PKEY *pkey)
 
 static int rsa_priv_decode(EVP_PKEY *pkey, const PKCS8_PRIV_KEY_INFO *p8)
 {
-    const unsigned char *p;
-    RSA *rsa;
-    int pklen;
-    const X509_ALGOR *alg;
+    int ret = 0;
+    RSA *rsa = ossl_rsa_key_from_pkcs8(p8, NULL, NULL);
 
-    if (!PKCS8_pkey_get0(NULL, &p, &pklen, &alg, p8))
-        return 0;
-    rsa = d2i_RSAPrivateKey(NULL, &p, pklen);
-    if (rsa == NULL) {
-        ERR_raise(ERR_LIB_RSA, ERR_R_RSA_LIB);
-        return 0;
-    }
-    if (!rsa_param_decode(rsa, alg)) {
-        RSA_free(rsa);
-        return 0;
+    if (rsa != NULL) {
+        ret = 1;
+        EVP_PKEY_assign(pkey, pkey->ameth->pkey_id, rsa);
     }
-
-    RSA_clear_flags(rsa, RSA_FLAG_TYPE_MASK);
-    switch (pkey->ameth->pkey_id) {
-    case EVP_PKEY_RSA:
-        RSA_set_flags(rsa, RSA_FLAG_TYPE_RSA);
-        break;
-    case EVP_PKEY_RSA_PSS:
-        RSA_set_flags(rsa, RSA_FLAG_TYPE_RSASSAPSS);
-        break;
-    default:
-        /* Leave the type bits zero */
-        break;
-    }
-
-    EVP_PKEY_assign(pkey, pkey->ameth->pkey_id, rsa);
-    return 1;
+    return ret;
 }
 
 static int int_rsa_size(const EVP_PKEY *pkey)
@@ -444,33 +394,12 @@ static int rsa_priv_print(BIO *bp, const EVP_PKEY *pkey, int indent,
     return pkey_rsa_print(bp, pkey, indent, 1);
 }
 
-static RSA_PSS_PARAMS *rsa_pss_decode(const X509_ALGOR *alg)
-{
-    RSA_PSS_PARAMS *pss;
-
-    pss = ASN1_TYPE_unpack_sequence(ASN1_ITEM_rptr(RSA_PSS_PARAMS),
-                                    alg->parameter);
-
-    if (pss == NULL)
-        return NULL;
-
-    if (pss->maskGenAlgorithm != NULL) {
-        pss->maskHash = ossl_x509_algor_mgf1_decode(pss->maskGenAlgorithm);
-        if (pss->maskHash == NULL) {
-            RSA_PSS_PARAMS_free(pss);
-            return NULL;
-        }
-    }
-
-    return pss;
-}
-
 static int rsa_sig_print(BIO *bp, const X509_ALGOR *sigalg,
                          const ASN1_STRING *sig, int indent, ASN1_PCTX *pctx)
 {
     if (OBJ_obj2nid(sigalg->algorithm) == EVP_PKEY_RSA_PSS) {
         int rv;
-        RSA_PSS_PARAMS *pss = rsa_pss_decode(sigalg);
+        RSA_PSS_PARAMS *pss = ossl_rsa_pss_decode(sigalg);
 
         rv = rsa_pss_param_print(bp, 0, pss, indent);
         RSA_PSS_PARAMS_free(pss);
@@ -601,7 +530,7 @@ int ossl_rsa_pss_to_ctx(EVP_MD_CTX *ctx, EVP_PKEY_CTX *pkctx,
         return -1;
     }
     /* Decode PSS parameters */
-    pss = rsa_pss_decode(sigalg);
+    pss = ossl_rsa_pss_decode(sigalg);
 
     if (!ossl_rsa_pss_get_param(pss, &md, &mgf1md, &saltlen)) {
         ERR_raise(ERR_LIB_RSA, RSA_R_INVALID_PSS_PARAMETERS);
@@ -656,36 +585,6 @@ static int rsa_pss_verify_param(const EVP_MD **pmd, const EVP_MD **pmgf1md,
     return 1;
 }
 
-static int rsa_pss_get_param_unverified(const RSA_PSS_PARAMS *pss,
-                                        const EVP_MD **pmd,
-                                        const EVP_MD **pmgf1md,
-                                        int *psaltlen, int *ptrailerField)
-{
-    RSA_PSS_PARAMS_30 pss_params;
-
-    /* Get the defaults from the ONE place */
-    (void)ossl_rsa_pss_params_30_set_defaults(&pss_params);
-
-    if (pss == NULL)
-        return 0;
-    *pmd = ossl_x509_algor_get_md(pss->hashAlgorithm);
-    if (*pmd == NULL)
-        return 0;
-    *pmgf1md = ossl_x509_algor_get_md(pss->maskHash);
-    if (*pmgf1md == NULL)
-        return 0;
-    if (pss->saltLength)
-        *psaltlen = ASN1_INTEGER_get(pss->saltLength);
-    else
-        *psaltlen = ossl_rsa_pss_params_30_saltlen(&pss_params);
-    if (pss->trailerField)
-        *ptrailerField = ASN1_INTEGER_get(pss->trailerField);
-    else
-        *ptrailerField = ossl_rsa_pss_params_30_trailerfield(&pss_params);;
-
-    return 1;
-}
-
 int ossl_rsa_pss_get_param(const RSA_PSS_PARAMS *pss, const EVP_MD **pmd,
                            const EVP_MD **pmgf1md, int *psaltlen)
 {
@@ -699,45 +598,11 @@ int ossl_rsa_pss_get_param(const RSA_PSS_PARAMS *pss, const EVP_MD **pmd,
      */
     int trailerField = 0;
 
-    return rsa_pss_get_param_unverified(pss, pmd, pmgf1md, psaltlen,
-                                        &trailerField)
+    return ossl_rsa_pss_get_param_unverified(pss, pmd, pmgf1md, psaltlen,
+                                             &trailerField)
         && rsa_pss_verify_param(pmd, pmgf1md, psaltlen, &trailerField);
 }
 
-static int rsa_sync_to_pss_params_30(RSA *rsa)
-{
-    if (rsa != NULL && rsa->pss != NULL) {
-        const EVP_MD *md = NULL, *mgf1md = NULL;
-        int md_nid, mgf1md_nid, saltlen, trailerField;
-        RSA_PSS_PARAMS_30 pss_params;
-
-        /*
-         * We don't care about the validity of the fields here, we just
-         * want to synchronise values.  Verifying here makes it impossible
-         * to even read a key with invalid values, making it hard to test
-         * a bad situation.
-         *
-         * Other routines use ossl_rsa_pss_get_param(), so the values will be
-         * checked, eventually.
-         */
-        if (!rsa_pss_get_param_unverified(rsa->pss, &md, &mgf1md,
-                                          &saltlen, &trailerField))
-            return 0;
-        md_nid = EVP_MD_type(md);
-        mgf1md_nid = EVP_MD_type(mgf1md);
-        if (!ossl_rsa_pss_params_30_set_defaults(&pss_params)
-            || !ossl_rsa_pss_params_30_set_hashalg(&pss_params, md_nid)
-            || !ossl_rsa_pss_params_30_set_maskgenhashalg(&pss_params,
-                                                          mgf1md_nid)
-            || !ossl_rsa_pss_params_30_set_saltlen(&pss_params, saltlen)
-            || !ossl_rsa_pss_params_30_set_trailerfield(&pss_params,
-                                                        trailerField))
-            return 0;
-        rsa->pss_params = pss_params;
-    }
-    return 1;
-}
-
 /*
  * Customised RSA item verification routine. This is called when a signature
  * is encountered requiring special handling. We currently only handle PSS.
@@ -806,7 +671,7 @@ static int rsa_sig_info_set(X509_SIG_INFO *siginf, const X509_ALGOR *sigalg,
     if (OBJ_obj2nid(sigalg->algorithm) != EVP_PKEY_RSA_PSS)
         return 0;
     /* Decode PSS parameters */
-    pss = rsa_pss_decode(sigalg);
+    pss = ossl_rsa_pss_decode(sigalg);
     if (!ossl_rsa_pss_get_param(pss, &md, &mgf1md, &saltlen))
         goto err;
     mdnid = EVP_MD_type(md);
@@ -894,8 +759,8 @@ static int rsa_int_export_to(const EVP_PKEY *from, int rsa_type,
         int md_nid, mgf1md_nid, saltlen, trailerfield;
         RSA_PSS_PARAMS_30 pss_params;
 
-        if (!rsa_pss_get_param_unverified(rsa->pss, &md, &mgf1md,
-                                          &saltlen, &trailerfield))
+        if (!ossl_rsa_pss_get_param_unverified(rsa->pss, &md, &mgf1md,
+                                               &saltlen, &trailerfield))
             goto err;
         md_nid = EVP_MD_type(md);
         mgf1md_nid = EVP_MD_type(mgf1md);
index 8c16a56db5f9267b577805c47e06b64b75750111..01ee87505891b3a2ff93fb2e8654e62ced76bab9 100644 (file)
 #include <string.h>
 #include <openssl/core_names.h>
 #include <openssl/params.h>
+#include <openssl/err.h>
 #include <openssl/evp.h>
 #include "internal/sizes.h"
 #include "internal/param_build_set.h"
+#include "crypto/asn1.h"
 #include "crypto/rsa.h"
 
 #include "e_os.h"                /* strcasecmp for Windows() */
@@ -319,3 +321,156 @@ int ossl_rsa_pss_params_30_fromdata(RSA_PSS_PARAMS_30 *pss_params,
     EVP_MD_free(mgf1md);
     return ret;
 }
+
+#ifndef FIPS_MODULE
+RSA_PSS_PARAMS *ossl_rsa_pss_decode(const X509_ALGOR *alg)
+{
+    RSA_PSS_PARAMS *pss;
+
+    pss = ASN1_TYPE_unpack_sequence(ASN1_ITEM_rptr(RSA_PSS_PARAMS),
+                                    alg->parameter);
+
+    if (pss == NULL)
+        return NULL;
+
+    if (pss->maskGenAlgorithm != NULL) {
+        pss->maskHash = ossl_x509_algor_mgf1_decode(pss->maskGenAlgorithm);
+        if (pss->maskHash == NULL) {
+            RSA_PSS_PARAMS_free(pss);
+            return NULL;
+        }
+    }
+
+    return pss;
+}
+
+static int ossl_rsa_sync_to_pss_params_30(RSA *rsa)
+{
+    const RSA_PSS_PARAMS *legacy_pss = NULL;
+    RSA_PSS_PARAMS_30 *pss = NULL;
+
+    if (rsa != NULL
+        && (legacy_pss = RSA_get0_pss_params(rsa)) != NULL
+        && (pss = ossl_rsa_get0_pss_params_30(rsa)) != NULL) {
+        const EVP_MD *md = NULL, *mgf1md = NULL;
+        int md_nid, mgf1md_nid, saltlen, trailerField;
+        RSA_PSS_PARAMS_30 pss_params;
+
+        /*
+         * We don't care about the validity of the fields here, we just
+         * want to synchronise values.  Verifying here makes it impossible
+         * to even read a key with invalid values, making it hard to test
+         * a bad situation.
+         *
+         * Other routines use ossl_rsa_pss_get_param(), so the values will
+         * be checked, eventually.
+         */
+        if (!ossl_rsa_pss_get_param_unverified(legacy_pss, &md, &mgf1md,
+                                               &saltlen, &trailerField))
+            return 0;
+        md_nid = EVP_MD_type(md);
+        mgf1md_nid = EVP_MD_type(mgf1md);
+        if (!ossl_rsa_pss_params_30_set_defaults(&pss_params)
+            || !ossl_rsa_pss_params_30_set_hashalg(&pss_params, md_nid)
+            || !ossl_rsa_pss_params_30_set_maskgenhashalg(&pss_params,
+                                                          mgf1md_nid)
+            || !ossl_rsa_pss_params_30_set_saltlen(&pss_params, saltlen)
+            || !ossl_rsa_pss_params_30_set_trailerfield(&pss_params,
+                                                        trailerField))
+            return 0;
+        *pss = pss_params;
+    }
+    return 1;
+}
+
+int ossl_rsa_pss_get_param_unverified(const RSA_PSS_PARAMS *pss,
+                                      const EVP_MD **pmd, const EVP_MD **pmgf1md,
+                                      int *psaltlen, int *ptrailerField)
+{
+    RSA_PSS_PARAMS_30 pss_params;
+
+    /* Get the defaults from the ONE place */
+    (void)ossl_rsa_pss_params_30_set_defaults(&pss_params);
+
+    if (pss == NULL)
+        return 0;
+    *pmd = ossl_x509_algor_get_md(pss->hashAlgorithm);
+    if (*pmd == NULL)
+        return 0;
+    *pmgf1md = ossl_x509_algor_get_md(pss->maskHash);
+    if (*pmgf1md == NULL)
+        return 0;
+    if (pss->saltLength)
+        *psaltlen = ASN1_INTEGER_get(pss->saltLength);
+    else
+        *psaltlen = ossl_rsa_pss_params_30_saltlen(&pss_params);
+    if (pss->trailerField)
+        *ptrailerField = ASN1_INTEGER_get(pss->trailerField);
+    else
+        *ptrailerField = ossl_rsa_pss_params_30_trailerfield(&pss_params);;
+
+    return 1;
+}
+
+int ossl_rsa_param_decode(RSA *rsa, const X509_ALGOR *alg)
+{
+    RSA_PSS_PARAMS *pss;
+    const ASN1_OBJECT *algoid;
+    const void *algp;
+    int algptype;
+
+    X509_ALGOR_get0(&algoid, &algptype, &algp, alg);
+    if (OBJ_obj2nid(algoid) != EVP_PKEY_RSA_PSS)
+        return 1;
+    if (algptype == V_ASN1_UNDEF)
+        return 1;
+    if (algptype != V_ASN1_SEQUENCE) {
+        ERR_raise(ERR_LIB_RSA, RSA_R_INVALID_PSS_PARAMETERS);
+        return 0;
+    }
+    if ((pss = ossl_rsa_pss_decode(alg)) == NULL
+        || !ossl_rsa_set0_pss_params(rsa, pss)) {
+        RSA_PSS_PARAMS_free(pss);
+        return 0;
+    }
+    if (!ossl_rsa_sync_to_pss_params_30(rsa))
+        return 0;
+    return 1;
+}
+
+RSA *ossl_rsa_key_from_pkcs8(const PKCS8_PRIV_KEY_INFO *p8inf,
+                             OSSL_LIB_CTX *libctx, const char *propq)
+{
+    const unsigned char *p;
+    RSA *rsa;
+    int pklen;
+    const X509_ALGOR *alg;
+
+    if (!PKCS8_pkey_get0(NULL, &p, &pklen, &alg, p8inf))
+        return 0;
+    rsa = d2i_RSAPrivateKey(NULL, &p, pklen);
+    if (rsa == NULL) {
+        ERR_raise(ERR_LIB_RSA, ERR_R_RSA_LIB);
+        return NULL;
+    }
+    if (!ossl_rsa_param_decode(rsa, alg)) {
+        RSA_free(rsa);
+        return NULL;
+    }
+
+    RSA_clear_flags(rsa, RSA_FLAG_TYPE_MASK);
+    switch (OBJ_obj2nid(alg->algorithm)) {
+    case EVP_PKEY_RSA:
+        RSA_set_flags(rsa, RSA_FLAG_TYPE_RSA);
+        break;
+    case EVP_PKEY_RSA_PSS:
+        RSA_set_flags(rsa, RSA_FLAG_TYPE_RSASSAPSS);
+        break;
+    default:
+        /* Leave the type bits zero */
+        break;
+    }
+
+    return rsa;
+}
+#endif
index 89cd4da5277daa6ab07dea02250e1cc115a35ec1..bfd274a66aefda14fa88e4baa6d68dac1d3c1546 100644 (file)
@@ -657,6 +657,18 @@ const RSA_PSS_PARAMS *RSA_get0_pss_params(const RSA *r)
 #endif
 }
 
+/* Internal */
+int ossl_rsa_set0_pss_params(RSA *r, RSA_PSS_PARAMS *pss)
+{
+#ifdef FIPS_MODULE
+    return 0;
+#else
+    RSA_PSS_PARAMS_free(r->pss);
+    r->pss = pss;
+    return 1;
+#endif
+}
+
 /* Internal */
 RSA_PSS_PARAMS_30 *ossl_rsa_get0_pss_params_30(RSA *r)
 {
index d8b597a0f126907b369314a3c35e31f084ae9ac0..b16ac8f42ff0662f3a7b3050ad69b179d14b248b 100644 (file)
@@ -14,6 +14,7 @@
 # include <openssl/core.h>
 # include <openssl/params.h>
 # include <openssl/dh.h>
+# include <openssl/x509.h>
 # include "internal/ffc.h"
 
 DH *ossl_dh_new_by_nid_ex(OSSL_LIB_CTX *libctx, int nid);
@@ -35,6 +36,8 @@ int ossl_dh_params_fromdata(DH *dh, const OSSL_PARAM params[]);
 int ossl_dh_key_fromdata(DH *dh, const OSSL_PARAM params[]);
 int ossl_dh_params_todata(DH *dh, OSSL_PARAM_BLD *bld, OSSL_PARAM params[]);
 int ossl_dh_key_todata(DH *dh, OSSL_PARAM_BLD *bld, OSSL_PARAM params[]);
+DH *ossl_dh_key_from_pkcs8(const PKCS8_PRIV_KEY_INFO *p8inf,
+                           OSSL_LIB_CTX *libctx, const char *propq);
 
 int ossl_dh_check_pub_key_partial(const DH *dh, const BIGNUM *pub_key, int *ret);
 int ossl_dh_check_priv_key(const DH *dh, const BIGNUM *priv_key, int *ret);
index 0c15c51da0b126c52a764a9bbe8d879f0596ddd6..38c49c3295f738ebd8609fd14421afe9e34786d4 100644 (file)
@@ -13,6 +13,7 @@
 
 # include <openssl/core.h>
 # include <openssl/dsa.h>
+# include <openssl/x509.h>
 # include "internal/ffc.h"
 
 #define DSA_PARAMGEN_TYPE_FIPS_186_4   0   /* Use FIPS186-4 standard */
@@ -31,6 +32,8 @@ int ossl_dsa_sign_int(int type, const unsigned char *dgst, int dlen,
 FFC_PARAMS *ossl_dsa_get0_params(DSA *dsa);
 int ossl_dsa_ffc_params_fromdata(DSA *dsa, const OSSL_PARAM params[]);
 int ossl_dsa_key_fromdata(DSA *dsa, const OSSL_PARAM params[]);
+DSA *ossl_dsa_key_from_pkcs8(const PKCS8_PRIV_KEY_INFO *p8inf,
+                             OSSL_LIB_CTX *libctx, const char *propq);
 
 int ossl_dsa_generate_public_key(BN_CTX *ctx, const DSA *dsa,
                                  const BIGNUM *priv_key, BIGNUM *pub_key);
index a3d87e9d1a7b4449716a90a835d49013644f267c..c679fd8d11cd866df9ba70722788909241e72ffd 100644 (file)
@@ -25,6 +25,7 @@ int evp_pkey_ctx_set_ec_param_enc_prov(EVP_PKEY_CTX *ctx, int param_enc);
 # ifndef OPENSSL_NO_EC
 #  include <openssl/core.h>
 #  include <openssl/ec.h>
+#  include <openssl/x509.h>
 #  include "crypto/types.h"
 
 /*-
@@ -78,6 +79,12 @@ int ossl_ec_group_set_params(EC_GROUP *group, const OSSL_PARAM params[]);
 int ossl_ec_key_fromdata(EC_KEY *ecx, const OSSL_PARAM params[],
                          int include_private);
 int ossl_ec_key_otherparams_fromdata(EC_KEY *ec, const OSSL_PARAM params[]);
+EC_KEY *ossl_ec_key_param_from_x509_algor(const X509_ALGOR *palg,
+                                          OSSL_LIB_CTX *libctx,
+                                          const char *propq);
+EC_KEY *ossl_ec_key_from_pkcs8(const PKCS8_PRIV_KEY_INFO *p8inf,
+                               OSSL_LIB_CTX *libctx, const char *propq);
+
 int ossl_ec_set_ecdh_cofactor_mode(EC_KEY *ec, int mode);
 int ossl_ec_encoding_name2id(const char *name);
 int ossl_ec_encoding_param2id(const OSSL_PARAM *p, int *id);
index 101a5748e8571c124610f698ef2b60651ef65fe1..dfc70fb4e65e4a96711c3415977f59b0e8b3ca54 100644 (file)
@@ -20,7 +20,9 @@
 #  include <openssl/core.h>
 #  include <openssl/e_os2.h>
 #  include <openssl/crypto.h>
+#  include <openssl/x509.h>
 #  include "internal/refcount.h"
+#  include "crypto/types.h"
 
 #  define X25519_KEYLEN         32
 #  define X448_KEYLEN           56
@@ -76,6 +78,7 @@ struct ecx_key_st {
 
 typedef struct ecx_key_st ECX_KEY;
 
+size_t ossl_ecx_key_length(ECX_KEY_TYPE type);
 ECX_KEY *ossl_ecx_key_new(OSSL_LIB_CTX *libctx, ECX_KEY_TYPE type,
                           int haspubkey, const char *propq);
 void ossl_ecx_key_set0_libctx(ECX_KEY *key, OSSL_LIB_CTX *libctx);
@@ -124,9 +127,22 @@ ossl_x448_public_from_private(uint8_t out_public_value[56],
 
 
 /* Backend support */
+typedef enum {
+    KEY_OP_PUBLIC,
+    KEY_OP_PRIVATE,
+    KEY_OP_KEYGEN
+} ecx_key_op_t;
+
+ECX_KEY *ossl_ecx_key_op(const X509_ALGOR *palg,
+                         const unsigned char *p, int plen,
+                         int pkey_id, ecx_key_op_t op,
+                         OSSL_LIB_CTX *libctx, const char *propq);
+
 int ossl_ecx_public_from_private(ECX_KEY *key);
 int ossl_ecx_key_fromdata(ECX_KEY *ecx, const OSSL_PARAM params[],
                           int include_private);
+ECX_KEY *ossl_ecx_key_from_pkcs8(const PKCS8_PRIV_KEY_INFO *p8inf,
+                                 OSSL_LIB_CTX *libctx, const char *propq);
 
 ECX_KEY *ossl_evp_pkey_get1_X25519(EVP_PKEY *pkey);
 ECX_KEY *ossl_evp_pkey_get1_X448(EVP_PKEY *pkey);
index 7fca88dfe4b5df05af787e9d7e81deee1903ee3d..69fa8a4d8acf28dfb01f63eab1db389f692c818a 100644 (file)
@@ -13,6 +13,7 @@
 
 # include <openssl/core.h>
 # include <openssl/rsa.h>
+# include <openssl/x509.h>
 # include "crypto/types.h"
 
 typedef struct rsa_pss_params_30_st {
@@ -69,6 +70,14 @@ int ossl_rsa_pss_params_30_fromdata(RSA_PSS_PARAMS_30 *pss_params,
                                     int *defaults_set,
                                     const OSSL_PARAM params[],
                                     OSSL_LIB_CTX *libctx);
+int ossl_rsa_set0_pss_params(RSA *r, RSA_PSS_PARAMS *pss);
+int ossl_rsa_pss_get_param_unverified(const RSA_PSS_PARAMS *pss,
+                                      const EVP_MD **pmd, const EVP_MD **pmgf1md,
+                                      int *psaltlen, int *ptrailerField);
+RSA_PSS_PARAMS *ossl_rsa_pss_decode(const X509_ALGOR *alg);
+int ossl_rsa_param_decode(RSA *rsa, const X509_ALGOR *alg);
+RSA *ossl_rsa_key_from_pkcs8(const PKCS8_PRIV_KEY_INFO *p8inf,
+                             OSSL_LIB_CTX *libctx, const char *propq);
 
 int ossl_rsa_padding_check_PKCS1_type_2_TLS(OSSL_LIB_CTX *ctx, unsigned char *to,
                                             size_t tlen,
@@ -113,4 +122,5 @@ void ossl_rsa_acvp_test_free(RSA_ACVP_TEST *t);
 # define RSA_ACVP_TEST void
 # endif
 
+RSA *evp_pkey_get1_RSA_PSS(EVP_PKEY *pkey);
 #endif
index 275d1d36c1644978c6e7c41a4454ba9bdc456643..13a5f9ce1d75cbe3923f06e596578ccdec11aa02 100644 (file)
 #ifdef OPENSSL_NO_DEPRECATED_3_0
 typedef struct rsa_st RSA;
 typedef struct rsa_meth_st RSA_METHOD;
+# ifndef OPENSSL_NO_EC
 typedef struct ec_key_st EC_KEY;
 typedef struct ec_key_method_st EC_KEY_METHOD;
+# endif
+#endif
+
+#ifndef OPENSSL_NO_EC
+typedef struct ecx_key_st ECX_KEY;
 #endif
index e0997a4712238fcddde80871354aacb0b4e7f1a3..98aea5f1fde96811599d363b8eea3a4f0c6bec46 100644 (file)
@@ -14,7 +14,7 @@
 # include "internal/refcount.h"
 # include <openssl/asn1.h>
 # include <openssl/x509.h>
-# include "crypto/ecx.h"
+# include "crypto/types.h"
 
 /* Internal X509 structures and functions: not for application use */
 
index 74f462794a993aa85697e1d3c22194fe3cb3ba57..f50fca38962b9729e120827a06eddebdcf43c930 100644 (file)
         SET_ERR_MARK();                                                 \
     } while(0)
 
-static int read_der(PROV_CTX *provctx, OSSL_CORE_BIO *cin,
-                    unsigned char **data, long *len)
-{
-    BUF_MEM *mem = NULL;
-    BIO *in = ossl_bio_new_from_core_bio(provctx, cin);
-    int ok = (asn1_d2i_read_bio(in, &mem) >= 0);
-
-    if (ok) {
-        *data = (unsigned char *)mem->data;
-        *len = (long)mem->length;
-        OPENSSL_free(mem);
-    }
-    BIO_free(in);
-    return ok;
-}
-
-static int der_from_p8(unsigned char **new_der, long *new_der_len,
-                       unsigned char *input_der, long input_der_len,
-                       OSSL_PASSPHRASE_CALLBACK *pw_cb, void *pw_cbarg)
-{
-    const unsigned char *derp;
-    X509_SIG *p8 = NULL;
-    int ok = 0;
-
-    if (!ossl_assert(new_der != NULL && *new_der == NULL)
-        || !ossl_assert(new_der_len != NULL))
-        return 0;
-
-    derp = input_der;
-    if ((p8 = d2i_X509_SIG(NULL, &derp, input_der_len)) != NULL) {
-        char pbuf[PEM_BUFSIZE];
-        size_t plen = 0;
-
-        if (!pw_cb(pbuf, sizeof(pbuf), &plen, NULL, pw_cbarg)) {
-            ERR_raise(ERR_LIB_PROV, PROV_R_UNABLE_TO_GET_PASSPHRASE);
-        } else {
-            const X509_ALGOR *alg = NULL;
-            const ASN1_OCTET_STRING *oct = NULL;
-            int len = 0;
-
-            X509_SIG_get0(p8, &alg, &oct);
-            if (PKCS12_pbe_crypt(alg, pbuf, plen, oct->data, oct->length,
-                                 new_der, &len, 0) != NULL)
-                ok = 1;
-            *new_der_len = len;
-        }
-    }
-    X509_SIG_free(p8);
-    return ok;
-}
-
-/* ---------------------------------------------------------------------- */
-
-static OSSL_FUNC_decoder_freectx_fn der2key_freectx;
-static OSSL_FUNC_decoder_decode_fn der2key_decode;
-static OSSL_FUNC_decoder_export_object_fn der2key_export_object;
-
 struct der2key_ctx_st;           /* Forward declaration */
-typedef void *extract_key_fn(EVP_PKEY *);
 typedef int check_key_fn(void *, struct der2key_ctx_st *ctx);
 typedef void adjust_key_fn(void *, struct der2key_ctx_st *ctx);
 typedef void free_key_fn(void *);
+typedef void *d2i_PKCS8_fn(void **, const unsigned char **, long,
+                           struct der2key_ctx_st *,
+                           OSSL_PASSPHRASE_CALLBACK *pw_cb, void *pw_cbarg);
 struct keytype_desc_st {
     const char *keytype_name;
     const OSSL_DISPATCH *fns; /* Keymgmt (to pilfer functions from) */
@@ -140,13 +85,9 @@ struct keytype_desc_st {
     d2i_of_void *d2i_private_key; /* From type-specific DER */
     d2i_of_void *d2i_public_key;  /* From type-specific DER */
     d2i_of_void *d2i_key_params;  /* From type-specific DER */
+    d2i_PKCS8_fn *d2i_PKCS8;      /* Wrapped in a PKCS#8, possibly encrypted */
     d2i_of_void *d2i_PUBKEY;      /* Wrapped in a SubjectPublicKeyInfo */
 
-    /*
-     * For PKCS#8 decoders, we use EVP_PKEY extractors, EVP_PKEY_get1_{TYPE}()
-     */
-    extract_key_fn *extract_key;
-
     /*
      * For any key, we may need to check that the key meets expectations.
      * This is useful when the same functions can decode several variants
@@ -169,8 +110,67 @@ struct keytype_desc_st {
 struct der2key_ctx_st {
     PROV_CTX *provctx;
     const struct keytype_desc_st *desc;
+    /* Flag used to signal that a failure is fatal */
+    unsigned int flag_fatal : 1;
 };
 
+static int read_der(PROV_CTX *provctx, OSSL_CORE_BIO *cin,
+                    unsigned char **data, long *len)
+{
+    BUF_MEM *mem = NULL;
+    BIO *in = ossl_bio_new_from_core_bio(provctx, cin);
+    int ok = (asn1_d2i_read_bio(in, &mem) >= 0);
+
+    if (ok) {
+        *data = (unsigned char *)mem->data;
+        *len = (long)mem->length;
+        OPENSSL_free(mem);
+    }
+    BIO_free(in);
+    return ok;
+}
+
+typedef void *key_from_pkcs8_t(const PKCS8_PRIV_KEY_INFO *p8inf,
+                               OSSL_LIB_CTX *libctx, const char *propq);
+static void *der2key_decode_p8(const unsigned char **input_der,
+                               long input_der_len, struct der2key_ctx_st *ctx,
+                               OSSL_PASSPHRASE_CALLBACK *pw_cb, void *pw_cbarg,
+                               key_from_pkcs8_t *key_from_pkcs8)
+{
+    X509_SIG *p8 = NULL;
+    PKCS8_PRIV_KEY_INFO *p8inf = NULL;
+    const X509_ALGOR *alg = NULL;
+    void *key = NULL;
+
+    ctx->flag_fatal = 0;
+    if ((p8 = d2i_X509_SIG(NULL, input_der, input_der_len)) != NULL) {
+        char pbuf[PEM_BUFSIZE];
+        size_t plen = 0;
+
+        if (!pw_cb(pbuf, sizeof(pbuf), &plen, NULL, pw_cbarg))
+            ERR_raise(ERR_LIB_PROV, PROV_R_UNABLE_TO_GET_PASSPHRASE);
+        else
+            p8inf = PKCS8_decrypt(p8, pbuf, plen);
+        if (p8inf == NULL)
+            ctx->flag_fatal = 1;
+        X509_SIG_free(p8);
+    } else {
+        p8inf = d2i_PKCS8_PRIV_KEY_INFO(NULL, input_der, input_der_len);
+    }
+    if (p8inf != NULL
+        && PKCS8_pkey_get0(NULL, NULL, NULL, &alg, p8inf)
+        && OBJ_obj2nid(alg->algorithm) == ctx->desc->evp_type)
+        key = key_from_pkcs8(p8inf, PROV_LIBCTX_OF(ctx->provctx), NULL);
+    PKCS8_PRIV_KEY_INFO_free(p8inf);
+    return key;
+}
+
+/* ---------------------------------------------------------------------- */
+
+static OSSL_FUNC_decoder_freectx_fn der2key_freectx;
+static OSSL_FUNC_decoder_decode_fn der2key_decode;
+static OSSL_FUNC_decoder_export_object_fn der2key_export_object;
+
 static struct der2key_ctx_st *
 der2key_newctx(void *provctx, const struct keytype_desc_st *desc)
 {
@@ -262,13 +262,9 @@ static int der2key_decode(void *vctx, OSSL_CORE_BIO *cin, int selection,
                           OSSL_PASSPHRASE_CALLBACK *pw_cb, void *pw_cbarg)
 {
     struct der2key_ctx_st *ctx = vctx;
-    void *libctx = PROV_LIBCTX_OF(ctx->provctx);
     unsigned char *der = NULL;
     const unsigned char *derp;
     long der_len = 0;
-    unsigned char *new_der = NULL;
-    long new_der_len;
-    EVP_PKEY *pkey = NULL;
     void *key = NULL;
     int orig_selection = selection;
     int ok = 0;
@@ -292,18 +288,21 @@ static int der2key_decode(void *vctx, OSSL_CORE_BIO *cin, int selection,
     if (!read_der(ctx->provctx, cin, &der, &der_len))
         goto next;
 
-    /* We try the typs specific functions first, if available */
-    if (ctx->desc->d2i_private_key != NULL
-        && (selection & OSSL_KEYMGMT_SELECT_PRIVATE_KEY) != 0) {
+    if ((selection & OSSL_KEYMGMT_SELECT_PRIVATE_KEY) != 0) {
         RESET_ERR_MARK();
         derp = der;
-        key = ctx->desc->d2i_private_key(NULL, &derp, der_len);
+        if (ctx->desc->d2i_PKCS8 != NULL) {
+            key = ctx->desc->d2i_PKCS8(NULL, &derp, der_len, ctx,
+                                       pw_cb, pw_cbarg);
+            if (ctx->flag_fatal)
+                goto end;
+        } else if (ctx->desc->d2i_private_key != NULL) {
+            key = ctx->desc->d2i_private_key(NULL, &derp, der_len);
+        }
         if (key == NULL && orig_selection != 0)
             goto next;
     }
-    if (key == NULL
-        && (ctx->desc->d2i_PUBKEY != NULL || ctx->desc->d2i_public_key != NULL)
-        && (selection & OSSL_KEYMGMT_SELECT_PUBLIC_KEY) != 0) {
+    if (key == NULL && (selection & OSSL_KEYMGMT_SELECT_PUBLIC_KEY) != 0) {
         RESET_ERR_MARK();
         derp = der;
         if (ctx->desc->d2i_PUBKEY != NULL)
@@ -313,71 +312,15 @@ static int der2key_decode(void *vctx, OSSL_CORE_BIO *cin, int selection,
         if (key == NULL && orig_selection != 0)
             goto next;
     }
-    if (key == NULL
-        && ctx->desc->d2i_key_params != NULL
-        && (selection & OSSL_KEYMGMT_SELECT_ALL_PARAMETERS) != 0) {
+    if (key == NULL && (selection & OSSL_KEYMGMT_SELECT_ALL_PARAMETERS) != 0) {
         RESET_ERR_MARK();
         derp = der;
-        key = ctx->desc->d2i_key_params(NULL, &derp, der_len);
-    }
-    if (key == NULL
-        && ctx->desc->extract_key != NULL) {
-        /*
-         * There is a EVP_PKEY extractor, so we use the more generic
-         * EVP_PKEY functions, since they know how to unpack PKCS#8 and
-         * SubjectPublicKeyInfo.
-         */
-
-        if ((selection & OSSL_KEYMGMT_SELECT_PRIVATE_KEY) != 0) {
-            /*
-             * Opportunistic attempt to decrypt.  If it doesn't work, we try
-             * to decode our input unencrypted.
-             */
-            if (der_from_p8(&new_der, &new_der_len, der, der_len,
-                            pw_cb, pw_cbarg)) {
-                OPENSSL_free(der);
-                der = new_der;
-                der_len = new_der_len;
-            }
-            RESET_ERR_MARK();
-
-            derp = der;
-            pkey = evp_privatekey_from_binary(ctx->desc->evp_type, NULL,
-                                              &derp, der_len, libctx, NULL);
-        }
-
-        /*
-         * As long as we have algos without a specific d2i_<TYPE>_PUBKEY,
-         * this code must remain...
-         */
-        if (pkey == NULL
-            && (selection & OSSL_KEYMGMT_SELECT_PUBLIC_KEY) != 0) {
-            RESET_ERR_MARK();
-            derp = der;
-            pkey = ossl_d2i_PUBKEY_legacy(NULL, &derp, der_len);
-        }
-
-        if (pkey != NULL) {
-            /*
-             * Tear out the low-level key pointer from the pkey,
-             * but only if it matches the expected key type.
-             *
-             * The check should be done with EVP_PKEY_is_a(), but
-             * as long as we still have #legacy internal keys, it's safer
-             * to use the type numbers inside the provider.
-             */
-            if (EVP_PKEY_id(pkey) == ctx->desc->evp_type)
-                key = ctx->desc->extract_key(pkey);
-
-            /*
-             * ctx->desc->extract_key() is expected to have incremented
-             * |key|'s reference count, so it should be safe to free |pkey|
-             * now.
-             */
-            EVP_PKEY_free(pkey);
-        }
+        if (ctx->desc->d2i_key_params != NULL)
+            key = ctx->desc->d2i_key_params(NULL, &derp, der_len);
+        if (key == NULL && orig_selection != 0)
+            goto next;
     }
-
+    RESET_ERR_MARK();
     if (key != NULL
         && ctx->desc->check_key != NULL
         && !ctx->desc->check_key(key, ctx)) {
@@ -453,10 +396,18 @@ static int der2key_export_object(void *vctx,
 
 #ifndef OPENSSL_NO_DH
 # define dh_evp_type                    EVP_PKEY_DH
-# define dh_evp_extract                 (extract_key_fn *)EVP_PKEY_get1_DH
 # define dh_d2i_private_key             NULL
 # define dh_d2i_public_key              NULL
 # define dh_d2i_key_params              (d2i_of_void *)d2i_DHparams
+
+static void *dh_d2i_PKCS8(void **key, const unsigned char **der, long der_len,
+                          struct der2key_ctx_st *ctx,
+                          OSSL_PASSPHRASE_CALLBACK *pw_cb, void *pw_cbarg)
+{
+    return der2key_decode_p8(der, der_len, ctx, pw_cb, pw_cbarg,
+                             (key_from_pkcs8_t *)ossl_dh_key_from_pkcs8);
+}
+
 # define dh_d2i_PUBKEY                  (d2i_of_void *)ossl_d2i_DH_PUBKEY
 # define dh_free                        (free_key_fn *)DH_free
 # define dh_check                       NULL
@@ -467,10 +418,10 @@ static void dh_adjust(void *key, struct der2key_ctx_st *ctx)
 }
 
 # define dhx_evp_type                   EVP_PKEY_DHX
-# define dhx_evp_extract                (extract_key_fn *)EVP_PKEY_get1_DH
 # define dhx_d2i_private_key            NULL
 # define dhx_d2i_public_key             NULL
 # define dhx_d2i_key_params             (d2i_of_void *)d2i_DHxparams
+# define dhx_d2i_PKCS8                  dh_d2i_PKCS8
 # define dhx_d2i_PUBKEY                 (d2i_of_void *)ossl_d2i_DHx_PUBKEY
 # define dhx_free                       (free_key_fn *)DH_free
 # define dhx_check                      NULL
@@ -481,10 +432,18 @@ static void dh_adjust(void *key, struct der2key_ctx_st *ctx)
 
 #ifndef OPENSSL_NO_DSA
 # define dsa_evp_type                   EVP_PKEY_DSA
-# define dsa_evp_extract                (extract_key_fn *)EVP_PKEY_get1_DSA
 # define dsa_d2i_private_key            (d2i_of_void *)d2i_DSAPrivateKey
 # define dsa_d2i_public_key             (d2i_of_void *)d2i_DSAPublicKey
 # define dsa_d2i_key_params             (d2i_of_void *)d2i_DSAparams
+
+static void *dsa_d2i_PKCS8(void **key, const unsigned char **der, long der_len,
+                           struct der2key_ctx_st *ctx,
+                           OSSL_PASSPHRASE_CALLBACK *pw_cb, void *pw_cbarg)
+{
+    return der2key_decode_p8(der, der_len, ctx, pw_cb, pw_cbarg,
+                             (key_from_pkcs8_t *)ossl_dsa_key_from_pkcs8);
+}
+
 # define dsa_d2i_PUBKEY                 (d2i_of_void *)d2i_DSA_PUBKEY
 # define dsa_free                       (free_key_fn *)DSA_free
 # define dsa_check                      NULL
@@ -499,10 +458,18 @@ static void dsa_adjust(void *key, struct der2key_ctx_st *ctx)
 
 #ifndef OPENSSL_NO_EC
 # define ec_evp_type                    EVP_PKEY_EC
-# define ec_evp_extract                 (extract_key_fn *)EVP_PKEY_get1_EC_KEY
 # define ec_d2i_private_key             (d2i_of_void *)d2i_ECPrivateKey
 # define ec_d2i_public_key              NULL
 # define ec_d2i_key_params              (d2i_of_void *)d2i_ECParameters
+
+static void *ec_d2i_PKCS8(void **key, const unsigned char **der, long der_len,
+                          struct der2key_ctx_st *ctx,
+                          OSSL_PASSPHRASE_CALLBACK *pw_cb, void *pw_cbarg)
+{
+    return der2key_decode_p8(der, der_len, ctx, pw_cb, pw_cbarg,
+                             (key_from_pkcs8_t *)ossl_ec_key_from_pkcs8);
+}
+
 # define ec_d2i_PUBKEY                  (d2i_of_void *)d2i_EC_PUBKEY
 # define ec_free                        (free_key_fn *)EC_KEY_free
 
@@ -525,46 +492,54 @@ static void ec_adjust(void *key, struct der2key_ctx_st *ctx)
  * so no d2i functions to be had.
  */
 
+static void *ecx_d2i_PKCS8(void **key, const unsigned char **der, long der_len,
+                           struct der2key_ctx_st *ctx,
+                           OSSL_PASSPHRASE_CALLBACK *pw_cb, void *pw_cbarg)
+{
+    return der2key_decode_p8(der, der_len, ctx, pw_cb, pw_cbarg,
+                             (key_from_pkcs8_t *)ossl_ecx_key_from_pkcs8);
+}
+
 static void ecx_key_adjust(void *key, struct der2key_ctx_st *ctx)
 {
     ossl_ecx_key_set0_libctx(key, PROV_LIBCTX_OF(ctx->provctx));
 }
 
 # define ed25519_evp_type               EVP_PKEY_ED25519
-# define ed25519_evp_extract            (extract_key_fn *)ossl_evp_pkey_get1_ED25519
 # define ed25519_d2i_private_key        NULL
 # define ed25519_d2i_public_key         NULL
 # define ed25519_d2i_key_params         NULL
+# define ed25519_d2i_PKCS8              ecx_d2i_PKCS8
 # define ed25519_d2i_PUBKEY             (d2i_of_void *)ossl_d2i_ED25519_PUBKEY
 # define ed25519_free                   (free_key_fn *)ossl_ecx_key_free
 # define ed25519_check                  NULL
 # define ed25519_adjust                 ecx_key_adjust
 
 # define ed448_evp_type                 EVP_PKEY_ED448
-# define ed448_evp_extract              (extract_key_fn *)ossl_evp_pkey_get1_ED448
 # define ed448_d2i_private_key          NULL
 # define ed448_d2i_public_key           NULL
 # define ed448_d2i_key_params           NULL
+# define ed448_d2i_PKCS8                ecx_d2i_PKCS8
 # define ed448_d2i_PUBKEY               (d2i_of_void *)ossl_d2i_ED448_PUBKEY
 # define ed448_free                     (free_key_fn *)ossl_ecx_key_free
 # define ed448_check                    NULL
 # define ed448_adjust                   ecx_key_adjust
 
 # define x25519_evp_type                EVP_PKEY_X25519
-# define x25519_evp_extract             (extract_key_fn *)ossl_evp_pkey_get1_X25519
 # define x25519_d2i_private_key         NULL
 # define x25519_d2i_public_key          NULL
 # define x25519_d2i_key_params          NULL
+# define x25519_d2i_PKCS8               ecx_d2i_PKCS8
 # define x25519_d2i_PUBKEY              (d2i_of_void *)ossl_d2i_X25519_PUBKEY
 # define x25519_free                    (free_key_fn *)ossl_ecx_key_free
 # define x25519_check                   NULL
 # define x25519_adjust                  ecx_key_adjust
 
 # define x448_evp_type                  EVP_PKEY_X448
-# define x448_evp_extract               (extract_key_fn *)ossl_evp_pkey_get1_X448
 # define x448_d2i_private_key           NULL
 # define x448_d2i_public_key            NULL
 # define x448_d2i_key_params            NULL
+# define x448_d2i_PKCS8                 ecx_d2i_PKCS8
 # define x448_d2i_PUBKEY                (d2i_of_void *)ossl_d2i_X448_PUBKEY
 # define x448_free                      (free_key_fn *)ossl_ecx_key_free
 # define x448_check                     NULL
@@ -572,10 +547,18 @@ static void ecx_key_adjust(void *key, struct der2key_ctx_st *ctx)
 
 # ifndef OPENSSL_NO_SM2
 #  define sm2_evp_type                  EVP_PKEY_SM2
-#  define sm2_evp_extract               (extract_key_fn *)EVP_PKEY_get1_EC_KEY
 #  define sm2_d2i_private_key           (d2i_of_void *)d2i_ECPrivateKey
 #  define sm2_d2i_public_key            NULL
 #  define sm2_d2i_key_params            (d2i_of_void *)d2i_ECParameters
+
+static void *sm2_d2i_PKCS8(void **key, const unsigned char **der, long der_len,
+                           struct der2key_ctx_st *ctx,
+                           OSSL_PASSPHRASE_CALLBACK *pw_cb, void *pw_cbarg)
+{
+    return der2key_decode_p8(der, der_len, ctx, pw_cb, pw_cbarg,
+                             (key_from_pkcs8_t *)ossl_ec_key_from_pkcs8);
+}
+
 #  define sm2_d2i_PUBKEY                (d2i_of_void *)d2i_EC_PUBKEY
 #  define sm2_free                      (free_key_fn *)EC_KEY_free
 #  define sm2_check                     ec_check
@@ -586,10 +569,18 @@ static void ecx_key_adjust(void *key, struct der2key_ctx_st *ctx)
 /* ---------------------------------------------------------------------- */
 
 #define rsa_evp_type                    EVP_PKEY_RSA
-#define rsa_evp_extract                 (extract_key_fn *)EVP_PKEY_get1_RSA
 #define rsa_d2i_private_key             (d2i_of_void *)d2i_RSAPrivateKey
 #define rsa_d2i_public_key              (d2i_of_void *)d2i_RSAPublicKey
 #define rsa_d2i_key_params              NULL
+
+static void *rsa_d2i_PKCS8(void **key, const unsigned char **der, long der_len,
+                           struct der2key_ctx_st *ctx,
+                           OSSL_PASSPHRASE_CALLBACK *pw_cb, void *pw_cbarg)
+{
+    return der2key_decode_p8(der, der_len, ctx, pw_cb, pw_cbarg,
+                             (key_from_pkcs8_t *)ossl_rsa_key_from_pkcs8);
+}
+
 #define rsa_d2i_PUBKEY                  (d2i_of_void *)d2i_RSA_PUBKEY
 #define rsa_free                        (free_key_fn *)RSA_free
 
@@ -612,10 +603,10 @@ static void rsa_adjust(void *key, struct der2key_ctx_st *ctx)
 }
 
 #define rsapss_evp_type                 EVP_PKEY_RSA_PSS
-#define rsapss_evp_extract              (extract_key_fn *)EVP_PKEY_get1_RSA
 #define rsapss_d2i_private_key          (d2i_of_void *)d2i_RSAPrivateKey
 #define rsapss_d2i_public_key           (d2i_of_void *)d2i_RSAPublicKey
 #define rsapss_d2i_key_params           NULL
+#define rsapss_d2i_PKCS8                rsa_d2i_PKCS8
 #define rsapss_d2i_PUBKEY               (d2i_of_void *)d2i_RSA_PUBKEY
 #define rsapss_free                     (free_key_fn *)RSA_free
 #define rsapss_check                    rsa_check
@@ -706,8 +697,8 @@ static void rsa_adjust(void *key, struct der2key_ctx_st *ctx)
         NULL,                                           \
         NULL,                                           \
         NULL,                                           \
+        keytype##_d2i_PKCS8,                            \
         NULL,                                           \
-        keytype##_evp_extract,                          \
         keytype##_check,                                \
         keytype##_adjust,                               \
         keytype##_free
@@ -718,8 +709,8 @@ static void rsa_adjust(void *key, struct der2key_ctx_st *ctx)
         NULL,                                           \
         NULL,                                           \
         NULL,                                           \
+        NULL,                                           \
         keytype##_d2i_PUBKEY,                           \
-        keytype##_evp_extract,                          \
         keytype##_check,                                \
         keytype##_adjust,                               \
         keytype##_free