diff --git a/crypto/evp/kdf_lib.c b/crypto/evp/kdf_lib.c index 14b697cef361a6..39757b5c775d90 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,74 @@ int EVP_KDF_derive(EVP_KDF_CTX *ctx, unsigned char *key, size_t keylen, return ctx->meth->derive(ctx->algctx, key, keylen, params); } +static int convert_key_cb(const OSSL_PARAM params[], void *arg) +{ + OSSL_PARAM_BLD *tmpl = arg; + const OSSL_PARAM *raw_bytes; + unsigned char *key_data; + size_t key_length; + + raw_bytes = OSSL_PARAM_locate_const(params, OSSL_SKEY_PARAM_RAW_BYTES); + if (raw_bytes == NULL) + return 0; + + if (!OSSL_PARAM_get_octet_ptr(raw_bytes, (const void **)&key_data, + &key_length)) + return 0; + + /* + * FIXME: Some kdfs of course decided to use a different name + * (OSSL_KDF_PARAM_SECRET) instead of OSSL_KDF_PARAM_KEY so we may need + * to have a fallback, or use get_settable params to find the correct + * name. + */ + return ossl_param_build_set_octet_string(tmpl, NULL, OSSL_KDF_PARAM_KEY, + key_data, key_length); +} + +int EVP_KDF_CTX_set_SKEY(EVP_KDF_CTX *ctx, EVP_SKEY *key, const char *paramname) +{ + if (ctx == NULL) + return 0; + + 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); + } else { + /* + * Provider does not support opaque keys, try to export and + * set params. + */ + OSSL_PARAM_BLD *tmpl = NULL; + OSSL_PARAM *params = NULL; + int ret = 0; + + if (!ctx->meth->set_ctx_params) + return 0; + + tmpl = OSSL_PARAM_BLD_new(); + if (tmpl == NULL) + return 0; + + if (EVP_SKEY_export(key, OSSL_SKEYMGMT_SELECT_SECRET_KEY, + convert_key_cb, tmpl)) { + params = OSSL_PARAM_BLD_to_param(tmpl); + if (params == NULL) + goto end; + + ret = ctx->meth->set_ctx_params(ctx->algctx, params); + } + + end: + OSSL_PARAM_free(params); + OSSL_PARAM_BLD_free(tmpl); + return ret; + } +} + 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 b7511312996062..116c8c825437d8 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 41e584ba74cf94..8c7e1718984b9f 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 e093cb5c2c74d5..fbf25e2b49a35c 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 e8a1d262621793..c3a1acd13d03a7 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 e0763d95d63d1a..eae33ba0a69513 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 9f12f029ca8fa8..93e7fdf085108e 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 4444b66f964864..5868fc2b4a43ed 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: