]> git.ipfire.org Git - thirdparty/openssl.git/commitdiff
Add additional EVP_SKEY helpers
authorSimo Sorce <simo@redhat.com>
Tue, 14 Jan 2025 22:53:28 +0000 (17:53 -0500)
committerDmitry Belyavskiy <beldmit@gmail.com>
Sat, 15 Feb 2025 17:51:31 +0000 (18:51 +0100)
EVP_SKEY_is_a() allows to check if a key is of a specific type.
EVP_SKEY_to_provider() provides an easy way to move a key to a
different provider.

Signed-off-by: Simo Sorce <simo@redhat.com>
Reviewed-by: Tomas Mraz <tomas@openssl.org>
Reviewed-by: Tim Hudson <tjh@openssl.org>
Reviewed-by: Dmitry Belyavskiy <beldmit@gmail.com>
(Merged from https://github.com/openssl/openssl/pull/26753)

crypto/evp/s_lib.c
doc/man3/EVP_SKEY.pod
include/openssl/evp.h
util/libcrypto.num

index efe83adab26304f809d6fee4b7259d2a26a597ce..3738f2e5fc91c6a9759643623ec2f9cfb2d39df7 100644 (file)
@@ -233,3 +233,78 @@ const char *EVP_SKEY_get0_provider_name(const EVP_SKEY *skey)
 
     return ossl_provider_name(skey->skeymgmt->prov);
 }
+
+int EVP_SKEY_is_a(const EVP_SKEY *skey, const char *name)
+{
+    if (skey == NULL)
+        return 0;
+
+    if (skey->skeymgmt == NULL)
+        return 0;
+
+    return EVP_SKEYMGMT_is_a(skey->skeymgmt, name);
+}
+
+struct transfer_cb_ctx {
+    int selection;
+    EVP_SKEYMGMT *skeymgmt;
+    void *keydata;
+};
+
+static int transfer_cb(const OSSL_PARAM params[], void *arg)
+{
+    struct transfer_cb_ctx *ctx = arg;
+
+    ctx->keydata = evp_skeymgmt_import(ctx->skeymgmt, ctx->selection, params);
+    return 1;
+}
+
+EVP_SKEY *EVP_SKEY_to_provider(EVP_SKEY *skey, OSSL_LIB_CTX *libctx,
+                               OSSL_PROVIDER *prov, const char *propquery)
+{
+    struct transfer_cb_ctx ctx = { 0 };
+    EVP_SKEYMGMT *skeymgmt = NULL;
+    EVP_SKEY *ret = NULL;
+
+    if (prov != NULL) {
+        skeymgmt = evp_skeymgmt_fetch_from_prov(prov, skey->skeymgmt->type_name,
+                                                propquery);
+
+    } else {
+        /* If no provider, get the default skeymgmt */
+        skeymgmt = EVP_SKEYMGMT_fetch(libctx, skey->skeymgmt->type_name,
+                                      propquery);
+    }
+
+    /* Short-circuit if destination provider is the same as origin */
+    if (skey->skeymgmt->name_id == skeymgmt->name_id
+        && skey->skeymgmt->prov == skeymgmt->prov) {
+        if (!EVP_SKEY_up_ref(skey))
+            goto err;
+        EVP_SKEYMGMT_free(skeymgmt);
+        return skey;
+    }
+
+    ctx.selection = OSSL_SKEYMGMT_SELECT_ALL;
+    ctx.skeymgmt = skeymgmt;
+
+    if (!EVP_SKEY_export(skey, ctx.selection, transfer_cb, &ctx))
+        goto err;
+
+    if (ctx.keydata == NULL)
+        goto err;
+
+    ret = evp_skey_alloc();
+    if (ret == NULL)
+        goto err;
+
+    ret->keydata = ctx.keydata;
+    ret->skeymgmt = skeymgmt;
+
+    return ret;
+
+ err:
+    EVP_SKEYMGMT_free(skeymgmt);
+    EVP_SKEY_free(ret);
+    return NULL;
+}
index 580d26ac056282a666f298230eb625a9c0344747..8ff05e6645e64f7f5237d151e84aab93697ec830 100644 (file)
@@ -6,7 +6,7 @@ EVP_SKEY, EVP_SKEY_generate,
 EVP_SKEY_import, EVP_SKEY_import_raw_key, EVP_SKEY_up_ref,
 EVP_SKEY_export, EVP_SKEY_get_raw_key, EVP_SKEY_get0_key_id,
 EVP_SKEY_get0_skeymgmt_name, EVP_SKEY_get0_provider_name,
-EVP_SKEY_free
+EVP_SKEY_free, EVP_SKEY_is_a, EVP_SKEY_to_provider
 - opaque symmetric key allocation and handling functions
 
 =head1 SYNOPSIS
@@ -34,6 +34,10 @@ EVP_SKEY_free
 
  int EVP_SKEY_up_ref(EVP_SKEY *key);
  void EVP_SKEY_free(EVP_SKEY *key);
+ int EVP_SKEY_is_a(const EVP_SKEY *skey, const char *name);
+ EVP_SKEY *EVP_SKEY_to_provider(EVP_SKEY *skey, OSSL_LIB_CTX *libctx,
+                                OSSL_PROVIDER *prov, const char *propquery);
+
 
 =head1 DESCRIPTION
 
