1989 lines
49 KiB
Diff
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 = ¶ms;
|
|
+ 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
|
|
|