From: Zhiqi Song songzhiqi1@huawei.com
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 --- 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 = ¶ms; + + 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);