uadk_engine/0012-uadk-add-uadk_prov_cipher.patch
2023-10-31 16:41:46 +08:00

945 lines
30 KiB
Diff

From 67f7a6d5e934e64abab69fc0cbd7ef4b09bb045e Mon Sep 17 00:00:00 2001
From: Zhangfei Gao <zhangfei.gao@linaro.org>
Date: Mon, 3 Jul 2023 07:05:17 +0000
Subject: [PATCH 12/48] uadk: add uadk_prov_cipher
Test:
openssl list -provider uadk_provider -cipher-algorithms
openssl speed -provider uadk_provider -provider default -evp sm4-ecb
openssl speed -provider uadk_provider -provider default -evp sm4-cbc
openssl speed -provider uadk_provider -provider default -evp aes-128-cbc
Signed-off-by: Zhangfei Gao <zhangfei.gao@linaro.org>
---
src/Makefile.am | 3 +-
src/uadk_prov.h | 14 +
src/uadk_prov_cipher.c | 820 +++++++++++++++++++++++++++++++++++++++++
src/uadk_prov_init.c | 31 ++
4 files changed, 867 insertions(+), 1 deletion(-)
create mode 100644 src/uadk_prov_cipher.c
diff --git a/src/Makefile.am b/src/Makefile.am
index bfaeb78..af16d85 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -50,7 +50,8 @@ uadk_engine_la_SOURCES+=v1/alg/ciphers/sec_ciphers.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_SOURCES=uadk_prov_init.c uadk_async.c uadk_utils.c \
+ uadk_prov_digest.c uadk_prov_cipher.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 c63c3fe..35f1789 100644
--- a/src/uadk_prov.h
+++ b/src/uadk_prov.h
@@ -26,5 +26,19 @@ extern const OSSL_DISPATCH uadk_sha256_functions[];
extern const OSSL_DISPATCH uadk_sha384_functions[];
extern const OSSL_DISPATCH uadk_sha512_functions[];
+extern const OSSL_DISPATCH uadk_aes_128_cbc_functions[];
+extern const OSSL_DISPATCH uadk_aes_192_cbc_functions[];
+extern const OSSL_DISPATCH uadk_aes_256_cbc_functions[];
+extern const OSSL_DISPATCH uadk_aes_128_ecb_functions[];
+extern const OSSL_DISPATCH uadk_aes_192_ecb_functions[];
+extern const OSSL_DISPATCH uadk_aes_256_ecb_functions[];
+extern const OSSL_DISPATCH uadk_aes_128_xts_functions[];
+extern const OSSL_DISPATCH uadk_aes_256_xts_functions[];
+extern const OSSL_DISPATCH uadk_sm4_cbc_functions[];
+extern const OSSL_DISPATCH uadk_sm4_ecb_functions[];
+extern const OSSL_DISPATCH uadk_des_ede3_cbc_functions[];
+extern const OSSL_DISPATCH uadk_des_ede3_ecb_functions[];
+
void uadk_prov_destroy_digest(void);
+void uadk_prov_destroy_cipher(void);
#endif
diff --git a/src/uadk_prov_cipher.c b/src/uadk_prov_cipher.c
new file mode 100644
index 0000000..af0fa02
--- /dev/null
+++ b/src/uadk_prov_cipher.c
@@ -0,0 +1,820 @@
+/*
+ * 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/core_names.h>
+#include <openssl/proverr.h>
+#include <uadk/wd_cipher.h>
+#include <uadk/wd_sched.h>
+#include "uadk.h"
+#include "uadk_async.h"
+
+#define UADK_DO_SOFT (-0xE0)
+#define CTX_SYNC_ENC 0
+#define CTX_SYNC_DEC 1
+#define CTX_ASYNC_ENC 2
+#define CTX_ASYNC_DEC 3
+#define CTX_NUM 4
+#define CTR_128BIT_COUNTER 16
+#define CTR_MODE_LEN_SHIFT 4
+#define BYTE_BITS 8
+#define IV_LEN 16
+#define ENV_ENABLED 1
+#define MAX_KEY_LEN 64
+#define ALG_NAME_SIZE 128
+
+/* Internal flags that can be queried */
+#define PROV_CIPHER_FLAG_AEAD 0x0001
+#define PROV_CIPHER_FLAG_CUSTOM_IV 0x0002
+#define PROV_CIPHER_FLAG_CTS 0x0004
+#define PROV_CIPHER_FLAG_TLS1_MULTIBLOCK 0x0008
+#define PROV_CIPHER_FLAG_RAND_KEY 0x0010
+
+/* Internal flags that are only used within the provider */
+#define PROV_CIPHER_FLAG_VARIABLE_LENGTH 0x0100
+#define PROV_CIPHER_FLAG_INVERSE_CIPHER 0x0200
+
+#define SMALL_PACKET_OFFLOAD_THRESHOLD_DEFAULT 192
+
+struct cipher_prov {
+ int pid;
+};
+static struct cipher_prov prov;
+static pthread_mutex_t cipher_mutex = PTHREAD_MUTEX_INITIALIZER;
+
+struct cipher_priv_ctx {
+ int nid;
+ handle_t sess;
+ struct wd_cipher_sess_setup setup;
+ struct wd_cipher_req req;
+ unsigned char iv[IV_LEN];
+ unsigned char key[MAX_KEY_LEN];
+ int switch_flag;
+ EVP_CIPHER_CTX *sw_ctx;
+ EVP_CIPHER *sw_cipher;
+ /* Crypto small packet offload threshold */
+ size_t switch_threshold;
+ unsigned int enc : 1;
+ size_t blksize;
+ size_t keylen;
+ size_t ivlen;
+ char alg_name[ALG_NAME_SIZE];
+};
+
+struct cipher_info {
+ int nid;
+ enum wd_cipher_alg alg;
+ enum wd_cipher_mode mode;
+ __u32 out_bytes;
+};
+
+static struct cipher_info cipher_info_table[] = {
+ { NID_aes_128_ecb, WD_CIPHER_AES, WD_CIPHER_ECB, 16},
+ { NID_aes_192_ecb, WD_CIPHER_AES, WD_CIPHER_ECB, 16},
+ { NID_aes_256_ecb, WD_CIPHER_AES, WD_CIPHER_ECB, 16},
+ { NID_aes_128_cbc, WD_CIPHER_AES, WD_CIPHER_CBC, 16},
+ { NID_aes_192_cbc, WD_CIPHER_AES, WD_CIPHER_CBC, 64},
+ { NID_aes_256_cbc, WD_CIPHER_AES, WD_CIPHER_CBC, 64},
+ { NID_aes_128_xts, WD_CIPHER_AES, WD_CIPHER_XTS, 32},
+ { NID_aes_256_xts, WD_CIPHER_AES, WD_CIPHER_XTS, 512},
+ { NID_sm4_cbc, WD_CIPHER_SM4, WD_CIPHER_CBC, 16},
+ { NID_des_ede3_cbc, WD_CIPHER_3DES, WD_CIPHER_CBC, 16},
+ { NID_des_ede3_ecb, WD_CIPHER_3DES, WD_CIPHER_ECB, 16},
+ { NID_aes_128_ctr, WD_CIPHER_AES, WD_CIPHER_CTR, 64},
+ { NID_aes_192_ctr, WD_CIPHER_AES, WD_CIPHER_CTR, 64},
+ { NID_aes_256_ctr, WD_CIPHER_AES, WD_CIPHER_CTR, 64},
+ { NID_aes_128_ofb128, WD_CIPHER_AES, WD_CIPHER_OFB, 16},
+ { NID_aes_192_ofb128, WD_CIPHER_AES, WD_CIPHER_OFB, 16},
+ { NID_aes_256_ofb128, WD_CIPHER_AES, WD_CIPHER_OFB, 16},
+ { NID_aes_128_cfb128, WD_CIPHER_AES, WD_CIPHER_CFB, 16},
+ { NID_aes_192_cfb128, WD_CIPHER_AES, WD_CIPHER_CFB, 16},
+ { NID_aes_256_cfb128, WD_CIPHER_AES, WD_CIPHER_CFB, 16},
+ { NID_sm4_ofb128, WD_CIPHER_SM4, WD_CIPHER_OFB, 16},
+ { NID_sm4_cfb128, WD_CIPHER_SM4, WD_CIPHER_CFB, 16},
+ { NID_sm4_ecb, WD_CIPHER_SM4, WD_CIPHER_ECB, 16},
+ { NID_sm4_ctr, WD_CIPHER_SM4, WD_CIPHER_CTR, 16},
+};
+
+static int uadk_fetch_sw_cipher(struct cipher_priv_ctx *priv)
+{
+ if (priv->sw_cipher)
+ return 1;
+
+ switch (priv->nid) {
+ case NID_aes_128_cbc:
+ priv->sw_cipher = EVP_CIPHER_fetch(NULL, "AES-128-CBC", "provider=default");
+ case NID_aes_192_cbc:
+ priv->sw_cipher = EVP_CIPHER_fetch(NULL, "AES-192-CBC", "provider=default");
+ case NID_aes_256_cbc:
+ priv->sw_cipher = EVP_CIPHER_fetch(NULL, "AES-256-CBC", "provider=default");
+ case NID_aes_128_ecb:
+ priv->sw_cipher = EVP_CIPHER_fetch(NULL, "AES-128-ECB", "provider=default");
+ case NID_aes_192_ecb:
+ priv->sw_cipher = EVP_CIPHER_fetch(NULL, "AES-192-ECB", "provider=default");
+ case NID_aes_256_ecb:
+ priv->sw_cipher = EVP_CIPHER_fetch(NULL, "AES-256-ECB", "provider=default");
+ case NID_aes_128_xts:
+ priv->sw_cipher = EVP_CIPHER_fetch(NULL, "AES-128-XTS", "provider=default");
+ case NID_aes_256_xts:
+ priv->sw_cipher = EVP_CIPHER_fetch(NULL, "AES-256-XTS", "provider=default");
+ case NID_sm4_cbc:
+ priv->sw_cipher = EVP_CIPHER_fetch(NULL, "SM4-CBC", "provider=default");
+ case NID_sm4_ecb:
+ priv->sw_cipher = EVP_CIPHER_fetch(NULL, "SM4-ECB", "provider=default");
+ case NID_des_ede3_cbc:
+ priv->sw_cipher = EVP_CIPHER_fetch(NULL, "DES-EDE3-CBC", "provider=default");
+ case NID_des_ede3_ecb:
+ priv->sw_cipher = EVP_CIPHER_fetch(NULL, "DES-EDE3-ECB", "provider=default");
+ case NID_aes_128_ctr:
+ priv->sw_cipher = EVP_CIPHER_fetch(NULL, "AES-128-CTR", "provider=default");
+ case NID_aes_192_ctr:
+ priv->sw_cipher = EVP_CIPHER_fetch(NULL, "AES-192-CTR", "provider=default");
+ case NID_aes_256_ctr:
+ priv->sw_cipher = EVP_CIPHER_fetch(NULL, "AES-256-CTR", "provider=default");
+ case NID_aes_128_ofb128:
+ priv->sw_cipher = EVP_CIPHER_fetch(NULL, "AES-128-OFB", "provider=default");
+ case NID_aes_192_ofb128:
+ priv->sw_cipher = EVP_CIPHER_fetch(NULL, "AES-192-OFB", "provider=default");
+ case NID_aes_256_ofb128:
+ priv->sw_cipher = EVP_CIPHER_fetch(NULL, "AES-256-OFB", "provider=default");
+ case NID_aes_128_cfb128:
+ priv->sw_cipher = EVP_CIPHER_fetch(NULL, "AES-128-CFB", "provider=default");
+ case NID_aes_192_cfb128:
+ priv->sw_cipher = EVP_CIPHER_fetch(NULL, "AES-192-CFB", "provider=default");
+ case NID_aes_256_cfb128:
+ priv->sw_cipher = EVP_CIPHER_fetch(NULL, "AES-256-CFB", "provider=default");
+ case NID_sm4_ofb128:
+ priv->sw_cipher = EVP_CIPHER_fetch(NULL, "SM4-OFB", "provider=default");
+ case NID_sm4_cfb128:
+ priv->sw_cipher = EVP_CIPHER_fetch(NULL, "SM4-CFB", "provider=default");
+ case NID_sm4_ctr:
+ priv->sw_cipher = EVP_CIPHER_fetch(NULL, "SM4-CTR", "provider=default");
+ default:
+ break;
+ }
+
+ if (unlikely(priv->sw_cipher == NULL)) {
+ fprintf(stderr, "fail to fetch sw_cipher\n");
+ return 0;
+ }
+
+ return 1;
+}
+
+static int uadk_prov_cipher_sw_init(struct cipher_priv_ctx *priv,
+ const unsigned char *key,
+ const unsigned char *iv)
+{
+ if (!uadk_fetch_sw_cipher(priv))
+ return 0;
+
+ if (!EVP_CipherInit_ex2(priv->sw_ctx, priv->sw_cipher, key, iv,
+ priv->enc, NULL)) {
+ fprintf(stderr, "SW cipher init error!\n");
+ return 0;
+ }
+
+ return 1;
+}
+
+static int uadk_prov_cipher_soft_work(struct cipher_priv_ctx *priv, unsigned char *out,
+ const unsigned char *in, size_t len)
+{
+ int sw_final_len = 0;
+ int outlen = 0;
+
+ if (priv->sw_cipher == NULL)
+ return 0;
+
+ if (!EVP_CipherUpdate(priv->sw_ctx, out, &outlen, in, len)) {
+ fprintf(stderr, "EVP_CipherUpdate sw_ctx failed.\n");
+ return 0;
+ }
+
+ if (!EVP_CipherFinal_ex(priv->sw_ctx, out + outlen, &sw_final_len)) {
+ fprintf(stderr, "EVP_CipherFinal_ex sw_ctx failed.\n");
+ return 0;
+ }
+
+ return 1;
+}
+
+static int uadk_cipher_env_poll(void *ctx)
+{
+ __u64 rx_cnt = 0;
+ __u32 recv = 0;
+ /* Poll one packet currently */
+ int expt = 1;
+ int ret;
+
+ do {
+ ret = wd_cipher_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_prov_cipher_init(struct cipher_priv_ctx *priv,
+ const unsigned char *key, size_t keylen,
+ const unsigned char *iv, size_t ivlen)
+{
+ int cipher_counts = ARRAY_SIZE(cipher_info_table);
+ int ret, i;
+
+ if (iv)
+ memcpy(priv->iv, iv, ivlen);
+
+ for (i = 0; i < cipher_counts; i++) {
+ if (priv->nid == cipher_info_table[i].nid) {
+ priv->setup.alg = cipher_info_table[i].alg;
+ priv->setup.mode = cipher_info_table[i].mode;
+ priv->req.out_bytes = cipher_info_table[i].out_bytes;
+ break;
+ }
+ }
+
+ if (i == cipher_counts) {
+ fprintf(stderr, "failed to setup the private ctx.\n");
+ return 0;
+ }
+
+ if (key) {
+ memcpy(priv->key, key, keylen);
+ ret = uadk_prov_cipher_sw_init(priv, key, iv);
+ if (unlikely(ret != 1))
+ return 0;
+ }
+
+ priv->switch_threshold = SMALL_PACKET_OFFLOAD_THRESHOLD_DEFAULT;
+
+ return 1;
+}
+
+static void async_cb(struct wd_cipher_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);
+ }
+}
+
+/* Increment counter (128-bit int) by c */
+static void ctr_iv_inc(uint8_t *counter, __u32 c)
+{
+ uint32_t n = CTR_128BIT_COUNTER;
+ uint8_t *counter1 = counter;
+ __u32 c_value = c;
+
+ /*
+ * Since the counter has been increased 1 by the hardware,
+ * so the c need to decrease 1.
+ */
+ c_value -= 1;
+ do {
+ --n;
+ c_value += counter1[n];
+ counter1[n] = (uint8_t)c_value;
+ c_value >>= BYTE_BITS;
+ } while (n);
+}
+
+static void uadk_cipher_update_priv_ctx(struct cipher_priv_ctx *priv)
+{
+ __u16 iv_bytes = priv->req.iv_bytes;
+ int offset = priv->req.in_bytes - iv_bytes;
+ unsigned char K[IV_LEN] = {0};
+ int i;
+
+ switch (priv->setup.mode) {
+ case WD_CIPHER_CFB:
+ case WD_CIPHER_CBC:
+ if (priv->req.op_type == WD_CIPHER_ENCRYPTION)
+ memcpy(priv->iv, priv->req.dst + offset, iv_bytes);
+ else
+ memcpy(priv->iv, priv->req.src + offset, iv_bytes);
+
+ break;
+ case WD_CIPHER_OFB:
+ for (i = 0; i < IV_LEN; i++) {
+ K[i] = *((unsigned char *)priv->req.src + offset + i) ^
+ *((unsigned char *)priv->req.dst + offset + i);
+ }
+ memcpy(priv->iv, K, iv_bytes);
+ break;
+ case WD_CIPHER_CTR:
+ ctr_iv_inc(priv->iv, priv->req.in_bytes >> CTR_MODE_LEN_SHIFT);
+ break;
+ default:
+ break;
+ }
+}
+
+static int uadk_do_cipher_sync(struct cipher_priv_ctx *priv)
+{
+ int ret;
+
+ if (unlikely(priv->switch_flag == UADK_DO_SOFT))
+ return 0;
+
+ if (priv->switch_threshold >= priv->req.in_bytes)
+ return 0;
+
+ ret = wd_do_cipher_sync(priv->sess, &priv->req);
+ if (ret)
+ return 0;
+ return 1;
+}
+
+static int uadk_do_cipher_async(struct cipher_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_cipher_async(priv->sess, &priv->req);
+ if (ret < 0 && ret != -EBUSY) {
+ fprintf(stderr, "do sec cipher failed, switch to soft cipher.\n");
+ async_free_poll_task(op->idx, 0);
+ return 0;
+ }
+ } while (ret == -EBUSY);
+
+ ret = async_pause_job(priv, op, ASYNC_TASK_CIPHER, idx);
+ if (!ret)
+ return 0;
+ return 1;
+}
+
+static void uadk_prov_cipher_ctx_init(struct cipher_priv_ctx *priv)
+{
+ struct sched_params params = {0};
+ int ret;
+
+ priv->req.iv_bytes = priv->ivlen;
+ priv->req.iv = priv->iv;
+
+ if (priv->switch_flag == UADK_DO_SOFT)
+ return;
+
+ pthread_mutex_lock(&cipher_mutex);
+ if (prov.pid != getpid()) {
+ ret = wd_cipher_init2(priv->alg_name, 0, 0);
+ if (unlikely(ret)) {
+ priv->switch_flag = UADK_DO_SOFT;
+ pthread_mutex_unlock(&cipher_mutex);
+ fprintf(stderr, "uadk failed to init cipher HW!\n");
+ return;
+ }
+ prov.pid = getpid();
+ async_register_poll_fn(ASYNC_TASK_CIPHER, uadk_cipher_env_poll);
+ }
+ pthread_mutex_unlock(&cipher_mutex);
+
+ params.type = priv->req.op_type;
+ /* Use the default numa parameters */
+ params.numa_id = -1;
+ priv->setup.sched_param = &params;
+
+ if (!priv->sess) {
+ priv->sess = wd_cipher_alloc_sess(&priv->setup);
+ if (!priv->sess)
+ fprintf(stderr, "uadk failed to alloc session!\n");
+ }
+
+ ret = wd_cipher_set_key(priv->sess, priv->key, priv->keylen);
+ if (ret) {
+ wd_cipher_free_sess(priv->sess);
+ priv->sess = 0;
+ fprintf(stderr, "uadk failed to set key!\n");
+ }
+}
+
+static int uadk_prov_do_cipher(struct cipher_priv_ctx *priv, unsigned char *out,
+ const unsigned char *in, size_t inlen)
+{
+ struct async_op op;
+ int ret;
+
+ priv->req.src = (unsigned char *)in;
+ priv->req.in_bytes = inlen;
+ priv->req.dst = out;
+ priv->req.out_buf_bytes = inlen;
+
+ uadk_prov_cipher_ctx_init(priv);
+ ret = async_setup_async_event_notification(&op);
+ if (!ret) {
+ fprintf(stderr, "failed to setup async event notification.\n");
+ return 0;
+ }
+
+ if (op.job == NULL) {
+ /* Synchronous, only the synchronous mode supports soft computing */
+ ret = uadk_do_cipher_sync(priv);
+ if (!ret)
+ goto sync_err;
+ } else {
+ /*
+ * If the length of the input data
+ * does not reach to hardware computing threshold,
+ * directly switch to soft cipher.
+ */
+ if (priv->req.in_bytes <= priv->switch_threshold)
+ goto sync_err;
+
+ ret = uadk_do_cipher_async(priv, &op);
+ if (!ret)
+ goto out_notify;
+ }
+ uadk_cipher_update_priv_ctx(priv);
+
+ return 1;
+sync_err:
+ ret = uadk_prov_cipher_soft_work(priv, out, in, inlen);
+ if (ret != 1)
+ fprintf(stderr, "do soft ciphers failed.\n");
+out_notify:
+ async_clear_async_event_notification();
+ return ret;
+}
+
+void uadk_prov_destroy_cipher(void)
+{
+ pthread_mutex_lock(&cipher_mutex);
+ if (prov.pid == getpid()) {
+ wd_cipher_uninit2();
+ prov.pid = 0;
+ }
+ pthread_mutex_unlock(&cipher_mutex);
+}
+
+static OSSL_FUNC_cipher_encrypt_init_fn uadk_prov_cipher_einit;
+static OSSL_FUNC_cipher_decrypt_init_fn uadk_prov_cipher_dinit;
+static OSSL_FUNC_cipher_freectx_fn uadk_prov_cipher_freectx;
+static OSSL_FUNC_cipher_get_ctx_params_fn uadk_prov_cipher_get_ctx_params;
+static OSSL_FUNC_cipher_gettable_ctx_params_fn uadk_prov_cipher_gettable_ctx_params;
+static OSSL_FUNC_cipher_set_ctx_params_fn uadk_prov_cipher_set_ctx_params;
+static OSSL_FUNC_cipher_settable_ctx_params_fn uadk_prov_cipher_settable_ctx_params;
+
+static int uadk_prov_cipher_cipher(void *vctx, unsigned char *out, size_t *outl,
+ size_t outsize, const unsigned char *in,
+ size_t inl)
+{
+ struct cipher_priv_ctx *priv = (struct cipher_priv_ctx *)vctx;
+ int ret;
+
+ if (inl == 0) {
+ *outl = 0;
+ return 1;
+ }
+
+ if (outsize < inl) {
+ ERR_raise(ERR_LIB_PROV, PROV_R_OUTPUT_BUFFER_TOO_SMALL);
+ return 0;
+ }
+
+ ret = uadk_prov_do_cipher(priv, out, in, inl);
+ if (ret != 1)
+ return ret;
+
+ *outl = inl;
+ return 1;
+
+}
+
+static int uadk_prov_cipher_final(void *vctx, unsigned char *out,
+ size_t *outl, size_t outsize)
+{
+ *outl = 0;
+ return 1;
+}
+
+static int uadk_prov_cipher_update(void *vctx, unsigned char *out,
+ size_t *outl, size_t outsize,
+ const unsigned char *in, size_t inl)
+{
+ struct cipher_priv_ctx *priv = (struct cipher_priv_ctx *)vctx;
+ int ret;
+
+ if (inl == 0) {
+ *outl = 0;
+ return 1;
+ }
+
+ if (outsize < inl) {
+ ERR_raise(ERR_LIB_PROV, PROV_R_OUTPUT_BUFFER_TOO_SMALL);
+ return 0;
+ }
+
+ ret = uadk_prov_do_cipher(priv, out, in, inl);
+ if (ret != 1)
+ return ret;
+
+ *outl = inl;
+ return 1;
+}
+
+static int uadk_prov_cipher_einit(void *vctx, const unsigned char *key, size_t keylen,
+ const unsigned char *iv, size_t ivlen,
+ const OSSL_PARAM params[])
+{
+ struct cipher_priv_ctx *priv = (struct cipher_priv_ctx *)vctx;
+ int ret;
+
+ priv->req.op_type = WD_CIPHER_ENCRYPTION;
+ priv->enc = 1;
+
+ ret = uadk_prov_cipher_init(priv, key, keylen, iv, ivlen);
+ if (unlikely(ret != 1))
+ return 0;
+
+ return 1;
+}
+
+static int uadk_prov_cipher_dinit(void *vctx, const unsigned char *key, size_t keylen,
+ const unsigned char *iv, size_t ivlen,
+ const OSSL_PARAM params[])
+{
+ struct cipher_priv_ctx *priv = (struct cipher_priv_ctx *)vctx;
+ int ret;
+
+ priv->req.op_type = WD_CIPHER_DECRYPTION;
+ priv->enc = 0;
+
+ ret = uadk_prov_cipher_init(priv, key, keylen, iv, ivlen);
+ if (unlikely(ret != 1))
+ return 0;
+
+ return 1;
+}
+
+static const OSSL_PARAM uadk_prov_settable_ctx_params[] = {
+ OSSL_PARAM_size_t(OSSL_CIPHER_PARAM_KEYLEN, NULL),
+ OSSL_PARAM_END
+};
+
+const OSSL_PARAM *uadk_prov_cipher_settable_ctx_params(ossl_unused void *cctx,
+ ossl_unused void *provctx)
+{
+ return uadk_prov_settable_ctx_params;
+}
+
+static int uadk_prov_cipher_set_ctx_params(void *vctx, const OSSL_PARAM params[])
+{
+ struct cipher_priv_ctx *priv = (struct cipher_priv_ctx *)vctx;
+ const OSSL_PARAM *p;
+ int ret = 1;
+
+ if (params == NULL)
+ return 1;
+
+ p = OSSL_PARAM_locate_const(params, OSSL_CIPHER_PARAM_KEYLEN);
+ if (p != NULL) {
+ size_t keylen;
+
+ if (!OSSL_PARAM_get_size_t(p, &keylen)) {
+ ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_GET_PARAMETER);
+ return 0;
+ }
+ if (priv->keylen != keylen) {
+ ERR_raise(ERR_LIB_PROV, PROV_R_INVALID_KEY_LENGTH);
+ return 0;
+ }
+ }
+
+ return ret;
+}
+
+static int uadk_prov_cipher_get_ctx_params(void *vctx, OSSL_PARAM params[])
+{
+ struct cipher_priv_ctx *priv = (struct cipher_priv_ctx *)vctx;
+ OSSL_PARAM *p;
+
+ p = OSSL_PARAM_locate(params, OSSL_CIPHER_PARAM_KEYLEN);
+ if (p != NULL && !OSSL_PARAM_set_size_t(p, priv->keylen)) {
+ ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_SET_PARAMETER);
+ return 0;
+ }
+ p = OSSL_PARAM_locate(params, OSSL_CIPHER_PARAM_IVLEN);
+ if (p != NULL && !OSSL_PARAM_set_size_t(p, priv->ivlen)) {
+ ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_SET_PARAMETER);
+ return 0;
+ }
+ p = OSSL_PARAM_locate(params, OSSL_CIPHER_PARAM_IV);
+ if (p != NULL && !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 0;
+ }
+ p = OSSL_PARAM_locate(params, OSSL_CIPHER_PARAM_UPDATED_IV);
+ if (p != NULL && !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 0;
+ }
+ return 1;
+}
+
+static const OSSL_PARAM uadk_prov_default_ctx_params[] = {
+ OSSL_PARAM_size_t(OSSL_CIPHER_PARAM_KEYLEN, NULL),
+ OSSL_PARAM_size_t(OSSL_CIPHER_PARAM_IVLEN, NULL),
+ OSSL_PARAM_octet_string(OSSL_CIPHER_PARAM_IV, NULL, 0),
+ OSSL_PARAM_octet_string(OSSL_CIPHER_PARAM_UPDATED_IV, NULL, 0),
+ OSSL_PARAM_END
+};
+
+const OSSL_PARAM *uadk_prov_cipher_gettable_ctx_params(ossl_unused void *cctx,
+ ossl_unused void *provctx)
+{
+ return uadk_prov_default_ctx_params;
+}
+
+static const OSSL_PARAM cipher_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_int(OSSL_CIPHER_PARAM_CTS, NULL),
+ OSSL_PARAM_int(OSSL_CIPHER_PARAM_HAS_RAND_KEY, NULL),
+ OSSL_PARAM_END
+};
+
+static const OSSL_PARAM *uadk_prov_cipher_gettable_params(ossl_unused void *provctx)
+{
+ return cipher_known_gettable_params;
+}
+
+static int ossl_cipher_generic_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 != NULL && !OSSL_PARAM_set_uint(p, md)) {
+ ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_SET_PARAMETER);
+ return 0;
+ }
+ p = OSSL_PARAM_locate(params, OSSL_CIPHER_PARAM_CUSTOM_IV);
+ if (p != NULL && !OSSL_PARAM_set_int(p, (flags & PROV_CIPHER_FLAG_CUSTOM_IV) != 0)) {
+ ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_SET_PARAMETER);
+ return 0;
+ }
+ p = OSSL_PARAM_locate(params, OSSL_CIPHER_PARAM_KEYLEN);
+ if (p != NULL && !OSSL_PARAM_set_size_t(p, kbits)) {
+ ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_SET_PARAMETER);
+ return 0;
+ }
+ p = OSSL_PARAM_locate(params, OSSL_CIPHER_PARAM_BLOCK_SIZE);
+ if (p != NULL && !OSSL_PARAM_set_size_t(p, blkbits)) {
+ ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_SET_PARAMETER);
+ return 0;
+ }
+ p = OSSL_PARAM_locate(params, OSSL_CIPHER_PARAM_IVLEN);
+ if (p != NULL && !OSSL_PARAM_set_size_t(p, ivbits)) {
+ ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_SET_PARAMETER);
+ return 0;
+ }
+ return 1;
+}
+
+static void uadk_prov_cipher_freectx(void *ctx)
+{
+ struct cipher_priv_ctx *priv = (struct cipher_priv_ctx *)ctx;
+
+ EVP_CIPHER_free(priv->sw_cipher);
+ EVP_CIPHER_CTX_free(priv->sw_ctx);
+
+ if (priv->sess) {
+ wd_cipher_free_sess(priv->sess);
+ priv->sess = 0;
+ }
+ OPENSSL_clear_free(priv, sizeof(*priv));
+}
+
+#define UADK_CIPHER_DESCR(nm, blk_size, key_len, iv_len, \
+ flags, e_nid, algnm, mode) \
+static OSSL_FUNC_cipher_newctx_fn uadk_##nm##_newctx; \
+static void *uadk_##nm##_newctx(void *provctx) \
+{ \
+ struct cipher_priv_ctx *ctx = OPENSSL_zalloc(sizeof(*ctx)); \
+ \
+ if (ctx == NULL) \
+ return NULL; \
+ ctx->blksize = blk_size; \
+ ctx->keylen = key_len; \
+ ctx->ivlen = iv_len; \
+ ctx->nid = e_nid; \
+ ctx->sw_ctx = EVP_CIPHER_CTX_new(); \
+ if (ctx->sw_ctx == NULL) \
+ fprintf(stderr, "EVP_CIPHER_CTX_new failed.\n"); \
+ 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 ossl_cipher_generic_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_cipher_freectx }, \
+ { OSSL_FUNC_CIPHER_ENCRYPT_INIT, \
+ (void (*)(void))uadk_prov_cipher_einit }, \
+ { OSSL_FUNC_CIPHER_DECRYPT_INIT, \
+ (void (*)(void))uadk_prov_cipher_dinit }, \
+ { OSSL_FUNC_CIPHER_UPDATE, (void (*)(void))uadk_prov_cipher_update }, \
+ { OSSL_FUNC_CIPHER_FINAL, (void (*)(void))uadk_prov_cipher_final }, \
+ { OSSL_FUNC_CIPHER_CIPHER, (void (*)(void))uadk_prov_cipher_cipher }, \
+ { OSSL_FUNC_CIPHER_GET_PARAMS, \
+ (void (*)(void))uadk_##nm##_get_params }, \
+ { OSSL_FUNC_CIPHER_GETTABLE_PARAMS, \
+ (void (*)(void))uadk_prov_cipher_gettable_params }, \
+ { OSSL_FUNC_CIPHER_GET_CTX_PARAMS, \
+ (void (*)(void))uadk_prov_cipher_get_ctx_params }, \
+ { OSSL_FUNC_CIPHER_GETTABLE_CTX_PARAMS, \
+ (void (*)(void))uadk_prov_cipher_gettable_ctx_params }, \
+ { OSSL_FUNC_CIPHER_SET_CTX_PARAMS, \
+ (void (*)(void))uadk_prov_cipher_set_ctx_params }, \
+ { OSSL_FUNC_CIPHER_SETTABLE_CTX_PARAMS, \
+ (void (*)(void))uadk_prov_cipher_settable_ctx_params }, \
+ { 0, NULL } \
+}
+
+UADK_CIPHER_DESCR(aes_128_cbc, 16, 16, 16, 0, NID_aes_128_cbc, cbc(aes), EVP_CIPH_CBC_MODE);
+UADK_CIPHER_DESCR(aes_192_cbc, 16, 24, 16, 0, NID_aes_192_cbc, cbc(aes), EVP_CIPH_CBC_MODE);
+UADK_CIPHER_DESCR(aes_256_cbc, 16, 32, 16, 0, NID_aes_256_cbc, cbc(aes), EVP_CIPH_CBC_MODE);
+UADK_CIPHER_DESCR(aes_128_ecb, 16, 16, 0, 0, NID_aes_128_ecb, ecb(aes), EVP_CIPH_ECB_MODE);
+UADK_CIPHER_DESCR(aes_192_ecb, 16, 24, 0, 0, NID_aes_192_ecb, ecb(aes), EVP_CIPH_ECB_MODE);
+UADK_CIPHER_DESCR(aes_256_ecb, 16, 32, 0, 0, NID_aes_256_ecb, ecb(aes), EVP_CIPH_ECB_MODE);
+UADK_CIPHER_DESCR(aes_128_xts, 1, 32, 16, 0, NID_aes_128_xts, xts(aes), EVP_CIPH_XTS_MODE | EVP_CIPH_CUSTOM_IV);
+UADK_CIPHER_DESCR(aes_256_xts, 1, 64, 16, 0, NID_aes_256_xts, xts(aes), EVP_CIPH_XTS_MODE | EVP_CIPH_CUSTOM_IV);
+UADK_CIPHER_DESCR(sm4_cbc, 16, 16, 16, 0, NID_sm4_cbc, cbc(sm4), EVP_CIPH_CBC_MODE);
+UADK_CIPHER_DESCR(sm4_ecb, 16, 16, 16, 0, NID_sm4_ecb, ecb(sm4), EVP_CIPH_ECB_MODE);
+UADK_CIPHER_DESCR(des_ede3_cbc, 8, 24, 8, 0, NID_des_ede3_cbc, cbc(des), EVP_CIPH_CBC_MODE);
+UADK_CIPHER_DESCR(des_ede3_ecb, 8, 24, 0, 0, NID_des_ede3_ecb, ecb(des), EVP_CIPH_ECB_MODE);
+
+/* v3 */
+UADK_CIPHER_DESCR(aes_128_ctr, 1, 16, 16, 0, NID_aes_128_ctr, ctr(aes), EVP_CIPH_CTR_MODE);
+UADK_CIPHER_DESCR(aes_192_ctr, 1, 24, 16, 0, NID_aes_192_ctr, ctr(aes), EVP_CIPH_CTR_MODE);
+UADK_CIPHER_DESCR(aes_256_ctr, 1, 32, 16, 0, NID_aes_256_ctr, ctr(aes), EVP_CIPH_CTR_MODE);
+UADK_CIPHER_DESCR(aes_128_ofb128, 1, 16, 16, 0, NID_aes_128_ofb128, ofb(aes), EVP_CIPH_OFB_MODE);
+UADK_CIPHER_DESCR(aes_192_ofb128, 1, 24, 16, 0, NID_aes_192_ofb128, ofb(aes), EVP_CIPH_OFB_MODE);
+UADK_CIPHER_DESCR(aes_256_ofb128, 1, 32, 16, 0, NID_aes_256_ofb128, ofb(aes), EVP_CIPH_OFB_MODE);
+UADK_CIPHER_DESCR(aes_128_cfb128, 1, 16, 16, 0, NID_aes_128_cfb128, cfb(aes), EVP_CIPH_CFB_MODE);
+UADK_CIPHER_DESCR(aes_192_cfb128, 1, 24, 16, 0, NID_aes_192_cfb128, cfb(aes), EVP_CIPH_CFB_MODE);
+UADK_CIPHER_DESCR(aes_256_cfb128, 1, 32, 16, 0, NID_aes_256_cfb128, cfb(aes), EVP_CIPH_CFB_MODE);
+UADK_CIPHER_DESCR(sm4_ofb128, 1, 16, 16, 0, NID_sm4_ofb128, ofb(sm4), EVP_CIPH_OFB_MODE);
+UADK_CIPHER_DESCR(sm4_cfb128, 1, 16, 16, 0, NID_sm4_cfb128, cfb(sm4), EVP_CIPH_CFB_MODE);
+UADK_CIPHER_DESCR(sm4_ctr, 1, 16, 16, 0, NID_sm4_ctr, ctr(sm4), EVP_CIPH_CTR_MODE);
diff --git a/src/uadk_prov_init.c b/src/uadk_prov_init.c
index e363584..b59a4e8 100644
--- a/src/uadk_prov_init.c
+++ b/src/uadk_prov_init.c
@@ -52,6 +52,34 @@ const OSSL_ALGORITHM uadk_prov_digests[] = {
{ NULL, NULL, NULL }
};
+const OSSL_ALGORITHM uadk_prov_ciphers[] = {
+ { "AES-128-CBC", UADK_DEFAULT_PROPERTIES,
+ uadk_aes_128_cbc_functions, "uadk_provider aes-128-cbc" },
+ { "AES-192-CBC", UADK_DEFAULT_PROPERTIES,
+ uadk_aes_192_cbc_functions, "uadk_provider aes-192-cbc" },
+ { "AES-256-CBC", UADK_DEFAULT_PROPERTIES,
+ uadk_aes_256_cbc_functions, "uadk_provider aes-256-cbc" },
+ { "AES-128-ECB", UADK_DEFAULT_PROPERTIES,
+ uadk_aes_128_ecb_functions, "uadk_provider aes-128-ecb" },
+ { "AES-192-ECB", UADK_DEFAULT_PROPERTIES,
+ uadk_aes_192_ecb_functions, "uadk_provider aes-192-ecb" },
+ { "AES-256-ECB", UADK_DEFAULT_PROPERTIES,
+ uadk_aes_256_ecb_functions, "uadk_provider aes-256-ecb" },
+ { "AES-128-XTS", UADK_DEFAULT_PROPERTIES,
+ uadk_aes_128_xts_functions, "uadk_provider aes-128-xts" },
+ { "AES-256-XTS", UADK_DEFAULT_PROPERTIES,
+ uadk_aes_256_xts_functions, "uadk_provider aes-256-xts" },
+ { "SM4-CBC:SM4", UADK_DEFAULT_PROPERTIES,
+ uadk_sm4_cbc_functions, "uadk_provider sm4-cbc" },
+ { "SM4-ECB", UADK_DEFAULT_PROPERTIES,
+ uadk_sm4_ecb_functions, "uadk_provider sm4-ecb" },
+ { "DES-EDE3-CBC", UADK_DEFAULT_PROPERTIES,
+ uadk_des_ede3_cbc_functions, "uadk_provider des-ede3-cbc" },
+ { "DES-EDE3-ECB", UADK_DEFAULT_PROPERTIES,
+ uadk_des_ede3_ecb_functions, "uadk_provider des-ede3-ecb" },
+ { NULL, NULL, NULL }
+};
+
static const OSSL_ALGORITHM *p_prov_query(void *provctx, int operation_id,
int *no_cache)
{
@@ -60,6 +88,8 @@ static const OSSL_ALGORITHM *p_prov_query(void *provctx, int operation_id,
switch (operation_id) {
case OSSL_OP_DIGEST:
return uadk_prov_digests;
+ case OSSL_OP_CIPHER:
+ return uadk_prov_ciphers;
}
return NULL;
}
@@ -69,6 +99,7 @@ static void p_teardown(void *provctx)
struct p_uadk_ctx *ctx = (struct p_uadk_ctx *)provctx;
uadk_prov_destroy_digest();
+ uadk_prov_destroy_cipher();
OPENSSL_free(ctx);
}
--
2.25.1