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 | 1028 ++++++++++++++++++++++++++++++++++++++++++ src/uadk_prov_init.c | 7 + 4 files changed, 1040 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..c396f39 --- /dev/null +++ b/src/uadk_prov_aead.c @@ -0,0 +1,1028 @@ +// 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 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; + priv->setup.sched_param = ¶ms; + + if (!priv->sess) { + priv->sess = wd_aead_alloc_sess(&priv->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 = 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..ffe8fe6 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(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 | 782 +++++++++++++++++++++++++++++++++++++++ src/uadk_prov_init.c | 2 + src/uadk_prov_pkey.c | 4 +- src/uadk_prov_pkey.h | 8 + 6 files changed, 798 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..826eb63 --- /dev/null +++ b/src/uadk_prov_ec_kmgmt.c @@ -0,0 +1,782 @@ +// 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_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; +} + +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 ec_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) +{ + 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_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 ffe8fe6..f7e703f 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;
diff --git a/src/uadk_prov_pkey.h b/src/uadk_prov_pkey.h index c9ddba1..98e4335 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 {
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 | 970 ++++++++++++++++++++++++++++++++++++++ src/uadk_prov_init.c | 9 +- src/uadk_prov_pkey.c | 7 + src/uadk_prov_pkey.h | 5 + 6 files changed, 990 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..a555091 --- /dev/null +++ b/src/uadk_prov_ecdh_exch.c @@ -0,0 +1,970 @@ +// 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 +#define BITS_TO_BYTES(bits) (((bits) + 7) >> 3) +#define UADK_PROV_MIN_BITS 112 +#define UADK_PROV_SECURITY_BITS 80 +#define UADK_SECURITY_CHECK_DISABLE 0 + +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 int ecdh_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 for keyexch!\n", bits); + + return UADK_P_FAIL; +} + +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 ecdh_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 ecdh_check_key(OSSL_LIB_CTX *ctx, const EC_KEY *ec, int protect) +{ +#if !defined(OPENSSL_NO_FIPS_SECURITYCHECKS) + 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; + } + +#endif /* OPENSSL_NO_FIPS_SECURITYCHECKS */ + + return UADK_P_SUCCESS; +} + +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 ecdh_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 = ecdh_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 f7e703f..0a6f200 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 SECURITY_CHECK_DISABLE 0
static int p_keymgmt_support_state[KEYMGMT_TYPE]; static int p_signature_support_state[SIGNATURE_TYPE]; @@ -811,3 +812,9 @@ void uadk_prov_ecc_uninit(void) } pthread_mutex_unlock(&ecc_mutex); } + +/* 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; +} diff --git a/src/uadk_prov_pkey.h b/src/uadk_prov_pkey.h index 98e4335..93fe39f 100644 --- a/src/uadk_prov_pkey.h +++ b/src/uadk_prov_pkey.h @@ -451,5 +451,10 @@ 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); +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);
#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 | 10 +- 8 files changed, 1255 insertions(+), 19 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 826eb63..e187781 100644 --- a/src/uadk_prov_ec_kmgmt.c +++ b/src/uadk_prov_ec_kmgmt.c @@ -158,7 +158,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 a555091..46d06ea 100644 --- a/src/uadk_prov_ecdh_exch.c +++ b/src/uadk_prov_ecdh_exch.c @@ -76,12 +76,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 int ecdh_bit_check(const EC_GROUP *group) { @@ -195,7 +189,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 0a6f200..24ccc39 100644 --- a/src/uadk_prov_pkey.c +++ b/src/uadk_prov_pkey.c @@ -30,10 +30,12 @@ #define SIGNATURE_TYPE 3 #define ASYM_CIPHER_TYPE 3 #define SECURITY_CHECK_DISABLE 0 +#define KEYEXCH_TYPE 4
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; @@ -83,6 +85,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) @@ -356,7 +368,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) { @@ -383,11 +395,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);
@@ -396,10 +414,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; @@ -629,7 +649,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);
@@ -643,7 +663,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;
@@ -662,7 +682,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)); @@ -767,7 +787,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)); @@ -818,3 +838,18 @@ int uadk_prov_securitycheck_enabled(OSSL_LIB_CTX *ctx) { return SECURITY_CHECK_DISABLE; } + +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); + } +} diff --git a/src/uadk_prov_pkey.h b/src/uadk_prov_pkey.h index 93fe39f..9ff5363 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,10 +457,10 @@ 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); -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_keyexch_get_support_state(int alg_tag);
#endif
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;