uadk_engine/0006-uadk_provider-support-x448-alg.patch
Eingesch de8288e8f7 uadk_engine: adding the uadk_provider library
(cherry picked from commit 66c935685ac0a2f1c37fd09e88d24f793a8c24ba)
2024-12-20 15:58:28 +08:00

1507 lines
39 KiB
Diff

From 1bd3dba1cf677fc7a23be78b4aad8979348c9871 Mon Sep 17 00:00:00 2001
From: Zhiqi Song <songzhiqi1@huawei.com>
Date: Thu, 19 Dec 2024 15:58:05 +0800
Subject: [PATCH 06/10] uadk_provider: support x448 alg
Test:
openssl genpkey -provider uadk_provider -algorithm X448 \
-out a_prikey_x448.pem
openssl pkey -in a_prikey_x448.pem -text
openssl pkey -in a_prikey_x448.pem -pubout -out a_pubkey_x448.pub
openssl genpkey -provider uadk_provider -algorithm x448 \
-out b_prikey_x448.pem
openssl pkey -in b_prikey_x448.pem -text
openssl pkey -in b_prikey_x448.pem -pubout -out b_pubkey_x448.pub
openssl pkeyutl -derive -out ab_x448.key -inkey a_prikey_x448.pem \
-peerkey b_pubkey_x448.pub -provider uadk_provider
openssl pkeyutl -derive -out ba_x448.key -inkey b_prikey_x448.pem \
-peerkey a_pubkey_x448.pub -provider uadk_provider
cmp ab_x448.key ba_x448.key
xxd ab_x448.key
xxd ba_x448.key
Signed-off-by: Zhiqi Song <songzhiqi1@huawei.com>
Signed-off-by: JiangShui Yang <yangjiangshui@h-partners.com>
---
src/Makefile.am | 3 +-
src/uadk_prov.h | 3 +
src/uadk_prov_ec_kmgmt.c | 2 +-
src/uadk_prov_ecdh_exch.c | 9 +-
src/uadk_prov_ecx.c | 1192 +++++++++++++++++++++++++++++++++++++
src/uadk_prov_init.c | 4 +
src/uadk_prov_pkey.c | 51 +-
src/uadk_prov_pkey.h | 12 +-
8 files changed, 1256 insertions(+), 20 deletions(-)
create mode 100644 src/uadk_prov_ecx.c
diff --git a/src/Makefile.am b/src/Makefile.am
index 5a1abe7..a165d3a 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -66,7 +66,8 @@ uadk_provider_la_SOURCES=uadk_prov_init.c uadk_async.c uadk_utils.c \
uadk_prov_bio.c uadk_prov_der_writer.c uadk_prov_packet.c \
uadk_prov_pkey.c uadk_prov_sm2.c \
uadk_prov_ffc.c uadk_prov_aead.c \
- uadk_prov_ec_kmgmt.c uadk_prov_ecdh_exch.c
+ uadk_prov_ec_kmgmt.c uadk_prov_ecdh_exch.c \
+ uadk_prov_ecx.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 7975884..84a3f01 100644
--- a/src/uadk_prov.h
+++ b/src/uadk_prov.h
@@ -182,6 +182,9 @@ extern const OSSL_DISPATCH uadk_sm2_asym_cipher_functions[FUNC_MAX_NUM];
extern const OSSL_DISPATCH uadk_ec_keymgmt_functions[FUNC_MAX_NUM];
extern const OSSL_DISPATCH uadk_ecdh_keyexch_functions[FUNC_MAX_NUM];
+extern const OSSL_DISPATCH uadk_x448_keymgmt_functions[FUNC_MAX_NUM];
+extern const OSSL_DISPATCH uadk_x448_keyexch_functions[FUNC_MAX_NUM];
+
void uadk_prov_destroy_digest(void);
void uadk_prov_destroy_cipher(void);
void uadk_prov_destroy_aead(void);
diff --git a/src/uadk_prov_ec_kmgmt.c b/src/uadk_prov_ec_kmgmt.c
index 86182bd..355d601 100644
--- a/src/uadk_prov_ec_kmgmt.c
+++ b/src/uadk_prov_ec_kmgmt.c
@@ -136,7 +136,7 @@ static handle_t ec_alloc_sess(EC_KEY *ec, struct wd_ecc_out **ec_out)
handle_t sess;
int ret;
- ret = uadk_prov_keymgmt_get_support_state(KEYMGMT_EC);
+ ret = uadk_prov_keymgmt_get_support_state(KEYMGMT_ECDH);
if (!ret) {
fprintf(stderr, "failed to get hardware ecdh keygen support!\n");
return ret;
diff --git a/src/uadk_prov_ecdh_exch.c b/src/uadk_prov_ecdh_exch.c
index f549d25..9ac8e58 100644
--- a/src/uadk_prov_ecdh_exch.c
+++ b/src/uadk_prov_ecdh_exch.c
@@ -72,12 +72,6 @@ struct ecdh_sess_ctx {
};
UADK_PKEY_KEYEXCH_DESCR(ecdh, ECDH);
-static bool g_keyexch_ecdh_support;
-
-void uadk_prov_keyexch_alg(void)
-{
- g_keyexch_ecdh_support = uadk_prov_support_algorithm("ecdh");
-}
static size_t ecdh_get_ec_size(const EC_GROUP *group)
{
@@ -169,7 +163,8 @@ static handle_t ecdh_alloc_sess(EC_KEY *privk)
{
int ret;
- if (!g_keyexch_ecdh_support) {
+ ret = uadk_prov_keyexch_get_support_state(KEYEXCH_ECDH);
+ if (!ret) {
fprintf(stderr, "invalid: hardware not support ecdh!\n");
return UADK_P_FAIL;
}
diff --git a/src/uadk_prov_ecx.c b/src/uadk_prov_ecx.c
new file mode 100644
index 0000000..302dc48
--- /dev/null
+++ b/src/uadk_prov_ecx.c
@@ -0,0 +1,1192 @@
+// SPDX-License-Identifier: Apache-2.0
+/*
+ * Copyright 2024 Huawei Technologies Co.,Ltd. All rights reserved.
+ *
+ * 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/err.h>
+#include <openssl/evp.h>
+#include <openssl/params.h>
+#include <openssl/param_build.h>
+#include <openssl/proverr.h>
+#include <openssl/rand.h>
+#include <openssl/trace.h>
+#include <uadk/wd_ecc.h>
+#include <uadk/wd_sched.h>
+#include "uadk_async.h"
+#include "uadk_prov.h"
+#include "uadk_prov_pkey.h"
+
+#define X448_KEYLEN 56
+#define X448_KEYBITS 448
+#define ECX_MAX_KEYLEN 57
+#define X448_SECURITY_BITS 224
+
+#define ECX_POSSIBLE_SELECTIONS (OSSL_KEYMGMT_SELECT_KEYPAIR)
+
+#define UADK_CRYPTO_UP_REF(val, ret, lock) CRYPTO_atomic_add(val, 1, ret, lock)
+
+static inline int UADK_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;
+}
+
+UADK_PKEY_KEYMGMT_DESCR(x448, X448);
+UADK_PKEY_KEYEXCH_DESCR(x448, X448);
+
+typedef enum {
+ ECX_KEY_TYPE_X25519 = 0x0,
+ ECX_KEY_TYPE_X448 = 0x1,
+} ECX_KEY_TYPE;
+
+typedef struct {
+ OSSL_LIB_CTX *libctx;
+ char *propq;
+ unsigned int haspubkey:1;
+ unsigned char pubkey[ECX_MAX_KEYLEN];
+ unsigned char *privkey;
+ size_t keylen;
+ ECX_KEY_TYPE type;
+ int references;
+ void *lock;
+} ECX_KEY;
+
+typedef struct {
+ OSSL_LIB_CTX *libctx;
+ char *propq;
+ ECX_KEY_TYPE type;
+ int selection;
+ size_t keylen;
+ /* uadk sesssion */
+ handle_t sess;
+} PROV_ECX_KEYMGMT_CTX;
+
+typedef struct {
+ size_t keylen;
+ ECX_KEY *key;
+ ECX_KEY *peerkey;
+ OSSL_LIB_CTX *libctx;
+ char *propq;
+ /* uadk sesssion */
+ handle_t sess;
+} PROV_ECX_KEYEXCH_CTX;
+
+static const OSSL_PARAM ecx_key_types[] = {
+ OSSL_PARAM_octet_string(OSSL_PKEY_PARAM_PUB_KEY, NULL, 0),
+ OSSL_PARAM_octet_string(OSSL_PKEY_PARAM_PRIV_KEY, NULL, 0),
+ OSSL_PARAM_END
+};
+
+struct x448_res {
+ int pid;
+} g_x448_prov;
+
+static void *uadk_keymgmt_x448_new(void *provctx)
+{
+ if (get_default_x448_keymgmt().new_fun == NULL)
+ return NULL;
+
+ return get_default_x448_keymgmt().new_fun(provctx);
+}
+
+void uadk_keymgmt_x448_free(void *keydata)
+{
+ if (get_default_x448_keymgmt().free == NULL)
+ return;
+
+ get_default_x448_keymgmt().free(keydata);
+}
+
+static int uadk_keymgmt_x448_has(const void *keydata, int selection)
+{
+ if (get_default_x448_keymgmt().has == NULL)
+ return UADK_P_FAIL;
+
+ return get_default_x448_keymgmt().has(keydata, selection);
+}
+
+static int uadk_keymgmt_x448_match(const void *keydata1, const void *keydata2, int selection)
+{
+ if (get_default_x448_keymgmt().match == NULL)
+ return UADK_P_FAIL;
+
+ return get_default_x448_keymgmt().match(keydata1, keydata2, selection);
+}
+
+static int uadk_keymgmt_x448_import(void *keydata, int selection, const OSSL_PARAM params[])
+{
+ if (get_default_x448_keymgmt().import == NULL)
+ return UADK_P_FAIL;
+
+ return get_default_x448_keymgmt().import(keydata, selection, params);
+}
+
+static int uadk_keymgmt_x448_export(void *keydata, int selection,
+ OSSL_CALLBACK *cb, void *cb_params)
+{
+ if (get_default_x448_keymgmt().export_fun == NULL)
+ return UADK_P_FAIL;
+
+ return get_default_x448_keymgmt().export_fun(keydata, selection, cb, cb_params);
+}
+
+static const OSSL_PARAM *uadk_keymgmt_x448_import_types(int selection)
+{
+ if (get_default_x448_keymgmt().import_types == NULL)
+ return NULL;
+
+ return get_default_x448_keymgmt().import_types(selection);
+}
+
+static const OSSL_PARAM *uadk_keymgmt_x448_export_types(int selection)
+{
+ if (get_default_x448_keymgmt().export_types == NULL)
+ return NULL;
+
+ return get_default_x448_keymgmt().export_types(selection);
+}
+
+void *uadk_keymgmt_x448_load(const void *reference, size_t reference_sz)
+{
+ if (get_default_x448_keymgmt().load == NULL)
+ return NULL;
+
+ return get_default_x448_keymgmt().load(reference, reference_sz);
+}
+
+static void *uadk_keymgmt_x448_dup(const void *keydata_from, int selection)
+{
+ if (get_default_x448_keymgmt().dup == NULL)
+ return NULL;
+
+ return get_default_x448_keymgmt().dup(keydata_from, selection);
+}
+
+static int uadk_keymgmt_x448_validate(const void *keydata, int selection, int checktype)
+{
+ if (get_default_x448_keymgmt().validate == NULL)
+ return UADK_P_FAIL;
+
+ return get_default_x448_keymgmt().validate(keydata, selection, checktype);
+}
+
+static const OSSL_PARAM *uadk_keymgmt_x448_gettable_params(void *provctx)
+{
+ if (get_default_x448_keymgmt().gettable_params == NULL)
+ return NULL;
+
+ return get_default_x448_keymgmt().gettable_params(provctx);
+}
+
+static int uadk_keymgmt_x448_set_params(void *key, const OSSL_PARAM params[])
+{
+ if (get_default_x448_keymgmt().set_params == NULL)
+ return UADK_P_FAIL;
+
+ return get_default_x448_keymgmt().set_params(key, params);
+}
+
+static const OSSL_PARAM *uadk_keymgmt_x448_settable_params(void *provctx)
+{
+ if (get_default_x448_keymgmt().settable_params == NULL)
+ return NULL;
+
+ return get_default_x448_keymgmt().settable_params(provctx);
+}
+
+static int uadk_keymgmt_x448_gen_set_params(void *genctx,
+ const OSSL_PARAM params[])
+{
+ if (get_default_x448_keymgmt().gen_set_params == NULL)
+ return UADK_P_FAIL;
+
+ return get_default_x448_keymgmt().gen_set_params(genctx, params);
+}
+
+static const OSSL_PARAM *uadk_keymgmt_x448_gen_settable_params(ossl_unused void *genctx,
+ ossl_unused void *provctx)
+{
+ if (get_default_x448_keymgmt().gen_settable_params == NULL)
+ return NULL;
+
+ return get_default_x448_keymgmt().gen_settable_params(genctx, provctx);
+}
+
+static int uadk_keymgmt_x448_gen_set_template(void *genctx, void *templ)
+{
+ if (get_default_x448_keymgmt().gen_set_template == NULL)
+ return UADK_P_FAIL;
+
+ return get_default_x448_keymgmt().gen_set_template(genctx, templ);
+}
+
+static const char *uadk_keymgmt_x448_query_operation_name(int operation_id)
+{
+ if (get_default_x448_keymgmt().query_operation_name == NULL)
+ return NULL;
+
+ return get_default_x448_keymgmt().query_operation_name(operation_id);
+}
+
+static int ossl_param_build_set_octet_string(OSSL_PARAM_BLD *bld, OSSL_PARAM *p, const char *key,
+ const unsigned char *data, size_t data_len)
+{
+ if (bld != NULL)
+ return OSSL_PARAM_BLD_push_octet_string(bld, key, data, data_len);
+
+ p = OSSL_PARAM_locate(p, key);
+ if (p != NULL)
+ return OSSL_PARAM_set_octet_string(p, data, data_len);
+
+ return UADK_P_SUCCESS;
+}
+
+static int ossl_param_build_set_bn_pad(OSSL_PARAM_BLD *bld, OSSL_PARAM *p,
+ const char *key, const BIGNUM *bn, size_t sz)
+{
+ if (bld != NULL)
+ return OSSL_PARAM_BLD_push_BN_pad(bld, key, bn, sz);
+
+ p = OSSL_PARAM_locate(p, key);
+ if (p != NULL) {
+ if (sz > p->data_size)
+ return UADK_P_FAIL;
+ p->data_size = sz;
+ return OSSL_PARAM_set_BN(p, bn);
+ }
+
+ return UADK_P_SUCCESS;
+}
+
+static int uadk_prov_key_to_params(ECX_KEY *key, OSSL_PARAM_BLD *tmpl,
+ OSSL_PARAM params[], int include_private)
+{
+ if (!ossl_param_build_set_octet_string(tmpl, params,
+ OSSL_PKEY_PARAM_PUB_KEY,
+ key->pubkey, key->keylen))
+ return UADK_P_FAIL;
+
+ if (include_private && key->privkey != NULL
+ && !ossl_param_build_set_octet_string(tmpl, params,
+ OSSL_PKEY_PARAM_PRIV_KEY,
+ key->privkey, key->keylen))
+ return UADK_P_FAIL;
+
+ return UADK_P_SUCCESS;
+}
+
+static int uadk_prov_ecx_get_params(void *key, OSSL_PARAM params[],
+ int bits, int secbits, int size)
+{
+ ECX_KEY *ecx = key;
+ OSSL_PARAM *p;
+
+ if (ecx == NULL)
+ return UADK_P_FAIL;
+
+ p = OSSL_PARAM_locate(params, OSSL_PKEY_PARAM_BITS);
+ if (p && !OSSL_PARAM_set_int(p, bits))
+ return UADK_P_FAIL;
+
+ p = OSSL_PARAM_locate(params, OSSL_PKEY_PARAM_SECURITY_BITS);
+ if (p && !OSSL_PARAM_set_int(p, secbits))
+ return UADK_P_FAIL;
+
+ p = OSSL_PARAM_locate(params, OSSL_PKEY_PARAM_MAX_SIZE);
+ if (p && !OSSL_PARAM_set_int(p, size))
+ return UADK_P_FAIL;
+
+ p = OSSL_PARAM_locate(params, OSSL_PKEY_PARAM_ENCODED_PUBLIC_KEY);
+ if (p && (ecx->type == ECX_KEY_TYPE_X25519 || ecx->type == ECX_KEY_TYPE_X448)) {
+ if (!OSSL_PARAM_set_octet_string(p, ecx->pubkey, ecx->keylen))
+ return UADK_P_FAIL;
+ }
+
+ return uadk_prov_key_to_params(ecx, NULL, params, 1);
+}
+
+static int uadk_keymgmt_x448_get_params(void *key, OSSL_PARAM params[])
+{
+ return uadk_prov_ecx_get_params(key, params, X448_KEYBITS, X448_SECURITY_BITS,
+ X448_KEYLEN);
+}
+
+static int ossl_ecx_gen_set_params(void *genctx, const OSSL_PARAM params[])
+{
+ PROV_ECX_KEYMGMT_CTX *gctx = (PROV_ECX_KEYMGMT_CTX *)genctx;
+ const char *groupname = NULL;
+ const OSSL_PARAM *p;
+
+ p = OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_GROUP_NAME);
+ if (p != NULL) {
+ /*
+ * We optionally allow setting a group name - but each algorithm only
+ * support one such name, so all we do is verify that it is the one we
+ * expected.
+ */
+ switch (gctx->type) {
+ case ECX_KEY_TYPE_X25519:
+ groupname = "x25519";
+ break;
+ case ECX_KEY_TYPE_X448:
+ groupname = "x448";
+ break;
+ default:
+ /* We only support this for key exchange at the moment */
+ break;
+ }
+ if (p->data_type != OSSL_PARAM_UTF8_STRING || groupname == NULL ||
+ OPENSSL_strcasecmp(p->data, groupname) != 0) {
+ fprintf(stderr, "invalid ecx params\n");
+ return UADK_P_FAIL;
+ }
+ }
+ p = OSSL_PARAM_locate_const(params, OSSL_KDF_PARAM_PROPERTIES);
+ if (p != NULL) {
+ if (p->data_type != OSSL_PARAM_UTF8_STRING)
+ return UADK_P_FAIL;
+
+ OPENSSL_free(gctx->propq);
+ gctx->propq = OPENSSL_strdup(p->data);
+ if (gctx->propq == NULL)
+ return UADK_P_FAIL;
+ }
+
+ return UADK_P_SUCCESS;
+}
+
+static handle_t uadk_prov_x448_alloc_sess(void)
+{
+ struct wd_ecc_sess_setup setup = {0};
+ struct sched_params params = {0};
+
+ setup.alg = "x448";
+ setup.key_bits = X448_KEYBITS;
+ params.numa_id = -1;
+ setup.sched_param = &params;
+
+ return wd_ecc_alloc_sess(&setup);
+}
+
+static void uadk_prov_x448_free_sess(handle_t sess)
+{
+ if (sess)
+ wd_ecc_free_sess(sess);
+}
+
+static void *ossl_ecx_gen_init(void *provctx, int selection, const OSSL_PARAM params[],
+ ECX_KEY_TYPE type)
+{
+ OSSL_LIB_CTX *libctx = prov_libctx_of(provctx);
+ PROV_ECX_KEYMGMT_CTX *gctx = NULL;
+ int ret;
+
+ gctx = OPENSSL_zalloc(sizeof(PROV_ECX_KEYMGMT_CTX));
+ if (gctx == NULL) {
+ fprintf(stderr, "failed to alloc ecx gctx\n");
+ return NULL;
+ }
+
+ gctx->libctx = libctx;
+ gctx->type = type;
+ gctx->selection = selection;
+
+ ret = ossl_ecx_gen_set_params(gctx, params);
+ if (ret == UADK_P_FAIL) {
+ fprintf(stderr, "failed to set ecx params\n");
+ OPENSSL_free(gctx);
+ gctx = NULL;
+ }
+
+ return gctx;
+}
+
+static void uadk_keymgmt_x448_gen_cleanup(void *genctx)
+{
+ /* genctx will be freed in cleanup function */
+ if (get_default_x448_keymgmt().gen_cleanup == NULL)
+ return;
+
+ get_default_x448_keymgmt().gen_cleanup(genctx);
+}
+
+static void *uadk_keymgmt_x448_gen_init(void *provctx, int selection,
+ const OSSL_PARAM params[])
+{
+ PROV_ECX_KEYMGMT_CTX *gctx = NULL;
+ int ret;
+
+ if (provctx == NULL) {
+ fprintf(stderr, "invalid: provctx is NULL\n");
+ return NULL;
+ }
+
+ return ossl_ecx_gen_init(provctx, selection, params, ECX_KEY_TYPE_X448);
+}
+
+ECX_KEY *uadk_prov_ecx_key_new(OSSL_LIB_CTX *libctx, ECX_KEY_TYPE type, int haspubkey,
+ const char *propq)
+{
+ ECX_KEY *ecx_key = OPENSSL_zalloc(sizeof(ECX_KEY));
+
+ if (ecx_key == NULL) {
+ fprintf(stderr, "failed to alloc ecx key");
+ return NULL;
+ }
+
+ ecx_key->libctx = libctx;
+ ecx_key->haspubkey = haspubkey;
+
+ switch (type) {
+ case ECX_KEY_TYPE_X448:
+ ecx_key->keylen = X448_KEYLEN;
+ ecx_key->type = type;
+ ecx_key->references = 1;
+ break;
+ default:
+ fprintf(stderr, "invalid: unsupported ecx type\n");
+ goto free_ecx_key;
+ }
+
+ if (propq) {
+ ecx_key->propq = OPENSSL_strdup(propq);
+ if (ecx_key->propq == NULL)
+ goto free_ecx_key;
+ }
+
+ ecx_key->lock = CRYPTO_THREAD_lock_new();
+ if (ecx_key->lock == NULL)
+ goto err;
+
+ return ecx_key;
+
+err:
+ if (propq)
+ OPENSSL_free(ecx_key->propq);
+free_ecx_key:
+ OPENSSL_free(ecx_key);
+ return NULL;
+}
+
+static void uadk_prov_ecx_key_free(ECX_KEY *ecx_key)
+{
+ int i = 0;
+
+ if (ecx_key == NULL)
+ return;
+
+ UADK_CRYPTO_DOWN_REF(&ecx_key->references, &i, ecx_key->lock);
+ if (i > 0)
+ return;
+
+ if (ecx_key->propq)
+ OPENSSL_free(ecx_key->propq);
+
+ if (ecx_key->privkey)
+ OPENSSL_secure_free(ecx_key->privkey);
+
+ if (ecx_key->lock)
+ CRYPTO_THREAD_lock_free(ecx_key->lock);
+
+ OPENSSL_free(ecx_key);
+}
+
+static ECX_KEY *uadk_prov_ecx_create_prikey(PROV_ECX_KEYMGMT_CTX *gctx)
+{
+ unsigned char *prikey = NULL;
+ ECX_KEY *ecx_key = NULL;
+ int ret;
+
+ ecx_key = uadk_prov_ecx_key_new(gctx->libctx, gctx->type, 0, gctx->propq);
+ if (ecx_key == NULL) {
+ fprintf(stderr, "failed to new ecx_key\n");
+ return UADK_P_FAIL;
+ }
+ gctx->keylen = X448_KEYLEN;
+
+ /* If we're doing parameter generation then we just return a blank key */
+ if ((gctx->selection & OSSL_KEYMGMT_SELECT_KEYPAIR) == 0)
+ return ecx_key;
+
+ prikey = OPENSSL_secure_malloc(ecx_key->keylen);
+ if (prikey == NULL) {
+ fprintf(stderr, "failed to alloc prikey\n");
+ goto free_ecx_key;
+ }
+
+ ret = RAND_priv_bytes(prikey, ecx_key->keylen);
+ if (ret <= 0) {
+ fprintf(stderr, "failed to set rand bytes to prikey\n");
+ goto free_pri;
+ }
+ ecx_key->privkey = prikey;
+
+ return ecx_key;
+
+free_pri:
+ OPENSSL_secure_free(prikey);
+free_ecx_key:
+ uadk_prov_ecx_key_free(ecx_key);
+
+ return NULL;
+}
+
+static void uadk_prov_ecx_free_prikey(ECX_KEY *ecx_key)
+{
+ if (ecx_key == NULL)
+ return;
+
+ if (ecx_key->privkey) {
+ OPENSSL_secure_free(ecx_key->privkey);
+ ecx_key->privkey = NULL;
+ }
+
+ uadk_prov_ecx_key_free(ecx_key);
+}
+
+static int uadk_prov_ecx_keygen_init_iot(handle_t sess, struct wd_ecc_req *req)
+{
+ struct wd_ecc_out *ecx_out;
+
+ ecx_out = wd_ecxdh_new_out(sess);
+ if (ecx_out == NULL) {
+ fprintf(stderr, "failed to new sign out\n");
+ return UADK_P_FAIL;
+ }
+
+ uadk_prov_ecc_fill_req(req, WD_ECXDH_GEN_KEY, NULL, ecx_out);
+
+ return UADK_P_SUCCESS;
+}
+
+static void uadk_prov_ecx_keygen_uninit_iot(handle_t sess, struct wd_ecc_req *req)
+{
+ wd_ecc_del_out(sess, req->dst);
+}
+
+static int uadk_prov_reverse_bytes(unsigned char *to_buf, __u32 size)
+{
+ unsigned char *tmp_buf = NULL;
+ unsigned char tmp;
+
+ if (size == 0) {
+ fprintf(stderr, "invalid size, size = %u\n", size);
+ return UADK_P_FAIL;
+ }
+
+ if (to_buf == NULL) {
+ fprintf(stderr, "to_buf is NULL\n");
+ return UADK_P_FAIL;
+ }
+
+ tmp_buf = to_buf + size - 1;
+ while (to_buf < tmp_buf) {
+ tmp = *tmp_buf;
+ *tmp_buf-- = *to_buf;
+ *to_buf++ = tmp;
+ }
+
+ return UADK_P_SUCCESS;
+}
+
+static int uadk_prov_reverse_bytes_ex(unsigned char *src_buf, unsigned char *dst_buf, __u32 size)
+{
+ __u32 i;
+
+ if (size == 0) {
+ fprintf(stderr, "invalid size, size = %u\n", size);
+ return UADK_P_FAIL;
+ }
+
+ if (src_buf == NULL) {
+ fprintf(stderr, "src_buf is NULL\n");
+ return UADK_P_FAIL;
+ }
+
+ if (dst_buf == NULL) {
+ fprintf(stderr, "dst_buf is NULL\n");
+ return UADK_P_FAIL;
+ }
+
+ for (i = 0; i < size; i++)
+ dst_buf[i] = src_buf[size - i - 1];
+
+ return UADK_P_SUCCESS;
+}
+
+static int uadk_prov_ecx_set_pkey(PROV_ECX_KEYMGMT_CTX *gctx, struct wd_ecc_req *req,
+ ECX_KEY *ecx_key)
+{
+ struct wd_ecc_point *pubkey = NULL;
+ int ret;
+
+ wd_ecxdh_get_out_params(req->dst, &pubkey);
+ if (pubkey == NULL) {
+ fprintf(stderr, "failed to get pubkey\n");
+ return UADK_P_FAIL;
+ }
+
+ if (pubkey->x.dsize >= ECX_MAX_KEYLEN) {
+ fprintf(stderr, "invalid: pubkey->x.dsize = %u\n",
+ pubkey->x.dsize);
+ return UADK_P_FAIL;
+ }
+
+ /* Trans public key from big-endian to little-endian */
+ ret = uadk_prov_reverse_bytes_ex((unsigned char *)pubkey->x.data,
+ ecx_key->pubkey, pubkey->x.dsize);
+ if (ret == UADK_P_FAIL) {
+ fprintf(stderr, "failed to transform pubkey\n");
+ return ret;
+ }
+ /* Trans private key from big-endian to little-endian */
+ ret = uadk_prov_reverse_bytes(ecx_key->privkey, gctx->keylen);
+ if (ret == UADK_P_FAIL) {
+ fprintf(stderr, "failed to transform prikey\n");
+ return ret;
+ }
+ /*
+ * This is a pretreatment of X448 described in RFC 7748.
+ * In order to decode the random bytes as an integer scaler, there
+ * are some special data processing. And use little-endian mode for
+ * decoding.
+ */
+ if (gctx->type == ECX_KEY_TYPE_X448) {
+ /* Set the two LSB of the first byte to 0 */
+ ecx_key->privkey[0] &= 0xFC;
+
+ /* Set the MSB of the last byte to 1 */
+ ecx_key->privkey[X448_KEYLEN - 1] |= 0x80;
+ } else {
+ fprintf(stderr, "invalid: unsupported ecx type\n");
+ return UADK_P_FAIL;
+ }
+
+ return ret;
+}
+
+static int uadk_prov_ecx_keygen_set_prikey(PROV_ECX_KEYMGMT_CTX *gctx, ECX_KEY *ecx_key)
+{
+ struct wd_ecc_key *ecc_key = NULL;
+ struct wd_dtb prikey = {0};
+ handle_t sess = gctx->sess;
+ int ret;
+
+ prikey.data = (char *)ecx_key->privkey;
+ prikey.dsize = ecx_key->keylen;
+
+ ecc_key = wd_ecc_get_key(sess);
+ ret = wd_ecc_set_prikey(ecc_key, &prikey);
+ if (ret) {
+ fprintf(stderr, "failed to set ecc prikey, ret = %d\n", ret);
+ return UADK_P_FAIL;
+ }
+
+ return UADK_P_SUCCESS;
+}
+
+static void *uadk_prov_ecx_keygen(PROV_ECX_KEYMGMT_CTX *gctx)
+{
+ struct wd_ecc_req req = {0};
+ ECX_KEY *ecx_key = NULL;
+ int ret;
+
+ ecx_key = uadk_prov_ecx_create_prikey(gctx);
+ if (ecx_key == NULL)
+ return NULL;
+
+ ret = uadk_prov_ecx_keygen_init_iot(gctx->sess, &req);
+ if (ret == UADK_P_FAIL)
+ goto free_prikey;
+
+ ret = uadk_prov_ecx_keygen_set_prikey(gctx, ecx_key);
+ if (ret == UADK_P_FAIL)
+ goto uninit_iot;
+
+ ret = uadk_prov_ecc_crypto(gctx->sess, &req, (void *)gctx->sess);
+ if (ret == UADK_P_FAIL)
+ goto uninit_iot;
+
+ ret = uadk_prov_ecx_set_pkey(gctx, &req, ecx_key);
+ if (ret == UADK_P_FAIL)
+ goto uninit_iot;
+
+ ecx_key->haspubkey = 1;
+
+ uadk_prov_ecx_keygen_uninit_iot(gctx->sess, &req);
+
+ return ecx_key;
+
+uninit_iot:
+ uadk_prov_ecx_keygen_uninit_iot(gctx->sess, &req);
+free_prikey:
+ uadk_prov_ecx_free_prikey(ecx_key);
+
+ return NULL;
+}
+
+static void *uadk_keymgmt_x448_gen(void *genctx, OSSL_CALLBACK *cb, void *cb_params)
+{
+ PROV_ECX_KEYMGMT_CTX *gctx = (PROV_ECX_KEYMGMT_CTX *)genctx;
+ ECX_KEY *ecx_key = NULL;
+ int ret;
+
+ if (gctx == NULL) {
+ fprintf(stderr, "invalid: ecx keygen ctx is NULL\n");
+ return NULL;
+ }
+
+ if (gctx->type != ECX_KEY_TYPE_X448) {
+ fprintf(stderr, "invalid: unsupported ecx type\n");
+ return NULL;
+ }
+
+ ret = uadk_prov_keymgmt_get_support_state(KEYMGMT_X448);
+ if (ret == UADK_P_FAIL) {
+ fprintf(stderr, "failed to get hardware x448 keygen support\n");
+ return NULL;
+ }
+
+ ret = uadk_prov_ecc_init("x448");
+ if (ret != UADK_P_SUCCESS) {
+ fprintf(stderr, "failed to init x448\n");
+ return NULL;
+ }
+
+ gctx->sess = uadk_prov_x448_alloc_sess();
+ if (gctx->sess == (handle_t)0) {
+ fprintf(stderr, "failed to alloc x448 sess\n");
+ return NULL;
+ }
+
+ ecx_key = uadk_prov_ecx_keygen(gctx);
+ if (ecx_key == NULL)
+ fprintf(stderr, "failed to generate x448 key\n");
+
+ uadk_prov_x448_free_sess(gctx->sess);
+
+ return ecx_key;
+}
+
+static UADK_PKEY_KEYEXCH get_default_x448_keyexch(void)
+{
+ static UADK_PKEY_KEYEXCH s_keyexch;
+ static int initilazed;
+
+ if (!initilazed) {
+ UADK_PKEY_KEYEXCH *keyexch =
+ (UADK_PKEY_KEYEXCH *)EVP_KEYEXCH_fetch(NULL, "X448", "provider=default");
+ if (keyexch) {
+ s_keyexch = *keyexch;
+ EVP_KEYEXCH_free((EVP_KEYEXCH *)keyexch);
+ initilazed = 1;
+ } else {
+ fprintf(stderr, "failed to EVP_KEYEXCH_fetch default X448 provider\n");
+ }
+ }
+ return s_keyexch;
+}
+
+static void *uadk_keyexch_x448_newctx(void *provctx)
+{
+ PROV_ECX_KEYEXCH_CTX *ecxctx = NULL;
+ int ret;
+
+ ecxctx = OPENSSL_zalloc(sizeof(PROV_ECX_KEYEXCH_CTX));
+ if (ecxctx == NULL) {
+ ERR_raise(ERR_LIB_PROV, ERR_R_MALLOC_FAILURE);
+ return NULL;
+ }
+
+ ecxctx->keylen = X448_KEYLEN;
+
+ return ecxctx;
+}
+
+static void uadk_keyexch_x448_freectx(void *vecxctx)
+{
+ PROV_ECX_KEYEXCH_CTX *ecxctx = (PROV_ECX_KEYEXCH_CTX *)vecxctx;
+
+ if (ecxctx == NULL)
+ return;
+
+ OPENSSL_free(ecxctx);
+ ecxctx = NULL;
+}
+
+static int uadk_keyexch_x448_set_ctx_params(void *ecxctx, const OSSL_PARAM params[])
+{
+ if (get_default_x448_keyexch().set_ctx_params == NULL)
+ return UADK_P_FAIL;
+
+ return get_default_x448_keyexch().set_ctx_params(ecxctx, params);
+}
+
+static const OSSL_PARAM *uadk_keyexch_x448_settable_ctx_params(ossl_unused void *ecxctx,
+ ossl_unused void *provctx)
+{
+ if (get_default_x448_keyexch().settable_ctx_params == NULL)
+ return NULL;
+
+ return get_default_x448_keyexch().settable_ctx_params(ecxctx, provctx);
+}
+
+static const OSSL_PARAM *uadk_keyexch_x448_gettable_ctx_params(ossl_unused void *ecxctx,
+ ossl_unused void *provctx)
+{
+ if (get_default_x448_keyexch().gettable_ctx_params == NULL)
+ return NULL;
+
+ return get_default_x448_keyexch().gettable_ctx_params(ecxctx, provctx);
+}
+
+static int uadk_keyexch_x448_get_ctx_params(void *ecxctx, OSSL_PARAM params[])
+{
+ if (get_default_x448_keyexch().get_ctx_params == NULL)
+ return UADK_P_FAIL;
+
+ return get_default_x448_keyexch().get_ctx_params(ecxctx, params);
+}
+
+static int uadk_keyexch_x448_init(void *vecxctx, void *vkey,
+ ossl_unused const OSSL_PARAM params[])
+{
+ PROV_ECX_KEYEXCH_CTX *ecxctx = (PROV_ECX_KEYEXCH_CTX *)vecxctx;
+ ECX_KEY *key = vkey;
+ int ret;
+
+ if (ecxctx == NULL) {
+ fprintf(stderr, "invalid: ecxctx is NULL\n");
+ return UADK_P_FAIL;
+ }
+
+ if (key == NULL) {
+ fprintf(stderr, "invalid: key is NULL\n");
+ return UADK_P_FAIL;
+ }
+
+ if (key->keylen != ecxctx->keylen) {
+ fprintf(stderr, "invalid: key->keylen(%zu) != ecxctx->keylen(%zu)\n",
+ key->keylen, ecxctx->keylen);
+ return UADK_P_FAIL;
+ }
+
+ uadk_prov_ecx_key_free(ecxctx->key);
+ ecxctx->key = key;
+
+ return UADK_P_SUCCESS;
+}
+
+int ossl_ecx_key_up_ref(ECX_KEY *key)
+{
+ int i = 0;
+
+ if (UADK_CRYPTO_UP_REF(&key->references, &i, key->lock) <= 0)
+ return UADK_P_FAIL;
+
+ return ((i > 1) ? UADK_P_SUCCESS : UADK_P_FAIL);
+}
+
+static int uadk_keyexch_x448_set_peer(void *vecxctx, void *vkey)
+{
+ PROV_ECX_KEYEXCH_CTX *ecxctx = (PROV_ECX_KEYEXCH_CTX *)vecxctx;
+ ECX_KEY *key = vkey;
+
+ if (ecxctx == NULL) {
+ fprintf(stderr, "invalid: ecxctx is NULL\n");
+ return UADK_P_FAIL;
+ }
+
+ if (key == NULL) {
+ fprintf(stderr, "invalid: key is NULL\n");
+ return UADK_P_FAIL;
+ }
+
+ if (key->keylen != ecxctx->keylen || !ossl_ecx_key_up_ref(key)) {
+ fprintf(stderr, "invalid: key->keylen(%zu) != ecxctx->keylen(%zu)\n",
+ key->keylen, ecxctx->keylen);
+ return UADK_P_FAIL;
+ }
+
+ uadk_prov_ecx_key_free(ecxctx->peerkey);
+ ecxctx->peerkey = key;
+
+ return UADK_P_SUCCESS;
+}
+
+static int uadk_prov_ecx_compkey_init_iot(PROV_ECX_KEYEXCH_CTX *ecxctx, struct wd_ecc_req *req)
+{
+ char buffer_y[ECX_MAX_KEYLEN] = {0};
+ handle_t sess = ecxctx->sess;
+ struct wd_ecc_point in_pubkey;
+ struct wd_ecc_out *ecx_out;
+ struct wd_ecc_in *ecx_in;
+ int ret;
+
+ /* Trans public key from little-endian to big-endian */
+ ret = uadk_prov_reverse_bytes(ecxctx->peerkey->pubkey, ecxctx->keylen);
+ if (ret == UADK_P_FAIL) {
+ fprintf(stderr, "failed to trans public key\n");
+ return UADK_P_FAIL;
+ }
+
+ in_pubkey.x.data = (char *)ecxctx->peerkey->pubkey;
+ in_pubkey.x.dsize = ecxctx->keylen;
+ in_pubkey.y.data = buffer_y;
+ in_pubkey.y.dsize = 1;
+
+ ecx_in = wd_ecxdh_new_in(sess, &in_pubkey);
+ if (ecx_in == NULL) {
+ fprintf(stderr, "failed to new ecxdh in\n");
+ return UADK_P_FAIL;
+ }
+
+ ecx_out = wd_ecxdh_new_out(sess);
+ if (ecx_out == NULL) {
+ fprintf(stderr, "failed to new ecxdh out\n");
+ ret = UADK_P_FAIL;
+ goto del_in;
+ }
+
+ uadk_prov_ecc_fill_req(req, WD_ECXDH_COMPUTE_KEY, ecx_in, ecx_out);
+
+ /* Trans public key from big-endian to little-endian */
+ ret = uadk_prov_reverse_bytes(ecxctx->peerkey->pubkey, ecxctx->keylen);
+ if (ret == UADK_P_FAIL) {
+ fprintf(stderr, "failed to trans public key\n");
+ goto del_out;
+ }
+
+ return ret;
+
+del_out:
+ wd_ecc_del_out(sess, ecx_out);
+del_in:
+ wd_ecc_del_in(sess, ecx_in);
+
+ return ret;
+}
+
+static void uadk_prov_ecx_compkey_uninit_iot(PROV_ECX_KEYEXCH_CTX *ecxctx, struct wd_ecc_req *req)
+{
+ wd_ecc_del_in(ecxctx->sess, req->src);
+ wd_ecc_del_out(ecxctx->sess, req->dst);
+}
+
+static int uadk_prov_ecx_derive_set_prikey(PROV_ECX_KEYEXCH_CTX *ecxctx)
+{
+ handle_t sess = ecxctx->sess;
+ struct wd_ecc_key *ecc_key;
+ struct wd_dtb prikey;
+ int ret;
+
+ /* Trans private key from little-endian to big-endian */
+ ret = uadk_prov_reverse_bytes(ecxctx->key->privkey, ecxctx->keylen);
+ if (!ret) {
+ fprintf(stderr, "failed to trans private key\n");
+ return UADK_P_FAIL;
+ }
+
+ prikey.data = (char *)ecxctx->key->privkey;
+ prikey.dsize = ecxctx->keylen;
+ ecc_key = wd_ecc_get_key(sess);
+ ret = wd_ecc_set_prikey(ecc_key, &prikey);
+ if (ret) {
+ fprintf(stderr, "failed to set ecc prikey, ret = %d\n", ret);
+ return UADK_P_FAIL;
+ }
+
+ /* Trans private key from big-endian to little-endian */
+ ret = uadk_prov_reverse_bytes(ecxctx->key->privkey, ecxctx->keylen);
+ if (ret == UADK_P_FAIL) {
+ fprintf(stderr, "failed to trans private key\n");
+ return UADK_P_FAIL;
+ }
+
+ return UADK_P_SUCCESS;
+}
+
+static void uadk_prov_x448_pad_out_key(unsigned char *dst_key, unsigned char *src_key,
+ size_t len)
+{
+ unsigned char x448_pad_key[X448_KEYLEN] = {0};
+
+ if (len != X448_KEYLEN) {
+ memcpy(x448_pad_key, src_key, len);
+ memcpy(dst_key, x448_pad_key, X448_KEYLEN);
+ } else {
+ memcpy(dst_key, src_key, X448_KEYLEN);
+ }
+}
+
+static void uadk_prov_ecx_pad_out_key(unsigned char *dst_key, unsigned char *src_key,
+ size_t len, int type)
+{
+ if (type == ECX_KEY_TYPE_X448) {
+ uadk_prov_x448_pad_out_key(dst_key, src_key, len);
+ return;
+ }
+}
+
+static int uadk_prov_ecx_derive(PROV_ECX_KEYEXCH_CTX *ecxctx, unsigned char *key, size_t *keylen)
+{
+ struct wd_ecc_point *s_key = NULL;
+ ECX_KEY *peer_ecx_key = NULL;
+ struct wd_ecc_req req = {0};
+ ECX_KEY *ecx_key = NULL;
+ int ret;
+
+ if (ecxctx == NULL) {
+ fprintf(stderr, "invalid: ctx is NULL\n");
+ return UADK_P_FAIL;
+ }
+
+ peer_ecx_key = ecxctx->peerkey;
+ ecx_key = ecxctx->key;
+ if (peer_ecx_key == NULL || ecx_key == NULL) {
+ fprintf(stderr, "invalid: peer_ecx_key or ecx_key is NULL\n");
+ return UADK_P_FAIL;
+ }
+
+ if (key == NULL || *keylen == 0) {
+ *keylen = (size_t)ecxctx->keylen;
+ return UADK_P_SUCCESS;
+ }
+
+ ret = uadk_prov_ecx_compkey_init_iot(ecxctx, &req);
+ if (ret == UADK_P_FAIL)
+ return UADK_P_FAIL;
+
+ ret = uadk_prov_ecx_derive_set_prikey(ecxctx);
+ if (ret == UADK_P_FAIL)
+ goto uninit_iot;
+
+ ret = uadk_prov_ecc_crypto(ecxctx->sess, &req, (void *)ecxctx);
+ if (ret == UADK_P_FAIL)
+ goto uninit_iot;
+
+ wd_ecxdh_get_out_params(req.dst, &s_key);
+ if (!s_key)
+ goto uninit_iot;
+
+ ret = uadk_prov_reverse_bytes((unsigned char *)s_key->x.data, s_key->x.dsize);
+ if (ret == UADK_P_FAIL)
+ goto uninit_iot;
+
+ uadk_prov_ecx_pad_out_key(key, (unsigned char *)s_key->x.data,
+ s_key->x.dsize, ecx_key->type);
+
+uninit_iot:
+ uadk_prov_ecx_compkey_uninit_iot(ecxctx, &req);
+
+ return ret;
+}
+
+static int uadk_keyexch_x448_derive(void *vecxctx, unsigned char *secret, size_t *secretlen,
+ size_t outlen)
+{
+ PROV_ECX_KEYEXCH_CTX *ecxctx = (PROV_ECX_KEYEXCH_CTX *)vecxctx;
+ int ret;
+
+ if (ecxctx == NULL) {
+ fprintf(stderr, "invalid: ecxctx is NULL in derive op\n");
+ return UADK_P_FAIL;
+ }
+
+ if (ecxctx->key == NULL || ecxctx->key->privkey == NULL ||
+ ecxctx->peerkey == NULL) {
+ ERR_raise(ERR_LIB_PROV, PROV_R_MISSING_KEY);
+ return UADK_P_FAIL;
+ }
+
+ if (ecxctx->keylen != X448_KEYLEN) {
+ ERR_raise(ERR_LIB_PROV, PROV_R_INVALID_KEY_LENGTH);
+ return UADK_P_FAIL;
+ }
+
+ if (secret == NULL) {
+ *secretlen = ecxctx->keylen;
+ return UADK_P_SUCCESS;
+ }
+
+ if (outlen < ecxctx->keylen) {
+ ERR_raise(ERR_LIB_PROV, PROV_R_OUTPUT_BUFFER_TOO_SMALL);
+ return UADK_P_FAIL;
+ }
+
+ ret = uadk_prov_keyexch_get_support_state(KEYEXCH_X448);
+ if (ret == UADK_P_FAIL) {
+ fprintf(stderr, "failed to get hardware x448 keyexch support\n");
+ return UADK_P_FAIL;
+ }
+
+ ret = uadk_prov_ecc_init("x448");
+ if (ret != UADK_P_SUCCESS) {
+ fprintf(stderr, "failed to init x448\n");
+ return UADK_P_FAIL;
+ }
+
+ ecxctx->sess = uadk_prov_x448_alloc_sess();
+ if (ecxctx->sess == (handle_t)0) {
+ fprintf(stderr, "failed to alloc sess\n");
+ return UADK_P_FAIL;
+ }
+
+ ret = uadk_prov_ecx_derive(ecxctx, secret, &ecxctx->keylen);
+ if (ret == UADK_P_FAIL)
+ fprintf(stderr, "failed to do x448 derive\n");
+
+ *secretlen = ecxctx->keylen;
+
+ uadk_prov_x448_free_sess(ecxctx->sess);
+
+ return ret;
+}
+
+static void *uadk_keyexch_x448_dupctx(void *vecxctx)
+{
+ PROV_ECX_KEYEXCH_CTX *srcctx = (PROV_ECX_KEYEXCH_CTX *)vecxctx;
+ PROV_ECX_KEYEXCH_CTX *dstctx;
+
+ if (srcctx == NULL)
+ return NULL;
+
+ dstctx = OPENSSL_zalloc(sizeof(PROV_ECX_KEYEXCH_CTX));
+ if (dstctx == NULL) {
+ ERR_raise(ERR_LIB_PROV, ERR_R_MALLOC_FAILURE);
+ return NULL;
+ }
+
+ *dstctx = *srcctx;
+ if (dstctx->key != NULL && !ossl_ecx_key_up_ref(dstctx->key)) {
+ ERR_raise(ERR_LIB_PROV, ERR_R_INTERNAL_ERROR);
+ OPENSSL_free(dstctx);
+ return NULL;
+ }
+
+ if (dstctx->peerkey != NULL && !ossl_ecx_key_up_ref(dstctx->peerkey)) {
+ ERR_raise(ERR_LIB_PROV, ERR_R_INTERNAL_ERROR);
+ uadk_prov_ecx_key_free(dstctx->key);
+ OPENSSL_free(dstctx);
+ return NULL;
+ }
+
+ return dstctx;
+}
diff --git a/src/uadk_prov_init.c b/src/uadk_prov_init.c
index 42e1272..9a2baeb 100644
--- a/src/uadk_prov_init.c
+++ b/src/uadk_prov_init.c
@@ -176,6 +176,8 @@ static const OSSL_ALGORITHM uadk_prov_keymgmt[] = {
uadk_sm2_keymgmt_functions, "uadk SM2 Keymgmt implementation." },
{ "EC", UADK_DEFAULT_PROPERTIES,
uadk_ec_keymgmt_functions, "uadk EC Keymgmt implementation."},
+ { "X448", UADK_DEFAULT_PROPERTIES,
+ uadk_x448_keymgmt_functions, "uadk X448 Keymgmt implementation."},
{ NULL, NULL, NULL }
};
@@ -192,6 +194,8 @@ static const OSSL_ALGORITHM uadk_prov_keyexch[] = {
uadk_dh_keyexch_functions, "UADK DH keyexch implementation"},
{ "ECDH", UADK_DEFAULT_PROPERTIES,
uadk_ecdh_keyexch_functions, "uadk_provider ecdh_keyexch" },
+ { "X448", UADK_DEFAULT_PROPERTIES,
+ uadk_x448_keyexch_functions, "uadk X448 keyexch implementation."},
{ NULL, NULL, NULL }
};
diff --git a/src/uadk_prov_pkey.c b/src/uadk_prov_pkey.c
index a861551..0615b61 100644
--- a/src/uadk_prov_pkey.c
+++ b/src/uadk_prov_pkey.c
@@ -29,6 +29,7 @@
#define PROV_SUPPORT 1
#define SIGNATURE_TYPE 3
#define ASYM_CIPHER_TYPE 3
+#define KEYEXCH_TYPE 4
#define SECURITY_CHECK_DISABLE 0
#define UADK_PROV_MIN_BITS 112
#define UADK_PROV_SECURITY_BITS 80
@@ -36,6 +37,7 @@
static int p_keymgmt_support_state[KEYMGMT_TYPE];
static int p_signature_support_state[SIGNATURE_TYPE];
static int p_asym_cipher_support_state[ASYM_CIPHER_TYPE];
+static int p_keyexch_support_state[KEYEXCH_TYPE];
struct ecc_prov {
int pid;
@@ -85,6 +87,16 @@ static void uadk_prov_asym_cipher_set_support_state(int alg_tag, int value)
p_asym_cipher_support_state[alg_tag] = value;
}
+int uadk_prov_keyexch_get_support_state(int alg_tag)
+{
+ return p_keyexch_support_state[alg_tag];
+}
+
+static void uadk_prov_keyexch_set_support_state(int alg_tag, int value)
+{
+ p_keyexch_support_state[alg_tag] = value;
+}
+
static int uadk_prov_ecc_get_hw_keybits(int key_bits)
{
if (key_bits > ECC384BITS)
@@ -358,7 +370,7 @@ int uadk_prov_ecc_crypto(handle_t sess, struct wd_ecc_req *req, void *usr)
{
struct uadk_e_cb_info cb_param;
struct async_op op;
- int idx, ret;
+ int idx, ret, cnt;
ret = async_setup_async_event_notification(&op);
if (ret == 0) {
@@ -385,11 +397,17 @@ int uadk_prov_ecc_crypto(handle_t sess, struct wd_ecc_req *req, void *usr)
goto err;
op.idx = idx;
+ cnt = 0;
do {
ret = wd_do_ecc_async(sess, req);
if (ret < 0 && ret != -EBUSY) {
- async_free_poll_task(op.idx, 0);
- goto err;
+ fprintf(stderr, "failed to do ecc async\n");
+ goto free_poll_task;
+ }
+
+ if (unlikely(++cnt > PROV_SEND_MAX_CNT)) {
+ fprintf(stderr, "do ecc async operation timeout\n");
+ goto free_poll_task;
}
} while (ret == -EBUSY);
@@ -398,10 +416,12 @@ int uadk_prov_ecc_crypto(handle_t sess, struct wd_ecc_req *req, void *usr)
goto err;
if (req->status)
- return UADK_P_FAIL;
+ goto err;
return UADK_P_SUCCESS;
+free_poll_task:
+ async_free_poll_task(op.idx, 0);
err:
(void)async_clear_async_event_notification();
return UADK_P_FAIL;
@@ -631,7 +651,7 @@ int uadk_prov_ecc_genctx_check(struct ec_gen_ctx *gctx, EC_KEY *ec)
return UADK_P_SUCCESS;
}
-bool uadk_prov_support_algorithm(const char *alg)
+static bool uadk_prov_support_algorithm(const char *alg)
{
struct uacce_dev_list *list = wd_get_accel_list(alg);
@@ -645,7 +665,7 @@ bool uadk_prov_support_algorithm(const char *alg)
void uadk_prov_keymgmt_alg(void)
{
- static const char * const keymgmt_alg[] = {"sm2", "ecdh"};
+ static const char * const keymgmt_alg[] = {"sm2", "x448", "ecdh"};
__u32 i, size;
bool sp;
@@ -664,7 +684,7 @@ void uadk_prov_signature_alg(void)
__u32 i, size;
bool sp;
- /* Enumerate keymgmt algs to check whether it is supported and set tags */
+ /* Enumerate signature algs to check whether it is supported and set tags */
size = ARRAY_SIZE(signature_alg);
for (i = 0; i < size; i++) {
sp = uadk_prov_support_algorithm(*(signature_alg + i));
@@ -769,7 +789,7 @@ void uadk_prov_asym_cipher_alg(void)
__u32 i, size;
bool sp;
- /* Enumerate keymgmt algs to check whether it is supported and set tags */
+ /* Enumerate asym_cipher algs to check whether it is supported and set tags */
size = ARRAY_SIZE(asym_cipher_alg);
for (i = 0; i < size; i++) {
sp = uadk_prov_support_algorithm(*(asym_cipher_alg + i));
@@ -815,6 +835,21 @@ void uadk_prov_ecc_uninit(void)
pthread_mutex_unlock(&ecc_mutex);
}
+void uadk_prov_keyexch_alg(void)
+{
+ static const char * const keyexch_alg[] = {"x448", "ecdh"};
+ __u32 i, size;
+ bool sp;
+
+ /* Enumerate keyexch algs to check whether it is supported and set tags */
+ size = ARRAY_SIZE(keyexch_alg);
+ for (i = 0; i < size; i++) {
+ sp = uadk_prov_support_algorithm(*(keyexch_alg + i));
+ if (sp)
+ uadk_prov_keyexch_set_support_state(i, PROV_SUPPORT);
+ }
+}
+
int uadk_prov_ecc_bit_check(const EC_GROUP *group)
{
int bits = EC_GROUP_order_bits(group);
diff --git a/src/uadk_prov_pkey.h b/src/uadk_prov_pkey.h
index fbec388..e79fc52 100644
--- a/src/uadk_prov_pkey.h
+++ b/src/uadk_prov_pkey.h
@@ -68,7 +68,8 @@
enum {
KEYMGMT_SM2 = 0x0,
- KEYMGMT_EC = 0x1,
+ KEYMGMT_X448 = 0x1,
+ KEYMGMT_ECDH = 0x2,
KEYMGMT_MAX = 0x6
};
@@ -83,6 +84,11 @@ enum {
COFACTOR_MODE_ENABLED = 1,
};
+enum {
+ KEYEXCH_X448 = 0x0,
+ KEYEXCH_ECDH = 0x1,
+};
+
struct curve_param {
/* Prime */
BIGNUM *p;
@@ -451,11 +457,11 @@ void uadk_prov_signature_alg(void);
void uadk_prov_asym_cipher_alg(void);
int uadk_prov_asym_cipher_get_support_state(int alg_tag);
int uadk_prov_ecc_init(const char *alg_name);
+void uadk_prov_keyexch_alg(void);
+int uadk_prov_keyexch_get_support_state(int alg_tag);
int uadk_prov_ecc_bit_check(const EC_GROUP *group);
-bool uadk_prov_support_algorithm(const char *alg);
int uadk_prov_get_affine_coordinates(const EC_GROUP *group, const EC_POINT *p,
BIGNUM *x, BIGNUM *y, BN_CTX *ctx);
-void uadk_prov_keyexch_alg(void);
int uadk_prov_securitycheck_enabled(OSSL_LIB_CTX *ctx);
int uadk_prov_ecc_check_key(OSSL_LIB_CTX *ctx, const EC_KEY *ec, int protect);
--
2.25.1