diff --git a/crypto/evp/kdf_lib.c b/crypto/evp/kdf_lib.c index 14b697cef361a..41062ad77b8b7 100644 --- a/crypto/evp/kdf_lib.c +++ b/crypto/evp/kdf_lib.c @@ -19,6 +19,7 @@ #include "internal/numbers.h" #include "internal/provider.h" #include "evp_local.h" +#include "internal/param_build_set.h" EVP_KDF_CTX *EVP_KDF_CTX_new(EVP_KDF *kdf) { @@ -144,6 +145,66 @@ int EVP_KDF_derive(EVP_KDF_CTX *ctx, unsigned char *key, size_t keylen, return ctx->meth->derive(ctx->algctx, key, keylen, params); } +struct convert_key { + const char *name; + OSSL_PARAM *param; +}; + +static int convert_key_cb(const OSSL_PARAM params[], void *arg) +{ + struct convert_key *ckey = arg; + const OSSL_PARAM *raw_bytes; + unsigned char *data; + size_t len; + + raw_bytes = OSSL_PARAM_locate_const(params, OSSL_SKEY_PARAM_RAW_BYTES); + if (raw_bytes == NULL) + return 0; + + if (!OSSL_PARAM_get_octet_string_ptr(raw_bytes, (const void **)&data, &len)) + return 0; + + *ckey->param = OSSL_PARAM_construct_octet_string(ckey->name, data, len); + return 1; +} + +int EVP_KDF_CTX_set_SKEY(EVP_KDF_CTX *ctx, EVP_SKEY *key, const char *paramname) +{ + struct convert_key ckey; + + if (ctx == NULL) + return 0; + + ckey.name = (paramname != NULL) ? paramname : OSSL_KDF_PARAM_KEY; + + if (ctx->meth->set_skey != NULL) { + if (ctx->meth->prov != key->skeymgmt->prov) { + /* TODO: export/import dance */ + return 0; + } + return ctx->meth->set_skey(ctx->algctx, key->keydata, ckey.name); + } else { + /* + * Provider does not support opaque keys, try to export and + * set params. + */ + OSSL_PARAM params[2] = { + OSSL_PARAM_END, + OSSL_PARAM_END, + }; + ckey.param = ¶ms[0]; + + if (!ctx->meth->set_ctx_params) + return 0; + + if (EVP_SKEY_export(key, OSSL_SKEYMGMT_SELECT_SECRET_KEY, + convert_key_cb, &ckey)) + return ctx->meth->set_ctx_params(ctx->algctx, params); + + return 0; + } +} + EVP_SKEY *EVP_KDF_derive_SKEY(EVP_KDF_CTX *ctx, const char *key_type, size_t keylen, const OSSL_PARAM params[]) { diff --git a/crypto/evp/kdf_meth.c b/crypto/evp/kdf_meth.c index b751131299606..116c8c825437d 100644 --- a/crypto/evp/kdf_meth.c +++ b/crypto/evp/kdf_meth.c @@ -137,6 +137,11 @@ static void *evp_kdf_from_algorithm(int name_id, break; kdf->set_ctx_params = OSSL_FUNC_kdf_set_ctx_params(fns); break; + case OSSL_FUNC_KDF_SET_SKEY: + if (kdf->set_skey != NULL) + break; + kdf->set_skey = OSSL_FUNC_kdf_set_skey(fns); + break; case OSSL_FUNC_KDF_DERIVE_SKEY: if (kdf->derive_skey != NULL) break; diff --git a/doc/man3/EVP_KDF.pod b/doc/man3/EVP_KDF.pod index 41e584ba74cf9..8c7e1718984b9 100644 --- a/doc/man3/EVP_KDF.pod +++ b/doc/man3/EVP_KDF.pod @@ -4,7 +4,8 @@ EVP_KDF, EVP_KDF_fetch, EVP_KDF_free, EVP_KDF_up_ref, EVP_KDF_CTX, EVP_KDF_CTX_new, EVP_KDF_CTX_free, EVP_KDF_CTX_dup, -EVP_KDF_CTX_reset, EVP_KDF_derive, EVP_KDF_derive_SKEY, +EVP_KDF_CTX_reset, EVP_KDF_derive, +EVP_KDF_CTX_set_SKEY, EVP_KDF_derive_SKEY, EVP_KDF_CTX_get_kdf_size, EVP_KDF_get0_provider, EVP_KDF_CTX_kdf, EVP_KDF_is_a, EVP_KDF_get0_name, EVP_KDF_names_do_all, EVP_KDF_get0_description, @@ -28,6 +29,7 @@ EVP_KDF_CTX_gettable_params, EVP_KDF_CTX_settable_params - EVP KDF routines size_t EVP_KDF_CTX_get_kdf_size(EVP_KDF_CTX *ctx); int EVP_KDF_derive(EVP_KDF_CTX *ctx, unsigned char *key, size_t keylen, const OSSL_PARAM params[]); + int EVP_KDF_CTX_set_SKEY(EVP_KDF_CTX *ctx, EVP_SKEY *key, const char *paramname); EVP_SKEY *EVP_KDF_derive_SKEY(EVP_KDF_CTX *ctx, EVP_SKEYMGMT *skeymgmt, const OSSL_PARAM params[]); int EVP_KDF_up_ref(EVP_KDF *kdf); @@ -62,8 +64,8 @@ algorithms and should be used instead of algorithm-specific functions. After creating a B for the required algorithm using EVP_KDF_CTX_new(), inputs to the algorithm are supplied either by passing them as part of the EVP_KDF_derive() or EVP_KDF_derive_SKEY() call or using calls to -EVP_KDF_CTX_set_params() before calling EVP_KDF_derive() or -EVP_KDF_derive_SKEY() to derive the key. +EVP_KDF_CTX_set_params() or EVP_KDF_CTX_set_SKEY() before calling +EVP_KDF_derive() or EVP_KDF_derive_SKEY() to derive the key. =head2 Types @@ -115,6 +117,13 @@ If the KDF doesn't support dealing with opaque keys or the passed B is from a different provider than the KDF method, the operation will fail. +EVP_KDF_CTX_set_SKEY() allows setting an skey object as the input key for the +derivation functions. As different KDFs may accept several parameters as key +names, we can specify the particular parameter name we set. +If null is passed, the parameter B is implied. +It is used when the input key is represented by B rather than raw +bytes. + EVP_KDF_get_params() retrieves details about the implementation I. The set of parameters given with I determine exactly what diff --git a/doc/man7/provider-kdf.pod b/doc/man7/provider-kdf.pod index e093cb5c2c74d..fbf25e2b49a35 100644 --- a/doc/man7/provider-kdf.pod +++ b/doc/man7/provider-kdf.pod @@ -37,6 +37,7 @@ provider-kdf - The KDF library E-E provider functions int OSSL_FUNC_kdf_get_params(OSSL_PARAM params[]); int OSSL_FUNC_kdf_get_ctx_params(void *kctx, OSSL_PARAM params[]); int OSSL_FUNC_kdf_set_ctx_params(void *kctx, const OSSL_PARAM params[]); + int OSSL_FUNC_kdf_set_skey(void *kctx, void *skeydata, const char *paramname); =head1 DESCRIPTION @@ -81,6 +82,7 @@ macros in L, as follows: OSSL_FUNC_kdf_gettable_params OSSL_FUNC_KDF_GETTABLE_PARAMS OSSL_FUNC_kdf_gettable_ctx_params OSSL_FUNC_KDF_GETTABLE_CTX_PARAMS OSSL_FUNC_kdf_settable_ctx_params OSSL_FUNC_KDF_SETTABLE_CTX_PARAMS + OSSL_FUNC_kdf_set_skey OSSL_FUNC_KDF_SET_SKEY A KDF algorithm implementation may not implement all of these functions. In order to be a consistent set of functions, at least the following functions @@ -149,6 +151,8 @@ with the provider side context I in its current state if it is not NULL. Otherwise, they return the parameters associated with the provider side algorithm I. +OSSL_FUNF_kdf_set_skey() sets the input key for KDF functions that take a +key as input. Parameters currently recognised by built-in KDFs are as follows. Not all parameters are relevant to, or are understood by all KDFs: @@ -332,8 +336,8 @@ OSSL_FUNC_kdf_newctx() and OSSL_FUNC_kdf_dupctx() should return the newly create provider side KDF context, or NULL on failure. OSSL_FUNC_kdf_derive(), OSSL_FUNC_kdf_derive_skey(), OSSL_FUNC_kdf_get_params(), -OSSL_FUNC_kdf_get_ctx_params() and OSSL_FUNC_kdf_set_ctx_params() should return 1 for -success or 0 on error. +OSSL_FUNC_kdf_get_ctx_params(), OSSL_FUNC_kdf_set_ctx_params() and +OSSL_FUNC_kdf_set_skey() should return 1 for success or 0 on error. OSSL_FUNC_kdf_gettable_params(), OSSL_FUNC_kdf_gettable_ctx_params() and OSSL_FUNC_kdf_settable_ctx_params() should return a constant L diff --git a/include/crypto/evp.h b/include/crypto/evp.h index e8a1d26262179..c3a1acd13d03a 100644 --- a/include/crypto/evp.h +++ b/include/crypto/evp.h @@ -247,6 +247,7 @@ struct evp_kdf_st { OSSL_FUNC_kdf_get_params_fn *get_params; OSSL_FUNC_kdf_get_ctx_params_fn *get_ctx_params; OSSL_FUNC_kdf_set_ctx_params_fn *set_ctx_params; + OSSL_FUNC_kdf_set_skey_fn *set_skey; OSSL_FUNC_kdf_derive_skey_fn *derive_skey; }; diff --git a/include/openssl/core_dispatch.h b/include/openssl/core_dispatch.h index e0763d95d63d1..eae33ba0a6951 100644 --- a/include/openssl/core_dispatch.h +++ b/include/openssl/core_dispatch.h @@ -477,7 +477,8 @@ OSSL_CORE_MAKE_FUNC(int, mac_init_skey, (void *mctx, void *key, const OSSL_PARAM # define OSSL_FUNC_KDF_GET_PARAMS 9 # define OSSL_FUNC_KDF_GET_CTX_PARAMS 10 # define OSSL_FUNC_KDF_SET_CTX_PARAMS 11 -# define OSSL_FUNC_KDF_DERIVE_SKEY 12 +# define OSSL_FUNC_KDF_SET_SKEY 12 +# define OSSL_FUNC_KDF_DERIVE_SKEY 13 OSSL_CORE_MAKE_FUNC(void *, kdf_newctx, (void *provctx)) OSSL_CORE_MAKE_FUNC(void *, kdf_dupctx, (void *src)) @@ -495,7 +496,10 @@ OSSL_CORE_MAKE_FUNC(int, kdf_get_ctx_params, (void *kctx, OSSL_PARAM params[])) OSSL_CORE_MAKE_FUNC(int, kdf_set_ctx_params, (void *kctx, const OSSL_PARAM params[])) -OSSL_CORE_MAKE_FUNC(void *, kdf_derive_skey, (void *kctx, const OSSL_PARAM params[])) +OSSL_CORE_MAKE_FUNC(int, kdf_set_skey, + (void *kctx, void *skeydata, const char *paramname)) +OSSL_CORE_MAKE_FUNC(void *, kdf_derive_skey, + (void *kctx, size_t keylen, const OSSL_PARAM params[])) /* RAND */ diff --git a/include/openssl/kdf.h b/include/openssl/kdf.h index 9f12f029ca8fa..93e7fdf085108 100644 --- a/include/openssl/kdf.h +++ b/include/openssl/kdf.h @@ -43,6 +43,7 @@ void EVP_KDF_CTX_reset(EVP_KDF_CTX *ctx); size_t EVP_KDF_CTX_get_kdf_size(EVP_KDF_CTX *ctx); int EVP_KDF_derive(EVP_KDF_CTX *ctx, unsigned char *key, size_t keylen, const OSSL_PARAM params[]); +int EVP_KDF_CTX_set_SKEY(EVP_KDF_CTX *ctx, EVP_SKEY *key, const char *paramname); EVP_SKEY *EVP_KDF_derive_SKEY(EVP_KDF_CTX *ctx, const char *key_type, size_t keylen, const OSSL_PARAM params[]); int EVP_KDF_get_params(EVP_KDF *kdf, OSSL_PARAM params[]); diff --git a/util/libcrypto.num b/util/libcrypto.num index 4444b66f96486..5868fc2b4a43e 100644 --- a/util/libcrypto.num +++ b/util/libcrypto.num @@ -5901,3 +5901,4 @@ 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_KDF_CTX_set_SKEY ? 3_5_0 EXIST::FUNCTION: