uadk_engine/0051-uadk-add-uadk_prov_dh.patch
2023-11-21 11:24:33 +08:00

1989 lines
49 KiB
Diff

From 2f367a44752241dacd01814632d6fbc8ba9e9710 Mon Sep 17 00:00:00 2001
From: Zhangfei Gao <zhangfei.gao@linaro.org>
Date: Mon, 23 Oct 2023 03:08:53 +0000
Subject: [PATCH 51/63] uadk: add uadk_prov_dh
Two funcs are supported
key generation, ie. keymgmt
key exchange, ie. keyexch
Test:
openssl dhparam -out dhparam.pem 2048
openssl genpkey -paramfile dhparam.pem -out privatekey1.pem \
-provider uadk_provider
openssl genpkey -paramfile dhparam.pem -out privatekey2.pem \
-provider uadk_provider
openssl pkey -in privatekey1.pem -pubout -out publickey1.pem \
-provider uadk_provider
openssl pkey -in privatekey2.pem -pubout -out publickey2.pem \
-provider uadk_provider
openssl pkeyutl -derive -inkey privatekey1.pem -peerkey publickey2.pem \
-out secret1.bin -provider uadk_provider
openssl pkeyutl -derive -inkey privatekey2.pem -peerkey publickey1.pem \
-out secret2.bin -provider uadk_provider
cmp secret1.bin secret2.bin
Signed-off-by: Zhangfei Gao <zhangfei.gao@linaro.org>
---
src/Makefile.am | 2 +-
src/uadk_prov.h | 4 +
src/uadk_prov_dh.c | 1863 ++++++++++++++++++++++++++++++++++++++++++
src/uadk_prov_init.c | 21 +-
4 files changed, 1883 insertions(+), 7 deletions(-)
create mode 100644 src/uadk_prov_dh.c
diff --git a/src/Makefile.am b/src/Makefile.am
index 9d5102a..668ba13 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -52,7 +52,7 @@ endif #WD_KAE
uadk_provider_la_SOURCES=uadk_prov_init.c uadk_async.c uadk_utils.c \
uadk_prov_digest.c uadk_prov_cipher.c \
- uadk_prov_rsa.c
+ uadk_prov_rsa.c uadk_prov_dh.c
uadk_provider_la_LDFLAGS=-module -version-number $(VERSION)
uadk_provider_la_LIBADD=$(WD_LIBS) -lpthread
diff --git a/src/uadk_prov.h b/src/uadk_prov.h
index 01e799e..718e78c 100644
--- a/src/uadk_prov.h
+++ b/src/uadk_prov.h
@@ -117,7 +117,11 @@ extern const OSSL_DISPATCH uadk_rsa_signature_functions[];
extern const OSSL_DISPATCH uadk_rsa_keymgmt_functions[];
extern const OSSL_DISPATCH uadk_rsa_asym_cipher_functions[];
+extern const OSSL_DISPATCH uadk_dh_keymgmt_functions[];
+extern const OSSL_DISPATCH uadk_dh_keyexch_functions[];
+
void uadk_prov_destroy_digest(void);
void uadk_prov_destroy_cipher(void);
void uadk_prov_destroy_rsa(void);
+void uadk_prov_destroy_dh(void);
#endif
diff --git a/src/uadk_prov_dh.c b/src/uadk_prov_dh.c
new file mode 100644
index 0000000..cf84cb9
--- /dev/null
+++ b/src/uadk_prov_dh.c
@@ -0,0 +1,1863 @@
+/*
+ * Copyright 2023-2024 Huawei Technologies Co.,Ltd. All rights reserved.
+ * Copyright 2023-2024 Linaro ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+#include <openssl/core_names.h>
+#include <openssl/proverr.h>
+#include <openssl/dh.h>
+#include <uadk/wd_dh.h>
+#include <uadk/wd_sched.h>
+#include "uadk.h"
+#include "uadk_async.h"
+#include "uadk_prov.h"
+
+#define DH768BITS 768
+#define DH1024BITS 1024
+#define DH1536BITS 1536
+#define DH2048BITS 2048
+#define DH3072BITS 3072
+#define DH4096BITS 4096
+#define UADK_DH_MAX_MODULE_BIT 4096
+#define DH_GENERATOR_2 2
+#define DH_GENERATOR_5 5
+#define CHAR_BIT_SIZE 3
+#define DH_PARAMS_CNT 3
+#define CTX_MODE_NUM 2
+#define UN_SET 0
+#define IS_SET 1
+#define CTX_ASYNC 1
+#define CTX_SYNC 0
+#define CTX_NUM 2
+#define UADK_DO_SOFT (-0xE0)
+#define UADK_E_SUCCESS 1
+#define UADK_E_FAIL 0
+#define UADK_E_POLL_SUCCESS 0
+#define UADK_E_POLL_FAIL (-1)
+#define UADK_E_INIT_SUCCESS 0
+#define ENV_ENABLED 1
+#define KEY_GEN_BY_ENGINE 1
+
+struct evp_keyexch_st {
+ int name_id;
+ char *type_name;
+ const char *description;
+ OSSL_PROVIDER *prov;
+ CRYPTO_REF_COUNT refcnt;
+
+ OSSL_FUNC_keyexch_newctx_fn *newctx;
+ OSSL_FUNC_keyexch_init_fn *init;
+ OSSL_FUNC_keyexch_set_peer_fn *set_peer;
+ OSSL_FUNC_keyexch_derive_fn *derive;
+ OSSL_FUNC_keyexch_freectx_fn *freectx;
+ OSSL_FUNC_keyexch_dupctx_fn *dupctx;
+ OSSL_FUNC_keyexch_set_ctx_params_fn *set_ctx_params;
+ OSSL_FUNC_keyexch_settable_ctx_params_fn *settable_ctx_params;
+ OSSL_FUNC_keyexch_get_ctx_params_fn *get_ctx_params;
+ OSSL_FUNC_keyexch_gettable_ctx_params_fn *gettable_ctx_params;
+} /* EVP_KEYEXCH */;
+
+typedef struct ffc_params_st {
+ /* Primes */
+ BIGNUM *p;
+ BIGNUM *q;
+ /* Generator */
+ BIGNUM *g;
+ /* DH X9.42 Optional Subgroup factor j >= 2 where p = j * q + 1 */
+ BIGNUM *j;
+
+ /* Required for FIPS186_4 validation of p, q and optionally canonical g */
+ unsigned char *seed;
+ /* If this value is zero the hash size is used as the seed length */
+ size_t seedlen;
+ /* Required for FIPS186_4 validation of p and q */
+ int pcounter;
+ int nid; /* The identity of a named group */
+
+ /*
+ * Required for FIPS186_4 generation & validation of canonical g.
+ * It uses unverifiable g if this value is -1.
+ */
+ int gindex;
+ int h; /* loop counter for unverifiable g */
+
+ unsigned int flags;
+ /*
+ * The digest to use for generation or validation. If this value is NULL,
+ * then the digest is chosen using the value of N.
+ */
+ const char *mdname;
+ const char *mdprops;
+#if OPENSSL_VERSION_NUMBER >= 0x30000060
+ /* Default key length for known named groups according to RFC7919 */
+ int keylength;
+#endif
+} FFC_PARAMS;
+
+struct dh_st {
+ /*
+ * This first argument is used to pick up errors when a DH is passed
+ * instead of a EVP_PKEY
+ */
+ int pad;
+ int version;
+ FFC_PARAMS params;
+ /* max generated private key length (can be less than len(q)) */
+ int32_t length;
+ BIGNUM *pub_key; /* g^x % p */
+ BIGNUM *priv_key; /* x */
+ int flags;
+ BN_MONT_CTX *method_mont_p;
+ CRYPTO_REF_COUNT references;
+#ifndef FIPS_MODULE
+ CRYPTO_EX_DATA ex_data;
+ ENGINE *engine;
+#endif
+ OSSL_LIB_CTX * libctx;
+ const DH_METHOD *meth;
+ CRYPTO_RWLOCK *lock;
+
+ /* Provider data */
+ size_t dirty_cnt; /* If any key material changes, increment this */
+}; /* DH */
+
+struct dh_method {
+ char *name;
+ /* Methods here */
+ int (*generate_key)(DH *dh);
+ int (*compute_key)(unsigned char *key, const BIGNUM *pub_key, DH *dh);
+
+ /* Can be null */
+ int (*bn_mod_exp)(const DH *dh, BIGNUM *r, const BIGNUM *a,
+ const BIGNUM *p, const BIGNUM *m, BN_CTX *ctx,
+ BN_MONT_CTX *m_ctx);
+ int (*init)(DH *dh);
+ int (*finish)(DH *dh);
+ int flags;
+ char *app_data;
+ /* If this is non-NULL, it will be used to generate parameters */
+ int (*generate_params)(DH *dh, int prime_len, int generator,
+ BN_GENCB *cb);
+};
+
+#define FFC_UNVERIFIABLE_GINDEX -1
+#define FFC_PARAM_FLAG_VALIDATE_PQ 0x01
+#define FFC_PARAM_FLAG_VALIDATE_G 0x02
+#define FFC_PARAM_FLAG_VALIDATE_PQG \
+ (FFC_PARAM_FLAG_VALIDATE_PQ | FFC_PARAM_FLAG_VALIDATE_G)
+
+struct uadk_dh_sess {
+ handle_t sess;
+ struct wd_dh_sess_setup setup;
+ struct wd_dh_req req;
+ DH *alg;
+ __u16 key_size;
+ /* key_flag: 0 - key is defined by user, 1 - key is generated by engine */
+ int key_flag;
+};
+
+struct dh_res {
+ int pid;
+} g_dh_res;
+
+static pthread_mutex_t dh_mutex = PTHREAD_MUTEX_INITIALIZER;
+
+/*
+ * This type is only really used to handle some legacy related functionality.
+ * If you need to use other KDF's (such as SSKDF) just use PROV_DH_KDF_NONE
+ * here and then create and run a KDF after the key is derived.
+ * Note that X942 has 2 variants of key derivation:
+ * (1) DH_KDF_X9_42_ASN1 - which contains an ANS1 encoded object that has
+ * the counter embedded in it.
+ * (2) DH_KDF_X941_CONCAT - which is the same as ECDH_X963_KDF (which can be
+ * done by creating a "X963KDF".
+ */
+enum kdf_type {
+ PROV_DH_KDF_NONE = 0,
+ PROV_DH_KDF_X9_42_ASN1
+};
+
+/*
+ * What's passed as an actual key is defined by the KEYMGMT interface.
+ * We happen to know that our KEYMGMT simply passes DH structures, so
+ * we use that here too.
+ */
+
+typedef struct {
+ OSSL_LIB_CTX *libctx;
+ DH *dh;
+ DH *dhpeer;
+ unsigned int pad : 1;
+
+ /* DH KDF */
+ /* KDF (if any) to use for DH */
+ enum kdf_type kdf_type;
+ /* Message digest to use for key derivation */
+ EVP_MD *kdf_md;
+ /* User key material */
+ unsigned char *kdf_ukm;
+ size_t kdf_ukmlen;
+ /* KDF output length */
+ size_t kdf_outlen;
+ char *kdf_cekalg;
+} UADK_PROV_DH_CTX;
+
+struct dh_gen_ctx {
+ OSSL_LIB_CTX *libctx;
+
+ FFC_PARAMS *ffc_params;
+ int selection;
+ /* All these parameters are used for parameter generation only */
+ /* If there is a group name then the remaining parameters are not needed */
+ int group_nid;
+ size_t pbits;
+ size_t qbits;
+ unsigned char *seed; /* optional FIPS186-4 param for testing */
+ size_t seedlen;
+ int gindex; /* optional FIPS186-4 generator index (ignored if -1) */
+ int gen_type; /* see dhtype2id */
+ int generator; /* Used by DH_PARAMGEN_TYPE_GENERATOR in non fips mode only */
+ int pcounter;
+ int hindex;
+ int priv_len;
+
+ char *mdname;
+ char *mdprops;
+ OSSL_CALLBACK *cb;
+ void *cbarg;
+ int dh_type;
+};
+
+typedef struct {
+ int id; /* libcrypto internal */
+ int name_id;
+ char *type_name;
+ const char *description;
+ OSSL_PROVIDER *prov;
+
+ int refcnt;
+ void *lock;
+
+ /* Constructor(s), destructor, information */
+ OSSL_FUNC_keymgmt_new_fn *new;
+ OSSL_FUNC_keymgmt_free_fn *free;
+ OSSL_FUNC_keymgmt_get_params_fn *get_params;
+ OSSL_FUNC_keymgmt_gettable_params_fn *gettable_params;
+ OSSL_FUNC_keymgmt_set_params_fn *set_params;
+ OSSL_FUNC_keymgmt_settable_params_fn *settable_params;
+
+ /* Generation, a complex constructor */
+ OSSL_FUNC_keymgmt_gen_init_fn *gen_init;
+ OSSL_FUNC_keymgmt_gen_set_template_fn *gen_set_template;
+ OSSL_FUNC_keymgmt_gen_set_params_fn *gen_set_params;
+ OSSL_FUNC_keymgmt_gen_settable_params_fn *gen_settable_params;
+ OSSL_FUNC_keymgmt_gen_fn *gen;
+ OSSL_FUNC_keymgmt_gen_cleanup_fn *gen_cleanup;
+ OSSL_FUNC_keymgmt_load_fn *load;
+
+ /* Key object checking */
+ OSSL_FUNC_keymgmt_query_operation_name_fn *query_operation_name;
+ OSSL_FUNC_keymgmt_has_fn *has;
+ OSSL_FUNC_keymgmt_validate_fn *validate;
+ OSSL_FUNC_keymgmt_match_fn *match;
+
+ /* Import and export routines */
+ OSSL_FUNC_keymgmt_import_fn *import;
+ OSSL_FUNC_keymgmt_import_types_fn *import_types;
+ OSSL_FUNC_keymgmt_export_fn *export;
+ OSSL_FUNC_keymgmt_export_types_fn *export_types;
+ OSSL_FUNC_keymgmt_dup_fn *dup;
+
+} UADK_DH_KEYMGMT;
+
+static inline int CRYPTO_UP_REF(int *val, int *ret, ossl_unused void *lock)
+{
+ *ret = __atomic_fetch_add(val, 1, __ATOMIC_RELAXED) + 1;
+ return 1;
+}
+
+static inline int CRYPTO_DOWN_REF(int *val, int *ret,
+ ossl_unused void *lock)
+{
+ *ret = __atomic_fetch_sub(val, 1, __ATOMIC_RELAXED) - 1;
+ if (*ret == 0)
+ __atomic_thread_fence(__ATOMIC_ACQUIRE);
+ return 1;
+}
+
+static FFC_PARAMS *uadk_dh_get0_params(DH *dh)
+{
+ return &dh->params;
+}
+
+static int uadk_DH_size(const DH *dh)
+{
+ if (dh->params.p != NULL)
+ return BN_num_bytes(dh->params.p);
+ return -1;
+}
+
+static void uadk_DH_get0_key(const DH *dh, const BIGNUM **pub_key,
+ const BIGNUM **priv_key)
+{
+ if (pub_key != NULL)
+ *pub_key = dh->pub_key;
+ if (priv_key != NULL)
+ *priv_key = dh->priv_key;
+}
+
+static int uadk_DH_set0_key(DH *dh, BIGNUM *pub_key, BIGNUM *priv_key)
+{
+ if (pub_key != NULL) {
+ BN_clear_free(dh->pub_key);
+ dh->pub_key = pub_key;
+ }
+
+ if (priv_key != NULL) {
+ BN_clear_free(dh->priv_key);
+ dh->priv_key = priv_key;
+ }
+
+ dh->dirty_cnt++;
+ return 1;
+}
+
+static FFC_PARAMS *uadk_ossl_dh_get0_params(DH *dh)
+{
+ return &dh->params;
+}
+
+static const BIGNUM *uadk_DH_get0_p(const DH *dh)
+{
+ return dh->params.p;
+}
+
+static int ossl_ffc_params_set_seed(FFC_PARAMS *params,
+ const unsigned char *seed, size_t seedlen)
+{
+ if (params == NULL)
+ return 0;
+
+ if (params->seed != NULL) {
+ if (params->seed == seed)
+ return 1;
+ OPENSSL_free(params->seed);
+ }
+
+ if (seed != NULL && seedlen > 0) {
+ params->seed = OPENSSL_memdup(seed, seedlen);
+ if (params->seed == NULL)
+ return 0;
+ params->seedlen = seedlen;
+ } else {
+ params->seed = NULL;
+ params->seedlen = 0;
+ }
+ return 1;
+}
+
+static int ffc_bn_cpy(BIGNUM **dst, const BIGNUM *src)
+{
+ BIGNUM *a;
+
+ /*
+ * If source is read only just copy the pointer, so
+ * we don't have to reallocate it.
+ */
+ if (src == NULL)
+ a = NULL;
+ else if (BN_get_flags(src, BN_FLG_STATIC_DATA)
+ && !BN_get_flags(src, BN_FLG_MALLOCED))
+ a = (BIGNUM *)src;
+ else {
+ a = BN_dup(src);
+ if (a == NULL)
+ return 0;
+ }
+
+ BN_clear_free(*dst);
+ *dst = a;
+ return 1;
+}
+
+static int ossl_ffc_params_copy(FFC_PARAMS *dst, const FFC_PARAMS *src)
+{
+ if (!ffc_bn_cpy(&dst->p, src->p)
+ || !ffc_bn_cpy(&dst->g, src->g)
+ || !ffc_bn_cpy(&dst->q, src->q)
+ || !ffc_bn_cpy(&dst->j, src->j))
+ return 0;
+
+ OPENSSL_free(dst->seed);
+ dst->seedlen = src->seedlen;
+ if (src->seed != NULL) {
+ dst->seed = OPENSSL_memdup(src->seed, src->seedlen);
+ if (dst->seed == NULL)
+ return 0;
+ } else {
+ dst->seed = NULL;
+ }
+ dst->nid = src->nid;
+ dst->pcounter = src->pcounter;
+ dst->h = src->h;
+ dst->gindex = src->gindex;
+ dst->flags = src->flags;
+ return 1;
+}
+
+static const BIGNUM *uadk_DH_get0_q(const DH *dh)
+{
+ return dh->params.q;
+}
+
+static long uadk_DH_get_length(const DH *dh)
+{
+ return dh->length;
+}
+
+static void ossl_ffc_params_get0_pqg(const FFC_PARAMS *d, const BIGNUM **p,
+ const BIGNUM **q, const BIGNUM **g)
+{
+ if (p != NULL)
+ *p = d->p;
+ if (q != NULL)
+ *q = d->q;
+ if (g != NULL)
+ *g = d->g;
+}
+
+static void uadk_DH_get0_pqg(const DH *dh, const BIGNUM **p,
+ const BIGNUM **q, const BIGNUM **g)
+{
+ ossl_ffc_params_get0_pqg(&dh->params, p, q, g);
+}
+
+static const BIGNUM *uadk_DH_get0_priv_key(const DH *dh)
+{
+ return dh->priv_key;
+}
+
+static const BIGNUM *uadk_DH_get0_pub_key(const DH *dh)
+{
+ return dh->pub_key;
+}
+
+static int uadk_DH_bits(const DH *dh)
+{
+ if (dh->params.p != NULL)
+ return BN_num_bits(dh->params.p);
+ return -1;
+}
+
+static void uadk_DH_clear_flags(DH *dh, int flags)
+{
+ dh->flags &= ~flags;
+}
+
+static void uadk_DH_set_flags(DH *dh, int flags)
+{
+ dh->flags |= flags;
+}
+
+static int uadk_ffc_params_cmp(const FFC_PARAMS *a, const FFC_PARAMS *b, int ignore_q)
+{
+ return BN_cmp(a->p, b->p) == 0 && BN_cmp(a->g, b->g) == 0 &&
+ (ignore_q || BN_cmp(a->q, b->q) == 0); /* Note: q may be NULL */
+}
+
+static int uadk_DH_up_ref(DH *r)
+{
+ int i;
+
+ if (CRYPTO_UP_REF(&r->references, &i, r->lock) <= 0)
+ return 0;
+
+ if (i < 2) {
+ fprintf(stderr, "refcount error.\n");
+ return 0;
+ }
+ return ((i > 1) ? 1 : 0);
+}
+
+static EVP_KEYEXCH get_default_keyexch(void)
+{
+ static EVP_KEYEXCH s_keyexch;
+ static int initilazed;
+
+ if (!initilazed) {
+ EVP_KEYEXCH *keyexch =
+ (EVP_KEYEXCH *)EVP_KEYEXCH_fetch(NULL, "DH", "provider=default");
+ if (keyexch) {
+ s_keyexch = *keyexch;
+ EVP_KEYEXCH_free((EVP_KEYEXCH *)keyexch);
+ initilazed = 1;
+ } else {
+ fprintf(stderr, "EVP_KEYEXCH_fetch from default provider failed");
+ }
+ }
+ return s_keyexch;
+}
+
+static int dh_generate_new_priv_key(const DH *dh, BIGNUM *new_priv_key)
+{
+ const BIGNUM *q = uadk_DH_get0_q(dh);
+ int bits;
+
+ if (q) {
+ do {
+ if (!BN_priv_rand_range(new_priv_key, q))
+ return UADK_E_FAIL;
+ } while (BN_is_zero(new_priv_key) || BN_is_one(new_priv_key));
+ } else {
+ bits = uadk_DH_get_length(dh) ?
+ uadk_DH_get_length(dh) : BN_num_bits(uadk_DH_get0_p(dh)) - 1;
+ if (!BN_priv_rand(new_priv_key, bits, BN_RAND_TOP_ONE,
+ BN_RAND_BOTTOM_ANY))
+ return UADK_E_FAIL;
+ }
+
+ return UADK_E_SUCCESS;
+}
+
+static int dh_try_get_priv_key(struct uadk_dh_sess *dh_sess, const DH *dh, BIGNUM **priv_key)
+{
+ *priv_key = (BIGNUM *)uadk_DH_get0_priv_key(dh);
+ if (!(*priv_key)) {
+ *priv_key = BN_secure_new();
+ if (!(*priv_key))
+ return UADK_E_FAIL;
+
+ if (!dh_generate_new_priv_key(dh, *priv_key))
+ goto err;
+
+ dh_sess->key_flag = KEY_GEN_BY_ENGINE;
+ }
+
+ return UADK_E_SUCCESS;
+
+err:
+ BN_free(*priv_key);
+ return UADK_E_FAIL;
+}
+
+static void uadk_prov_dh_cb(void *req_t)
+{
+ struct wd_dh_req *req_new = (struct wd_dh_req *)req_t;
+ struct uadk_e_cb_info *cb_param;
+ struct wd_dh_req *req_origin;
+ struct async_op *op;
+
+ if (!req_new)
+ return;
+
+ cb_param = req_new->cb_param;
+ if (!cb_param)
+ return;
+
+ req_origin = cb_param->priv;
+ if (!req_origin)
+ return;
+
+ req_origin->status = req_new->status;
+ if (!req_origin->status)
+ req_origin->pri_bytes = req_new->pri_bytes;
+
+ op = cb_param->op;
+ if (op && op->job && !op->done) {
+ op->done = 1;
+ async_free_poll_task(op->idx, 1);
+ async_wake_job(op->job);
+ }
+}
+
+static int uadk_dh_env_poll(void *ctx)
+{
+ __u64 rx_cnt = 0;
+ __u32 recv = 0;
+ /* Poll one packet currently */
+ int expt = 1;
+ int ret;
+
+ do {
+ ret = wd_dh_poll(expt, &recv);
+ if (ret < 0 || recv == expt)
+ return ret;
+ rx_cnt++;
+ } while (rx_cnt < ENGINE_RECV_MAX_CNT);
+
+ fprintf(stderr, "failed to poll msg: timeout!\n");
+
+ return -ETIMEDOUT;
+}
+
+static int uadk_prov_dh_init(void)
+{
+ int ret;
+
+ pthread_mutex_lock(&dh_mutex);
+ if (g_dh_res.pid != getpid()) {
+ ret = wd_dh_init2("dh", 0, 0);
+ if (unlikely(ret))
+ return ret;
+ g_dh_res.pid = getpid();
+ async_register_poll_fn(ASYNC_TASK_DH, uadk_dh_env_poll);
+ }
+ pthread_mutex_unlock(&dh_mutex);
+
+ return UADK_E_INIT_SUCCESS;
+}
+
+static struct uadk_dh_sess *dh_new_eng_session(DH *dh_alg)
+{
+ struct uadk_dh_sess *dh_sess;
+
+ dh_sess = OPENSSL_malloc(sizeof(struct uadk_dh_sess));
+ if (!dh_sess)
+ return NULL;
+
+ memset(dh_sess, 0, sizeof(struct uadk_dh_sess));
+
+ dh_sess->alg = dh_alg;
+
+ return dh_sess;
+}
+
+static int dh_init_eng_session(struct uadk_dh_sess *dh_sess,
+ __u16 bits, bool is_g2)
+{
+ __u16 key_size = bits >> CHAR_BIT_SIZE;
+ struct sched_params params = {0};
+
+ if (dh_sess->sess && dh_sess->req.x_p) {
+ memset(dh_sess->req.x_p, 0, dh_sess->req.pbytes +
+ dh_sess->req.xbytes);
+ return UADK_E_SUCCESS;
+ }
+
+ if (!dh_sess->sess) {
+ dh_sess->key_size = key_size;
+ dh_sess->setup.key_bits = bits;
+ dh_sess->setup.is_g2 = is_g2;
+ /* Use the default numa parameters */
+ params.numa_id = -1;
+ dh_sess->setup.sched_param = &params;
+ dh_sess->sess = wd_dh_alloc_sess(&dh_sess->setup);
+ if (!dh_sess->sess)
+ return UADK_E_FAIL;
+ }
+
+ return UADK_E_SUCCESS;
+}
+
+static void dh_free_eng_session(struct uadk_dh_sess *dh_sess)
+{
+ if (!dh_sess)
+ return;
+
+ if (dh_sess->sess)
+ wd_dh_free_sess(dh_sess->sess);
+
+ if (dh_sess->req.x_p)
+ OPENSSL_free(dh_sess->req.x_p);
+
+ if (dh_sess->req.pv)
+ OPENSSL_free(dh_sess->req.pv);
+
+ OPENSSL_free(dh_sess);
+}
+
+static struct uadk_dh_sess *dh_get_eng_session(DH *dh, __u16 bits,
+ bool is_g2)
+{
+ struct uadk_dh_sess *dh_sess = dh_new_eng_session(dh);
+ int ret;
+
+ if (!dh_sess)
+ return NULL;
+
+ ret = dh_init_eng_session(dh_sess, bits, is_g2);
+ if (!ret) {
+ dh_free_eng_session(dh_sess);
+ return NULL;
+ }
+
+ return dh_sess;
+}
+
+static int check_dh_bit_useful(const __u16 bits)
+{
+ /*
+ * Check whether bits exceeds the limit.
+ * The max module bits of openssl soft alg is
+ * OPENSSL_DH_MAX_MODULUS_BITS, 10000 bits.
+ * OpenSSL speed tool supports 2048/3072/4096/6144/8192 bits.
+ * UADK supports 768/1024/1536/2048/3072/4096 bits.
+ * UADK-engine will be consistent with UADK.
+ */
+ switch (bits) {
+ case DH768BITS:
+ case DH1024BITS:
+ case DH1536BITS:
+ case DH2048BITS:
+ case DH3072BITS:
+ case DH4096BITS:
+ return UADK_E_SUCCESS;
+ default:
+ break;
+ }
+
+ return UADK_E_FAIL;
+}
+
+static int dh_prepare_data(const BIGNUM *g, DH *dh,
+ struct uadk_dh_sess **dh_sess,
+ BIGNUM **priv_key)
+{
+ bool is_g2 = BN_is_word(g, DH_GENERATOR_2);
+ __u16 bits;
+ int ret;
+
+ /*
+ * The max module bits of DH is
+ * OPENSSL_DH_MAX_MODULUS_BITS, 10000 bits.
+ */
+ bits = (__u16)uadk_DH_bits(dh);
+ ret = check_dh_bit_useful(bits);
+ if (!ret) {
+ fprintf(stderr, "op size is not supported by uadk engine\n");
+ return UADK_E_FAIL;
+ }
+
+ *dh_sess = dh_get_eng_session(dh, bits, is_g2);
+ if (!(*dh_sess)) {
+ fprintf(stderr, "failed to get eng ctx\n");
+ return UADK_E_FAIL;
+ }
+
+ ret = dh_try_get_priv_key(*dh_sess, dh, priv_key);
+ if (!ret) {
+ dh_free_eng_session(*dh_sess);
+ return UADK_E_FAIL;
+ }
+
+ return ret;
+}
+
+static int dh_set_g(const BIGNUM *g, const __u16 key_size,
+ unsigned char *ag_bin, struct uadk_dh_sess *dh_sess)
+{
+ struct wd_dtb g_dtb;
+ __u32 gbytes;
+ int ret;
+
+ gbytes = BN_bn2bin(g, ag_bin);
+ g_dtb.data = (char *)ag_bin;
+ g_dtb.bsize = key_size;
+ g_dtb.dsize = gbytes;
+
+ ret = wd_dh_set_g(dh_sess->sess, &g_dtb);
+ if (ret) {
+ fprintf(stderr, "failed to set dh g\n");
+ return UADK_E_FAIL;
+ }
+
+ return UADK_E_SUCCESS;
+}
+
+static int dh_get_pubkey(struct uadk_dh_sess *dh_sess, BIGNUM **pubkey)
+{
+ const unsigned char *pubkey_str;
+
+ pubkey_str = (const unsigned char *)dh_sess->req.pri;
+ if (!pubkey_str)
+ return UADK_E_FAIL;
+
+ *pubkey = BN_bin2bn(pubkey_str, dh_sess->req.pri_bytes, *pubkey);
+ if (!(*pubkey))
+ return UADK_E_FAIL;
+
+ return UADK_E_SUCCESS;
+}
+
+static int dh_fill_genkey_req(const BIGNUM *g, const BIGNUM *p,
+ const BIGNUM *priv_key,
+ struct uadk_dh_sess *dh_sess)
+{
+ __u16 key_size = dh_sess->key_size;
+ unsigned char *apriv_key_bin;
+ unsigned char *ag_bin;
+ unsigned char *ap_bin;
+ unsigned char *out_pri;
+ int ret;
+
+ ag_bin = OPENSSL_malloc(key_size);
+ if (!ag_bin)
+ return UADK_E_FAIL;
+
+ /* Malloc a contiguous chunk of memory */
+ apriv_key_bin = OPENSSL_malloc(key_size * DH_PARAMS_CNT);
+ if (!apriv_key_bin)
+ goto free_ag;
+
+ ap_bin = apriv_key_bin + key_size;
+ out_pri = ap_bin + key_size;
+ memset(ag_bin, 0, key_size);
+ memset(apriv_key_bin, 0, key_size);
+ memset(ap_bin, 0, key_size);
+ memset(out_pri, 0, key_size);
+
+ /* Construct data block of g */
+ ret = dh_set_g(g, key_size, ag_bin, dh_sess);
+ if (!ret)
+ goto free_apriv;
+
+ dh_sess->req.xbytes = BN_bn2bin(priv_key, apriv_key_bin);
+ dh_sess->req.pbytes = BN_bn2bin(p, ap_bin);
+ dh_sess->req.x_p = (void *)apriv_key_bin;
+ dh_sess->req.pri = out_pri;
+ dh_sess->req.pri_bytes = key_size;
+ dh_sess->req.op_type = WD_DH_PHASE1;
+
+ OPENSSL_free(ag_bin);
+
+ return ret;
+
+free_apriv:
+ OPENSSL_free(apriv_key_bin);
+free_ag:
+ OPENSSL_free(ag_bin);
+ return UADK_E_FAIL;
+}
+
+static int dh_fill_compkey_req(const BIGNUM *g, const BIGNUM *p,
+ const BIGNUM *priv_key, const BIGNUM *pub_key,
+ struct uadk_dh_sess *dh_sess)
+{
+ __u16 key_size = dh_sess->key_size;
+ unsigned char *apriv_key_bin;
+ unsigned char *ap_bin;
+ unsigned char *ag_bin;
+ unsigned char *out_pri;
+ int ret;
+
+ ag_bin = OPENSSL_malloc(key_size);
+ if (!ag_bin)
+ return UADK_E_FAIL;
+
+ apriv_key_bin = OPENSSL_malloc(key_size * DH_PARAMS_CNT);
+ if (!apriv_key_bin)
+ goto free_ag;
+
+ ap_bin = apriv_key_bin + key_size;
+ out_pri = ap_bin + key_size;
+ memset(ag_bin, 0, key_size);
+ memset(apriv_key_bin, 0, key_size);
+ memset(ap_bin, 0, key_size);
+ memset(out_pri, 0, key_size);
+
+ ret = dh_set_g(g, key_size, ag_bin, dh_sess);
+ if (!ret)
+ goto free_apriv;
+
+ dh_sess->req.x_p = apriv_key_bin;
+ dh_sess->req.xbytes = BN_bn2bin(priv_key, apriv_key_bin);
+ dh_sess->req.pbytes = BN_bn2bin(p, ap_bin);
+
+ dh_sess->req.pv = ag_bin;
+ dh_sess->req.pvbytes = BN_bn2bin(pub_key, ag_bin);
+ dh_sess->req.pri = out_pri;
+ dh_sess->req.pri_bytes = key_size;
+ dh_sess->req.op_type = WD_DH_PHASE2;
+
+ return ret;
+
+free_apriv:
+ OPENSSL_free(apriv_key_bin);
+free_ag:
+ OPENSSL_free(ag_bin);
+ return UADK_E_FAIL;
+}
+
+static int dh_do_crypto(struct uadk_dh_sess *dh_sess)
+{
+ struct uadk_e_cb_info cb_param;
+ struct async_op op;
+ int idx, ret;
+
+ ret = async_setup_async_event_notification(&op);
+ if (!ret) {
+ printf("failed to setup async event notification.\n");
+ return UADK_E_FAIL;
+ }
+
+ if (!op.job) {
+ ret = wd_do_dh_sync(dh_sess->sess, &dh_sess->req);
+ if (ret)
+ return UADK_E_FAIL;
+ } else {
+ cb_param.op = &op;
+ cb_param.priv = &dh_sess->req;
+ dh_sess->req.cb = uadk_prov_dh_cb;
+ dh_sess->req.cb_param = &cb_param;
+ dh_sess->req.status = -1;
+ ret = async_get_free_task(&idx);
+ if (!ret)
+ goto err;
+
+ op.idx = idx;
+
+ do {
+ ret = wd_do_dh_async(dh_sess->sess, &dh_sess->req);
+ if (ret < 0 && ret != -EBUSY) {
+ async_free_poll_task(idx, 0);
+ goto err;
+ }
+ } while (ret == -EBUSY);
+
+ ret = async_pause_job(dh_sess, &op, ASYNC_TASK_DH, idx);
+ if (!ret)
+ goto err;
+
+ ret = dh_sess->req.status;
+ if (ret)
+ goto err;
+ }
+
+ return UADK_E_SUCCESS;
+
+err:
+ (void)async_clear_async_event_notification();
+ return UADK_E_FAIL;
+}
+
+static int dh_soft_set_pkey(DH *dh, BIGNUM *pub_key, BIGNUM *priv_key)
+{
+ const BIGNUM *old_pub = uadk_DH_get0_pub_key(dh);
+ const BIGNUM *old_priv = uadk_DH_get0_priv_key(dh);
+
+ if (old_pub != pub_key && old_priv != priv_key)
+ uadk_DH_set0_key(dh, pub_key, priv_key);
+ else if (old_pub != pub_key)
+ uadk_DH_set0_key(dh, pub_key, NULL);
+ else if (old_priv != priv_key)
+ uadk_DH_set0_key(dh, NULL, priv_key);
+
+ return UADK_E_SUCCESS;
+}
+
+static int uadk_dh_generate_key(DH *dh)
+{
+ struct uadk_dh_sess *dh_sess = NULL;
+ BIGNUM *priv_key = NULL;
+ BIGNUM *pub_key = NULL;
+ const BIGNUM *p = NULL;
+ const BIGNUM *g = NULL;
+ const BIGNUM *q = NULL;
+ int ret;
+
+ if (!dh)
+ goto exe_soft;
+
+ ret = uadk_prov_dh_init();
+ if (ret)
+ goto exe_soft;
+
+ uadk_DH_get0_pqg(dh, &p, &q, &g);
+ if (!p || !g || q)
+ goto exe_soft;
+
+ /* Get session and prepare private key */
+ ret = dh_prepare_data(g, dh, &dh_sess, &priv_key);
+ if (!ret) {
+ fprintf(stderr, "prepare dh data failed\n");
+ goto exe_soft;
+ }
+
+ ret = dh_fill_genkey_req(g, p, priv_key, dh_sess);
+ if (!ret) {
+ fprintf(stderr, "failed to fill req\n");
+ goto free_data;
+ }
+
+ ret = dh_do_crypto(dh_sess);
+ if (!ret) {
+ fprintf(stderr, "failed to generate DH key\n");
+ goto free_data;
+ }
+
+ ret = dh_get_pubkey(dh_sess, &pub_key);
+ if (!ret) {
+ fprintf(stderr, "failed to get public key\n");
+ goto free_data;
+ }
+
+ ret = dh_soft_set_pkey(dh, pub_key, priv_key);
+ dh_free_eng_session(dh_sess);
+
+ return ret;
+
+free_data:
+ if (dh_sess->key_flag == KEY_GEN_BY_ENGINE)
+ BN_free(priv_key);
+ dh_free_eng_session(dh_sess);
+exe_soft:
+ fprintf(stderr, "switch to execute openssl software calculation.\n");
+ return UADK_DO_SOFT;
+}
+
+static int uadk_dh_compute_key(unsigned char *key, const BIGNUM *pub_key,
+ DH *dh)
+{
+ struct uadk_dh_sess *dh_sess = NULL;
+ BIGNUM *priv_key = NULL;
+ const BIGNUM *p = NULL;
+ const BIGNUM *g = NULL;
+ const BIGNUM *q = NULL;
+ int ret;
+
+ if (!dh || !key || !pub_key || !uadk_DH_get0_priv_key(dh))
+ goto exe_soft;
+
+ ret = uadk_prov_dh_init();
+ if (ret)
+ goto exe_soft;
+
+ uadk_DH_get0_pqg(dh, &p, &q, &g);
+ if (!p || !g)
+ goto exe_soft;
+
+ ret = dh_prepare_data(g, dh, &dh_sess, &priv_key);
+ if (!ret) {
+ fprintf(stderr, "failed to prepare dh data\n");
+ goto exe_soft;
+ }
+
+ ret = dh_fill_compkey_req(g, p, priv_key, pub_key, dh_sess);
+ if (!ret) {
+ fprintf(stderr, "failed to fill req\n");
+ goto free_data;
+ }
+
+ ret = dh_do_crypto(dh_sess);
+ if (!ret) {
+ fprintf(stderr, "failed to generate DH shared key\n");
+ goto free_data;
+ }
+
+ memcpy(key, dh_sess->req.pri, dh_sess->req.pri_bytes);
+ ret = dh_sess->req.pri_bytes;
+ dh_free_eng_session(dh_sess);
+
+ return ret;
+
+free_data:
+ if (dh_sess->key_flag == KEY_GEN_BY_ENGINE)
+ BN_free(priv_key);
+ dh_free_eng_session(dh_sess);
+exe_soft:
+ fprintf(stderr, "switch to execute openssl software calculation.\n");
+ return UADK_DO_SOFT;
+}
+
+static void uadk_ffc_params_init(FFC_PARAMS *params)
+{
+ memset(params, 0, sizeof(*params));
+ params->pcounter = -1;
+ params->gindex = FFC_UNVERIFIABLE_GINDEX;
+ params->flags = FFC_PARAM_FLAG_VALIDATE_PQG;
+}
+
+static void uadk_ffc_params_cleanup(FFC_PARAMS *params)
+{
+ BN_free(params->p);
+ BN_free(params->q);
+ BN_free(params->g);
+ BN_free(params->j);
+ OPENSSL_free(params->seed);
+ uadk_ffc_params_init(params);
+}
+
+static void uadk_DH_free(DH *r)
+{
+ int i;
+
+ if (r == NULL)
+ return;
+
+ CRYPTO_DOWN_REF(&r->references, &i, r->lock);
+ if (i > 0)
+ return;
+
+ if (i < 0)
+ fprintf(stderr, "WARN: refcount error.\n");
+
+ if (r->meth != NULL && r->meth->finish != NULL)
+ r->meth->finish(r);
+
+ CRYPTO_free_ex_data(CRYPTO_EX_INDEX_DH, r, &r->ex_data);
+
+ CRYPTO_THREAD_lock_free(r->lock);
+
+ uadk_ffc_params_cleanup(&r->params);
+ BN_clear_free(r->pub_key);
+ BN_clear_free(r->priv_key);
+ OPENSSL_free(r);
+}
+
+static void *uadk_dh_keyexch_newctx(void *provctx)
+{
+ UADK_PROV_DH_CTX *pdhctx;
+
+ pdhctx = OPENSSL_zalloc(sizeof(UADK_PROV_DH_CTX));
+ if (pdhctx == NULL)
+ return NULL;
+ pdhctx->libctx = prov_libctx_of(provctx);
+ pdhctx->kdf_type = PROV_DH_KDF_NONE;
+ return pdhctx;
+}
+
+/* The 2 parties must share the same domain parameters */
+static int uadk_dh_keyexch_match_params(DH *priv, DH *peer)
+{
+ int ret;
+ FFC_PARAMS *dhparams_priv = uadk_dh_get0_params(priv);
+ FFC_PARAMS *dhparams_peer = uadk_dh_get0_params(peer);
+
+ ret = dhparams_priv != NULL && dhparams_peer != NULL &&
+ uadk_ffc_params_cmp(dhparams_priv, dhparams_peer, 1);
+ if (!ret)
+ ERR_raise(ERR_LIB_PROV, PROV_R_MISMATCHING_DOMAIN_PARAMETERS);
+ return ret;
+}
+
+static int uadk_dh_keyexch_set_peer(void *vpdhctx, void *vdh)
+{
+ UADK_PROV_DH_CTX *pdhctx = (UADK_PROV_DH_CTX *)vpdhctx;
+
+ if (pdhctx == NULL || vdh == NULL ||
+ !uadk_dh_keyexch_match_params(vdh, pdhctx->dh) ||
+ !uadk_DH_up_ref(vdh))
+ return 0;
+ uadk_DH_free(pdhctx->dhpeer);
+ pdhctx->dhpeer = vdh;
+ return 1;
+}
+
+static int uadk_dh_plain_derive(void *vpdhctx, unsigned char *secret,
+ size_t *secretlen, size_t outlen)
+{
+ UADK_PROV_DH_CTX *pdhctx = (UADK_PROV_DH_CTX *)vpdhctx;
+ const BIGNUM *pub_key = NULL;
+ size_t dhsize;
+ int ret;
+
+ if (pdhctx->dh == NULL || pdhctx->dhpeer == NULL) {
+ ERR_raise(ERR_LIB_PROV, PROV_R_MISSING_KEY);
+ return 0;
+ }
+
+ dhsize = (size_t)uadk_DH_size(pdhctx->dh);
+ if (secret == NULL) {
+ *secretlen = dhsize;
+ return 1;
+ }
+
+ if (outlen < dhsize) {
+ ERR_raise(ERR_LIB_PROV, PROV_R_OUTPUT_BUFFER_TOO_SMALL);
+ return 0;
+ }
+
+ uadk_DH_get0_key(pdhctx->dhpeer, &pub_key, NULL);
+
+ ret = uadk_dh_compute_key(secret, pub_key, pdhctx->dh);
+ if (ret <= 0)
+ return ret;
+
+ *secretlen = ret;
+ return 1;
+}
+static int uadk_dh_keyexch_derive(void *vpdhctx, unsigned char *secret,
+ size_t *psecretlen, size_t outlen)
+{
+ typedef int (*fun_ptr)(void *vpdhctx, unsigned char *secret,
+ size_t *secretlen, size_t outlen);
+ UADK_PROV_DH_CTX *pdhctx = (UADK_PROV_DH_CTX *)vpdhctx;
+ int ret = 0;
+
+ switch (pdhctx->kdf_type) {
+ case PROV_DH_KDF_NONE:
+ ret = uadk_dh_plain_derive(pdhctx, secret, psecretlen, outlen);
+ if (ret == UADK_DO_SOFT)
+ goto exec_soft;
+ default:
+ break;
+ }
+ return ret;
+
+exec_soft:
+ fprintf(stderr, "switch to execute openssl software calculation.\n");
+ fun_ptr fun = get_default_keyexch().derive;
+
+ if (!fun)
+ return 0;
+
+ return fun(vpdhctx, secret, psecretlen, outlen);
+}
+
+static void uadk_dh_keyexch_freectx(void *vpdhctx)
+{
+ UADK_PROV_DH_CTX *pdhctx = (UADK_PROV_DH_CTX *)vpdhctx;
+
+ OPENSSL_free(pdhctx->kdf_cekalg);
+ uadk_DH_free(pdhctx->dh);
+ uadk_DH_free(pdhctx->dhpeer);
+ EVP_MD_free(pdhctx->kdf_md);
+ OPENSSL_clear_free(pdhctx->kdf_ukm, pdhctx->kdf_ukmlen);
+ OPENSSL_free(pdhctx);
+}
+
+static void *uadk_dh_keyexch_dupctx(void *vpdhctx)
+{
+ UADK_PROV_DH_CTX *srcctx = (UADK_PROV_DH_CTX *)vpdhctx;
+ UADK_PROV_DH_CTX *dstctx;
+
+ dstctx = OPENSSL_zalloc(sizeof(*srcctx));
+ if (dstctx == NULL)
+ return NULL;
+
+ *dstctx = *srcctx;
+ dstctx->dh = NULL;
+ dstctx->dhpeer = NULL;
+ dstctx->kdf_md = NULL;
+ dstctx->kdf_ukm = NULL;
+ dstctx->kdf_cekalg = NULL;
+
+ if (srcctx->dh != NULL && !uadk_DH_up_ref(srcctx->dh))
+ goto err;
+ else
+ dstctx->dh = srcctx->dh;
+
+ if (srcctx->dhpeer != NULL && !uadk_DH_up_ref(srcctx->dhpeer))
+ goto err;
+ else
+ dstctx->dhpeer = srcctx->dhpeer;
+
+ if (srcctx->kdf_md != NULL && !EVP_MD_up_ref(srcctx->kdf_md))
+ goto err;
+ else
+ dstctx->kdf_md = srcctx->kdf_md;
+
+ /* Duplicate UKM data if present */
+ if (srcctx->kdf_ukm != NULL && srcctx->kdf_ukmlen > 0) {
+ dstctx->kdf_ukm = OPENSSL_memdup(srcctx->kdf_ukm,
+ srcctx->kdf_ukmlen);
+ if (dstctx->kdf_ukm == NULL)
+ goto err;
+ }
+
+ if (srcctx->kdf_cekalg != NULL) {
+ dstctx->kdf_cekalg = OPENSSL_strdup(srcctx->kdf_cekalg);
+ if (dstctx->kdf_cekalg == NULL)
+ goto err;
+ }
+
+ return dstctx;
+err:
+ uadk_dh_keyexch_freectx(dstctx);
+ return NULL;
+}
+
+static int uadk_dh_keyexch_set_ctx_params(void *vpdhctx,
+ const OSSL_PARAM params[])
+{
+ UADK_PROV_DH_CTX *pdhctx = (UADK_PROV_DH_CTX *)vpdhctx;
+ const OSSL_PARAM *p;
+ unsigned int pad;
+ char name[80] = {'\0'}; /* should be big enough */
+ char *str = NULL;
+
+ if (pdhctx == NULL)
+ return 0;
+ if (params == NULL)
+ return 1;
+
+ p = OSSL_PARAM_locate_const(params, OSSL_EXCHANGE_PARAM_KDF_TYPE);
+ if (p != NULL) {
+ str = name;
+ if (!OSSL_PARAM_get_utf8_string(p, &str, sizeof(name)))
+ return 0;
+
+ if (name[0] == '\0')
+ pdhctx->kdf_type = PROV_DH_KDF_NONE;
+ else if (strcmp(name, OSSL_KDF_NAME_X942KDF_ASN1) == 0)
+ pdhctx->kdf_type = PROV_DH_KDF_X9_42_ASN1;
+ else
+ return 0;
+ }
+ p = OSSL_PARAM_locate_const(params, OSSL_EXCHANGE_PARAM_KDF_DIGEST);
+ if (p != NULL) {
+ char mdprops[80] = {'\0'}; /* should be big enough */
+
+ str = name;
+ if (!OSSL_PARAM_get_utf8_string(p, &str, sizeof(name)))
+ return 0;
+
+ str = mdprops;
+ p = OSSL_PARAM_locate_const(params,
+ OSSL_EXCHANGE_PARAM_KDF_DIGEST_PROPS);
+
+ if (p != NULL)
+ if (!OSSL_PARAM_get_utf8_string(p, &str, sizeof(mdprops)))
+ return 0;
+
+ EVP_MD_free(pdhctx->kdf_md);
+ pdhctx->kdf_md = EVP_MD_fetch(pdhctx->libctx, name, mdprops);
+
+ if (pdhctx->kdf_md == NULL)
+ return 0;
+ }
+
+ p = OSSL_PARAM_locate_const(params, OSSL_EXCHANGE_PARAM_KDF_OUTLEN);
+ if (p != NULL) {
+ size_t outlen;
+
+ if (!OSSL_PARAM_get_size_t(p, &outlen))
+ return 0;
+ pdhctx->kdf_outlen = outlen;
+ }
+
+ p = OSSL_PARAM_locate_const(params, OSSL_EXCHANGE_PARAM_KDF_UKM);
+ if (p != NULL) {
+ void *tmp_ukm = NULL;
+ size_t tmp_ukmlen;
+
+ OPENSSL_free(pdhctx->kdf_ukm);
+ pdhctx->kdf_ukm = NULL;
+ pdhctx->kdf_ukmlen = 0;
+ /* ukm is an optional field so it can be NULL */
+ if (p->data != NULL && p->data_size != 0) {
+ if (!OSSL_PARAM_get_octet_string(p, &tmp_ukm, 0, &tmp_ukmlen))
+ return 0;
+ pdhctx->kdf_ukm = tmp_ukm;
+ pdhctx->kdf_ukmlen = tmp_ukmlen;
+ }
+ }
+
+ p = OSSL_PARAM_locate_const(params, OSSL_EXCHANGE_PARAM_PAD);
+ if (p != NULL) {
+ if (!OSSL_PARAM_get_uint(p, &pad))
+ return 0;
+ pdhctx->pad = pad ? 1 : 0;
+ }
+
+ p = OSSL_PARAM_locate_const(params, OSSL_KDF_PARAM_CEK_ALG);
+ if (p != NULL) {
+ str = name;
+
+ OPENSSL_free(pdhctx->kdf_cekalg);
+ pdhctx->kdf_cekalg = NULL;
+ if (p->data != NULL && p->data_size != 0) {
+ if (!OSSL_PARAM_get_utf8_string(p, &str, sizeof(name)))
+ return 0;
+ pdhctx->kdf_cekalg = OPENSSL_strdup(name);
+ if (pdhctx->kdf_cekalg == NULL)
+ return 0;
+ }
+ }
+ return 1;
+}
+
+static const OSSL_PARAM known_settable_ctx_params[] = {
+ OSSL_PARAM_int(OSSL_EXCHANGE_PARAM_PAD, NULL),
+ OSSL_PARAM_utf8_string(OSSL_EXCHANGE_PARAM_KDF_TYPE, NULL, 0),
+ OSSL_PARAM_utf8_string(OSSL_EXCHANGE_PARAM_KDF_DIGEST, NULL, 0),
+ OSSL_PARAM_utf8_string(OSSL_EXCHANGE_PARAM_KDF_DIGEST_PROPS, NULL, 0),
+ OSSL_PARAM_size_t(OSSL_EXCHANGE_PARAM_KDF_OUTLEN, NULL),
+ OSSL_PARAM_octet_string(OSSL_EXCHANGE_PARAM_KDF_UKM, NULL, 0),
+ OSSL_PARAM_utf8_string(OSSL_KDF_PARAM_CEK_ALG, NULL, 0),
+ OSSL_PARAM_END
+};
+
+static const
+OSSL_PARAM *uadk_dh_keyexch_settable_ctx_params(ossl_unused void *vpdhctx,
+ ossl_unused void *provctx)
+{
+ return known_settable_ctx_params;
+}
+
+static const OSSL_PARAM known_gettable_ctx_params[] = {
+ OSSL_PARAM_utf8_string(OSSL_EXCHANGE_PARAM_KDF_TYPE, NULL, 0),
+ OSSL_PARAM_utf8_string(OSSL_EXCHANGE_PARAM_KDF_DIGEST, NULL, 0),
+ OSSL_PARAM_size_t(OSSL_EXCHANGE_PARAM_KDF_OUTLEN, NULL),
+ OSSL_PARAM_DEFN(OSSL_EXCHANGE_PARAM_KDF_UKM, OSSL_PARAM_OCTET_PTR,
+ NULL, 0),
+ OSSL_PARAM_utf8_string(OSSL_KDF_PARAM_CEK_ALG, NULL, 0),
+ OSSL_PARAM_END
+};
+
+static const
+OSSL_PARAM *uadk_dh_keyexch_gettable_ctx_params(ossl_unused void *vpdhctx,
+ ossl_unused void *provctx)
+{
+ return known_gettable_ctx_params;
+}
+
+static int uadk_dh_keyexch_get_ctx_params(void *vpdhctx, OSSL_PARAM params[])
+{
+ UADK_PROV_DH_CTX *pdhctx = (UADK_PROV_DH_CTX *)vpdhctx;
+ OSSL_PARAM *p;
+
+ if (pdhctx == NULL)
+ return 0;
+
+ p = OSSL_PARAM_locate(params, OSSL_EXCHANGE_PARAM_KDF_TYPE);
+ if (p != NULL) {
+ const char *kdf_type = NULL;
+
+ switch (pdhctx->kdf_type) {
+ case PROV_DH_KDF_NONE:
+ kdf_type = "";
+ break;
+ case PROV_DH_KDF_X9_42_ASN1:
+ kdf_type = OSSL_KDF_NAME_X942KDF_ASN1;
+ break;
+ default:
+ return 0;
+ }
+
+ if (!OSSL_PARAM_set_utf8_string(p, kdf_type))
+ return 0;
+ }
+
+ p = OSSL_PARAM_locate(params, OSSL_EXCHANGE_PARAM_KDF_DIGEST);
+ if (p != NULL && !OSSL_PARAM_set_utf8_string(p, pdhctx->kdf_md == NULL
+ ? ""
+ : EVP_MD_get0_name(pdhctx->kdf_md)))
+ return 0;
+
+ p = OSSL_PARAM_locate(params, OSSL_EXCHANGE_PARAM_KDF_OUTLEN);
+ if (p != NULL && !OSSL_PARAM_set_size_t(p, pdhctx->kdf_outlen))
+ return 0;
+
+ p = OSSL_PARAM_locate(params, OSSL_EXCHANGE_PARAM_KDF_UKM);
+ if (p != NULL && !OSSL_PARAM_set_octet_ptr(p, pdhctx->kdf_ukm, pdhctx->kdf_ukmlen))
+ return 0;
+
+ p = OSSL_PARAM_locate(params, OSSL_KDF_PARAM_CEK_ALG);
+ if (p != NULL && !OSSL_PARAM_set_utf8_string(p, pdhctx->kdf_cekalg == NULL
+ ? ""
+ : pdhctx->kdf_cekalg))
+ return 0;
+
+ return 1;
+}
+
+static int uadk_dh_keyexch_init(void *vpdhctx, void *vdh, const OSSL_PARAM params[])
+{
+ UADK_PROV_DH_CTX *pdhctx = (UADK_PROV_DH_CTX *)vpdhctx;
+
+ if (pdhctx == NULL || vdh == NULL || !uadk_DH_up_ref(vdh))
+ return 0;
+ uadk_DH_free(pdhctx->dh);
+ pdhctx->dh = vdh;
+ pdhctx->kdf_type = PROV_DH_KDF_NONE;
+ return uadk_dh_keyexch_set_ctx_params(pdhctx, params);
+}
+
+static UADK_DH_KEYMGMT get_default_keymgmt(void)
+{
+ static UADK_DH_KEYMGMT s_keymgmt;
+ static int initilazed;
+
+ if (!initilazed) {
+ UADK_DH_KEYMGMT *keymgmt =
+ (UADK_DH_KEYMGMT *)EVP_KEYMGMT_fetch(NULL, "DH", "provider=default");
+
+ if (keymgmt) {
+ s_keymgmt = *keymgmt;
+ EVP_KEYMGMT_free((EVP_KEYMGMT *)keymgmt);
+ initilazed = 1;
+ } else {
+ fprintf(stderr, "WARN: EVP_KEYMGMT_fetch from default provider failed");
+ }
+ }
+ return s_keymgmt;
+}
+
+static void *uadk_dh_keymgmt_newdata(void *provctx)
+{
+ typedef void *(*fun_ptr)(void *);
+ fun_ptr fun = get_default_keymgmt().new;
+
+ if (!fun)
+ return NULL;
+ return fun(provctx);
+}
+
+static void uadk_dh_keymgmt_freedata(void *keydata)
+{
+ typedef void (*fun_ptr)(void *);
+ fun_ptr fun = get_default_keymgmt().free;
+
+ if (!fun)
+ return;
+ fun(keydata);
+}
+
+static int uadk_dh_keymgmt_has(const void *keydata, int selection)
+{
+ typedef int (*fun_ptr)(const void *, int);
+ fun_ptr fun = get_default_keymgmt().has;
+
+ if (!fun)
+ return 0;
+ return fun(keydata, selection);
+}
+
+static int uadk_dh_keymgmt_match(const void *keydata1, const void *keydata2, int selection)
+{
+ typedef int (*fun_ptr)(const void *, const void *, int);
+ fun_ptr fun = get_default_keymgmt().match;
+
+ if (!fun)
+ return 0;
+ return fun(keydata1, keydata2, selection);
+}
+
+static int uadk_dh_keymgmt_import(void *keydata, int selection, const OSSL_PARAM params[])
+{
+ typedef int (*fun_ptr)(void *, int, const OSSL_PARAM *);
+ fun_ptr fun = get_default_keymgmt().import;
+
+ if (!fun)
+ return 0;
+ return fun(keydata, selection, params);
+}
+
+static int uadk_dh_keymgmt_export(void *keydata, int selection, OSSL_CALLBACK *param_cb,
+ void *cbarg)
+{
+ typedef int (*fun_ptr)(void *, int, OSSL_CALLBACK *, void *);
+ fun_ptr fun = get_default_keymgmt().export;
+
+ if (!fun)
+ return 0;
+ return fun(keydata, selection, param_cb, cbarg);
+}
+
+static const OSSL_PARAM *uadk_dh_keymgmt_import_types(int selection)
+{
+ typedef const OSSL_PARAM *(*fun_ptr)(int);
+ fun_ptr fun = get_default_keymgmt().import_types;
+
+ if (!fun)
+ return NULL;
+ return fun(selection);
+}
+
+static const OSSL_PARAM *uadk_dh_keymgmt_export_types(int selection)
+{
+ typedef const OSSL_PARAM *(*fun_ptr)(int);
+ fun_ptr fun = get_default_keymgmt().export_types;
+
+ if (!fun)
+ return NULL;
+ return fun(selection);
+}
+
+static ossl_inline int uadk_dh_keymgmt_get_params(void *key, OSSL_PARAM params[])
+{
+ typedef int (*fun_ptr)(void *, OSSL_PARAM *);
+ fun_ptr fun = get_default_keymgmt().get_params;
+
+ if (!fun)
+ return 0;
+ return fun(key, params);
+}
+
+static const OSSL_PARAM *uadk_dh_keymgmt_gettable_params(void *provctx)
+{
+ typedef const OSSL_PARAM *(*fun_ptr)(void *);
+ fun_ptr fun = get_default_keymgmt().gettable_params;
+
+ if (!fun)
+ return NULL;
+ return fun(provctx);
+}
+
+static const OSSL_PARAM *uadk_dh_keymgmt_settable_params(void *provctx)
+{
+ typedef const OSSL_PARAM *(*fun_ptr)(void *);
+ fun_ptr fun = get_default_keymgmt().settable_params;
+
+ if (!fun)
+ return NULL;
+ return fun(provctx);
+}
+
+static int uadk_dh_keymgmt_set_params(void *key, const OSSL_PARAM params[])
+{
+ typedef int (*fun_ptr)(void *, const OSSL_PARAM *);
+ fun_ptr fun = get_default_keymgmt().set_params;
+
+ if (!fun)
+ return 0;
+ return fun(key, params);
+}
+
+static int uadk_dh_keymgmt_validate(const void *keydata, int selection, int checktype)
+{
+ typedef int (*fun_ptr)(const void *, int, int);
+ fun_ptr fun = get_default_keymgmt().validate;
+
+ if (!fun)
+ return 0;
+ return fun(keydata, selection, checktype);
+}
+
+static void *uadk_dh_keymgmt_gen_init(void *provctx, int selection,
+ const OSSL_PARAM params[])
+{
+ typedef void *(*fun_ptr)(void *, int, const OSSL_PARAM *);
+ fun_ptr fun = get_default_keymgmt().gen_init;
+
+ if (!fun)
+ return NULL;
+ return fun(provctx, selection, params);
+}
+
+static int uadk_dh_keymgmt_gen_set_template(void *genctx, void *templ)
+{
+ typedef int (*fun_ptr)(void *, void *);
+ fun_ptr fun = get_default_keymgmt().gen_set_template;
+
+ if (!fun)
+ return 0;
+ return fun(genctx, templ);
+}
+
+static const
+OSSL_PARAM *uadk_dh_keymgmt_gen_settable_params(ossl_unused void *genctx,
+ ossl_unused void *provctx)
+{
+ typedef const OSSL_PARAM *(*fun_ptr)(void *, void *);
+ fun_ptr fun = get_default_keymgmt().gen_settable_params;
+
+ if (!fun)
+ return NULL;
+ return fun(genctx, provctx);
+}
+
+static int uadk_dh_keymgmt_gen_set_params(void *genctx,
+ const OSSL_PARAM params[])
+{
+ typedef int (*fun_ptr)(void *, const OSSL_PARAM *);
+ fun_ptr fun = get_default_keymgmt().gen_set_params;
+
+ if (!fun)
+ return 0;
+ return fun(genctx, params);
+}
+
+static int dh_gencb(int p, int n, BN_GENCB *cb)
+{
+ struct dh_gen_ctx *gctx = BN_GENCB_get_arg(cb);
+ OSSL_PARAM params[] = { OSSL_PARAM_END, OSSL_PARAM_END, OSSL_PARAM_END };
+
+ params[0] = OSSL_PARAM_construct_int(OSSL_GEN_PARAM_POTENTIAL, &p);
+ params[1] = OSSL_PARAM_construct_int(OSSL_GEN_PARAM_ITERATION, &n);
+
+ return gctx->cb(params, gctx->cbarg);
+}
+
+static DH *ossl_dh_new_ex(OSSL_LIB_CTX *libctx)
+{
+ DH *ret = OPENSSL_zalloc(sizeof(*ret));
+
+ if (ret == NULL) {
+ ERR_raise(ERR_LIB_RSA, ERR_R_MALLOC_FAILURE);
+ return NULL;
+ }
+
+ ret->references = 1;
+ ret->lock = CRYPTO_THREAD_lock_new();
+ if (ret->lock == NULL) {
+ ERR_raise(ERR_LIB_DH, ERR_R_MALLOC_FAILURE);
+ OPENSSL_free(ret);
+ return NULL;
+ }
+
+ ret->libctx = libctx;
+
+ return ret;
+}
+
+static void *uadk_dh_keymgmt_gen(void *genctx, OSSL_CALLBACK *osslcb, void *cbarg)
+{
+ typedef void* (*fun_ptr)(void *, OSSL_CALLBACK *, void *);
+ struct dh_gen_ctx *gctx = genctx;
+ DH *dh = NULL;
+ BN_GENCB *gencb = NULL;
+ FFC_PARAMS *ffc;
+ fun_ptr fun;
+ int ret;
+
+ if (gctx == NULL)
+ return NULL;
+
+ dh = ossl_dh_new_ex(gctx->libctx);
+ if (dh == NULL)
+ return NULL;
+ ffc = uadk_ossl_dh_get0_params(dh);
+ if (gctx->ffc_params != NULL
+ && !ossl_ffc_params_copy(ffc, gctx->ffc_params))
+ goto exec_soft;
+ if (!ossl_ffc_params_set_seed(ffc, gctx->seed, gctx->seedlen))
+ goto exec_soft;
+ gctx->cb = osslcb;
+ gctx->cbarg = cbarg;
+ gencb = BN_GENCB_new();
+ if (gencb != NULL)
+ BN_GENCB_set(gencb, dh_gencb, genctx);
+
+
+ ret = uadk_dh_generate_key(dh);
+ if (ret == UADK_DO_SOFT)
+ goto exec_soft;
+ uadk_DH_clear_flags(dh, DH_FLAG_TYPE_MASK);
+ uadk_DH_set_flags(dh, gctx->dh_type);
+ BN_GENCB_free(gencb);
+ return dh;
+
+exec_soft:
+ if (dh)
+ uadk_dh_keymgmt_freedata(dh);
+ if (gencb)
+ BN_GENCB_free(gencb);
+ fun = get_default_keymgmt().gen;
+ if (!fun)
+ return NULL;
+ return fun(genctx, osslcb, cbarg);
+}
+
+static void uadk_dh_keymgmt_gen_cleanup(void *genctx)
+{
+ typedef void (*fun_ptr)(void *);
+ fun_ptr fun = get_default_keymgmt().gen_cleanup;
+
+ if (!fun)
+ return;
+ fun(genctx);
+}
+
+static void *uadk_dh_keymgmt_load(const void *reference, size_t reference_sz)
+{
+ typedef void *(*fun_ptr)(const void *, size_t);
+ fun_ptr fun = get_default_keymgmt().load;
+
+ if (!fun)
+ return NULL;
+ return fun(reference, reference_sz);
+}
+
+static void *uadk_dh_keymgmt_dup(const void *keydata_from, int selection)
+{
+ typedef void *(*fun_ptr)(const void *, int);
+ fun_ptr fun = get_default_keymgmt().dup;
+
+ if (!fun)
+ return NULL;
+ return fun(keydata_from, selection);
+}
+
+const OSSL_DISPATCH uadk_dh_keyexch_functions[] = {
+ {OSSL_FUNC_KEYEXCH_NEWCTX,
+ (void (*)(void))uadk_dh_keyexch_newctx},
+ {OSSL_FUNC_KEYEXCH_INIT,
+ (void (*)(void))uadk_dh_keyexch_init},
+ {OSSL_FUNC_KEYEXCH_DERIVE,
+ (void (*)(void))uadk_dh_keyexch_derive},
+ {OSSL_FUNC_KEYEXCH_SET_PEER,
+ (void (*)(void))uadk_dh_keyexch_set_peer},
+ {OSSL_FUNC_KEYEXCH_FREECTX,
+ (void (*)(void))uadk_dh_keyexch_freectx},
+ {OSSL_FUNC_KEYEXCH_DUPCTX,
+ (void (*)(void))uadk_dh_keyexch_dupctx},
+ {OSSL_FUNC_KEYEXCH_SET_CTX_PARAMS,
+ (void (*)(void))uadk_dh_keyexch_set_ctx_params},
+ {OSSL_FUNC_KEYEXCH_SETTABLE_CTX_PARAMS,
+ (void (*)(void))uadk_dh_keyexch_settable_ctx_params},
+ {OSSL_FUNC_KEYEXCH_GET_CTX_PARAMS,
+ (void (*)(void))uadk_dh_keyexch_get_ctx_params},
+ {OSSL_FUNC_KEYEXCH_GETTABLE_CTX_PARAMS,
+ (void (*)(void))uadk_dh_keyexch_gettable_ctx_params},
+ {0, NULL}
+};
+
+const OSSL_DISPATCH uadk_dh_keymgmt_functions[] = {
+ {OSSL_FUNC_KEYMGMT_NEW,
+ (void (*)(void))uadk_dh_keymgmt_newdata},
+ {OSSL_FUNC_KEYMGMT_GEN_INIT,
+ (void (*)(void))uadk_dh_keymgmt_gen_init},
+ {OSSL_FUNC_KEYMGMT_GEN_SET_TEMPLATE,
+ (void (*)(void))uadk_dh_keymgmt_gen_set_template},
+ {OSSL_FUNC_KEYMGMT_GEN_SET_PARAMS,
+ (void (*)(void))uadk_dh_keymgmt_gen_set_params},
+ {OSSL_FUNC_KEYMGMT_GEN_SETTABLE_PARAMS,
+ (void (*)(void))uadk_dh_keymgmt_gen_settable_params},
+ {OSSL_FUNC_KEYMGMT_GEN,
+ (void (*)(void))uadk_dh_keymgmt_gen},
+ {OSSL_FUNC_KEYMGMT_GEN_CLEANUP,
+ (void (*)(void))uadk_dh_keymgmt_gen_cleanup},
+ {OSSL_FUNC_KEYMGMT_LOAD,
+ (void (*)(void))uadk_dh_keymgmt_load},
+ {OSSL_FUNC_KEYMGMT_FREE,
+ (void (*)(void))uadk_dh_keymgmt_freedata},
+ {OSSL_FUNC_KEYMGMT_GET_PARAMS,
+ (void (*)(void))uadk_dh_keymgmt_get_params},
+ {OSSL_FUNC_KEYMGMT_GETTABLE_PARAMS,
+ (void (*)(void))uadk_dh_keymgmt_gettable_params},
+ {OSSL_FUNC_KEYMGMT_SET_PARAMS,
+ (void (*)(void))uadk_dh_keymgmt_set_params},
+ {OSSL_FUNC_KEYMGMT_SETTABLE_PARAMS,
+ (void (*)(void))uadk_dh_keymgmt_settable_params},
+ {OSSL_FUNC_KEYMGMT_HAS,
+ (void (*)(void))uadk_dh_keymgmt_has},
+ {OSSL_FUNC_KEYMGMT_MATCH,
+ (void (*)(void))uadk_dh_keymgmt_match},
+ {OSSL_FUNC_KEYMGMT_VALIDATE,
+ (void (*)(void))uadk_dh_keymgmt_validate},
+ {OSSL_FUNC_KEYMGMT_IMPORT,
+ (void (*)(void))uadk_dh_keymgmt_import},
+ {OSSL_FUNC_KEYMGMT_IMPORT_TYPES,
+ (void (*)(void))uadk_dh_keymgmt_import_types},
+ {OSSL_FUNC_KEYMGMT_EXPORT,
+ (void (*)(void))uadk_dh_keymgmt_export},
+ {OSSL_FUNC_KEYMGMT_EXPORT_TYPES,
+ (void (*)(void))uadk_dh_keymgmt_export_types},
+ {OSSL_FUNC_KEYMGMT_DUP,
+ (void (*)(void))uadk_dh_keymgmt_dup},
+ {0, NULL}
+};
+
+void uadk_prov_destroy_dh(void)
+{
+ pthread_mutex_lock(&dh_mutex);
+ if (g_dh_res.pid == getpid()) {
+ wd_dh_uninit2();
+ g_dh_res.pid = 0;
+ }
+ pthread_mutex_lock(&dh_mutex);
+}
diff --git a/src/uadk_prov_init.c b/src/uadk_prov_init.c
index fc09b64..c3d4a63 100644
--- a/src/uadk_prov_init.c
+++ b/src/uadk_prov_init.c
@@ -78,15 +78,16 @@ const OSSL_ALGORITHM uadk_prov_ciphers[] = {
};
static const OSSL_ALGORITHM uadk_prov_signature[] = {
- {"RSA", UADK_DEFAULT_PROPERTIES,
- uadk_rsa_signature_functions, "uadk_provider rsa_signature" },
- {NULL, NULL, NULL}
+ { "RSA", UADK_DEFAULT_PROPERTIES,
+ uadk_rsa_signature_functions, "uadk_provider rsa_signature" },
+ { NULL, NULL, NULL }
};
static const OSSL_ALGORITHM uadk_prov_keymgmt[] = {
- {"RSA", UADK_DEFAULT_PROPERTIES,
- uadk_rsa_keymgmt_functions, "uadk RSA Keymgmt implementation."},
- {NULL, NULL, NULL}
+ { "RSA", UADK_DEFAULT_PROPERTIES,
+ uadk_rsa_keymgmt_functions, "uadk RSA Keymgmt implementation." },
+ { "DH", UADK_DEFAULT_PROPERTIES, uadk_dh_keymgmt_functions },
+ { NULL, NULL, NULL }
};
static const OSSL_ALGORITHM uadk_prov_asym_cipher[] = {
@@ -94,6 +95,12 @@ static const OSSL_ALGORITHM uadk_prov_asym_cipher[] = {
{ NULL, NULL, NULL }
};
+static const OSSL_ALGORITHM uadk_prov_keyexch[] = {
+ { "DH", UADK_DEFAULT_PROPERTIES,
+ uadk_dh_keyexch_functions, "UADK DH keyexch implementation"},
+ { NULL, NULL, NULL }
+};
+
static const OSSL_ALGORITHM *uadk_query(void *provctx, int operation_id,
int *no_cache)
{
@@ -120,6 +127,8 @@ static const OSSL_ALGORITHM *uadk_query(void *provctx, int operation_id,
return uadk_prov_keymgmt;
case OSSL_OP_ASYM_CIPHER:
return uadk_prov_asym_cipher;
+ case OSSL_OP_KEYEXCH:
+ return uadk_prov_keyexch;
case OSSL_OP_STORE:
return prov->query_operation(provctx, operation_id, no_cache);
}
--
2.25.1