916 lines
25 KiB
Diff
916 lines
25 KiB
Diff
From c6aab5dadf83fad2716b1687366d040303b1301c Mon Sep 17 00:00:00 2001
|
|
From: Zhangfei Gao <zhangfei.gao@linaro.org>
|
|
Date: Fri, 9 Jun 2023 09:04:30 +0000
|
|
Subject: [PATCH 6/7] uadk: support openssl 3.0
|
|
|
|
Openssl3.0 provoder will be built when libcrypto >= 3.0
|
|
|
|
First step to support digest
|
|
|
|
Test with
|
|
openssl speed -provider xx/uadk_provider.so -provider default -evp md5
|
|
openssl speed -provider xx/uadk_provider.so -provider default -evp sm3
|
|
openssl speed -provider xx/uadk_provider.so -provider default -evp sha1
|
|
openssl speed -provider xx/uadk_provider.so -provider default -evp sha2-224
|
|
openssl speed -provider xx/uadk_provider.so -provider default -evp sha2-256
|
|
openssl speed -provider xx/uadk_provider.so -provider default -evp sha2-384
|
|
openssl speed -provider xx/uadk_provider.so -provider default -evp sha2-512
|
|
|
|
Signed-off-by: Zhangfei Gao <zhangfei.gao@linaro.org>
|
|
---
|
|
src/Makefile.am | 11 +
|
|
src/uadk_prov.h | 30 ++
|
|
src/uadk_prov_digest.c | 699 +++++++++++++++++++++++++++++++++++++++++
|
|
src/uadk_prov_init.c | 110 +++++++
|
|
4 files changed, 850 insertions(+)
|
|
create mode 100644 src/uadk_prov.h
|
|
create mode 100644 src/uadk_prov_digest.c
|
|
create mode 100644 src/uadk_prov_init.c
|
|
|
|
diff --git a/src/Makefile.am b/src/Makefile.am
|
|
index 65afe1d..bfaeb78 100644
|
|
--- a/src/Makefile.am
|
|
+++ b/src/Makefile.am
|
|
@@ -5,6 +5,10 @@ if HAVE_CRYPTO
|
|
lib_LTLIBRARIES=uadk_engine.la
|
|
endif #HAVE_CRYPTO
|
|
|
|
+if HAVE_CRYPTO3
|
|
+lib_LTLIBRARIES=uadk_provider.la
|
|
+endif #HAVE_CRYPTO3
|
|
+
|
|
uadk_engine_la_SOURCES=uadk_utils.c uadk_engine_init.c uadk_cipher.c \
|
|
uadk_digest.c uadk_async.c uadk_rsa.c uadk_sm2.c \
|
|
uadk_pkey.c uadk_dh.c uadk_ec.c uadk_ecx.c
|
|
@@ -45,3 +49,10 @@ uadk_engine_la_SOURCES+=v1/alg/ciphers/sec_ciphers.c \
|
|
v1/async/async_poll.c \
|
|
v1/async/async_task_queue.c
|
|
endif #WD_KAE
|
|
+
|
|
+uadk_provider_la_SOURCES=uadk_prov_init.c uadk_prov_digest.c uadk_async.c uadk_utils.c
|
|
+
|
|
+uadk_provider_la_LDFLAGS=-module -version-number $(VERSION)
|
|
+uadk_provider_la_LIBADD=$(WD_LIBS) -lpthread
|
|
+uadk_provider_la_CFLAGS=$(WD_CFLAGS) $(libcrypto_CFLAGS)
|
|
+uadk_provider_la_CFLAGS+=-DCRYPTO3
|
|
diff --git a/src/uadk_prov.h b/src/uadk_prov.h
|
|
new file mode 100644
|
|
index 0000000..c63c3fe
|
|
--- /dev/null
|
|
+++ b/src/uadk_prov.h
|
|
@@ -0,0 +1,30 @@
|
|
+/*
|
|
+ * 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.
|
|
+ *
|
|
+ */
|
|
+#ifndef UADK_PROV_H
|
|
+#define UADK_PROV_H
|
|
+
|
|
+extern const OSSL_DISPATCH uadk_md5_functions[];
|
|
+extern const OSSL_DISPATCH uadk_sm3_functions[];
|
|
+extern const OSSL_DISPATCH uadk_sha1_functions[];
|
|
+extern const OSSL_DISPATCH uadk_sha224_functions[];
|
|
+extern const OSSL_DISPATCH uadk_sha256_functions[];
|
|
+extern const OSSL_DISPATCH uadk_sha384_functions[];
|
|
+extern const OSSL_DISPATCH uadk_sha512_functions[];
|
|
+
|
|
+void uadk_prov_destroy_digest(void);
|
|
+#endif
|
|
diff --git a/src/uadk_prov_digest.c b/src/uadk_prov_digest.c
|
|
new file mode 100644
|
|
index 0000000..fd05753
|
|
--- /dev/null
|
|
+++ b/src/uadk_prov_digest.c
|
|
@@ -0,0 +1,699 @@
|
|
+/*
|
|
+ * 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 <openssl/md5.h>
|
|
+#include <openssl/evp.h>
|
|
+#include <openssl/core_names.h>
|
|
+#include <openssl/proverr.h>
|
|
+#include <uadk/wd_cipher.h>
|
|
+#include <uadk/wd_digest.h>
|
|
+#include <uadk/wd_sched.h>
|
|
+#include "uadk.h"
|
|
+#include "uadk_async.h"
|
|
+#include "uadk_utils.h"
|
|
+
|
|
+#define UADK_DO_SOFT (-0xE0)
|
|
+#define CTX_SYNC 0
|
|
+#define CTX_ASYNC 1
|
|
+#define CTX_NUM 2
|
|
+#define DIGEST_DOING 1
|
|
+#define DIGEST_END 0
|
|
+
|
|
+/* The max BD data length is 16M-512B */
|
|
+#define BUF_LEN 0xFFFE00
|
|
+
|
|
+#define SM3_DIGEST_LENGTH 32
|
|
+#define SM3_CBLOCK 64
|
|
+#define SM3_SMALL_PACKET_OFFLOAD_THRESHOLD_DEFAULT (512)
|
|
+#define MD5_SMALL_PACKET_OFFLOAD_THRESHOLD_DEFAULT (8 * 1024)
|
|
+#define SHA_SMALL_PACKET_OFFLOAD_THRESHOLD_DEFAULT (512)
|
|
+#define MAX_DIGEST_LENGTH 64
|
|
+#define DIGEST_BLOCK_SIZE (512 * 1024)
|
|
+#define ALG_NAME_SIZE 128
|
|
+
|
|
+enum sec_digest_state {
|
|
+ SEC_DIGEST_INIT,
|
|
+ SEC_DIGEST_FIRST_UPDATING,
|
|
+ SEC_DIGEST_DOING,
|
|
+ SEC_DIGEST_FINAL
|
|
+};
|
|
+
|
|
+struct digest_threshold_table {
|
|
+ int nid;
|
|
+ int threshold;
|
|
+};
|
|
+
|
|
+struct digest_prov {
|
|
+ int pid;
|
|
+};
|
|
+
|
|
+static struct digest_prov prov;
|
|
+static pthread_mutex_t digest_mutex = PTHREAD_MUTEX_INITIALIZER;
|
|
+
|
|
+struct evp_md_ctx_st {
|
|
+ const EVP_MD *digest;
|
|
+ /* Functional reference if 'digest' is ENGINE-provided */
|
|
+ ENGINE *engine;
|
|
+ unsigned long flags;
|
|
+ void *md_data;
|
|
+ /* Public key context for sign/verify */
|
|
+ EVP_PKEY_CTX *pctx;
|
|
+ /* Update function: usually copied from EVP_MD */
|
|
+ int (*update)(EVP_MD_CTX *ctx, const void *data, size_t count);
|
|
+};
|
|
+
|
|
+struct digest_priv_ctx {
|
|
+ handle_t sess;
|
|
+ struct wd_digest_sess_setup setup;
|
|
+ struct wd_digest_req req;
|
|
+ unsigned char *data;
|
|
+ unsigned char out[MAX_DIGEST_LENGTH];
|
|
+ EVP_MD_CTX *soft_ctx;
|
|
+ EVP_MD *soft_md;
|
|
+ size_t last_update_bufflen;
|
|
+ uint32_t e_nid;
|
|
+ uint32_t state;
|
|
+ uint32_t switch_threshold;
|
|
+ int switch_flag;
|
|
+ size_t md_size;
|
|
+ size_t blk_size;
|
|
+ char alg_name[ALG_NAME_SIZE];
|
|
+};
|
|
+
|
|
+struct digest_info {
|
|
+ int nid;
|
|
+ enum wd_digest_mode mode;
|
|
+ enum wd_digest_type alg;
|
|
+ __u32 out_len;
|
|
+};
|
|
+
|
|
+static struct digest_threshold_table digest_pkt_threshold_table[] = {
|
|
+ { NID_sm3, SM3_SMALL_PACKET_OFFLOAD_THRESHOLD_DEFAULT },
|
|
+ { NID_md5, MD5_SMALL_PACKET_OFFLOAD_THRESHOLD_DEFAULT },
|
|
+ { NID_sha1, SHA_SMALL_PACKET_OFFLOAD_THRESHOLD_DEFAULT },
|
|
+ { NID_sha224, SHA_SMALL_PACKET_OFFLOAD_THRESHOLD_DEFAULT },
|
|
+ { NID_sha256, SHA_SMALL_PACKET_OFFLOAD_THRESHOLD_DEFAULT },
|
|
+ { NID_sha384, SHA_SMALL_PACKET_OFFLOAD_THRESHOLD_DEFAULT },
|
|
+ { NID_sha512, SHA_SMALL_PACKET_OFFLOAD_THRESHOLD_DEFAULT },
|
|
+};
|
|
+
|
|
+static struct digest_info digest_info_table[] = {
|
|
+ {NID_md5, WD_DIGEST_NORMAL, WD_DIGEST_MD5, 16},
|
|
+ {NID_sm3, WD_DIGEST_NORMAL, WD_DIGEST_SM3, 32},
|
|
+ {NID_sha1, WD_DIGEST_NORMAL, WD_DIGEST_SHA1, 20},
|
|
+ {NID_sha224, WD_DIGEST_NORMAL, WD_DIGEST_SHA224, 28},
|
|
+ {NID_sha256, WD_DIGEST_NORMAL, WD_DIGEST_SHA256, 32},
|
|
+ {NID_sha384, WD_DIGEST_NORMAL, WD_DIGEST_SHA384, 48},
|
|
+ {NID_sha512, WD_DIGEST_NORMAL, WD_DIGEST_SHA512, 64},
|
|
+};
|
|
+
|
|
+static int uadk_e_digests_soft_md(struct digest_priv_ctx *priv)
|
|
+{
|
|
+ if (priv->soft_md)
|
|
+ return 1;
|
|
+
|
|
+ switch (priv->e_nid) {
|
|
+ case NID_sm3:
|
|
+ priv->soft_md = EVP_MD_fetch(NULL, OSSL_DIGEST_NAME_SM3, "provider=default");
|
|
+ break;
|
|
+ case NID_md5:
|
|
+ priv->soft_md = EVP_MD_fetch(NULL, OSSL_DIGEST_NAME_MD5, "provider=default");
|
|
+ break;
|
|
+ case NID_sha1:
|
|
+ priv->soft_md = EVP_MD_fetch(NULL, OSSL_DIGEST_NAME_SHA1, "provider=default");
|
|
+ break;
|
|
+ case NID_sha224:
|
|
+ priv->soft_md = EVP_MD_fetch(NULL, OSSL_DIGEST_NAME_SHA3_224, "provider=default");
|
|
+ break;
|
|
+ case NID_sha256:
|
|
+ priv->soft_md = EVP_MD_fetch(NULL, OSSL_DIGEST_NAME_SHA3_256, "provider=default");
|
|
+ break;
|
|
+ case NID_sha384:
|
|
+ priv->soft_md = EVP_MD_fetch(NULL, OSSL_DIGEST_NAME_SHA3_384, "provider=default");
|
|
+ break;
|
|
+ case NID_sha512:
|
|
+ priv->soft_md = EVP_MD_fetch(NULL, OSSL_DIGEST_NAME_SHA3_512, "provider=default");
|
|
+ break;
|
|
+ default:
|
|
+ break;
|
|
+ }
|
|
+
|
|
+ if (unlikely(priv->soft_md == NULL))
|
|
+ return 0;
|
|
+
|
|
+ return 1;
|
|
+}
|
|
+
|
|
+static uint32_t sec_digest_get_sw_threshold(int n_id)
|
|
+{
|
|
+ int threshold_table_size = ARRAY_SIZE(digest_pkt_threshold_table);
|
|
+ int i = 0;
|
|
+
|
|
+ do {
|
|
+ if (digest_pkt_threshold_table[i].nid == n_id)
|
|
+ return digest_pkt_threshold_table[i].threshold;
|
|
+ } while (++i < threshold_table_size);
|
|
+
|
|
+ fprintf(stderr, "nid %d not found in digest threshold table", n_id);
|
|
+ return 0;
|
|
+}
|
|
+
|
|
+static int digest_soft_init(struct digest_priv_ctx *priv)
|
|
+{
|
|
+ return EVP_DigestInit(priv->soft_ctx, priv->soft_md);
|
|
+}
|
|
+
|
|
+static int digest_soft_update(EVP_MD_CTX *ctx, const void *data, size_t len)
|
|
+{
|
|
+ return EVP_DigestUpdate(ctx, data, len);
|
|
+}
|
|
+
|
|
+static int digest_soft_final(struct digest_priv_ctx *priv, unsigned char *digest)
|
|
+{
|
|
+ unsigned int digest_length = EVP_MD_get_size(priv->soft_md);
|
|
+
|
|
+ return EVP_DigestFinal(priv->soft_ctx, digest, &digest_length);
|
|
+}
|
|
+
|
|
+static void digest_soft_cleanup(struct digest_priv_ctx *priv)
|
|
+{
|
|
+ EVP_MD_CTX *ctx = priv->soft_ctx;
|
|
+
|
|
+ if (ctx != NULL) {
|
|
+ if (ctx->md_data) {
|
|
+ OPENSSL_free(ctx->md_data);
|
|
+ ctx->md_data = NULL;
|
|
+ }
|
|
+ EVP_MD_CTX_free(ctx);
|
|
+ ctx = NULL;
|
|
+ }
|
|
+
|
|
+ if (priv->soft_md) {
|
|
+ EVP_MD_free(priv->soft_md);
|
|
+ priv->soft_md = NULL;
|
|
+ }
|
|
+}
|
|
+
|
|
+static int uadk_e_digest_soft_work(struct digest_priv_ctx *priv, int len,
|
|
+ unsigned char *digest)
|
|
+{
|
|
+ digest_soft_init(priv);
|
|
+
|
|
+ if (len != 0)
|
|
+ digest_soft_update(priv->soft_ctx, priv->data, len);
|
|
+
|
|
+ digest_soft_final(priv, digest);
|
|
+ digest_soft_cleanup(priv);
|
|
+
|
|
+ return 1;
|
|
+}
|
|
+
|
|
+static int uadk_e_digest_env_poll(void *ctx)
|
|
+{
|
|
+ __u64 rx_cnt = 0;
|
|
+ __u32 recv = 0;
|
|
+ /* Poll one packet currently */
|
|
+ int expt = 1;
|
|
+ int ret;
|
|
+
|
|
+ do {
|
|
+ ret = wd_digest_poll(expt, &recv);
|
|
+ if (ret < 0 || recv == expt)
|
|
+ return ret;
|
|
+ rx_cnt++;
|
|
+ } while (rx_cnt < ENGINE_RECV_MAX_CNT);
|
|
+
|
|
+ fprintf(stderr, "failed to poll msg: timeout!\n");
|
|
+
|
|
+ return -ETIMEDOUT;
|
|
+}
|
|
+
|
|
+static int uadk_digest_init(struct digest_priv_ctx *priv)
|
|
+{
|
|
+ int digest_counts = ARRAY_SIZE(digest_info_table);
|
|
+ struct sched_params params = {0};
|
|
+ int nid = priv->e_nid;
|
|
+ int ret, i;
|
|
+
|
|
+ pthread_mutex_lock(&digest_mutex);
|
|
+ if (prov.pid != getpid()) {
|
|
+ ret = wd_digest_init2(priv->alg_name, 0, 0);
|
|
+ if (unlikely(ret)) {
|
|
+ priv->switch_flag = UADK_DO_SOFT;
|
|
+ goto soft_init;
|
|
+ }
|
|
+ prov.pid = getpid();
|
|
+ async_register_poll_fn(ASYNC_TASK_DIGEST, uadk_e_digest_env_poll);
|
|
+ }
|
|
+ pthread_mutex_unlock(&digest_mutex);
|
|
+
|
|
+ for (i = 0; i < digest_counts; i++) {
|
|
+ if (nid == digest_info_table[i].nid) {
|
|
+ priv->setup.alg = digest_info_table[i].alg;
|
|
+ priv->setup.mode = digest_info_table[i].mode;
|
|
+ priv->req.out_buf_bytes = MAX_DIGEST_LENGTH;
|
|
+ priv->req.out_bytes = digest_info_table[i].out_len;
|
|
+ break;
|
|
+ }
|
|
+ }
|
|
+
|
|
+ if (unlikely(i == digest_counts)) {
|
|
+ fprintf(stderr, "failed to setup the private ctx.\n");
|
|
+ return 0;
|
|
+ }
|
|
+
|
|
+ /* Use the default numa parameters */
|
|
+ params.numa_id = -1;
|
|
+ priv->setup.sched_param = ¶ms;
|
|
+ priv->sess = wd_digest_alloc_sess(&priv->setup);
|
|
+ if (unlikely(!priv->sess))
|
|
+ return 0;
|
|
+
|
|
+ priv->data = malloc(DIGEST_BLOCK_SIZE);
|
|
+ if (unlikely(!priv->data)) {
|
|
+ wd_digest_free_sess(priv->sess);
|
|
+ return 0;
|
|
+ }
|
|
+
|
|
+ if (uadk_e_digests_soft_md(priv))
|
|
+ priv->switch_threshold = sec_digest_get_sw_threshold(nid);
|
|
+
|
|
+ return 1;
|
|
+
|
|
+soft_init:
|
|
+ pthread_mutex_unlock(&digest_mutex);
|
|
+ fprintf(stderr, "uadk failed to initialize digest.\n");
|
|
+ return digest_soft_init(priv);
|
|
+}
|
|
+
|
|
+static void digest_update_out_length(struct digest_priv_ctx *priv)
|
|
+{
|
|
+ /* Sha224 and Sha384 need full length mac buffer as doing long hash */
|
|
+ if (priv->e_nid == NID_sha224)
|
|
+ priv->req.out_bytes = WD_DIGEST_SHA224_FULL_LEN;
|
|
+
|
|
+ if (priv->e_nid == NID_sha384)
|
|
+ priv->req.out_bytes = WD_DIGEST_SHA384_FULL_LEN;
|
|
+}
|
|
+
|
|
+static int digest_update_inner(struct digest_priv_ctx *priv, const void *data, size_t data_len)
|
|
+{
|
|
+ const unsigned char *tmpdata = (const unsigned char *)data;
|
|
+ size_t left_len = data_len;
|
|
+ int copy_to_bufflen;
|
|
+ int ret;
|
|
+
|
|
+ digest_update_out_length(priv);
|
|
+
|
|
+ priv->req.has_next = DIGEST_DOING;
|
|
+
|
|
+ while (priv->last_update_bufflen + left_len > DIGEST_BLOCK_SIZE) {
|
|
+ copy_to_bufflen = DIGEST_BLOCK_SIZE - priv->last_update_bufflen;
|
|
+ uadk_memcpy(priv->data + priv->last_update_bufflen, tmpdata,
|
|
+ copy_to_bufflen);
|
|
+
|
|
+ priv->last_update_bufflen = DIGEST_BLOCK_SIZE;
|
|
+ priv->req.in_bytes = DIGEST_BLOCK_SIZE;
|
|
+ priv->req.in = priv->data;
|
|
+ priv->req.out = priv->out;
|
|
+ left_len -= copy_to_bufflen;
|
|
+ tmpdata += copy_to_bufflen;
|
|
+ if (priv->state == SEC_DIGEST_INIT)
|
|
+ priv->state = SEC_DIGEST_FIRST_UPDATING;
|
|
+ else if (priv->state == SEC_DIGEST_FIRST_UPDATING)
|
|
+ priv->state = SEC_DIGEST_DOING;
|
|
+
|
|
+ ret = wd_do_digest_sync(priv->sess, &priv->req);
|
|
+ if (ret) {
|
|
+ fprintf(stderr, "do sec digest sync failed, switch to soft digest.\n");
|
|
+ goto do_soft_digest;
|
|
+ }
|
|
+
|
|
+ priv->last_update_bufflen = 0;
|
|
+ if (left_len <= DIGEST_BLOCK_SIZE) {
|
|
+ priv->last_update_bufflen = left_len;
|
|
+ uadk_memcpy(priv->data, tmpdata, priv->last_update_bufflen);
|
|
+ break;
|
|
+ }
|
|
+ }
|
|
+
|
|
+ return 1;
|
|
+
|
|
+do_soft_digest:
|
|
+ if (priv->state == SEC_DIGEST_FIRST_UPDATING
|
|
+ && priv->data
|
|
+ && priv->last_update_bufflen != 0) {
|
|
+ priv->switch_flag = UADK_DO_SOFT;
|
|
+ digest_soft_init(priv);
|
|
+ ret = digest_soft_update(priv->soft_ctx,
|
|
+ priv->data, priv->last_update_bufflen);
|
|
+ if (ret != 1)
|
|
+ return ret;
|
|
+
|
|
+ return digest_soft_update(priv->soft_ctx,
|
|
+ tmpdata, left_len);
|
|
+ }
|
|
+
|
|
+ fprintf(stderr, "do soft digest failed during updating!\n");
|
|
+ return 0;
|
|
+}
|
|
+
|
|
+static int uadk_digest_update(struct digest_priv_ctx *priv, const void *data, size_t data_len)
|
|
+{
|
|
+ if (unlikely(priv->switch_flag == UADK_DO_SOFT))
|
|
+ goto soft_update;
|
|
+
|
|
+ if (priv->last_update_bufflen + data_len <= DIGEST_BLOCK_SIZE) {
|
|
+ uadk_memcpy(priv->data + priv->last_update_bufflen, data, data_len);
|
|
+ priv->last_update_bufflen += data_len;
|
|
+ return 1;
|
|
+ }
|
|
+
|
|
+ return digest_update_inner(priv, data, data_len);
|
|
+
|
|
+soft_update:
|
|
+ return digest_soft_update(priv->soft_ctx, data, data_len);
|
|
+}
|
|
+
|
|
+static void async_cb(struct wd_digest_req *req, void *data)
|
|
+{
|
|
+ struct uadk_e_cb_info *cb_param;
|
|
+ struct async_op *op;
|
|
+
|
|
+ if (!req)
|
|
+ return;
|
|
+
|
|
+ cb_param = req->cb_param;
|
|
+ if (!cb_param)
|
|
+ return;
|
|
+ op = cb_param->op;
|
|
+ if (op && op->job && !op->done) {
|
|
+ op->done = 1;
|
|
+ async_free_poll_task(op->idx, 1);
|
|
+ async_wake_job(op->job);
|
|
+ }
|
|
+}
|
|
+
|
|
+static int do_digest_sync(struct digest_priv_ctx *priv)
|
|
+{
|
|
+ int ret;
|
|
+
|
|
+ if (priv->req.in_bytes <= priv->switch_threshold &&
|
|
+ priv->state == SEC_DIGEST_INIT)
|
|
+ return 0;
|
|
+
|
|
+ ret = wd_do_digest_sync(priv->sess, &priv->req);
|
|
+ if (ret) {
|
|
+ fprintf(stderr, "do sec digest sync failed, switch to soft digest.\n");
|
|
+ return 0;
|
|
+ }
|
|
+ return 1;
|
|
+}
|
|
+
|
|
+static int do_digest_async(struct digest_priv_ctx *priv, struct async_op *op)
|
|
+{
|
|
+ struct uadk_e_cb_info cb_param;
|
|
+ int idx, ret;
|
|
+
|
|
+ if (unlikely(priv->switch_flag == UADK_DO_SOFT)) {
|
|
+ fprintf(stderr, "async cipher init failed.\n");
|
|
+ return 0;
|
|
+ }
|
|
+
|
|
+ cb_param.op = op;
|
|
+ cb_param.priv = priv;
|
|
+ priv->req.cb = (void *)async_cb;
|
|
+ priv->req.cb_param = &cb_param;
|
|
+
|
|
+ ret = async_get_free_task(&idx);
|
|
+ if (!ret)
|
|
+ return 0;
|
|
+
|
|
+ op->idx = idx;
|
|
+
|
|
+ do {
|
|
+ ret = wd_do_digest_async(priv->sess, &priv->req);
|
|
+ if (ret < 0 && ret != -EBUSY) {
|
|
+ fprintf(stderr, "do sec digest async failed.\n");
|
|
+ async_free_poll_task(op->idx, 0);
|
|
+ return 0;
|
|
+ }
|
|
+ } while (ret == -EBUSY);
|
|
+
|
|
+ ret = async_pause_job(priv, op, ASYNC_TASK_DIGEST, idx);
|
|
+ if (!ret)
|
|
+ return 0;
|
|
+ return 1;
|
|
+}
|
|
+
|
|
+static int uadk_digest_final(struct digest_priv_ctx *priv, unsigned char *digest)
|
|
+{
|
|
+ struct async_op op;
|
|
+ int ret;
|
|
+
|
|
+ priv->req.has_next = DIGEST_END;
|
|
+ priv->req.in = priv->data;
|
|
+ priv->req.out = priv->out;
|
|
+ priv->req.in_bytes = priv->last_update_bufflen;
|
|
+
|
|
+ if (priv->e_nid == NID_sha224)
|
|
+ priv->req.out_bytes = WD_DIGEST_SHA224_LEN;
|
|
+
|
|
+ if (priv->e_nid == NID_sha384)
|
|
+ priv->req.out_bytes = WD_DIGEST_SHA384_LEN;
|
|
+
|
|
+ ret = async_setup_async_event_notification(&op);
|
|
+ if (unlikely(!ret)) {
|
|
+ fprintf(stderr, "failed to setup async event notification.\n");
|
|
+ return 0;
|
|
+ }
|
|
+
|
|
+ if (op.job == NULL) {
|
|
+ /* Synchronous, only the synchronous mode supports soft computing */
|
|
+ if (unlikely(priv->switch_flag == UADK_DO_SOFT)) {
|
|
+ ret = digest_soft_final(priv, digest);
|
|
+ digest_soft_cleanup(priv);
|
|
+ goto clear;
|
|
+ }
|
|
+
|
|
+ ret = do_digest_sync(priv);
|
|
+ if (!ret)
|
|
+ goto sync_err;
|
|
+ } else {
|
|
+ ret = do_digest_async(priv, &op);
|
|
+ if (!ret)
|
|
+ goto clear;
|
|
+ }
|
|
+ memcpy(digest, priv->req.out, priv->req.out_bytes);
|
|
+
|
|
+ return 1;
|
|
+
|
|
+sync_err:
|
|
+ if (priv->state == SEC_DIGEST_INIT) {
|
|
+ ret = uadk_e_digest_soft_work(priv, priv->req.in_bytes, digest);
|
|
+ } else {
|
|
+ ret = 0;
|
|
+ fprintf(stderr, "do sec digest stream mode failed.\n");
|
|
+ }
|
|
+clear:
|
|
+ async_clear_async_event_notification();
|
|
+ return ret;
|
|
+}
|
|
+
|
|
+static int uadk_digest_cleanup(struct digest_priv_ctx *priv)
|
|
+{
|
|
+ if (priv->sess) {
|
|
+ wd_digest_free_sess(priv->sess);
|
|
+ priv->sess = 0;
|
|
+ }
|
|
+
|
|
+ if (priv->data)
|
|
+ OPENSSL_free(priv->data);
|
|
+
|
|
+ return 1;
|
|
+}
|
|
+
|
|
+/* some params related code is copied from OpenSSL v3.0 prov/digestcommon.h */
|
|
+static const OSSL_PARAM uadk_digest_default_known_gettable_params[] = {
|
|
+ OSSL_PARAM_size_t(OSSL_DIGEST_PARAM_BLOCK_SIZE, NULL),
|
|
+ OSSL_PARAM_size_t(OSSL_DIGEST_PARAM_SIZE, NULL),
|
|
+ OSSL_PARAM_int(OSSL_DIGEST_PARAM_XOF, NULL),
|
|
+ OSSL_PARAM_int(OSSL_DIGEST_PARAM_ALGID_ABSENT, NULL),
|
|
+ OSSL_PARAM_END
|
|
+};
|
|
+
|
|
+static const OSSL_PARAM *uadk_prov_gettable_params(void *provctx)
|
|
+{
|
|
+ return uadk_digest_default_known_gettable_params;
|
|
+}
|
|
+
|
|
+static int uadk_digest_default_get_params(OSSL_PARAM params[], size_t blksz,
|
|
+ size_t paramsz)
|
|
+{
|
|
+ OSSL_PARAM *p = NULL;
|
|
+
|
|
+ p = OSSL_PARAM_locate(params, OSSL_DIGEST_PARAM_BLOCK_SIZE);
|
|
+ if (p != NULL && !OSSL_PARAM_set_size_t(p, blksz)) {
|
|
+ ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_SET_PARAMETER);
|
|
+ return 0;
|
|
+ }
|
|
+ p = OSSL_PARAM_locate(params, OSSL_DIGEST_PARAM_SIZE);
|
|
+ if (p != NULL && !OSSL_PARAM_set_size_t(p, paramsz)) {
|
|
+ ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_SET_PARAMETER);
|
|
+ return 0;
|
|
+ }
|
|
+ p = OSSL_PARAM_locate(params, OSSL_DIGEST_PARAM_XOF);
|
|
+ if (p != NULL
|
|
+ && !OSSL_PARAM_set_int(p, 0)) {
|
|
+ ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_SET_PARAMETER);
|
|
+ return 0;
|
|
+ }
|
|
+ p = OSSL_PARAM_locate(params, OSSL_DIGEST_PARAM_ALGID_ABSENT);
|
|
+ if (p != NULL
|
|
+ && !OSSL_PARAM_set_int(p, 0)) {
|
|
+ ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_SET_PARAMETER);
|
|
+ return 0;
|
|
+ }
|
|
+
|
|
+ return 1;
|
|
+}
|
|
+
|
|
+static void uadk_prov_freectx(void *dctx)
|
|
+{
|
|
+ struct digest_priv_ctx *priv = (struct digest_priv_ctx *)dctx;
|
|
+
|
|
+ uadk_digest_cleanup(priv);
|
|
+ OPENSSL_clear_free(priv, sizeof(*priv));
|
|
+}
|
|
+
|
|
+static void *uadk_prov_dupctx(void *dctx)
|
|
+{
|
|
+ struct digest_priv_ctx *in;
|
|
+ struct digest_priv_ctx *ret;
|
|
+
|
|
+ in = (struct digest_priv_ctx *)dctx;
|
|
+ ret = OPENSSL_zalloc(sizeof(struct digest_priv_ctx *));
|
|
+
|
|
+ if (ret != NULL)
|
|
+ *ret = *in;
|
|
+ return ret;
|
|
+}
|
|
+
|
|
+static int uadk_prov_init(void *dctx, const OSSL_PARAM params[])
|
|
+{
|
|
+ struct digest_priv_ctx *priv =
|
|
+ (struct digest_priv_ctx *) dctx;
|
|
+
|
|
+ return uadk_digest_init(priv);
|
|
+}
|
|
+
|
|
+static int uadk_prov_update(void *dctx, const unsigned char *in, size_t inl)
|
|
+{
|
|
+ return uadk_digest_update((struct digest_priv_ctx *)dctx, in, inl);
|
|
+}
|
|
+
|
|
+/*
|
|
+ * Note:
|
|
+ * The I<dctx> parameter contains a pointer to the provider side context.
|
|
+ * The digest should be written to I<*out> and the length of the digest to I<*outl>.
|
|
+ * The digest should not exceed I<outsz> bytes.
|
|
+ */
|
|
+static int uadk_prov_final(void *dctx, unsigned char *out,
|
|
+ size_t *outl, size_t outsz)
|
|
+{
|
|
+ struct digest_priv_ctx *priv =
|
|
+ (struct digest_priv_ctx *) dctx;
|
|
+ int ret;
|
|
+
|
|
+ if (outsz > 0) {
|
|
+ ret = uadk_digest_final(priv, out);
|
|
+ if (!ret)
|
|
+ return ret;
|
|
+ }
|
|
+
|
|
+ if (unlikely(outl != NULL))
|
|
+ *outl = priv->md_size;
|
|
+
|
|
+ return 1;
|
|
+}
|
|
+
|
|
+void uadk_prov_destroy_digest(void)
|
|
+{
|
|
+ pthread_mutex_lock(&digest_mutex);
|
|
+ if (prov.pid == getpid()) {
|
|
+ wd_digest_uninit2();
|
|
+ prov.pid = 0;
|
|
+ }
|
|
+ pthread_mutex_unlock(&digest_mutex);
|
|
+}
|
|
+
|
|
+static OSSL_FUNC_digest_freectx_fn uadk_prov_freectx;
|
|
+static OSSL_FUNC_digest_dupctx_fn uadk_prov_dupctx;
|
|
+static OSSL_FUNC_digest_init_fn uadk_prov_init;
|
|
+static OSSL_FUNC_digest_update_fn uadk_prov_update;
|
|
+static OSSL_FUNC_digest_final_fn uadk_prov_final;
|
|
+static OSSL_FUNC_digest_gettable_params_fn
|
|
+ uadk_prov_gettable_params;
|
|
+
|
|
+#define UADK_PROVIDER_IMPLEMENTATION(name, nid, mdsize, blksize) \
|
|
+static OSSL_FUNC_digest_newctx_fn uadk_##name##_newctx; \
|
|
+static void *uadk_##name##_newctx(void *provctx) \
|
|
+{ \
|
|
+ struct digest_priv_ctx *ctx = OPENSSL_zalloc(sizeof(*ctx)); \
|
|
+ \
|
|
+ if (ctx == NULL) \
|
|
+ return NULL; \
|
|
+ ctx->blk_size = blksize; \
|
|
+ ctx->md_size = mdsize; \
|
|
+ ctx->e_nid = nid; \
|
|
+ ctx->soft_ctx = EVP_MD_CTX_new(); \
|
|
+ if (ctx->soft_ctx == NULL) \
|
|
+ fprintf(stderr, "EVP_MD_CTX_new failed.\n"); \
|
|
+ strncpy(ctx->alg_name, #name, ALG_NAME_SIZE - 1); \
|
|
+ return ctx; \
|
|
+} \
|
|
+static OSSL_FUNC_digest_get_params_fn uadk_##name##_get_params; \
|
|
+static int uadk_##name##_get_params(OSSL_PARAM params[]) \
|
|
+{ \
|
|
+ return uadk_digest_default_get_params(params, blksize, mdsize); \
|
|
+} \
|
|
+const OSSL_DISPATCH uadk_##name##_functions[] = { \
|
|
+ { OSSL_FUNC_DIGEST_NEWCTX, (void (*)(void))uadk_##name##_newctx }, \
|
|
+ { OSSL_FUNC_DIGEST_FREECTX, (void (*)(void))uadk_prov_freectx }, \
|
|
+ { OSSL_FUNC_DIGEST_DUPCTX, (void (*)(void))uadk_prov_dupctx }, \
|
|
+ { OSSL_FUNC_DIGEST_INIT, (void (*)(void))uadk_prov_init }, \
|
|
+ { OSSL_FUNC_DIGEST_UPDATE, (void (*)(void))uadk_prov_update }, \
|
|
+ { OSSL_FUNC_DIGEST_FINAL, (void (*)(void))uadk_prov_final }, \
|
|
+ { OSSL_FUNC_DIGEST_GET_PARAMS, \
|
|
+ (void (*)(void))uadk_##name##_get_params }, \
|
|
+ { OSSL_FUNC_DIGEST_GETTABLE_PARAMS, \
|
|
+ (void (*)(void))uadk_prov_gettable_params }, \
|
|
+ { 0, NULL } \
|
|
+}
|
|
+
|
|
+UADK_PROVIDER_IMPLEMENTATION(md5, NID_md5, MD5_DIGEST_LENGTH, MD5_CBLOCK);
|
|
+UADK_PROVIDER_IMPLEMENTATION(sm3, NID_sm3, SM3_DIGEST_LENGTH, SM3_CBLOCK);
|
|
+UADK_PROVIDER_IMPLEMENTATION(sha1, NID_sha1, 20, 64);
|
|
+UADK_PROVIDER_IMPLEMENTATION(sha224, NID_sha224, 28, 64);
|
|
+UADK_PROVIDER_IMPLEMENTATION(sha256, NID_sha256, 32, 64);
|
|
+UADK_PROVIDER_IMPLEMENTATION(sha384, NID_sha384, 48, 128);
|
|
+UADK_PROVIDER_IMPLEMENTATION(sha512, NID_sha512, 64, 128);
|
|
diff --git a/src/uadk_prov_init.c b/src/uadk_prov_init.c
|
|
new file mode 100644
|
|
index 0000000..e363584
|
|
--- /dev/null
|
|
+++ b/src/uadk_prov_init.c
|
|
@@ -0,0 +1,110 @@
|
|
+/*
|
|
+ * 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 <string.h>
|
|
+
|
|
+#include <openssl/core_dispatch.h>
|
|
+#include <openssl/core_names.h>
|
|
+#include <openssl/crypto.h>
|
|
+
|
|
+#include "uadk_async.h"
|
|
+#include "uadk_prov.h"
|
|
+
|
|
+struct p_uadk_ctx {
|
|
+ const OSSL_CORE_HANDLE *handle;
|
|
+ OSSL_LIB_CTX *libctx;
|
|
+};
|
|
+
|
|
+const char *engine_uadk_id = "uadk_provider";
|
|
+static const char UADK_DEFAULT_PROPERTIES[] = "provider=uadk";
|
|
+
|
|
+const OSSL_ALGORITHM uadk_prov_digests[] = {
|
|
+ { OSSL_DIGEST_NAME_MD5, UADK_DEFAULT_PROPERTIES,
|
|
+ uadk_md5_functions, "uadk_provider md5" },
|
|
+ { OSSL_DIGEST_NAME_SM3, UADK_DEFAULT_PROPERTIES,
|
|
+ uadk_sm3_functions, "uadk_provider sm3" },
|
|
+ { OSSL_DIGEST_NAME_SHA1, UADK_DEFAULT_PROPERTIES,
|
|
+ uadk_sha1_functions, "uadk_provider sha1" },
|
|
+ { OSSL_DIGEST_NAME_SHA2_224, UADK_DEFAULT_PROPERTIES,
|
|
+ uadk_sha224_functions, "uadk_provider sha2-224" },
|
|
+ { OSSL_DIGEST_NAME_SHA2_256, UADK_DEFAULT_PROPERTIES,
|
|
+ uadk_sha256_functions, "uadk_provider sha2-256" },
|
|
+ { OSSL_DIGEST_NAME_SHA2_384, UADK_DEFAULT_PROPERTIES,
|
|
+ uadk_sha384_functions, "uadk_provider sha2-384" },
|
|
+ { OSSL_DIGEST_NAME_SHA2_512, UADK_DEFAULT_PROPERTIES,
|
|
+ uadk_sha512_functions, "uadk_provider sha2-512" },
|
|
+ { NULL, NULL, NULL }
|
|
+};
|
|
+
|
|
+static const OSSL_ALGORITHM *p_prov_query(void *provctx, int operation_id,
|
|
+ int *no_cache)
|
|
+{
|
|
+ *no_cache = 0;
|
|
+
|
|
+ switch (operation_id) {
|
|
+ case OSSL_OP_DIGEST:
|
|
+ return uadk_prov_digests;
|
|
+ }
|
|
+ return NULL;
|
|
+}
|
|
+
|
|
+static void p_teardown(void *provctx)
|
|
+{
|
|
+ struct p_uadk_ctx *ctx = (struct p_uadk_ctx *)provctx;
|
|
+
|
|
+ uadk_prov_destroy_digest();
|
|
+ OPENSSL_free(ctx);
|
|
+}
|
|
+
|
|
+static const OSSL_DISPATCH p_test_table[] = {
|
|
+ { OSSL_FUNC_PROVIDER_QUERY_OPERATION, (void (*)(void))p_prov_query },
|
|
+ { OSSL_FUNC_PROVIDER_TEARDOWN, (void (*)(void))p_teardown },
|
|
+ { 0, NULL }
|
|
+};
|
|
+
|
|
+static void provider_init_child_at_fork_handler(void)
|
|
+{
|
|
+ int ret;
|
|
+
|
|
+ ret = async_module_init();
|
|
+ if (!ret)
|
|
+ fprintf(stderr, "async_module_init fail!\n");
|
|
+}
|
|
+
|
|
+int OSSL_provider_init(const OSSL_CORE_HANDLE *handle,
|
|
+ const OSSL_DISPATCH *oin,
|
|
+ const OSSL_DISPATCH **out,
|
|
+ void **provctx)
|
|
+{
|
|
+ struct p_uadk_ctx *ctx;
|
|
+ int ret;
|
|
+
|
|
+ ctx = OPENSSL_zalloc(sizeof(*ctx));
|
|
+ if (ctx == NULL)
|
|
+ return 0;
|
|
+
|
|
+ ret = async_module_init();
|
|
+ if (!ret)
|
|
+ fprintf(stderr, "async_module_init fail!\n");
|
|
+ pthread_atfork(NULL, NULL, provider_init_child_at_fork_handler);
|
|
+
|
|
+ *provctx = (void *)ctx;
|
|
+ *out = p_test_table;
|
|
+ return 1;
|
|
+}
|
|
--
|
|
2.25.1
|
|
|