diff --git a/crypto/evp/s_lib.c b/crypto/evp/s_lib.c index efe83adab2630..3738f2e5fc91c 100644 --- a/crypto/evp/s_lib.c +++ b/crypto/evp/s_lib.c @@ -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; +} diff --git a/doc/man3/EVP_SKEY.pod b/doc/man3/EVP_SKEY.pod index 580d26ac05628..8ff05e6645e64 100644 --- a/doc/man3/EVP_SKEY.pod +++ b/doc/man3/EVP_SKEY.pod @@ -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. EVP_SKEY_free() decrements the reference count of I and, if the reference count is zero, frees it. If I is NULL, nothing is done. +EVP_SKEY_is_a() checks if the key type of I is I. + +EVP_SKEY_to_provider() simplifies the task of importing a I into a +different provider identified by I. If I is NULL, the default +provider for the key type identified via I is used. + =head2 Selections The following constants can be used for I: @@ -103,6 +113,9 @@ All parameters will be selected. The B 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 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 has the key type I, +otherwise 0. + +EVP_SKEY_to_provider() returns a new B suitable for operations with +the I provider or NULL in case of failure. + =head1 SEE ALSO L, L, L @@ -126,8 +145,8 @@ L, L, L The B 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 diff --git a/include/openssl/evp.h b/include/openssl/evp.h index ab02c79b68297..e6cd3211c0d54 100644 --- a/include/openssl/evp.h +++ b/include/openssl/evp.h @@ -2268,6 +2268,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, @@ -2284,6 +2285,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 } diff --git a/util/libcrypto.num b/util/libcrypto.num index e47db5e4eb71c..913382b42a441 100644 --- a/util/libcrypto.num +++ b/util/libcrypto.num @@ -5899,3 +5899,5 @@ 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: