Skip to content

Commit

Permalink
Add additional EVP_SKEY helpers
Browse files Browse the repository at this point in the history
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 <[email protected]>
  • Loading branch information
simo5 authored and beldmit committed Jan 28, 2025
1 parent 0fe757d commit a6c74c4
Show file tree
Hide file tree
Showing 5 changed files with 119 additions and 6 deletions.
19 changes: 16 additions & 3 deletions crypto/evp/kdf_lib.c
Original file line number Diff line number Diff line change
Expand Up @@ -176,11 +176,24 @@ int EVP_KDF_CTX_set_SKEY(EVP_KDF_CTX *ctx, EVP_SKEY *key)
return 0;

if (ctx->meth->set_skey != NULL) {
EVP_SKEY *tmp_key = NULL;
int ret;

/* Transfer key to meth provider if different from key's */
if (ctx->meth->prov != key->skeymgmt->prov) {
/* TODO: export/import dance */
return 0;
/* FIXME: no libctx, no propquery */
tmp_key = EVP_SKEY_to_provider(key, NULL, ctx->meth->prov, NULL);
if (tmp_key == NULL)
return 0;
} else {
tmp_key = key;
}
return ctx->meth->set_skey(ctx->algctx, key->keydata);

ret = ctx->meth->set_skey(ctx->algctx, tmp_key->keydata);
if (tmp_key != key)
EVP_SKEY_free(tmp_key);

return ret;
} else {
/*
* Provider does not support opaque keys, try to export and
Expand Down
76 changes: 76 additions & 0 deletions crypto/evp/s_lib.c
Original file line number Diff line number Diff line change
Expand Up @@ -231,3 +231,79 @@ 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) {
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_int();
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;
}
25 changes: 22 additions & 3 deletions doc/man3/EVP_SKEY.pod
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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

Expand Down Expand Up @@ -80,6 +84,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 up. 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>:
Expand All @@ -106,6 +116,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
Expand All @@ -120,6 +133,12 @@ EVP_SKEY_export() and EVP_SKEY_get_raw_key() return 1 for success and 0 for fail
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> quiteable 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)>
Expand All @@ -129,8 +148,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
Expand Down
3 changes: 3 additions & 0 deletions include/openssl/evp.h
Original file line number Diff line number Diff line change
Expand Up @@ -2270,6 +2270,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,
Expand All @@ -2286,6 +2287,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
}
Expand Down
2 changes: 2 additions & 0 deletions util/libcrypto.num
Original file line number Diff line number Diff line change
Expand Up @@ -5902,3 +5902,5 @@ 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_KDF_CTX_set_SKEY ? 3_5_0 EXIST::FUNCTION:
EVP_SKEY_is_a ? 3_5_0 EXIST::FUNCTION:
EVP_SKEY_to_provider ? 3_5_0 EXIST::FUNCTION:

0 comments on commit a6c74c4

Please sign in to comment.