*** BLURB HERE ***
Chenghai Huang (1): uadk_provider: add aead alg for uadk_provider in openssl3.0
Qi Tao (1): uadk_provider/rsa: cleanup variable definition and return value
Weili Qian (6): uadk_provider: move functions to uadk_prov_pkey.c uadk_provider: add query_operation_name callback for keymgmt uadk_provider: support ec keymgmt hardware acceleration uadk_provider: support ecdh keyexch hardware acceleration uadk_provider: use default provider to get random data uadk_provider: alloc memory when copying ctx
Zhiqi Song (1): uadk_provider: support x448 alg
lizhi (1): uadk_engine: clear some compilation warnings, specific cleanup is as follows.
src/Makefile.am | 20 +- src/uadk_aead.c | 2 +- src/uadk_prov.h | 12 +- src/uadk_prov_aead.c | 1030 +++++++++++++++++++++++++++++++ src/uadk_prov_bio.c | 2 + src/uadk_prov_cipher.c | 6 +- src/uadk_prov_der_writer.c | 2 +- src/uadk_prov_dh.c | 17 +- src/uadk_prov_digest.c | 38 +- src/uadk_prov_ec_kmgmt.c | 746 +++++++++++++++++++++++ src/uadk_prov_ecdh_exch.c | 884 +++++++++++++++++++++++++++ src/uadk_prov_ecx.c | 1164 ++++++++++++++++++++++++++++++++++++ src/uadk_prov_ffc.c | 24 +- src/uadk_prov_ffc.h | 1 - src/uadk_prov_init.c | 33 +- src/uadk_prov_pkey.c | 191 +++++- src/uadk_prov_pkey.h | 28 +- src/uadk_prov_rsa.c | 326 +++++----- src/uadk_prov_sm2.c | 71 +-- 19 files changed, 4329 insertions(+), 268 deletions(-) create mode 100644 src/uadk_prov_aead.c create mode 100644 src/uadk_prov_ec_kmgmt.c create mode 100644 src/uadk_prov_ecdh_exch.c create mode 100644 src/uadk_prov_ecx.c
From: Chenghai Huang huangchenghai2@huawei.com
The following 3 AES algorithms are added: AES-128-GCM AES-192-GCM AES-256-GCM
Signed-off-by: Chenghai Huang huangchenghai2@huawei.com --- src/Makefile.am | 2 +- src/uadk_prov.h | 4 + src/uadk_prov_aead.c | 1030 ++++++++++++++++++++++++++++++++++++++++++ src/uadk_prov_init.c | 7 + 4 files changed, 1042 insertions(+), 1 deletion(-) create mode 100644 src/uadk_prov_aead.c
diff --git a/src/Makefile.am b/src/Makefile.am index 54c00e7..921305b 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -65,7 +65,7 @@ uadk_provider_la_SOURCES=uadk_prov_init.c uadk_async.c uadk_utils.c \ uadk_prov_rsa.c uadk_prov_dh.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_ffc.c uadk_prov_aead.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 8756fc6..ac82245 100644 --- a/src/uadk_prov.h +++ b/src/uadk_prov.h @@ -162,6 +162,9 @@ extern const OSSL_DISPATCH uadk_sm4_ecb_functions[FUNC_MAX_NUM]; extern const OSSL_DISPATCH uadk_sm4_ofb128_functions[FUNC_MAX_NUM]; extern const OSSL_DISPATCH uadk_sm4_cfb128_functions[FUNC_MAX_NUM]; extern const OSSL_DISPATCH uadk_sm4_ctr_functions[FUNC_MAX_NUM]; +extern const OSSL_DISPATCH uadk_aes_128_gcm_functions[FUNC_MAX_NUM]; +extern const OSSL_DISPATCH uadk_aes_192_gcm_functions[FUNC_MAX_NUM]; +extern const OSSL_DISPATCH uadk_aes_256_gcm_functions[FUNC_MAX_NUM]; extern const OSSL_DISPATCH uadk_des_ede3_cbc_functions[]; extern const OSSL_DISPATCH uadk_des_ede3_ecb_functions[];
@@ -178,6 +181,7 @@ extern const OSSL_DISPATCH uadk_sm2_asym_cipher_functions[FUNC_MAX_NUM];
void uadk_prov_destroy_digest(void); void uadk_prov_destroy_cipher(void); +void uadk_prov_destroy_aead(void); void uadk_prov_destroy_rsa(void); void uadk_prov_destroy_dh(void); void uadk_prov_sm2_uninit(void); diff --git a/src/uadk_prov_aead.c b/src/uadk_prov_aead.c new file mode 100644 index 0000000..d6e90ca --- /dev/null +++ b/src/uadk_prov_aead.c @@ -0,0 +1,1030 @@ +// SPDX-License-Identifier: Apache-2.0 +/* + * 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 <stdio.h> +#include <stdbool.h> +#include <string.h> +#include <dlfcn.h> +#include <numa.h> +#include <openssl/core_names.h> +#include <openssl/proverr.h> +#include <uadk/wd_aead.h> +#include <uadk/wd_sched.h> +#include "uadk.h" +#include "uadk_async.h" +#include "uadk_prov.h" + +#define MAX_IV_LEN 16 +#define MAX_KEY_LEN 64 +#define MAX_AAD_LEN 0xFFFF +#define ALG_NAME_SIZE 128 +#define AES_GCM_TAG_LEN 16 +/* The max data length is 16M-512B */ +#define AEAD_BLOCK_SIZE 0xFFFE00 + +#define UADK_OSSL_FAIL 0 +#define UADK_AEAD_SUCCESS 1 +#define UADK_AEAD_FAIL (-1) + +#define UNINITIALISED_SIZET ((size_t)-1) +#define IV_STATE_UNINITIALISED 0 +#define IV_STATE_SET 1 +#define KEY_STATE_SET 1 + +/* Internal flags that can be queried */ +#define PROV_CIPHER_FLAG_AEAD 0x0001 +#define PROV_CIPHER_FLAG_CUSTOM_IV 0x0002 +#define AEAD_FLAGS (PROV_CIPHER_FLAG_AEAD | PROV_CIPHER_FLAG_CUSTOM_IV) + +#define UADK_AEAD_DEF_CTXS 2 +#define UADK_AEAD_OP_NUM 1 + +struct aead_prov { + int pid; +}; +static struct aead_prov aprov; +static pthread_mutex_t aead_mutex = PTHREAD_MUTEX_INITIALIZER; + +enum uadk_aead_mode { + UNINIT_MODE, + ASYNC_MODE, + SYNC_MODE +}; + +enum aead_tag_status { + INIT_TAG, + READ_TAG, /* The MAC has been read. */ + SET_TAG /* The MAC has been set to req. */ +}; + +struct aead_priv_ctx { + int nid; + char alg_name[ALG_NAME_SIZE]; + size_t keylen; + size_t ivlen; + size_t taglen; + + unsigned int enc : 1; + unsigned int key_set : 1; /* Whether key is copied to priv key buffers */ + unsigned int iv_set : 1; /* Whether iv is copied to priv iv buffers */ + enum aead_tag_status tag_set; /* Whether mac is copied to priv mac buffers */ + + unsigned char iv[MAX_IV_LEN]; + unsigned char key[MAX_KEY_LEN]; + unsigned char buf[AES_GCM_TAG_LEN]; /* mac buffers */ + unsigned char *data; /* store input and output when block mode */ + + struct wd_aead_sess_setup setup; + struct wd_aead_req req; + enum uadk_aead_mode mode; + handle_t sess; +}; + +struct aead_info { + int nid; + enum wd_cipher_alg alg; + enum wd_cipher_mode mode; +}; + +static struct aead_info aead_info_table[] = { + { NID_aes_128_gcm, WD_CIPHER_AES, WD_CIPHER_GCM }, + { NID_aes_192_gcm, WD_CIPHER_AES, WD_CIPHER_GCM }, + { NID_aes_256_gcm, WD_CIPHER_AES, WD_CIPHER_GCM } +}; + +static int uadk_aead_poll(void *ctx) +{ + __u64 rx_cnt = 0; + __u32 recv = 0; + /* Poll one packet currently */ + int expt = 1; + int ret; + + do { + ret = wd_aead_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 void uadk_aead_mutex_infork(void) +{ + /* Release the replication lock of the child process */ + pthread_mutex_unlock(&aead_mutex); +} + +static int uadk_prov_aead_dev_init(struct aead_priv_ctx *priv) +{ + struct wd_ctx_nums ctx_set_num; + struct wd_ctx_params cparams = {0}; + int ret = UADK_AEAD_SUCCESS; + + pthread_atfork(NULL, NULL, uadk_aead_mutex_infork); + pthread_mutex_lock(&aead_mutex); + if (aprov.pid == getpid()) + goto mutex_unlock; + + cparams.op_type_num = UADK_AEAD_OP_NUM; + cparams.ctx_set_num = &ctx_set_num; + cparams.bmp = numa_allocate_nodemask(); + if (!cparams.bmp) { + ret = UADK_AEAD_FAIL; + fprintf(stderr, "failed to create nodemask!\n"); + goto mutex_unlock; + } + + numa_bitmask_setall(cparams.bmp); + + ctx_set_num.sync_ctx_num = UADK_AEAD_DEF_CTXS; + ctx_set_num.async_ctx_num = UADK_AEAD_DEF_CTXS; + + ret = wd_aead_init2_(priv->alg_name, TASK_MIX, SCHED_POLICY_RR, &cparams); + if (unlikely(ret)) { + ret = UADK_AEAD_FAIL; + fprintf(stderr, "failed to init aead!\n"); + goto free_nodemask; + } + + aprov.pid = getpid(); + async_register_poll_fn(ASYNC_TASK_AEAD, uadk_aead_poll); + +free_nodemask: + numa_free_nodemask(cparams.bmp); +mutex_unlock: + pthread_mutex_unlock(&aead_mutex); + return ret; +} + +static int uadk_prov_aead_ctx_init(struct aead_priv_ctx *priv) +{ + struct wd_aead_sess_setup setup = {0}; + struct sched_params params = {0}; + int ret; + + if (!priv->key_set || !priv->iv_set) { + fprintf(stderr, "key or iv is not set yet!\n"); + return UADK_AEAD_FAIL; + } + + priv->req.iv_bytes = priv->ivlen; + priv->req.iv = priv->iv; + priv->req.out_bytes = 0; + priv->req.mac = priv->buf; + priv->req.mac_bytes = priv->taglen; + + ret = uadk_prov_aead_dev_init(priv); + if (unlikely(ret < 0)) + return UADK_AEAD_FAIL; + + /* dec and enc use the same op */ + params.type = 0; + /* Use the default numa parameters */ + params.numa_id = -1; + memcpy(&setup, &priv->setup, sizeof(struct wd_aead_sess_setup)); + setup.sched_param = ¶ms; + + if (!priv->sess) { + priv->sess = wd_aead_alloc_sess(&setup); + if (!priv->sess) { + fprintf(stderr, "uadk failed to alloc session!\n"); + return UADK_AEAD_FAIL; + } + + ret = wd_aead_set_authsize(priv->sess, priv->taglen); + if (ret) { + fprintf(stderr, "uadk failed to set authsize!\n"); + goto free_sess; + } + + ret = wd_aead_set_ckey(priv->sess, priv->key, priv->keylen); + if (ret) { + fprintf(stderr, "uadk failed to set key!\n"); + goto free_sess; + } + } + + return UADK_AEAD_SUCCESS; + +free_sess: + wd_aead_free_sess(priv->sess); + priv->sess = 0; + return UADK_AEAD_FAIL; +} + +static void *uadk_prov_aead_cb(struct wd_aead_req *req, void *data) +{ + struct uadk_e_cb_info *cb_param; + struct wd_aead_req *req_origin; + struct async_op *op; + + if (!req) + return NULL; + + cb_param = req->cb_param; + if (!cb_param) + return NULL; + + req_origin = cb_param->priv; + req_origin->state = req->state; + + 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); + } + + return NULL; +} + +static int do_aes_gcm_prepare(struct aead_priv_ctx *priv) +{ + if (priv->mode == UNINIT_MODE) { + if (ASYNC_get_current_job()) + priv->mode = ASYNC_MODE; + else + priv->mode = SYNC_MODE; + } + + if (!priv->enc && priv->tag_set == READ_TAG) { + if (likely(priv->taglen == AES_GCM_TAG_LEN)) { + memcpy(priv->req.mac, priv->buf, AES_GCM_TAG_LEN); + priv->tag_set = SET_TAG; + } else { + fprintf(stderr, "invalid: aead gcm mac length only support 16B.\n"); + return UADK_AEAD_FAIL; + } + } + + return UADK_AEAD_SUCCESS; +} + +static void uadk_do_aead_async_prepare(struct aead_priv_ctx *priv, unsigned char *out, + const unsigned char *in, size_t inlen) +{ + priv->req.in_bytes = inlen; + /* AAD data is input or output together with plaintext or ciphertext. */ + if (priv->req.assoc_bytes) { + memcpy(priv->data + priv->req.assoc_bytes, in, inlen); + priv->req.src = priv->data; + priv->req.dst = priv->data + AEAD_BLOCK_SIZE; + } else { + priv->req.src = (unsigned char *)in; + priv->req.dst = out; + } +} + +static int uadk_do_aead_sync_inner(struct aead_priv_ctx *priv, unsigned char *out, + const unsigned char *in, size_t inlen, enum wd_aead_msg_state state) +{ + int ret; + + if ((state == AEAD_MSG_BLOCK || state == AEAD_MSG_END) + && !priv->enc && priv->tag_set != SET_TAG) { + fprintf(stderr, "The tag for synchronous decryption is not set.\n"); + return UADK_AEAD_FAIL; + } + + priv->req.msg_state = state; + priv->req.src = (unsigned char *)in; + priv->req.dst = out; + priv->req.in_bytes = inlen; + priv->req.state = 0; + ret = wd_do_aead_sync(priv->sess, &priv->req); + if (unlikely(ret < 0 || priv->req.state)) { + fprintf(stderr, "do aead task failed, msg state: %u, ret: %d, state: %u!\n", + state, ret, priv->req.state); + return UADK_AEAD_FAIL; + } + + return inlen; +} + +static int uadk_do_aead_sync(struct aead_priv_ctx *priv, unsigned char *out, + const unsigned char *in, size_t inlen) +{ + size_t nbytes, tail, processing_len, max_mid_len; + const unsigned char *in_block = in; + unsigned char *out_block = out; + int ret; + + /* Due to a hardware limitation, zero-length aad using block mode. */ + if (!priv->req.assoc_bytes) + return uadk_do_aead_sync_inner(priv, out, in, inlen, AEAD_MSG_BLOCK); + + tail = inlen % AES_BLOCK_SIZE; + nbytes = inlen - tail; + max_mid_len = AEAD_BLOCK_SIZE - priv->req.assoc_bytes; + + /* If the data length is not 16-byte aligned, it is split according to the protocol. */ + while (nbytes > 0) { + processing_len = nbytes > max_mid_len ? max_mid_len : nbytes; + processing_len -= (processing_len % AES_BLOCK_SIZE); + + ret = uadk_do_aead_sync_inner(priv, out_block, in_block, + processing_len, AEAD_MSG_MIDDLE); + if (ret < 0) + return UADK_AEAD_FAIL; + nbytes -= processing_len; + in_block = in_block + processing_len; + out_block = out_block + processing_len; + } + + if (tail) { + ret = uadk_do_aead_sync_inner(priv, out_block, in_block, tail, AEAD_MSG_END); + if (ret < 0) + return UADK_AEAD_FAIL; + } + + return inlen; +} + +static int uadk_do_aead_async(struct aead_priv_ctx *priv, struct async_op *op, + unsigned char *out, const unsigned char *in, size_t inlen) +{ + struct uadk_e_cb_info *cb_param; + int cnt = 0; + int ret; + + if (!priv->enc && priv->tag_set != SET_TAG) { + fprintf(stderr, "The tag for asynchronous decryption is not set.\n"); + return UADK_AEAD_FAIL; + } + + if (unlikely(priv->req.assoc_bytes + inlen > AEAD_BLOCK_SIZE)) { + fprintf(stderr, "aead input data length is too long!\n"); + return UADK_AEAD_FAIL; + } + + uadk_do_aead_async_prepare(priv, out, in, inlen); + + cb_param = malloc(sizeof(struct uadk_e_cb_info)); + if (unlikely(!cb_param)) { + fprintf(stderr, "failed to alloc cb_param.\n"); + return UADK_AEAD_FAIL; + } + + cb_param->op = op; + cb_param->priv = &priv->req; + priv->req.cb = uadk_prov_aead_cb; + priv->req.cb_param = cb_param; + priv->req.msg_state = AEAD_MSG_BLOCK; + priv->req.state = UADK_AEAD_FAIL; + + ret = async_get_free_task(&op->idx); + if (unlikely(!ret)) + goto free_cb_param; + + do { + ret = wd_do_aead_async(priv->sess, &priv->req); + if (unlikely(ret < 0)) { + if (unlikely(ret != -EBUSY)) + fprintf(stderr, "do aead async operation failed ret = %d.\n", ret); + else if (unlikely(cnt++ > ENGINE_SEND_MAX_CNT)) + fprintf(stderr, "do aead async operation timeout.\n"); + else + continue; + + async_free_poll_task(op->idx, 0); + ret = UADK_AEAD_FAIL; + goto free_cb_param; + } + } while (ret == -EBUSY); + + ret = async_pause_job(priv, op, ASYNC_TASK_AEAD); + if (unlikely(!ret || priv->req.state)) { + fprintf(stderr, "do aead async job failed, ret: %d, state: %u!\n", + ret, priv->req.state); + ret = UADK_AEAD_FAIL; + goto free_cb_param; + } + + if (priv->req.assoc_bytes) + memcpy(out, priv->req.dst + priv->req.assoc_bytes, inlen); + +free_cb_param: + free(cb_param); + return ret; +} + +static int uadk_prov_do_aes_gcm_first(struct aead_priv_ctx *priv, unsigned char *out, + const unsigned char *in, size_t inlen) +{ + int ret; + + if (inlen > MAX_AAD_LEN) { + fprintf(stderr, "the aad len is out of range, aad len = %lu.\n", inlen); + return UADK_AEAD_FAIL; + } + + priv->req.assoc_bytes = inlen; + + /* Asynchronous jobs use the block mode. */ + if (priv->mode == ASYNC_MODE || !priv->req.assoc_bytes) { + memcpy(priv->data, in, inlen); + return UADK_AEAD_SUCCESS; + } + + ret = uadk_do_aead_sync_inner(priv, out, in, inlen, AEAD_MSG_FIRST); + if (unlikely(ret < 0)) + return UADK_AEAD_FAIL; + + return UADK_AEAD_SUCCESS; +} + +static int uadk_prov_do_aes_gcm_update(struct aead_priv_ctx *priv, unsigned char *out, + const unsigned char *in, size_t inlen) +{ + struct async_op *op; + int ret; + + if (priv->mode == ASYNC_MODE) { + op = malloc(sizeof(struct async_op)); + if (unlikely(!op)) + return UADK_AEAD_FAIL; + + ret = async_setup_async_event_notification(op); + if (unlikely(!ret)) { + fprintf(stderr, "failed to setup async event notification.\n"); + goto free_op; + } + + ret = uadk_do_aead_async(priv, op, out, in, inlen); + if (unlikely(ret < 0)) { + fprintf(stderr, "uadk_do_aead_async failed ret = %d.\n", ret); + goto free_notification; + } + + free(op); + return inlen; + } + + return uadk_do_aead_sync(priv, out, in, inlen); + +free_notification: + (void)async_clear_async_event_notification(); +free_op: + free(op); + return UADK_AEAD_FAIL; +} + +static int uadk_prov_do_aes_gcm_final(struct aead_priv_ctx *priv, unsigned char *out, + const unsigned char *in, size_t inlen) +{ + int ret; + + if (priv->mode == ASYNC_MODE || !priv->req.assoc_bytes || + priv->req.msg_state == AEAD_MSG_END) + goto out; + + ret = uadk_do_aead_sync_inner(priv, out, in, inlen, AEAD_MSG_END); + if (unlikely(ret < 0)) + return UADK_AEAD_FAIL; + +out: + if (priv->enc) + memcpy(priv->buf, priv->req.mac, priv->taglen); + else + priv->tag_set = INIT_TAG; + + priv->mode = UNINIT_MODE; + return UADK_AEAD_SUCCESS; +} + +static int uadk_prov_do_aes_gcm(struct aead_priv_ctx *priv, unsigned char *out, + size_t *outl, size_t outsize, + const unsigned char *in, size_t inlen) +{ + int ret; + + ret = uadk_prov_aead_ctx_init(priv); + if (ret != UADK_AEAD_SUCCESS) + return UADK_AEAD_FAIL; + + ret = do_aes_gcm_prepare(priv); + if (unlikely(ret < 0)) + return UADK_AEAD_FAIL; + + if (in) { + if (!out) + return uadk_prov_do_aes_gcm_first(priv, out, in, inlen); + + return uadk_prov_do_aes_gcm_update(priv, out, in, inlen); + } + + return uadk_prov_do_aes_gcm_final(priv, out, NULL, 0); +} + +void uadk_prov_destroy_aead(void) +{ + pthread_mutex_lock(&aead_mutex); + if (aprov.pid == getpid()) { + wd_aead_uninit2(); + aprov.pid = 0; + } + pthread_mutex_unlock(&aead_mutex); +} + +static OSSL_FUNC_cipher_encrypt_init_fn uadk_prov_aead_einit; +static OSSL_FUNC_cipher_decrypt_init_fn uadk_prov_aead_dinit; +static OSSL_FUNC_cipher_freectx_fn uadk_prov_aead_freectx; +static OSSL_FUNC_cipher_dupctx_fn uadk_prov_aead_dupctx; +static OSSL_FUNC_cipher_get_ctx_params_fn uadk_prov_aead_get_ctx_params; +static OSSL_FUNC_cipher_gettable_ctx_params_fn uadk_prov_aead_gettable_ctx_params; +static OSSL_FUNC_cipher_set_ctx_params_fn uadk_prov_aead_set_ctx_params; +static OSSL_FUNC_cipher_settable_ctx_params_fn uadk_prov_aead_settable_ctx_params; + +static int uadk_prov_aead_cipher(void *vctx, unsigned char *out, size_t *outl, + size_t outsize, const unsigned char *in, + size_t inl) +{ + struct aead_priv_ctx *priv = (struct aead_priv_ctx *)vctx; + int ret; + + if (!vctx || !out || !outl) + return UADK_OSSL_FAIL; + + if (outsize < inl) { + ERR_raise(ERR_LIB_PROV, PROV_R_OUTPUT_BUFFER_TOO_SMALL); + return UADK_OSSL_FAIL; + } + + ret = uadk_prov_do_aes_gcm(priv, out, outl, outsize, in, inl); + if (ret < 0) + return UADK_OSSL_FAIL; + + *outl = inl; + return UADK_AEAD_SUCCESS; +} + +static int uadk_prov_aead_stream_update(void *vctx, unsigned char *out, + size_t *outl, size_t outsize, + const unsigned char *in, size_t inl) +{ + struct aead_priv_ctx *priv = (struct aead_priv_ctx *)vctx; + int ret; + + if (!vctx) + return UADK_OSSL_FAIL; + + if (outsize < inl) { + ERR_raise(ERR_LIB_PROV, PROV_R_OUTPUT_BUFFER_TOO_SMALL); + return UADK_OSSL_FAIL; + } + + ret = uadk_prov_do_aes_gcm(priv, out, outl, outsize, in, inl); + if (ret < 0) { + fprintf(stderr, "stream data update failed.\n"); + return UADK_OSSL_FAIL; + } + + *outl = inl; + return UADK_AEAD_SUCCESS; +} + +static int uadk_prov_aead_stream_final(void *vctx, unsigned char *out, + size_t *outl, size_t outsize) +{ + struct aead_priv_ctx *priv = (struct aead_priv_ctx *)vctx; + int ret; + + if (!vctx || !out || !outl) + return UADK_OSSL_FAIL; + + ret = uadk_prov_do_aes_gcm(priv, out, outl, outsize, NULL, 0); + if (ret < 0) { + fprintf(stderr, "stream data final failed, ret = %d\n", ret); + return UADK_OSSL_FAIL; + } + + *outl = 0; + return UADK_AEAD_SUCCESS; +} + +static int uadk_get_aead_info(struct aead_priv_ctx *priv) +{ + int aead_counts = ARRAY_SIZE(aead_info_table); + int i; + + for (i = 0; i < aead_counts; i++) { + if (priv->nid == aead_info_table[i].nid) { + priv->setup.calg = aead_info_table[i].alg; + priv->setup.cmode = aead_info_table[i].mode; + break; + } + } + + if (unlikely(i == aead_counts)) { + fprintf(stderr, "failed to setup the private ctx.\n"); + return UADK_AEAD_FAIL; + } + + return UADK_AEAD_SUCCESS; +} + +static int uadk_prov_aead_init(struct aead_priv_ctx *priv, + const unsigned char *key, size_t keylen, + const unsigned char *iv, size_t ivlen) +{ + int ret; + + if (ivlen > MAX_IV_LEN || keylen > MAX_KEY_LEN) { + fprintf(stderr, "invalid keylen or ivlen.\n"); + return UADK_OSSL_FAIL; + } + + if (iv) { + memcpy(priv->iv, iv, ivlen); + priv->iv_set = IV_STATE_SET; + } + + ret = uadk_get_aead_info(priv); + if (unlikely(ret < 0)) + return UADK_OSSL_FAIL; + + if (key) { + memcpy(priv->key, key, keylen); + priv->key_set = KEY_STATE_SET; + } + + ret = uadk_prov_aead_dev_init(priv); + if (unlikely(ret < 0)) + return UADK_OSSL_FAIL; + + return UADK_AEAD_SUCCESS; +} + +static int uadk_prov_aead_einit(void *vctx, const unsigned char *key, size_t keylen, + const unsigned char *iv, size_t ivlen, + const OSSL_PARAM params[]) +{ + struct aead_priv_ctx *priv = (struct aead_priv_ctx *)vctx; + + if (!vctx) + return UADK_OSSL_FAIL; + + priv->req.op_type = WD_CIPHER_ENCRYPTION_DIGEST; + priv->enc = 1; + + return uadk_prov_aead_init(priv, key, keylen, iv, ivlen); +} + +static int uadk_prov_aead_dinit(void *vctx, const unsigned char *key, size_t keylen, + const unsigned char *iv, size_t ivlen, + const OSSL_PARAM params[]) +{ + struct aead_priv_ctx *priv = (struct aead_priv_ctx *)vctx; + + if (!vctx) + return UADK_OSSL_FAIL; + + priv->req.op_type = WD_CIPHER_DECRYPTION_DIGEST; + priv->enc = 0; + + return uadk_prov_aead_init(priv, key, keylen, iv, ivlen); +} + +static const OSSL_PARAM uadk_prov_settable_ctx_params[] = { + OSSL_PARAM_size_t(OSSL_CIPHER_PARAM_KEYLEN, NULL), + OSSL_PARAM_size_t(OSSL_CIPHER_PARAM_AEAD_IVLEN, NULL), + OSSL_PARAM_octet_string(OSSL_CIPHER_PARAM_AEAD_TAG, NULL, 0), + OSSL_PARAM_END +}; + +const OSSL_PARAM *uadk_prov_aead_settable_ctx_params(ossl_unused void *cctx, + ossl_unused void *provctx) +{ + return uadk_prov_settable_ctx_params; +} + +static int uadk_prov_aead_set_ctx_params(void *vctx, const OSSL_PARAM params[]) +{ + struct aead_priv_ctx *priv = (struct aead_priv_ctx *)vctx; + const OSSL_PARAM *p; + size_t sz = 0; + void *vp; + + if (!vctx) + return UADK_OSSL_FAIL; + + p = OSSL_PARAM_locate_const(params, OSSL_CIPHER_PARAM_AEAD_TAG); + if (p) { + vp = priv->buf; + if (!OSSL_PARAM_get_octet_string(p, &vp, EVP_GCM_TLS_TAG_LEN, &sz)) { + ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_GET_PARAMETER); + return UADK_OSSL_FAIL; + } + + if (sz == 0 || priv->enc) { + ERR_raise(ERR_LIB_PROV, PROV_R_INVALID_TAG); + return UADK_OSSL_FAIL; + } + priv->tag_set = READ_TAG; + priv->taglen = sz; + } + + p = OSSL_PARAM_locate_const(params, OSSL_CIPHER_PARAM_KEYLEN); + if (p) { + size_t keylen; + + if (!OSSL_PARAM_get_size_t(p, &keylen)) { + ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_GET_PARAMETER); + return UADK_OSSL_FAIL; + } + if (priv->keylen != keylen) { + ERR_raise(ERR_LIB_PROV, PROV_R_INVALID_KEY_LENGTH); + return UADK_OSSL_FAIL; + } + } + + p = OSSL_PARAM_locate_const(params, OSSL_CIPHER_PARAM_AEAD_IVLEN); + if (p) { + if (!OSSL_PARAM_get_size_t(p, &sz)) { + ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_GET_PARAMETER); + return UADK_OSSL_FAIL; + } + if (sz == 0 || sz > priv->ivlen) { + ERR_raise(ERR_LIB_PROV, PROV_R_INVALID_IV_LENGTH); + return UADK_OSSL_FAIL; + } + priv->ivlen = sz; + } + + return UADK_AEAD_SUCCESS; +} + +static const OSSL_PARAM uadk_prov_aead_ctx_params[] = { + OSSL_PARAM_size_t(OSSL_CIPHER_PARAM_KEYLEN, NULL), + OSSL_PARAM_size_t(OSSL_CIPHER_PARAM_IVLEN, NULL), + OSSL_PARAM_size_t(OSSL_CIPHER_PARAM_AEAD_TAGLEN, NULL), + OSSL_PARAM_octet_string(OSSL_CIPHER_PARAM_IV, NULL, 0), + OSSL_PARAM_octet_string(OSSL_CIPHER_PARAM_UPDATED_IV, NULL, 0), + OSSL_PARAM_octet_string(OSSL_CIPHER_PARAM_AEAD_TAG, NULL, 0), + OSSL_PARAM_END +}; + +static const OSSL_PARAM *uadk_prov_aead_gettable_ctx_params(ossl_unused void *cctx, + ossl_unused void *provctx) +{ + return uadk_prov_aead_ctx_params; +} + +static int uadk_prov_aead_get_ctx_params(void *vctx, OSSL_PARAM params[]) +{ + struct aead_priv_ctx *priv = (struct aead_priv_ctx *)vctx; + OSSL_PARAM *p; + + if (!vctx || !params) + return UADK_OSSL_FAIL; + + p = OSSL_PARAM_locate(params, OSSL_CIPHER_PARAM_IVLEN); + if (p && !OSSL_PARAM_set_size_t(p, priv->ivlen)) { + ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_SET_PARAMETER); + return UADK_OSSL_FAIL; + } + + p = OSSL_PARAM_locate(params, OSSL_CIPHER_PARAM_KEYLEN); + if (p && !OSSL_PARAM_set_size_t(p, priv->keylen)) { + ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_SET_PARAMETER); + return UADK_OSSL_FAIL; + } + + p = OSSL_PARAM_locate(params, OSSL_CIPHER_PARAM_AEAD_TAGLEN); + if (p) { + size_t taglen = (priv->taglen != UNINITIALISED_SIZET) ? + priv->taglen : AES_GCM_TAG_LEN; + + if (!OSSL_PARAM_set_size_t(p, taglen)) { + ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_SET_PARAMETER); + return UADK_OSSL_FAIL; + } + } + + p = OSSL_PARAM_locate(params, OSSL_CIPHER_PARAM_IV); + if (p) { + if (priv->iv_set == IV_STATE_UNINITIALISED) + return UADK_OSSL_FAIL; + if (priv->ivlen > p->data_size) { + ERR_raise(ERR_LIB_PROV, PROV_R_INVALID_IV_LENGTH); + return UADK_OSSL_FAIL; + } + if (!OSSL_PARAM_set_octet_string(p, priv->iv, priv->ivlen) + && !OSSL_PARAM_set_octet_ptr(p, &priv->iv, priv->ivlen)) { + ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_SET_PARAMETER); + return UADK_OSSL_FAIL; + } + } + + p = OSSL_PARAM_locate(params, OSSL_CIPHER_PARAM_UPDATED_IV); + if (p) { + if (priv->iv_set == IV_STATE_UNINITIALISED) + return UADK_OSSL_FAIL; + if (priv->ivlen > p->data_size) { + ERR_raise(ERR_LIB_PROV, PROV_R_INVALID_IV_LENGTH); + return UADK_OSSL_FAIL; + } + if (!OSSL_PARAM_set_octet_string(p, priv->iv, priv->ivlen) + && !OSSL_PARAM_set_octet_ptr(p, &priv->iv, priv->ivlen)) { + ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_SET_PARAMETER); + return UADK_OSSL_FAIL; + } + } + + p = OSSL_PARAM_locate(params, OSSL_CIPHER_PARAM_AEAD_TAG); + if (p) { + size_t sz = p->data_size; + + if (sz == 0 || sz > EVP_GCM_TLS_TAG_LEN || !priv->enc + || priv->taglen == UNINITIALISED_SIZET) { + ERR_raise(ERR_LIB_PROV, PROV_R_INVALID_TAG); + return UADK_OSSL_FAIL; + } + + if (!OSSL_PARAM_set_octet_string(p, priv->buf, sz)) { + ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_SET_PARAMETER); + return UADK_OSSL_FAIL; + } + } + return UADK_AEAD_SUCCESS; +} + +static const OSSL_PARAM aead_known_gettable_params[] = { + OSSL_PARAM_uint(OSSL_CIPHER_PARAM_MODE, NULL), + OSSL_PARAM_size_t(OSSL_CIPHER_PARAM_KEYLEN, NULL), + OSSL_PARAM_size_t(OSSL_CIPHER_PARAM_IVLEN, NULL), + OSSL_PARAM_size_t(OSSL_CIPHER_PARAM_BLOCK_SIZE, NULL), + OSSL_PARAM_int(OSSL_CIPHER_PARAM_AEAD, NULL), + OSSL_PARAM_int(OSSL_CIPHER_PARAM_CUSTOM_IV, NULL), + OSSL_PARAM_END +}; + +static const OSSL_PARAM *uadk_prov_aead_gettable_params(ossl_unused void *provctx) +{ + return aead_known_gettable_params; +} + +static int uadk_cipher_aead_get_params(OSSL_PARAM params[], unsigned int md, + uint64_t flags, size_t kbits, + size_t blkbits, size_t ivbits) +{ + OSSL_PARAM *p; + + p = OSSL_PARAM_locate(params, OSSL_CIPHER_PARAM_MODE); + if (p && !OSSL_PARAM_set_uint(p, md)) { + ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_SET_PARAMETER); + return UADK_OSSL_FAIL; + } + p = OSSL_PARAM_locate(params, OSSL_CIPHER_PARAM_AEAD); + if (p && !OSSL_PARAM_set_int(p, (flags & PROV_CIPHER_FLAG_AEAD) != 0)) { + ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_SET_PARAMETER); + return UADK_OSSL_FAIL; + } + p = OSSL_PARAM_locate(params, OSSL_CIPHER_PARAM_CUSTOM_IV); + if (p && !OSSL_PARAM_set_int(p, (flags & PROV_CIPHER_FLAG_CUSTOM_IV) != 0)) { + ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_SET_PARAMETER); + return UADK_OSSL_FAIL; + } + p = OSSL_PARAM_locate(params, OSSL_CIPHER_PARAM_KEYLEN); + if (p && !OSSL_PARAM_set_size_t(p, kbits)) { + ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_SET_PARAMETER); + return UADK_OSSL_FAIL; + } + p = OSSL_PARAM_locate(params, OSSL_CIPHER_PARAM_BLOCK_SIZE); + if (p && !OSSL_PARAM_set_size_t(p, blkbits)) { + ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_SET_PARAMETER); + return UADK_OSSL_FAIL; + } + p = OSSL_PARAM_locate(params, OSSL_CIPHER_PARAM_IVLEN); + if (p && !OSSL_PARAM_set_size_t(p, ivbits)) { + ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_SET_PARAMETER); + return UADK_OSSL_FAIL; + } + + return UADK_AEAD_SUCCESS; +} + +static void *uadk_prov_aead_dupctx(void *ctx) +{ + struct aead_priv_ctx *priv, *ret; + + priv = (struct aead_priv_ctx *)ctx; + if (!priv) + return NULL; + + ret = OPENSSL_memdup(priv, sizeof(*priv)); + if (!ret) + return NULL; + + ret->sess = 0; + ret->data = OPENSSL_memdup(priv->data, AEAD_BLOCK_SIZE << 1); + if (!ret->data) { + OPENSSL_clear_free(ret, sizeof(*ret)); + return NULL; + } + + return ret; +} + +static void uadk_prov_aead_freectx(void *ctx) +{ + struct aead_priv_ctx *priv = (struct aead_priv_ctx *)ctx; + + if (!ctx) + return; + + if (priv->sess) { + wd_aead_free_sess(priv->sess); + priv->sess = 0; + } + + if (priv->data) { + OPENSSL_clear_free(priv->data, AEAD_BLOCK_SIZE << 1); + priv->data = NULL; + } + OPENSSL_clear_free(priv, sizeof(*priv)); +} + +#define UADK_AEAD_DESCR(nm, tag_len, key_len, iv_len, blk_size, \ + flags, e_nid, algnm, mode) \ +static OSSL_FUNC_cipher_newctx_fn uadk_##nm##_newctx; \ +static void *uadk_##nm##_newctx(void *provctx) \ +{ \ + struct aead_priv_ctx *ctx = OPENSSL_zalloc(sizeof(*ctx)); \ + if (!ctx) \ + return NULL; \ + \ + ctx->data = OPENSSL_zalloc(AEAD_BLOCK_SIZE << 1); \ + if (!ctx->data) { \ + OPENSSL_clear_free(ctx, sizeof(*ctx)); \ + return NULL; \ + } \ + \ + ctx->keylen = key_len; \ + ctx->ivlen = iv_len; \ + ctx->nid = e_nid; \ + ctx->taglen = tag_len; \ + strncpy(ctx->alg_name, #algnm, ALG_NAME_SIZE - 1); \ + \ + return ctx; \ +} \ +static OSSL_FUNC_cipher_get_params_fn uadk_##nm##_get_params; \ +static int uadk_##nm##_get_params(OSSL_PARAM params[]) \ +{ \ + return uadk_cipher_aead_get_params(params, mode, flags, \ + key_len, blk_size, iv_len); \ +} \ +const OSSL_DISPATCH uadk_##nm##_functions[] = { \ + { OSSL_FUNC_CIPHER_NEWCTX, (void (*)(void))uadk_##nm##_newctx }, \ + { OSSL_FUNC_CIPHER_FREECTX, (void (*)(void))uadk_prov_aead_freectx }, \ + { OSSL_FUNC_CIPHER_DUPCTX, (void (*)(void))uadk_prov_aead_dupctx }, \ + { OSSL_FUNC_CIPHER_ENCRYPT_INIT, \ + (void (*)(void))uadk_prov_aead_einit }, \ + { OSSL_FUNC_CIPHER_DECRYPT_INIT, \ + (void (*)(void))uadk_prov_aead_dinit }, \ + { OSSL_FUNC_CIPHER_UPDATE, \ + (void (*)(void))uadk_prov_aead_stream_update }, \ + { OSSL_FUNC_CIPHER_FINAL, \ + (void (*)(void))uadk_prov_aead_stream_final }, \ + { OSSL_FUNC_CIPHER_CIPHER, (void (*)(void))uadk_prov_aead_cipher }, \ + { OSSL_FUNC_CIPHER_GET_PARAMS, \ + (void (*)(void))uadk_##nm##_get_params }, \ + { OSSL_FUNC_CIPHER_GETTABLE_PARAMS, \ + (void (*)(void))uadk_prov_aead_gettable_params }, \ + { OSSL_FUNC_CIPHER_GET_CTX_PARAMS, \ + (void (*)(void))uadk_prov_aead_get_ctx_params }, \ + { OSSL_FUNC_CIPHER_GETTABLE_CTX_PARAMS, \ + (void (*)(void))uadk_prov_aead_gettable_ctx_params }, \ + { OSSL_FUNC_CIPHER_SET_CTX_PARAMS, \ + (void (*)(void))uadk_prov_aead_set_ctx_params }, \ + { OSSL_FUNC_CIPHER_SETTABLE_CTX_PARAMS, \ + (void (*)(void))uadk_prov_aead_settable_ctx_params }, \ + { 0, NULL } \ +} + +UADK_AEAD_DESCR(aes_128_gcm, AES_GCM_TAG_LEN, 16, 12, 8, AEAD_FLAGS, NID_aes_128_gcm, gcm(aes), + EVP_CIPH_GCM_MODE); +UADK_AEAD_DESCR(aes_192_gcm, AES_GCM_TAG_LEN, 24, 12, 8, AEAD_FLAGS, NID_aes_192_gcm, gcm(aes), + EVP_CIPH_GCM_MODE); +UADK_AEAD_DESCR(aes_256_gcm, AES_GCM_TAG_LEN, 32, 12, 8, AEAD_FLAGS, NID_aes_256_gcm, gcm(aes), + EVP_CIPH_GCM_MODE); diff --git a/src/uadk_prov_init.c b/src/uadk_prov_init.c index 972f953..772ddbb 100644 --- a/src/uadk_prov_init.c +++ b/src/uadk_prov_init.c @@ -137,6 +137,12 @@ const OSSL_ALGORITHM uadk_prov_ciphers_v3[] = { uadk_aes_192_cfb128_functions, "uadk_provider aes-192-cfb" }, { "AES-256-CFB", UADK_DEFAULT_PROPERTIES, uadk_aes_256_cfb128_functions, "uadk_provider aes-256-cfb" }, + { "AES-128-GCM", UADK_DEFAULT_PROPERTIES, + uadk_aes_128_gcm_functions, "uadk_provider aes-128-gcm" }, + { "AES-192-GCM", UADK_DEFAULT_PROPERTIES, + uadk_aes_192_gcm_functions, "uadk_provider aes-192-gcm" }, + { "AES-256-GCM", UADK_DEFAULT_PROPERTIES, + uadk_aes_256_gcm_functions, "uadk_provider aes-256-gcm" }, { "SM4-CBC", UADK_DEFAULT_PROPERTIES, uadk_sm4_cbc_functions, "uadk_provider sm4-cbc" }, { "SM4-ECB", UADK_DEFAULT_PROPERTIES, @@ -232,6 +238,7 @@ static void uadk_teardown(void *provctx)
uadk_prov_destroy_digest(); uadk_prov_destroy_cipher(); + uadk_prov_destroy_aead(); uadk_prov_destroy_rsa(); uadk_prov_sm2_uninit(); uadk_prov_dh_uninit();
From: Weili Qian qianweili@huawei.com
The ecc algorithm initialization and resource release processes are the same. Therefore, the functions uadk_prov_sm2_init() and uadk_prov_sm2_uninit() functions are moved from uadk_prov_sm2.c to uadk_prov_pkey.c and change the functions name.
Signed-off-by: Weili Qian qianweili@huawei.com --- src/uadk_prov.h | 2 +- src/uadk_prov_init.c | 2 +- src/uadk_prov_pkey.c | 44 ++++++++++++++++++++++++++++++++ src/uadk_prov_pkey.h | 2 +- src/uadk_prov_sm2.c | 61 ++++++-------------------------------------- 5 files changed, 55 insertions(+), 56 deletions(-)
diff --git a/src/uadk_prov.h b/src/uadk_prov.h index ac82245..e85aff8 100644 --- a/src/uadk_prov.h +++ b/src/uadk_prov.h @@ -184,7 +184,7 @@ void uadk_prov_destroy_cipher(void); void uadk_prov_destroy_aead(void); void uadk_prov_destroy_rsa(void); void uadk_prov_destroy_dh(void); -void uadk_prov_sm2_uninit(void); +void uadk_prov_ecc_uninit(void); void uadk_prov_dh_uninit(void); int uadk_prov_cipher_version(void);
diff --git a/src/uadk_prov_init.c b/src/uadk_prov_init.c index 772ddbb..55202ae 100644 --- a/src/uadk_prov_init.c +++ b/src/uadk_prov_init.c @@ -240,7 +240,7 @@ static void uadk_teardown(void *provctx) uadk_prov_destroy_cipher(); uadk_prov_destroy_aead(); uadk_prov_destroy_rsa(); - uadk_prov_sm2_uninit(); + uadk_prov_ecc_uninit(); uadk_prov_dh_uninit(); OPENSSL_free(ctx); OSSL_PROVIDER_unload(prov); diff --git a/src/uadk_prov_pkey.c b/src/uadk_prov_pkey.c index d1f7afe..6e0612e 100644 --- a/src/uadk_prov_pkey.c +++ b/src/uadk_prov_pkey.c @@ -34,6 +34,13 @@ 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];
+struct ecc_prov { + int pid; +}; + +static struct ecc_prov g_ecc_prov; +static pthread_mutex_t ecc_mutex = PTHREAD_MUTEX_INITIALIZER; + /* Mapping between a flag and a name */ static const OSSL_ITEM encoding_nameid_map[] = { { OPENSSL_EC_EXPLICIT_CURVE, OSSL_PKEY_EC_ENCODING_EXPLICIT }, @@ -767,3 +774,40 @@ void uadk_prov_asym_cipher_alg(void) uadk_prov_asym_cipher_set_support_state(i, PROV_SUPPORT); } } + +static void uadk_prov_ecc_mutex_infork(void) +{ + /* Release the replication lock of the child process */ + pthread_mutex_unlock(&ecc_mutex); +} + +int uadk_prov_ecc_init(const char *alg_name) +{ + int ret; + + pthread_atfork(NULL, NULL, uadk_prov_ecc_mutex_infork); + pthread_mutex_lock(&ecc_mutex); + if (g_ecc_prov.pid != getpid()) { + ret = wd_ecc_init2((char *)alg_name, SCHED_POLICY_RR, TASK_HW); + if (unlikely(ret)) { + pthread_mutex_unlock(&ecc_mutex); + return UADK_P_FAIL; + } + g_ecc_prov.pid = getpid(); + async_register_poll_fn(ASYNC_TASK_ECC, uadk_prov_ecc_poll); + } + pthread_mutex_unlock(&ecc_mutex); + + return UADK_P_SUCCESS; +} + +/* Uninit only when the process exits, will not uninit when thread exits. */ +void uadk_prov_ecc_uninit(void) +{ + pthread_mutex_lock(&ecc_mutex); + if (g_ecc_prov.pid == getpid()) { + wd_ecc_uninit2(); + g_ecc_prov.pid = 0; + } + pthread_mutex_unlock(&ecc_mutex); +} diff --git a/src/uadk_prov_pkey.h b/src/uadk_prov_pkey.h index 0e27fcb..3eb9667 100644 --- a/src/uadk_prov_pkey.h +++ b/src/uadk_prov_pkey.h @@ -41,7 +41,6 @@ #define UADK_ECC_MAX_KEY_BITS 521 #define UADK_ECC_MAX_KEY_BYTES 66 #define UADK_ECC_CV_PARAM_NUM 6 -#define UADK_P_INTI_SUCCESS 0 #define UADK_P_SUCCESS 1 #define UADK_P_FAIL 0 #define UADK_P_INVALID (-1) @@ -440,5 +439,6 @@ int uadk_prov_ecc_set_public_key(handle_t sess, const EC_KEY *eckey); 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);
#endif diff --git a/src/uadk_prov_sm2.c b/src/uadk_prov_sm2.c index b6d5d01..e27cccb 100644 --- a/src/uadk_prov_sm2.c +++ b/src/uadk_prov_sm2.c @@ -36,8 +36,6 @@ UADK_PKEY_KEYMGMT_DESCR(sm2, SM2); UADK_PKEY_SIGNATURE_DESCR(sm2, SM2); UADK_PKEY_ASYM_CIPHER_DESCR(sm2, SM2);
-static pthread_mutex_t sm2_mutex = PTHREAD_MUTEX_INITIALIZER; - static const OSSL_PARAM sm2_asym_cipher_known_settable_ctx_params[] = { OSSL_PARAM_utf8_string(OSSL_ASYM_CIPHER_PARAM_DIGEST, NULL, 0), OSSL_PARAM_utf8_string(OSSL_ASYM_CIPHER_PARAM_PROPERTIES, NULL, 0), @@ -64,12 +62,6 @@ static const OSSL_PARAM sm2_sig_known_gettable_ctx_params[] = { OSSL_PARAM_END };
-struct sm2_prov { - int pid; -}; - -static struct sm2_prov g_sm2_prov; - enum { CTX_INIT_FAIL = -1, CTX_UNINIT, @@ -457,43 +449,6 @@ static const OSSL_PARAM *uadk_keymgmt_sm2_gen_settable_params(ossl_unused void * return get_default_sm2_keymgmt().gen_settable_params(genctx, provctx); }
-static void uadk_prov_sm2_mutex_infork(void) -{ - /* Release the replication lock of the child process */ - pthread_mutex_unlock(&sm2_mutex); -} - -int uadk_prov_sm2_init(void) -{ - int ret; - - pthread_atfork(NULL, NULL, uadk_prov_sm2_mutex_infork); - pthread_mutex_lock(&sm2_mutex); - if (g_sm2_prov.pid != getpid()) { - ret = wd_ecc_init2("sm2", SCHED_POLICY_RR, TASK_HW); - if (unlikely(ret)) { - pthread_mutex_unlock(&sm2_mutex); - return ret; - } - g_sm2_prov.pid = getpid(); - async_register_poll_fn(ASYNC_TASK_ECC, uadk_prov_ecc_poll); - } - pthread_mutex_unlock(&sm2_mutex); - - return UADK_P_INTI_SUCCESS; -} - -/* Uninit only when the process exits, will not uninit when thread exits. */ -void uadk_prov_sm2_uninit(void) -{ - pthread_mutex_lock(&sm2_mutex); - if (g_sm2_prov.pid == getpid()) { - wd_ecc_uninit2(); - g_sm2_prov.pid = 0; - } - pthread_mutex_unlock(&sm2_mutex); -} - static int uadk_prov_sm2_keygen_init_iot(handle_t sess, struct wd_ecc_req *req) { struct wd_ecc_out *ecc_out = wd_sm2_new_kg_out(sess); @@ -671,8 +626,8 @@ static void *uadk_keymgmt_sm2_gen(void *genctx, OSSL_CALLBACK *osslcb, void *cba }
/* SM2 hardware init */ - ret = uadk_prov_sm2_init(); - if (ret) { + ret = uadk_prov_ecc_init("sm2"); + if (ret == UADK_P_FAIL) { fprintf(stderr, "failed to init sm2\n"); goto free_ec_key; } @@ -1001,10 +956,10 @@ static int uadk_signature_sm2_sign_init(void *vpsm2ctx, void *ec, }
/* Init with UADK */ - ret = uadk_prov_sm2_init(); - if (ret) { + ret = uadk_prov_ecc_init("sm2"); + if (ret == UADK_P_FAIL) { fprintf(stderr, "failed to init sm2\n"); - return UADK_P_FAIL; + return ret; }
psm2ctx->sm2_pctx->init_status = CTX_INIT_SUCC; @@ -2408,10 +2363,10 @@ static int uadk_asym_cipher_sm2_encrypt_init(void *vpsm2ctx, void *vkey, }
/* Init with UADK */ - ret = uadk_prov_sm2_init(); - if (ret) { + ret = uadk_prov_ecc_init("sm2"); + if (ret == UADK_P_FAIL) { fprintf(stderr, "failed to init sm2\n"); - return UADK_P_FAIL; + return ret; }
smctx->init_status = CTX_INIT_SUCC;
From: Weili Qian qianweili@huawei.com
The key generation process may query the name of the algorithm supported by operation_id. If callback is not implemented, task will fail.
Signed-off-by: Weili Qian qianweili@huawei.com --- src/uadk_prov_dh.c | 8 ++++++++ src/uadk_prov_pkey.h | 3 +++ src/uadk_prov_rsa.c | 8 ++++++++ src/uadk_prov_sm2.c | 10 ++++++++++ 4 files changed, 29 insertions(+)
diff --git a/src/uadk_prov_dh.c b/src/uadk_prov_dh.c index e5c956c..8d2c6f6 100644 --- a/src/uadk_prov_dh.c +++ b/src/uadk_prov_dh.c @@ -190,6 +190,14 @@ typedef struct { char *kdf_cekalg; } PROV_DH_KEYEXCH_CTX;
+static const char *uadk_keymgmt_dh_query_operation_name(int operation_id) +{ + if (get_default_dh_keymgmt().query_operation_name == NULL) + return NULL; + + return get_default_dh_keymgmt().query_operation_name(operation_id); +} + static void *uadk_keymgmt_dh_new(void *provctx) { if (get_default_dh_keymgmt().new_fun == NULL) diff --git a/src/uadk_prov_pkey.h b/src/uadk_prov_pkey.h index 3eb9667..c9ddba1 100644 --- a/src/uadk_prov_pkey.h +++ b/src/uadk_prov_pkey.h @@ -168,6 +168,7 @@ static OSSL_FUNC_keymgmt_import_types_fn uadk_keymgmt_##nm##_import_types; \ static OSSL_FUNC_keymgmt_export_fn uadk_keymgmt_##nm##_export; \ static OSSL_FUNC_keymgmt_export_types_fn uadk_keymgmt_##nm##_export_types; \ static OSSL_FUNC_keymgmt_dup_fn uadk_keymgmt_##nm##_dup; \ +static OSSL_FUNC_keymgmt_query_operation_name_fn uadk_keymgmt_##nm##_query_operation_name; \ static UADK_PKEY_KEYMGMT get_default_##nm##_keymgmt(void) \ { \ static UADK_PKEY_KEYMGMT s_keymgmt; \ @@ -215,6 +216,8 @@ const OSSL_DISPATCH uadk_##nm##_keymgmt_functions[] = { \ { OSSL_FUNC_KEYMGMT_EXPORT, (void (*)(void))uadk_keymgmt_##nm##_export }, \ { OSSL_FUNC_KEYMGMT_EXPORT_TYPES, (void (*)(void))uadk_keymgmt_##nm##_export_types }, \ { OSSL_FUNC_KEYMGMT_DUP, (void (*)(void))uadk_keymgmt_##nm##_dup }, \ + { OSSL_FUNC_KEYMGMT_QUERY_OPERATION_NAME, \ + (void (*)(void))uadk_keymgmt_##nm##_query_operation_name }, \ { 0, NULL } \ } \
diff --git a/src/uadk_prov_rsa.c b/src/uadk_prov_rsa.c index 9872b27..d1ec153 100644 --- a/src/uadk_prov_rsa.c +++ b/src/uadk_prov_rsa.c @@ -2476,6 +2476,14 @@ static const OSSL_PARAM *uadk_asym_cipher_rsa_settable_ctx_params(void *vprsactx return get_default_rsa_asym_cipher().settable_ctx_params(vprsactx, provctx); }
+static const char *uadk_keymgmt_rsa_query_operation_name(int operation_id) +{ + if (!get_default_rsa_keymgmt().query_operation_name) + return NULL; + + return get_default_rsa_keymgmt().query_operation_name(operation_id); +} + static void *uadk_keymgmt_rsa_new(void *provctx) { if (!get_default_rsa_keymgmt().new_fun) diff --git a/src/uadk_prov_sm2.c b/src/uadk_prov_sm2.c index e27cccb..df753bd 100644 --- a/src/uadk_prov_sm2.c +++ b/src/uadk_prov_sm2.c @@ -191,6 +191,16 @@ ASN1_SEQUENCE(SM2_Ciphertext) = {
IMPLEMENT_ASN1_FUNCTIONS(SM2_Ciphertext)
+static const char *uadk_keymgmt_sm2_query_operation_name(int operation_id) +{ + if (!get_default_sm2_keymgmt().query_operation_name) { + fprintf(stderr, "failed to get keymgmt query_operation_name function\n"); + return NULL; + } + + return get_default_sm2_keymgmt().query_operation_name(operation_id); +} + /** * Create an uadk provider side sm2 key object. *
From: Weili Qian qianweili@huawei.com
Support ECDH key generation.
Signed-off-by: Weili Qian qianweili@huawei.com --- src/Makefile.am | 3 +- src/uadk_prov.h | 2 + src/uadk_prov_ec_kmgmt.c | 746 +++++++++++++++++++++++++++++++++++++++ src/uadk_prov_init.c | 2 + src/uadk_prov_pkey.c | 26 +- src/uadk_prov_pkey.h | 9 + 6 files changed, 785 insertions(+), 3 deletions(-) create mode 100644 src/uadk_prov_ec_kmgmt.c
diff --git a/src/Makefile.am b/src/Makefile.am index 921305b..b2e2c06 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -65,7 +65,8 @@ uadk_provider_la_SOURCES=uadk_prov_init.c uadk_async.c uadk_utils.c \ uadk_prov_rsa.c uadk_prov_dh.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_ffc.c uadk_prov_aead.c \ + uadk_prov_ec_kmgmt.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 e85aff8..9c310b7 100644 --- a/src/uadk_prov.h +++ b/src/uadk_prov.h @@ -179,6 +179,8 @@ extern const OSSL_DISPATCH uadk_sm2_keymgmt_functions[FUNC_MAX_NUM]; extern const OSSL_DISPATCH uadk_sm2_signature_functions[FUNC_MAX_NUM]; extern const OSSL_DISPATCH uadk_sm2_asym_cipher_functions[FUNC_MAX_NUM];
+extern const OSSL_DISPATCH uadk_ec_keymgmt_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 new file mode 100644 index 0000000..86182bd --- /dev/null +++ b/src/uadk_prov_ec_kmgmt.c @@ -0,0 +1,746 @@ +// 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/err.h> +#include <openssl/evp.h> +#include <openssl/err.h> +#include <openssl/bn.h> +#include <uadk/wd_ecc.h> +#include "uadk_async.h" +#include "uadk_prov.h" +#include "uadk_prov_pkey.h" + +#define UADK_PROV_ECC_PADDING 7 +#define UADK_PROV_RAND_MAX_CNT 1000 +#define UADK_EC_DEFAULT_FLAGS 0 +#define UADK_EC_FLAGS_ERROR (-1) + +static const OSSL_ITEM check_group_type_nameid_map[] = { + {0, OSSL_PKEY_EC_GROUP_CHECK_DEFAULT}, + {EC_FLAG_CHECK_NAMED_GROUP, OSSL_PKEY_EC_GROUP_CHECK_NAMED}, + {EC_FLAG_CHECK_NAMED_GROUP_NIST, OSSL_PKEY_EC_GROUP_CHECK_NAMED_NIST}, +}; + +UADK_PKEY_KEYMGMT_DESCR(ec, EC); + +static int ec_param_check(struct ec_gen_ctx *gctx, EC_KEY *ec) +{ + const EC_GROUP *group; + int type, ret; + + ret = uadk_prov_ecc_genctx_check(gctx, ec); + if (!ret) { + fprintf(stderr, "failed to check genctx!\n"); + return ret; + } + + group = EC_KEY_get0_group(ec); + /* Field GF(2m) is not supported by uadk */ + type = EC_METHOD_get_field_type(EC_GROUP_method_of(group)); + if (type != NID_X9_62_prime_field) { + fprintf(stderr, "invalid: uadk unsupport Field GF(2m)!\n"); + return UADK_P_FAIL; + } + + return uadk_prov_ecc_bit_check(group); +} + +static int ec_set_public_key(EC_KEY *ec, struct wd_ecc_out *ec_out) +{ + int key_size_std, key_size_x, key_size_y; + struct wd_ecc_point *pubkey = NULL; + int ret = UADK_P_FAIL; + const EC_GROUP *group; + int x_shift, y_shift; + unsigned char *buff; + EC_POINT *point; + int buff_size; + + wd_ecxdh_get_out_params(ec_out, &pubkey); + if (!pubkey) { + fprintf(stderr, "failed to get pubkey!\n"); + return ret; + } + + group = EC_KEY_get0_group(ec); + point = EC_POINT_new(group); + if (!point) { + fprintf(stderr, "failed to new ec point!\n"); + return ret; + } + + key_size_std = (unsigned int)(EC_GROUP_get_degree(group) + + UADK_PROV_ECC_PADDING) >> TRANS_BITS_BYTES_SHIFT; + key_size_x = pubkey->x.dsize; + key_size_y = pubkey->y.dsize; + if (key_size_x > key_size_std || key_size_y > key_size_std) { + fprintf(stderr, "invalid: key size is error!\n"); + goto free_point; + } + + /* + * The public key is composed as: tag + point_x + point_y + * tag - 1 byte + * point_x - [key_size_std] bytes + * point_y - [key_size_std] bytes + */ + buff_size = ECC_POINT_SIZE(key_size_std) + 1; + x_shift = key_size_std - key_size_x + 1; + y_shift = buff_size - key_size_y; + buff = (unsigned char *)OPENSSL_zalloc(buff_size); + if (!buff) { + fprintf(stderr, "failed to alloc buf, buff_size = %d!\n", + buff_size); + goto free_point; + } + + buff[0] = UADK_OCTET_STRING; + memcpy(buff + x_shift, pubkey->x.data, key_size_x); + memcpy(buff + y_shift, pubkey->y.data, key_size_y); + + ret = EC_POINT_oct2point(group, point, buff, buff_size, NULL); + if (!ret) { + fprintf(stderr, "failed to do EC_POINT_oct2point!\n"); + goto free_buf; + } + + ret = EC_KEY_set_public_key(ec, point); + if (!ret) + fprintf(stderr, "failed to do EC_KEY_set_public_key!\n"); + +free_buf: + OPENSSL_free(buff); +free_point: + EC_POINT_free(point); + + return ret; +} + +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); + if (!ret) { + fprintf(stderr, "failed to get hardware ecdh keygen support!\n"); + return ret; + } + + ret = uadk_prov_ecc_init("ecdh"); + if (!ret) { + fprintf(stderr, "failed to init ecdh!\n"); + return ret; + } + + sess = uadk_prov_ecc_alloc_sess(ec, "ecdh"); + if (!sess) { + fprintf(stderr, "failed to alloc ec sess!\n"); + return ret; + } + + *ec_out = wd_ecxdh_new_out(sess); + if (!(*ec_out)) { + fprintf(stderr, "failed to new sign out\n"); + wd_ecc_free_sess(sess); + return UADK_P_FAIL; + } + + return sess; +} + +static void ec_free_sess(handle_t sess, struct wd_ecc_out *ec_out) +{ + wd_ecc_del_out(sess, ec_out); + wd_ecc_free_sess(sess); +} + +static int ec_set_private_key(EC_KEY *ec, BIGNUM *priv_key) +{ + BIGNUM *priv_k = priv_key; + int ret = UADK_P_FAIL; + const EC_GROUP *group; + const BIGNUM *order; + int cnt = 0; + + if (priv_k) + goto set_key; + + priv_k = BN_new(); + if (!priv_k) { + fprintf(stderr, "failed to BN_new priv_k!\n"); + return UADK_P_FAIL; + } + + group = EC_KEY_get0_group(ec); + order = EC_GROUP_get0_order(group); + + do { + cnt++; + if (cnt > UADK_PROV_RAND_MAX_CNT) { + fprintf(stderr, "failed to get appropriate prikey, timeout\n"); + goto free_priv_k; + } + + if (!BN_priv_rand_range(priv_k, order)) { + fprintf(stderr, "failed to get rand data!\n"); + goto free_priv_k; + } + } while (BN_is_zero(priv_k) || BN_is_one(priv_k)); + +set_key: + ret = EC_KEY_set_private_key(ec, priv_k); + if (!ret) + fprintf(stderr, "failed to set private key!\n"); + +free_priv_k: + if (!priv_key) + BN_clear_free(priv_k); + return ret; +} + +static int ec_update_private_key(EC_KEY *ec, handle_t sess, BIGNUM *priv_key) +{ + int ret; + + ret = ec_set_private_key(ec, priv_key); + if (!ret) + return ret; + + return uadk_prov_ecc_set_private_key(sess, ec); +} + +static int ec_hw_keygen(EC_KEY *ec, BIGNUM *priv_key) +{ + struct wd_ecc_out *ec_out = NULL; + struct wd_ecc_req req = {0}; + handle_t sess; + int ret; + + sess = ec_alloc_sess(ec, &ec_out); + if (!sess) { + fprintf(stderr, "failed to alloc sess!\n"); + return UADK_P_FAIL; + } + + ret = ec_update_private_key(ec, sess, priv_key); + if (!ret) { + fprintf(stderr, "failed to update private key!\n"); + goto free_sess; + } + + uadk_prov_ecc_fill_req(&req, WD_ECXDH_GEN_KEY, NULL, ec_out); + ret = uadk_prov_ecc_crypto(sess, &req, (void *)sess); + if (!ret) { + fprintf(stderr, "failed to generate key!\n"); + goto free_sess; + } + + ret = ec_set_public_key(ec, ec_out); + +free_sess: + ec_free_sess(sess, ec_out); + return ret; +} + +static int ec_set_cofactor_mode(EC_KEY *ec, int mode) +{ + const EC_GROUP *group = EC_KEY_get0_group(ec); + const BIGNUM *cofactor; + /* + * mode can be only 0 for disable, or 1 for enable here. + * + * This is in contrast with the same parameter on an ECDH EVP_PKEY_CTX that + * also supports mode == -1 with the meaning of "reset to the default for + * the associated key". + */ + if (mode < COFACTOR_MODE_DISABLED || mode > COFACTOR_MODE_ENABLED) + return UADK_P_FAIL; + + cofactor = EC_GROUP_get0_cofactor(group); + if (!cofactor) + return UADK_P_FAIL; + + /* ECDH cofactor mode has no effect if cofactor is 1 */ + if (BN_is_one(cofactor)) + return UADK_P_SUCCESS; + + if (mode == COFACTOR_MODE_ENABLED) + EC_KEY_set_flags(ec, EC_FLAG_COFACTOR_ECDH); + else + EC_KEY_clear_flags(ec, EC_FLAG_COFACTOR_ECDH); + + return UADK_P_SUCCESS; +} + +static int ec_check_group_type_name2id(const char *name) +{ + size_t size = OSSL_NELEM(check_group_type_nameid_map); + size_t i; + + /* Return the default value if there is no name */ + if (!name) + return UADK_EC_DEFAULT_FLAGS; + + for (i = 0; i < size; i++) { + if (!OPENSSL_strcasecmp(name, check_group_type_nameid_map[i].ptr)) + return check_group_type_nameid_map[i].id; + } + + return UADK_EC_FLAGS_ERROR; +} + +static int ec_set_check_group_type(EC_KEY *ec, const char *name) +{ + int flags; + + flags = ec_check_group_type_name2id(name); + if (flags == UADK_EC_FLAGS_ERROR) + return UADK_P_FAIL; + + EC_KEY_clear_flags(ec, EC_FLAG_CHECK_NAMED_GROUP_MASK); + EC_KEY_set_flags(ec, flags); + + return UADK_P_SUCCESS; +} + +static void *uadk_keymgmt_ec_gen(void *genctx, OSSL_CALLBACK *osslcb, void *cbarg) +{ + struct ec_gen_ctx *gctx = genctx; + EC_KEY *ec; + int ret; + + if (!gctx) { + fprintf(stderr, "invalid: gctx is NULL to ec gen!\n"); + return NULL; + } + + ec = EC_KEY_new_ex(gctx->libctx, NULL); + if (!ec) { + fprintf(stderr, "failed to new ec key!\n"); + return NULL; + } + + ret = ec_param_check(genctx, ec); + if (!ret) { + fprintf(stderr, "failed to check genctx!\n"); + goto free_ec_key; + } + + /* Whether you want it or not, you get a keypair, not just one half */ + if ((gctx->selection & OSSL_KEYMGMT_SELECT_KEYPAIR) != 0) { + ret = ec_hw_keygen(ec, gctx->priv_key); + if (!ret) { + fprintf(stderr, "failed to gen public key!\n"); + goto free_ec_key; + } + } + + if (gctx->ecdh_mode != COFACTOR_MODE_USE_KEY) { + ret = ec_set_cofactor_mode(ec, gctx->ecdh_mode); + if (!ret) + goto free_ec_key; + } + + if (gctx->group_check) { + ret = ec_set_check_group_type(ec, gctx->group_check); + if (!ret) + goto free_ec_key; + } + + return ec; + +free_ec_key: + EC_KEY_free(ec); + return NULL; +} + +static void uadk_keymgmt_ec_gen_cleanup(void *genctx) +{ + struct ec_gen_ctx *gctx = genctx; + + if (!gctx) + return; + + EC_GROUP_free(gctx->gen_group); + BN_free(gctx->p); + BN_free(gctx->a); + BN_free(gctx->b); + BN_free(gctx->order); + BN_free(gctx->cofactor); + BN_clear_free(gctx->priv_key); + OPENSSL_free(gctx->group_name); + OPENSSL_free(gctx->field_type); + OPENSSL_free(gctx->pt_format); + OPENSSL_free(gctx->encoding); + OPENSSL_free(gctx->seed); + OPENSSL_free(gctx->gen); + OPENSSL_free(gctx); +} + +static void *uadk_keymgmt_ec_gen_init(void *provctx, int selection, + const OSSL_PARAM params[]) +{ + struct ec_gen_ctx *gctx; + int ret; + + if (!provctx) + return NULL; + + if (!(selection & OSSL_KEYMGMT_SELECT_ALL)) + return NULL; + + gctx = OPENSSL_zalloc(sizeof(*gctx)); + if (!gctx) + return NULL; + + gctx->libctx = prov_libctx_of(provctx); + gctx->selection = selection; + + ret = uadk_keymgmt_ec_gen_set_params(gctx, params); + if (!ret) { + OPENSSL_free(gctx); + return NULL; + } + + return gctx; +} + +static int uadk_keymgmt_ec_gen_set_template(void *genctx, void *templ) +{ + struct ec_gen_ctx *gctx = genctx; + const EC_GROUP *src_group; + EC_GROUP *dst_group; + EC_KEY *ec = templ; + + if (!gctx || !ec) { + fprintf(stderr, "invalid: genctx or templ is NULL!\n"); + return UADK_P_FAIL; + } + + src_group = EC_KEY_get0_group(ec); + if (!src_group) { + fprintf(stderr, "failed to get source group!\n"); + return UADK_P_FAIL; + } + + dst_group = EC_GROUP_dup(src_group); + if (!dst_group) { + fprintf(stderr, "failed to copy group!\n"); + return UADK_P_FAIL; + } + + EC_GROUP_free(gctx->gen_group); + gctx->gen_group = dst_group; + + return UADK_P_SUCCESS; +} + +static int ec_set_int_param(const char *key, int *val, const OSSL_PARAM params[]) +{ + const OSSL_PARAM *p; + + p = OSSL_PARAM_locate_const(params, key); + if (!p) + return UADK_P_SUCCESS; + + return OSSL_PARAM_get_int(p, val); +} + +static int ec_set_utf8_param(const char *key, char **val, const OSSL_PARAM params[]) +{ + const OSSL_PARAM *p; + + p = OSSL_PARAM_locate_const(params, key); + if (!p) + return UADK_P_SUCCESS; + + if (p->data_type != OSSL_PARAM_UTF8_STRING) + return UADK_P_FAIL; + + OPENSSL_free(*val); + *val = OPENSSL_strdup(p->data); + if (!(*val)) + return UADK_P_FAIL; + + return UADK_P_SUCCESS; +} + +static int ec_set_bn_param(const char *key, BIGNUM **val, const OSSL_PARAM params[]) +{ + const OSSL_PARAM *p; + + p = OSSL_PARAM_locate_const(params, key); + if (!p) + return UADK_P_SUCCESS; + + if (!(*val)) + *val = BN_new(); + + if (!(*val)) + return UADK_P_FAIL; + + return OSSL_PARAM_get_BN(p, val); +} + +static int ec_set_octet_param(const char *key, unsigned char **val, + size_t *val_len, const OSSL_PARAM params[]) +{ + const OSSL_PARAM *p; + + p = OSSL_PARAM_locate_const(params, key); + if (!p) + return UADK_P_SUCCESS; + + if (p->data_type != OSSL_PARAM_OCTET_STRING) + return UADK_P_FAIL; + + OPENSSL_free(*val); + *val = OPENSSL_memdup(p->data, p->data_size); + if (!(*val)) + return UADK_P_FAIL; + + *val_len = p->data_size; + + return UADK_P_SUCCESS; +} + +static int uadk_keymgmt_ec_gen_set_params(void *genctx, const OSSL_PARAM params[]) +{ + struct ec_gen_ctx *gctx = genctx; + int ret; + + if (!gctx) { + fprintf(stderr, "invalid: gctx is NULL to set params!\n"); + return UADK_P_FAIL; + } + + ret = ec_set_int_param(OSSL_PKEY_PARAM_USE_COFACTOR_ECDH, &gctx->ecdh_mode, params); + if (!ret) + return ret; + + ret = ec_set_utf8_param(OSSL_PKEY_PARAM_GROUP_NAME, &gctx->group_name, params); + if (!ret) + return ret; + + ret = ec_set_utf8_param(OSSL_PKEY_PARAM_EC_FIELD_TYPE, &gctx->field_type, params); + if (!ret) + return ret; + + ret = ec_set_utf8_param(OSSL_PKEY_PARAM_EC_ENCODING, &gctx->encoding, params); + if (!ret) + return ret; + + ret = ec_set_utf8_param(OSSL_PKEY_PARAM_EC_POINT_CONVERSION_FORMAT, + &gctx->pt_format, params); + if (!ret) + return ret; + + ret = ec_set_utf8_param(OSSL_PKEY_PARAM_EC_GROUP_CHECK_TYPE, + &gctx->group_check, params); + if (!ret) + return ret; + + ret = ec_set_bn_param(OSSL_PKEY_PARAM_EC_P, &gctx->p, params); + if (!ret) + return ret; + + ret = ec_set_bn_param(OSSL_PKEY_PARAM_EC_A, &gctx->a, params); + if (!ret) + return ret; + + ret = ec_set_bn_param(OSSL_PKEY_PARAM_EC_B, &gctx->b, params); + if (!ret) + return ret; + + ret = ec_set_bn_param(OSSL_PKEY_PARAM_EC_ORDER, &gctx->order, params); + if (!ret) + return ret; + + ret = ec_set_bn_param(OSSL_PKEY_PARAM_PRIV_KEY, &gctx->priv_key, params); + if (!ret) + return ret; + + ret = ec_set_bn_param(OSSL_PKEY_PARAM_EC_COFACTOR, &gctx->cofactor, params); + if (!ret) + return ret; + + ret = ec_set_octet_param(OSSL_PKEY_PARAM_EC_SEED, &gctx->seed, + &gctx->seed_len, params); + if (!ret) + return ret; + + return ec_set_octet_param(OSSL_PKEY_PARAM_EC_GENERATOR, + &gctx->gen, &gctx->gen_len, params); +} + +static const OSSL_PARAM *uadk_keymgmt_ec_gen_settable_params(ossl_unused void *genctx, + ossl_unused void *provctx) +{ + static OSSL_PARAM settable[] = { + OSSL_PARAM_utf8_string(OSSL_PKEY_PARAM_GROUP_NAME, NULL, 0), + OSSL_PARAM_int(OSSL_PKEY_PARAM_USE_COFACTOR_ECDH, NULL), + OSSL_PARAM_utf8_string(OSSL_PKEY_PARAM_EC_ENCODING, NULL, 0), + OSSL_PARAM_utf8_string(OSSL_PKEY_PARAM_EC_POINT_CONVERSION_FORMAT, + NULL, 0), + OSSL_PARAM_utf8_string(OSSL_PKEY_PARAM_EC_FIELD_TYPE, NULL, 0), + OSSL_PARAM_BN(OSSL_PKEY_PARAM_EC_P, NULL, 0), + OSSL_PARAM_BN(OSSL_PKEY_PARAM_EC_A, NULL, 0), + OSSL_PARAM_BN(OSSL_PKEY_PARAM_EC_B, NULL, 0), + OSSL_PARAM_octet_string(OSSL_PKEY_PARAM_EC_GENERATOR, NULL, 0), + OSSL_PARAM_BN(OSSL_PKEY_PARAM_EC_ORDER, NULL, 0), + OSSL_PARAM_BN(OSSL_PKEY_PARAM_EC_COFACTOR, NULL, 0), + OSSL_PARAM_BN(OSSL_PKEY_PARAM_PRIV_KEY, NULL, 0), + OSSL_PARAM_octet_string(OSSL_PKEY_PARAM_EC_SEED, NULL, 0), + OSSL_PARAM_END + }; + + return settable; +} + +static void *uadk_keymgmt_ec_new(void *provctx) +{ + if (!get_default_ec_keymgmt().new_fun) + return NULL; + + return get_default_ec_keymgmt().new_fun(provctx); +} + +static void uadk_keymgmt_ec_free(void *keydata) +{ + if (!get_default_ec_keymgmt().free) + return; + + return get_default_ec_keymgmt().free(keydata); +} + +static int uadk_keymgmt_ec_get_params(void *key, OSSL_PARAM params[]) +{ + if (!get_default_ec_keymgmt().get_params) + return UADK_P_FAIL; + + return get_default_ec_keymgmt().get_params(key, params); +} + +static const OSSL_PARAM *uadk_keymgmt_ec_gettable_params(void *provctx) +{ + if (!get_default_ec_keymgmt().gettable_params) + return NULL; + + return get_default_ec_keymgmt().gettable_params(provctx); +} + +static int uadk_keymgmt_ec_set_params(void *key, const OSSL_PARAM params[]) +{ + if (!get_default_ec_keymgmt().set_params) + return UADK_P_FAIL; + + return get_default_ec_keymgmt().set_params(key, params); +} + +static const OSSL_PARAM *uadk_keymgmt_ec_settable_params(void *provctx) +{ + if (!get_default_ec_keymgmt().settable_params) + return NULL; + + return get_default_ec_keymgmt().settable_params(provctx); +} + +static void *uadk_keymgmt_ec_load(const void *reference, size_t reference_sz) +{ + if (!get_default_ec_keymgmt().load) + return NULL; + + return get_default_ec_keymgmt().load(reference, reference_sz); +} + +static int uadk_keymgmt_ec_has(const void *keydata, int selection) +{ + if (!get_default_ec_keymgmt().has) + return UADK_P_FAIL; + + return get_default_ec_keymgmt().has(keydata, selection); +} + +static int uadk_keymgmt_ec_validate(const void *keydata, + int selection, int checktype) +{ + if (!get_default_ec_keymgmt().validate) + return UADK_P_FAIL; + + return get_default_ec_keymgmt().validate(keydata, selection, checktype); +} + +static int uadk_keymgmt_ec_match(const void *keydata1, + const void *keydata2, int selection) +{ + if (!get_default_ec_keymgmt().match) + return UADK_P_FAIL; + + return get_default_ec_keymgmt().match(keydata1, keydata2, selection); +} + +static int uadk_keymgmt_ec_import(void *keydata, int selection, + const OSSL_PARAM params[]) +{ + if (!get_default_ec_keymgmt().import) + return UADK_P_FAIL; + + return get_default_ec_keymgmt().import(keydata, selection, params); +} + +static const OSSL_PARAM *uadk_keymgmt_ec_import_types(int selection) +{ + if (!get_default_ec_keymgmt().import_types) + return NULL; + + return get_default_ec_keymgmt().import_types(selection); +} + +static int uadk_keymgmt_ec_export(void *keydata, int selection, + OSSL_CALLBACK *param_cb, void *cbarg) +{ + if (!get_default_ec_keymgmt().export_fun) + return UADK_P_FAIL; + + return get_default_ec_keymgmt().export_fun(keydata, selection, param_cb, cbarg); +} + +static const OSSL_PARAM *uadk_keymgmt_ec_export_types(int selection) +{ + if (!get_default_ec_keymgmt().export_types) + return NULL; + + return get_default_ec_keymgmt().export_types(selection); +} + +static void *uadk_keymgmt_ec_dup(const void *keydata_from, int selection) +{ + if (!get_default_ec_keymgmt().dup) + return NULL; + + return get_default_ec_keymgmt().dup(keydata_from, selection); +} + +static const char *uadk_keymgmt_ec_query_operation_name(int operation_id) +{ + if (!get_default_ec_keymgmt().query_operation_name) + return NULL; + + return get_default_ec_keymgmt().query_operation_name(operation_id); +} diff --git a/src/uadk_prov_init.c b/src/uadk_prov_init.c index 55202ae..b5d3df5 100644 --- a/src/uadk_prov_init.c +++ b/src/uadk_prov_init.c @@ -174,6 +174,8 @@ static const OSSL_ALGORITHM uadk_prov_keymgmt[] = { { "DH", UADK_DEFAULT_PROPERTIES, uadk_dh_keymgmt_functions }, { "SM2", UADK_DEFAULT_PROPERTIES, uadk_sm2_keymgmt_functions, "uadk SM2 Keymgmt implementation." }, + { "EC", UADK_DEFAULT_PROPERTIES, + uadk_ec_keymgmt_functions, "uadk EC Keymgmt implementation."}, { NULL, NULL, NULL } };
diff --git a/src/uadk_prov_pkey.c b/src/uadk_prov_pkey.c index 6e0612e..170c30b 100644 --- a/src/uadk_prov_pkey.c +++ b/src/uadk_prov_pkey.c @@ -628,7 +628,7 @@ int uadk_prov_ecc_genctx_check(struct ec_gen_ctx *gctx, EC_KEY *ec) return UADK_P_SUCCESS; }
-static bool uadk_prov_support_algorithm(const char *alg) +bool uadk_prov_support_algorithm(const char *alg) { struct uacce_dev_list *list = wd_get_accel_list(alg);
@@ -642,7 +642,7 @@ static bool uadk_prov_support_algorithm(const char *alg)
void uadk_prov_keymgmt_alg(void) { - static const char * const keymgmt_alg[] = {"sm2"}; + static const char * const keymgmt_alg[] = {"sm2", "ecdh"}; __u32 i, size; bool sp;
@@ -811,3 +811,25 @@ void uadk_prov_ecc_uninit(void) } pthread_mutex_unlock(&ecc_mutex); } + +int uadk_prov_ecc_bit_check(const EC_GROUP *group) +{ + int bits = EC_GROUP_order_bits(group); + + switch (bits) { + case ECC128BITS: + case ECC192BITS: + case ECC224BITS: + case ECC256BITS: + case ECC320BITS: + case ECC384BITS: + case ECC521BITS: + return UADK_P_SUCCESS; + default: + break; + } + + fprintf(stderr, "invalid: unsupport key bits %d!\n", bits); + + return UADK_P_FAIL; +} diff --git a/src/uadk_prov_pkey.h b/src/uadk_prov_pkey.h index c9ddba1..1d4911c 100644 --- a/src/uadk_prov_pkey.h +++ b/src/uadk_prov_pkey.h @@ -68,6 +68,7 @@
enum { KEYMGMT_SM2 = 0x0, + KEYMGMT_EC = 0x1, KEYMGMT_MAX = 0x6 };
@@ -76,6 +77,12 @@ enum { SIGNATURE_MAX = 0x3 };
+enum { + COFACTOR_MODE_USE_KEY = -1, + COFACTOR_MODE_DISABLED = 0, + COFACTOR_MODE_ENABLED = 1, +}; + struct curve_param { /* Prime */ BIGNUM *p; @@ -102,6 +109,7 @@ struct ec_gen_ctx { int selection; int ecdh_mode; EC_GROUP *gen_group; + BIGNUM *priv_key; };
typedef struct { @@ -443,5 +451,6 @@ 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); +int uadk_prov_ecc_bit_check(const EC_GROUP *group);
#endif
From: Weili Qian qianweili@huawei.com
Support ECDH key exchange.
Test: openssl speed -provider uadk_provider ecdhp192 openssl speed -provider uadk_provider ecdhp224 openssl speed -provider uadk_provider ecdhp256 openssl speed -provider uadk_provider ecdhp384 openssl speed -provider uadk_provider ecdhp521
Signed-off-by: Weili Qian qianweili@huawei.com --- src/Makefile.am | 2 +- src/uadk_prov.h | 1 + src/uadk_prov_ecdh_exch.c | 889 ++++++++++++++++++++++++++++++++++++++ src/uadk_prov_init.c | 9 +- src/uadk_prov_pkey.c | 68 +++ src/uadk_prov_pkey.h | 6 + 6 files changed, 971 insertions(+), 4 deletions(-) create mode 100644 src/uadk_prov_ecdh_exch.c
diff --git a/src/Makefile.am b/src/Makefile.am index b2e2c06..5a1abe7 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -66,7 +66,7 @@ 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_ec_kmgmt.c uadk_prov_ecdh_exch.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 9c310b7..7975884 100644 --- a/src/uadk_prov.h +++ b/src/uadk_prov.h @@ -180,6 +180,7 @@ extern const OSSL_DISPATCH uadk_sm2_signature_functions[FUNC_MAX_NUM]; 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];
void uadk_prov_destroy_digest(void); void uadk_prov_destroy_cipher(void); diff --git a/src/uadk_prov_ecdh_exch.c b/src/uadk_prov_ecdh_exch.c new file mode 100644 index 0000000..f549d25 --- /dev/null +++ b/src/uadk_prov_ecdh_exch.c @@ -0,0 +1,889 @@ +// 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/err.h> +#include <openssl/evp.h> +#include <openssl/err.h> +#include <openssl/bn.h> +#include <openssl/kdf.h> +#include <uadk/wd_ecc.h> +#include "uadk_async.h" +#include "uadk_prov.h" +#include "uadk_prov_der_writer.h" +#include "uadk_prov_pkey.h" + +#define UADK_PROV_MAX_PARAM_LEN 80 + +enum kdf_type { + PROV_ECDH_KDF_NONE = 0, + PROV_ECDH_KDF_X9_63 +}; + +/* + * What's passed as an actual key is defined by the KEYMGMT interface. + * We happen to know that our KEYMGMT simply passes EC_KEY structures, so + * we use that here too. + */ +struct ecdh_ctx { + OSSL_LIB_CTX *libctx; + + EC_KEY *k; + EC_KEY *peerk; + + /* + * ECDH cofactor mode: + * + * . 0 disabled + * . 1 enabled + * . -1 use cofactor mode set for k + */ + int cofactor_mode; + /* KDF (if any) to use for ECDH */ + 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; +}; + +struct ecdh_sess_ctx { + EC_KEY *privk; + const EC_POINT *pub_key; + const BIGNUM *cofactor; + const EC_GROUP *group; +}; + +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) +{ + size_t degree; + + degree = EC_GROUP_get_degree(group); + + return BITS_TO_BYTES(degree); +} + +static int ecdh_param_check(struct ecdh_ctx *pecdhctx, struct ecdh_sess_ctx *sess_ctx) +{ + const EC_GROUP *group; + int type; + + if (!pecdhctx->k || !pecdhctx->peerk) { + fprintf(stderr, "invalid: k or peerk is NULL.\n"); + return UADK_P_FAIL; + } + + sess_ctx->pub_key = EC_KEY_get0_public_key(pecdhctx->peerk); + if (!sess_ctx->pub_key) { + fprintf(stderr, "invalid: public key is NULL.\n"); + return UADK_P_FAIL; + } + + group = EC_KEY_get0_group(pecdhctx->k); + if (!group) { + fprintf(stderr, "invalid: group is 0.\n"); + return UADK_P_FAIL; + } + + sess_ctx->cofactor = EC_GROUP_get0_cofactor(group); + if (!sess_ctx->cofactor) { + fprintf(stderr, "invalid: cofactor is NULL!\n"); + return UADK_P_FAIL; + } + + /* Field GF(2m) is not supported by uadk */ + type = EC_METHOD_get_field_type(EC_GROUP_method_of(group)); + if (type != NID_X9_62_prime_field) { + fprintf(stderr, "invalid: uadk unsupport Field GF(2m)!\n"); + return UADK_P_FAIL; + } + + sess_ctx->group = group; + + return uadk_prov_ecc_bit_check(group); +} + +static int ecdh_set_privk(struct ecdh_ctx *pecdhctx, + struct ecdh_sess_ctx *sess_ctx) +{ + int key_cofactor_mode; + + /* + * The ctx->cofactor_mode flag has precedence over the + * cofactor_mode flag set on ctx->k. + * + * - if ctx->cofactor_mode == -1, use ctx->k directly + * - if ctx->cofactor_mode == key_cofactor_mode, use ctx->k directly + * - if ctx->cofactor_mode != key_cofactor_mode: + * - if ctx->k->cofactor == 1, the cofactor_mode flag is irrelevant, use + * ctx->k directly + * - if ctx->k->cofactor != 1, use a duplicate of ctx->k with the flag + * set to ctx->cofactor_mode + */ + key_cofactor_mode = (EC_KEY_get_flags(pecdhctx->k) & EC_FLAG_COFACTOR_ECDH) ? + COFACTOR_MODE_ENABLED : COFACTOR_MODE_DISABLED; + if (pecdhctx->cofactor_mode != COFACTOR_MODE_USE_KEY && + pecdhctx->cofactor_mode != key_cofactor_mode && + !BN_is_one(sess_ctx->cofactor)) { + sess_ctx->privk = EC_KEY_dup(pecdhctx->k); + if (!sess_ctx->privk) + return UADK_P_FAIL; + + if (pecdhctx->cofactor_mode == COFACTOR_MODE_ENABLED) + EC_KEY_set_flags(sess_ctx->privk, EC_FLAG_COFACTOR_ECDH); + else + EC_KEY_clear_flags(sess_ctx->privk, EC_FLAG_COFACTOR_ECDH); + } else { + sess_ctx->privk = pecdhctx->k; + } + + return UADK_P_SUCCESS; +} + +static handle_t ecdh_alloc_sess(EC_KEY *privk) +{ + int ret; + + if (!g_keyexch_ecdh_support) { + fprintf(stderr, "invalid: hardware not support ecdh!\n"); + return UADK_P_FAIL; + } + + ret = uadk_prov_ecc_init("ecdh"); + if (!ret) { + fprintf(stderr, "failed to init ecdh to compute key!\n"); + return UADK_P_FAIL; + } + + return uadk_prov_ecc_alloc_sess(privk, "ecdh"); +} + +static void ecdh_free_sess(handle_t sess) +{ + wd_ecc_free_sess(sess); +} + +static int ecdh_init_req(struct ecdh_sess_ctx *sess_ctx, + struct wd_ecc_req *req, handle_t sess) +{ + char buf_x[UADK_ECC_MAX_KEY_BYTES]; + char buf_y[UADK_ECC_MAX_KEY_BYTES]; + struct wd_ecc_point in_pkey; + struct wd_ecc_out *ecdh_out; + struct wd_ecc_in *ecdh_in; + BIGNUM *pkey_x, *pkey_y; + int ret = UADK_P_FAIL; + BN_CTX *ctx; + + ctx = BN_CTX_new(); + if (!ctx) + return -ENOMEM; + + BN_CTX_start(ctx); + pkey_x = BN_CTX_get(ctx); + if (!pkey_x) + goto free_ctx; + + pkey_y = BN_CTX_get(ctx); + if (!pkey_y) + goto free_ctx; + + uadk_prov_get_affine_coordinates(sess_ctx->group, sess_ctx->pub_key, pkey_x, pkey_y, ctx); + in_pkey.x.data = buf_x; + in_pkey.y.data = buf_y; + in_pkey.x.dsize = BN_bn2bin(pkey_x, (unsigned char *)in_pkey.x.data); + in_pkey.y.dsize = BN_bn2bin(pkey_y, (unsigned char *)in_pkey.y.data); + + /* Set public key */ + ecdh_in = wd_ecxdh_new_in(sess, &in_pkey); + if (!ecdh_in) { + fprintf(stderr, "failed to new ecxdh in\n"); + goto free_ctx; + } + + ecdh_out = wd_ecxdh_new_out(sess); + if (!ecdh_out) { + fprintf(stderr, "failed to new ecxdh out\n"); + wd_ecc_del_in(sess, ecdh_in); + goto free_ctx; + } + + uadk_prov_ecc_fill_req(req, WD_ECXDH_COMPUTE_KEY, ecdh_in, ecdh_out); + + ret = UADK_P_SUCCESS; + +free_ctx: + BN_CTX_end(ctx); + BN_CTX_free(ctx); + + return ret; +} + +static void ecdh_uninit_req(struct wd_ecc_req *req, handle_t sess) +{ + wd_ecc_del_in(sess, req->src); + wd_ecc_del_out(sess, req->dst); +} + +static int ecdh_get_shared_key(unsigned char *secret, + size_t size, size_t *psecretlen, + struct wd_ecc_req *req) +{ + struct wd_ecc_point *shared_key = NULL; + + wd_ecxdh_get_out_params(req->dst, &shared_key); + if (!shared_key) { + fprintf(stderr, "failed to get ecdh shared key\n"); + return UADK_P_FAIL; + } + + size = size < shared_key->x.dsize ? size : shared_key->x.dsize; + *psecretlen = size; + + memcpy(secret, (unsigned char *)shared_key->x.data, size); + + return UADK_P_SUCCESS; +} + +static int ecdh_compute_key(struct ecdh_sess_ctx *sess_ctx, + unsigned char *secret, + size_t *psecretlen, size_t size) +{ + struct wd_ecc_req req = {0}; + handle_t sess; + int ret; + + sess = ecdh_alloc_sess(sess_ctx->privk); + if (!sess) { + fprintf(stderr, "failed to alloc sess to compute key!\n"); + return UADK_P_FAIL; + } + + ret = uadk_prov_ecc_set_private_key(sess, sess_ctx->privk); + if (!ret) { + fprintf(stderr, "failed to set private key!\n"); + goto free_sess; + } + + ret = ecdh_init_req(sess_ctx, &req, sess); + if (!ret) { + fprintf(stderr, "failed to init req!\n"); + goto free_sess; + } + + ret = uadk_prov_ecc_crypto(sess, &req, (void *)sess); + if (!ret) { + fprintf(stderr, "failed to calculate shared key!\n"); + goto uninit_req; + } + + ret = ecdh_get_shared_key(secret, size, psecretlen, &req); + +uninit_req: + ecdh_uninit_req(&req, sess); +free_sess: + ecdh_free_sess(sess); + return ret; +} + +static int ecdh_plain_derive(struct ecdh_ctx *pecdhctx, + unsigned char *secret, + size_t *psecretlen, size_t outlen) +{ + struct ecdh_sess_ctx sess_ctx = {0}; + size_t size, ec_size; + int ret; + + ret = ecdh_param_check(pecdhctx, &sess_ctx); + if (!ret) + return ret; + + ec_size = ecdh_get_ec_size(sess_ctx.group); + if (!secret) { + *psecretlen = ec_size; + return UADK_P_SUCCESS; + } + + ret = ecdh_set_privk(pecdhctx, &sess_ctx); + if (!ret) { + fprintf(stderr, "failed to set private key!\n"); + return ret; + } + + size = outlen < ec_size ? outlen : ec_size; + ret = ecdh_compute_key(&sess_ctx, secret, psecretlen, size); + if (sess_ctx.privk != pecdhctx->k) + EC_KEY_free(sess_ctx.privk); + + return ret; +} + +/* Key derivation function from X9.63/SECG */ +static int ecdh_kdf_X9_63(unsigned char *out, struct ecdh_ctx *pecdhctx, + unsigned char *stmp, size_t stmplen) +{ + EVP_KDF *kdf = EVP_KDF_fetch(pecdhctx->libctx, OSSL_KDF_NAME_X963KDF, NULL); + const char *mdname = EVP_MD_get0_name(pecdhctx->kdf_md); + OSSL_PARAM params[4], *p = params; + int ret = UADK_P_FAIL; + EVP_KDF_CTX *kctx; + + if (!kdf) { + fprintf(stderr, "failed to fetch kdf!\n"); + return ret; + } + + kctx = EVP_KDF_CTX_new(kdf); + if (!kctx) { + fprintf(stderr, "failed to new kctx!\n"); + goto free_kdf; + } + + *p++ = OSSL_PARAM_construct_utf8_string(OSSL_KDF_PARAM_DIGEST, (char *)mdname, 0); + *p++ = OSSL_PARAM_construct_octet_string(OSSL_KDF_PARAM_KEY, (void *)stmp, stmplen); + *p++ = OSSL_PARAM_construct_octet_string(OSSL_KDF_PARAM_INFO, + (void *)pecdhctx->kdf_ukm, pecdhctx->kdf_ukmlen); + *p = OSSL_PARAM_construct_end(); + + ret = EVP_KDF_derive(kctx, out, pecdhctx->kdf_outlen, params); + ret = ret <= 0 ? UADK_P_FAIL : UADK_P_SUCCESS; + + EVP_KDF_CTX_free(kctx); + +free_kdf: + EVP_KDF_free(kdf); + + return ret; +} + +static int ecdh_X9_63_kdf_derive(struct ecdh_ctx *pecdhctx, unsigned char *secret, + size_t *psecretlen, size_t outlen) +{ + unsigned char *stmp; + size_t stmplen = 0; + int ret; + + if (!secret) { + *psecretlen = pecdhctx->kdf_outlen; + return UADK_P_SUCCESS; + } + + if (outlen < pecdhctx->kdf_outlen) { + fprintf(stderr, "invalid: outlen %lu is less than kdf_outlen %lu!\n", + outlen, pecdhctx->kdf_outlen); + return UADK_P_FAIL; + } + + ret = ecdh_plain_derive(pecdhctx, NULL, &stmplen, 0); + if (!ret) + return ret; + + stmp = OPENSSL_secure_malloc(stmplen); + if (!stmp) { + fprintf(stderr, "failed to alloc stmp!\n"); + return UADK_P_FAIL; + } + + ret = ecdh_plain_derive(pecdhctx, stmp, &stmplen, stmplen); + if (!ret) + goto free_stmp; + + ret = ecdh_kdf_X9_63(secret, pecdhctx, stmp, stmplen); + if (!ret) + goto free_stmp; + + *psecretlen = pecdhctx->kdf_outlen; + + free_stmp: + OPENSSL_secure_clear_free(stmp, stmplen); + return ret; +} + +static int uadk_keyexch_ecdh_derive(void *vpecdhctx, unsigned char *secret, + size_t *psecretlen, size_t outlen) +{ + struct ecdh_ctx *pecdhctx = vpecdhctx; + + if (!pecdhctx) { + fprintf(stderr, "invalid: vpecdhctx is NULL to derive!\n"); + return UADK_P_FAIL; + } + + switch (pecdhctx->kdf_type) { + case PROV_ECDH_KDF_NONE: + return ecdh_plain_derive(pecdhctx, secret, psecretlen, outlen); + case PROV_ECDH_KDF_X9_63: + return ecdh_X9_63_kdf_derive(pecdhctx, secret, psecretlen, outlen); + default: + break; + } + + return UADK_P_FAIL; +} + +static void *uadk_keyexch_ecdh_newctx(void *provctx) +{ + struct ecdh_ctx *pectx; + + pectx = OPENSSL_zalloc(sizeof(*pectx)); + if (!pectx) + return NULL; + + pectx->libctx = prov_libctx_of(provctx); + pectx->cofactor_mode = COFACTOR_MODE_USE_KEY; + pectx->kdf_type = PROV_ECDH_KDF_NONE; + + return pectx; +} + +static void uadk_keyexch_ecdh_freectx(void *vpecdhctx) +{ + struct ecdh_ctx *pecdhctx = vpecdhctx; + + if (!pecdhctx) + return; + + EC_KEY_free(pecdhctx->k); + EC_KEY_free(pecdhctx->peerk); + EVP_MD_free(pecdhctx->kdf_md); + OPENSSL_clear_free(pecdhctx->kdf_ukm, pecdhctx->kdf_ukmlen); + OPENSSL_free(pecdhctx); +} + +static int uadk_keyexch_ecdh_init(void *vpecdhctx, void *vecdh, const OSSL_PARAM params[]) +{ + struct ecdh_ctx *pecdhctx = vpecdhctx; + int ret; + + if (!pecdhctx || !vecdh) { + fprintf(stderr, "invalid: pecdhctx or vecdh is to init!\n"); + return UADK_P_FAIL; + } + + if (!EC_KEY_up_ref(vecdh)) + return UADK_P_FAIL; + + EC_KEY_free(pecdhctx->k); + pecdhctx->k = vecdh; + pecdhctx->cofactor_mode = COFACTOR_MODE_USE_KEY; + pecdhctx->kdf_type = PROV_ECDH_KDF_NONE; + + ret = uadk_keyexch_ecdh_set_ctx_params(pecdhctx, params); + if (!ret) { + fprintf(stderr, "failed to set_ctx_params!\n"); + return ret; + } + + return uadk_prov_ecc_check_key(pecdhctx->libctx, vecdh, 1); +} + +static int ecdh_match_params(const EC_KEY *privk, const EC_KEY *pubk) +{ + const EC_GROUP *group_privk = EC_KEY_get0_group(privk); + const EC_GROUP *group_pubk = EC_KEY_get0_group(pubk); + int ret = UADK_P_SUCCESS; + BN_CTX *ctx; + + ctx = BN_CTX_new_ex(privk->libctx); + if (!ctx) { + fprintf(stderr, "failed to new ctx!\n"); + return UADK_P_FAIL; + } + + if (group_privk && group_pubk) { + if (EC_GROUP_cmp(group_privk, group_pubk, ctx)) { + fprintf(stderr, "invalid: privk is not match pubk!\n"); + ret = UADK_P_FAIL; + } + } + + BN_CTX_free(ctx); + + return ret; +} + +static int uadk_keyexch_ecdh_set_peer(void *vpecdhctx, void *vecdh) +{ + struct ecdh_ctx *pecdhctx = vpecdhctx; + int ret; + + if (!pecdhctx || !vecdh) { + fprintf(stderr, "invalid: vpecdhctx or vecdh is NULL to set_peer!\n"); + return UADK_P_FAIL; + } + + ret = ecdh_match_params(pecdhctx->k, vecdh); + if (!ret) + return ret; + + ret = uadk_prov_ecc_check_key(pecdhctx->libctx, vecdh, 1); + if (!ret) + return ret; + + if (!EC_KEY_up_ref(vecdh)) + return UADK_P_FAIL; + + EC_KEY_free(pecdhctx->peerk); + pecdhctx->peerk = vecdh; + + return UADK_P_SUCCESS; +} + +static void *uadk_keyexch_ecdh_dupctx(void *vpecdhctx) +{ + struct ecdh_ctx *srcctx = vpecdhctx; + struct ecdh_ctx *dstctx; + + if (!srcctx) { + fprintf(stderr, "invalid: source ecdh ctx is NULL!\n"); + return NULL; + } + + dstctx = OPENSSL_zalloc(sizeof(*srcctx)); + if (!dstctx) { + fprintf(stderr, "failed to alloc dst ctx!\n"); + return NULL; + } + + memcpy(dstctx, srcctx, sizeof(*dstctx)); + + dstctx->k = NULL; + dstctx->peerk = NULL; + dstctx->kdf_md = NULL; + dstctx->kdf_ukm = NULL; + + /* up-ref all ref-counted objects referenced in dstctx */ + if (srcctx->k && !EC_KEY_up_ref(srcctx->k)) + goto err; + else + dstctx->k = srcctx->k; + + if (srcctx->peerk && !EC_KEY_up_ref(srcctx->peerk)) + goto err; + else + dstctx->peerk = srcctx->peerk; + + if (srcctx->kdf_md && !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 && srcctx->kdf_ukmlen > 0) { + dstctx->kdf_ukm = OPENSSL_memdup(srcctx->kdf_ukm, + srcctx->kdf_ukmlen); + if (!dstctx->kdf_ukm) + goto err; + } + + return dstctx; + +err: + uadk_keyexch_ecdh_freectx(dstctx); + return NULL; +} + +static int ecdh_set_cofactor_mode(struct ecdh_ctx *pectx, const OSSL_PARAM params[]) +{ + const OSSL_PARAM *p; + int mode, ret; + + p = OSSL_PARAM_locate_const(params, OSSL_EXCHANGE_PARAM_EC_ECDH_COFACTOR_MODE); + if (!p) + return UADK_P_SUCCESS; + + ret = OSSL_PARAM_get_int(p, &mode); + if (!ret) + return UADK_P_FAIL; + + if (mode < COFACTOR_MODE_USE_KEY || mode > COFACTOR_MODE_ENABLED) + return UADK_P_FAIL; + + pectx->cofactor_mode = mode; + + return UADK_P_SUCCESS; +} + +static int ecdh_get_cofactor_mode(struct ecdh_ctx *pectx, OSSL_PARAM params[]) +{ + int mode = pectx->cofactor_mode; + OSSL_PARAM *p; + + p = OSSL_PARAM_locate(params, OSSL_EXCHANGE_PARAM_EC_ECDH_COFACTOR_MODE); + if (!p) + return UADK_P_SUCCESS; + + if (mode == COFACTOR_MODE_USE_KEY) + /* Check what is the default for pecdhctx->k */ + mode = EC_KEY_get_flags(pectx->k) & EC_FLAG_COFACTOR_ECDH ? + COFACTOR_MODE_ENABLED : COFACTOR_MODE_DISABLED; + + return OSSL_PARAM_set_int(p, mode); +} + +static int ecdh_set_kdf_type(struct ecdh_ctx *pectx, const OSSL_PARAM params[]) +{ + char name[UADK_PROV_MAX_PARAM_LEN] = {'\0'}; + const OSSL_PARAM *p; + char *str = name; + int ret; + + p = OSSL_PARAM_locate_const(params, OSSL_EXCHANGE_PARAM_KDF_TYPE); + if (!p) + return UADK_P_SUCCESS; + + ret = OSSL_PARAM_get_utf8_string(p, &str, sizeof(name)); + if (!ret) + return UADK_P_FAIL; + + if (name[0] == '\0') + pectx->kdf_type = PROV_ECDH_KDF_NONE; + else if (!strcmp(name, OSSL_KDF_NAME_X963KDF)) + pectx->kdf_type = PROV_ECDH_KDF_X9_63; + else + return UADK_P_FAIL; + + return UADK_P_SUCCESS; +} + +static int ecdh_get_kdf_type(struct ecdh_ctx *pectx, OSSL_PARAM params[]) +{ + const char *kdf_type; + OSSL_PARAM *p; + + p = OSSL_PARAM_locate(params, OSSL_EXCHANGE_PARAM_KDF_TYPE); + if (!p) + return UADK_P_SUCCESS; + + switch (pectx->kdf_type) { + case PROV_ECDH_KDF_NONE: + kdf_type = ""; + break; + case PROV_ECDH_KDF_X9_63: + kdf_type = OSSL_KDF_NAME_X963KDF; + break; + default: + return UADK_P_FAIL; + } + + return OSSL_PARAM_set_utf8_string(p, kdf_type); +} + +static int ecdh_set_kdf_digest(struct ecdh_ctx *pectx, const OSSL_PARAM params[]) +{ + char mdprops[UADK_PROV_MAX_PARAM_LEN] = {'\0'}; + char name[UADK_PROV_MAX_PARAM_LEN] = {'\0'}; + const OSSL_PARAM *p; + char *str = name; + int ret; + + p = OSSL_PARAM_locate_const(params, OSSL_EXCHANGE_PARAM_KDF_DIGEST); + if (!p) + return UADK_P_SUCCESS; + + ret = OSSL_PARAM_get_utf8_string(p, &str, sizeof(name)); + if (!ret) + return UADK_P_FAIL; + + p = OSSL_PARAM_locate_const(params, OSSL_EXCHANGE_PARAM_KDF_DIGEST_PROPS); + if (p) { + str = mdprops; + ret = OSSL_PARAM_get_utf8_string(p, &str, sizeof(mdprops)); + if (!ret) + return UADK_P_FAIL; + } + + EVP_MD_free(pectx->kdf_md); + pectx->kdf_md = EVP_MD_fetch(pectx->libctx, name, mdprops); + if (!pectx->kdf_md) + return UADK_P_FAIL; + + return UADK_P_SUCCESS; +} + +static int ecdh_get_kdf_digest(struct ecdh_ctx *pectx, OSSL_PARAM params[]) +{ + OSSL_PARAM *p; + + p = OSSL_PARAM_locate(params, OSSL_EXCHANGE_PARAM_KDF_DIGEST); + if (!p) + return UADK_P_SUCCESS; + + if (!pectx->kdf_md) + return OSSL_PARAM_set_utf8_string(p, ""); + + return OSSL_PARAM_set_utf8_string(p, EVP_MD_get0_name(pectx->kdf_md)); +} + +static int ecdh_set_kdf_outlen(struct ecdh_ctx *pectx, const OSSL_PARAM params[]) +{ + const OSSL_PARAM *p; + + p = OSSL_PARAM_locate_const(params, OSSL_EXCHANGE_PARAM_KDF_OUTLEN); + if (!p) + return UADK_P_SUCCESS; + + return OSSL_PARAM_get_size_t(p, &pectx->kdf_outlen); +} + +static int ecdh_get_kdf_outlen(struct ecdh_ctx *pectx, OSSL_PARAM params[]) +{ + OSSL_PARAM *p; + + p = OSSL_PARAM_locate(params, OSSL_EXCHANGE_PARAM_KDF_OUTLEN); + if (!p) + return UADK_P_SUCCESS; + + return OSSL_PARAM_set_size_t(p, pectx->kdf_outlen); +} + +static int ecdh_set_kdf_ukm(struct ecdh_ctx *pectx, const OSSL_PARAM params[]) +{ + const OSSL_PARAM *p; + void *tmp_ukm = NULL; + size_t tmp_ukmlen; + int ret; + + p = OSSL_PARAM_locate_const(params, OSSL_EXCHANGE_PARAM_KDF_UKM); + if (!p) + return UADK_P_SUCCESS; + + ret = OSSL_PARAM_get_octet_string(p, &tmp_ukm, 0, &tmp_ukmlen); + if (!ret) + return ret; + + OPENSSL_free(pectx->kdf_ukm); + pectx->kdf_ukm = tmp_ukm; + pectx->kdf_ukmlen = tmp_ukmlen; + + return UADK_P_SUCCESS; +} + +static int ecdh_get_kdf_ukm(struct ecdh_ctx *pectx, OSSL_PARAM params[]) +{ + OSSL_PARAM *p; + + p = OSSL_PARAM_locate(params, OSSL_EXCHANGE_PARAM_KDF_UKM); + if (!p) + return UADK_P_SUCCESS; + + return OSSL_PARAM_set_octet_ptr(p, pectx->kdf_ukm, pectx->kdf_ukmlen); +} + +static int uadk_keyexch_ecdh_set_ctx_params(void *vpecdhctx, const OSSL_PARAM params[]) +{ + struct ecdh_ctx *pectx = (struct ecdh_ctx *)vpecdhctx; + int ret; + + if (!pectx) { + fprintf(stderr, "invalid: pectx is NULL to set_ctx_params!\n"); + return UADK_P_FAIL; + } + + if (!params) + return UADK_P_SUCCESS; + + ret = ecdh_set_cofactor_mode(pectx, params); + if (!ret) + return ret; + + ret = ecdh_set_kdf_type(pectx, params); + if (!ret) + return ret; + + ret = ecdh_set_kdf_digest(pectx, params); + if (!ret) + return ret; + + ret = ecdh_set_kdf_outlen(pectx, params); + if (!ret) + return ret; + + return ecdh_set_kdf_ukm(pectx, params); +} + +static int uadk_keyexch_ecdh_get_ctx_params(void *vpecdhctx, OSSL_PARAM params[]) +{ + struct ecdh_ctx *pectx = vpecdhctx; + int ret; + + if (!pectx) { + fprintf(stderr, "invalid: pectx is NULL to get_ctx_params!\n"); + return UADK_P_FAIL; + } + + ret = ecdh_get_cofactor_mode(pectx, params); + if (!ret) + return ret; + + ret = ecdh_get_kdf_type(pectx, params); + if (!ret) + return ret; + + ret = ecdh_get_kdf_digest(pectx, params); + if (!ret) + return ret; + + ret = ecdh_get_kdf_outlen(pectx, params); + if (!ret) + return ret; + + return ecdh_get_kdf_ukm(pectx, params); +} + +static const OSSL_PARAM *uadk_keyexch_ecdh_settable_ctx_params(ossl_unused void *vpecdhctx, + ossl_unused void *provctx) +{ + static const OSSL_PARAM known_settable_ctx_params[] = { + OSSL_PARAM_int(OSSL_EXCHANGE_PARAM_EC_ECDH_COFACTOR_MODE, 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_END + }; + + return known_settable_ctx_params; +} + +static const OSSL_PARAM *uadk_keyexch_ecdh_gettable_ctx_params(ossl_unused void *vpecdhctx, + ossl_unused void *provctx) +{ + static const OSSL_PARAM known_gettable_ctx_params[] = { + OSSL_PARAM_int(OSSL_EXCHANGE_PARAM_EC_ECDH_COFACTOR_MODE, 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_size_t(OSSL_EXCHANGE_PARAM_KDF_OUTLEN, NULL), + OSSL_PARAM_DEFN(OSSL_EXCHANGE_PARAM_KDF_UKM, OSSL_PARAM_OCTET_PTR, + NULL, 0), + OSSL_PARAM_END + }; + + return known_gettable_ctx_params; +} diff --git a/src/uadk_prov_init.c b/src/uadk_prov_init.c index b5d3df5..42e1272 100644 --- a/src/uadk_prov_init.c +++ b/src/uadk_prov_init.c @@ -190,6 +190,8 @@ static const OSSL_ALGORITHM uadk_prov_asym_cipher[] = { static const OSSL_ALGORITHM uadk_prov_keyexch[] = { { "DH", UADK_DEFAULT_PROPERTIES, uadk_dh_keyexch_functions, "UADK DH keyexch implementation"}, + { "ECDH", UADK_DEFAULT_PROPERTIES, + uadk_ecdh_keyexch_functions, "uadk_provider ecdh_keyexch" }, { NULL, NULL, NULL } };
@@ -218,15 +220,16 @@ static const OSSL_ALGORITHM *uadk_query(void *provctx, int operation_id, return uadk_prov_ciphers_v3; return uadk_prov_ciphers_v2; case OSSL_OP_SIGNATURE: - (void)uadk_prov_signature_alg(); + uadk_prov_signature_alg(); return uadk_prov_signature; case OSSL_OP_KEYMGMT: - (void)uadk_prov_keymgmt_alg(); + uadk_prov_keymgmt_alg(); return uadk_prov_keymgmt; case OSSL_OP_ASYM_CIPHER: - (void)uadk_prov_asym_cipher_alg(); + uadk_prov_asym_cipher_alg(); return uadk_prov_asym_cipher; case OSSL_OP_KEYEXCH: + uadk_prov_keyexch_alg(); return uadk_prov_keyexch; case OSSL_OP_STORE: return prov->query_operation(provctx, operation_id, no_cache); diff --git a/src/uadk_prov_pkey.c b/src/uadk_prov_pkey.c index 170c30b..a861551 100644 --- a/src/uadk_prov_pkey.c +++ b/src/uadk_prov_pkey.c @@ -29,6 +29,9 @@ #define PROV_SUPPORT 1 #define SIGNATURE_TYPE 3 #define ASYM_CIPHER_TYPE 3 +#define SECURITY_CHECK_DISABLE 0 +#define UADK_PROV_MIN_BITS 112 +#define UADK_PROV_SECURITY_BITS 80
static int p_keymgmt_support_state[KEYMGMT_TYPE]; static int p_signature_support_state[SIGNATURE_TYPE]; @@ -833,3 +836,68 @@ int uadk_prov_ecc_bit_check(const EC_GROUP *group)
return UADK_P_FAIL; } + +/* Currently, disable the security checks in the default provider and uadk provider */ +int uadk_prov_securitycheck_enabled(OSSL_LIB_CTX *ctx) +{ + return SECURITY_CHECK_DISABLE; +} + +#ifdef OPENSSL_NO_FIPS_SECURITYCHECKS +int uadk_prov_ecc_check_key(OSSL_LIB_CTX *ctx, const EC_KEY *ec, int protect) +{ + return UADK_P_SUCCESS; +} +#else +int uadk_prov_ecc_check_key(OSSL_LIB_CTX *ctx, const EC_KEY *ec, int protect) +{ + const EC_GROUP *group = EC_KEY_get0_group(ec); + const char *curve_name; + int nid, strength; + + if (!uadk_prov_securitycheck_enabled(ctx)) + return UADK_P_SUCCESS; + + if (!group) { + fprintf(stderr, "invalid: group is NULL!\n"); + return UADK_P_FAIL; + } + + nid = EC_GROUP_get_curve_name(group); + if (nid == NID_undef) { + fprintf(stderr, "invalid: explicit curves are not allowed in fips mode!\n"); + return UADK_P_FAIL; + } + + curve_name = EC_curve_nid2nist(nid); + if (!curve_name) { + fprintf(stderr, "invalid: Curve %s is not approved in FIPS mode!\n", + curve_name); + return UADK_P_FAIL; + } + + /* + * For EC the security strength is the (order_bits / 2) + * e.g. P-224 is 112 bits. + */ + strength = (unsigned int)EC_GROUP_order_bits(group) >> 1; + /* The min security strength allowed for legacy verification is 80 bits */ + if (strength < UADK_PROV_SECURITY_BITS) { + fprintf(stderr, "invalid: Curve %s strength %d is not approved in FIPS mode!\n", + curve_name, strength); + return UADK_P_FAIL; + } + + /* + * For signing or key agreement only allow curves with at least 112 bits of + * security strength + */ + if (protect && strength < UADK_PROV_MIN_BITS) { + fprintf(stderr, "invalid: Curve %s strength %d cannot be used for signing\n", + curve_name, strength); + return UADK_P_FAIL; + } + + return UADK_P_SUCCESS; +} +#endif /* OPENSSL_NO_FIPS_SECURITYCHECKS */ diff --git a/src/uadk_prov_pkey.h b/src/uadk_prov_pkey.h index 1d4911c..fbec388 100644 --- a/src/uadk_prov_pkey.h +++ b/src/uadk_prov_pkey.h @@ -452,5 +452,11 @@ 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); 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);
#endif
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);
From: lizhi lizhi206@huawei.com
1. Wformat, solve format dismatch 2. Wdiffarded qualifiers, const pointer lost const qualifier 3. Wmissing prototypes, use static to limit scope of internal function 4. Wunused, unused functions and variables 5. Wswitch, add default branch and break to switch 6. Redundant decls, duplicate declarations in macro definitions
Signed-off-by: lizhi lizhi206@huawei.com --- src/Makefile.am | 16 ++++++++++++++++ src/uadk_aead.c | 2 +- src/uadk_prov_bio.c | 2 ++ src/uadk_prov_cipher.c | 6 +++--- src/uadk_prov_der_writer.c | 2 +- src/uadk_prov_dh.c | 9 +++++---- src/uadk_prov_digest.c | 18 +++++++++--------- src/uadk_prov_ecx.c | 34 +++------------------------------- src/uadk_prov_ffc.c | 24 ++++++++++++------------ src/uadk_prov_ffc.h | 1 - src/uadk_prov_pkey.c | 8 ++++---- src/uadk_prov_pkey.h | 2 +- 12 files changed, 57 insertions(+), 67 deletions(-)
diff --git a/src/Makefile.am b/src/Makefile.am index a165d3a..20f20c5 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -24,6 +24,14 @@ uadk_engine_la_CFLAGS=$(WD_CFLAGS) $(libcrypto_CFLAGS) uadk_engine_la_CFLAGS+=-DCRYPTO uadk_engine_la_CFLAGS+=-fPIC -fPIE -pie -fstack-protector-strong -D_FORTIFY_SOURCE=2 \ -O2 -ftrapv -Wl,-z,relro,-z,now -Wl,-s +uadk_engine_la_CFLAGS += -Wall -Wuninitialized -Wno-error -Wno-error=format -Wundef \ +-Wunused -Wdate-time -Wfloat-equal -Wshadow -Wvla -Wdisabled-optimization \ +-Wempty-body -Wignored-qualifiers -Wimplicit-fallthrough=3 -Wtype-limits \ +-Wshift-negative-value -Wswitch-default -Wframe-larger-than=8192 -Wshift-overflow=2 \ +-Wwrite-strings -Wmissing-format-attribute -Wformat-nonliteral -Wduplicated-cond \ +-Wtrampolines -Wlogical-op -Wsuggest-attribute=format -Wduplicated-branches \ +-Wmissing-include-dirs -Wformat-signedness -Wmissing-declarations -Wreturn-local-addr \ +-Wredundant-decls -Wfloat-conversion -Wmissing-prototypes -Wstrict-prototypes if WD_ENGINE uadk_engine_la_CFLAGS+=-DOPENSSL_SUPPRESS_DEPRECATED endif #WD_ENGINE @@ -73,3 +81,11 @@ uadk_provider_la_LDFLAGS=-module -version-number $(VERSION) uadk_provider_la_LIBADD=$(WD_LIBS) -lpthread uadk_provider_la_CFLAGS=$(WD_CFLAGS) $(libcrypto_CFLAGS) uadk_provider_la_CFLAGS+=-DOPENSSL_SUPPRESS_DEPRECATED +uadk_provider_la_CFLAGS+=-Wall -Wuninitialized -Wno-error -Wno-error=format -Wundef \ +-Wunused -Wdate-time -Wfloat-equal -Wshadow -Wvla -Wdisabled-optimization \ +-Wempty-body -Wignored-qualifiers -Wimplicit-fallthrough=3 -Wtype-limits \ +-Wshift-negative-value -Wswitch-default -Wframe-larger-than=8192 -Wshift-overflow=2 \ +-Wwrite-strings -Wmissing-format-attribute -Wformat-nonliteral -Wduplicated-cond \ +-Wtrampolines -Wlogical-op -Wsuggest-attribute=format -Wduplicated-branches \ +-Wmissing-include-dirs -Wformat-signedness -Wmissing-declarations -Wreturn-local-addr \ +-Wredundant-decls -Wfloat-conversion -Wmissing-prototypes -Wstrict-prototypes \ No newline at end of file diff --git a/src/uadk_aead.c b/src/uadk_aead.c index 1da7753..23f4329 100644 --- a/src/uadk_aead.c +++ b/src/uadk_aead.c @@ -469,7 +469,7 @@ static int do_aead_sync_inner(struct aead_priv_ctx *priv, unsigned char *out, priv->req.state = 0; ret = wd_do_aead_sync(priv->sess, &priv->req); if (unlikely(ret < 0 || priv->req.state)) { - fprintf(stderr, "do aead task failed, msg state: %d, ret: %d, state: %u!\n", + fprintf(stderr, "do aead task failed, msg state: %u, ret: %d, state: %u!\n", state, ret, priv->req.state); return RET_FAIL; } diff --git a/src/uadk_prov_bio.c b/src/uadk_prov_bio.c index 5be3e8a..d419a6a 100644 --- a/src/uadk_prov_bio.c +++ b/src/uadk_prov_bio.c @@ -71,6 +71,8 @@ void ossl_prov_bio_from_dispatch(const OSSL_DISPATCH *fns) if (c_bio_vprintf == NULL) c_bio_vprintf = OSSL_FUNC_BIO_vprintf(fns); break; + default: + break; } fns++; } diff --git a/src/uadk_prov_cipher.c b/src/uadk_prov_cipher.c index e511b71..c098115 100644 --- a/src/uadk_prov_cipher.c +++ b/src/uadk_prov_cipher.c @@ -124,7 +124,7 @@ struct cipher_priv_ctx { unsigned int pad : 1; /* Whether padding should be used or not */ unsigned int cts_mode; /* Use to set the type for CTS modes */ unsigned int key_set : 1; /* Whether key is copied to priv key buffers */ - unsigned int iv_set : 1; /* Whether key is copied to priv iv buffers */ + unsigned int iv_set : 1; /* Whether iv is copied to priv iv buffers */ size_t blksize; size_t keylen; size_t ivlen; @@ -180,7 +180,7 @@ static struct cts_mode_name2id_st cts_modes[] = { { WD_CIPHER_CBC_CS3, OSSL_CIPHER_CTS_MODE_CS3, UADK_CIPHER_CTS_CS3_NAME }, };
-const char *ossl_cipher_cbc_cts_mode_id2name(unsigned int id) +static const char *ossl_cipher_cbc_cts_mode_id2name(unsigned int id) { size_t i;
@@ -191,7 +191,7 @@ const char *ossl_cipher_cbc_cts_mode_id2name(unsigned int id) return NULL; }
-int ossl_cipher_cbc_cts_mode_name2id(const char *name) +static int ossl_cipher_cbc_cts_mode_name2id(const char *name) { size_t i;
diff --git a/src/uadk_prov_der_writer.c b/src/uadk_prov_der_writer.c index 3876d49..e7e7e49 100644 --- a/src/uadk_prov_der_writer.c +++ b/src/uadk_prov_der_writer.c @@ -139,7 +139,7 @@ int ossl_DER_w_uint32(WPACKET *pkt, int tag, uint32_t v) return int_der_w_integer(pkt, tag, int_put_bytes_uint32, &v); }
-BN_ULONG *bn_get_words(const BIGNUM *a) +static BN_ULONG *bn_get_words(const BIGNUM *a) { return a->d; } diff --git a/src/uadk_prov_dh.c b/src/uadk_prov_dh.c index 8d2c6f6..f3724ac 100644 --- a/src/uadk_prov_dh.c +++ b/src/uadk_prov_dh.c @@ -1629,7 +1629,7 @@ static int uadk_prov_dh_plain_derive(PROV_DH_KEYEXCH_CTX *pdhctx, unsigned char else ret = uadk_dh_compute_key(secret, pubkey, pdhctx->dh); if (ret <= 0) { - fprintf(stderr, "failed to do dh compute, pad(%d)\n", pad); + fprintf(stderr, "failed to do dh compute, pad(%u)\n", pad); return ret; }
@@ -1639,9 +1639,9 @@ static int uadk_prov_dh_plain_derive(PROV_DH_KEYEXCH_CTX *pdhctx, unsigned char }
/* Key derivation function from X9.63/SECG */ -int ossl_dh_kdf_X9_42_asn1(unsigned char *out, PROV_DH_KEYEXCH_CTX *pdhctx, - const unsigned char *z, size_t z_len, - const char *propq) +static int ossl_dh_kdf_X9_42_asn1(unsigned char *out, PROV_DH_KEYEXCH_CTX *pdhctx, + const unsigned char *z, size_t z_len, + const char *propq) { OSSL_LIB_CTX *libctx = pdhctx->libctx; const char *cek_alg = pdhctx->kdf_cekalg; @@ -1749,6 +1749,7 @@ static int uadk_keyexch_dh_derive(void *dhctx, unsigned char *secret, break; case PROV_DH_KDF_X9_42_ASN1: ret = uadk_prov_dh_X9_42_kdf_derive(pdhctx, secret, psecretlen, outlen); + break; default: fprintf(stderr, "invalid: unsupport kdf type\n"); break; diff --git a/src/uadk_prov_digest.c b/src/uadk_prov_digest.c index 0fe31d2..8c539ed 100644 --- a/src/uadk_prov_digest.c +++ b/src/uadk_prov_digest.c @@ -629,6 +629,15 @@ static void uadk_digest_cleanup(struct digest_priv_ctx *priv) OPENSSL_free(priv->soft_ctx); }
+static OSSL_FUNC_digest_freectx_fn uadk_prov_freectx; +static OSSL_FUNC_digest_dupctx_fn uadk_prov_dupctx; +static OSSL_FUNC_digest_init_fn uadk_prov_init; +static OSSL_FUNC_digest_update_fn uadk_prov_update; +static OSSL_FUNC_digest_final_fn uadk_prov_final; +static OSSL_FUNC_digest_digest_fn uadk_prov_digest; +static OSSL_FUNC_digest_gettable_params_fn + uadk_prov_gettable_params; + /* some params related code is copied from OpenSSL v3.0 prov/digestcommon.h */ static const OSSL_PARAM uadk_digest_default_known_gettable_params[] = { OSSL_PARAM_size_t(OSSL_DIGEST_PARAM_BLOCK_SIZE, NULL), @@ -791,15 +800,6 @@ void uadk_prov_destroy_digest(void) pthread_mutex_unlock(&digest_mutex); }
-static OSSL_FUNC_digest_freectx_fn uadk_prov_freectx; -static OSSL_FUNC_digest_dupctx_fn uadk_prov_dupctx; -static OSSL_FUNC_digest_init_fn uadk_prov_init; -static OSSL_FUNC_digest_update_fn uadk_prov_update; -static OSSL_FUNC_digest_final_fn uadk_prov_final; -static OSSL_FUNC_digest_digest_fn uadk_prov_digest; -static OSSL_FUNC_digest_gettable_params_fn - uadk_prov_gettable_params; - #define UADK_PROVIDER_IMPLEMENTATION(name, nid, mdsize, blksize) \ static OSSL_FUNC_digest_newctx_fn uadk_##name##_newctx; \ static void *uadk_##name##_newctx(void *provctx) \ diff --git a/src/uadk_prov_ecx.c b/src/uadk_prov_ecx.c index 302dc48..d7954b7 100644 --- a/src/uadk_prov_ecx.c +++ b/src/uadk_prov_ecx.c @@ -88,12 +88,6 @@ typedef struct { 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; @@ -258,23 +252,6 @@ static int ossl_param_build_set_octet_string(OSSL_PARAM_BLD *bld, OSSL_PARAM *p, 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) { @@ -430,9 +407,6 @@ static void uadk_keymgmt_x448_gen_cleanup(void *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; @@ -441,8 +415,8 @@ static void *uadk_keymgmt_x448_gen_init(void *provctx, int selection, 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) +static 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));
@@ -807,7 +781,6 @@ static UADK_PKEY_KEYEXCH get_default_x448_keyexch(void) 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) { @@ -870,7 +843,6 @@ static int uadk_keyexch_x448_init(void *vecxctx, void *vkey, { 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"); @@ -894,7 +866,7 @@ static int uadk_keyexch_x448_init(void *vecxctx, void *vkey, return UADK_P_SUCCESS; }
-int ossl_ecx_key_up_ref(ECX_KEY *key) +static int ossl_ecx_key_up_ref(ECX_KEY *key) { int i = 0;
diff --git a/src/uadk_prov_ffc.c b/src/uadk_prov_ffc.c index ed5e037..015c1b9 100644 --- a/src/uadk_prov_ffc.c +++ b/src/uadk_prov_ffc.c @@ -937,7 +937,7 @@ err: return ret; }
-OSSL_LIB_CTX *ossl_bn_get_libctx(BN_CTX *ctx) +static OSSL_LIB_CTX *ossl_bn_get_libctx(BN_CTX *ctx) { if (ctx == NULL) return NULL; @@ -1064,9 +1064,9 @@ static int ffc_validate_LN(size_t L, size_t N, int type, int verify) } #endif /* FIPS_MODULE */
-int ossl_ffc_params_set_validate_params(FFC_PARAMS *params, - const unsigned char *seed, - size_t seedlen, int counter) +static int ossl_ffc_params_set_validate_params(FFC_PARAMS *params, + const unsigned char *seed, + size_t seedlen, int counter) { if (!ossl_ffc_params_set_seed(params, seed, seedlen)) return 0; @@ -1086,10 +1086,10 @@ static const char *default_mdname(size_t N) }
/* FIPS186-4 A.2.2 Unverifiable partial validation of Generator g */ -int ossl_ffc_params_validate_unverifiable_g(BN_CTX *ctx, BN_MONT_CTX *mont, - const BIGNUM *p, const BIGNUM *q, - const BIGNUM *g, BIGNUM *tmp, - int *ret) +static int ossl_ffc_params_validate_unverifiable_g(BN_CTX *ctx, BN_MONT_CTX *mont, + const BIGNUM *p, const BIGNUM *q, + const BIGNUM *g, BIGNUM *tmp, + int *ret) { /* * A.2.2 Step (1) AND @@ -1574,10 +1574,10 @@ static int generate_canonical_g(BN_CTX *ctx, BN_MONT_CTX *mont, * - FFC_PARAM_RET_STATUS_UNVERIFIABLE_G if the validation of G succeeded, * but G is unverifiable. */ -int ossl_ffc_params_FIPS186_4_gen_verify(OSSL_LIB_CTX *libctx, - FFC_PARAMS *params, int mode, int type, - size_t L, size_t N, int *res, - BN_GENCB *cb) +static int ossl_ffc_params_FIPS186_4_gen_verify(OSSL_LIB_CTX *libctx, + FFC_PARAMS *params, int mode, + int type, size_t L, size_t N, + int *res, BN_GENCB *cb) { int ok = FFC_PARAM_RET_STATUS_FAILED; unsigned char *seed = NULL, *seed_tmp = NULL; diff --git a/src/uadk_prov_ffc.h b/src/uadk_prov_ffc.h index 92102d3..d63a5ce 100644 --- a/src/uadk_prov_ffc.h +++ b/src/uadk_prov_ffc.h @@ -99,7 +99,6 @@ #define OSSL_NELEM(x) (sizeof(x)/sizeof((x)[0])) /* Macro to make a BIGNUM from static data */ #define make_dh_bn(x) \ - extern const BIGNUM ossl_bignum_##x; \ const BIGNUM ossl_bignum_##x = { \ (BN_ULONG *) x, \ OSSL_NELEM(x), \ diff --git a/src/uadk_prov_pkey.c b/src/uadk_prov_pkey.c index 0615b61..244cdb4 100644 --- a/src/uadk_prov_pkey.c +++ b/src/uadk_prov_pkey.c @@ -178,7 +178,7 @@ static void uadk_prov_init_dtb_param(void *dtb, char *start, }
int uadk_prov_get_affine_coordinates(const EC_GROUP *group, const EC_POINT *p, - BIGNUM *x, BIGNUM *y, BN_CTX *ctx) + BIGNUM *x, BIGNUM *y, BN_CTX *ctx) { # if OPENSSL_VERSION_NUMBER > 0x10101000L if (!EC_POINT_get_affine_coordinates(group, p, x, y, ctx)) @@ -190,8 +190,8 @@ int uadk_prov_get_affine_coordinates(const EC_GROUP *group, const EC_POINT *p, return UADK_P_SUCCESS; }
-int uadk_prov_get_curve(const EC_GROUP *group, BIGNUM *p, BIGNUM *a, - BIGNUM *b, BN_CTX *ctx) +static int uadk_prov_get_curve(const EC_GROUP *group, BIGNUM *p, BIGNUM *a, + BIGNUM *b, BN_CTX *ctx) { # if OPENSSL_VERSION_NUMBER > 0x10101000L if (!EC_GROUP_get_curve(group, p, a, b, ctx)) @@ -293,7 +293,7 @@ free_ctx: return ret; }
-handle_t uadk_prov_ecc_alloc_sess(const EC_KEY *eckey, char *alg) +handle_t uadk_prov_ecc_alloc_sess(const EC_KEY *eckey, const char *alg) { char buff[UADK_ECC_MAX_KEY_BYTES * UADK_ECC_CV_PARAM_NUM]; struct sched_params sch_p = {0}; diff --git a/src/uadk_prov_pkey.h b/src/uadk_prov_pkey.h index e79fc52..f40313d 100644 --- a/src/uadk_prov_pkey.h +++ b/src/uadk_prov_pkey.h @@ -439,7 +439,7 @@ const OSSL_DISPATCH uadk_##nm##_keyexch_functions[] = { \ { 0, NULL } \ } \
-handle_t uadk_prov_ecc_alloc_sess(const EC_KEY *eckey, char *alg); +handle_t uadk_prov_ecc_alloc_sess(const EC_KEY *eckey, const char *alg); int uadk_prov_ecc_crypto(handle_t sess, struct wd_ecc_req *req, void *usr); int uadk_prov_keymgmt_get_support_state(int alg_tag); int uadk_prov_ecc_get_numa_id(void);
Cleanup variable definition and return value, make the function clearer.
Signed-off-by: Qi Tao taoqi10@huawei.com --- src/uadk_prov_rsa.c | 318 ++++++++++++++++++++++---------------------- 1 file changed, 159 insertions(+), 159 deletions(-)
diff --git a/src/uadk_prov_rsa.c b/src/uadk_prov_rsa.c index d1ec153..eac4e46 100644 --- a/src/uadk_prov_rsa.c +++ b/src/uadk_prov_rsa.c @@ -32,17 +32,17 @@
#define UN_SET 0 #define IS_SET 1 +#define RSA_MAX_PRIME_NUM 2 #define BIT_BYTES_SHIFT 3 #define RSA_MIN_MODULUS_BITS 512 -#define RSA_MAX_PRIME_NUM 2 #define RSA1024BITS 1024 #define RSA2048BITS 2048 #define RSA3072BITS 3072 #define RSA4096BITS 4096 #define OPENSSLRSA7680BITS 7680 #define OPENSSLRSA15360BITS 15360 -#define CTX_ASYNC 1 #define CTX_SYNC 0 +#define CTX_ASYNC 1 #define CTX_NUM 2 #define BN_CONTINUE 1 #define BN_VALID 0 @@ -50,11 +50,11 @@ #define BN_REDO (-2) #define GET_ERR_FINISH 0 #define UNUSED(x) ((void)(x)) -#define UADK_E_SUCCESS 1 #define UADK_E_FAIL 0 +#define UADK_E_SUCCESS 1 #define UADK_DO_SOFT (-0xE0) -#define UADK_E_POLL_SUCCESS 0 #define UADK_E_POLL_FAIL (-1) +#define UADK_E_POLL_SUCCESS 0 #define UADK_E_INIT_SUCCESS 0 #define CHECK_PADDING_FAIL (-1) #define ENV_ENABLED 1 @@ -67,15 +67,6 @@ UADK_PKEY_KEYMGMT_DESCR(rsa, RSA); UADK_PKEY_SIGNATURE_DESCR(rsa, RSA); UADK_PKEY_ASYM_CIPHER_DESCR(rsa, RSA); - -struct bignum_st { - BN_ULONG *d; - int top; - int dmax; - int neg; - int flags; -}; - struct rsa_keypair { struct wd_rsa_pubkey *pubkey; struct wd_rsa_prikey *prikey; @@ -87,17 +78,20 @@ struct rsa_keygen_param { struct wd_dtb *wd_q; };
+struct bignum_st { + BN_ULONG *d; + int top; + int dmax; + int neg; + int flags; +}; + struct rsa_keygen_param_bn { BIGNUM *e; BIGNUM *p; BIGNUM *q; };
-struct rsa_pubkey_param { - const BIGNUM *e; - const BIGNUM *n; -}; - struct rsa_prikey_param { const BIGNUM *n; const BIGNUM *e; @@ -118,6 +112,16 @@ struct rsa_prime_param { BIGNUM *prime; };
+struct rsa_pubkey_param { + const BIGNUM *e; + const BIGNUM *n; +}; + +struct rsa_sched { + int sched_type; + struct wd_sched wd_sched; +}; + struct uadk_rsa_sess { handle_t sess; struct wd_rsa_sess_setup setup; @@ -128,11 +132,6 @@ struct uadk_rsa_sess { int key_size; };
-struct rsa_sched { - int sched_type; - struct wd_sched wd_sched; -}; - struct rsa_prov { int pid; }; @@ -506,11 +505,10 @@ static void free_tbuf(PROV_RSA_SIG_CTX *ctx)
static int rsa_check_bit_useful(const int bits, int flen) { - if (flen > (bits >> BIT_BYTES_SHIFT)) - return UADK_DO_SOFT; - if (bits < RSA_MIN_MODULUS_BITS) return UADK_E_FAIL; + if (flen > (bits >> BIT_BYTES_SHIFT)) + return UADK_DO_SOFT;
switch (bits) { case RSA1024BITS: @@ -554,6 +552,7 @@ static int check_rsa_prime_sufficient(int *num, const int *bitsr, ret = rsa_prime_mul_res(*num, param, ctx, cb); if (ret) return ret; + /* * If |r1|, product of factors so far, is not as long as expected * (by checking the first 4 bits are less than 0x9 or greater than @@ -572,10 +571,10 @@ static int check_rsa_prime_sufficient(int *num, const int *bitsr, return BN_ERR;
bitst = BN_get_word(param->r2); - if (bitst < 0x9 || bitst > 0xF) { + if (bitst > 0xF || bitst < 0x9) { /* - * For keys with more than 4 primes, we attempt longer factor to - * meet length requirement. + * For keys with more than 4 primes, we attempt longer factor + * to meet length requirement. * Otherwise, we just re-generate the prime with the same length. * This strategy has the following goals: * 1. 1024-bit factors are efficient when using 3072 and 4096-bit key @@ -586,15 +585,14 @@ static int check_rsa_prime_sufficient(int *num, const int *bitsr, else return BN_ERR;
- ret = BN_GENCB_call(cb, GENCB_NEXT, *n); - (*n)++; + ret = BN_GENCB_call(cb, GENCB_NEXT, (*n)++); if (!ret) return BN_ERR;
if (retries == PRIME_RETRY_COUNT) { - *num = -1; - *bitse = 0; retries = 0; + *bitse = 0; + *num = -1; return BN_CONTINUE; } retries++; @@ -616,6 +614,7 @@ static void rsa_set_primes(int num, BIGNUM *rsa_p, BIGNUM *rsa_q, *prime = rsa_p; else *prime = rsa_q; + /* Set BN_FLG_CONSTTIME to prime exponent */ BN_set_flags(*prime, BN_FLG_CONSTTIME); } @@ -624,18 +623,19 @@ static int check_rsa_prime_equal(int num, BIGNUM *rsa_p, BIGNUM *rsa_q, BIGNUM *prime) { BIGNUM *prev_prime; - int j; + int k;
- for (j = 0; j < num; j++) { + for (k = 0; k < num; k++) { prev_prime = NULL; - if (j == 0) + if (k == 0) prev_prime = rsa_p; else prev_prime = rsa_q; + /* - * BN_cmp(a,b) returns -1 if a < b; - * returns 0 if a == b; - * returns 1 if a > b. + * BN_cmp(a,b) return -1 if a < b; + * return 0 if a == b; + * return 1 if a > b. */ if (!BN_cmp(prime, prev_prime)) return UADK_E_FAIL; @@ -660,10 +660,11 @@ static int check_rsa_prime_useful(int * const n, struct rsa_prime_param *param, return BN_ERR; ERR_set_mark(); BN_set_flags(param->r2, BN_FLG_CONSTTIME); + /* * BN_mod_inverse(r, a, n, ctx) used to compute inverse modulo n. - * Precisely, it computes the inverse of "a" modulo "n", and places - * the result in "r", which means (a * r) % n == 1. + * Precisely, it computes the inverse of a modulo n, and places + * the result in r, which means (a * r) % n == 1. * If r == NULL, error. If r != NULL, success. * The expected result: (r2 * r1) % e_pub == 1, * the inverse of r2 exist, that is r1. @@ -678,8 +679,7 @@ static int check_rsa_prime_useful(int * const n, struct rsa_prime_param *param, else return BN_ERR;
- ret = BN_GENCB_call(cb, GENCB_NEXT, *n); - (*n)++; + ret = BN_GENCB_call(cb, GENCB_NEXT, (*n)++); if (!ret) return BN_ERR;
@@ -694,6 +694,7 @@ static int get_rsa_prime_once(int num, const int *bitsr, int * const n,
if (num >= RSA_MAX_PRIME_NUM) return ret; + while (1) { /* Generate prime with bitsr[num] len. */ if (!BN_generate_prime_ex(param->prime, bitsr[num], @@ -702,6 +703,7 @@ static int get_rsa_prime_once(int num, const int *bitsr, int * const n, if (!check_rsa_prime_equal(num, param->rsa_p, param->rsa_q, param->prime)) continue; + ret = check_rsa_prime_useful(n, param, e_pub, ctx, cb); if (ret == BN_ERR) return BN_ERR; @@ -722,8 +724,8 @@ static void rsa_switch_p_q(BIGNUM *rsa_p, BIGNUM *rsa_q, BIGNUM *p, BIGNUM *q) rsa_q = tmp; }
- BN_copy(q, rsa_q); BN_copy(p, rsa_p); + BN_copy(q, rsa_q); }
static int check_rsa_is_crt(RSA *rsa) @@ -755,23 +757,23 @@ static int get_rsa_prime_param(struct rsa_prime_param *param, BN_CTX *ctx) { param->r1 = BN_CTX_get(ctx); if (!param->r1) - goto end; + goto error;
param->r2 = BN_CTX_get(ctx); if (!param->r2) - goto end; - - param->rsa_p = BN_CTX_get(ctx); - if (!param->rsa_p) - goto end; + goto error;
param->rsa_q = BN_CTX_get(ctx); if (!param->rsa_q) - goto end; + goto error; + + param->rsa_p = BN_CTX_get(ctx); + if (!param->rsa_p) + goto error;
return UADK_E_SUCCESS;
-end: +error: fprintf(stderr, "failed to allocate rsa prime params\n"); return -ENOMEM; } @@ -781,31 +783,31 @@ static int rsa_primes_gen(int bits, BIGNUM *e_pub, BIGNUM *p, { struct rsa_prime_param *param = NULL; int bitsr[RSA_MAX_PRIME_NUM] = {0}; - int flag, quo, rmd, i; - BN_CTX *ctx; + int flag, quot, rmd, i; + BN_CTX *bnctx; int bitse = 0; int ret = 0; /* n: modulo n, a part of public key */ int n = 0;
- ctx = BN_CTX_new(); - if (!ctx) + bnctx = BN_CTX_new(); + if (!bnctx) return ret;
- BN_CTX_start(ctx); + BN_CTX_start(bnctx); param = OPENSSL_zalloc(sizeof(struct rsa_prime_param)); if (!param) goto free_ctx;
- ret = get_rsa_prime_param(param, ctx); + ret = get_rsa_prime_param(param, bnctx); if (ret != UADK_E_SUCCESS) goto free_param;
/* Divide bits into 'primes' pieces evenly */ - quo = bits / RSA_MAX_PRIME_NUM; + quot = bits / RSA_MAX_PRIME_NUM; rmd = bits % RSA_MAX_PRIME_NUM; for (i = 0; i < RSA_MAX_PRIME_NUM; i++) - bitsr[i] = (i < rmd) ? quo + 1 : quo; + bitsr[i] = (i < rmd) ? quot + 1 : quot;
/* Generate p, q and other primes (if any) */ for (i = 0; i < RSA_MAX_PRIME_NUM; i++) { @@ -815,12 +817,12 @@ static int rsa_primes_gen(int bits, BIGNUM *e_pub, BIGNUM *p, rsa_set_primes(i, param->rsa_p, param->rsa_q, ¶m->prime); while (flag == 1) { ret = get_rsa_prime_once(i, bitsr, &n, e_pub, param, - ctx, cb); + bnctx, cb); if (ret == -1) goto free_param; bitse += bitsr[i]; ret = check_rsa_prime_sufficient(&i, bitsr, &bitse, &n, - param, ctx, cb); + param, bnctx, cb); if (ret == BN_ERR) goto free_param; else if (ret == BN_REDO) @@ -836,8 +838,8 @@ static int rsa_primes_gen(int bits, BIGNUM *e_pub, BIGNUM *p, free_param: OPENSSL_free(param); free_ctx: - BN_CTX_end(ctx); - BN_CTX_free(ctx); + BN_CTX_end(bnctx); + BN_CTX_free(bnctx); return ret; }
@@ -847,7 +849,7 @@ static int add_rsa_pubenc_padding(int flen, const unsigned char *from, int ret;
if (!buf || !num) { - fprintf(stderr, "buf or num is invalid\n"); + fprintf(stderr, "buf or num is invalid.\n"); return UADK_E_FAIL; }
@@ -855,12 +857,12 @@ static int add_rsa_pubenc_padding(int flen, const unsigned char *from, case RSA_PKCS1_PADDING: ret = RSA_padding_add_PKCS1_type_2(buf, num, from, flen); if (!ret) - fprintf(stderr, "RSA_PKCS1_PADDING err\n"); + fprintf(stderr, "RSA_PKCS1_PADDING err.\n"); break; case RSA_PKCS1_OAEP_PADDING: ret = RSA_padding_add_PKCS1_OAEP(buf, num, from, flen, NULL, 0); if (!ret) - fprintf(stderr, "RSA_PKCS1_OAEP_PADDING err\n"); + fprintf(stderr, "RSA_PKCS1_OAEP_PADDING err.\n"); break; default: ret = UADK_E_FAIL; @@ -879,13 +881,13 @@ static int check_rsa_pridec_padding(unsigned char *to, int num, case RSA_PKCS1_PADDING: ret = RSA_padding_check_PKCS1_type_2(to, num, buf, flen, num); if (ret == CHECK_PADDING_FAIL) - fprintf(stderr, "RSA_PKCS1_PADDING err\n"); + fprintf(stderr, "RSA_PKCS1_PADDING err.\n"); break; case RSA_PKCS1_OAEP_PADDING: ret = RSA_padding_check_PKCS1_OAEP(to, num, buf, flen, num, NULL, 0); if (ret == CHECK_PADDING_FAIL) - fprintf(stderr, "RSA_PKCS1_OAEP_PADDING err\n"); + fprintf(stderr, "RSA_PKCS1_OAEP_PADDING err.\n"); break; default: ret = UADK_E_FAIL; @@ -907,12 +909,12 @@ static int add_rsa_prienc_padding(int flen, const unsigned char *from, case RSA_PKCS1_PADDING: ret = RSA_padding_add_PKCS1_type_1(to_buf, tlen, from, flen); if (!ret) - fprintf(stderr, "RSA_PKCS1_PADDING err\n"); + fprintf(stderr, "RSA_PKCS1_PADDING err.\n"); break; case RSA_X931_PADDING: ret = RSA_padding_add_X931(to_buf, tlen, from, flen); if (ret == -1) - fprintf(stderr, "RSA_X931_PADDING err\n"); + fprintf(stderr, "RSA_X931_PADDING err.\n"); break; default: ret = UADK_E_FAIL; @@ -933,12 +935,12 @@ static int check_rsa_pubdec_padding(unsigned char *to, int num, case RSA_PKCS1_PADDING: ret = RSA_padding_check_PKCS1_type_1(to, num, buf, len, num); if (ret == CHECK_PADDING_FAIL) - fprintf(stderr, "RSA_PKCS1_PADDING err\n"); + fprintf(stderr, "RSA_PKCS1_PADDING err.\n"); break; case RSA_X931_PADDING: ret = RSA_padding_check_X931(to, num, buf, len, num); if (ret == CHECK_PADDING_FAIL) - fprintf(stderr, "RSA_X931_PADDING err\n"); + fprintf(stderr, "RSA_X931_PADDING err.\n"); break; default: ret = UADK_E_FAIL; @@ -950,10 +952,15 @@ static int check_rsa_pubdec_padding(unsigned char *to, int num, return ret; }
+static BN_ULONG *bn_get_words(const BIGNUM *a) +{ + return a->d; +} + static int check_rsa_input_para(const int flen, const unsigned char *from, unsigned char *to, RSA *rsa) { - if (!rsa || !from || !to || flen <= 0) { + if (!rsa || !to || !from || flen <= 0) { fprintf(stderr, "input param invalid\n"); return UADK_E_FAIL; } @@ -961,11 +968,6 @@ static int check_rsa_input_para(const int flen, const unsigned char *from, return rsa_check_bit_useful(uadk_rsa_bits(rsa), flen); }
-static BN_ULONG *bn_get_words(const BIGNUM *a) -{ - return a->d; -} - static int rsa_get_sign_res(int padding, BIGNUM *to_bn, const BIGNUM *n, BIGNUM *ret_bn, BIGNUM **res) { @@ -1053,8 +1055,8 @@ static struct uadk_rsa_sess *rsa_new_eng_session(RSA *rsa)
memset(rsa_sess, 0, sizeof(struct uadk_rsa_sess)); rsa_sess->alg = rsa; - rsa_sess->is_prikey_ready = UN_SET; rsa_sess->is_pubkey_ready = UN_SET; + rsa_sess->is_prikey_ready = UN_SET;
return rsa_sess; } @@ -1065,8 +1067,8 @@ static void rsa_free_eng_session(struct uadk_rsa_sess *rsa_sess) return;
rsa_sess->alg = NULL; - rsa_sess->is_prikey_ready = UN_SET; rsa_sess->is_pubkey_ready = UN_SET; + rsa_sess->is_prikey_ready = UN_SET;
wd_rsa_free_sess(rsa_sess->sess); OPENSSL_free(rsa_sess); @@ -1079,7 +1081,7 @@ static struct uadk_rsa_sess *rsa_get_eng_session(RSA *rsa, unsigned int bits, struct sched_params params = {0}; struct uadk_rsa_sess *rsa_sess;
- rsa_sess = rsa_new_eng_session(rsa); + rsa_sess = rsa_new_eng_session(rsa); if (!rsa_sess) return NULL;
@@ -1105,8 +1107,8 @@ static int rsa_fill_pubkey(struct rsa_pubkey_param *pubkey_param, unsigned char *in_buf, unsigned char *to) { struct wd_rsa_pubkey *pubkey = NULL; - struct wd_dtb *wd_e = NULL; struct wd_dtb *wd_n = NULL; + struct wd_dtb *wd_e = NULL;
if (!rsa_sess->is_pubkey_ready) { wd_rsa_get_pubkey(rsa_sess->sess, &pubkey); @@ -1114,17 +1116,17 @@ static int rsa_fill_pubkey(struct rsa_pubkey_param *pubkey_param, return UADK_E_FAIL;
wd_rsa_get_pubkey_params(pubkey, &wd_e, &wd_n); - if (!wd_e || !wd_n) + if (!wd_n || !wd_e) return UADK_E_FAIL;
- wd_e->dsize = BN_bn2bin(pubkey_param->e, - (unsigned char *)wd_e->data); wd_n->dsize = BN_bn2bin(pubkey_param->n, (unsigned char *)wd_n->data); - rsa_sess->is_pubkey_ready = IS_SET; + wd_e->dsize = BN_bn2bin(pubkey_param->e, + (unsigned char *)wd_e->data); rsa_sess->req.src_bytes = rsa_sess->key_size; rsa_sess->req.dst_bytes = rsa_sess->key_size; rsa_sess->req.op_type = WD_RSA_VERIFY; + rsa_sess->is_pubkey_ready = IS_SET; rsa_sess->req.src = in_buf; rsa_sess->req.dst = to;
@@ -1140,12 +1142,12 @@ static int rsa_fill_prikey(RSA *rsa, struct uadk_rsa_sess *rsa_sess, { struct wd_rsa_prikey *prikey = NULL; struct wd_dtb *wd_qinv = NULL; - struct wd_dtb *wd_dq = NULL; struct wd_dtb *wd_dp = NULL; - struct wd_dtb *wd_q = NULL; + struct wd_dtb *wd_dq = NULL; struct wd_dtb *wd_p = NULL; - struct wd_dtb *wd_d = NULL; + struct wd_dtb *wd_q = NULL; struct wd_dtb *wd_n = NULL; + struct wd_dtb *wd_d = NULL;
if (!(rsa_sess->is_prikey_ready) && (pri->is_crt)) { wd_rsa_get_prikey(rsa_sess->sess, &prikey); @@ -1157,14 +1159,14 @@ static int rsa_fill_prikey(RSA *rsa, struct uadk_rsa_sess *rsa_sess, if (!wd_dq || !wd_dp || !wd_qinv || !wd_q || !wd_p) return UADK_E_FAIL;
- wd_dq->dsize = BN_bn2bin(pri->dmq1, - (unsigned char *)wd_dq->data); wd_dp->dsize = BN_bn2bin(pri->dmp1, (unsigned char *)wd_dp->data); - wd_q->dsize = BN_bn2bin(pri->q, - (unsigned char *)wd_q->data); + wd_dq->dsize = BN_bn2bin(pri->dmq1, + (unsigned char *)wd_dq->data); wd_p->dsize = BN_bn2bin(pri->p, (unsigned char *)wd_p->data); + wd_q->dsize = BN_bn2bin(pri->q, + (unsigned char *)wd_q->data); wd_qinv->dsize = BN_bn2bin(pri->iqmp, (unsigned char *)wd_qinv->data); } else if (!(rsa_sess->is_prikey_ready) && !(pri->is_crt)) { @@ -1176,16 +1178,17 @@ static int rsa_fill_prikey(RSA *rsa, struct uadk_rsa_sess *rsa_sess, if (!wd_d || !wd_n) return UADK_E_FAIL;
- wd_d->dsize = BN_bn2bin(pri->d, - (unsigned char *)wd_d->data); wd_n->dsize = BN_bn2bin(pri->n, (unsigned char *)wd_n->data); + wd_d->dsize = BN_bn2bin(pri->d, + (unsigned char *)wd_d->data); } else { return UADK_E_FAIL; } + rsa_sess->is_prikey_ready = IS_SET; - rsa_sess->req.src_bytes = rsa_sess->key_size; rsa_sess->req.op_type = WD_RSA_SIGN; + rsa_sess->req.src_bytes = rsa_sess->key_size; rsa_sess->req.dst_bytes = rsa_sess->key_size; rsa_sess->req.src = in_buf; rsa_sess->req.dst = to; @@ -1198,7 +1201,7 @@ static int rsa_get_keygen_param(struct wd_rsa_req *req, handle_t ctx, RSA *rsa, { struct wd_rsa_kg_out *out = (struct wd_rsa_kg_out *)req->dst; struct wd_dtb wd_d, wd_n, wd_qinv, wd_dq, wd_dp; - BIGNUM *dmp1, *dmq1, *iqmp, *n, *d; + BIGNUM *dmp1, *dmq1, *iqmp, *d, *n; unsigned int key_bits, key_size; BN_CTX *bn_ctx = *bn_ctx_in;
@@ -1210,14 +1213,14 @@ static int rsa_get_keygen_param(struct wd_rsa_req *req, handle_t ctx, RSA *rsa, wd_rsa_get_kg_out_params(out, &wd_d, &wd_n); wd_rsa_get_kg_out_crt_params(out, &wd_qinv, &wd_dq, &wd_dp);
- dmp1 = BN_CTX_get(bn_ctx); - if (!dmp1) - return UADK_E_FAIL; - dmq1 = BN_CTX_get(bn_ctx); if (!dmq1) return UADK_E_FAIL;
+ dmp1 = BN_CTX_get(bn_ctx); + if (!dmp1) + return UADK_E_FAIL; + iqmp = BN_CTX_get(bn_ctx); if (!iqmp) return UADK_E_FAIL; @@ -1230,8 +1233,8 @@ static int rsa_get_keygen_param(struct wd_rsa_req *req, handle_t ctx, RSA *rsa, if (!d) return UADK_E_FAIL;
- BN_bin2bn((unsigned char *)wd_d.data, key_size, d); BN_bin2bn((unsigned char *)wd_n.data, key_size, n); + BN_bin2bn((unsigned char *)wd_d.data, key_size, d); BN_bin2bn((unsigned char *)wd_qinv.data, wd_qinv.dsize, iqmp); BN_bin2bn((unsigned char *)wd_dq.data, wd_dq.dsize, dmq1); BN_bin2bn((unsigned char *)wd_dp.data, wd_dp.dsize, dmp1); @@ -1246,15 +1249,15 @@ static int rsa_get_keygen_param(struct wd_rsa_req *req, handle_t ctx, RSA *rsa,
static void uadk_e_rsa_cb(void *req_t) { - struct wd_rsa_req *req_new = (struct wd_rsa_req *)req_t; + struct wd_rsa_req *req = (struct wd_rsa_req *)req_t; struct uadk_e_cb_info *cb_param; struct wd_rsa_req *req_origin; struct async_op *op;
- if (!req_new) + if (!req) return;
- cb_param = req_new->cb_param; + cb_param = req->cb_param; if (!cb_param) return;
@@ -1262,7 +1265,7 @@ static void uadk_e_rsa_cb(void *req_t) if (!req_origin) return;
- req_origin->status = req_new->status; + req_origin->status = req->status;
op = cb_param->op; if (op && op->job && !op->done) { @@ -1345,21 +1348,19 @@ static int rsa_fill_keygen_data(struct uadk_rsa_sess *rsa_sess,
wd_rsa_get_crt_prikey_params(key_pair->prikey, NULL, NULL, NULL, &keygen_param->wd_q, &keygen_param->wd_p); - if (!keygen_param->wd_q || !keygen_param->wd_p) + if (!keygen_param->wd_p || !keygen_param->wd_q) return UADK_E_FAIL;
- keygen_param->wd_q->dsize = BN_bn2bin(bn_param->q, - (unsigned char *)keygen_param->wd_q->data); keygen_param->wd_p->dsize = BN_bn2bin(bn_param->p, (unsigned char *)keygen_param->wd_p->data); + keygen_param->wd_q->dsize = BN_bn2bin(bn_param->q, + (unsigned char *)keygen_param->wd_q->data);
rsa_sess->req.src_bytes = rsa_sess->key_size; rsa_sess->req.dst_bytes = rsa_sess->key_size; rsa_sess->req.op_type = WD_RSA_GENKEY; - rsa_sess->req.src = wd_rsa_new_kg_in(rsa_sess->sess, - keygen_param->wd_e, - keygen_param->wd_p, - keygen_param->wd_q); + rsa_sess->req.src = wd_rsa_new_kg_in(rsa_sess->sess, keygen_param->wd_e, + keygen_param->wd_p, keygen_param->wd_q); if (!rsa_sess->req.src) return UADK_E_FAIL;
@@ -1377,8 +1378,8 @@ static void rsa_free_keygen_data(struct uadk_rsa_sess *rsa_sess) if (!rsa_sess) return;
- wd_rsa_del_kg_in(rsa_sess->sess, rsa_sess->req.src); wd_rsa_del_kg_out(rsa_sess->sess, rsa_sess->req.dst); + wd_rsa_del_kg_in(rsa_sess->sess, rsa_sess->req.src); }
static int rsa_keygen_param_alloc(struct rsa_keygen_param **keygen_param, @@ -1389,7 +1390,7 @@ static int rsa_keygen_param_alloc(struct rsa_keygen_param **keygen_param,
*keygen_param = OPENSSL_malloc(sizeof(struct rsa_keygen_param)); if (!(*keygen_param)) - goto err; + goto error;
*keygen_bn_param = (struct rsa_keygen_param_bn *) OPENSSL_malloc(sizeof(struct rsa_keygen_param_bn)); @@ -1407,10 +1408,6 @@ static int rsa_keygen_param_alloc(struct rsa_keygen_param **keygen_param, BN_CTX_start(bn_ctx); *bn_ctx_in = bn_ctx;
- (*keygen_bn_param)->e = BN_CTX_get(bn_ctx); - if (!(*keygen_bn_param)->e) - goto free_bn_ctx; - (*keygen_bn_param)->p = BN_CTX_get(bn_ctx); if (!(*keygen_bn_param)->p) goto free_bn_ctx; @@ -1419,6 +1416,10 @@ static int rsa_keygen_param_alloc(struct rsa_keygen_param **keygen_param, if (!(*keygen_bn_param)->q) goto free_bn_ctx;
+ (*keygen_bn_param)->e = BN_CTX_get(bn_ctx); + if (!(*keygen_bn_param)->e) + goto free_bn_ctx; + return UADK_E_SUCCESS;
free_bn_ctx: @@ -1430,7 +1431,7 @@ free_keygen_bn_param: OPENSSL_free(*keygen_bn_param); free_keygen_param: OPENSSL_free(*keygen_param); -err: +error: return -ENOMEM; }
@@ -1440,9 +1441,9 @@ static void rsa_keygen_param_free(struct rsa_keygen_param **keygen_param, int free_bn_ctx_tag) { /* - * When an abnormal situation occurs, uadk engine needs - * to switch to software keygen function, so we need to - * free BN ctx we alloced before. But in normal situation, + * When an abnormal situation occurs, uadk engine needs to + * switch to software keygen function, so we need to free + * BN ctx we alloced before. But in normal situation, * the BN ctx should be freed by OpenSSL tools or users. * Therefore, we use a tag to distinguish these cases. */ @@ -1451,20 +1452,14 @@ static void rsa_keygen_param_free(struct rsa_keygen_param **keygen_param, BN_CTX_free(*bn_ctx); }
- OPENSSL_free(*keygen_bn_param); - OPENSSL_free(*keygen_param); OPENSSL_free(*key_pair); + OPENSSL_free(*keygen_param); + OPENSSL_free(*keygen_bn_param); }
static int rsa_pkey_param_alloc(struct rsa_pubkey_param **pub, struct rsa_prikey_param **pri) { - if (pub) { - *pub = OPENSSL_malloc(sizeof(struct rsa_pubkey_param)); - if (!(*pub)) - return -ENOMEM; - } - if (pri) { *pri = OPENSSL_malloc(sizeof(struct rsa_prikey_param)); if (!(*pri)) { @@ -1474,23 +1469,29 @@ static int rsa_pkey_param_alloc(struct rsa_pubkey_param **pub, } }
+ if (pub) { + *pub = OPENSSL_malloc(sizeof(struct rsa_pubkey_param)); + if (!(*pub)) + return -ENOMEM; + } + return UADK_E_SUCCESS; }
static void rsa_pkey_param_free(struct rsa_pubkey_param **pub, struct rsa_prikey_param **pri) { - if (pub) - OPENSSL_free(*pub); if (pri) OPENSSL_free(*pri); + if (pub) + OPENSSL_free(*pub); }
static int rsa_create_pub_bn_ctx(RSA *rsa, struct rsa_pubkey_param *pub, unsigned char **from_buf, int *num_bytes) { uadk_rsa_get0_key(rsa, &pub->n, &pub->e, NULL); - if (!(pub->n) || !(pub->e)) + if (!(pub->e) || !(pub->n)) return UADK_E_FAIL;
*num_bytes = BN_num_bytes(pub->n); @@ -1782,27 +1783,27 @@ static int uadk_prov_rsa_private_sign(int flen, const unsigned char *from, unsigned char *to, RSA *rsa, int padding) { struct uadk_rsa_sess *rsa_sess = NULL; - struct rsa_prikey_param *pri = NULL; + struct rsa_prikey_param *prik = NULL; unsigned char *from_buf = NULL; - int num_bytes, ret; + int ret, num_bytes;
ret = check_rsa_input_para(flen, from, to, rsa); if (ret != UADK_E_SUCCESS) return ret;
- ret = rsa_pkey_param_alloc(NULL, &pri); + ret = rsa_pkey_param_alloc(NULL, &prik); if (ret == -ENOMEM) return UADK_E_FAIL;
- pri->is_crt = check_rsa_is_crt(rsa); + prik->is_crt = check_rsa_is_crt(rsa);
- rsa_sess = rsa_get_eng_session(rsa, uadk_rsa_bits(rsa), pri->is_crt); + rsa_sess = rsa_get_eng_session(rsa, uadk_rsa_bits(rsa), prik->is_crt); if (!rsa_sess) { ret = UADK_DO_SOFT; goto free_pkey; }
- ret = rsa_create_pri_bn_ctx(rsa, pri, &from_buf, &num_bytes); + ret = rsa_create_pri_bn_ctx(rsa, prik, &from_buf, &num_bytes); if (ret <= 0 || flen > num_bytes) { ret = UADK_E_FAIL; goto free_sess; @@ -1814,7 +1815,7 @@ static int uadk_prov_rsa_private_sign(int flen, const unsigned char *from, goto free_buf; }
- ret = rsa_fill_prikey(rsa, rsa_sess, pri, from_buf, to); + ret = rsa_fill_prikey(rsa, rsa_sess, prik, from_buf, to); if (!ret) { ret = UADK_E_FAIL; goto free_buf; @@ -1826,14 +1827,14 @@ static int uadk_prov_rsa_private_sign(int flen, const unsigned char *from, goto free_buf; }
- ret = sign_trans_bn(rsa_sess, from_buf, pri, padding, to, num_bytes); + ret = sign_trans_bn(rsa_sess, from_buf, prik, padding, to, num_bytes);
free_buf: rsa_free_pri_bn_ctx(&from_buf); free_sess: rsa_free_eng_session(rsa_sess); free_pkey: - rsa_pkey_param_free(NULL, &pri); + rsa_pkey_param_free(NULL, &prik); return ret; }
@@ -1897,23 +1898,23 @@ static int uadk_prov_rsa_public_verify(int flen, const unsigned char *from, ret = rsa_fill_pubkey(pub, rsa_sess, from_buf, to); if (!ret) { ret = UADK_E_FAIL; - goto free_buf; + goto free_buff; }
memcpy(rsa_sess->req.src, from, rsa_sess->req.src_bytes); ret = rsa_do_crypto(rsa_sess); if (!ret || rsa_sess->req.status) { ret = UADK_DO_SOFT; - goto free_buf; + goto free_buff; }
ret = verify_trans_bn(rsa_sess, from_buf, num_bytes, pub, padding, &len); if (!ret) - goto free_buf; + goto free_buff;
ret = check_rsa_pubdec_padding(to, num_bytes, from_buf, len, padding);
-free_buf: +free_buff: rsa_free_pub_bn_ctx(&from_buf); free_sess: rsa_free_eng_session(rsa_sess); @@ -1951,24 +1952,24 @@ static int uadk_rsa_asym_init(void *vprsactx, void *vrsa, static int uadk_rsa_init(void *vprsactx, void *vrsa, const OSSL_PARAM params[], int operation) { - PROV_RSA_SIG_CTX *priv = (PROV_RSA_SIG_CTX *)vprsactx; + PROV_RSA_SIG_CTX *ctx = (PROV_RSA_SIG_CTX *)vprsactx;
- if (priv == NULL || vrsa == NULL) + if (ctx == NULL || vrsa == NULL) return UADK_E_FAIL;
- priv->rsa = vrsa; - priv->operation = operation; + ctx->rsa = vrsa; + ctx->operation = operation;
/* Maximum for sign, auto for verify */ - priv->saltlen = RSA_PSS_SALTLEN_AUTO; - priv->min_saltlen = -1; + ctx->saltlen = RSA_PSS_SALTLEN_AUTO; + ctx->min_saltlen = -1;
- switch (uadk_rsa_test_flags(priv->rsa, RSA_FLAG_TYPE_MASK)) { + switch (uadk_rsa_test_flags(ctx->rsa, RSA_FLAG_TYPE_MASK)) { case RSA_FLAG_TYPE_RSA: - priv->pad_mode = RSA_PKCS1_PADDING; + ctx->pad_mode = RSA_PKCS1_PADDING; break; case RSA_FLAG_TYPE_RSASSAPSS: - priv->pad_mode = RSA_PKCS1_PSS_PADDING; + ctx->pad_mode = RSA_PKCS1_PSS_PADDING; break; default: ERR_raise(ERR_LIB_RSA, PROV_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE); @@ -1976,7 +1977,7 @@ static int uadk_rsa_init(void *vprsactx, void *vrsa, }
if (uadk_prov_rsa_init()) - priv->soft = 1; + ctx->soft = 1;
return UADK_E_SUCCESS; } @@ -2430,7 +2431,6 @@ static int uadk_asym_cipher_rsa_decrypt(void *vprsactx, unsigned char *out, else return UADK_E_FAIL; } - *outlen = ret;
return UADK_E_SUCCESS;
From: Weili Qian qianweili@huawei.com
In asynchronous scenarios, if random numbers are obtained using uadk provider cipher, deadlocks may occur. Therefore, random numbers are obtained using default provider cipher.
logs like: 20808E99FFFF0000:error:1C8000B6:Provider routines:ossl_drbg_lock_parent: parent locking not enabled:providers/implementations/rands/drbg.c:70: 20808E99FFFF0000:error:1C8000C9:Provider routines:get_parent_strength: unable to lock parent:providers/implementations/rands/drbg.c:97: 20808E99FFFF0000:error:1C8000BD:Provider routines: ossl_prov_drbg_instantiate: error retrieving entropy: providers/implementations/rands/drbg.c:456: 20808E99FFFF0000:error:1C8000C0:Provider routines:ossl_prov_drbg_generate: in error state:providers/implementations/rands/drbg.c:630: 20808E99FFFF0000:error:030000D6:digital envelope routines: evp_rand_generate_locked:generate error:crypto/evp/evp_rand.c:560:
Signed-off-by: Weili Qian qianweili@huawei.com --- src/uadk_prov_init.c | 9 +++++++++ 1 file changed, 9 insertions(+)
diff --git a/src/uadk_prov_init.c b/src/uadk_prov_init.c index 9a2baeb..8616931 100644 --- a/src/uadk_prov_init.c +++ b/src/uadk_prov_init.c @@ -25,6 +25,7 @@ #include <openssl/crypto.h> #include <openssl/evp.h> #include <openssl/provider.h> +#include <openssl/rand.h>
#include "uadk_async.h" #include "uadk_prov.h" @@ -212,6 +213,14 @@ static const OSSL_ALGORITHM *uadk_query(void *provctx, int operation_id, * and overwrite the openssl.cnf property. */ EVP_set_default_properties(NULL, "?provider=uadk_provider"); + + /* + * In asynchronous scenarios, if random numbers are obtained using + * uadk provider cipher, deadlocks may occur. Therefore, random numbers are + * obtained using default provider cipher. + */ + (void)RAND_set_DRBG_type(prov_libctx_of(provctx), NULL, + "provider=default", NULL, NULL); }
*no_cache = 0;
From: Weili Qian qianweili@huawei.com
When the ctx is copied, if the pointer members in the ctx structure do not re-apply for memory and re-alloc session, the double free error occurs when the memory in the source ctx and copied ctx is released.
Signed-off-by: Weili Qian qianweili@huawei.com --- src/uadk_prov_digest.c | 20 ++++++++++++++------ 1 file changed, 14 insertions(+), 6 deletions(-)
diff --git a/src/uadk_prov_digest.c b/src/uadk_prov_digest.c index 8c539ed..86819cb 100644 --- a/src/uadk_prov_digest.c +++ b/src/uadk_prov_digest.c @@ -698,16 +698,24 @@ static void uadk_prov_freectx(void *dctx)
static void *uadk_prov_dupctx(void *dctx) { - struct digest_priv_ctx *in, *ret; + struct digest_priv_ctx *dst_ctx; + int ret;
if (!dctx) return NULL;
- in = (struct digest_priv_ctx *)dctx; - ret = OPENSSL_malloc(sizeof(struct digest_priv_ctx)); - if (ret) - memcpy(ret, in, sizeof(struct digest_priv_ctx)); - return ret; + dst_ctx = OPENSSL_malloc(sizeof(struct digest_priv_ctx)); + if (!dst_ctx) + return NULL; + + memcpy(dst_ctx, dctx, sizeof(struct digest_priv_ctx)); + ret = uadk_digest_init(dst_ctx); + if (!ret) { + OPENSSL_clear_free(dst_ctx, sizeof(struct digest_priv_ctx)); + return NULL; + } + + return dst_ctx; }
static int uadk_prov_init(void *dctx, const OSSL_PARAM params[])