[openssl] master update

Matt Caswell matt at openssl.org
Mon May 4 08:39:14 UTC 2020


The branch master has been updated
       via  b756626a3732869875c50f150bddacfbcac5a7ab (commit)
       via  86dc26baf65dd2ba83beff80ce37d05a3f6c33b0 (commit)
       via  2b1bc78acc0d7ef3a10ca0cb3d2280375032d137 (commit)
       via  262ff12347f30548080ad904b7d15928221864aa (commit)
       via  48b4b1044906b6bdbf948f11bf54c5b2733c0c94 (commit)
       via  d4fe478df04073abf0657506b58ed3f67443fcaf (commit)
       via  c19d89785075393d27287c90086fa2aeaa842e62 (commit)
       via  f3336f40508dfd4821f0048b149ffb45f8f08875 (commit)
       via  969024b4580172b1cd836550e227d64515c628bc (commit)
       via  a6f8a834ba6f877baa427e3d25694d49beb29306 (commit)
       via  1c4f340dd35f0ca48e263ab85399a965e1125ac6 (commit)
      from  7421f085005e0d7a1dd2fe61b991ff23cef91c22 (commit)


- Log -----------------------------------------------------------------
commit b756626a3732869875c50f150bddacfbcac5a7ab
Author: Matt Caswell <matt at openssl.org>
Date:   Tue Apr 28 17:45:53 2020 +0100

    Allow OSSL_PARAM_get_octet_string() to pass a NULL buffer
    
    We may just want to know the number of octets so allow passing a NULL
    buffer.
    
    Reviewed-by: Shane Lontis <shane.lontis at oracle.com>
    (Merged from https://github.com/openssl/openssl/pull/11635)

commit 86dc26baf65dd2ba83beff80ce37d05a3f6c33b0
Author: Matt Caswell <matt at openssl.org>
Date:   Mon Apr 27 17:17:05 2020 +0100

    Add some tests for the newly added raw private/public key functions
    
    We already had soem tests for the older raw private/public key functions
    so we expand those to call the new versions as well and pass in a libctx.
    
    Reviewed-by: Shane Lontis <shane.lontis at oracle.com>
    (Merged from https://github.com/openssl/openssl/pull/11635)

commit 2b1bc78acc0d7ef3a10ca0cb3d2280375032d137
Author: Matt Caswell <matt at openssl.org>
Date:   Mon Apr 27 16:48:18 2020 +0100

    Document the new raw private/public key functions
    
    Document the newly added EVP_PKEY_new_raw_private_key_with_libctx and
    EVP_PKEY_new_raw_public_key_with_libctx functions.
    
    Reviewed-by: Shane Lontis <shane.lontis at oracle.com>
    (Merged from https://github.com/openssl/openssl/pull/11635)

commit 262ff12347f30548080ad904b7d15928221864aa
Author: Matt Caswell <matt at openssl.org>
Date:   Mon Apr 27 16:14:16 2020 +0100

    Implement key match functionality for ECX keys
    
    This makes EVP_PKEY_cmp work for provider side ECX keys.
    
    Reviewed-by: Shane Lontis <shane.lontis at oracle.com>
    (Merged from https://github.com/openssl/openssl/pull/11635)

commit 48b4b1044906b6bdbf948f11bf54c5b2733c0c94
Author: Matt Caswell <matt at openssl.org>
Date:   Fri Apr 24 17:40:31 2020 +0100

    Fix the KEYNID2TYPE macro
    
    This macro was not correctly handling Ed25519 keys
    
    Reviewed-by: Shane Lontis <shane.lontis at oracle.com>
    (Merged from https://github.com/openssl/openssl/pull/11635)

commit d4fe478df04073abf0657506b58ed3f67443fcaf
Author: Matt Caswell <matt at openssl.org>
Date:   Fri Apr 24 16:20:27 2020 +0100

    Don't export ECX key data twice
    
    We had a redundant couple of lines where we exported key data twice.
    
    Reviewed-by: Shane Lontis <shane.lontis at oracle.com>
    (Merged from https://github.com/openssl/openssl/pull/11635)

commit c19d89785075393d27287c90086fa2aeaa842e62
Author: Matt Caswell <matt at openssl.org>
Date:   Fri Apr 24 16:19:25 2020 +0100

    Ensure EVP_PKEY_get_raw_[private|public]_key work with provider keys
    
    If the key is a provider key then we should export it from the provider.
    
    Fixes #11627
    
    Reviewed-by: Shane Lontis <shane.lontis at oracle.com>
    (Merged from https://github.com/openssl/openssl/pull/11635)

commit f3336f40508dfd4821f0048b149ffb45f8f08875
Author: Matt Caswell <matt at openssl.org>
Date:   Fri Apr 24 15:43:20 2020 +0100

    Add the library ctx into an ECX_KEY
    
    At various points we need to be able to retrieve the current library
    context so we store it in the ECX_KEY structure.
    
    Reviewed-by: Shane Lontis <shane.lontis at oracle.com>
    (Merged from https://github.com/openssl/openssl/pull/11635)

commit 969024b4580172b1cd836550e227d64515c628bc
Author: Matt Caswell <matt at openssl.org>
Date:   Fri Apr 24 15:32:34 2020 +0100

    Add the ability to ECX to import keys with only the private key
    
    ECX keys can very easily crete the public key from the private key.
    Therefore when we import ecx keys it is sufficent to just have the private
    key.
    
    Reviewed-by: Shane Lontis <shane.lontis at oracle.com>
    (Merged from https://github.com/openssl/openssl/pull/11635)

commit a6f8a834ba6f877baa427e3d25694d49beb29306
Author: Matt Caswell <matt at openssl.org>
Date:   Fri Apr 24 11:44:15 2020 +0100

    Ensure OSSL_PARAM_BLD_free() can accept a NULL
    
    All OpenSSL free functions should accept NULL.
    
    Reviewed-by: Shane Lontis <shane.lontis at oracle.com>
    (Merged from https://github.com/openssl/openssl/pull/11635)

commit 1c4f340dd35f0ca48e263ab85399a965e1125ac6
Author: Matt Caswell <matt at openssl.org>
Date:   Fri Apr 24 11:33:33 2020 +0100

    Make EVP_new_raw_[private|public]_key provider aware
    
    We also introduce variants which are OPENSSL_CTX aware
    
    Reviewed-by: Shane Lontis <shane.lontis at oracle.com>
    (Merged from https://github.com/openssl/openssl/pull/11635)

-----------------------------------------------------------------------

Summary of changes:
 crypto/ec/ecx_backend.c                       |  48 ++++--
 crypto/ec/ecx_backend.h                       |   6 +-
 crypto/ec/ecx_key.c                           |   3 +-
 crypto/ec/ecx_meth.c                          |  34 +---
 crypto/evp/p_lib.c                            | 234 +++++++++++++++++++++-----
 crypto/param_build.c                          |   2 +
 crypto/params.c                               |   5 +-
 doc/man3/EVP_PKEY_new.pod                     |  53 ++++--
 doc/man3/OSSL_PARAM_int.pod                   |   4 +-
 include/crypto/ecx.h                          |   4 +-
 include/openssl/evp.h                         |  10 ++
 providers/implementations/keymgmt/ecx_kmgmt.c |  59 +++++--
 test/evp_extra_test.c                         |  53 ++++--
 util/libcrypto.num                            |   2 +
 14 files changed, 397 insertions(+), 120 deletions(-)

diff --git a/crypto/ec/ecx_backend.c b/crypto/ec/ecx_backend.c
index e613337029..042f9ca8da 100644
--- a/crypto/ec/ecx_backend.c
+++ b/crypto/ec/ecx_backend.c
@@ -9,6 +9,8 @@
 
 #include <openssl/core_names.h>
 #include <openssl/params.h>
+#include <openssl/ec.h>
+#include <openssl/err.h>
 #include "crypto/ecx.h"
 #include "ecx_backend.h"
 
@@ -18,10 +20,35 @@
  * implementations alike.
  */
 
+int ecx_public_from_private(ECX_KEY *key)
+{
+    switch (key->type) {
+    case ECX_KEY_TYPE_X25519:
+        X25519_public_from_private(key->pubkey, key->privkey);
+        break;
+    case ECX_KEY_TYPE_ED25519:
+        if (!ED25519_public_from_private(key->libctx, key->pubkey, key->privkey)) {
+            ECerr(0, EC_R_FAILED_MAKING_PUBLIC_KEY);
+            return 0;
+        }
+        break;
+    case ECX_KEY_TYPE_X448:
+        X448_public_from_private(key->pubkey, key->privkey);
+        break;
+    case ECX_KEY_TYPE_ED448:
+        if (!ED448_public_from_private(key->libctx, key->pubkey, key->privkey)) {
+            ECerr(0, EC_R_FAILED_MAKING_PUBLIC_KEY);
+            return 0;
+        }
+        break;
+    }
+    return 1;
+}
+
 int ecx_key_fromdata(ECX_KEY *ecx, const OSSL_PARAM params[],
                      int include_private)
 {
-    size_t privkeylen = 0, pubkeylen;
+    size_t privkeylen = 0, pubkeylen = 0;
     const OSSL_PARAM *param_priv_key = NULL, *param_pub_key;
     unsigned char *pubkey;
 
@@ -32,11 +59,8 @@ int ecx_key_fromdata(ECX_KEY *ecx, const OSSL_PARAM params[],
     if (include_private)
         param_priv_key =
             OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_PRIV_KEY);
-    /*
-     * If a private key is present then a public key must also be present.
-     * Alternatively we've just got a public key.
-     */
-    if (param_pub_key == NULL)
+
+    if (param_pub_key == NULL && param_priv_key == NULL)
         return 0;
 
     if (param_priv_key != NULL
@@ -46,15 +70,19 @@ int ecx_key_fromdata(ECX_KEY *ecx, const OSSL_PARAM params[],
         return 0;
 
     pubkey = ecx->pubkey;
-    if (!OSSL_PARAM_get_octet_string(param_pub_key,
-                                     (void **)&pubkey,
-                                     sizeof(ecx->pubkey), &pubkeylen))
+    if (param_pub_key != NULL
+        && !OSSL_PARAM_get_octet_string(param_pub_key,
+                                        (void **)&pubkey,
+                                         sizeof(ecx->pubkey), &pubkeylen))
         return 0;
 
-    if (pubkeylen != ecx->keylen
+    if ((param_pub_key != NULL && pubkeylen != ecx->keylen)
         || (param_priv_key != NULL && privkeylen != ecx->keylen))
         return 0;
 
+    if (param_pub_key == NULL && !ecx_public_from_private(ecx))
+        return 0;
+
     ecx->haspubkey = 1;
 
     return 1;
diff --git a/crypto/ec/ecx_backend.h b/crypto/ec/ecx_backend.h
index 50ece17abb..2c01294789 100644
--- a/crypto/ec/ecx_backend.h
+++ b/crypto/ec/ecx_backend.h
@@ -13,8 +13,8 @@
                                      : ((id) == EVP_PKEY_X448 ? X448_KEYLEN \
                                                               : ED448_KEYLEN))
 #define KEYNID2TYPE(id) \
-    (IS25519(id) ?  ECX_KEY_TYPE_X25519 \
+    (IS25519(id) ? ((id) == EVP_PKEY_X25519 ? ECX_KEY_TYPE_X25519 \
+                                            : ECX_KEY_TYPE_ED25519) \
                  : ((id) == EVP_PKEY_X448 ? ECX_KEY_TYPE_X448 \
-                                          : ((id) == EVP_PKEY_ED25519 ? ECX_KEY_TYPE_ED25519 \
-                                                                      : ECX_KEY_TYPE_ED448)))
+                                          : ECX_KEY_TYPE_ED448))
 #define KEYLEN(p)       KEYLENID((p)->ameth->pkey_id)
diff --git a/crypto/ec/ecx_key.c b/crypto/ec/ecx_key.c
index 0b43d26ae4..46abd57a74 100644
--- a/crypto/ec/ecx_key.c
+++ b/crypto/ec/ecx_key.c
@@ -10,13 +10,14 @@
 #include <openssl/err.h>
 #include "crypto/ecx.h"
 
-ECX_KEY *ecx_key_new(ECX_KEY_TYPE type, int haspubkey)
+ECX_KEY *ecx_key_new(OPENSSL_CTX *libctx, ECX_KEY_TYPE type, int haspubkey)
 {
     ECX_KEY *ret = OPENSSL_zalloc(sizeof(*ret));
 
     if (ret == NULL)
         return NULL;
 
+    ret->libctx = libctx;
     ret->haspubkey = haspubkey;
     switch (type) {
     case ECX_KEY_TYPE_X25519:
diff --git a/crypto/ec/ecx_meth.c b/crypto/ec/ecx_meth.c
index a9c71f33aa..eedb1c9259 100644
--- a/crypto/ec/ecx_meth.c
+++ b/crypto/ec/ecx_meth.c
@@ -59,7 +59,7 @@ static int ecx_key_op(EVP_PKEY *pkey, int id, const X509_ALGOR *palg,
         }
     }
 
-    key = ecx_key_new(KEYNID2TYPE(id), 1);
+    key = ecx_key_new(libctx, KEYNID2TYPE(id), 1);
     if (key == NULL) {
         ECerr(EC_F_ECX_KEY_OP, ERR_R_MALLOC_FAILURE);
         return 0;
@@ -88,25 +88,9 @@ static int ecx_key_op(EVP_PKEY *pkey, int id, const X509_ALGOR *palg,
         } else {
             memcpy(privkey, p, KEYLENID(id));
         }
-        switch (id) {
-        case EVP_PKEY_X25519:
-            X25519_public_from_private(pubkey, privkey);
-            break;
-        case EVP_PKEY_ED25519:
-            if (!ED25519_public_from_private(libctx, pubkey, privkey)) {
-                ECerr(EC_F_ECX_KEY_OP, EC_R_FAILED_MAKING_PUBLIC_KEY);
-                goto err;
-            }
-            break;
-        case EVP_PKEY_X448:
-            X448_public_from_private(pubkey, privkey);
-            break;
-        case EVP_PKEY_ED448:
-            if (!ED448_public_from_private(libctx, pubkey, privkey)) {
-                ECerr(EC_F_ECX_KEY_OP, EC_R_FAILED_MAKING_PUBLIC_KEY);
-                goto err;
-            }
-            break;
+        if (!ecx_public_from_private(key)) {
+            ECerr(EC_F_ECX_KEY_OP, EC_R_FAILED_MAKING_PUBLIC_KEY);
+            goto err;
         }
     }
 
@@ -455,7 +439,7 @@ static int ecx_generic_import_from(const OSSL_PARAM params[], void *vpctx,
 {
     EVP_PKEY_CTX *pctx = vpctx;
     EVP_PKEY *pkey = EVP_PKEY_CTX_get0_pkey(pctx);
-    ECX_KEY *ecx = ecx_key_new(KEYNID2TYPE(keytype), 0);
+    ECX_KEY *ecx = ecx_key_new(pctx->libctx, KEYNID2TYPE(keytype), 0);
 
     if (ecx == NULL) {
         ERR_raise(ERR_LIB_DH, ERR_R_MALLOC_FAILURE);
@@ -963,7 +947,7 @@ static int s390x_pkey_ecx_keygen25519(EVP_PKEY_CTX *ctx, EVP_PKEY *pkey)
         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
     };
-    ECX_KEY *key = ecx_key_new(ECX_KEY_TYPE_X25519, 1);
+    ECX_KEY *key = ecx_key_new(ctx->libctx, ECX_KEY_TYPE_X25519, 1);
     unsigned char *privkey = NULL, *pubkey;
 
     if (key == NULL) {
@@ -1005,7 +989,7 @@ static int s390x_pkey_ecx_keygen448(EVP_PKEY_CTX *ctx, EVP_PKEY *pkey)
         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
     };
-    ECX_KEY *key = ecx_key_new(ECX_KEY_TYPE_X448, 1);
+    ECX_KEY *key = ecx_key_new(ctx->libctx, ECX_KEY_TYPE_X448, 1);
     unsigned char *privkey = NULL, *pubkey;
 
     if (key == NULL) {
@@ -1050,7 +1034,7 @@ static int s390x_pkey_ecd_keygen25519(EVP_PKEY_CTX *ctx, EVP_PKEY *pkey)
         0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66,
     };
     unsigned char x_dst[32], buff[SHA512_DIGEST_LENGTH];
-    ECX_KEY *key = ecx_key_new(ECX_KEY_TYPE_ED25519, 1);
+    ECX_KEY *key = ecx_key_new(ctx->libctx, ECX_KEY_TYPE_ED25519, 1);
     unsigned char *privkey = NULL, *pubkey;
     unsigned int sz;
 
@@ -1107,7 +1091,7 @@ static int s390x_pkey_ecd_keygen448(EVP_PKEY_CTX *ctx, EVP_PKEY *pkey)
         0x24, 0xbc, 0xb6, 0x6e, 0x71, 0x46, 0x3f, 0x69, 0x00
     };
     unsigned char x_dst[57], buff[114];
-    ECX_KEY *key = ecx_key_new(ECX_KEY_TYPE_ED448, 1);
+    ECX_KEY *key = ecx_key_new(ctx->libctx, ECX_KEY_TYPE_ED448, 1);
     unsigned char *privkey = NULL, *pubkey;
     EVP_MD_CTX *hashctx = NULL;
 
diff --git a/crypto/evp/p_lib.c b/crypto/evp/p_lib.c
index bbeb7276fe..9eb9f4937b 100644
--- a/crypto/evp/p_lib.c
+++ b/crypto/evp/p_lib.c
@@ -28,6 +28,7 @@
 #include <openssl/cmac.h>
 #include <openssl/engine.h>
 #include <openssl/params.h>
+#include <openssl/param_build.h>
 #include <openssl/serializer.h>
 #include <openssl/core_names.h>
 
@@ -320,78 +321,213 @@ int EVP_PKEY_cmp(const EVP_PKEY *a, const EVP_PKEY *b)
     return -2;
 }
 
-EVP_PKEY *EVP_PKEY_new_raw_private_key(int type, ENGINE *e,
-                                       const unsigned char *priv,
-                                       size_t len)
+
+static EVP_PKEY *new_raw_key_int(OPENSSL_CTX *libctx,
+                                 const char *strtype,
+                                 const char *propq,
+                                 int nidtype,
+                                 ENGINE *e,
+                                 const unsigned char *key,
+                                 size_t len,
+                                 int key_is_priv)
 {
-    EVP_PKEY *ret = EVP_PKEY_new();
+    EVP_PKEY *pkey = NULL;
+    EVP_PKEY_CTX *ctx = NULL;
+    const EVP_PKEY_ASN1_METHOD *ameth = NULL;
+    int result = 0;
 
-    if (ret == NULL
-        || !pkey_set_type(ret, e, type, NULL, -1, NULL)) {
-        /* EVPerr already called */
-        goto err;
+# ifndef OPENSSL_NO_ENGINE
+    /* Check if there is an Engine for this type */
+    if (e == NULL) {
+        ENGINE *tmpe = NULL;
+
+        if (strtype != NULL)
+            ameth = EVP_PKEY_asn1_find_str(&tmpe, strtype, -1);
+        else if (nidtype != EVP_PKEY_NONE)
+            ameth = EVP_PKEY_asn1_find(&tmpe, nidtype);
+
+        /* If tmpe is NULL then no engine is claiming to support this type */
+        if (tmpe == NULL)
+            ameth = NULL;
+
+        ENGINE_finish(tmpe);
     }
+# endif
 
-    if (ret->ameth->set_priv_key == NULL) {
-        EVPerr(EVP_F_EVP_PKEY_NEW_RAW_PRIVATE_KEY,
-               EVP_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE);
+    if (e == NULL && ameth == NULL) {
+        /*
+         * No engine is claiming to support this type, so lets see if we have
+         * a provider.
+         */
+        ctx = EVP_PKEY_CTX_new_from_name(libctx,
+                                         strtype != NULL ? strtype
+                                                         : OBJ_nid2sn(nidtype),
+                                         propq);
+        if (ctx == NULL) {
+            EVPerr(0, ERR_R_MALLOC_FAILURE);
+            goto err;
+        }
+        /* May fail if no provider available */
+        ERR_set_mark();
+        if (EVP_PKEY_key_fromdata_init(ctx) == 1) {
+            OSSL_PARAM params[] = { OSSL_PARAM_END, OSSL_PARAM_END };
+
+            ERR_clear_last_mark();
+            params[0] = OSSL_PARAM_construct_octet_string(
+                            key_is_priv ? OSSL_PKEY_PARAM_PRIV_KEY
+                                        : OSSL_PKEY_PARAM_PUB_KEY,
+                            (void *)key, len);
+
+            if (EVP_PKEY_fromdata(ctx, &pkey, params) != 1) {
+                EVPerr(0, EVP_R_KEY_SETUP_FAILED);
+                goto err;
+            }
+
+            EVP_PKEY_CTX_free(ctx);
+
+            return pkey;
+        }
+        ERR_pop_to_mark();
+        /* else not supported so fallback to legacy */
+    }
+
+    /* Legacy code path */
+
+    pkey = EVP_PKEY_new();
+    if (pkey == NULL) {
+        EVPerr(0, ERR_R_MALLOC_FAILURE);
         goto err;
     }
 
-    if (!ret->ameth->set_priv_key(ret, priv, len)) {
-        EVPerr(EVP_F_EVP_PKEY_NEW_RAW_PRIVATE_KEY, EVP_R_KEY_SETUP_FAILED);
+    if (!pkey_set_type(pkey, e, nidtype, strtype, -1, NULL)) {
+        /* EVPerr already called */
         goto err;
     }
 
-    return ret;
+    if (!ossl_assert(pkey->ameth != NULL))
+        goto err;
 
+    if (key_is_priv) {
+        if (pkey->ameth->set_priv_key == NULL) {
+            EVPerr(0, EVP_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE);
+            goto err;
+        }
+
+        if (!pkey->ameth->set_priv_key(pkey, key, len)) {
+            EVPerr(0, EVP_R_KEY_SETUP_FAILED);
+            goto err;
+        }
+    } else {
+        if (pkey->ameth->set_pub_key == NULL) {
+            EVPerr(0, EVP_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE);
+            goto err;
+        }
+
+        if (!pkey->ameth->set_pub_key(pkey, key, len)) {
+            EVPerr(0, EVP_R_KEY_SETUP_FAILED);
+            goto err;
+        }
+    }
+
+    result = 1;
  err:
-    EVP_PKEY_free(ret);
-    return NULL;
+    if (!result) {
+        EVP_PKEY_free(pkey);
+        pkey = NULL;
+    }
+    EVP_PKEY_CTX_free(ctx);
+    return pkey;
+}
+
+EVP_PKEY *EVP_PKEY_new_raw_private_key_with_libctx(OPENSSL_CTX *libctx,
+                                                   const char *keytype,
+                                                   const char *propq,
+                                                   const unsigned char *priv,
+                                                   size_t len)
+{
+    return new_raw_key_int(libctx, keytype, propq, EVP_PKEY_NONE, NULL, priv,
+                           len, 1);
+}
+
+EVP_PKEY *EVP_PKEY_new_raw_private_key(int type, ENGINE *e,
+                                       const unsigned char *priv,
+                                       size_t len)
+{
+    return new_raw_key_int(NULL, NULL, NULL, type, e, priv, len, 1);
+}
+
+EVP_PKEY *EVP_PKEY_new_raw_public_key_with_libctx(OPENSSL_CTX *libctx,
+                                                  const char *keytype,
+                                                  const char *propq,
+                                                  const unsigned char *pub,
+                                                  size_t len)
+{
+    return new_raw_key_int(libctx, keytype, propq, EVP_PKEY_NONE, NULL, pub,
+                           len, 0);
 }
 
 EVP_PKEY *EVP_PKEY_new_raw_public_key(int type, ENGINE *e,
                                       const unsigned char *pub,
                                       size_t len)
 {
-    EVP_PKEY *ret = EVP_PKEY_new();
+    return new_raw_key_int(NULL, NULL, NULL, type, e, pub, len, 0);
+}
 
-    if (ret == NULL
-        || !pkey_set_type(ret, e, type, NULL, -1, NULL)) {
-        /* EVPerr already called */
-        goto err;
-    }
+struct raw_key_details_st
+{
+    unsigned char **key;
+    size_t *len;
+    int selection;
+};
 
-    if (ret->ameth->set_pub_key == NULL) {
-        EVPerr(EVP_F_EVP_PKEY_NEW_RAW_PUBLIC_KEY,
-               EVP_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE);
-        goto err;
-    }
+static OSSL_CALLBACK get_raw_key_details;
+static int get_raw_key_details(const OSSL_PARAM params[], void *arg)
+{
+    const OSSL_PARAM *p = NULL;
+    struct raw_key_details_st *raw_key = arg;
 
-    if (!ret->ameth->set_pub_key(ret, pub, len)) {
-        EVPerr(EVP_F_EVP_PKEY_NEW_RAW_PUBLIC_KEY, EVP_R_KEY_SETUP_FAILED);
-        goto err;
+    if (raw_key->selection == OSSL_KEYMGMT_SELECT_PRIVATE_KEY) {
+        if ((p = OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_PRIV_KEY))
+                != NULL)
+            return OSSL_PARAM_get_octet_string(p, (void **)raw_key->key,
+                                               SIZE_MAX, raw_key->len);
+    } else if (raw_key->selection == OSSL_KEYMGMT_SELECT_PUBLIC_KEY) {
+        if ((p = OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_PUB_KEY))
+                != NULL)
+            return OSSL_PARAM_get_octet_string(p, (void **)raw_key->key,
+                                               SIZE_MAX, raw_key->len);
     }
 
-    return ret;
-
- err:
-    EVP_PKEY_free(ret);
-    return NULL;
+    return 0;
 }
 
 int EVP_PKEY_get_raw_private_key(const EVP_PKEY *pkey, unsigned char *priv,
                                  size_t *len)
 {
-    /* TODO(3.0) Do we need to do anything about provider side keys? */
-     if (pkey->ameth->get_priv_key == NULL) {
-        EVPerr(EVP_F_EVP_PKEY_GET_RAW_PRIVATE_KEY,
-               EVP_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE);
+    if (pkey->keymgmt != NULL) {
+        struct raw_key_details_st raw_key;
+
+        raw_key.key = priv == NULL ? NULL : &priv;
+        raw_key.len = len;
+        raw_key.selection = OSSL_KEYMGMT_SELECT_PRIVATE_KEY;
+
+        return evp_keymgmt_export(pkey->keymgmt, pkey->keydata,
+                                  OSSL_KEYMGMT_SELECT_PRIVATE_KEY,
+                                  get_raw_key_details, &raw_key);
+    }
+
+    if (pkey->ameth == NULL) {
+        EVPerr(0, EVP_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE);
+        return 0;
+    }
+
+    if (pkey->ameth->get_priv_key == NULL) {
+        EVPerr(0, EVP_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE);
         return 0;
     }
 
     if (!pkey->ameth->get_priv_key(pkey, priv, len)) {
-        EVPerr(EVP_F_EVP_PKEY_GET_RAW_PRIVATE_KEY, EVP_R_GET_RAW_KEY_FAILED);
+        EVPerr(0, EVP_R_GET_RAW_KEY_FAILED);
         return 0;
     }
 
@@ -401,7 +537,23 @@ int EVP_PKEY_get_raw_private_key(const EVP_PKEY *pkey, unsigned char *priv,
 int EVP_PKEY_get_raw_public_key(const EVP_PKEY *pkey, unsigned char *pub,
                                 size_t *len)
 {
-    /* TODO(3.0) Do we need to do anything about provider side keys? */
+    if (pkey->keymgmt != NULL) {
+        struct raw_key_details_st raw_key;
+
+        raw_key.key = pub == NULL ? NULL : &pub;
+        raw_key.len = len;
+        raw_key.selection = OSSL_KEYMGMT_SELECT_PUBLIC_KEY;
+
+        return evp_keymgmt_export(pkey->keymgmt, pkey->keydata,
+                                  OSSL_KEYMGMT_SELECT_PUBLIC_KEY,
+                                  get_raw_key_details, &raw_key);
+    }
+
+    if (pkey->ameth == NULL) {
+        EVPerr(0, EVP_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE);
+        return 0;
+    }
+
      if (pkey->ameth->get_pub_key == NULL) {
         EVPerr(EVP_F_EVP_PKEY_GET_RAW_PUBLIC_KEY,
                EVP_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE);
diff --git a/crypto/param_build.c b/crypto/param_build.c
index 43b194bcea..76522cd377 100644
--- a/crypto/param_build.c
+++ b/crypto/param_build.c
@@ -125,6 +125,8 @@ static void free_all_params(OSSL_PARAM_BLD *bld)
 
 void OSSL_PARAM_BLD_free(OSSL_PARAM_BLD *bld)
 {
+    if (bld == NULL)
+        return;
     free_all_params(bld);
     sk_OSSL_PARAM_BLD_DEF_free(bld->params);
     OPENSSL_free(bld);
diff --git a/crypto/params.c b/crypto/params.c
index 32161d0533..06ae1bc44f 100644
--- a/crypto/params.c
+++ b/crypto/params.c
@@ -780,7 +780,7 @@ static int get_string_internal(const OSSL_PARAM *p, void **val, size_t max_len,
 {
     size_t sz;
 
-    if (val == NULL || p == NULL || p->data_type != type)
+    if ((val == NULL && used_len == NULL) || p == NULL || p->data_type != type)
         return 0;
 
     sz = p->data_size;
@@ -793,6 +793,9 @@ static int get_string_internal(const OSSL_PARAM *p, void **val, size_t max_len,
     if (p->data == NULL)
         return 0;
 
+    if (val == NULL)
+        return 1;
+
     if (*val == NULL) {
         char *const q = OPENSSL_malloc(sz);
 
diff --git a/doc/man3/EVP_PKEY_new.pod b/doc/man3/EVP_PKEY_new.pod
index b3bbe63aec..3efab95671 100644
--- a/doc/man3/EVP_PKEY_new.pod
+++ b/doc/man3/EVP_PKEY_new.pod
@@ -5,7 +5,9 @@
 EVP_PKEY_new,
 EVP_PKEY_up_ref,
 EVP_PKEY_free,
+EVP_PKEY_new_raw_private_key_with_libctx,
 EVP_PKEY_new_raw_private_key,
+EVP_PKEY_new_raw_public_key_with_libctx,
 EVP_PKEY_new_raw_public_key,
 EVP_PKEY_new_CMAC_key,
 EVP_PKEY_new_mac_key,
@@ -21,8 +23,18 @@ EVP_PKEY_get_raw_public_key
  int EVP_PKEY_up_ref(EVP_PKEY *key);
  void EVP_PKEY_free(EVP_PKEY *key);
 
+ EVP_PKEY *EVP_PKEY_new_raw_private_key_with_libctx(OPENSSL_CTX *libctx,
+                                                    const char *keytype,
+                                                    const char *propq,
+                                                    const unsigned char *key,
+                                                    size_t keylen);
  EVP_PKEY *EVP_PKEY_new_raw_private_key(int type, ENGINE *e,
                                         const unsigned char *key, size_t keylen);
+ EVP_PKEY *EVP_PKEY_new_raw_public_key_with_libctx(OPENSSL_CTX *libctx,
+                                                   const char *keytype,
+                                                   const char *propq,
+                                                   const unsigned char *key,
+                                                   size_t keylen);
  EVP_PKEY *EVP_PKEY_new_raw_public_key(int type, ENGINE *e,
                                        const unsigned char *key, size_t keylen);
  EVP_PKEY *EVP_PKEY_new_CMAC_key(ENGINE *e, const unsigned char *priv,
@@ -46,16 +58,34 @@ EVP_PKEY_up_ref() increments the reference count of B<key>.
 EVP_PKEY_free() decrements the reference count of B<key> and, if the reference
 count is zero, frees it up. If B<key> is NULL, nothing is done.
 
-EVP_PKEY_new_raw_private_key() allocates a new B<EVP_PKEY>. If B<e> is non-NULL
-then the new B<EVP_PKEY> structure is associated with the engine B<e>. The
-B<type> argument indicates what kind of key this is. The value should be a NID
-for a public key algorithm that supports raw private keys, i.e. one of
-B<EVP_PKEY_HMAC>, B<EVP_PKEY_POLY1305>, B<EVP_PKEY_SIPHASH>, B<EVP_PKEY_X25519>,
-B<EVP_PKEY_ED25519>, B<EVP_PKEY_X448> or B<EVP_PKEY_ED448>. B<key> points to the
-raw private key data for this B<EVP_PKEY> which should be of length B<keylen>.
-The length should be appropriate for the type of the key. The public key data
-will be automatically derived from the given private key data (if appropriate
-for the algorithm type).
+EVP_PKEY_new_raw_private_key_with_libctx() allocates a new B<EVP_PKEY>. Unless
+an engine should be used for the key type, a provider for the key is found using
+the library context I<libctx> and the property query string I<propq>. The
+I<keytype> argument indicates what kind of key this is. The value should be a
+string for a public key algorithm that supports raw private keys, i.e one of
+"POLY1305", "SIPHASH", "X25519", "ED25519", "X448" or "ED448". Note that you may
+also use "HMAC" which is not a public key algorithm but is treated as such by
+some OpenSSL APIs. You are encouraged to use the EVP_MAC APIs instead for HMAC
+(see L<EVP_MAC(3)>). I<key> points to the raw private key data for this
+B<EVP_PKEY> which should be of length I<keylen>. The length should be
+appropriate for the type of the key. The public key data will be automatically
+derived from the given private key data (if appropriate for the algorithm type).
+
+EVP_PKEY_new_raw_private_key() does the same as
+EVP_PKEY_new_raw_private_key_with_libctx() except that the default library
+context and default property query are used instead. If B<e> is non-NULL then
+the new B<EVP_PKEY> structure is associated with the engine B<e>. The B<type>
+argument indicates what kind of key this is. The value should be a NID for a
+public key algorithm that supports raw private keys, i.e. one of
+B<EVP_PKEY_POLY1305>, B<EVP_PKEY_SIPHASH>, B<EVP_PKEY_X25519>,
+B<EVP_PKEY_ED25519>, B<EVP_PKEY_X448> or B<EVP_PKEY_ED448>. As for
+EVP_PKEY_new_raw_private_key_with_libctx() you may also use B<EVP_PKEY_HMAC>.
+
+EVP_PKEY_new_raw_public_key_with_libctx() works in the same way as
+EVP_PKEY_new_raw_private_key_with_libctx() except that B<key> points to the raw
+public key data. The B<EVP_PKEY> structure will be initialised without any
+private key information. Algorithm types that support raw public keys are
+"X25519", "ED25519", "X448" or "ED448".
 
 EVP_PKEY_new_raw_public_key() works in the same way as
 EVP_PKEY_new_raw_private_key() except that B<key> points to the raw public key
@@ -127,6 +157,9 @@ EVP_PKEY_new_raw_private_key(), EVP_PKEY_new_raw_public_key(),
 EVP_PKEY_new_CMAC_key(), EVP_PKEY_new_raw_private_key() and
 EVP_PKEY_get_raw_public_key() functions were added in OpenSSL 1.1.1.
 
+The EVP_PKEY_new_raw_private_key_with_libctx and
+EVP_PKEY_new_raw_public_key_with_libctx functions were added in OpenSSL 3.0.
+
 =head1 COPYRIGHT
 
 Copyright 2002-2020 The OpenSSL Project Authors. All Rights Reserved.
diff --git a/doc/man3/OSSL_PARAM_int.pod b/doc/man3/OSSL_PARAM_int.pod
index 9126906883..09215184a7 100644
--- a/doc/man3/OSSL_PARAM_int.pod
+++ b/doc/man3/OSSL_PARAM_int.pod
@@ -233,7 +233,9 @@ OSSL_PARAM_get_octet_string() retrieves an OCTET string from the parameter
 pointed to by B<p>.
 The OCTETs are either stored into B<*val> with a length limit of B<max_len> or,
 in the case when B<*val> is B<NULL>, memory is allocated and
-B<max_len> is ignored.
+B<max_len> is ignored. B<*used_len> is populated with the number of OCTETs
+stored. If B<val> is NULL then the OCTETS are not stored, but B<*used_len> is
+still populated.
 If memory is allocated by this function, it must be freed by the caller.
 
 OSSL_PARAM_set_octet_string() sets an OCTET string from the parameter
diff --git a/include/crypto/ecx.h b/include/crypto/ecx.h
index 5ee6b8ce7e..54ce5f2b7c 100644
--- a/include/crypto/ecx.h
+++ b/include/crypto/ecx.h
@@ -61,6 +61,7 @@ typedef enum {
            : EVP_PKEY_ED448)))
 
 struct ecx_key_st {
+    OPENSSL_CTX *libctx;
     unsigned int haspubkey:1;
     unsigned char pubkey[MAX_KEYLEN];
     unsigned char *privkey;
@@ -73,7 +74,7 @@ struct ecx_key_st {
 typedef struct ecx_key_st ECX_KEY;
 
 size_t ecx_key_length(ECX_KEY_TYPE type);
-ECX_KEY *ecx_key_new(ECX_KEY_TYPE type, int haspubkey);
+ECX_KEY *ecx_key_new(OPENSSL_CTX *libctx, ECX_KEY_TYPE type, int haspubkey);
 unsigned char *ecx_key_allocate_privkey(ECX_KEY *key);
 void ecx_key_free(ECX_KEY *key);
 int ecx_key_up_ref(ECX_KEY *key);
@@ -109,6 +110,7 @@ void X448_public_from_private(uint8_t out_public_value[56],
                               const uint8_t private_key[56]);
 
 /* Backend support */
+int ecx_public_from_private(ECX_KEY *key);
 int ecx_key_fromdata(ECX_KEY *ecx, const OSSL_PARAM params[],
                      int include_private);
 
diff --git a/include/openssl/evp.h b/include/openssl/evp.h
index 23cf52df0f..5dc29d1976 100644
--- a/include/openssl/evp.h
+++ b/include/openssl/evp.h
@@ -1518,9 +1518,19 @@ void EVP_PKEY_CTX_set0_keygen_info(EVP_PKEY_CTX *ctx, int *dat, int datlen);
 
 EVP_PKEY *EVP_PKEY_new_mac_key(int type, ENGINE *e,
                                const unsigned char *key, int keylen);
+EVP_PKEY *EVP_PKEY_new_raw_private_key_with_libctx(OPENSSL_CTX *libctx,
+                                                   const char *keytype,
+                                                   const char *propq,
+                                                   const unsigned char *priv,
+                                                   size_t len);
 EVP_PKEY *EVP_PKEY_new_raw_private_key(int type, ENGINE *e,
                                        const unsigned char *priv,
                                        size_t len);
+EVP_PKEY *EVP_PKEY_new_raw_public_key_with_libctx(OPENSSL_CTX *libctx,
+                                                  const char *keytype,
+                                                  const char *propq,
+                                                  const unsigned char *pub,
+                                                  size_t len);
 EVP_PKEY *EVP_PKEY_new_raw_public_key(int type, ENGINE *e,
                                       const unsigned char *pub,
                                       size_t len);
diff --git a/providers/implementations/keymgmt/ecx_kmgmt.c b/providers/implementations/keymgmt/ecx_kmgmt.c
index 2ba8f53e5a..e2b613e5e0 100644
--- a/providers/implementations/keymgmt/ecx_kmgmt.c
+++ b/providers/implementations/keymgmt/ecx_kmgmt.c
@@ -47,6 +47,7 @@ static OSSL_OP_keymgmt_gettable_params_fn x448_gettable_params;
 static OSSL_OP_keymgmt_gettable_params_fn ed25519_gettable_params;
 static OSSL_OP_keymgmt_gettable_params_fn ed448_gettable_params;
 static OSSL_OP_keymgmt_has_fn ecx_has;
+static OSSL_OP_keymgmt_match_fn ecx_match;
 static OSSL_OP_keymgmt_import_fn ecx_import;
 static OSSL_OP_keymgmt_import_types_fn ecx_imexport_types;
 static OSSL_OP_keymgmt_export_fn ecx_export;
@@ -68,22 +69,22 @@ static void *s390x_ecd_keygen448(struct ecx_gen_ctx *gctx);
 
 static void *x25519_new_key(void *provctx)
 {
-    return ecx_key_new(ECX_KEY_TYPE_X25519, 0);
+    return ecx_key_new(PROV_LIBRARY_CONTEXT_OF(provctx), ECX_KEY_TYPE_X25519, 0);
 }
 
 static void *x448_new_key(void *provctx)
 {
-    return ecx_key_new(ECX_KEY_TYPE_X448, 0);
+    return ecx_key_new(PROV_LIBRARY_CONTEXT_OF(provctx), ECX_KEY_TYPE_X448, 0);
 }
 
 static void *ed25519_new_key(void *provctx)
 {
-    return ecx_key_new(ECX_KEY_TYPE_ED25519, 0);
+    return ecx_key_new(PROV_LIBRARY_CONTEXT_OF(provctx), ECX_KEY_TYPE_ED25519, 0);
 }
 
 static void *ed448_new_key(void *provctx)
 {
-    return ecx_key_new(ECX_KEY_TYPE_ED448, 0);
+    return ecx_key_new(PROV_LIBRARY_CONTEXT_OF(provctx), ECX_KEY_TYPE_ED448, 0);
 }
 
 static int ecx_has(void *keydata, int selection)
@@ -104,6 +105,36 @@ static int ecx_has(void *keydata, int selection)
     return ok;
 }
 
+static int ecx_match(const void *keydata1, const void *keydata2, int selection)
+{
+    const ECX_KEY *key1 = keydata1;
+    const ECX_KEY *key2 = keydata2;
+    int ok = 1;
+
+    if ((selection & OSSL_KEYMGMT_SELECT_DOMAIN_PARAMETERS) != 0)
+        ok = ok && key1->type == key2->type;
+    if ((selection & OSSL_KEYMGMT_SELECT_PRIVATE_KEY) != 0) {
+        if ((key1->privkey == NULL && key2->privkey != NULL)
+                || (key1->privkey != NULL && key2->privkey == NULL)
+                || key1->type != key2->type)
+            ok = 0;
+        else
+            ok = ok && (key1->privkey == NULL /* implies key2->privkey == NULL */
+                        || CRYPTO_memcmp(key1->privkey, key2->privkey,
+                                         key1->keylen) == 0);
+    }
+    if ((selection & OSSL_KEYMGMT_SELECT_PUBLIC_KEY) != 0) {
+        if (key1->haspubkey != key2->haspubkey
+                || key1->type != key2->type)
+            ok = 0;
+        else
+            ok = ok && (key1->haspubkey == 0 /* implies key2->haspubkey == 0 */
+                        || CRYPTO_memcmp(key1->pubkey, key2->pubkey,
+                                         key1->keylen) == 0);
+    }
+    return ok;
+}
+
 static int ecx_import(void *keydata, int selection, const OSSL_PARAM params[])
 {
     ECX_KEY *key = keydata;
@@ -113,12 +144,11 @@ static int ecx_import(void *keydata, int selection, const OSSL_PARAM params[])
     if (key == NULL)
         return 0;
 
-    if ((selection & OSSL_KEYMGMT_SELECT_PUBLIC_KEY) == 0)
+    if ((selection & OSSL_KEYMGMT_SELECT_KEYPAIR) == 0)
         return 0;
 
     include_private = ((selection & OSSL_KEYMGMT_SELECT_PRIVATE_KEY) != 0);
-    if ((selection & OSSL_KEYMGMT_SELECT_KEYPAIR) != 0)
-        ok = ok && ecx_key_fromdata(key, params, include_private);
+    ok = ok && ecx_key_fromdata(key, params, include_private);
 
     return ok;
 }
@@ -162,10 +192,6 @@ static int ecx_export(void *keydata, int selection, OSSL_CALLBACK *param_cb,
          && !key_to_params(key, tmpl, NULL))
         goto err;
 
-    if ((selection & OSSL_KEYMGMT_SELECT_KEYPAIR) != 0
-         && !key_to_params(key, tmpl, NULL))
-        goto err;
-
     params = OSSL_PARAM_BLD_to_param(tmpl);
     if (params == NULL)
         goto err;
@@ -326,7 +352,7 @@ static void *ecx_gen(struct ecx_gen_ctx *gctx)
 
     if (gctx == NULL)
         return NULL;
-    if ((key = ecx_key_new(gctx->type, 0)) == NULL) {
+    if ((key = ecx_key_new(gctx->libctx, gctx->type, 0)) == NULL) {
         ERR_raise(ERR_LIB_PROV, ERR_R_MALLOC_FAILURE);
         return NULL;
     }
@@ -425,6 +451,7 @@ static void ecx_gen_cleanup(void *genctx)
         { OSSL_FUNC_KEYMGMT_GET_PARAMS, (void (*) (void))alg##_get_params }, \
         { OSSL_FUNC_KEYMGMT_GETTABLE_PARAMS, (void (*) (void))alg##_gettable_params }, \
         { OSSL_FUNC_KEYMGMT_HAS, (void (*)(void))ecx_has }, \
+        { OSSL_FUNC_KEYMGMT_MATCH, (void (*)(void))ecx_match }, \
         { OSSL_FUNC_KEYMGMT_IMPORT, (void (*)(void))ecx_import }, \
         { OSSL_FUNC_KEYMGMT_IMPORT_TYPES, (void (*)(void))ecx_imexport_types }, \
         { OSSL_FUNC_KEYMGMT_EXPORT, (void (*)(void))ecx_export }, \
@@ -450,7 +477,7 @@ static void *s390x_ecx_keygen25519(struct ecx_gen_ctx *gctx)
         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
     };
-    ECX_KEY *key = ecx_key_new(ECX_KEY_TYPE_X25519, 1);
+    ECX_KEY *key = ecx_key_new(gctx->libctx, ECX_KEY_TYPE_X25519, 1);
     unsigned char *privkey = NULL, *pubkey;
 
     if (key == NULL) {
@@ -490,7 +517,7 @@ static void *s390x_ecx_keygen448(struct ecx_gen_ctx *gctx)
         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
     };
-    ECX_KEY *key = ecx_key_new(ECX_KEY_TYPE_X448, 1);
+    ECX_KEY *key = ecx_key_new(gctx->libctx, ECX_KEY_TYPE_X448, 1);
     unsigned char *privkey = NULL, *pubkey;
 
     if (key == NULL) {
@@ -533,7 +560,7 @@ static void *s390x_ecd_keygen25519(struct ecx_gen_ctx *gctx)
         0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66,
     };
     unsigned char x_dst[32], buff[SHA512_DIGEST_LENGTH];
-    ECX_KEY *key = ecx_key_new(ECX_KEY_TYPE_ED25519, 1);
+    ECX_KEY *key = ecx_key_new(gctx->libctx, ECX_KEY_TYPE_ED25519, 1);
     unsigned char *privkey = NULL, *pubkey;
     unsigned int sz;
     EVP_MD *sha = NULL;
@@ -595,7 +622,7 @@ static void *s390x_ecd_keygen448(struct ecx_gen_ctx *gctx)
         0x24, 0xbc, 0xb6, 0x6e, 0x71, 0x46, 0x3f, 0x69, 0x00
     };
     unsigned char x_dst[57], buff[114];
-    ECX_KEY *key = ecx_key_new(ECX_KEY_TYPE_ED448, 1);
+    ECX_KEY *key = ecx_key_new(gctx->libctx, ECX_KEY_TYPE_ED448, 1);
     unsigned char *privkey = NULL, *pubkey;
     EVP_MD_CTX *hashctx = NULL;
     EVP_MD *shake = NULL;
diff --git a/test/evp_extra_test.c b/test/evp_extra_test.c
index b7e23a162e..9deae29c47 100644
--- a/test/evp_extra_test.c
+++ b/test/evp_extra_test.c
@@ -29,6 +29,8 @@
 #include "internal/sizes.h"
 #include "crypto/evp.h"
 
+static OPENSSL_CTX *testctx = NULL;
+
 /*
  * kExampleRSAKeyDER is an RSA private key in ASN.1, DER format. Of course, you
  * should never use this key anywhere but in an example.
@@ -1005,7 +1007,7 @@ static struct keys_st {
 #endif
 };
 
-static int test_set_get_raw_keys_int(int tst, int pub)
+static int test_set_get_raw_keys_int(int tst, int pub, int uselibctx)
 {
     int ret = 0;
     unsigned char buf[80];
@@ -1022,17 +1024,34 @@ static int test_set_get_raw_keys_int(int tst, int pub)
     if (pub) {
         inlen = strlen(keys[tst].pub);
         in = (unsigned char *)keys[tst].pub;
-        pkey = EVP_PKEY_new_raw_public_key(keys[tst].type,
-                                           NULL,
-                                           in,
-                                           inlen);
+        if (uselibctx) {
+            pkey = EVP_PKEY_new_raw_public_key_with_libctx(
+                        testctx,
+                        OBJ_nid2sn(keys[tst].type),
+                        NULL,
+                        in,
+                        inlen);
+        } else {
+            pkey = EVP_PKEY_new_raw_public_key(keys[tst].type,
+                                               NULL,
+                                               in,
+                                               inlen);
+        }
     } else {
         inlen = strlen(keys[tst].priv);
         in = (unsigned char *)keys[tst].priv;
-        pkey = EVP_PKEY_new_raw_private_key(keys[tst].type,
-                                            NULL,
-                                            in,
-                                            inlen);
+        if (uselibctx) {
+            pkey = EVP_PKEY_new_raw_private_key_with_libctx(
+                        testctx, OBJ_nid2sn(keys[tst].type),
+                        NULL,
+                        in,
+                        inlen);
+        } else {
+            pkey = EVP_PKEY_new_raw_private_key(keys[tst].type,
+                                                NULL,
+                                                in,
+                                                inlen);
+        }
     }
 
     if (!TEST_ptr(pkey)
@@ -1052,8 +1071,10 @@ static int test_set_get_raw_keys_int(int tst, int pub)
 
 static int test_set_get_raw_keys(int tst)
 {
-    return test_set_get_raw_keys_int(tst, 0)
-           && test_set_get_raw_keys_int(tst, 1);
+    return test_set_get_raw_keys_int(tst, 0, 0)
+           && test_set_get_raw_keys_int(tst, 0, 1)
+           && test_set_get_raw_keys_int(tst, 1, 0)
+           && test_set_get_raw_keys_int(tst, 1, 1);
 }
 
 static int pkey_custom_check(EVP_PKEY *pkey)
@@ -1583,6 +1604,11 @@ static int test_keygen_with_empty_template(int n)
 
 int setup_tests(void)
 {
+    testctx = OPENSSL_CTX_new();
+
+    if (!TEST_ptr(testctx))
+        return 0;
+
     ADD_ALL_TESTS(test_EVP_DigestSignInit, 9);
     ADD_TEST(test_EVP_DigestVerifyInit);
     ADD_TEST(test_EVP_Enveloped);
@@ -1624,3 +1650,8 @@ int setup_tests(void)
 
     return 1;
 }
+
+void cleanup_tests(void)
+{
+    OPENSSL_CTX_free(testctx);
+}
diff --git a/util/libcrypto.num b/util/libcrypto.num
index ec0e6a171b..82ae2e7e84 100644
--- a/util/libcrypto.num
+++ b/util/libcrypto.num
@@ -5081,3 +5081,5 @@ OSSL_PARAM_modified                     ?	3_0_0	EXIST::FUNCTION:
 OSSL_PARAM_set_all_unmodified           ?	3_0_0	EXIST::FUNCTION:
 EVP_default_properties_is_fips_enabled  ?	3_0_0	EXIST::FUNCTION:
 EVP_default_properties_enable_fips      ?	3_0_0	EXIST::FUNCTION:
+EVP_PKEY_new_raw_private_key_with_libctx ?	3_0_0	EXIST::FUNCTION:
+EVP_PKEY_new_raw_public_key_with_libctx ?	3_0_0	EXIST::FUNCTION:


More information about the openssl-commits mailing list