@@ -77,6 +81,12 @@ EVP_SKEY_up_ref() increments the reference count of I<key>.
 EVP_SKEY_free() decrements the reference count of I<key> and, if the reference
 count is zero, frees it. If I<key> is NULL, nothing is done.
 
+EVP_SKEY_is_a() checks if the key type of I<skey> is I<name>.
+
+EVP_SKEY_to_provider() simplifies the task of importing a I<skey> into a
+different provider identified by I<prov>. If I<prov> is NULL, the default
+provider for the key type identified via I<skey> is used.
+
 =head2 Selections
 
 The following constants can be used for I<selection>:
@@ -103,6 +113,9 @@ All parameters will be selected.
 The B<EVP_SKEY> structure is used by various OpenSSL functions which require a
 general symmetric key without reference to any particular algorithm.
 
+The EVP_SKEY_to_provider() function will fail and return NULL if the origin
+key I<skey> cannot be exported from its provider.
+
 =head1 RETURN VALUES
 
 EVP_SKEY_generate(), EVP_SKEY_import() and EVP_SKEY_import_raw_key() return
@@ -117,6 +130,12 @@ EVP_SKEY_export() and EVP_SKEY_get_raw_key() return 1 for success and 0 on failu
 EVP_SKEY_get0_skeymgmt_name() and EVP_SKEY_get0_provider_name() return the
 names of the associated EVP_SKEYMGMT object and its provider correspondigly.
 
+EVP_SKEY_is_a() returns 1 if I<skey> has the key type I<name>,
+otherwise 0.
+
+EVP_SKEY_to_provider() returns a new B<EVP_SKEY> suitable for operations with
+the I<prov> provider or NULL in case of failure.
+
 =head1 SEE ALSO
 
 L<EVP_SKEYMGMT(3)>, L<provider(7)>, L<OSSL_PARAM(3)>
@@ -126,8 +145,8 @@ L<EVP_SKEYMGMT(3)>, L<provider(7)>, L<OSSL_PARAM(3)>
 The B<EVP_SKEY> API and functions EVP_SKEY_export(),
 EVP_SKEY_free(), EVP_SKEY_get_raw_key(), EVP_SKEY_import(),
 EVP_SKEY_import_raw_key(), EVP_SKEY_up_ref(), EVP_SKEY_generate(),
-EVP_SKEY_get0_key_id(), EVP_SKEY_get0_provider_name(), and
-EVP_SKEY_get0_skeymgmt_name()
+EVP_SKEY_get0_key_id(), EVP_SKEY_get0_provider_name(),
+EVP_SKEY_get0_skeymgmt_name(), EVP_SKEY_is_a(), EVP_SKEY_to_provider()
 were introduced in OpenSSL 3.5.
 
 =head1 COPYRIGHT
index 9b41a569770ea0ae7adc21e0e3772e886cf1f8d4..c58377355fa219943b3a534ca5ed110f57d59350 100644 (file)
@@ -2272,6 +2272,7 @@ OSSL_LIB_CTX *EVP_PKEY_CTX_get0_libctx(EVP_PKEY_CTX *ctx);
 const char *EVP_PKEY_CTX_get0_propq(const EVP_PKEY_CTX *ctx);
 const OSSL_PROVIDER *EVP_PKEY_CTX_get0_provider(const EVP_PKEY_CTX *ctx);
 
+int EVP_SKEY_is_a(const EVP_SKEY *skey, const char *name);
 EVP_SKEY *EVP_SKEY_import(OSSL_LIB_CTX *libctx, const char *skeymgmtname, const char *propquery,
                           int selection, const OSSL_PARAM *params);
 EVP_SKEY *EVP_SKEY_generate(OSSL_LIB_CTX *libctx, const char *skeymgmtname,
@@ -2288,6 +2289,8 @@ int EVP_SKEY_up_ref(EVP_SKEY *skey);
 void EVP_SKEY_free(EVP_SKEY *skey);
 const char *EVP_SKEY_get0_skeymgmt_name(const EVP_SKEY *skey);
 const char *EVP_SKEY_get0_provider_name(const EVP_SKEY *skey);
+EVP_SKEY *EVP_SKEY_to_provider(EVP_SKEY *skey, OSSL_LIB_CTX *libctx,
+                               OSSL_PROVIDER *prov, const char *propquery);
 
 # ifdef  __cplusplus
 }
index 25f7122e6760bef8db8be521d9d8812a727a8f28..25f20e40655f845a4aef5499477afce1bc672854 100644 (file)
@@ -5913,6 +5913,8 @@ EVP_SKEY_get0_skeymgmt_name             ? 3_5_0   EXIST::FUNCTION:
 EVP_SKEY_get0_provider_name             ?      3_5_0   EXIST::FUNCTION:
 EVP_SKEYMGMT_get0_gen_settable_params   ?      3_5_0   EXIST::FUNCTION:
 EVP_SKEYMGMT_get0_imp_settable_params   ?      3_5_0   EXIST::FUNCTION:
+EVP_SKEY_is_a                           ?      3_5_0   EXIST::FUNCTION:
+EVP_SKEY_to_provider                    ?      3_5_0   EXIST::FUNCTION:
 OSSL_PROVIDER_add_conf_parameter        ?      3_5_0   EXIST::FUNCTION:
 OSSL_PROVIDER_get_conf_parameters       ?      3_5_0   EXIST::FUNCTION:
 OSSL_PROVIDER_conf_get_bool             ?      3_5_0   EXIST::FUNCTION: