Add additional EVP_SKEY helpers

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)
This commit is contained in:
Simo Sorce 2025-01-14 17:53:28 -05:00 committed by Dmitry Belyavskiy
parent 71debb7b84
commit fc00d9b7b1
4 changed files with 102 additions and 3 deletions

View 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;
}

View 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

View 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
}

View 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: