diff --git a/0049-uadk_prov_init-remove-engine_uadk_id.patch b/0049-uadk_prov_init-remove-engine_uadk_id.patch new file mode 100644 index 0000000..8cba41a --- /dev/null +++ b/0049-uadk_prov_init-remove-engine_uadk_id.patch @@ -0,0 +1,198 @@ +From 82144d6f4802aae3a562fbdb1e51c4d35e2b32b2 Mon Sep 17 00:00:00 2001 +From: Zhangfei Gao +Date: Fri, 20 Oct 2023 07:53:45 +0000 +Subject: [PATCH 49/63] uadk_prov_init: remove engine_uadk_id. + +It looks strange to define engine_uadk_id in uadk_prov_init.c + +ASYNC_WAIT_CTX_set_wait_fd and ASYNC_WAIT_CTX_get_fd does not need to +use engine_uadk_id as the key, only if the key is the same. +So define uadk_async_key in the file itself. + +Signed-off-by: Zhangfei Gao +--- + src/uadk.h | 1 - + src/uadk_async.c | 17 +++++++++-------- + src/uadk_engine_init.c | 2 +- + src/uadk_prov_init.c | 1 - + src/v1/async/async_event.c | 19 ++++++++++--------- + 5 files changed, 20 insertions(+), 20 deletions(-) + +diff --git a/src/uadk.h b/src/uadk.h +index 30c099f..5a98feb 100644 +--- a/src/uadk.h ++++ b/src/uadk.h +@@ -28,7 +28,6 @@ enum { + HW_V3, + }; + +-extern const char *engine_uadk_id; + int uadk_e_bind_cipher(ENGINE *e); + void uadk_e_destroy_cipher(void); + int uadk_e_bind_digest(ENGINE *e); +diff --git a/src/uadk_async.c b/src/uadk_async.c +index c46976c..45f3918 100644 +--- a/src/uadk_async.c ++++ b/src/uadk_async.c +@@ -24,6 +24,7 @@ + #include "uadk.h" + #include "uadk_async.h" + ++static const char *uadk_async_key = "uadk_async_key"; + static struct async_poll_queue poll_queue; + + static int g_uadk_e_keep_polling; +@@ -61,15 +62,15 @@ int async_setup_async_event_notification(struct async_op *op) + if (waitctx == NULL) + return 0; + +- if (ASYNC_WAIT_CTX_get_fd(waitctx, engine_uadk_id, ++ if (ASYNC_WAIT_CTX_get_fd(waitctx, uadk_async_key, + &efd, &custom) == 0) { + efd = eventfd(0, EFD_NONBLOCK); + if (efd == -1) + return 0; + +- if (ASYNC_WAIT_CTX_set_wait_fd(waitctx, engine_uadk_id, efd, ++ if (ASYNC_WAIT_CTX_set_wait_fd(waitctx, uadk_async_key, efd, + custom, async_fd_cleanup) == 0) { +- async_fd_cleanup(waitctx, engine_uadk_id, efd, NULL); ++ async_fd_cleanup(waitctx, uadk_async_key, efd, NULL); + return 0; + } + } +@@ -99,13 +100,13 @@ int async_clear_async_event_notification(void) + return 0; + + if (num_add_fds > 0) { +- if (ASYNC_WAIT_CTX_get_fd(waitctx, engine_uadk_id, ++ if (ASYNC_WAIT_CTX_get_fd(waitctx, uadk_async_key, + &efd, &custom) == 0) + return 0; + +- async_fd_cleanup(waitctx, engine_uadk_id, efd, NULL); ++ async_fd_cleanup(waitctx, uadk_async_key, efd, NULL); + +- if (ASYNC_WAIT_CTX_clear_fd(waitctx, engine_uadk_id) == 0) ++ if (ASYNC_WAIT_CTX_clear_fd(waitctx, uadk_async_key) == 0) + return 0; + } + +@@ -272,7 +273,7 @@ int async_pause_job(void *ctx, struct async_op *op, enum task_type type, int id) + if (ASYNC_pause_job() == 0) + return 0; + +- ret = ASYNC_WAIT_CTX_get_fd(waitctx, engine_uadk_id, &efd, &custom); ++ ret = ASYNC_WAIT_CTX_get_fd(waitctx, uadk_async_key, &efd, &custom); + if (ret <= 0) + continue; + +@@ -299,7 +300,7 @@ int async_wake_job(ASYNC_JOB *job) + if (waitctx == NULL) + return 0; + +- ret = ASYNC_WAIT_CTX_get_fd(waitctx, engine_uadk_id, &efd, &custom); ++ ret = ASYNC_WAIT_CTX_get_fd(waitctx, uadk_async_key, &efd, &custom); + if (ret > 0) { + if (write(efd, &buf, sizeof(uint64_t)) == -1) + fprintf(stderr, "failed to write to fd: %d - error: %d\n", efd, errno); +diff --git a/src/uadk_engine_init.c b/src/uadk_engine_init.c +index e2aa392..cf54360 100644 +--- a/src/uadk_engine_init.c ++++ b/src/uadk_engine_init.c +@@ -35,7 +35,7 @@ + #define UADK_CMD_ENABLE_ECC_ENV (ENGINE_CMD_BASE + 4) + + /* Constants used when creating the ENGINE */ +-const char *engine_uadk_id = "uadk_engine"; ++static const char *engine_uadk_id = "uadk_engine"; + static const char *engine_uadk_name = "uadk hardware engine support"; + + static int uadk_cipher; +diff --git a/src/uadk_prov_init.c b/src/uadk_prov_init.c +index 2bde080..9b2c190 100644 +--- a/src/uadk_prov_init.c ++++ b/src/uadk_prov_init.c +@@ -28,7 +28,6 @@ + #include "uadk_async.h" + #include "uadk_prov.h" + +-const char *engine_uadk_id = "uadk_provider"; + static const char UADK_DEFAULT_PROPERTIES[] = "provider=uadk_provider"; + static OSSL_PROVIDER *prov; + +diff --git a/src/v1/async/async_event.c b/src/v1/async/async_event.c +index 245c269..c843bcf 100644 +--- a/src/v1/async/async_event.c ++++ b/src/v1/async/async_event.c +@@ -35,7 +35,8 @@ + + #include "async_event.h" + #include "../utils/engine_log.h" +-#include "../../uadk.h" ++ ++static const char *uadk_async_key = "uadk_async_key"; + + static void async_fd_cleanup(ASYNC_WAIT_CTX *ctx, const void *key, OSSL_ASYNC_FD readfd, void *custom) + { +@@ -66,7 +67,7 @@ int async_setup_async_event_notification_v1(int jobStatus) + return 0; + } + +- if (ASYNC_WAIT_CTX_get_fd(waitctx, engine_uadk_id, &efd, ++ if (ASYNC_WAIT_CTX_get_fd(waitctx, uadk_async_key, &efd, + &custom) == 0) { + efd = eventfd(0, EFD_NONBLOCK); + if (efd == -1) { +@@ -74,10 +75,10 @@ int async_setup_async_event_notification_v1(int jobStatus) + return 0; + } + +- if (ASYNC_WAIT_CTX_set_wait_fd(waitctx, engine_uadk_id, efd, ++ if (ASYNC_WAIT_CTX_set_wait_fd(waitctx, uadk_async_key, efd, + custom, async_fd_cleanup) == 0) { + US_ERR("set wait fd error."); +- async_fd_cleanup(waitctx, engine_uadk_id, efd, NULL); ++ async_fd_cleanup(waitctx, uadk_async_key, efd, NULL); + return 0; + } + } +@@ -111,14 +112,14 @@ int async_clear_async_event_notification_v1(void) + } + + if (num_add_fds > 0) { +- if (ASYNC_WAIT_CTX_get_fd(waitctx, engine_uadk_id, &efd, &custom) == 0) { ++ if (ASYNC_WAIT_CTX_get_fd(waitctx, uadk_async_key, &efd, &custom) == 0) { + US_ERR("no fd."); + return 0; + } + +- async_fd_cleanup(waitctx, engine_uadk_id, efd, NULL); ++ async_fd_cleanup(waitctx, uadk_async_key, efd, NULL); + +- if (ASYNC_WAIT_CTX_clear_fd(waitctx, engine_uadk_id) == 0) { ++ if (ASYNC_WAIT_CTX_clear_fd(waitctx, uadk_async_key) == 0) { + US_ERR("clear fd error."); + return 0; + } +@@ -148,7 +149,7 @@ int async_pause_job_v1(volatile ASYNC_JOB *job, int jobStatus) + return ret; + } + +- ret = ASYNC_WAIT_CTX_get_fd(waitctx, engine_uadk_id, &efd, &custom); ++ ret = ASYNC_WAIT_CTX_get_fd(waitctx, uadk_async_key, &efd, &custom); + if (ret > 0) { + if (read(efd, &buf, sizeof(uint64_t)) == -1) { + if (errno != EAGAIN) +@@ -178,7 +179,7 @@ int async_wake_job_v1(volatile ASYNC_JOB *job, int jobStatus) + return ret; + } + +- ret = ASYNC_WAIT_CTX_get_fd(waitctx, engine_uadk_id, &efd, &custom); ++ ret = ASYNC_WAIT_CTX_get_fd(waitctx, uadk_async_key, &efd, &custom); + if (ret > 0) { + if (write(efd, &buf, sizeof(uint64_t)) == -1) + US_ERR("Failed to write to fd: %d - error: %d\n", efd, errno); +-- +2.25.1 + diff --git a/0050-uadk_prov-reuse-OSSL_OP_STORE-from-default-provider.patch b/0050-uadk_prov-reuse-OSSL_OP_STORE-from-default-provider.patch new file mode 100644 index 0000000..87015c0 --- /dev/null +++ b/0050-uadk_prov-reuse-OSSL_OP_STORE-from-default-provider.patch @@ -0,0 +1,161 @@ +From db09ea12d7a95247022f8907b3321c3cb4b42900 Mon Sep 17 00:00:00 2001 +From: Zhangfei Gao +Date: Fri, 20 Oct 2023 08:46:18 +0000 +Subject: [PATCH 50/63] uadk_prov: reuse OSSL_OP_STORE from default provider + +The store func is provided in default provider, so "-provider default" +is required. otherwise errors reported: + +Could not open file or uri for loading private key from privatekey1.pem +2020D5BEFFFF0000:error:16000069:STORE routines:ossl_store_get0_loader_int:\ + unregistered scheme:crypto/store/store_register.c:237:scheme=file +2020D5BEFFFF0000:error:1608010C:STORE routines:inner_loader_fetch: \ + unsupported:crypto/store/store_meth.c:356:No store loader found. \ + For standard store loaders you need at least one of the default or base \ + providers available. Did you forget to load them? Info: \ + Global default library context, Scheme (file : 0), Properties () + +Instead, uadk_provider can provide OSSL_OP_STORE by reusing +the default provider's prov->query_operation + +Signed-off-by: Zhangfei Gao +--- + src/uadk_prov.h | 62 ++++++++++++++++++++++++++++++++++++++++++++ + src/uadk_prov_init.c | 2 ++ + src/uadk_prov_rsa.c | 4 +-- + test/sanity_test.sh | 6 ++--- + 4 files changed, 68 insertions(+), 6 deletions(-) + +diff --git a/src/uadk_prov.h b/src/uadk_prov.h +index efb29ee..01e799e 100644 +--- a/src/uadk_prov.h ++++ b/src/uadk_prov.h +@@ -18,6 +18,68 @@ + #ifndef UADK_PROV_H + #define UADK_PROV_H + ++typedef int CRYPTO_REF_COUNT; ++ ++struct ossl_provider_st { ++ /* Flag bits */ ++ unsigned int flag_initialized:1; ++ unsigned int flag_activated:1; ++ unsigned int flag_fallback:1; /* Can be used as fallback */ ++ ++ /* Getting and setting the flags require synchronization */ ++ CRYPTO_RWLOCK *flag_lock; ++ ++ /* OpenSSL library side data */ ++ CRYPTO_REF_COUNT refcnt; ++ CRYPTO_RWLOCK *refcnt_lock; /* For the ref counter */ ++ int activatecnt; ++ char *name; ++ char *path; ++ void *module; ++ OSSL_provider_init_fn *init_function; ++ ++ STACK_OF(INFOPAIR) * parameters; ++ OSSL_LIB_CTX *libctx; /* The library context this instance is in */ ++ struct provider_store_st *store; /* The store this instance belongs to */ ++#ifndef FIPS_MODULE ++ /* ++ * In the FIPS module inner provider, this isn't needed, since the ++ * error upcalls are always direct calls to the outer provider. ++ */ ++ int error_lib; /* ERR library number, one for each provider */ ++# ifndef OPENSSL_NO_ERR ++ char *error_strings; /* Copy of what the provider gives us */ ++# endif ++#endif ++ ++ /* Provider side functions */ ++ OSSL_FUNC_provider_teardown_fn * teardown; ++ OSSL_FUNC_provider_gettable_params_fn *gettable_params; ++ OSSL_FUNC_provider_get_params_fn *get_params; ++ OSSL_FUNC_provider_get_capabilities_fn *get_capabilities; ++ OSSL_FUNC_provider_self_test_fn *self_test; ++ OSSL_FUNC_provider_query_operation_fn *query_operation; ++ OSSL_FUNC_provider_unquery_operation_fn *unquery_operation; ++ ++ /* ++ * Cache of bit to indicate of query_operation() has been called on ++ * a specific operation or not. ++ */ ++ unsigned char *operation_bits; ++ size_t operation_bits_sz; ++ CRYPTO_RWLOCK *opbits_lock; ++ ++#ifndef FIPS_MODULE ++ /* Whether this provider is the child of some other provider */ ++ const OSSL_CORE_HANDLE * handle; ++ unsigned int ischild:1; ++#endif ++ ++ /* Provider side data */ ++ void *provctx; ++ const OSSL_DISPATCH *dispatch; ++}; ++ + struct uadk_prov_ctx { + const OSSL_CORE_HANDLE *handle; + OSSL_LIB_CTX *libctx; +diff --git a/src/uadk_prov_init.c b/src/uadk_prov_init.c +index 9b2c190..fc09b64 100644 +--- a/src/uadk_prov_init.c ++++ b/src/uadk_prov_init.c +@@ -120,6 +120,8 @@ static const OSSL_ALGORITHM *uadk_query(void *provctx, int operation_id, + return uadk_prov_keymgmt; + case OSSL_OP_ASYM_CIPHER: + return uadk_prov_asym_cipher; ++ case OSSL_OP_STORE: ++ return prov->query_operation(provctx, operation_id, no_cache); + } + return NULL; + } +diff --git a/src/uadk_prov_rsa.c b/src/uadk_prov_rsa.c +index a342e92..cd9b1e1 100644 +--- a/src/uadk_prov_rsa.c ++++ b/src/uadk_prov_rsa.c +@@ -220,7 +220,7 @@ struct rsa_st { + /* Be careful using this if the RSA structure is shared */ + CRYPTO_EX_DATA ex_data; + +- int references; //CRYPTO_REF_COUNT references; ++ CRYPTO_REF_COUNT references; + int flags; + /* Used to cache montgomery values */ + BN_MONT_CTX *_method_mod_n; +@@ -235,8 +235,6 @@ struct rsa_st { + + typedef struct rsa_st RSA; + +-typedef int CRYPTO_REF_COUNT; +- + struct evp_signature_st { + int name_id; + char *type_name; +diff --git a/test/sanity_test.sh b/test/sanity_test.sh +index 6a37014..5b61da3 100755 +--- a/test/sanity_test.sh ++++ b/test/sanity_test.sh +@@ -78,14 +78,14 @@ if [[ $signature_algs =~ "uadk_provider" ]]; then + openssl speed -provider $engine_id -async_jobs 1 rsa4096 + + openssl genrsa -out prikey.pem -provider $engine_id 1024 +- openssl rsa -in prikey.pem -pubout -out pubkey.pem -provider $engine_id -provider default ++ openssl rsa -in prikey.pem -pubout -out pubkey.pem -provider $engine_id + echo "Content to be encrypted" > plain.txt + + openssl pkeyutl -encrypt -in plain.txt -inkey pubkey.pem -pubin -out enc.txt \ +- -pkeyopt rsa_padding_mode:pkcs1 -provider uadk_provider -provider default ++ -pkeyopt rsa_padding_mode:pkcs1 -provider $engine_id + + openssl pkeyutl -decrypt -in enc.txt -inkey prikey.pem -out dec.txt \ +- -pkeyopt rsa_padding_mode:pkcs1 -provider $engine_id -provider default ++ -pkeyopt rsa_padding_mode:pkcs1 -provider $engine_id + fi + + if [[ $version =~ "1.1.1" ]]; then +-- +2.25.1 + diff --git a/0051-uadk-add-uadk_prov_dh.patch b/0051-uadk-add-uadk_prov_dh.patch new file mode 100644 index 0000000..f9f2c62 --- /dev/null +++ b/0051-uadk-add-uadk_prov_dh.patch @@ -0,0 +1,1988 @@ +From 2f367a44752241dacd01814632d6fbc8ba9e9710 Mon Sep 17 00:00:00 2001 +From: Zhangfei Gao +Date: Mon, 23 Oct 2023 03:08:53 +0000 +Subject: [PATCH 51/63] uadk: add uadk_prov_dh + +Two funcs are supported +key generation, ie. keymgmt +key exchange, ie. keyexch + +Test: +openssl dhparam -out dhparam.pem 2048 + +openssl genpkey -paramfile dhparam.pem -out privatekey1.pem \ + -provider uadk_provider +openssl genpkey -paramfile dhparam.pem -out privatekey2.pem \ + -provider uadk_provider + +openssl pkey -in privatekey1.pem -pubout -out publickey1.pem \ + -provider uadk_provider +openssl pkey -in privatekey2.pem -pubout -out publickey2.pem \ + -provider uadk_provider + +openssl pkeyutl -derive -inkey privatekey1.pem -peerkey publickey2.pem \ + -out secret1.bin -provider uadk_provider +openssl pkeyutl -derive -inkey privatekey2.pem -peerkey publickey1.pem \ + -out secret2.bin -provider uadk_provider + +cmp secret1.bin secret2.bin + +Signed-off-by: Zhangfei Gao +--- + src/Makefile.am | 2 +- + src/uadk_prov.h | 4 + + src/uadk_prov_dh.c | 1863 ++++++++++++++++++++++++++++++++++++++++++ + src/uadk_prov_init.c | 21 +- + 4 files changed, 1883 insertions(+), 7 deletions(-) + create mode 100644 src/uadk_prov_dh.c + +diff --git a/src/Makefile.am b/src/Makefile.am +index 9d5102a..668ba13 100644 +--- a/src/Makefile.am ++++ b/src/Makefile.am +@@ -52,7 +52,7 @@ endif #WD_KAE + + uadk_provider_la_SOURCES=uadk_prov_init.c uadk_async.c uadk_utils.c \ + uadk_prov_digest.c uadk_prov_cipher.c \ +- uadk_prov_rsa.c ++ uadk_prov_rsa.c uadk_prov_dh.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 01e799e..718e78c 100644 +--- a/src/uadk_prov.h ++++ b/src/uadk_prov.h +@@ -117,7 +117,11 @@ extern const OSSL_DISPATCH uadk_rsa_signature_functions[]; + extern const OSSL_DISPATCH uadk_rsa_keymgmt_functions[]; + extern const OSSL_DISPATCH uadk_rsa_asym_cipher_functions[]; + ++extern const OSSL_DISPATCH uadk_dh_keymgmt_functions[]; ++extern const OSSL_DISPATCH uadk_dh_keyexch_functions[]; ++ + void uadk_prov_destroy_digest(void); + void uadk_prov_destroy_cipher(void); + void uadk_prov_destroy_rsa(void); ++void uadk_prov_destroy_dh(void); + #endif +diff --git a/src/uadk_prov_dh.c b/src/uadk_prov_dh.c +new file mode 100644 +index 0000000..cf84cb9 +--- /dev/null ++++ b/src/uadk_prov_dh.c +@@ -0,0 +1,1863 @@ ++/* ++ * 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 ++#include ++#include ++#include ++#include ++#include "uadk.h" ++#include "uadk_async.h" ++#include "uadk_prov.h" ++ ++#define DH768BITS 768 ++#define DH1024BITS 1024 ++#define DH1536BITS 1536 ++#define DH2048BITS 2048 ++#define DH3072BITS 3072 ++#define DH4096BITS 4096 ++#define UADK_DH_MAX_MODULE_BIT 4096 ++#define DH_GENERATOR_2 2 ++#define DH_GENERATOR_5 5 ++#define CHAR_BIT_SIZE 3 ++#define DH_PARAMS_CNT 3 ++#define CTX_MODE_NUM 2 ++#define UN_SET 0 ++#define IS_SET 1 ++#define CTX_ASYNC 1 ++#define CTX_SYNC 0 ++#define CTX_NUM 2 ++#define UADK_DO_SOFT (-0xE0) ++#define UADK_E_SUCCESS 1 ++#define UADK_E_FAIL 0 ++#define UADK_E_POLL_SUCCESS 0 ++#define UADK_E_POLL_FAIL (-1) ++#define UADK_E_INIT_SUCCESS 0 ++#define ENV_ENABLED 1 ++#define KEY_GEN_BY_ENGINE 1 ++ ++struct evp_keyexch_st { ++ int name_id; ++ char *type_name; ++ const char *description; ++ OSSL_PROVIDER *prov; ++ CRYPTO_REF_COUNT refcnt; ++ ++ OSSL_FUNC_keyexch_newctx_fn *newctx; ++ OSSL_FUNC_keyexch_init_fn *init; ++ OSSL_FUNC_keyexch_set_peer_fn *set_peer; ++ OSSL_FUNC_keyexch_derive_fn *derive; ++ OSSL_FUNC_keyexch_freectx_fn *freectx; ++ OSSL_FUNC_keyexch_dupctx_fn *dupctx; ++ OSSL_FUNC_keyexch_set_ctx_params_fn *set_ctx_params; ++ OSSL_FUNC_keyexch_settable_ctx_params_fn *settable_ctx_params; ++ OSSL_FUNC_keyexch_get_ctx_params_fn *get_ctx_params; ++ OSSL_FUNC_keyexch_gettable_ctx_params_fn *gettable_ctx_params; ++} /* EVP_KEYEXCH */; ++ ++typedef struct ffc_params_st { ++ /* Primes */ ++ BIGNUM *p; ++ BIGNUM *q; ++ /* Generator */ ++ BIGNUM *g; ++ /* DH X9.42 Optional Subgroup factor j >= 2 where p = j * q + 1 */ ++ BIGNUM *j; ++ ++ /* Required for FIPS186_4 validation of p, q and optionally canonical g */ ++ unsigned char *seed; ++ /* If this value is zero the hash size is used as the seed length */ ++ size_t seedlen; ++ /* Required for FIPS186_4 validation of p and q */ ++ int pcounter; ++ int nid; /* The identity of a named group */ ++ ++ /* ++ * Required for FIPS186_4 generation & validation of canonical g. ++ * It uses unverifiable g if this value is -1. ++ */ ++ int gindex; ++ int h; /* loop counter for unverifiable g */ ++ ++ unsigned int flags; ++ /* ++ * The digest to use for generation or validation. If this value is NULL, ++ * then the digest is chosen using the value of N. ++ */ ++ const char *mdname; ++ const char *mdprops; ++#if OPENSSL_VERSION_NUMBER >= 0x30000060 ++ /* Default key length for known named groups according to RFC7919 */ ++ int keylength; ++#endif ++} FFC_PARAMS; ++ ++struct dh_st { ++ /* ++ * This first argument is used to pick up errors when a DH is passed ++ * instead of a EVP_PKEY ++ */ ++ int pad; ++ int version; ++ FFC_PARAMS params; ++ /* max generated private key length (can be less than len(q)) */ ++ int32_t length; ++ BIGNUM *pub_key; /* g^x % p */ ++ BIGNUM *priv_key; /* x */ ++ int flags; ++ BN_MONT_CTX *method_mont_p; ++ CRYPTO_REF_COUNT references; ++#ifndef FIPS_MODULE ++ CRYPTO_EX_DATA ex_data; ++ ENGINE *engine; ++#endif ++ OSSL_LIB_CTX * libctx; ++ const DH_METHOD *meth; ++ CRYPTO_RWLOCK *lock; ++ ++ /* Provider data */ ++ size_t dirty_cnt; /* If any key material changes, increment this */ ++}; /* DH */ ++ ++struct dh_method { ++ char *name; ++ /* Methods here */ ++ int (*generate_key)(DH *dh); ++ int (*compute_key)(unsigned char *key, const BIGNUM *pub_key, DH *dh); ++ ++ /* Can be null */ ++ int (*bn_mod_exp)(const DH *dh, BIGNUM *r, const BIGNUM *a, ++ const BIGNUM *p, const BIGNUM *m, BN_CTX *ctx, ++ BN_MONT_CTX *m_ctx); ++ int (*init)(DH *dh); ++ int (*finish)(DH *dh); ++ int flags; ++ char *app_data; ++ /* If this is non-NULL, it will be used to generate parameters */ ++ int (*generate_params)(DH *dh, int prime_len, int generator, ++ BN_GENCB *cb); ++}; ++ ++#define FFC_UNVERIFIABLE_GINDEX -1 ++#define FFC_PARAM_FLAG_VALIDATE_PQ 0x01 ++#define FFC_PARAM_FLAG_VALIDATE_G 0x02 ++#define FFC_PARAM_FLAG_VALIDATE_PQG \ ++ (FFC_PARAM_FLAG_VALIDATE_PQ | FFC_PARAM_FLAG_VALIDATE_G) ++ ++struct uadk_dh_sess { ++ handle_t sess; ++ struct wd_dh_sess_setup setup; ++ struct wd_dh_req req; ++ DH *alg; ++ __u16 key_size; ++ /* key_flag: 0 - key is defined by user, 1 - key is generated by engine */ ++ int key_flag; ++}; ++ ++struct dh_res { ++ int pid; ++} g_dh_res; ++ ++static pthread_mutex_t dh_mutex = PTHREAD_MUTEX_INITIALIZER; ++ ++/* ++ * This type is only really used to handle some legacy related functionality. ++ * If you need to use other KDF's (such as SSKDF) just use PROV_DH_KDF_NONE ++ * here and then create and run a KDF after the key is derived. ++ * Note that X942 has 2 variants of key derivation: ++ * (1) DH_KDF_X9_42_ASN1 - which contains an ANS1 encoded object that has ++ * the counter embedded in it. ++ * (2) DH_KDF_X941_CONCAT - which is the same as ECDH_X963_KDF (which can be ++ * done by creating a "X963KDF". ++ */ ++enum kdf_type { ++ PROV_DH_KDF_NONE = 0, ++ PROV_DH_KDF_X9_42_ASN1 ++}; ++ ++/* ++ * What's passed as an actual key is defined by the KEYMGMT interface. ++ * We happen to know that our KEYMGMT simply passes DH structures, so ++ * we use that here too. ++ */ ++ ++typedef struct { ++ OSSL_LIB_CTX *libctx; ++ DH *dh; ++ DH *dhpeer; ++ unsigned int pad : 1; ++ ++ /* DH KDF */ ++ /* KDF (if any) to use for DH */ ++ 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; ++ char *kdf_cekalg; ++} UADK_PROV_DH_CTX; ++ ++struct dh_gen_ctx { ++ OSSL_LIB_CTX *libctx; ++ ++ FFC_PARAMS *ffc_params; ++ int selection; ++ /* All these parameters are used for parameter generation only */ ++ /* If there is a group name then the remaining parameters are not needed */ ++ int group_nid; ++ size_t pbits; ++ size_t qbits; ++ unsigned char *seed; /* optional FIPS186-4 param for testing */ ++ size_t seedlen; ++ int gindex; /* optional FIPS186-4 generator index (ignored if -1) */ ++ int gen_type; /* see dhtype2id */ ++ int generator; /* Used by DH_PARAMGEN_TYPE_GENERATOR in non fips mode only */ ++ int pcounter; ++ int hindex; ++ int priv_len; ++ ++ char *mdname; ++ char *mdprops; ++ OSSL_CALLBACK *cb; ++ void *cbarg; ++ int dh_type; ++}; ++ ++typedef struct { ++ int id; /* libcrypto internal */ ++ int name_id; ++ char *type_name; ++ const char *description; ++ OSSL_PROVIDER *prov; ++ ++ int refcnt; ++ void *lock; ++ ++ /* Constructor(s), destructor, information */ ++ OSSL_FUNC_keymgmt_new_fn *new; ++ OSSL_FUNC_keymgmt_free_fn *free; ++ OSSL_FUNC_keymgmt_get_params_fn *get_params; ++ OSSL_FUNC_keymgmt_gettable_params_fn *gettable_params; ++ OSSL_FUNC_keymgmt_set_params_fn *set_params; ++ OSSL_FUNC_keymgmt_settable_params_fn *settable_params; ++ ++ /* Generation, a complex constructor */ ++ OSSL_FUNC_keymgmt_gen_init_fn *gen_init; ++ OSSL_FUNC_keymgmt_gen_set_template_fn *gen_set_template; ++ OSSL_FUNC_keymgmt_gen_set_params_fn *gen_set_params; ++ OSSL_FUNC_keymgmt_gen_settable_params_fn *gen_settable_params; ++ OSSL_FUNC_keymgmt_gen_fn *gen; ++ OSSL_FUNC_keymgmt_gen_cleanup_fn *gen_cleanup; ++ OSSL_FUNC_keymgmt_load_fn *load; ++ ++ /* Key object checking */ ++ OSSL_FUNC_keymgmt_query_operation_name_fn *query_operation_name; ++ OSSL_FUNC_keymgmt_has_fn *has; ++ OSSL_FUNC_keymgmt_validate_fn *validate; ++ OSSL_FUNC_keymgmt_match_fn *match; ++ ++ /* Import and export routines */ ++ OSSL_FUNC_keymgmt_import_fn *import; ++ OSSL_FUNC_keymgmt_import_types_fn *import_types; ++ OSSL_FUNC_keymgmt_export_fn *export; ++ OSSL_FUNC_keymgmt_export_types_fn *export_types; ++ OSSL_FUNC_keymgmt_dup_fn *dup; ++ ++} UADK_DH_KEYMGMT; ++ ++static inline int CRYPTO_UP_REF(int *val, int *ret, ossl_unused void *lock) ++{ ++ *ret = __atomic_fetch_add(val, 1, __ATOMIC_RELAXED) + 1; ++ return 1; ++} ++ ++static inline int 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; ++} ++ ++static FFC_PARAMS *uadk_dh_get0_params(DH *dh) ++{ ++ return &dh->params; ++} ++ ++static int uadk_DH_size(const DH *dh) ++{ ++ if (dh->params.p != NULL) ++ return BN_num_bytes(dh->params.p); ++ return -1; ++} ++ ++static void uadk_DH_get0_key(const DH *dh, const BIGNUM **pub_key, ++ const BIGNUM **priv_key) ++{ ++ if (pub_key != NULL) ++ *pub_key = dh->pub_key; ++ if (priv_key != NULL) ++ *priv_key = dh->priv_key; ++} ++ ++static int uadk_DH_set0_key(DH *dh, BIGNUM *pub_key, BIGNUM *priv_key) ++{ ++ if (pub_key != NULL) { ++ BN_clear_free(dh->pub_key); ++ dh->pub_key = pub_key; ++ } ++ ++ if (priv_key != NULL) { ++ BN_clear_free(dh->priv_key); ++ dh->priv_key = priv_key; ++ } ++ ++ dh->dirty_cnt++; ++ return 1; ++} ++ ++static FFC_PARAMS *uadk_ossl_dh_get0_params(DH *dh) ++{ ++ return &dh->params; ++} ++ ++static const BIGNUM *uadk_DH_get0_p(const DH *dh) ++{ ++ return dh->params.p; ++} ++ ++static int ossl_ffc_params_set_seed(FFC_PARAMS *params, ++ const unsigned char *seed, size_t seedlen) ++{ ++ if (params == NULL) ++ return 0; ++ ++ if (params->seed != NULL) { ++ if (params->seed == seed) ++ return 1; ++ OPENSSL_free(params->seed); ++ } ++ ++ if (seed != NULL && seedlen > 0) { ++ params->seed = OPENSSL_memdup(seed, seedlen); ++ if (params->seed == NULL) ++ return 0; ++ params->seedlen = seedlen; ++ } else { ++ params->seed = NULL; ++ params->seedlen = 0; ++ } ++ return 1; ++} ++ ++static int ffc_bn_cpy(BIGNUM **dst, const BIGNUM *src) ++{ ++ BIGNUM *a; ++ ++ /* ++ * If source is read only just copy the pointer, so ++ * we don't have to reallocate it. ++ */ ++ if (src == NULL) ++ a = NULL; ++ else if (BN_get_flags(src, BN_FLG_STATIC_DATA) ++ && !BN_get_flags(src, BN_FLG_MALLOCED)) ++ a = (BIGNUM *)src; ++ else { ++ a = BN_dup(src); ++ if (a == NULL) ++ return 0; ++ } ++ ++ BN_clear_free(*dst); ++ *dst = a; ++ return 1; ++} ++ ++static int ossl_ffc_params_copy(FFC_PARAMS *dst, const FFC_PARAMS *src) ++{ ++ if (!ffc_bn_cpy(&dst->p, src->p) ++ || !ffc_bn_cpy(&dst->g, src->g) ++ || !ffc_bn_cpy(&dst->q, src->q) ++ || !ffc_bn_cpy(&dst->j, src->j)) ++ return 0; ++ ++ OPENSSL_free(dst->seed); ++ dst->seedlen = src->seedlen; ++ if (src->seed != NULL) { ++ dst->seed = OPENSSL_memdup(src->seed, src->seedlen); ++ if (dst->seed == NULL) ++ return 0; ++ } else { ++ dst->seed = NULL; ++ } ++ dst->nid = src->nid; ++ dst->pcounter = src->pcounter; ++ dst->h = src->h; ++ dst->gindex = src->gindex; ++ dst->flags = src->flags; ++ return 1; ++} ++ ++static const BIGNUM *uadk_DH_get0_q(const DH *dh) ++{ ++ return dh->params.q; ++} ++ ++static long uadk_DH_get_length(const DH *dh) ++{ ++ return dh->length; ++} ++ ++static void ossl_ffc_params_get0_pqg(const FFC_PARAMS *d, const BIGNUM **p, ++ const BIGNUM **q, const BIGNUM **g) ++{ ++ if (p != NULL) ++ *p = d->p; ++ if (q != NULL) ++ *q = d->q; ++ if (g != NULL) ++ *g = d->g; ++} ++ ++static void uadk_DH_get0_pqg(const DH *dh, const BIGNUM **p, ++ const BIGNUM **q, const BIGNUM **g) ++{ ++ ossl_ffc_params_get0_pqg(&dh->params, p, q, g); ++} ++ ++static const BIGNUM *uadk_DH_get0_priv_key(const DH *dh) ++{ ++ return dh->priv_key; ++} ++ ++static const BIGNUM *uadk_DH_get0_pub_key(const DH *dh) ++{ ++ return dh->pub_key; ++} ++ ++static int uadk_DH_bits(const DH *dh) ++{ ++ if (dh->params.p != NULL) ++ return BN_num_bits(dh->params.p); ++ return -1; ++} ++ ++static void uadk_DH_clear_flags(DH *dh, int flags) ++{ ++ dh->flags &= ~flags; ++} ++ ++static void uadk_DH_set_flags(DH *dh, int flags) ++{ ++ dh->flags |= flags; ++} ++ ++static int uadk_ffc_params_cmp(const FFC_PARAMS *a, const FFC_PARAMS *b, int ignore_q) ++{ ++ return BN_cmp(a->p, b->p) == 0 && BN_cmp(a->g, b->g) == 0 && ++ (ignore_q || BN_cmp(a->q, b->q) == 0); /* Note: q may be NULL */ ++} ++ ++static int uadk_DH_up_ref(DH *r) ++{ ++ int i; ++ ++ if (CRYPTO_UP_REF(&r->references, &i, r->lock) <= 0) ++ return 0; ++ ++ if (i < 2) { ++ fprintf(stderr, "refcount error.\n"); ++ return 0; ++ } ++ return ((i > 1) ? 1 : 0); ++} ++ ++static EVP_KEYEXCH get_default_keyexch(void) ++{ ++ static EVP_KEYEXCH s_keyexch; ++ static int initilazed; ++ ++ if (!initilazed) { ++ EVP_KEYEXCH *keyexch = ++ (EVP_KEYEXCH *)EVP_KEYEXCH_fetch(NULL, "DH", "provider=default"); ++ if (keyexch) { ++ s_keyexch = *keyexch; ++ EVP_KEYEXCH_free((EVP_KEYEXCH *)keyexch); ++ initilazed = 1; ++ } else { ++ fprintf(stderr, "EVP_KEYEXCH_fetch from default provider failed"); ++ } ++ } ++ return s_keyexch; ++} ++ ++static int dh_generate_new_priv_key(const DH *dh, BIGNUM *new_priv_key) ++{ ++ const BIGNUM *q = uadk_DH_get0_q(dh); ++ int bits; ++ ++ if (q) { ++ do { ++ if (!BN_priv_rand_range(new_priv_key, q)) ++ return UADK_E_FAIL; ++ } while (BN_is_zero(new_priv_key) || BN_is_one(new_priv_key)); ++ } else { ++ bits = uadk_DH_get_length(dh) ? ++ uadk_DH_get_length(dh) : BN_num_bits(uadk_DH_get0_p(dh)) - 1; ++ if (!BN_priv_rand(new_priv_key, bits, BN_RAND_TOP_ONE, ++ BN_RAND_BOTTOM_ANY)) ++ return UADK_E_FAIL; ++ } ++ ++ return UADK_E_SUCCESS; ++} ++ ++static int dh_try_get_priv_key(struct uadk_dh_sess *dh_sess, const DH *dh, BIGNUM **priv_key) ++{ ++ *priv_key = (BIGNUM *)uadk_DH_get0_priv_key(dh); ++ if (!(*priv_key)) { ++ *priv_key = BN_secure_new(); ++ if (!(*priv_key)) ++ return UADK_E_FAIL; ++ ++ if (!dh_generate_new_priv_key(dh, *priv_key)) ++ goto err; ++ ++ dh_sess->key_flag = KEY_GEN_BY_ENGINE; ++ } ++ ++ return UADK_E_SUCCESS; ++ ++err: ++ BN_free(*priv_key); ++ return UADK_E_FAIL; ++} ++ ++static void uadk_prov_dh_cb(void *req_t) ++{ ++ struct wd_dh_req *req_new = (struct wd_dh_req *)req_t; ++ struct uadk_e_cb_info *cb_param; ++ struct wd_dh_req *req_origin; ++ struct async_op *op; ++ ++ if (!req_new) ++ return; ++ ++ cb_param = req_new->cb_param; ++ if (!cb_param) ++ return; ++ ++ req_origin = cb_param->priv; ++ if (!req_origin) ++ return; ++ ++ req_origin->status = req_new->status; ++ if (!req_origin->status) ++ req_origin->pri_bytes = req_new->pri_bytes; ++ ++ 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 uadk_dh_env_poll(void *ctx) ++{ ++ __u64 rx_cnt = 0; ++ __u32 recv = 0; ++ /* Poll one packet currently */ ++ int expt = 1; ++ int ret; ++ ++ do { ++ ret = wd_dh_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_dh_init(void) ++{ ++ int ret; ++ ++ pthread_mutex_lock(&dh_mutex); ++ if (g_dh_res.pid != getpid()) { ++ ret = wd_dh_init2("dh", 0, 0); ++ if (unlikely(ret)) ++ return ret; ++ g_dh_res.pid = getpid(); ++ async_register_poll_fn(ASYNC_TASK_DH, uadk_dh_env_poll); ++ } ++ pthread_mutex_unlock(&dh_mutex); ++ ++ return UADK_E_INIT_SUCCESS; ++} ++ ++static struct uadk_dh_sess *dh_new_eng_session(DH *dh_alg) ++{ ++ struct uadk_dh_sess *dh_sess; ++ ++ dh_sess = OPENSSL_malloc(sizeof(struct uadk_dh_sess)); ++ if (!dh_sess) ++ return NULL; ++ ++ memset(dh_sess, 0, sizeof(struct uadk_dh_sess)); ++ ++ dh_sess->alg = dh_alg; ++ ++ return dh_sess; ++} ++ ++static int dh_init_eng_session(struct uadk_dh_sess *dh_sess, ++ __u16 bits, bool is_g2) ++{ ++ __u16 key_size = bits >> CHAR_BIT_SIZE; ++ struct sched_params params = {0}; ++ ++ if (dh_sess->sess && dh_sess->req.x_p) { ++ memset(dh_sess->req.x_p, 0, dh_sess->req.pbytes + ++ dh_sess->req.xbytes); ++ return UADK_E_SUCCESS; ++ } ++ ++ if (!dh_sess->sess) { ++ dh_sess->key_size = key_size; ++ dh_sess->setup.key_bits = bits; ++ dh_sess->setup.is_g2 = is_g2; ++ /* Use the default numa parameters */ ++ params.numa_id = -1; ++ dh_sess->setup.sched_param = ¶ms; ++ dh_sess->sess = wd_dh_alloc_sess(&dh_sess->setup); ++ if (!dh_sess->sess) ++ return UADK_E_FAIL; ++ } ++ ++ return UADK_E_SUCCESS; ++} ++ ++static void dh_free_eng_session(struct uadk_dh_sess *dh_sess) ++{ ++ if (!dh_sess) ++ return; ++ ++ if (dh_sess->sess) ++ wd_dh_free_sess(dh_sess->sess); ++ ++ if (dh_sess->req.x_p) ++ OPENSSL_free(dh_sess->req.x_p); ++ ++ if (dh_sess->req.pv) ++ OPENSSL_free(dh_sess->req.pv); ++ ++ OPENSSL_free(dh_sess); ++} ++ ++static struct uadk_dh_sess *dh_get_eng_session(DH *dh, __u16 bits, ++ bool is_g2) ++{ ++ struct uadk_dh_sess *dh_sess = dh_new_eng_session(dh); ++ int ret; ++ ++ if (!dh_sess) ++ return NULL; ++ ++ ret = dh_init_eng_session(dh_sess, bits, is_g2); ++ if (!ret) { ++ dh_free_eng_session(dh_sess); ++ return NULL; ++ } ++ ++ return dh_sess; ++} ++ ++static int check_dh_bit_useful(const __u16 bits) ++{ ++ /* ++ * Check whether bits exceeds the limit. ++ * The max module bits of openssl soft alg is ++ * OPENSSL_DH_MAX_MODULUS_BITS, 10000 bits. ++ * OpenSSL speed tool supports 2048/3072/4096/6144/8192 bits. ++ * UADK supports 768/1024/1536/2048/3072/4096 bits. ++ * UADK-engine will be consistent with UADK. ++ */ ++ switch (bits) { ++ case DH768BITS: ++ case DH1024BITS: ++ case DH1536BITS: ++ case DH2048BITS: ++ case DH3072BITS: ++ case DH4096BITS: ++ return UADK_E_SUCCESS; ++ default: ++ break; ++ } ++ ++ return UADK_E_FAIL; ++} ++ ++static int dh_prepare_data(const BIGNUM *g, DH *dh, ++ struct uadk_dh_sess **dh_sess, ++ BIGNUM **priv_key) ++{ ++ bool is_g2 = BN_is_word(g, DH_GENERATOR_2); ++ __u16 bits; ++ int ret; ++ ++ /* ++ * The max module bits of DH is ++ * OPENSSL_DH_MAX_MODULUS_BITS, 10000 bits. ++ */ ++ bits = (__u16)uadk_DH_bits(dh); ++ ret = check_dh_bit_useful(bits); ++ if (!ret) { ++ fprintf(stderr, "op size is not supported by uadk engine\n"); ++ return UADK_E_FAIL; ++ } ++ ++ *dh_sess = dh_get_eng_session(dh, bits, is_g2); ++ if (!(*dh_sess)) { ++ fprintf(stderr, "failed to get eng ctx\n"); ++ return UADK_E_FAIL; ++ } ++ ++ ret = dh_try_get_priv_key(*dh_sess, dh, priv_key); ++ if (!ret) { ++ dh_free_eng_session(*dh_sess); ++ return UADK_E_FAIL; ++ } ++ ++ return ret; ++} ++ ++static int dh_set_g(const BIGNUM *g, const __u16 key_size, ++ unsigned char *ag_bin, struct uadk_dh_sess *dh_sess) ++{ ++ struct wd_dtb g_dtb; ++ __u32 gbytes; ++ int ret; ++ ++ gbytes = BN_bn2bin(g, ag_bin); ++ g_dtb.data = (char *)ag_bin; ++ g_dtb.bsize = key_size; ++ g_dtb.dsize = gbytes; ++ ++ ret = wd_dh_set_g(dh_sess->sess, &g_dtb); ++ if (ret) { ++ fprintf(stderr, "failed to set dh g\n"); ++ return UADK_E_FAIL; ++ } ++ ++ return UADK_E_SUCCESS; ++} ++ ++static int dh_get_pubkey(struct uadk_dh_sess *dh_sess, BIGNUM **pubkey) ++{ ++ const unsigned char *pubkey_str; ++ ++ pubkey_str = (const unsigned char *)dh_sess->req.pri; ++ if (!pubkey_str) ++ return UADK_E_FAIL; ++ ++ *pubkey = BN_bin2bn(pubkey_str, dh_sess->req.pri_bytes, *pubkey); ++ if (!(*pubkey)) ++ return UADK_E_FAIL; ++ ++ return UADK_E_SUCCESS; ++} ++ ++static int dh_fill_genkey_req(const BIGNUM *g, const BIGNUM *p, ++ const BIGNUM *priv_key, ++ struct uadk_dh_sess *dh_sess) ++{ ++ __u16 key_size = dh_sess->key_size; ++ unsigned char *apriv_key_bin; ++ unsigned char *ag_bin; ++ unsigned char *ap_bin; ++ unsigned char *out_pri; ++ int ret; ++ ++ ag_bin = OPENSSL_malloc(key_size); ++ if (!ag_bin) ++ return UADK_E_FAIL; ++ ++ /* Malloc a contiguous chunk of memory */ ++ apriv_key_bin = OPENSSL_malloc(key_size * DH_PARAMS_CNT); ++ if (!apriv_key_bin) ++ goto free_ag; ++ ++ ap_bin = apriv_key_bin + key_size; ++ out_pri = ap_bin + key_size; ++ memset(ag_bin, 0, key_size); ++ memset(apriv_key_bin, 0, key_size); ++ memset(ap_bin, 0, key_size); ++ memset(out_pri, 0, key_size); ++ ++ /* Construct data block of g */ ++ ret = dh_set_g(g, key_size, ag_bin, dh_sess); ++ if (!ret) ++ goto free_apriv; ++ ++ dh_sess->req.xbytes = BN_bn2bin(priv_key, apriv_key_bin); ++ dh_sess->req.pbytes = BN_bn2bin(p, ap_bin); ++ dh_sess->req.x_p = (void *)apriv_key_bin; ++ dh_sess->req.pri = out_pri; ++ dh_sess->req.pri_bytes = key_size; ++ dh_sess->req.op_type = WD_DH_PHASE1; ++ ++ OPENSSL_free(ag_bin); ++ ++ return ret; ++ ++free_apriv: ++ OPENSSL_free(apriv_key_bin); ++free_ag: ++ OPENSSL_free(ag_bin); ++ return UADK_E_FAIL; ++} ++ ++static int dh_fill_compkey_req(const BIGNUM *g, const BIGNUM *p, ++ const BIGNUM *priv_key, const BIGNUM *pub_key, ++ struct uadk_dh_sess *dh_sess) ++{ ++ __u16 key_size = dh_sess->key_size; ++ unsigned char *apriv_key_bin; ++ unsigned char *ap_bin; ++ unsigned char *ag_bin; ++ unsigned char *out_pri; ++ int ret; ++ ++ ag_bin = OPENSSL_malloc(key_size); ++ if (!ag_bin) ++ return UADK_E_FAIL; ++ ++ apriv_key_bin = OPENSSL_malloc(key_size * DH_PARAMS_CNT); ++ if (!apriv_key_bin) ++ goto free_ag; ++ ++ ap_bin = apriv_key_bin + key_size; ++ out_pri = ap_bin + key_size; ++ memset(ag_bin, 0, key_size); ++ memset(apriv_key_bin, 0, key_size); ++ memset(ap_bin, 0, key_size); ++ memset(out_pri, 0, key_size); ++ ++ ret = dh_set_g(g, key_size, ag_bin, dh_sess); ++ if (!ret) ++ goto free_apriv; ++ ++ dh_sess->req.x_p = apriv_key_bin; ++ dh_sess->req.xbytes = BN_bn2bin(priv_key, apriv_key_bin); ++ dh_sess->req.pbytes = BN_bn2bin(p, ap_bin); ++ ++ dh_sess->req.pv = ag_bin; ++ dh_sess->req.pvbytes = BN_bn2bin(pub_key, ag_bin); ++ dh_sess->req.pri = out_pri; ++ dh_sess->req.pri_bytes = key_size; ++ dh_sess->req.op_type = WD_DH_PHASE2; ++ ++ return ret; ++ ++free_apriv: ++ OPENSSL_free(apriv_key_bin); ++free_ag: ++ OPENSSL_free(ag_bin); ++ return UADK_E_FAIL; ++} ++ ++static int dh_do_crypto(struct uadk_dh_sess *dh_sess) ++{ ++ struct uadk_e_cb_info cb_param; ++ struct async_op op; ++ int idx, ret; ++ ++ ret = async_setup_async_event_notification(&op); ++ if (!ret) { ++ printf("failed to setup async event notification.\n"); ++ return UADK_E_FAIL; ++ } ++ ++ if (!op.job) { ++ ret = wd_do_dh_sync(dh_sess->sess, &dh_sess->req); ++ if (ret) ++ return UADK_E_FAIL; ++ } else { ++ cb_param.op = &op; ++ cb_param.priv = &dh_sess->req; ++ dh_sess->req.cb = uadk_prov_dh_cb; ++ dh_sess->req.cb_param = &cb_param; ++ dh_sess->req.status = -1; ++ ret = async_get_free_task(&idx); ++ if (!ret) ++ goto err; ++ ++ op.idx = idx; ++ ++ do { ++ ret = wd_do_dh_async(dh_sess->sess, &dh_sess->req); ++ if (ret < 0 && ret != -EBUSY) { ++ async_free_poll_task(idx, 0); ++ goto err; ++ } ++ } while (ret == -EBUSY); ++ ++ ret = async_pause_job(dh_sess, &op, ASYNC_TASK_DH, idx); ++ if (!ret) ++ goto err; ++ ++ ret = dh_sess->req.status; ++ if (ret) ++ goto err; ++ } ++ ++ return UADK_E_SUCCESS; ++ ++err: ++ (void)async_clear_async_event_notification(); ++ return UADK_E_FAIL; ++} ++ ++static int dh_soft_set_pkey(DH *dh, BIGNUM *pub_key, BIGNUM *priv_key) ++{ ++ const BIGNUM *old_pub = uadk_DH_get0_pub_key(dh); ++ const BIGNUM *old_priv = uadk_DH_get0_priv_key(dh); ++ ++ if (old_pub != pub_key && old_priv != priv_key) ++ uadk_DH_set0_key(dh, pub_key, priv_key); ++ else if (old_pub != pub_key) ++ uadk_DH_set0_key(dh, pub_key, NULL); ++ else if (old_priv != priv_key) ++ uadk_DH_set0_key(dh, NULL, priv_key); ++ ++ return UADK_E_SUCCESS; ++} ++ ++static int uadk_dh_generate_key(DH *dh) ++{ ++ struct uadk_dh_sess *dh_sess = NULL; ++ BIGNUM *priv_key = NULL; ++ BIGNUM *pub_key = NULL; ++ const BIGNUM *p = NULL; ++ const BIGNUM *g = NULL; ++ const BIGNUM *q = NULL; ++ int ret; ++ ++ if (!dh) ++ goto exe_soft; ++ ++ ret = uadk_prov_dh_init(); ++ if (ret) ++ goto exe_soft; ++ ++ uadk_DH_get0_pqg(dh, &p, &q, &g); ++ if (!p || !g || q) ++ goto exe_soft; ++ ++ /* Get session and prepare private key */ ++ ret = dh_prepare_data(g, dh, &dh_sess, &priv_key); ++ if (!ret) { ++ fprintf(stderr, "prepare dh data failed\n"); ++ goto exe_soft; ++ } ++ ++ ret = dh_fill_genkey_req(g, p, priv_key, dh_sess); ++ if (!ret) { ++ fprintf(stderr, "failed to fill req\n"); ++ goto free_data; ++ } ++ ++ ret = dh_do_crypto(dh_sess); ++ if (!ret) { ++ fprintf(stderr, "failed to generate DH key\n"); ++ goto free_data; ++ } ++ ++ ret = dh_get_pubkey(dh_sess, &pub_key); ++ if (!ret) { ++ fprintf(stderr, "failed to get public key\n"); ++ goto free_data; ++ } ++ ++ ret = dh_soft_set_pkey(dh, pub_key, priv_key); ++ dh_free_eng_session(dh_sess); ++ ++ return ret; ++ ++free_data: ++ if (dh_sess->key_flag == KEY_GEN_BY_ENGINE) ++ BN_free(priv_key); ++ dh_free_eng_session(dh_sess); ++exe_soft: ++ fprintf(stderr, "switch to execute openssl software calculation.\n"); ++ return UADK_DO_SOFT; ++} ++ ++static int uadk_dh_compute_key(unsigned char *key, const BIGNUM *pub_key, ++ DH *dh) ++{ ++ struct uadk_dh_sess *dh_sess = NULL; ++ BIGNUM *priv_key = NULL; ++ const BIGNUM *p = NULL; ++ const BIGNUM *g = NULL; ++ const BIGNUM *q = NULL; ++ int ret; ++ ++ if (!dh || !key || !pub_key || !uadk_DH_get0_priv_key(dh)) ++ goto exe_soft; ++ ++ ret = uadk_prov_dh_init(); ++ if (ret) ++ goto exe_soft; ++ ++ uadk_DH_get0_pqg(dh, &p, &q, &g); ++ if (!p || !g) ++ goto exe_soft; ++ ++ ret = dh_prepare_data(g, dh, &dh_sess, &priv_key); ++ if (!ret) { ++ fprintf(stderr, "failed to prepare dh data\n"); ++ goto exe_soft; ++ } ++ ++ ret = dh_fill_compkey_req(g, p, priv_key, pub_key, dh_sess); ++ if (!ret) { ++ fprintf(stderr, "failed to fill req\n"); ++ goto free_data; ++ } ++ ++ ret = dh_do_crypto(dh_sess); ++ if (!ret) { ++ fprintf(stderr, "failed to generate DH shared key\n"); ++ goto free_data; ++ } ++ ++ memcpy(key, dh_sess->req.pri, dh_sess->req.pri_bytes); ++ ret = dh_sess->req.pri_bytes; ++ dh_free_eng_session(dh_sess); ++ ++ return ret; ++ ++free_data: ++ if (dh_sess->key_flag == KEY_GEN_BY_ENGINE) ++ BN_free(priv_key); ++ dh_free_eng_session(dh_sess); ++exe_soft: ++ fprintf(stderr, "switch to execute openssl software calculation.\n"); ++ return UADK_DO_SOFT; ++} ++ ++static void uadk_ffc_params_init(FFC_PARAMS *params) ++{ ++ memset(params, 0, sizeof(*params)); ++ params->pcounter = -1; ++ params->gindex = FFC_UNVERIFIABLE_GINDEX; ++ params->flags = FFC_PARAM_FLAG_VALIDATE_PQG; ++} ++ ++static void uadk_ffc_params_cleanup(FFC_PARAMS *params) ++{ ++ BN_free(params->p); ++ BN_free(params->q); ++ BN_free(params->g); ++ BN_free(params->j); ++ OPENSSL_free(params->seed); ++ uadk_ffc_params_init(params); ++} ++ ++static void uadk_DH_free(DH *r) ++{ ++ int i; ++ ++ if (r == NULL) ++ return; ++ ++ CRYPTO_DOWN_REF(&r->references, &i, r->lock); ++ if (i > 0) ++ return; ++ ++ if (i < 0) ++ fprintf(stderr, "WARN: refcount error.\n"); ++ ++ if (r->meth != NULL && r->meth->finish != NULL) ++ r->meth->finish(r); ++ ++ CRYPTO_free_ex_data(CRYPTO_EX_INDEX_DH, r, &r->ex_data); ++ ++ CRYPTO_THREAD_lock_free(r->lock); ++ ++ uadk_ffc_params_cleanup(&r->params); ++ BN_clear_free(r->pub_key); ++ BN_clear_free(r->priv_key); ++ OPENSSL_free(r); ++} ++ ++static void *uadk_dh_keyexch_newctx(void *provctx) ++{ ++ UADK_PROV_DH_CTX *pdhctx; ++ ++ pdhctx = OPENSSL_zalloc(sizeof(UADK_PROV_DH_CTX)); ++ if (pdhctx == NULL) ++ return NULL; ++ pdhctx->libctx = prov_libctx_of(provctx); ++ pdhctx->kdf_type = PROV_DH_KDF_NONE; ++ return pdhctx; ++} ++ ++/* The 2 parties must share the same domain parameters */ ++static int uadk_dh_keyexch_match_params(DH *priv, DH *peer) ++{ ++ int ret; ++ FFC_PARAMS *dhparams_priv = uadk_dh_get0_params(priv); ++ FFC_PARAMS *dhparams_peer = uadk_dh_get0_params(peer); ++ ++ ret = dhparams_priv != NULL && dhparams_peer != NULL && ++ uadk_ffc_params_cmp(dhparams_priv, dhparams_peer, 1); ++ if (!ret) ++ ERR_raise(ERR_LIB_PROV, PROV_R_MISMATCHING_DOMAIN_PARAMETERS); ++ return ret; ++} ++ ++static int uadk_dh_keyexch_set_peer(void *vpdhctx, void *vdh) ++{ ++ UADK_PROV_DH_CTX *pdhctx = (UADK_PROV_DH_CTX *)vpdhctx; ++ ++ if (pdhctx == NULL || vdh == NULL || ++ !uadk_dh_keyexch_match_params(vdh, pdhctx->dh) || ++ !uadk_DH_up_ref(vdh)) ++ return 0; ++ uadk_DH_free(pdhctx->dhpeer); ++ pdhctx->dhpeer = vdh; ++ return 1; ++} ++ ++static int uadk_dh_plain_derive(void *vpdhctx, unsigned char *secret, ++ size_t *secretlen, size_t outlen) ++{ ++ UADK_PROV_DH_CTX *pdhctx = (UADK_PROV_DH_CTX *)vpdhctx; ++ const BIGNUM *pub_key = NULL; ++ size_t dhsize; ++ int ret; ++ ++ if (pdhctx->dh == NULL || pdhctx->dhpeer == NULL) { ++ ERR_raise(ERR_LIB_PROV, PROV_R_MISSING_KEY); ++ return 0; ++ } ++ ++ dhsize = (size_t)uadk_DH_size(pdhctx->dh); ++ if (secret == NULL) { ++ *secretlen = dhsize; ++ return 1; ++ } ++ ++ if (outlen < dhsize) { ++ ERR_raise(ERR_LIB_PROV, PROV_R_OUTPUT_BUFFER_TOO_SMALL); ++ return 0; ++ } ++ ++ uadk_DH_get0_key(pdhctx->dhpeer, &pub_key, NULL); ++ ++ ret = uadk_dh_compute_key(secret, pub_key, pdhctx->dh); ++ if (ret <= 0) ++ return ret; ++ ++ *secretlen = ret; ++ return 1; ++} ++static int uadk_dh_keyexch_derive(void *vpdhctx, unsigned char *secret, ++ size_t *psecretlen, size_t outlen) ++{ ++ typedef int (*fun_ptr)(void *vpdhctx, unsigned char *secret, ++ size_t *secretlen, size_t outlen); ++ UADK_PROV_DH_CTX *pdhctx = (UADK_PROV_DH_CTX *)vpdhctx; ++ int ret = 0; ++ ++ switch (pdhctx->kdf_type) { ++ case PROV_DH_KDF_NONE: ++ ret = uadk_dh_plain_derive(pdhctx, secret, psecretlen, outlen); ++ if (ret == UADK_DO_SOFT) ++ goto exec_soft; ++ default: ++ break; ++ } ++ return ret; ++ ++exec_soft: ++ fprintf(stderr, "switch to execute openssl software calculation.\n"); ++ fun_ptr fun = get_default_keyexch().derive; ++ ++ if (!fun) ++ return 0; ++ ++ return fun(vpdhctx, secret, psecretlen, outlen); ++} ++ ++static void uadk_dh_keyexch_freectx(void *vpdhctx) ++{ ++ UADK_PROV_DH_CTX *pdhctx = (UADK_PROV_DH_CTX *)vpdhctx; ++ ++ OPENSSL_free(pdhctx->kdf_cekalg); ++ uadk_DH_free(pdhctx->dh); ++ uadk_DH_free(pdhctx->dhpeer); ++ EVP_MD_free(pdhctx->kdf_md); ++ OPENSSL_clear_free(pdhctx->kdf_ukm, pdhctx->kdf_ukmlen); ++ OPENSSL_free(pdhctx); ++} ++ ++static void *uadk_dh_keyexch_dupctx(void *vpdhctx) ++{ ++ UADK_PROV_DH_CTX *srcctx = (UADK_PROV_DH_CTX *)vpdhctx; ++ UADK_PROV_DH_CTX *dstctx; ++ ++ dstctx = OPENSSL_zalloc(sizeof(*srcctx)); ++ if (dstctx == NULL) ++ return NULL; ++ ++ *dstctx = *srcctx; ++ dstctx->dh = NULL; ++ dstctx->dhpeer = NULL; ++ dstctx->kdf_md = NULL; ++ dstctx->kdf_ukm = NULL; ++ dstctx->kdf_cekalg = NULL; ++ ++ if (srcctx->dh != NULL && !uadk_DH_up_ref(srcctx->dh)) ++ goto err; ++ else ++ dstctx->dh = srcctx->dh; ++ ++ if (srcctx->dhpeer != NULL && !uadk_DH_up_ref(srcctx->dhpeer)) ++ goto err; ++ else ++ dstctx->dhpeer = srcctx->dhpeer; ++ ++ if (srcctx->kdf_md != NULL && !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 != NULL && srcctx->kdf_ukmlen > 0) { ++ dstctx->kdf_ukm = OPENSSL_memdup(srcctx->kdf_ukm, ++ srcctx->kdf_ukmlen); ++ if (dstctx->kdf_ukm == NULL) ++ goto err; ++ } ++ ++ if (srcctx->kdf_cekalg != NULL) { ++ dstctx->kdf_cekalg = OPENSSL_strdup(srcctx->kdf_cekalg); ++ if (dstctx->kdf_cekalg == NULL) ++ goto err; ++ } ++ ++ return dstctx; ++err: ++ uadk_dh_keyexch_freectx(dstctx); ++ return NULL; ++} ++ ++static int uadk_dh_keyexch_set_ctx_params(void *vpdhctx, ++ const OSSL_PARAM params[]) ++{ ++ UADK_PROV_DH_CTX *pdhctx = (UADK_PROV_DH_CTX *)vpdhctx; ++ const OSSL_PARAM *p; ++ unsigned int pad; ++ char name[80] = {'\0'}; /* should be big enough */ ++ char *str = NULL; ++ ++ if (pdhctx == NULL) ++ return 0; ++ if (params == NULL) ++ return 1; ++ ++ p = OSSL_PARAM_locate_const(params, OSSL_EXCHANGE_PARAM_KDF_TYPE); ++ if (p != NULL) { ++ str = name; ++ if (!OSSL_PARAM_get_utf8_string(p, &str, sizeof(name))) ++ return 0; ++ ++ if (name[0] == '\0') ++ pdhctx->kdf_type = PROV_DH_KDF_NONE; ++ else if (strcmp(name, OSSL_KDF_NAME_X942KDF_ASN1) == 0) ++ pdhctx->kdf_type = PROV_DH_KDF_X9_42_ASN1; ++ else ++ return 0; ++ } ++ p = OSSL_PARAM_locate_const(params, OSSL_EXCHANGE_PARAM_KDF_DIGEST); ++ if (p != NULL) { ++ char mdprops[80] = {'\0'}; /* should be big enough */ ++ ++ str = name; ++ if (!OSSL_PARAM_get_utf8_string(p, &str, sizeof(name))) ++ return 0; ++ ++ str = mdprops; ++ p = OSSL_PARAM_locate_const(params, ++ OSSL_EXCHANGE_PARAM_KDF_DIGEST_PROPS); ++ ++ if (p != NULL) ++ if (!OSSL_PARAM_get_utf8_string(p, &str, sizeof(mdprops))) ++ return 0; ++ ++ EVP_MD_free(pdhctx->kdf_md); ++ pdhctx->kdf_md = EVP_MD_fetch(pdhctx->libctx, name, mdprops); ++ ++ if (pdhctx->kdf_md == NULL) ++ return 0; ++ } ++ ++ p = OSSL_PARAM_locate_const(params, OSSL_EXCHANGE_PARAM_KDF_OUTLEN); ++ if (p != NULL) { ++ size_t outlen; ++ ++ if (!OSSL_PARAM_get_size_t(p, &outlen)) ++ return 0; ++ pdhctx->kdf_outlen = outlen; ++ } ++ ++ p = OSSL_PARAM_locate_const(params, OSSL_EXCHANGE_PARAM_KDF_UKM); ++ if (p != NULL) { ++ void *tmp_ukm = NULL; ++ size_t tmp_ukmlen; ++ ++ OPENSSL_free(pdhctx->kdf_ukm); ++ pdhctx->kdf_ukm = NULL; ++ pdhctx->kdf_ukmlen = 0; ++ /* ukm is an optional field so it can be NULL */ ++ if (p->data != NULL && p->data_size != 0) { ++ if (!OSSL_PARAM_get_octet_string(p, &tmp_ukm, 0, &tmp_ukmlen)) ++ return 0; ++ pdhctx->kdf_ukm = tmp_ukm; ++ pdhctx->kdf_ukmlen = tmp_ukmlen; ++ } ++ } ++ ++ p = OSSL_PARAM_locate_const(params, OSSL_EXCHANGE_PARAM_PAD); ++ if (p != NULL) { ++ if (!OSSL_PARAM_get_uint(p, &pad)) ++ return 0; ++ pdhctx->pad = pad ? 1 : 0; ++ } ++ ++ p = OSSL_PARAM_locate_const(params, OSSL_KDF_PARAM_CEK_ALG); ++ if (p != NULL) { ++ str = name; ++ ++ OPENSSL_free(pdhctx->kdf_cekalg); ++ pdhctx->kdf_cekalg = NULL; ++ if (p->data != NULL && p->data_size != 0) { ++ if (!OSSL_PARAM_get_utf8_string(p, &str, sizeof(name))) ++ return 0; ++ pdhctx->kdf_cekalg = OPENSSL_strdup(name); ++ if (pdhctx->kdf_cekalg == NULL) ++ return 0; ++ } ++ } ++ return 1; ++} ++ ++static const OSSL_PARAM known_settable_ctx_params[] = { ++ OSSL_PARAM_int(OSSL_EXCHANGE_PARAM_PAD, 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_utf8_string(OSSL_KDF_PARAM_CEK_ALG, NULL, 0), ++ OSSL_PARAM_END ++}; ++ ++static const ++OSSL_PARAM *uadk_dh_keyexch_settable_ctx_params(ossl_unused void *vpdhctx, ++ ossl_unused void *provctx) ++{ ++ return known_settable_ctx_params; ++} ++ ++static const OSSL_PARAM known_gettable_ctx_params[] = { ++ 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_utf8_string(OSSL_KDF_PARAM_CEK_ALG, NULL, 0), ++ OSSL_PARAM_END ++}; ++ ++static const ++OSSL_PARAM *uadk_dh_keyexch_gettable_ctx_params(ossl_unused void *vpdhctx, ++ ossl_unused void *provctx) ++{ ++ return known_gettable_ctx_params; ++} ++ ++static int uadk_dh_keyexch_get_ctx_params(void *vpdhctx, OSSL_PARAM params[]) ++{ ++ UADK_PROV_DH_CTX *pdhctx = (UADK_PROV_DH_CTX *)vpdhctx; ++ OSSL_PARAM *p; ++ ++ if (pdhctx == NULL) ++ return 0; ++ ++ p = OSSL_PARAM_locate(params, OSSL_EXCHANGE_PARAM_KDF_TYPE); ++ if (p != NULL) { ++ const char *kdf_type = NULL; ++ ++ switch (pdhctx->kdf_type) { ++ case PROV_DH_KDF_NONE: ++ kdf_type = ""; ++ break; ++ case PROV_DH_KDF_X9_42_ASN1: ++ kdf_type = OSSL_KDF_NAME_X942KDF_ASN1; ++ break; ++ default: ++ return 0; ++ } ++ ++ if (!OSSL_PARAM_set_utf8_string(p, kdf_type)) ++ return 0; ++ } ++ ++ p = OSSL_PARAM_locate(params, OSSL_EXCHANGE_PARAM_KDF_DIGEST); ++ if (p != NULL && !OSSL_PARAM_set_utf8_string(p, pdhctx->kdf_md == NULL ++ ? "" ++ : EVP_MD_get0_name(pdhctx->kdf_md))) ++ return 0; ++ ++ p = OSSL_PARAM_locate(params, OSSL_EXCHANGE_PARAM_KDF_OUTLEN); ++ if (p != NULL && !OSSL_PARAM_set_size_t(p, pdhctx->kdf_outlen)) ++ return 0; ++ ++ p = OSSL_PARAM_locate(params, OSSL_EXCHANGE_PARAM_KDF_UKM); ++ if (p != NULL && !OSSL_PARAM_set_octet_ptr(p, pdhctx->kdf_ukm, pdhctx->kdf_ukmlen)) ++ return 0; ++ ++ p = OSSL_PARAM_locate(params, OSSL_KDF_PARAM_CEK_ALG); ++ if (p != NULL && !OSSL_PARAM_set_utf8_string(p, pdhctx->kdf_cekalg == NULL ++ ? "" ++ : pdhctx->kdf_cekalg)) ++ return 0; ++ ++ return 1; ++} ++ ++static int uadk_dh_keyexch_init(void *vpdhctx, void *vdh, const OSSL_PARAM params[]) ++{ ++ UADK_PROV_DH_CTX *pdhctx = (UADK_PROV_DH_CTX *)vpdhctx; ++ ++ if (pdhctx == NULL || vdh == NULL || !uadk_DH_up_ref(vdh)) ++ return 0; ++ uadk_DH_free(pdhctx->dh); ++ pdhctx->dh = vdh; ++ pdhctx->kdf_type = PROV_DH_KDF_NONE; ++ return uadk_dh_keyexch_set_ctx_params(pdhctx, params); ++} ++ ++static UADK_DH_KEYMGMT get_default_keymgmt(void) ++{ ++ static UADK_DH_KEYMGMT s_keymgmt; ++ static int initilazed; ++ ++ if (!initilazed) { ++ UADK_DH_KEYMGMT *keymgmt = ++ (UADK_DH_KEYMGMT *)EVP_KEYMGMT_fetch(NULL, "DH", "provider=default"); ++ ++ if (keymgmt) { ++ s_keymgmt = *keymgmt; ++ EVP_KEYMGMT_free((EVP_KEYMGMT *)keymgmt); ++ initilazed = 1; ++ } else { ++ fprintf(stderr, "WARN: EVP_KEYMGMT_fetch from default provider failed"); ++ } ++ } ++ return s_keymgmt; ++} ++ ++static void *uadk_dh_keymgmt_newdata(void *provctx) ++{ ++ typedef void *(*fun_ptr)(void *); ++ fun_ptr fun = get_default_keymgmt().new; ++ ++ if (!fun) ++ return NULL; ++ return fun(provctx); ++} ++ ++static void uadk_dh_keymgmt_freedata(void *keydata) ++{ ++ typedef void (*fun_ptr)(void *); ++ fun_ptr fun = get_default_keymgmt().free; ++ ++ if (!fun) ++ return; ++ fun(keydata); ++} ++ ++static int uadk_dh_keymgmt_has(const void *keydata, int selection) ++{ ++ typedef int (*fun_ptr)(const void *, int); ++ fun_ptr fun = get_default_keymgmt().has; ++ ++ if (!fun) ++ return 0; ++ return fun(keydata, selection); ++} ++ ++static int uadk_dh_keymgmt_match(const void *keydata1, const void *keydata2, int selection) ++{ ++ typedef int (*fun_ptr)(const void *, const void *, int); ++ fun_ptr fun = get_default_keymgmt().match; ++ ++ if (!fun) ++ return 0; ++ return fun(keydata1, keydata2, selection); ++} ++ ++static int uadk_dh_keymgmt_import(void *keydata, int selection, const OSSL_PARAM params[]) ++{ ++ typedef int (*fun_ptr)(void *, int, const OSSL_PARAM *); ++ fun_ptr fun = get_default_keymgmt().import; ++ ++ if (!fun) ++ return 0; ++ return fun(keydata, selection, params); ++} ++ ++static int uadk_dh_keymgmt_export(void *keydata, int selection, OSSL_CALLBACK *param_cb, ++ void *cbarg) ++{ ++ typedef int (*fun_ptr)(void *, int, OSSL_CALLBACK *, void *); ++ fun_ptr fun = get_default_keymgmt().export; ++ ++ if (!fun) ++ return 0; ++ return fun(keydata, selection, param_cb, cbarg); ++} ++ ++static const OSSL_PARAM *uadk_dh_keymgmt_import_types(int selection) ++{ ++ typedef const OSSL_PARAM *(*fun_ptr)(int); ++ fun_ptr fun = get_default_keymgmt().import_types; ++ ++ if (!fun) ++ return NULL; ++ return fun(selection); ++} ++ ++static const OSSL_PARAM *uadk_dh_keymgmt_export_types(int selection) ++{ ++ typedef const OSSL_PARAM *(*fun_ptr)(int); ++ fun_ptr fun = get_default_keymgmt().export_types; ++ ++ if (!fun) ++ return NULL; ++ return fun(selection); ++} ++ ++static ossl_inline int uadk_dh_keymgmt_get_params(void *key, OSSL_PARAM params[]) ++{ ++ typedef int (*fun_ptr)(void *, OSSL_PARAM *); ++ fun_ptr fun = get_default_keymgmt().get_params; ++ ++ if (!fun) ++ return 0; ++ return fun(key, params); ++} ++ ++static const OSSL_PARAM *uadk_dh_keymgmt_gettable_params(void *provctx) ++{ ++ typedef const OSSL_PARAM *(*fun_ptr)(void *); ++ fun_ptr fun = get_default_keymgmt().gettable_params; ++ ++ if (!fun) ++ return NULL; ++ return fun(provctx); ++} ++ ++static const OSSL_PARAM *uadk_dh_keymgmt_settable_params(void *provctx) ++{ ++ typedef const OSSL_PARAM *(*fun_ptr)(void *); ++ fun_ptr fun = get_default_keymgmt().settable_params; ++ ++ if (!fun) ++ return NULL; ++ return fun(provctx); ++} ++ ++static int uadk_dh_keymgmt_set_params(void *key, const OSSL_PARAM params[]) ++{ ++ typedef int (*fun_ptr)(void *, const OSSL_PARAM *); ++ fun_ptr fun = get_default_keymgmt().set_params; ++ ++ if (!fun) ++ return 0; ++ return fun(key, params); ++} ++ ++static int uadk_dh_keymgmt_validate(const void *keydata, int selection, int checktype) ++{ ++ typedef int (*fun_ptr)(const void *, int, int); ++ fun_ptr fun = get_default_keymgmt().validate; ++ ++ if (!fun) ++ return 0; ++ return fun(keydata, selection, checktype); ++} ++ ++static void *uadk_dh_keymgmt_gen_init(void *provctx, int selection, ++ const OSSL_PARAM params[]) ++{ ++ typedef void *(*fun_ptr)(void *, int, const OSSL_PARAM *); ++ fun_ptr fun = get_default_keymgmt().gen_init; ++ ++ if (!fun) ++ return NULL; ++ return fun(provctx, selection, params); ++} ++ ++static int uadk_dh_keymgmt_gen_set_template(void *genctx, void *templ) ++{ ++ typedef int (*fun_ptr)(void *, void *); ++ fun_ptr fun = get_default_keymgmt().gen_set_template; ++ ++ if (!fun) ++ return 0; ++ return fun(genctx, templ); ++} ++ ++static const ++OSSL_PARAM *uadk_dh_keymgmt_gen_settable_params(ossl_unused void *genctx, ++ ossl_unused void *provctx) ++{ ++ typedef const OSSL_PARAM *(*fun_ptr)(void *, void *); ++ fun_ptr fun = get_default_keymgmt().gen_settable_params; ++ ++ if (!fun) ++ return NULL; ++ return fun(genctx, provctx); ++} ++ ++static int uadk_dh_keymgmt_gen_set_params(void *genctx, ++ const OSSL_PARAM params[]) ++{ ++ typedef int (*fun_ptr)(void *, const OSSL_PARAM *); ++ fun_ptr fun = get_default_keymgmt().gen_set_params; ++ ++ if (!fun) ++ return 0; ++ return fun(genctx, params); ++} ++ ++static int dh_gencb(int p, int n, BN_GENCB *cb) ++{ ++ struct dh_gen_ctx *gctx = BN_GENCB_get_arg(cb); ++ OSSL_PARAM params[] = { OSSL_PARAM_END, OSSL_PARAM_END, OSSL_PARAM_END }; ++ ++ params[0] = OSSL_PARAM_construct_int(OSSL_GEN_PARAM_POTENTIAL, &p); ++ params[1] = OSSL_PARAM_construct_int(OSSL_GEN_PARAM_ITERATION, &n); ++ ++ return gctx->cb(params, gctx->cbarg); ++} ++ ++static DH *ossl_dh_new_ex(OSSL_LIB_CTX *libctx) ++{ ++ DH *ret = OPENSSL_zalloc(sizeof(*ret)); ++ ++ if (ret == NULL) { ++ ERR_raise(ERR_LIB_RSA, ERR_R_MALLOC_FAILURE); ++ return NULL; ++ } ++ ++ ret->references = 1; ++ ret->lock = CRYPTO_THREAD_lock_new(); ++ if (ret->lock == NULL) { ++ ERR_raise(ERR_LIB_DH, ERR_R_MALLOC_FAILURE); ++ OPENSSL_free(ret); ++ return NULL; ++ } ++ ++ ret->libctx = libctx; ++ ++ return ret; ++} ++ ++static void *uadk_dh_keymgmt_gen(void *genctx, OSSL_CALLBACK *osslcb, void *cbarg) ++{ ++ typedef void* (*fun_ptr)(void *, OSSL_CALLBACK *, void *); ++ struct dh_gen_ctx *gctx = genctx; ++ DH *dh = NULL; ++ BN_GENCB *gencb = NULL; ++ FFC_PARAMS *ffc; ++ fun_ptr fun; ++ int ret; ++ ++ if (gctx == NULL) ++ return NULL; ++ ++ dh = ossl_dh_new_ex(gctx->libctx); ++ if (dh == NULL) ++ return NULL; ++ ffc = uadk_ossl_dh_get0_params(dh); ++ if (gctx->ffc_params != NULL ++ && !ossl_ffc_params_copy(ffc, gctx->ffc_params)) ++ goto exec_soft; ++ if (!ossl_ffc_params_set_seed(ffc, gctx->seed, gctx->seedlen)) ++ goto exec_soft; ++ gctx->cb = osslcb; ++ gctx->cbarg = cbarg; ++ gencb = BN_GENCB_new(); ++ if (gencb != NULL) ++ BN_GENCB_set(gencb, dh_gencb, genctx); ++ ++ ++ ret = uadk_dh_generate_key(dh); ++ if (ret == UADK_DO_SOFT) ++ goto exec_soft; ++ uadk_DH_clear_flags(dh, DH_FLAG_TYPE_MASK); ++ uadk_DH_set_flags(dh, gctx->dh_type); ++ BN_GENCB_free(gencb); ++ return dh; ++ ++exec_soft: ++ if (dh) ++ uadk_dh_keymgmt_freedata(dh); ++ if (gencb) ++ BN_GENCB_free(gencb); ++ fun = get_default_keymgmt().gen; ++ if (!fun) ++ return NULL; ++ return fun(genctx, osslcb, cbarg); ++} ++ ++static void uadk_dh_keymgmt_gen_cleanup(void *genctx) ++{ ++ typedef void (*fun_ptr)(void *); ++ fun_ptr fun = get_default_keymgmt().gen_cleanup; ++ ++ if (!fun) ++ return; ++ fun(genctx); ++} ++ ++static void *uadk_dh_keymgmt_load(const void *reference, size_t reference_sz) ++{ ++ typedef void *(*fun_ptr)(const void *, size_t); ++ fun_ptr fun = get_default_keymgmt().load; ++ ++ if (!fun) ++ return NULL; ++ return fun(reference, reference_sz); ++} ++ ++static void *uadk_dh_keymgmt_dup(const void *keydata_from, int selection) ++{ ++ typedef void *(*fun_ptr)(const void *, int); ++ fun_ptr fun = get_default_keymgmt().dup; ++ ++ if (!fun) ++ return NULL; ++ return fun(keydata_from, selection); ++} ++ ++const OSSL_DISPATCH uadk_dh_keyexch_functions[] = { ++ {OSSL_FUNC_KEYEXCH_NEWCTX, ++ (void (*)(void))uadk_dh_keyexch_newctx}, ++ {OSSL_FUNC_KEYEXCH_INIT, ++ (void (*)(void))uadk_dh_keyexch_init}, ++ {OSSL_FUNC_KEYEXCH_DERIVE, ++ (void (*)(void))uadk_dh_keyexch_derive}, ++ {OSSL_FUNC_KEYEXCH_SET_PEER, ++ (void (*)(void))uadk_dh_keyexch_set_peer}, ++ {OSSL_FUNC_KEYEXCH_FREECTX, ++ (void (*)(void))uadk_dh_keyexch_freectx}, ++ {OSSL_FUNC_KEYEXCH_DUPCTX, ++ (void (*)(void))uadk_dh_keyexch_dupctx}, ++ {OSSL_FUNC_KEYEXCH_SET_CTX_PARAMS, ++ (void (*)(void))uadk_dh_keyexch_set_ctx_params}, ++ {OSSL_FUNC_KEYEXCH_SETTABLE_CTX_PARAMS, ++ (void (*)(void))uadk_dh_keyexch_settable_ctx_params}, ++ {OSSL_FUNC_KEYEXCH_GET_CTX_PARAMS, ++ (void (*)(void))uadk_dh_keyexch_get_ctx_params}, ++ {OSSL_FUNC_KEYEXCH_GETTABLE_CTX_PARAMS, ++ (void (*)(void))uadk_dh_keyexch_gettable_ctx_params}, ++ {0, NULL} ++}; ++ ++const OSSL_DISPATCH uadk_dh_keymgmt_functions[] = { ++ {OSSL_FUNC_KEYMGMT_NEW, ++ (void (*)(void))uadk_dh_keymgmt_newdata}, ++ {OSSL_FUNC_KEYMGMT_GEN_INIT, ++ (void (*)(void))uadk_dh_keymgmt_gen_init}, ++ {OSSL_FUNC_KEYMGMT_GEN_SET_TEMPLATE, ++ (void (*)(void))uadk_dh_keymgmt_gen_set_template}, ++ {OSSL_FUNC_KEYMGMT_GEN_SET_PARAMS, ++ (void (*)(void))uadk_dh_keymgmt_gen_set_params}, ++ {OSSL_FUNC_KEYMGMT_GEN_SETTABLE_PARAMS, ++ (void (*)(void))uadk_dh_keymgmt_gen_settable_params}, ++ {OSSL_FUNC_KEYMGMT_GEN, ++ (void (*)(void))uadk_dh_keymgmt_gen}, ++ {OSSL_FUNC_KEYMGMT_GEN_CLEANUP, ++ (void (*)(void))uadk_dh_keymgmt_gen_cleanup}, ++ {OSSL_FUNC_KEYMGMT_LOAD, ++ (void (*)(void))uadk_dh_keymgmt_load}, ++ {OSSL_FUNC_KEYMGMT_FREE, ++ (void (*)(void))uadk_dh_keymgmt_freedata}, ++ {OSSL_FUNC_KEYMGMT_GET_PARAMS, ++ (void (*)(void))uadk_dh_keymgmt_get_params}, ++ {OSSL_FUNC_KEYMGMT_GETTABLE_PARAMS, ++ (void (*)(void))uadk_dh_keymgmt_gettable_params}, ++ {OSSL_FUNC_KEYMGMT_SET_PARAMS, ++ (void (*)(void))uadk_dh_keymgmt_set_params}, ++ {OSSL_FUNC_KEYMGMT_SETTABLE_PARAMS, ++ (void (*)(void))uadk_dh_keymgmt_settable_params}, ++ {OSSL_FUNC_KEYMGMT_HAS, ++ (void (*)(void))uadk_dh_keymgmt_has}, ++ {OSSL_FUNC_KEYMGMT_MATCH, ++ (void (*)(void))uadk_dh_keymgmt_match}, ++ {OSSL_FUNC_KEYMGMT_VALIDATE, ++ (void (*)(void))uadk_dh_keymgmt_validate}, ++ {OSSL_FUNC_KEYMGMT_IMPORT, ++ (void (*)(void))uadk_dh_keymgmt_import}, ++ {OSSL_FUNC_KEYMGMT_IMPORT_TYPES, ++ (void (*)(void))uadk_dh_keymgmt_import_types}, ++ {OSSL_FUNC_KEYMGMT_EXPORT, ++ (void (*)(void))uadk_dh_keymgmt_export}, ++ {OSSL_FUNC_KEYMGMT_EXPORT_TYPES, ++ (void (*)(void))uadk_dh_keymgmt_export_types}, ++ {OSSL_FUNC_KEYMGMT_DUP, ++ (void (*)(void))uadk_dh_keymgmt_dup}, ++ {0, NULL} ++}; ++ ++void uadk_prov_destroy_dh(void) ++{ ++ pthread_mutex_lock(&dh_mutex); ++ if (g_dh_res.pid == getpid()) { ++ wd_dh_uninit2(); ++ g_dh_res.pid = 0; ++ } ++ pthread_mutex_lock(&dh_mutex); ++} +diff --git a/src/uadk_prov_init.c b/src/uadk_prov_init.c +index fc09b64..c3d4a63 100644 +--- a/src/uadk_prov_init.c ++++ b/src/uadk_prov_init.c +@@ -78,15 +78,16 @@ const OSSL_ALGORITHM uadk_prov_ciphers[] = { + }; + + static const OSSL_ALGORITHM uadk_prov_signature[] = { +- {"RSA", UADK_DEFAULT_PROPERTIES, +- uadk_rsa_signature_functions, "uadk_provider rsa_signature" }, +- {NULL, NULL, NULL} ++ { "RSA", UADK_DEFAULT_PROPERTIES, ++ uadk_rsa_signature_functions, "uadk_provider rsa_signature" }, ++ { NULL, NULL, NULL } + }; + + static const OSSL_ALGORITHM uadk_prov_keymgmt[] = { +- {"RSA", UADK_DEFAULT_PROPERTIES, +- uadk_rsa_keymgmt_functions, "uadk RSA Keymgmt implementation."}, +- {NULL, NULL, NULL} ++ { "RSA", UADK_DEFAULT_PROPERTIES, ++ uadk_rsa_keymgmt_functions, "uadk RSA Keymgmt implementation." }, ++ { "DH", UADK_DEFAULT_PROPERTIES, uadk_dh_keymgmt_functions }, ++ { NULL, NULL, NULL } + }; + + static const OSSL_ALGORITHM uadk_prov_asym_cipher[] = { +@@ -94,6 +95,12 @@ static const OSSL_ALGORITHM uadk_prov_asym_cipher[] = { + { NULL, NULL, NULL } + }; + ++static const OSSL_ALGORITHM uadk_prov_keyexch[] = { ++ { "DH", UADK_DEFAULT_PROPERTIES, ++ uadk_dh_keyexch_functions, "UADK DH keyexch implementation"}, ++ { NULL, NULL, NULL } ++}; ++ + static const OSSL_ALGORITHM *uadk_query(void *provctx, int operation_id, + int *no_cache) + { +@@ -120,6 +127,8 @@ static const OSSL_ALGORITHM *uadk_query(void *provctx, int operation_id, + return uadk_prov_keymgmt; + case OSSL_OP_ASYM_CIPHER: + return uadk_prov_asym_cipher; ++ case OSSL_OP_KEYEXCH: ++ return uadk_prov_keyexch; + case OSSL_OP_STORE: + return prov->query_operation(provctx, operation_id, no_cache); + } +-- +2.25.1 + diff --git a/0052-uadk-add-DH-sanity-test.patch b/0052-uadk-add-DH-sanity-test.patch new file mode 100644 index 0000000..619795f --- /dev/null +++ b/0052-uadk-add-DH-sanity-test.patch @@ -0,0 +1,225 @@ +From e98342b85f0f437de57f82078ecfff987d939570 Mon Sep 17 00:00:00 2001 +From: Zhangfei Gao +Date: Mon, 23 Oct 2023 06:38:15 +0000 +Subject: [PATCH 52/63] uadk: add DH sanity test + +Add DH sanity test. + +Also, for clarity, put all 3.0 sanity tests into a different file: +test/sanity_test_openssl3.0.sh + +Signed-off-by: Zhangfei Gao +--- + test/sanity_test.sh | 73 +-------------------- + test/sanity_test_openssl3.0.sh | 115 +++++++++++++++++++++++++++++++++ + 2 files changed, 116 insertions(+), 72 deletions(-) + create mode 100755 test/sanity_test_openssl3.0.sh + +diff --git a/test/sanity_test.sh b/test/sanity_test.sh +index 5b61da3..7f2d586 100755 +--- a/test/sanity_test.sh ++++ b/test/sanity_test.sh +@@ -14,78 +14,7 @@ echo "OpenSSL major version is "$major_version + + # Check if the major version is equal to or greater than 3 + if ((major_version >= 3)); then +- engine_id="$TEST_SCRIPT_DIR/../src/.libs/uadk_provider.so" +- digest_algs=$(openssl list -provider $engine_id -digest-algorithms) +- cipher_algs=$(openssl list -provider $engine_id -cipher-algorithms) +- signature_algs=$(openssl list -provider $engine_id -signature-algorithms) +-fi +- +-if [[ $digest_algs =~ "uadk_provider" ]]; then +- echo "uadk_provider testing digest" +- openssl speed -provider $engine_id -evp md5 +- openssl speed -provider $engine_id -evp sm3 +- openssl speed -provider $engine_id -evp sha1 +- openssl speed -provider $engine_id -evp sha2-224 +- openssl speed -provider $engine_id -evp sha2-256 +- openssl speed -provider $engine_id -evp sha2-384 +- openssl speed -provider $engine_id -evp sha2-512 +- +- openssl speed -provider $engine_id -async_jobs 1 -evp md5 +- openssl speed -provider $engine_id -async_jobs 1 -evp sm3 +- openssl speed -provider $engine_id -async_jobs 1 -evp sha1 +- openssl speed -provider $engine_id -async_jobs 1 -evp sha2-224 +- openssl speed -provider $engine_id -async_jobs 1 -evp sha2-256 +- openssl speed -provider $engine_id -async_jobs 1 -evp sha2-384 +- openssl speed -provider $engine_id -async_jobs 1 -evp sha2-512 +-fi +- +-if [[ $cipher_algs =~ "uadk_provider" ]]; then +- echo "uadk_provider testing cipher" +- openssl speed -provider $engine_id -evp aes-128-cbc +- openssl speed -provider $engine_id -evp aes-192-cbc +- openssl speed -provider $engine_id -evp aes-256-cbc +- openssl speed -provider $engine_id -evp aes-128-ecb +- openssl speed -provider $engine_id -evp aes-192-ecb +- openssl speed -provider $engine_id -evp aes-256-ecb +- openssl speed -provider $engine_id -evp aes-128-xts +- openssl speed -provider $engine_id -evp aes-256-xts +- openssl speed -provider $engine_id -evp sm4-cbc +- openssl speed -provider $engine_id -evp sm4-ecb +- openssl speed -provider $engine_id -evp des-ede3-cbc +- openssl speed -provider $engine_id -evp des-ede3-ecb +- +- openssl speed -provider $engine_id -async_jobs 1 -evp aes-128-cbc +- openssl speed -provider $engine_id -async_jobs 1 -evp aes-192-cbc +- openssl speed -provider $engine_id -async_jobs 1 -evp aes-256-cbc +- openssl speed -provider $engine_id -async_jobs 1 -evp aes-128-ecb +- openssl speed -provider $engine_id -async_jobs 1 -evp aes-192-ecb +- openssl speed -provider $engine_id -async_jobs 1 -evp aes-256-ecb +- openssl speed -provider $engine_id -async_jobs 1 -evp aes-128-xts +- openssl speed -provider $engine_id -async_jobs 1 -evp aes-256-xts +- openssl speed -provider $engine_id -async_jobs 1 -evp sm4-cbc +- openssl speed -provider $engine_id -async_jobs 1 -evp sm4-ecb +- openssl speed -provider $engine_id -async_jobs 1 -evp des-ede3-cbc +- openssl speed -provider $engine_id -async_jobs 1 -evp des-ede3-ecb +-fi +- +-if [[ $signature_algs =~ "uadk_provider" ]]; then +- echo "uadk_provider testing rsa" +- openssl speed -provider $engine_id rsa1024 +- openssl speed -provider $engine_id rsa2048 +- openssl speed -provider $engine_id rsa4096 +- openssl speed -provider $engine_id -async_jobs 1 rsa1024 +- openssl speed -provider $engine_id -async_jobs 1 rsa2048 +- openssl speed -provider $engine_id -async_jobs 1 rsa4096 +- +- openssl genrsa -out prikey.pem -provider $engine_id 1024 +- openssl rsa -in prikey.pem -pubout -out pubkey.pem -provider $engine_id +- echo "Content to be encrypted" > plain.txt +- +- openssl pkeyutl -encrypt -in plain.txt -inkey pubkey.pem -pubin -out enc.txt \ +- -pkeyopt rsa_padding_mode:pkcs1 -provider $engine_id +- +- openssl pkeyutl -decrypt -in enc.txt -inkey prikey.pem -out dec.txt \ +- -pkeyopt rsa_padding_mode:pkcs1 -provider $engine_id ++ $TEST_SCRIPT_DIR/sanity_test_openssl3.0.sh + fi + + if [[ $version =~ "1.1.1" ]]; then +diff --git a/test/sanity_test_openssl3.0.sh b/test/sanity_test_openssl3.0.sh +new file mode 100755 +index 0000000..7f543ae +--- /dev/null ++++ b/test/sanity_test_openssl3.0.sh +@@ -0,0 +1,115 @@ ++#!/bin/bash ++ ++set -x ++sudo chmod 666 /dev/hisi_* ++ ++TEST_SCRIPT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )" ++ ++version=$(openssl version) ++echo $version ++ ++# Extract the major version number (e.g., "3") from the version string ++major_version=$(echo $version | awk -F'[ .]' '{print $2}') ++echo "OpenSSL major version is "$major_version ++ ++# Check if the major version is equal to or greater than 3 ++if ((major_version >= 3)); then ++ engine_id="$TEST_SCRIPT_DIR/../src/.libs/uadk_provider.so" ++ digest_algs=$(openssl list -provider $engine_id -digest-algorithms) ++ cipher_algs=$(openssl list -provider $engine_id -cipher-algorithms) ++ signature_algs=$(openssl list -provider $engine_id -signature-algorithms) ++ keyexch_algs=$(openssl list -provider $engine_id -key-exchange-algorithms) ++fi ++ ++if [[ $digest_algs =~ "uadk_provider" ]]; then ++ echo "uadk_provider testing digest" ++ openssl speed -provider $engine_id -evp md5 ++ openssl speed -provider $engine_id -evp sm3 ++ openssl speed -provider $engine_id -evp sha1 ++ openssl speed -provider $engine_id -evp sha2-224 ++ openssl speed -provider $engine_id -evp sha2-256 ++ openssl speed -provider $engine_id -evp sha2-384 ++ openssl speed -provider $engine_id -evp sha2-512 ++ ++ openssl speed -provider $engine_id -async_jobs 1 -evp md5 ++ openssl speed -provider $engine_id -async_jobs 1 -evp sm3 ++ openssl speed -provider $engine_id -async_jobs 1 -evp sha1 ++ openssl speed -provider $engine_id -async_jobs 1 -evp sha2-224 ++ openssl speed -provider $engine_id -async_jobs 1 -evp sha2-256 ++ openssl speed -provider $engine_id -async_jobs 1 -evp sha2-384 ++ openssl speed -provider $engine_id -async_jobs 1 -evp sha2-512 ++fi ++ ++if [[ $cipher_algs =~ "uadk_provider" ]]; then ++ echo "uadk_provider testing cipher" ++ openssl speed -provider $engine_id -evp aes-128-cbc ++ openssl speed -provider $engine_id -evp aes-192-cbc ++ openssl speed -provider $engine_id -evp aes-256-cbc ++ openssl speed -provider $engine_id -evp aes-128-ecb ++ openssl speed -provider $engine_id -evp aes-192-ecb ++ openssl speed -provider $engine_id -evp aes-256-ecb ++ openssl speed -provider $engine_id -evp aes-128-xts ++ openssl speed -provider $engine_id -evp aes-256-xts ++ openssl speed -provider $engine_id -evp sm4-cbc ++ openssl speed -provider $engine_id -evp sm4-ecb ++ openssl speed -provider $engine_id -evp des-ede3-cbc ++ openssl speed -provider $engine_id -evp des-ede3-ecb ++ ++ openssl speed -provider $engine_id -async_jobs 1 -evp aes-128-cbc ++ openssl speed -provider $engine_id -async_jobs 1 -evp aes-192-cbc ++ openssl speed -provider $engine_id -async_jobs 1 -evp aes-256-cbc ++ openssl speed -provider $engine_id -async_jobs 1 -evp aes-128-ecb ++ openssl speed -provider $engine_id -async_jobs 1 -evp aes-192-ecb ++ openssl speed -provider $engine_id -async_jobs 1 -evp aes-256-ecb ++ openssl speed -provider $engine_id -async_jobs 1 -evp aes-128-xts ++ openssl speed -provider $engine_id -async_jobs 1 -evp aes-256-xts ++ openssl speed -provider $engine_id -async_jobs 1 -evp sm4-cbc ++ openssl speed -provider $engine_id -async_jobs 1 -evp sm4-ecb ++ openssl speed -provider $engine_id -async_jobs 1 -evp des-ede3-cbc ++ openssl speed -provider $engine_id -async_jobs 1 -evp des-ede3-ecb ++fi ++ ++if [[ $signature_algs =~ "uadk_provider" ]]; then ++ echo "uadk_provider testing rsa" ++ openssl speed -provider $engine_id rsa1024 ++ openssl speed -provider $engine_id rsa2048 ++ openssl speed -provider $engine_id rsa4096 ++ openssl speed -provider $engine_id -async_jobs 1 rsa1024 ++ openssl speed -provider $engine_id -async_jobs 1 rsa2048 ++ openssl speed -provider $engine_id -async_jobs 1 rsa4096 ++ ++ openssl genrsa -out prikey.pem -provider $engine_id 1024 ++ openssl rsa -in prikey.pem -pubout -out pubkey.pem -provider $engine_id ++ echo "Content to be encrypted" > plain.txt ++ ++ openssl pkeyutl -encrypt -in plain.txt -inkey pubkey.pem -pubin -out enc.txt \ ++ -pkeyopt rsa_padding_mode:pkcs1 -provider $engine_id ++ ++ openssl pkeyutl -decrypt -in enc.txt -inkey prikey.pem -out dec.txt \ ++ -pkeyopt rsa_padding_mode:pkcs1 -provider $engine_id ++fi ++ ++if [[ $keyexch_algs =~ "uadk_provider" ]]; then ++ echo "uadk_provider testing dh" ++ ++ #1. Generate global public parameters, and save them in the file dhparam.pem: ++ openssl dhparam -out dhparam.pem 2048 ++ ++ #2. Generate own private key: ++ openssl genpkey -paramfile dhparam.pem -out privatekey1.pem -provider $engine_id ++ openssl genpkey -paramfile dhparam.pem -out privatekey2.pem -provider $engine_id ++ ++ #3. Generate public key: ++ openssl pkey -in privatekey1.pem -pubout -out publickey1.pem -provider $engine_id ++ openssl pkey -in privatekey2.pem -pubout -out publickey2.pem -provider $engine_id ++ ++ #4. After exchanging public key, each user can derive the shared secret: ++ openssl pkeyutl -derive -inkey privatekey1.pem -peerkey publickey2.pem -out secret1.bin -provider $engine_id ++ openssl pkeyutl -derive -inkey privatekey2.pem -peerkey publickey1.pem -out secret2.bin -provider $engine_id ++ ++ #5. Check secret1.bin and secret2.bin: ++ cmp secret1.bin secret2.bin ++ xxd secret1.bin ++ xxd secret2.bin ++ #secret1.bin and secret2.bin should be same. ++fi +-- +2.25.1 + diff --git a/0053-uadk-add-uadk_provider.cnf.patch b/0053-uadk-add-uadk_provider.cnf.patch new file mode 100644 index 0000000..5d864b4 --- /dev/null +++ b/0053-uadk-add-uadk_provider.cnf.patch @@ -0,0 +1,41 @@ +From 9d0d42f00ed60dd8b1dd13fd611068dcea6408d4 Mon Sep 17 00:00:00 2001 +From: Zhangfei Gao +Date: Tue, 24 Oct 2023 08:55:11 +0000 +Subject: [PATCH 53/63] uadk: add uadk_provider.cnf + +uadk_provider can be enabled via uadk_provider.cnf + +export OPENSSL_CONF=/path/to/uadk_provider.cnf +openssl command -config /path/to/uadk_provider.cnf +application calls CONF_modules_load_file + +Signed-off-by: Zhangfei Gao +--- + uadk_provider.cnf | 15 +++++++++++++++ + 1 file changed, 15 insertions(+) + create mode 100644 uadk_provider.cnf + +diff --git a/uadk_provider.cnf b/uadk_provider.cnf +new file mode 100644 +index 0000000..c9d1596 +--- /dev/null ++++ b/uadk_provider.cnf +@@ -0,0 +1,15 @@ ++# uadk_provider can be enabled via uadk_provider.cnf ++# export OPENSSL_CONF=/path/to/uadk_provider.cnf ++# openssl command -config /path/to/uadk_provider.cnf ++# application calls CONF_modules_load_file ++ ++openssl_conf = openssl_init ++ ++[openssl_init] ++providers = provider_sect ++ ++[provider_sect] ++uadk_provider = uadk_sect ++ ++[uadk_sect] ++activate = 1 +-- +2.25.1 + diff --git a/0054-uadk-add-evp_test.sh.patch b/0054-uadk-add-evp_test.sh.patch new file mode 100644 index 0000000..68bb4e9 --- /dev/null +++ b/0054-uadk-add-evp_test.sh.patch @@ -0,0 +1,66 @@ +From 172ab332b9ada14fe333dd585dda3ceacd09dfc6 Mon Sep 17 00:00:00 2001 +From: Zhangfei Gao +Date: Tue, 24 Oct 2023 09:07:06 +0000 +Subject: [PATCH 54/63] uadk: add evp_test.sh + +Enable uadk_provider via export OPENSSL_CONF +cd to /path/to/openssl/test and doing evp_test + +For example: +./test/evp_test.sh ../openssl + +Signed-off-by: Zhangfei Gao +Signed-off-by: Guodong Xu +--- + test/evp_test.sh | 39 +++++++++++++++++++++++++++++++++++++++ + 1 file changed, 39 insertions(+) + create mode 100755 test/evp_test.sh + +diff --git a/test/evp_test.sh b/test/evp_test.sh +new file mode 100755 +index 0000000..5c1b022 +--- /dev/null ++++ b/test/evp_test.sh +@@ -0,0 +1,39 @@ ++#!/bin/bash ++ ++set -x ++ ++TEST_SCRIPT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )" ++ ++if [ $# -eq 0 ]; then ++ echo "No para: evp_test.sh /path/to/openssl" ++ exit ++fi ++ ++export OPENSSL_CONF=$TEST_SCRIPT_DIR/../uadk_provider.cnf ++ ++cd "$1"/test ++ ++#Cipher test ++digest_algs=$(openssl list -digest-algorithms) ++if [[ $digest_algs =~ "uadk_provider" ]]; then ++ ./evp_test ./recipes/30-test_evp_data/evpmd_sm3.txt ++ ./evp_test ./recipes/30-test_evp_data/evpmd_sha.txt ++fi ++ ++cipher_algs=$(openssl list -cipher-algorithms) ++if [[ $cipher_algs =~ "uadk_provider" ]]; then ++ ./evp_test ./recipes/30-test_evp_data/evpciph_sm4.txt ++ ./evp_test ./recipes/30-test_evp_data/evpciph_aes_common.txt ++ ./evp_test ./recipes/30-test_evp_data/evpciph_des3_common.txt ++fi ++ ++signature_algs=$(openssl list -signature-algorithms) ++if [[ $signature_algs =~ "uadk_provider" ]]; then ++ ./evp_test ./recipes/30-test_evp_data/evppkey_rsa.txt ++ ./evp_test ./recipes/30-test_evp_data/evppkey_rsa_common.txt ++fi ++ ++keyexch_algs=$(openssl list -key-exchange-algorithms) ++if [[ $keyexch_algs =~ "uadk_provider" ]]; then ++ ./evp_test ./recipes/30-test_evp_data/evppkey_dh.txt ++fi +-- +2.25.1 + diff --git a/0055-uadk_engine-remove-redundant-param-of-async.patch b/0055-uadk_engine-remove-redundant-param-of-async.patch new file mode 100644 index 0000000..5703472 --- /dev/null +++ b/0055-uadk_engine-remove-redundant-param-of-async.patch @@ -0,0 +1,202 @@ +From 553d8a9068a7848294dba8605be3a2feb9db1498 Mon Sep 17 00:00:00 2001 +From: Zhiqi Song +Date: Thu, 9 Nov 2023 11:23:37 +0800 +Subject: [PATCH 55/63] uadk_engine: remove redundant param of async + +Remove redundant index parameter of async_pause_job(), +as the value of the index has been saved in async_op +type variable. + +Signed-off-by: Zhiqi Song +--- + src/uadk_async.c | 8 ++++---- + src/uadk_async.h | 2 +- + src/uadk_cipher.c | 2 +- + src/uadk_dh.c | 4 ++-- + src/uadk_digest.c | 2 +- + src/uadk_pkey.c | 2 +- + src/uadk_prov_cipher.c | 2 +- + src/uadk_prov_dh.c | 2 +- + src/uadk_prov_digest.c | 2 +- + src/uadk_prov_rsa.c | 2 +- + src/uadk_rsa.c | 2 +- + 11 files changed, 15 insertions(+), 15 deletions(-) + +diff --git a/src/uadk_async.c b/src/uadk_async.c +index 45f3918..870065d 100644 +--- a/src/uadk_async.c ++++ b/src/uadk_async.c +@@ -234,14 +234,14 @@ out: + return ret; + } + +-static int async_add_poll_task(void *ctx, struct async_op *op, enum task_type type, int id) ++static int async_add_poll_task(void *ctx, struct async_op *op, enum task_type type) + { + struct async_poll_task *task_queue; + struct async_poll_task *task; + int ret; + + task_queue = poll_queue.head; +- task = &task_queue[id]; ++ task = &task_queue[op->idx]; + task->ctx = ctx; + task->type = type; + task->op = op; +@@ -253,7 +253,7 @@ static int async_add_poll_task(void *ctx, struct async_op *op, enum task_type ty + return 1; + } + +-int async_pause_job(void *ctx, struct async_op *op, enum task_type type, int id) ++int async_pause_job(void *ctx, struct async_op *op, enum task_type type) + { + ASYNC_WAIT_CTX *waitctx; + OSSL_ASYNC_FD efd; +@@ -261,7 +261,7 @@ int async_pause_job(void *ctx, struct async_op *op, enum task_type type, int id) + uint64_t buf; + int ret; + +- ret = async_add_poll_task(ctx, op, type, id); ++ ret = async_add_poll_task(ctx, op, type); + if (ret == 0) + return ret; + +diff --git a/src/uadk_async.h b/src/uadk_async.h +index 9160c98..1208c30 100644 +--- a/src/uadk_async.h ++++ b/src/uadk_async.h +@@ -72,7 +72,7 @@ struct async_poll_queue { + + int async_setup_async_event_notification(struct async_op *op); + int async_clear_async_event_notification(void); +-int async_pause_job(void *ctx, struct async_op *op, enum task_type type, int id); ++int async_pause_job(void *ctx, struct async_op *op, enum task_type type); + void async_register_poll_fn(int type, async_recv_t func); + int async_module_init(void); + int async_wake_job(ASYNC_JOB *job); +diff --git a/src/uadk_cipher.c b/src/uadk_cipher.c +index 901c29e..ed25787 100644 +--- a/src/uadk_cipher.c ++++ b/src/uadk_cipher.c +@@ -841,7 +841,7 @@ static int do_cipher_async(struct cipher_priv_ctx *priv, struct async_op *op) + } + } while (ret == -EBUSY); + +- ret = async_pause_job(priv, op, ASYNC_TASK_CIPHER, idx); ++ ret = async_pause_job(priv, op, ASYNC_TASK_CIPHER); + if (!ret) + return 0; + return 1; +diff --git a/src/uadk_dh.c b/src/uadk_dh.c +index acb5b8a..418747e 100644 +--- a/src/uadk_dh.c ++++ b/src/uadk_dh.c +@@ -723,12 +723,12 @@ static int dh_do_crypto(struct uadk_dh_sess *dh_sess) + do { + ret = wd_do_dh_async(dh_sess->sess, &dh_sess->req); + if (ret < 0 && ret != -EBUSY) { +- async_free_poll_task(idx, 0); ++ async_free_poll_task(op.idx, 0); + goto err; + } + } while (ret == -EBUSY); + +- ret = async_pause_job(dh_sess, &op, ASYNC_TASK_DH, idx); ++ ret = async_pause_job(dh_sess, &op, ASYNC_TASK_DH); + if (!ret) + goto err; + +diff --git a/src/uadk_digest.c b/src/uadk_digest.c +index beb9f51..fa96e57 100644 +--- a/src/uadk_digest.c ++++ b/src/uadk_digest.c +@@ -757,7 +757,7 @@ static int do_digest_async(struct digest_priv_ctx *priv, struct async_op *op) + } + } while (ret == -EBUSY); + +- ret = async_pause_job(priv, op, ASYNC_TASK_DIGEST, idx); ++ ret = async_pause_job(priv, op, ASYNC_TASK_DIGEST); + if (!ret) + return 0; + return 1; +diff --git a/src/uadk_pkey.c b/src/uadk_pkey.c +index 60e3238..b071d8b 100644 +--- a/src/uadk_pkey.c ++++ b/src/uadk_pkey.c +@@ -312,7 +312,7 @@ int uadk_ecc_crypto(handle_t sess, struct wd_ecc_req *req, void *usr) + } + } while (ret == -EBUSY); + +- ret = async_pause_job((void *)usr, &op, ASYNC_TASK_ECC, idx); ++ ret = async_pause_job((void *)usr, &op, ASYNC_TASK_ECC); + if (!ret) + goto err; + if (req->status) +diff --git a/src/uadk_prov_cipher.c b/src/uadk_prov_cipher.c +index 21bf0a2..9b0e9fe 100644 +--- a/src/uadk_prov_cipher.c ++++ b/src/uadk_prov_cipher.c +@@ -396,7 +396,7 @@ static int uadk_do_cipher_async(struct cipher_priv_ctx *priv, struct async_op *o + } + } while (ret == -EBUSY); + +- ret = async_pause_job(priv, op, ASYNC_TASK_CIPHER, idx); ++ ret = async_pause_job(priv, op, ASYNC_TASK_CIPHER); + if (!ret) + return 0; + return 1; +diff --git a/src/uadk_prov_dh.c b/src/uadk_prov_dh.c +index cf84cb9..5437c46 100644 +--- a/src/uadk_prov_dh.c ++++ b/src/uadk_prov_dh.c +@@ -926,7 +926,7 @@ static int dh_do_crypto(struct uadk_dh_sess *dh_sess) + } + } while (ret == -EBUSY); + +- ret = async_pause_job(dh_sess, &op, ASYNC_TASK_DH, idx); ++ ret = async_pause_job(dh_sess, &op, ASYNC_TASK_DH); + if (!ret) + goto err; + +diff --git a/src/uadk_prov_digest.c b/src/uadk_prov_digest.c +index ecb8d23..8d6bf06 100644 +--- a/src/uadk_prov_digest.c ++++ b/src/uadk_prov_digest.c +@@ -445,7 +445,7 @@ static int uadk_do_digest_async(struct digest_priv_ctx *priv, struct async_op *o + } + } while (ret == -EBUSY); + +- ret = async_pause_job(priv, op, ASYNC_TASK_DIGEST, idx); ++ ret = async_pause_job(priv, op, ASYNC_TASK_DIGEST); + if (!ret) + return 0; + return 1; +diff --git a/src/uadk_prov_rsa.c b/src/uadk_prov_rsa.c +index cd9b1e1..b60de0c 100644 +--- a/src/uadk_prov_rsa.c ++++ b/src/uadk_prov_rsa.c +@@ -1349,7 +1349,7 @@ static int rsa_do_crypto(struct uadk_rsa_sess *rsa_sess) + } + } while (ret == -EBUSY); + +- ret = async_pause_job(rsa_sess, &op, ASYNC_TASK_RSA, idx); ++ ret = async_pause_job(rsa_sess, &op, ASYNC_TASK_RSA); + if (!ret) + goto err; + +diff --git a/src/uadk_rsa.c b/src/uadk_rsa.c +index d0780a7..ca05ef7 100644 +--- a/src/uadk_rsa.c ++++ b/src/uadk_rsa.c +@@ -1118,7 +1118,7 @@ static int rsa_do_crypto(struct uadk_rsa_sess *rsa_sess) + } + } while (ret == -EBUSY); + +- ret = async_pause_job(rsa_sess, &op, ASYNC_TASK_RSA, idx); ++ ret = async_pause_job(rsa_sess, &op, ASYNC_TASK_RSA); + if (!ret) + goto err; + +-- +2.25.1 + diff --git a/0056-uadk_engine-support-aead-aes-gcm-algorithm.patch b/0056-uadk_engine-support-aead-aes-gcm-algorithm.patch new file mode 100644 index 0000000..93ca347 --- /dev/null +++ b/0056-uadk_engine-support-aead-aes-gcm-algorithm.patch @@ -0,0 +1,1729 @@ +From 2566ea8a058f1d4f6b472f73f9b3c74c5a6be743 Mon Sep 17 00:00:00 2001 +From: Wenkai Lin +Date: Thu, 9 Nov 2023 11:23:38 +0800 +Subject: [PATCH 56/63] uadk_engine: support aead aes-gcm algorithm + +OpenSSL EVP interface supports the AEAD mode in which +authentication and encryption and decryption are performed +at the same time, unload software computing to hardware +on the UADK engine. Currently, aes-128-gcm, aes-192-gcm, +and aes-256-gcm are supported. + +Signed-off-by: Wenkai Lin +--- + src/Makefile.am | 3 +- + src/uadk.h | 2 - + src/uadk_aead.c | 732 ++++++++++++++++++++++++++++++++++++++ + src/uadk_async.h | 1 + + src/uadk_cipher.c | 545 ++++++++++------------------ + src/uadk_cipher_adapter.c | 204 +++++++++++ + src/uadk_cipher_adapter.h | 36 ++ + src/uadk_engine_init.c | 24 +- + 8 files changed, 1173 insertions(+), 374 deletions(-) + create mode 100644 src/uadk_aead.c + create mode 100644 src/uadk_cipher_adapter.c + create mode 100644 src/uadk_cipher_adapter.h + +diff --git a/src/Makefile.am b/src/Makefile.am +index 668ba13..3806de3 100644 +--- a/src/Makefile.am ++++ b/src/Makefile.am +@@ -11,7 +11,8 @@ 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 ++ uadk_pkey.c uadk_dh.c uadk_ec.c uadk_ecx.c \ ++ uadk_aead.c uadk_cipher_adapter.c + + uadk_engine_la_LIBADD=-ldl $(WD_LIBS) -lpthread + uadk_engine_la_LDFLAGS=-module -version-number $(VERSION) +diff --git a/src/uadk.h b/src/uadk.h +index 5a98feb..4cf2c13 100644 +--- a/src/uadk.h ++++ b/src/uadk.h +@@ -28,8 +28,6 @@ enum { + HW_V3, + }; + +-int uadk_e_bind_cipher(ENGINE *e); +-void uadk_e_destroy_cipher(void); + int uadk_e_bind_digest(ENGINE *e); + void uadk_e_destroy_digest(void); + int uadk_e_bind_rsa(ENGINE *e); +diff --git a/src/uadk_aead.c b/src/uadk_aead.c +new file mode 100644 +index 0000000..64a5f5c +--- /dev/null ++++ b/src/uadk_aead.c +@@ -0,0 +1,732 @@ ++/* ++ * Copyright 2023 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 ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include "uadk_cipher_adapter.h" ++#include "uadk.h" ++#include "uadk_async.h" ++#include "uadk_utils.h" ++ ++#define RET_FAIL -1 ++#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 AES_GCM_CTR_LEN 4 ++#define AES_GCM_BLOCK_SIZE 16 ++#define AES_GCM_IV_LEN 12 ++#define AES_GCM_TAG_LEN 16 ++#define GCM_FLAG (EVP_CIPH_FLAG_DEFAULT_ASN1 | EVP_CIPH_GCM_MODE \ ++ | EVP_CIPH_CUSTOM_IV | EVP_CIPH_FLAG_AEAD_CIPHER \ ++ | EVP_CIPH_FLAG_CUSTOM_CIPHER | EVP_CIPH_ALWAYS_CALL_INIT) ++/* The max data length is 16M-512B */ ++#define AEAD_BLOCK_SIZE 0xFFFE00 ++ ++struct aead_priv_ctx { ++ handle_t sess; ++ struct wd_aead_sess_setup setup; ++ struct wd_aead_req req; ++ unsigned char *data; ++ unsigned char iv[AES_GCM_BLOCK_SIZE]; ++ unsigned char mac[AES_GCM_TAG_LEN]; ++ size_t last_update_bufflen; ++}; ++ ++struct aead_engine { ++ struct wd_ctx_config ctx_cfg; ++ struct wd_sched sched; ++ int numa_id; ++ int pid; ++ pthread_spinlock_t lock; ++}; ++ ++static struct aead_engine engine; ++ ++static EVP_CIPHER *uadk_aes_128_gcm; ++static EVP_CIPHER *uadk_aes_192_gcm; ++static EVP_CIPHER *uadk_aes_256_gcm; ++ ++static int uadk_e_aead_env_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 int uadk_e_aead_poll(void *ctx) ++{ ++ struct aead_priv_ctx *priv = (struct aead_priv_ctx *) ctx; ++ __u64 rx_cnt = 0; ++ __u32 recv = 0; ++ /* Poll one packet currently */ ++ int expt = 1; ++ int ret, idx; ++ ++ if (priv->req.op_type == WD_CIPHER_ENCRYPTION_DIGEST) ++ idx = CTX_ASYNC_ENC; ++ else ++ idx = CTX_ASYNC_DEC; ++ ++ do { ++ ret = wd_aead_poll_ctx(idx, expt, &recv); ++ if (!ret && recv == expt) ++ return 0; ++ else if (ret == -EAGAIN) ++ rx_cnt++; ++ else ++ return RET_FAIL; ++ } while (rx_cnt < ENGINE_RECV_MAX_CNT); ++ ++ fprintf(stderr, "failed to recv msg: timeout!\n"); ++ ++ return -ETIMEDOUT; ++} ++ ++static handle_t sched_single_aead_init(handle_t h_sched_ctx, void *sched_param) ++{ ++ struct sched_params *param = (struct sched_params *)sched_param; ++ struct sched_params *skey; ++ ++ skey = malloc(sizeof(struct sched_params)); ++ if (!skey) { ++ fprintf(stderr, "fail to alloc aead sched key!\n"); ++ return (handle_t)0; ++ } ++ ++ skey->numa_id = param->numa_id; ++ skey->type = param->type; ++ ++ return (handle_t)skey; ++} ++ ++static __u32 sched_single_pick_next_ctx(handle_t sched_ctx, void *sched_key, const int sched_mode) ++{ ++ struct sched_params *key = (struct sched_params *)sched_key; ++ ++ if (sched_mode) { ++ if (key->type == WD_CIPHER_ENCRYPTION_DIGEST) ++ return CTX_ASYNC_ENC; ++ else ++ return CTX_ASYNC_DEC; ++ } else { ++ if (key->type == WD_CIPHER_ENCRYPTION_DIGEST) ++ return CTX_SYNC_ENC; ++ else ++ return CTX_SYNC_DEC; ++ } ++} ++ ++static int sched_single_poll_policy(handle_t h_sched_ctx, __u32 expect, __u32 *count) ++{ ++ return 0; ++} ++ ++static int uadk_e_wd_aead_cipher_env_init(struct uacce_dev *dev) ++{ ++ int ret; ++ ++ ret = uadk_e_set_env("WD_AEAD_CTX_NUM", dev->numa_id); ++ if (ret) ++ return ret; ++ ++ ret = wd_aead_env_init(NULL); ++ ++ async_register_poll_fn(ASYNC_TASK_AEAD, uadk_e_aead_env_poll); ++ ++ return ret; ++} ++ ++static int uadk_e_wd_aead_cipher_init(struct uacce_dev *dev) ++{ ++ __u32 i, j; ++ int ret; ++ ++ engine.numa_id = dev->numa_id; ++ ++ ret = uadk_e_is_env_enabled("aead"); ++ if (ret) ++ return uadk_e_wd_aead_cipher_env_init(dev); ++ ++ memset(&engine.ctx_cfg, 0, sizeof(struct wd_ctx_config)); ++ engine.ctx_cfg.ctx_num = CTX_NUM; ++ engine.ctx_cfg.ctxs = calloc(CTX_NUM, sizeof(struct wd_ctx)); ++ if (!engine.ctx_cfg.ctxs) ++ return -ENOMEM; ++ ++ for (i = 0; i < CTX_NUM; i++) { ++ engine.ctx_cfg.ctxs[i].ctx = wd_request_ctx(dev); ++ if (!engine.ctx_cfg.ctxs[i].ctx) { ++ ret = -ENOMEM; ++ goto err_freectx; ++ } ++ } ++ ++ engine.ctx_cfg.ctxs[CTX_SYNC_ENC].op_type = CTX_TYPE_ENCRYPT; ++ engine.ctx_cfg.ctxs[CTX_SYNC_DEC].op_type = CTX_TYPE_DECRYPT; ++ engine.ctx_cfg.ctxs[CTX_SYNC_ENC].ctx_mode = CTX_MODE_SYNC; ++ engine.ctx_cfg.ctxs[CTX_SYNC_DEC].ctx_mode = CTX_MODE_SYNC; ++ ++ engine.ctx_cfg.ctxs[CTX_ASYNC_ENC].op_type = CTX_TYPE_ENCRYPT; ++ engine.ctx_cfg.ctxs[CTX_ASYNC_DEC].op_type = CTX_TYPE_DECRYPT; ++ engine.ctx_cfg.ctxs[CTX_ASYNC_ENC].ctx_mode = CTX_MODE_ASYNC; ++ engine.ctx_cfg.ctxs[CTX_ASYNC_DEC].ctx_mode = CTX_MODE_ASYNC; ++ ++ engine.sched.name = "sched_single"; ++ engine.sched.pick_next_ctx = sched_single_pick_next_ctx; ++ engine.sched.poll_policy = sched_single_poll_policy; ++ engine.sched.sched_init = sched_single_aead_init; ++ ++ ret = wd_aead_init(&engine.ctx_cfg, &engine.sched); ++ if (ret) ++ goto err_freectx; ++ ++ async_register_poll_fn(ASYNC_TASK_AEAD, uadk_e_aead_poll); ++ return ret; ++ ++err_freectx: ++ for (j = 0; j < i; j++) ++ wd_release_ctx(engine.ctx_cfg.ctxs[j].ctx); ++ ++ free(engine.ctx_cfg.ctxs); ++ ++ return ret; ++} ++ ++static int uadk_e_init_aead_cipher(void) ++{ ++ struct uacce_dev *dev; ++ int ret; ++ ++ if (engine.pid != getpid()) { ++ pthread_spin_lock(&engine.lock); ++ if (engine.pid == getpid()) { ++ pthread_spin_unlock(&engine.lock); ++ return 1; ++ } ++ ++ dev = wd_get_accel_dev("aead"); ++ if (!dev) { ++ pthread_spin_unlock(&engine.lock); ++ fprintf(stderr, "failed to get device for aead.\n"); ++ return 0; ++ } ++ ++ ret = uadk_e_wd_aead_cipher_init(dev); ++ if (ret < 0) { ++ pthread_spin_unlock(&engine.lock); ++ fprintf(stderr, "failed to initiate aead cipher.\n"); ++ free(dev); ++ return 0; ++ } ++ ++ engine.pid = getpid(); ++ pthread_spin_unlock(&engine.lock); ++ free(dev); ++ } ++ ++ return 1; ++} ++ ++static int uadk_e_ctx_init(struct aead_priv_ctx *priv, const unsigned char *ckey, int ckey_len) ++{ ++ struct sched_params params = {0}; ++ int ret; ++ ++ ret = uadk_e_init_aead_cipher(); ++ if (unlikely(!ret)) { ++ fprintf(stderr, "uadk failed to init aead HW!\n"); ++ return 0; ++ } ++ ++ params.type = priv->req.op_type; ++ ret = uadk_e_is_env_enabled("aead"); ++ if (ret) ++ params.type = 0; ++ ++ params.numa_id = engine.numa_id; ++ priv->setup.sched_param = ¶ms; ++ if (!priv->sess) { ++ priv->sess = wd_aead_alloc_sess(&priv->setup); ++ if (!priv->sess) { ++ fprintf(stderr, "uadk engine failed to alloc aead session!\n"); ++ return 0; ++ } ++ ret = wd_aead_set_authsize(priv->sess, AES_GCM_TAG_LEN); ++ if (ret < 0) { ++ fprintf(stderr, "uadk engine failed to set authsize!\n"); ++ goto out; ++ } ++ ++ ret = wd_aead_set_ckey(priv->sess, ckey, ckey_len); ++ if (ret) { ++ fprintf(stderr, "uadk engine failed to set ckey!\n"); ++ goto out; ++ } ++ priv->data = malloc(AEAD_BLOCK_SIZE << 1); ++ if (unlikely(!priv->data)) { ++ fprintf(stderr, "uadk engine failed to alloc data!\n"); ++ goto out; ++ } ++ } ++ ++ return 1; ++out: ++ wd_aead_free_sess(priv->sess); ++ priv->sess = 0; ++ return 0; ++} ++ ++static int uadk_e_aes_gcm_init(EVP_CIPHER_CTX *ctx, const unsigned char *ckey, ++ const unsigned char *iv, int enc) ++{ ++ struct aead_priv_ctx *priv = ++ (struct aead_priv_ctx *)EVP_CIPHER_CTX_get_cipher_data(ctx); ++ int ret, ckey_len; ++ ++ if (unlikely(!ckey)) ++ return 1; ++ ++ if (iv) ++ memcpy(priv->iv, iv, AES_GCM_IV_LEN); ++ ++ priv->setup.calg = WD_CIPHER_AES; ++ priv->setup.cmode = WD_CIPHER_GCM; ++ priv->setup.dalg = 0; ++ priv->setup.dmode = 0; ++ ++ priv->last_update_bufflen = 0; ++ priv->req.assoc_bytes = 0; ++ priv->req.out_bytes = 0; ++ priv->req.data_fmt = WD_FLAT_BUF; ++ ++ priv->req.iv = priv->iv; ++ priv->req.iv_bytes = AES_GCM_IV_LEN; ++ memset(priv->iv + AES_GCM_IV_LEN, 0, AES_GCM_CTR_LEN); ++ ++ priv->req.mac = priv->mac; ++ priv->req.mac_bytes = AES_GCM_TAG_LEN; ++ ++ if (enc) ++ priv->req.op_type = WD_CIPHER_ENCRYPTION_DIGEST; ++ else ++ priv->req.op_type = WD_CIPHER_DECRYPTION_DIGEST; ++ ++ ckey_len = EVP_CIPHER_CTX_key_length(ctx); ++ ret = uadk_e_ctx_init(priv, ckey, ckey_len); ++ if (!ret) ++ return 0; ++ ++ return 1; ++} ++ ++static int uadk_e_aes_gcm_cleanup(EVP_CIPHER_CTX *ctx) ++{ ++ struct aead_priv_ctx *priv = ++ (struct aead_priv_ctx *)EVP_CIPHER_CTX_get_cipher_data(ctx); ++ ++ if (priv->sess) { ++ wd_aead_free_sess(priv->sess); ++ priv->sess = 0; ++ } ++ ++ if (priv->data) { ++ free(priv->data); ++ priv->data = NULL; ++ } ++ ++ return 1; ++} ++ ++static int uadk_e_aes_gcm_set_ctrl(EVP_CIPHER_CTX *ctx, int type, int arg, void *ptr) ++{ ++ struct aead_priv_ctx *priv = ++ (struct aead_priv_ctx *)EVP_CIPHER_CTX_get_cipher_data(ctx); ++ int enc = EVP_CIPHER_CTX_encrypting(ctx); ++ ++ switch (type) { ++ case EVP_CTRL_INIT: ++ priv->req.iv_bytes = 0; ++ return 1; ++ case EVP_CTRL_GET_IVLEN: ++ *(int *)ptr = priv->req.iv_bytes; ++ return 1; ++ case EVP_CTRL_GCM_SET_IVLEN: ++ if (arg != AES_GCM_IV_LEN) { ++ fprintf(stderr, "gcm only support 12 bytes.\n"); ++ return 0; ++ } ++ return 1; ++ case EVP_CTRL_GCM_GET_TAG: ++ if (arg <= 0 || arg > AES_GCM_TAG_LEN) { ++ fprintf(stderr, "TAG length invalid.\n"); ++ return 0; ++ } ++ ++ if (EVP_CIPHER_CTX_buf_noconst(ctx) == NULL || ptr == NULL) { ++ fprintf(stderr, "ctx memory pointer is invalid.\n"); ++ return 0; ++ } ++ ++ memcpy(ptr, EVP_CIPHER_CTX_buf_noconst(ctx), arg); ++ return 1; ++ case EVP_CTRL_GCM_SET_TAG: ++ if (arg != AES_GCM_TAG_LEN || enc) { ++ fprintf(stderr, "cannot set tag when encrypt or arg is invalid.\n"); ++ return 0; ++ } ++ ++ if (EVP_CIPHER_CTX_buf_noconst(ctx) == NULL || ptr == NULL) { ++ fprintf(stderr, "ctx memory pointer is invalid.\n"); ++ return 0; ++ } ++ ++ memcpy(EVP_CIPHER_CTX_buf_noconst(ctx), ptr, AES_GCM_TAG_LEN); ++ return 1; ++ default: ++ fprintf(stderr, "unsupported ctrl type: %d\n", type); ++ return 0; ++ } ++} ++ ++static int uadk_e_do_aes_gcm_first(EVP_CIPHER_CTX *ctx, unsigned char *out, ++ const unsigned char *in, size_t inlen) ++{ ++ struct aead_priv_ctx *priv = ++ (struct aead_priv_ctx *)EVP_CIPHER_CTX_get_cipher_data(ctx); ++ int ret; ++ ++ priv->req.assoc_bytes = inlen; ++ ++ if (ASYNC_get_current_job()) { ++ memcpy(priv->data + priv->last_update_bufflen, in, inlen); ++ priv->last_update_bufflen += inlen; ++ return 1; ++ } ++ ++ priv->req.src = (unsigned char *)in; ++ priv->req.msg_state = AEAD_MSG_FIRST; ++ ++ ret = wd_do_aead_sync(priv->sess, &priv->req); ++ if (ret < 0) { ++ fprintf(stderr, "do sec aead first operation failed, ret:%d!\n", ret); ++ return RET_FAIL; ++ } ++ ++ return 1; ++} ++ ++static int uadk_e_hw_update(struct aead_priv_ctx *priv, unsigned char *out, ++ unsigned char *in, size_t inlen) ++{ ++ int ret; ++ ++ priv->req.src = in; ++ priv->req.dst = out; ++ priv->req.in_bytes = inlen; ++ priv->req.msg_state = AEAD_MSG_MIDDLE; ++ ret = wd_do_aead_sync(priv->sess, &priv->req); ++ if (ret < 0) { ++ fprintf(stderr, "do sec aead update operation failed, ret:%d!\n", ret); ++ return RET_FAIL; ++ } ++ ++ return 0; ++} ++ ++static int uadk_e_cache_data(struct aead_priv_ctx *priv, const unsigned char *in, size_t inlen) ++{ ++ if (ASYNC_get_current_job() || !priv->req.assoc_bytes) { ++ if (priv->last_update_bufflen + inlen > AEAD_BLOCK_SIZE) { ++ fprintf(stderr, "aead input data length is too long!\n"); ++ return RET_FAIL; ++ } ++ memcpy(priv->data + priv->last_update_bufflen, in, inlen); ++ priv->last_update_bufflen += inlen; ++ return 0; ++ } ++ ++ return 1; ++} ++ ++static int uadk_e_do_aes_gcm_update(EVP_CIPHER_CTX *ctx, unsigned char *out, ++ const unsigned char *in, size_t inlen) ++{ ++ struct aead_priv_ctx *priv = ++ (struct aead_priv_ctx *)EVP_CIPHER_CTX_get_cipher_data(ctx); ++ int ret; ++ ++ ret = uadk_e_cache_data(priv, in, inlen); ++ if (ret <= 0) ++ return ret; ++ ++ ret = uadk_e_hw_update(priv, out, in, inlen); ++ if (ret < 0) ++ return RET_FAIL; ++ ++ return inlen; ++} ++ ++static void *uadk_e_aead_cb(struct wd_aead_req *req, void *data) ++{ ++ struct uadk_e_cb_info *cb_param; ++ struct async_op *op; ++ ++ if (!req) ++ return NULL; ++ ++ cb_param = req->cb_param; ++ if (!cb_param) ++ return NULL; ++ ++ 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_aead_async(struct aead_priv_ctx *priv, struct async_op *op) ++{ ++ struct uadk_e_cb_info *cb_param; ++ int ret = 0; ++ int idx; ++ ++ priv->req.in_bytes = priv->last_update_bufflen - priv->req.assoc_bytes; ++ priv->req.dst = priv->data + AEAD_BLOCK_SIZE; ++ ++ cb_param = malloc(sizeof(struct uadk_e_cb_info)); ++ if (!cb_param) { ++ fprintf(stderr, "failed to alloc cb_param.\n"); ++ return ret; ++ } ++ ++ cb_param->op = op; ++ cb_param->priv = priv; ++ priv->req.cb = uadk_e_aead_cb; ++ priv->req.cb_param = cb_param; ++ ++ ret = async_get_free_task(&idx); ++ if (!ret) ++ goto free_cb_param; ++ ++ op->idx = idx; ++ do { ++ ret = wd_do_aead_async(priv->sess, &priv->req); ++ if (ret < 0 && ret != -EBUSY) { ++ fprintf(stderr, "do sec aead async failed.\n"); ++ async_free_poll_task(op->idx, 0); ++ ret = 0; ++ goto free_cb_param; ++ } ++ } while (ret == -EBUSY); ++ ++ ret = async_pause_job(priv, op, ASYNC_TASK_AEAD); ++ ++free_cb_param: ++ free(cb_param); ++ return ret; ++} ++ ++static int uadk_e_do_aes_gcm_final(EVP_CIPHER_CTX *ctx, unsigned char *out, ++ const unsigned char *in, size_t inlen) ++{ ++ struct aead_priv_ctx *priv = ++ (struct aead_priv_ctx *)EVP_CIPHER_CTX_get_cipher_data(ctx); ++ unsigned char *ctx_buf = EVP_CIPHER_CTX_buf_noconst(ctx); ++ struct async_op *op; ++ int ret, enc; ++ ++ op = malloc(sizeof(struct async_op)); ++ if (!op) ++ return RET_FAIL; ++ ++ ret = async_setup_async_event_notification(op); ++ if (unlikely(!ret)) { ++ fprintf(stderr, "failed to setup async event notification.\n"); ++ free(op); ++ return RET_FAIL; ++ } ++ ++ if (priv->req.assoc_bytes && !op->job) ++ priv->req.msg_state = AEAD_MSG_END; ++ else ++ priv->req.msg_state = AEAD_MSG_BLOCK; ++ ++ enc = EVP_CIPHER_CTX_encrypting(ctx); ++ if (!enc) ++ memcpy(priv->req.mac, ctx_buf, AES_GCM_TAG_LEN); ++ ++ priv->req.src = priv->data; ++ if (!op->job) { ++ priv->req.in_bytes = priv->last_update_bufflen; ++ priv->req.dst = out; ++ ret = wd_do_aead_sync(priv->sess, &priv->req); ++ if (ret < 0) { ++ fprintf(stderr, "do sec aead final operation failed, ret: %d!\n", ret); ++ goto out; ++ } ++ } else { ++ ret = do_aead_async(priv, op); ++ if (!ret) ++ goto out; ++ ++ memcpy(out, priv->req.dst + priv->req.assoc_bytes, priv->req.in_bytes); ++ } ++ ++ if (enc) ++ memcpy(ctx_buf, priv->req.mac, AES_GCM_TAG_LEN); ++ ++ priv->last_update_bufflen = 0; ++ ++ free(op); ++ return priv->req.in_bytes; ++ ++out: ++ (void)async_clear_async_event_notification(); ++ free(op); ++ return RET_FAIL; ++} ++ ++static int uadk_e_do_aes_gcm(EVP_CIPHER_CTX *ctx, unsigned char *out, ++ const unsigned char *in, size_t inlen) ++{ ++ int ret; ++ ++ if (in) { ++ if (out == NULL) ++ return uadk_e_do_aes_gcm_first(ctx, out, in, inlen); ++ ++ return uadk_e_do_aes_gcm_update(ctx, out, in, inlen); ++ } ++ ++ return uadk_e_do_aes_gcm_final(ctx, out, NULL, 0); ++} ++ ++#define UADK_AEAD_DESCR(name, block_size, key_size, iv_len, flags, ctx_size, \ ++ init, cipher, cleanup, set_params, get_params, ctrl) \ ++do {\ ++ uadk_##name = EVP_CIPHER_meth_new(NID_##name, block_size, key_size); \ ++ if (uadk_##name == 0 || \ ++ !EVP_CIPHER_meth_set_iv_length(uadk_##name, iv_len) || \ ++ !EVP_CIPHER_meth_set_flags(uadk_##name, flags) || \ ++ !EVP_CIPHER_meth_set_impl_ctx_size(uadk_##name, ctx_size) || \ ++ !EVP_CIPHER_meth_set_init(uadk_##name, init) || \ ++ !EVP_CIPHER_meth_set_do_cipher(uadk_##name, cipher) || \ ++ !EVP_CIPHER_meth_set_cleanup(uadk_##name, cleanup) || \ ++ !EVP_CIPHER_meth_set_set_asn1_params(uadk_##name, set_params) || \ ++ !EVP_CIPHER_meth_set_get_asn1_params(uadk_##name, get_params) || \ ++ !EVP_CIPHER_meth_set_ctrl(uadk_##name, ctrl)) \ ++ return 0;\ ++} while (0) ++ ++EVP_CIPHER *uadk_create_gcm_cipher_meth(int nid) ++{ ++ EVP_CIPHER *aead = NULL; ++ ++ switch (nid) { ++ case NID_aes_128_gcm: ++ UADK_AEAD_DESCR(aes_128_gcm, AES_GCM_BLOCK_SIZE, 16, AES_GCM_IV_LEN, ++ GCM_FLAG, sizeof(struct aead_priv_ctx), ++ uadk_e_aes_gcm_init, uadk_e_do_aes_gcm, uadk_e_aes_gcm_cleanup, ++ (EVP_CIPH_FLAG_DEFAULT_ASN1 ? NULL : EVP_CIPHER_set_asn1_iv), ++ (EVP_CIPH_FLAG_DEFAULT_ASN1 ? NULL : EVP_CIPHER_get_asn1_iv), ++ uadk_e_aes_gcm_set_ctrl); ++ aead = uadk_aes_128_gcm; ++ break; ++ case NID_aes_192_gcm: ++ UADK_AEAD_DESCR(aes_192_gcm, AES_GCM_BLOCK_SIZE, 24, AES_GCM_IV_LEN, ++ GCM_FLAG, sizeof(struct aead_priv_ctx), ++ uadk_e_aes_gcm_init, uadk_e_do_aes_gcm, uadk_e_aes_gcm_cleanup, ++ (EVP_CIPH_FLAG_DEFAULT_ASN1 ? NULL : EVP_CIPHER_set_asn1_iv), ++ (EVP_CIPH_FLAG_DEFAULT_ASN1 ? NULL : EVP_CIPHER_get_asn1_iv), ++ uadk_e_aes_gcm_set_ctrl); ++ aead = uadk_aes_192_gcm; ++ break; ++ case NID_aes_256_gcm: ++ UADK_AEAD_DESCR(aes_256_gcm, AES_GCM_BLOCK_SIZE, 32, AES_GCM_IV_LEN, ++ GCM_FLAG, sizeof(struct aead_priv_ctx), ++ uadk_e_aes_gcm_init, uadk_e_do_aes_gcm, uadk_e_aes_gcm_cleanup, ++ (EVP_CIPH_FLAG_DEFAULT_ASN1 ? NULL : EVP_CIPHER_set_asn1_iv), ++ (EVP_CIPH_FLAG_DEFAULT_ASN1 ? NULL : EVP_CIPHER_get_asn1_iv), ++ uadk_e_aes_gcm_set_ctrl); ++ aead = uadk_aes_256_gcm; ++ break; ++ default: ++ aead = NULL; ++ break; ++ } ++ ++ return aead; ++} ++ ++static void destroy_aead(struct engine_cipher_info *info, int num) ++{ ++ __u32 i; ++ ++ for (i = 0; i < num; i++) { ++ if (info[i].cipher != NULL) { ++ EVP_CIPHER_meth_free(info[i].cipher); ++ info[i].cipher = NULL; ++ } ++ } ++} ++ ++void uadk_e_destroy_aead(struct engine_cipher_info *info, int num) ++{ ++ __u32 i; ++ int ret; ++ ++ if (engine.pid == getpid()) { ++ ret = uadk_e_is_env_enabled("aead"); ++ if (ret) { ++ wd_aead_env_uninit(); ++ } else { ++ wd_aead_uninit(); ++ for (i = 0; i < engine.ctx_cfg.ctx_num; i++) ++ wd_release_ctx(engine.ctx_cfg.ctxs[i].ctx); ++ ++ free(engine.ctx_cfg.ctxs); ++ } ++ engine.pid = 0; ++ } ++ ++ pthread_spin_destroy(&engine.lock); ++ destroy_aead(info, num); ++} +diff --git a/src/uadk_async.h b/src/uadk_async.h +index 1208c30..678e392 100644 +--- a/src/uadk_async.h ++++ b/src/uadk_async.h +@@ -41,6 +41,7 @@ typedef int (*async_recv_t)(void *ctx); + enum task_type { + ASYNC_TASK_CIPHER, + ASYNC_TASK_DIGEST, ++ ASYNC_TASK_AEAD, + ASYNC_TASK_RSA, + ASYNC_TASK_DH, + ASYNC_TASK_ECC, +diff --git a/src/uadk_cipher.c b/src/uadk_cipher.c +index ed25787..73be09d 100644 +--- a/src/uadk_cipher.c ++++ b/src/uadk_cipher.c +@@ -25,6 +25,7 @@ + #include + #include "uadk.h" + #include "uadk_async.h" ++#include "uadk_cipher_adapter.h" + + #define UADK_DO_SOFT (-0xE0) + #define CTX_SYNC_ENC 0 +@@ -74,54 +75,8 @@ struct cipher_info { + __u32 out_bytes; + }; + +-static int platform; +- + #define SMALL_PACKET_OFFLOAD_THRESHOLD_DEFAULT 192 + +-static int cipher_hw_v2_nids[] = { +- NID_aes_128_cbc, +- NID_aes_192_cbc, +- NID_aes_256_cbc, +- NID_aes_128_ecb, +- NID_aes_192_ecb, +- NID_aes_256_ecb, +- NID_aes_128_xts, +- NID_aes_256_xts, +- NID_sm4_cbc, +- NID_des_ede3_cbc, +- NID_des_ede3_ecb, +- NID_sm4_ecb, +- 0, +-}; +- +-static int cipher_hw_v3_nids[] = { +- NID_aes_128_cbc, +- NID_aes_192_cbc, +- NID_aes_256_cbc, +- NID_aes_128_ctr, +- NID_aes_192_ctr, +- NID_aes_256_ctr, +- NID_aes_128_ecb, +- NID_aes_192_ecb, +- NID_aes_256_ecb, +- NID_aes_128_xts, +- NID_aes_256_xts, +- NID_sm4_cbc, +- NID_sm4_ecb, +- NID_des_ede3_cbc, +- NID_des_ede3_ecb, +- NID_aes_128_cfb128, +- NID_aes_192_cfb128, +- NID_aes_256_cfb128, +- NID_aes_128_ofb128, +- NID_aes_192_ofb128, +- NID_aes_256_ofb128, +- NID_sm4_cfb128, +- NID_sm4_ofb128, +- NID_sm4_ctr, +- 0, +-}; +- + static EVP_CIPHER *uadk_aes_128_cbc; + static EVP_CIPHER *uadk_aes_192_cbc; + static EVP_CIPHER *uadk_aes_256_cbc; +@@ -328,130 +283,6 @@ static void uadk_e_cipher_sw_cleanup(EVP_CIPHER_CTX *ctx) + } + } + +-static int uadk_get_accel_platform(char *alg_name) +-{ +- struct uacce_dev *dev; +- +- dev = wd_get_accel_dev(alg_name); +- if (dev == NULL) +- return 0; +- +- if (!strcmp(dev->api, "hisi_qm_v2")) +- platform = HW_V2; +- else +- platform = HW_V3; +- free(dev); +- +- return 1; +-} +- +-static int uadk_e_engine_ciphers(ENGINE *e, const EVP_CIPHER **cipher, +- const int **nids, int nid) +-{ +- int *cipher_nids; +- __u32 size, i; +- int ret = 1; +- +- if (platform == HW_V2) { +- size = (sizeof(cipher_hw_v2_nids) - 1) / sizeof(int); +- cipher_nids = cipher_hw_v2_nids; +- } else { +- size = (sizeof(cipher_hw_v3_nids) - 1) / sizeof(int); +- cipher_nids = cipher_hw_v3_nids; +- } +- +- if (!cipher) { +- *nids = cipher_nids; +- return size; +- } +- +- for (i = 0; i < size; i++) { +- if (nid == cipher_nids[i]) +- break; +- } +- +- switch (nid) { +- case NID_aes_128_cbc: +- *cipher = uadk_aes_128_cbc; +- break; +- case NID_aes_192_cbc: +- *cipher = uadk_aes_192_cbc; +- break; +- case NID_aes_256_cbc: +- *cipher = uadk_aes_256_cbc; +- break; +- case NID_aes_128_ctr: +- *cipher = uadk_aes_128_ctr; +- break; +- case NID_aes_192_ctr: +- *cipher = uadk_aes_192_ctr; +- break; +- case NID_aes_256_ctr: +- *cipher = uadk_aes_256_ctr; +- break; +- case NID_aes_128_ecb: +- *cipher = uadk_aes_128_ecb; +- break; +- case NID_aes_192_ecb: +- *cipher = uadk_aes_192_ecb; +- break; +- case NID_aes_256_ecb: +- *cipher = uadk_aes_256_ecb; +- break; +- case NID_aes_128_xts: +- *cipher = uadk_aes_128_xts; +- break; +- case NID_aes_256_xts: +- *cipher = uadk_aes_256_xts; +- break; +- case NID_sm4_cbc: +- *cipher = uadk_sm4_cbc; +- break; +- case NID_sm4_ecb: +- *cipher = uadk_sm4_ecb; +- break; +- case NID_des_ede3_cbc: +- *cipher = uadk_des_ede3_cbc; +- break; +- case NID_des_ede3_ecb: +- *cipher = uadk_des_ede3_ecb; +- break; +- case NID_aes_128_ofb128: +- *cipher = uadk_aes_128_ofb128; +- break; +- case NID_aes_192_ofb128: +- *cipher = uadk_aes_192_ofb128; +- break; +- case NID_aes_256_ofb128: +- *cipher = uadk_aes_256_ofb128; +- break; +- case NID_aes_128_cfb128: +- *cipher = uadk_aes_128_cfb128; +- break; +- case NID_aes_192_cfb128: +- *cipher = uadk_aes_192_cfb128; +- break; +- case NID_aes_256_cfb128: +- *cipher = uadk_aes_256_cfb128; +- break; +- case NID_sm4_ofb128: +- *cipher = uadk_sm4_ofb128; +- break; +- case NID_sm4_cfb128: +- *cipher = uadk_sm4_cfb128; +- break; +- case NID_sm4_ctr: +- *cipher = uadk_sm4_ctr; +- break; +- default: +- ret = 0; +- *cipher = NULL; +- break; +- } +- +- return ret; +-} +- + static handle_t sched_single_init(handle_t h_sched_ctx, void *sched_param) + { + struct sched_params *param = (struct sched_params *)sched_param; +@@ -560,7 +391,8 @@ static int uadk_e_wd_cipher_env_init(struct uacce_dev *dev) + + static int uadk_e_wd_cipher_init(struct uacce_dev *dev) + { +- int ret, i, j; ++ __u32 i, j; ++ int ret; + + g_cipher_engine.numa_id = dev->numa_id; + +@@ -978,210 +810,193 @@ do { \ + return 0; \ + } while (0) + +-static int bind_v2_cipher(void) +-{ +- UADK_CIPHER_DESCR(aes_128_cbc, 16, 16, 16, EVP_CIPH_CBC_MODE, +- sizeof(struct cipher_priv_ctx), uadk_e_cipher_init, +- uadk_e_do_cipher, uadk_e_cipher_cleanup, +- EVP_CIPHER_set_asn1_iv, EVP_CIPHER_get_asn1_iv); +- UADK_CIPHER_DESCR(aes_192_cbc, 16, 24, 16, EVP_CIPH_CBC_MODE, +- sizeof(struct cipher_priv_ctx), uadk_e_cipher_init, +- uadk_e_do_cipher, uadk_e_cipher_cleanup, +- EVP_CIPHER_set_asn1_iv, EVP_CIPHER_get_asn1_iv); +- UADK_CIPHER_DESCR(aes_256_cbc, 16, 32, 16, EVP_CIPH_CBC_MODE, +- sizeof(struct cipher_priv_ctx), uadk_e_cipher_init, +- uadk_e_do_cipher, uadk_e_cipher_cleanup, +- EVP_CIPHER_set_asn1_iv, EVP_CIPHER_get_asn1_iv); +- UADK_CIPHER_DESCR(aes_128_ecb, 16, 16, 0, EVP_CIPH_ECB_MODE, +- sizeof(struct cipher_priv_ctx), uadk_e_cipher_init, +- uadk_e_do_cipher, uadk_e_cipher_cleanup, +- EVP_CIPHER_set_asn1_iv, EVP_CIPHER_get_asn1_iv); +- UADK_CIPHER_DESCR(aes_192_ecb, 16, 24, 0, EVP_CIPH_ECB_MODE, +- sizeof(struct cipher_priv_ctx), uadk_e_cipher_init, +- uadk_e_do_cipher, uadk_e_cipher_cleanup, +- EVP_CIPHER_set_asn1_iv, EVP_CIPHER_get_asn1_iv); +- UADK_CIPHER_DESCR(aes_256_ecb, 16, 32, 0, EVP_CIPH_ECB_MODE, +- sizeof(struct cipher_priv_ctx), uadk_e_cipher_init, +- uadk_e_do_cipher, uadk_e_cipher_cleanup, +- EVP_CIPHER_set_asn1_iv, EVP_CIPHER_get_asn1_iv); +- UADK_CIPHER_DESCR(aes_128_xts, 1, 32, 16, EVP_CIPH_XTS_MODE | EVP_CIPH_CUSTOM_IV, +- sizeof(struct cipher_priv_ctx), uadk_e_cipher_init, +- uadk_e_do_cipher, uadk_e_cipher_cleanup, +- EVP_CIPHER_set_asn1_iv, EVP_CIPHER_get_asn1_iv); +- UADK_CIPHER_DESCR(aes_256_xts, 1, 64, 16, EVP_CIPH_XTS_MODE | EVP_CIPH_CUSTOM_IV, +- sizeof(struct cipher_priv_ctx), uadk_e_cipher_init, +- uadk_e_do_cipher, uadk_e_cipher_cleanup, +- EVP_CIPHER_set_asn1_iv, EVP_CIPHER_get_asn1_iv); +- UADK_CIPHER_DESCR(sm4_cbc, 16, 16, 16, EVP_CIPH_CBC_MODE, +- sizeof(struct cipher_priv_ctx), uadk_e_cipher_init, +- uadk_e_do_cipher, uadk_e_cipher_cleanup, +- EVP_CIPHER_set_asn1_iv, EVP_CIPHER_get_asn1_iv); +- UADK_CIPHER_DESCR(des_ede3_cbc, 8, 24, 8, EVP_CIPH_CBC_MODE, +- sizeof(struct cipher_priv_ctx), uadk_e_cipher_init, +- uadk_e_do_cipher, uadk_e_cipher_cleanup, +- EVP_CIPHER_set_asn1_iv, EVP_CIPHER_get_asn1_iv); +- UADK_CIPHER_DESCR(des_ede3_ecb, 8, 24, 0, EVP_CIPH_ECB_MODE, +- sizeof(struct cipher_priv_ctx), uadk_e_cipher_init, +- uadk_e_do_cipher, uadk_e_cipher_cleanup, +- EVP_CIPHER_set_asn1_iv, EVP_CIPHER_get_asn1_iv); +- UADK_CIPHER_DESCR(sm4_ecb, 16, 16, 0, EVP_CIPH_ECB_MODE, +- sizeof(struct cipher_priv_ctx), uadk_e_cipher_init, +- uadk_e_do_cipher, uadk_e_cipher_cleanup, +- EVP_CIPHER_set_asn1_iv, EVP_CIPHER_get_asn1_iv); +- +- return 0; +-} +- +-static int bind_v3_cipher(void) +-{ +- UADK_CIPHER_DESCR(aes_128_ctr, 1, 16, 16, EVP_CIPH_CTR_MODE, +- sizeof(struct cipher_priv_ctx), uadk_e_cipher_init, +- uadk_e_do_cipher, uadk_e_cipher_cleanup, +- EVP_CIPHER_set_asn1_iv, EVP_CIPHER_get_asn1_iv); +- UADK_CIPHER_DESCR(aes_192_ctr, 1, 24, 16, EVP_CIPH_CTR_MODE, +- sizeof(struct cipher_priv_ctx), uadk_e_cipher_init, +- uadk_e_do_cipher, uadk_e_cipher_cleanup, +- EVP_CIPHER_set_asn1_iv, EVP_CIPHER_get_asn1_iv); +- UADK_CIPHER_DESCR(aes_256_ctr, 1, 32, 16, EVP_CIPH_CTR_MODE, +- sizeof(struct cipher_priv_ctx), uadk_e_cipher_init, +- uadk_e_do_cipher, uadk_e_cipher_cleanup, +- EVP_CIPHER_set_asn1_iv, EVP_CIPHER_get_asn1_iv); +- UADK_CIPHER_DESCR(aes_128_ofb128, 1, 16, 16, EVP_CIPH_OFB_MODE, +- sizeof(struct cipher_priv_ctx), uadk_e_cipher_init, +- uadk_e_do_cipher, uadk_e_cipher_cleanup, +- EVP_CIPHER_set_asn1_iv, EVP_CIPHER_get_asn1_iv); +- UADK_CIPHER_DESCR(aes_192_ofb128, 1, 24, 16, EVP_CIPH_OFB_MODE, +- sizeof(struct cipher_priv_ctx), uadk_e_cipher_init, +- uadk_e_do_cipher, uadk_e_cipher_cleanup, +- EVP_CIPHER_set_asn1_iv, EVP_CIPHER_get_asn1_iv); +- UADK_CIPHER_DESCR(aes_256_ofb128, 1, 32, 16, EVP_CIPH_OFB_MODE, +- sizeof(struct cipher_priv_ctx), uadk_e_cipher_init, +- uadk_e_do_cipher, uadk_e_cipher_cleanup, +- EVP_CIPHER_set_asn1_iv, EVP_CIPHER_get_asn1_iv); +- UADK_CIPHER_DESCR(aes_128_cfb128, 1, 16, 16, EVP_CIPH_CFB_MODE, +- sizeof(struct cipher_priv_ctx), uadk_e_cipher_init, +- uadk_e_do_cipher, uadk_e_cipher_cleanup, +- EVP_CIPHER_set_asn1_iv, EVP_CIPHER_get_asn1_iv); +- UADK_CIPHER_DESCR(aes_192_cfb128, 1, 24, 16, EVP_CIPH_CFB_MODE, +- sizeof(struct cipher_priv_ctx), uadk_e_cipher_init, +- uadk_e_do_cipher, uadk_e_cipher_cleanup, +- EVP_CIPHER_set_asn1_iv, EVP_CIPHER_get_asn1_iv); +- UADK_CIPHER_DESCR(aes_256_cfb128, 1, 32, 16, EVP_CIPH_CFB_MODE, +- sizeof(struct cipher_priv_ctx), uadk_e_cipher_init, +- uadk_e_do_cipher, uadk_e_cipher_cleanup, +- EVP_CIPHER_set_asn1_iv, EVP_CIPHER_get_asn1_iv); +- UADK_CIPHER_DESCR(sm4_ofb128, 1, 16, 16, EVP_CIPH_OFB_MODE, +- sizeof(struct cipher_priv_ctx), uadk_e_cipher_init, +- uadk_e_do_cipher, uadk_e_cipher_cleanup, +- EVP_CIPHER_set_asn1_iv, EVP_CIPHER_get_asn1_iv); +- UADK_CIPHER_DESCR(sm4_cfb128, 1, 16, 16, EVP_CIPH_OFB_MODE, +- sizeof(struct cipher_priv_ctx), uadk_e_cipher_init, +- uadk_e_do_cipher, uadk_e_cipher_cleanup, +- EVP_CIPHER_set_asn1_iv, EVP_CIPHER_get_asn1_iv); +- UADK_CIPHER_DESCR(sm4_ctr, 1, 16, 16, EVP_CIPH_CTR_MODE, +- sizeof(struct cipher_priv_ctx), uadk_e_cipher_init, +- uadk_e_do_cipher, uadk_e_cipher_cleanup, +- EVP_CIPHER_set_asn1_iv, EVP_CIPHER_get_asn1_iv); +- +- return 0; +-} +- +-int uadk_e_bind_cipher(ENGINE *e) ++EVP_CIPHER *uadk_create_cipher_meth(int nid) + { +- int ret; ++ EVP_CIPHER *cipher; + +- ret = uadk_get_accel_platform("cipher"); +- if (!ret) { +- fprintf(stderr, "failed to get accel hardware version.\n"); +- return 0; ++ switch (nid) { ++ case NID_aes_128_cbc: ++ UADK_CIPHER_DESCR(aes_128_cbc, 16, 16, 16, EVP_CIPH_CBC_MODE, ++ sizeof(struct cipher_priv_ctx), uadk_e_cipher_init, ++ uadk_e_do_cipher, uadk_e_cipher_cleanup, ++ EVP_CIPHER_set_asn1_iv, EVP_CIPHER_get_asn1_iv); ++ cipher = uadk_aes_128_cbc; ++ break; ++ case NID_aes_192_cbc: ++ UADK_CIPHER_DESCR(aes_192_cbc, 16, 24, 16, EVP_CIPH_CBC_MODE, ++ sizeof(struct cipher_priv_ctx), uadk_e_cipher_init, ++ uadk_e_do_cipher, uadk_e_cipher_cleanup, ++ EVP_CIPHER_set_asn1_iv, EVP_CIPHER_get_asn1_iv); ++ cipher = uadk_aes_192_cbc; ++ break; ++ case NID_aes_256_cbc: ++ UADK_CIPHER_DESCR(aes_256_cbc, 16, 32, 16, EVP_CIPH_CBC_MODE, ++ sizeof(struct cipher_priv_ctx), uadk_e_cipher_init, ++ uadk_e_do_cipher, uadk_e_cipher_cleanup, ++ EVP_CIPHER_set_asn1_iv, EVP_CIPHER_get_asn1_iv); ++ cipher = uadk_aes_256_cbc; ++ break; ++ case NID_aes_128_ecb: ++ UADK_CIPHER_DESCR(aes_128_ecb, 16, 16, 0, EVP_CIPH_ECB_MODE, ++ sizeof(struct cipher_priv_ctx), uadk_e_cipher_init, ++ uadk_e_do_cipher, uadk_e_cipher_cleanup, ++ EVP_CIPHER_set_asn1_iv, EVP_CIPHER_get_asn1_iv); ++ cipher = uadk_aes_128_ecb; ++ break; ++ case NID_aes_192_ecb: ++ UADK_CIPHER_DESCR(aes_192_ecb, 16, 24, 0, EVP_CIPH_ECB_MODE, ++ sizeof(struct cipher_priv_ctx), uadk_e_cipher_init, ++ uadk_e_do_cipher, uadk_e_cipher_cleanup, ++ EVP_CIPHER_set_asn1_iv, EVP_CIPHER_get_asn1_iv); ++ cipher = uadk_aes_192_ecb; ++ break; ++ case NID_aes_256_ecb: ++ UADK_CIPHER_DESCR(aes_256_ecb, 16, 32, 0, EVP_CIPH_ECB_MODE, ++ sizeof(struct cipher_priv_ctx), uadk_e_cipher_init, ++ uadk_e_do_cipher, uadk_e_cipher_cleanup, ++ EVP_CIPHER_set_asn1_iv, EVP_CIPHER_get_asn1_iv); ++ cipher = uadk_aes_256_ecb; ++ break; ++ case NID_aes_128_xts: ++ UADK_CIPHER_DESCR(aes_128_xts, 1, 32, 16, EVP_CIPH_XTS_MODE | EVP_CIPH_CUSTOM_IV, ++ sizeof(struct cipher_priv_ctx), uadk_e_cipher_init, ++ uadk_e_do_cipher, uadk_e_cipher_cleanup, ++ EVP_CIPHER_set_asn1_iv, EVP_CIPHER_get_asn1_iv); ++ cipher = uadk_aes_128_xts; ++ break; ++ case NID_aes_256_xts: ++ UADK_CIPHER_DESCR(aes_256_xts, 1, 64, 16, EVP_CIPH_XTS_MODE | EVP_CIPH_CUSTOM_IV, ++ sizeof(struct cipher_priv_ctx), uadk_e_cipher_init, ++ uadk_e_do_cipher, uadk_e_cipher_cleanup, ++ EVP_CIPHER_set_asn1_iv, EVP_CIPHER_get_asn1_iv); ++ cipher = uadk_aes_256_xts; ++ break; ++ case NID_sm4_cbc: ++ UADK_CIPHER_DESCR(sm4_cbc, 16, 16, 16, EVP_CIPH_CBC_MODE, ++ sizeof(struct cipher_priv_ctx), uadk_e_cipher_init, ++ uadk_e_do_cipher, uadk_e_cipher_cleanup, ++ EVP_CIPHER_set_asn1_iv, EVP_CIPHER_get_asn1_iv); ++ cipher = uadk_sm4_cbc; ++ break; ++ case NID_des_ede3_cbc: ++ UADK_CIPHER_DESCR(des_ede3_cbc, 8, 24, 8, EVP_CIPH_CBC_MODE, ++ sizeof(struct cipher_priv_ctx), uadk_e_cipher_init, ++ uadk_e_do_cipher, uadk_e_cipher_cleanup, ++ EVP_CIPHER_set_asn1_iv, EVP_CIPHER_get_asn1_iv); ++ cipher = uadk_des_ede3_cbc; ++ break; ++ case NID_des_ede3_ecb: ++ UADK_CIPHER_DESCR(des_ede3_ecb, 8, 24, 0, EVP_CIPH_ECB_MODE, ++ sizeof(struct cipher_priv_ctx), uadk_e_cipher_init, ++ uadk_e_do_cipher, uadk_e_cipher_cleanup, ++ EVP_CIPHER_set_asn1_iv, EVP_CIPHER_get_asn1_iv); ++ cipher = uadk_des_ede3_ecb; ++ break; ++ case NID_aes_128_ctr: ++ UADK_CIPHER_DESCR(aes_128_ctr, 1, 16, 16, EVP_CIPH_CTR_MODE, ++ sizeof(struct cipher_priv_ctx), uadk_e_cipher_init, ++ uadk_e_do_cipher, uadk_e_cipher_cleanup, ++ EVP_CIPHER_set_asn1_iv, EVP_CIPHER_get_asn1_iv); ++ cipher = uadk_aes_128_ctr; ++ break; ++ case NID_aes_192_ctr: ++ UADK_CIPHER_DESCR(aes_192_ctr, 1, 24, 16, EVP_CIPH_CTR_MODE, ++ sizeof(struct cipher_priv_ctx), uadk_e_cipher_init, ++ uadk_e_do_cipher, uadk_e_cipher_cleanup, ++ EVP_CIPHER_set_asn1_iv, EVP_CIPHER_get_asn1_iv); ++ cipher = uadk_aes_192_ctr; ++ break; ++ case NID_aes_256_ctr: ++ UADK_CIPHER_DESCR(aes_256_ctr, 1, 32, 16, EVP_CIPH_CTR_MODE, ++ sizeof(struct cipher_priv_ctx), uadk_e_cipher_init, ++ uadk_e_do_cipher, uadk_e_cipher_cleanup, ++ EVP_CIPHER_set_asn1_iv, EVP_CIPHER_get_asn1_iv); ++ cipher = uadk_aes_256_ctr; ++ break; ++ case NID_aes_128_ofb128: ++ UADK_CIPHER_DESCR(aes_128_ofb128, 1, 16, 16, EVP_CIPH_OFB_MODE, ++ sizeof(struct cipher_priv_ctx), uadk_e_cipher_init, ++ uadk_e_do_cipher, uadk_e_cipher_cleanup, ++ EVP_CIPHER_set_asn1_iv, EVP_CIPHER_get_asn1_iv); ++ cipher = uadk_aes_128_ofb128; ++ break; ++ case NID_aes_192_ofb128: ++ UADK_CIPHER_DESCR(aes_192_ofb128, 1, 24, 16, EVP_CIPH_OFB_MODE, ++ sizeof(struct cipher_priv_ctx), uadk_e_cipher_init, ++ uadk_e_do_cipher, uadk_e_cipher_cleanup, ++ EVP_CIPHER_set_asn1_iv, EVP_CIPHER_get_asn1_iv); ++ cipher = uadk_aes_192_ofb128; ++ break; ++ case NID_aes_256_ofb128: ++ UADK_CIPHER_DESCR(aes_256_ofb128, 1, 32, 16, EVP_CIPH_OFB_MODE, ++ sizeof(struct cipher_priv_ctx), uadk_e_cipher_init, ++ uadk_e_do_cipher, uadk_e_cipher_cleanup, ++ EVP_CIPHER_set_asn1_iv, EVP_CIPHER_get_asn1_iv); ++ cipher = uadk_aes_256_ofb128; ++ break; ++ case NID_aes_128_cfb128: ++ UADK_CIPHER_DESCR(aes_128_cfb128, 1, 16, 16, EVP_CIPH_CFB_MODE, ++ sizeof(struct cipher_priv_ctx), uadk_e_cipher_init, ++ uadk_e_do_cipher, uadk_e_cipher_cleanup, ++ EVP_CIPHER_set_asn1_iv, EVP_CIPHER_get_asn1_iv); ++ cipher = uadk_aes_128_cfb128; ++ break; ++ case NID_aes_192_cfb128: ++ UADK_CIPHER_DESCR(aes_192_cfb128, 1, 24, 16, EVP_CIPH_CFB_MODE, ++ sizeof(struct cipher_priv_ctx), uadk_e_cipher_init, ++ uadk_e_do_cipher, uadk_e_cipher_cleanup, ++ EVP_CIPHER_set_asn1_iv, EVP_CIPHER_get_asn1_iv); ++ cipher = uadk_aes_192_cfb128; ++ break; ++ case NID_aes_256_cfb128: ++ UADK_CIPHER_DESCR(aes_256_cfb128, 1, 32, 16, EVP_CIPH_CFB_MODE, ++ sizeof(struct cipher_priv_ctx), uadk_e_cipher_init, ++ uadk_e_do_cipher, uadk_e_cipher_cleanup, ++ EVP_CIPHER_set_asn1_iv, EVP_CIPHER_get_asn1_iv); ++ cipher = uadk_aes_256_cfb128; ++ break; ++ case NID_sm4_ofb128: ++ UADK_CIPHER_DESCR(sm4_ofb128, 1, 16, 16, EVP_CIPH_OFB_MODE, ++ sizeof(struct cipher_priv_ctx), uadk_e_cipher_init, ++ uadk_e_do_cipher, uadk_e_cipher_cleanup, ++ EVP_CIPHER_set_asn1_iv, EVP_CIPHER_get_asn1_iv); ++ cipher = uadk_sm4_ofb128; ++ break; ++ case NID_sm4_cfb128: ++ UADK_CIPHER_DESCR(sm4_cfb128, 1, 16, 16, EVP_CIPH_OFB_MODE, ++ sizeof(struct cipher_priv_ctx), uadk_e_cipher_init, ++ uadk_e_do_cipher, uadk_e_cipher_cleanup, ++ EVP_CIPHER_set_asn1_iv, EVP_CIPHER_get_asn1_iv); ++ cipher = uadk_sm4_cfb128; ++ break; ++ case NID_sm4_ctr: ++ UADK_CIPHER_DESCR(sm4_ctr, 1, 16, 16, EVP_CIPH_CTR_MODE, ++ sizeof(struct cipher_priv_ctx), uadk_e_cipher_init, ++ uadk_e_do_cipher, uadk_e_cipher_cleanup, ++ EVP_CIPHER_set_asn1_iv, EVP_CIPHER_get_asn1_iv); ++ cipher = uadk_sm4_ctr; ++ break; ++ default: ++ cipher = NULL; ++ break; + } + +- bind_v2_cipher(); +- if (platform > HW_V2) +- bind_v3_cipher(); +- +- return ENGINE_set_ciphers(e, uadk_e_engine_ciphers); +-} +- +-static void destroy_v2_cipher(void) +-{ +- EVP_CIPHER_meth_free(uadk_aes_128_cbc); +- uadk_aes_128_cbc = 0; +- EVP_CIPHER_meth_free(uadk_aes_192_cbc); +- uadk_aes_192_cbc = 0; +- EVP_CIPHER_meth_free(uadk_aes_256_cbc); +- uadk_aes_256_cbc = 0; +- EVP_CIPHER_meth_free(uadk_aes_128_ecb); +- uadk_aes_128_ecb = 0; +- EVP_CIPHER_meth_free(uadk_aes_192_ecb); +- uadk_aes_192_ecb = 0; +- EVP_CIPHER_meth_free(uadk_aes_256_ecb); +- uadk_aes_256_ecb = 0; +- EVP_CIPHER_meth_free(uadk_aes_128_xts); +- uadk_aes_128_xts = 0; +- EVP_CIPHER_meth_free(uadk_aes_256_xts); +- uadk_aes_256_xts = 0; +- EVP_CIPHER_meth_free(uadk_sm4_cbc); +- uadk_sm4_cbc = 0; +- EVP_CIPHER_meth_free(uadk_des_ede3_cbc); +- uadk_des_ede3_cbc = 0; +- EVP_CIPHER_meth_free(uadk_des_ede3_ecb); +- uadk_des_ede3_ecb = 0; +- EVP_CIPHER_meth_free(uadk_sm4_ecb); +- uadk_sm4_ecb = 0; ++ return cipher; + } + +-static void destroy_v3_cipher(void) ++static void destroy_cipher(struct engine_cipher_info *info, int num) + { +- EVP_CIPHER_meth_free(uadk_aes_128_ctr); +- uadk_aes_128_ctr = 0; +- EVP_CIPHER_meth_free(uadk_aes_192_ctr); +- uadk_aes_192_ctr = 0; +- EVP_CIPHER_meth_free(uadk_aes_256_ctr); +- uadk_aes_256_ctr = 0; +- EVP_CIPHER_meth_free(uadk_aes_128_ofb128); +- uadk_aes_128_ofb128 = 0; +- EVP_CIPHER_meth_free(uadk_aes_192_ofb128); +- uadk_aes_192_ofb128 = 0; +- EVP_CIPHER_meth_free(uadk_aes_256_ofb128); +- uadk_aes_256_ofb128 = 0; +- EVP_CIPHER_meth_free(uadk_aes_128_cfb128); +- uadk_aes_128_cfb128 = 0; +- EVP_CIPHER_meth_free(uadk_aes_192_cfb128); +- uadk_aes_192_cfb128 = 0; +- EVP_CIPHER_meth_free(uadk_aes_256_cfb128); +- uadk_aes_256_cfb128 = 0; +- EVP_CIPHER_meth_free(uadk_sm4_cfb128); +- uadk_sm4_cfb128 = 0; +- EVP_CIPHER_meth_free(uadk_sm4_ofb128); +- uadk_sm4_ofb128 = 0; +- EVP_CIPHER_meth_free(uadk_sm4_ctr); +- uadk_sm4_ctr = 0; +-} +- +-void uadk_e_destroy_cipher(void) +-{ +- __u32 i; +- int ret; +- +- if (g_cipher_engine.pid == getpid()) { +- ret = uadk_e_is_env_enabled("cipher"); +- if (ret == ENV_ENABLED) { +- wd_cipher_env_uninit(); +- } else { +- wd_cipher_uninit(); +- for (i = 0; i < g_cipher_engine.ctx_cfg.ctx_num; i++) +- wd_release_ctx(g_cipher_engine.ctx_cfg.ctxs[i].ctx); +- free(g_cipher_engine.ctx_cfg.ctxs); ++ for (int i = 0; i != num; ++i) { ++ if (info[i].cipher != NULL) { ++ EVP_CIPHER_meth_free(info[i].cipher); ++ info[i].cipher = NULL; + } +- g_cipher_engine.pid = 0; + } ++} + +- pthread_spin_destroy(&g_cipher_engine.lock); +- +- destroy_v2_cipher(); +- if (platform > HW_V2) +- destroy_v3_cipher(); ++void uadk_e_destroy_cipher(struct engine_cipher_info *info, int num) ++{ ++ destroy_cipher(info, num); + } + + void uadk_e_cipher_lock_init(void) +diff --git a/src/uadk_cipher_adapter.c b/src/uadk_cipher_adapter.c +new file mode 100644 +index 0000000..c915df8 +--- /dev/null ++++ b/src/uadk_cipher_adapter.c +@@ -0,0 +1,204 @@ ++/* ++ * Copyright 2023 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 "uadk_cipher_adapter.h" ++ ++#define HW_SEC_V2 0 ++#define HW_SEC_V3 1 ++#define OTHERS_HW 2 ++ ++static int cipher_hw_v2_nids[] = { ++ NID_aes_128_cbc, ++ NID_aes_192_cbc, ++ NID_aes_256_cbc, ++ NID_aes_128_ecb, ++ NID_aes_192_ecb, ++ NID_aes_256_ecb, ++ NID_aes_128_xts, ++ NID_aes_256_xts, ++ NID_sm4_cbc, ++ NID_des_ede3_cbc, ++ NID_des_ede3_ecb, ++ NID_aes_128_gcm, ++ NID_aes_192_gcm, ++ NID_aes_256_gcm ++}; ++ ++static int cipher_hw_v3_nids[] = { ++ NID_aes_128_cbc, ++ NID_aes_192_cbc, ++ NID_aes_256_cbc, ++ NID_aes_128_ctr, ++ NID_aes_192_ctr, ++ NID_aes_256_ctr, ++ NID_aes_128_ecb, ++ NID_aes_192_ecb, ++ NID_aes_256_ecb, ++ NID_aes_128_xts, ++ NID_aes_256_xts, ++ NID_sm4_cbc, ++ NID_sm4_ecb, ++ NID_des_ede3_cbc, ++ NID_des_ede3_ecb, ++ NID_aes_128_cfb128, ++ NID_aes_192_cfb128, ++ NID_aes_256_cfb128, ++ NID_aes_128_ofb128, ++ NID_aes_192_ofb128, ++ NID_aes_256_ofb128, ++ NID_sm4_cfb128, ++ NID_sm4_ofb128, ++ NID_sm4_ctr, ++ NID_aes_128_gcm, ++ NID_aes_192_gcm, ++ NID_aes_256_gcm ++}; ++ ++static struct engine_cipher_info c_info[] = { ++ {NID_aes_128_cbc, NULL}, ++ {NID_aes_192_cbc, NULL}, ++ {NID_aes_256_cbc, NULL}, ++ {NID_aes_128_ctr, NULL}, ++ {NID_aes_192_ctr, NULL}, ++ {NID_aes_256_ctr, NULL}, ++ {NID_aes_128_ecb, NULL}, ++ {NID_aes_192_ecb, NULL}, ++ {NID_aes_256_ecb, NULL}, ++ {NID_aes_128_xts, NULL}, ++ {NID_aes_256_xts, NULL}, ++ {NID_sm4_cbc, NULL}, ++ {NID_sm4_ecb, NULL}, ++ {NID_des_ede3_cbc, NULL}, ++ {NID_des_ede3_ecb, NULL}, ++ {NID_aes_128_cfb128, NULL}, ++ {NID_aes_192_cfb128, NULL}, ++ {NID_aes_256_cfb128, NULL}, ++ {NID_aes_128_ofb128, NULL}, ++ {NID_aes_192_ofb128, NULL}, ++ {NID_aes_256_ofb128, NULL}, ++ {NID_sm4_cfb128, NULL}, ++ {NID_sm4_ofb128, NULL}, ++ {NID_sm4_ctr, NULL}, ++ {NID_aes_128_gcm, NULL}, ++ {NID_aes_192_gcm, NULL}, ++ {NID_aes_256_gcm, NULL} ++}; ++ ++static const unsigned int num_cc = ARRAY_SIZE(c_info); ++ ++static void uadk_e_create_ciphers(int index) ++{ ++ switch (c_info[index].nid) { ++ case NID_aes_128_gcm: ++ case NID_aes_192_gcm: ++ case NID_aes_256_gcm: ++ c_info[index].cipher = uadk_create_gcm_cipher_meth(c_info[index].nid); ++ break; ++ case NID_aes_128_cbc: ++ case NID_aes_192_cbc: ++ case NID_aes_256_cbc: ++ case NID_aes_128_ctr: ++ case NID_aes_192_ctr: ++ case NID_aes_256_ctr: ++ case NID_aes_128_ecb: ++ case NID_aes_192_ecb: ++ case NID_aes_256_ecb: ++ case NID_aes_128_xts: ++ case NID_aes_256_xts: ++ case NID_sm4_cbc: ++ case NID_sm4_ecb: ++ case NID_des_ede3_cbc: ++ case NID_des_ede3_ecb: ++ case NID_aes_128_cfb128: ++ case NID_aes_192_cfb128: ++ case NID_aes_256_cfb128: ++ case NID_aes_128_ofb128: ++ case NID_aes_192_ofb128: ++ case NID_aes_256_ofb128: ++ case NID_sm4_cfb128: ++ case NID_sm4_ofb128: ++ case NID_sm4_ctr: ++ c_info[index].cipher = uadk_create_cipher_meth(c_info[index].nid); ++ break; ++ default: ++ break; ++ } ++} ++ ++int uadk_e_ciphers(ENGINE *e, const EVP_CIPHER **cipher, const int **nids, int nid) ++{ ++ int platform = OTHERS_HW; ++ struct uacce_dev *dev; ++ __u32 i; ++ ++ if (!e) ++ return 0; ++ ++ if ((nids == NULL) && ((cipher == NULL) || (nid < 0))) { ++ if (cipher != NULL) ++ *cipher = NULL; ++ return 0; ++ } ++ ++ dev = wd_get_accel_dev("cipher"); ++ if (!dev) { ++ fprintf(stderr, "no device available, switch to software!\n"); ++ return 0; ++ } ++ ++ if (!strcmp(dev->api, "hisi_qm_v2")) ++ platform = HW_SEC_V2; ++ else if (!strcmp(dev->api, "hisi_qm_v3")) ++ platform = HW_SEC_V3; ++ ++ free(dev); ++ ++ if (cipher == NULL) { ++ if (platform == HW_SEC_V2) { ++ *nids = cipher_hw_v2_nids; ++ return ARRAY_SIZE(cipher_hw_v2_nids); ++ } else if (platform == HW_SEC_V3) { ++ *nids = cipher_hw_v3_nids; ++ return ARRAY_SIZE(cipher_hw_v3_nids); ++ } ++ ++ return 0; ++ } ++ ++ for (i = 0; i < num_cc; i++) { ++ if (nid == c_info[i].nid) { ++ if (c_info[i].cipher == NULL) ++ uadk_e_create_ciphers(i); ++ ++ *cipher = c_info[i].cipher; ++ return 1; ++ } ++ } ++ ++ *cipher = NULL; ++ return 0; ++} ++ ++int uadk_e_bind_ciphers(ENGINE *e) ++{ ++ return ENGINE_set_ciphers(e, uadk_e_ciphers); ++} ++ ++void uadk_e_destroy_ciphers(void) ++{ ++ uadk_e_destroy_cipher(c_info, num_cc); ++ uadk_e_destroy_aead(c_info, num_cc); ++} +diff --git a/src/uadk_cipher_adapter.h b/src/uadk_cipher_adapter.h +new file mode 100644 +index 0000000..f7b6fb4 +--- /dev/null ++++ b/src/uadk_cipher_adapter.h +@@ -0,0 +1,36 @@ ++/* ++ * Copyright 2023 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. ++ * ++ */ ++#ifndef UADK_ADAPT_H ++#define UADK_ADAPT_H ++#include ++#include ++ ++struct engine_cipher_info { ++ int nid; ++ EVP_CIPHER *cipher; ++}; ++ ++#define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0])) ++ ++EVP_CIPHER *uadk_create_gcm_cipher_meth(int nid); ++EVP_CIPHER *uadk_create_cipher_meth(int nid); ++void uadk_e_destroy_aead(struct engine_cipher_info *info, int num); ++void uadk_e_destroy_cipher(struct engine_cipher_info *info, int num); ++ ++int uadk_e_bind_ciphers(ENGINE *e); ++void uadk_e_destroy_ciphers(void); ++#endif +diff --git a/src/uadk_engine_init.c b/src/uadk_engine_init.c +index cf54360..33707bf 100644 +--- a/src/uadk_engine_init.c ++++ b/src/uadk_engine_init.c +@@ -24,15 +24,17 @@ + #include + #include "uadk.h" + #include "uadk_async.h" ++#include "uadk_cipher_adapter.h" + #ifdef KAE + #include "v1/uadk_v1.h" + #endif + + #define UADK_CMD_ENABLE_CIPHER_ENV ENGINE_CMD_BASE +-#define UADK_CMD_ENABLE_DIGEST_ENV (ENGINE_CMD_BASE + 1) +-#define UADK_CMD_ENABLE_RSA_ENV (ENGINE_CMD_BASE + 2) +-#define UADK_CMD_ENABLE_DH_ENV (ENGINE_CMD_BASE + 3) +-#define UADK_CMD_ENABLE_ECC_ENV (ENGINE_CMD_BASE + 4) ++#define UADK_CMD_ENABLE_AEAD_ENV (ENGINE_CMD_BASE + 1) ++#define UADK_CMD_ENABLE_DIGEST_ENV (ENGINE_CMD_BASE + 2) ++#define UADK_CMD_ENABLE_RSA_ENV (ENGINE_CMD_BASE + 3) ++#define UADK_CMD_ENABLE_DH_ENV (ENGINE_CMD_BASE + 4) ++#define UADK_CMD_ENABLE_ECC_ENV (ENGINE_CMD_BASE + 5) + + /* Constants used when creating the ENGINE */ + static const char *engine_uadk_id = "uadk_engine"; +@@ -60,6 +62,12 @@ static const ENGINE_CMD_DEFN g_uadk_cmd_defns[] = { + "Enable or Disable cipher engine environment variable.", + ENGINE_CMD_FLAG_NUMERIC + }, ++ { ++ UADK_CMD_ENABLE_AEAD_ENV, ++ "UADK_CMD_ENABLE_AEAD_ENV", ++ "Enable or Disable aead engine environment variable.", ++ ENGINE_CMD_FLAG_NUMERIC ++ }, + { + UADK_CMD_ENABLE_DIGEST_ENV, + "UADK_CMD_ENABLE_DIGEST_ENV", +@@ -104,6 +112,7 @@ struct uadk_alg_env_enabled { + + static struct uadk_alg_env_enabled uadk_env_enabled[] = { + { "cipher", 0 }, ++ { "aead", 0 }, + { "digest", 0 }, + { "rsa", 0 }, + { "dh", 0 }, +@@ -176,6 +185,9 @@ static int uadk_engine_ctrl(ENGINE *e, int cmd, long i, + case UADK_CMD_ENABLE_CIPHER_ENV: + uadk_e_set_env_enabled("cipher", i); + break; ++ case UADK_CMD_ENABLE_AEAD_ENV: ++ uadk_e_set_env_enabled("aead", i); ++ break; + case UADK_CMD_ENABLE_DIGEST_ENV: + uadk_e_set_env_enabled("digest", i); + break; +@@ -210,7 +222,7 @@ static int uadk_destroy(ENGINE *e) + #endif + + if (uadk_cipher) +- uadk_e_destroy_cipher(); ++ uadk_e_destroy_ciphers(); + if (uadk_digest) + uadk_e_destroy_digest(); + if (uadk_rsa) +@@ -328,7 +340,7 @@ static void bind_fn_uadk_alg(ENGINE *e) + + dev = wd_get_accel_dev("cipher"); + if (dev) { +- if (!uadk_e_bind_cipher(e)) ++ if (!uadk_e_bind_ciphers(e)) + fprintf(stderr, "uadk bind cipher failed\n"); + else + uadk_cipher = 1; +-- +2.25.1 + diff --git a/0057-cipher-fix-uadk_e_destroy_cipher-memory-leak.patch b/0057-cipher-fix-uadk_e_destroy_cipher-memory-leak.patch new file mode 100644 index 0000000..c524171 --- /dev/null +++ b/0057-cipher-fix-uadk_e_destroy_cipher-memory-leak.patch @@ -0,0 +1,45 @@ +From fef65630b7470bbb6f4fbecd946247fe8ba09027 Mon Sep 17 00:00:00 2001 +From: Wenkai Lin +Date: Thu, 9 Nov 2023 11:23:39 +0800 +Subject: [PATCH 57/63] cipher: fix uadk_e_destroy_cipher memory leak + +Fix an issue where hardware resources are not released +and locks are not destroyed. + +Signed-off-by: Wenkai Lin +--- + src/uadk_cipher.c | 18 ++++++++++++++++++ + 1 file changed, 18 insertions(+) + +diff --git a/src/uadk_cipher.c b/src/uadk_cipher.c +index 73be09d..63cc738 100644 +--- a/src/uadk_cipher.c ++++ b/src/uadk_cipher.c +@@ -996,6 +996,24 @@ static void destroy_cipher(struct engine_cipher_info *info, int num) + + void uadk_e_destroy_cipher(struct engine_cipher_info *info, int num) + { ++ __u32 i; ++ int ret; ++ ++ if (g_cipher_engine.pid == getpid()) { ++ ret = uadk_e_is_env_enabled("cipher"); ++ if (ret == ENV_ENABLED) { ++ wd_cipher_env_uninit(); ++ } else { ++ wd_cipher_uninit(); ++ for (i = 0; i < g_cipher_engine.ctx_cfg.ctx_num; i++) ++ wd_release_ctx(g_cipher_engine.ctx_cfg.ctxs[i].ctx); ++ free(g_cipher_engine.ctx_cfg.ctxs); ++ } ++ g_cipher_engine.pid = 0; ++ } ++ ++ pthread_spin_destroy(&g_cipher_engine.lock); ++ + destroy_cipher(info, num); + } + +-- +2.25.1 + diff --git a/0058-aead-fix-for-engine-lock-is-not-initialized.patch b/0058-aead-fix-for-engine-lock-is-not-initialized.patch new file mode 100644 index 0000000..a0ff112 --- /dev/null +++ b/0058-aead-fix-for-engine-lock-is-not-initialized.patch @@ -0,0 +1,216 @@ +From 06b1812e0bac3588519c48a8016c0fae559be7be Mon Sep 17 00:00:00 2001 +From: Wenkai Lin +Date: Thu, 9 Nov 2023 11:23:40 +0800 +Subject: [PATCH 58/63] aead: fix for engine lock is not initialized + +Fix an issue where the AEAD global lock is not initialized. + +In the multi-thread scenario, if the hardware is faulty +and the get_dev return is empty, the uadk engine should +continue to complete registration instead of returning. + +Signed-off-by: Wenkai Lin +--- + src/uadk.h | 1 + + src/uadk_aead.c | 81 ++++++++++++++++++++++-------------------- + src/uadk_engine_init.c | 4 ++- + 3 files changed, 47 insertions(+), 39 deletions(-) + +diff --git a/src/uadk.h b/src/uadk.h +index 4cf2c13..3dbaba1 100644 +--- a/src/uadk.h ++++ b/src/uadk.h +@@ -42,5 +42,6 @@ void uadk_e_ecc_lock_init(void); + void uadk_e_rsa_lock_init(void); + void uadk_e_dh_lock_init(void); + void uadk_e_cipher_lock_init(void); ++void uadk_e_aead_lock_init(void); + void uadk_e_digest_lock_init(void); + #endif +diff --git a/src/uadk_aead.c b/src/uadk_aead.c +index 64a5f5c..360f3f8 100644 +--- a/src/uadk_aead.c ++++ b/src/uadk_aead.c +@@ -61,7 +61,7 @@ struct aead_engine { + pthread_spinlock_t lock; + }; + +-static struct aead_engine engine; ++static struct aead_engine g_aead_engine; + + static EVP_CIPHER *uadk_aes_128_gcm; + static EVP_CIPHER *uadk_aes_192_gcm; +@@ -175,42 +175,42 @@ static int uadk_e_wd_aead_cipher_init(struct uacce_dev *dev) + __u32 i, j; + int ret; + +- engine.numa_id = dev->numa_id; ++ g_aead_engine.numa_id = dev->numa_id; + + ret = uadk_e_is_env_enabled("aead"); + if (ret) + return uadk_e_wd_aead_cipher_env_init(dev); + +- memset(&engine.ctx_cfg, 0, sizeof(struct wd_ctx_config)); +- engine.ctx_cfg.ctx_num = CTX_NUM; +- engine.ctx_cfg.ctxs = calloc(CTX_NUM, sizeof(struct wd_ctx)); +- if (!engine.ctx_cfg.ctxs) ++ memset(&g_aead_engine.ctx_cfg, 0, sizeof(struct wd_ctx_config)); ++ g_aead_engine.ctx_cfg.ctx_num = CTX_NUM; ++ g_aead_engine.ctx_cfg.ctxs = calloc(CTX_NUM, sizeof(struct wd_ctx)); ++ if (!g_aead_engine.ctx_cfg.ctxs) + return -ENOMEM; + + for (i = 0; i < CTX_NUM; i++) { +- engine.ctx_cfg.ctxs[i].ctx = wd_request_ctx(dev); +- if (!engine.ctx_cfg.ctxs[i].ctx) { ++ g_aead_engine.ctx_cfg.ctxs[i].ctx = wd_request_ctx(dev); ++ if (!g_aead_engine.ctx_cfg.ctxs[i].ctx) { + ret = -ENOMEM; + goto err_freectx; + } + } + +- engine.ctx_cfg.ctxs[CTX_SYNC_ENC].op_type = CTX_TYPE_ENCRYPT; +- engine.ctx_cfg.ctxs[CTX_SYNC_DEC].op_type = CTX_TYPE_DECRYPT; +- engine.ctx_cfg.ctxs[CTX_SYNC_ENC].ctx_mode = CTX_MODE_SYNC; +- engine.ctx_cfg.ctxs[CTX_SYNC_DEC].ctx_mode = CTX_MODE_SYNC; ++ g_aead_engine.ctx_cfg.ctxs[CTX_SYNC_ENC].op_type = CTX_TYPE_ENCRYPT; ++ g_aead_engine.ctx_cfg.ctxs[CTX_SYNC_DEC].op_type = CTX_TYPE_DECRYPT; ++ g_aead_engine.ctx_cfg.ctxs[CTX_SYNC_ENC].ctx_mode = CTX_MODE_SYNC; ++ g_aead_engine.ctx_cfg.ctxs[CTX_SYNC_DEC].ctx_mode = CTX_MODE_SYNC; + +- engine.ctx_cfg.ctxs[CTX_ASYNC_ENC].op_type = CTX_TYPE_ENCRYPT; +- engine.ctx_cfg.ctxs[CTX_ASYNC_DEC].op_type = CTX_TYPE_DECRYPT; +- engine.ctx_cfg.ctxs[CTX_ASYNC_ENC].ctx_mode = CTX_MODE_ASYNC; +- engine.ctx_cfg.ctxs[CTX_ASYNC_DEC].ctx_mode = CTX_MODE_ASYNC; ++ g_aead_engine.ctx_cfg.ctxs[CTX_ASYNC_ENC].op_type = CTX_TYPE_ENCRYPT; ++ g_aead_engine.ctx_cfg.ctxs[CTX_ASYNC_DEC].op_type = CTX_TYPE_DECRYPT; ++ g_aead_engine.ctx_cfg.ctxs[CTX_ASYNC_ENC].ctx_mode = CTX_MODE_ASYNC; ++ g_aead_engine.ctx_cfg.ctxs[CTX_ASYNC_DEC].ctx_mode = CTX_MODE_ASYNC; + +- engine.sched.name = "sched_single"; +- engine.sched.pick_next_ctx = sched_single_pick_next_ctx; +- engine.sched.poll_policy = sched_single_poll_policy; +- engine.sched.sched_init = sched_single_aead_init; ++ g_aead_engine.sched.name = "sched_single"; ++ g_aead_engine.sched.pick_next_ctx = sched_single_pick_next_ctx; ++ g_aead_engine.sched.poll_policy = sched_single_poll_policy; ++ g_aead_engine.sched.sched_init = sched_single_aead_init; + +- ret = wd_aead_init(&engine.ctx_cfg, &engine.sched); ++ ret = wd_aead_init(&g_aead_engine.ctx_cfg, &g_aead_engine.sched); + if (ret) + goto err_freectx; + +@@ -219,9 +219,9 @@ static int uadk_e_wd_aead_cipher_init(struct uacce_dev *dev) + + err_freectx: + for (j = 0; j < i; j++) +- wd_release_ctx(engine.ctx_cfg.ctxs[j].ctx); ++ wd_release_ctx(g_aead_engine.ctx_cfg.ctxs[j].ctx); + +- free(engine.ctx_cfg.ctxs); ++ free(g_aead_engine.ctx_cfg.ctxs); + + return ret; + } +@@ -231,30 +231,30 @@ static int uadk_e_init_aead_cipher(void) + struct uacce_dev *dev; + int ret; + +- if (engine.pid != getpid()) { +- pthread_spin_lock(&engine.lock); +- if (engine.pid == getpid()) { +- pthread_spin_unlock(&engine.lock); ++ if (g_aead_engine.pid != getpid()) { ++ pthread_spin_lock(&g_aead_engine.lock); ++ if (g_aead_engine.pid == getpid()) { ++ pthread_spin_unlock(&g_aead_engine.lock); + return 1; + } + + dev = wd_get_accel_dev("aead"); + if (!dev) { +- pthread_spin_unlock(&engine.lock); ++ pthread_spin_unlock(&g_aead_engine.lock); + fprintf(stderr, "failed to get device for aead.\n"); + return 0; + } + + ret = uadk_e_wd_aead_cipher_init(dev); + if (ret < 0) { +- pthread_spin_unlock(&engine.lock); ++ pthread_spin_unlock(&g_aead_engine.lock); + fprintf(stderr, "failed to initiate aead cipher.\n"); + free(dev); + return 0; + } + +- engine.pid = getpid(); +- pthread_spin_unlock(&engine.lock); ++ g_aead_engine.pid = getpid(); ++ pthread_spin_unlock(&g_aead_engine.lock); + free(dev); + } + +@@ -277,7 +277,7 @@ static int uadk_e_ctx_init(struct aead_priv_ctx *priv, const unsigned char *ckey + if (ret) + params.type = 0; + +- params.numa_id = engine.numa_id; ++ params.numa_id = g_aead_engine.numa_id; + priv->setup.sched_param = ¶ms; + if (!priv->sess) { + priv->sess = wd_aead_alloc_sess(&priv->setup); +@@ -713,20 +713,25 @@ void uadk_e_destroy_aead(struct engine_cipher_info *info, int num) + __u32 i; + int ret; + +- if (engine.pid == getpid()) { ++ if (g_aead_engine.pid == getpid()) { + ret = uadk_e_is_env_enabled("aead"); + if (ret) { + wd_aead_env_uninit(); + } else { + wd_aead_uninit(); +- for (i = 0; i < engine.ctx_cfg.ctx_num; i++) +- wd_release_ctx(engine.ctx_cfg.ctxs[i].ctx); ++ for (i = 0; i < g_aead_engine.ctx_cfg.ctx_num; i++) ++ wd_release_ctx(g_aead_engine.ctx_cfg.ctxs[i].ctx); + +- free(engine.ctx_cfg.ctxs); ++ free(g_aead_engine.ctx_cfg.ctxs); + } +- engine.pid = 0; ++ g_aead_engine.pid = 0; + } + +- pthread_spin_destroy(&engine.lock); ++ pthread_spin_destroy(&g_aead_engine.lock); + destroy_aead(info, num); + } ++ ++void uadk_e_aead_lock_init(void) ++{ ++ pthread_spin_init(&g_aead_engine.lock, PTHREAD_PROCESS_PRIVATE); ++} +diff --git a/src/uadk_engine_init.c b/src/uadk_engine_init.c +index 33707bf..c9cdd10 100644 +--- a/src/uadk_engine_init.c ++++ b/src/uadk_engine_init.c +@@ -262,8 +262,10 @@ static int uadk_init(ENGINE *e) + + if (uadk_digest) + uadk_e_digest_lock_init(); +- if (uadk_cipher) ++ if (uadk_cipher) { + uadk_e_cipher_lock_init(); ++ uadk_e_aead_lock_init(); ++ } + if (uadk_rsa) + uadk_e_rsa_lock_init(); + if (uadk_dh) +-- +2.25.1 + diff --git a/0059-uadk-fix-cipher-switchover-to-software-calculation-f.patch b/0059-uadk-fix-cipher-switchover-to-software-calculation-f.patch new file mode 100644 index 0000000..d12af06 --- /dev/null +++ b/0059-uadk-fix-cipher-switchover-to-software-calculation-f.patch @@ -0,0 +1,84 @@ +From f8c8181e68dfa14360aaaa2feff24779fc03ce76 Mon Sep 17 00:00:00 2001 +From: Wenkai Lin +Date: Thu, 9 Nov 2023 11:23:41 +0800 +Subject: [PATCH 59/63] uadk: fix cipher switchover to software calculation + fails + +In the multi-thread scenario, if the hardware is faulty +and the get_dev return is empty, the uadk engine should +continue to complete registration instead of returning. + +Signed-off-by: Wenkai Lin +--- + src/uadk_cipher_adapter.c | 35 +++++++++++++++++++---------------- + 1 file changed, 19 insertions(+), 16 deletions(-) + +diff --git a/src/uadk_cipher_adapter.c b/src/uadk_cipher_adapter.c +index c915df8..2c4ed15 100644 +--- a/src/uadk_cipher_adapter.c ++++ b/src/uadk_cipher_adapter.c +@@ -16,9 +16,11 @@ + */ + #include "uadk_cipher_adapter.h" + +-#define HW_SEC_V2 0 +-#define HW_SEC_V3 1 +-#define OTHERS_HW 2 ++#define HW_UNINIT -1 ++#define HW_SEC_V2 0 ++#define HW_SEC_V3 1 ++ ++static int g_platform = HW_UNINIT; + + static int cipher_hw_v2_nids[] = { + NID_aes_128_cbc, +@@ -140,7 +142,6 @@ static void uadk_e_create_ciphers(int index) + + int uadk_e_ciphers(ENGINE *e, const EVP_CIPHER **cipher, const int **nids, int nid) + { +- int platform = OTHERS_HW; + struct uacce_dev *dev; + __u32 i; + +@@ -153,24 +154,26 @@ int uadk_e_ciphers(ENGINE *e, const EVP_CIPHER **cipher, const int **nids, int n + return 0; + } + +- dev = wd_get_accel_dev("cipher"); +- if (!dev) { +- fprintf(stderr, "no device available, switch to software!\n"); +- return 0; +- } ++ if (g_platform == HW_UNINIT) { ++ dev = wd_get_accel_dev("cipher"); ++ if (!dev) { ++ fprintf(stderr, "no device available, switch to software!\n"); ++ return 0; ++ } + +- if (!strcmp(dev->api, "hisi_qm_v2")) +- platform = HW_SEC_V2; +- else if (!strcmp(dev->api, "hisi_qm_v3")) +- platform = HW_SEC_V3; ++ if (!strcmp(dev->api, "hisi_qm_v2")) ++ g_platform = HW_SEC_V2; ++ else ++ g_platform = HW_SEC_V3; + +- free(dev); ++ free(dev); ++ } + + if (cipher == NULL) { +- if (platform == HW_SEC_V2) { ++ if (g_platform == HW_SEC_V2) { + *nids = cipher_hw_v2_nids; + return ARRAY_SIZE(cipher_hw_v2_nids); +- } else if (platform == HW_SEC_V3) { ++ } else if (g_platform == HW_SEC_V3) { + *nids = cipher_hw_v3_nids; + return ARRAY_SIZE(cipher_hw_v3_nids); + } +-- +2.25.1 + diff --git a/0060-aead-fix-tag-length-check.patch b/0060-aead-fix-tag-length-check.patch new file mode 100644 index 0000000..d232ade --- /dev/null +++ b/0060-aead-fix-tag-length-check.patch @@ -0,0 +1,67 @@ +From d2e54deb1a0e1596fde73bc0970fb058316f3fb5 Mon Sep 17 00:00:00 2001 +From: Wenkai Lin +Date: Thu, 9 Nov 2023 11:23:42 +0800 +Subject: [PATCH 60/63] aead: fix tag length check + +Encryption and decryption are distinguished when taglen is checked. + +Signed-off-by: Wenkai Lin +--- + src/uadk_aead.c | 19 ++++++++++--------- + 1 file changed, 10 insertions(+), 9 deletions(-) + +diff --git a/src/uadk_aead.c b/src/uadk_aead.c +index 360f3f8..00ba4d2 100644 +--- a/src/uadk_aead.c ++++ b/src/uadk_aead.c +@@ -375,6 +375,7 @@ static int uadk_e_aes_gcm_set_ctrl(EVP_CIPHER_CTX *ctx, int type, int arg, void + { + struct aead_priv_ctx *priv = + (struct aead_priv_ctx *)EVP_CIPHER_CTX_get_cipher_data(ctx); ++ void *ctx_buf = EVP_CIPHER_CTX_buf_noconst(ctx); + int enc = EVP_CIPHER_CTX_encrypting(ctx); + + switch (type) { +@@ -391,30 +392,30 @@ static int uadk_e_aes_gcm_set_ctrl(EVP_CIPHER_CTX *ctx, int type, int arg, void + } + return 1; + case EVP_CTRL_GCM_GET_TAG: +- if (arg <= 0 || arg > AES_GCM_TAG_LEN) { +- fprintf(stderr, "TAG length invalid.\n"); ++ if (arg <= 0 || arg > AES_GCM_TAG_LEN || !enc) { ++ fprintf(stderr, "cannot get tag when decrypt or arg is invalid.\n"); + return 0; + } + +- if (EVP_CIPHER_CTX_buf_noconst(ctx) == NULL || ptr == NULL) { +- fprintf(stderr, "ctx memory pointer is invalid.\n"); ++ if (ctx_buf == NULL || ptr == NULL) { ++ fprintf(stderr, "failed to get tag, ctx memory pointer is invalid.\n"); + return 0; + } + +- memcpy(ptr, EVP_CIPHER_CTX_buf_noconst(ctx), arg); ++ memcpy(ptr, ctx_buf, arg); + return 1; + case EVP_CTRL_GCM_SET_TAG: +- if (arg != AES_GCM_TAG_LEN || enc) { ++ if (arg <= 0 || arg > AES_GCM_TAG_LEN || enc) { + fprintf(stderr, "cannot set tag when encrypt or arg is invalid.\n"); + return 0; + } + +- if (EVP_CIPHER_CTX_buf_noconst(ctx) == NULL || ptr == NULL) { +- fprintf(stderr, "ctx memory pointer is invalid.\n"); ++ if (ctx_buf == NULL || ptr == NULL) { ++ fprintf(stderr, "failed to set tag, ctx memory pointer is invalid.\n"); + return 0; + } + +- memcpy(EVP_CIPHER_CTX_buf_noconst(ctx), ptr, AES_GCM_TAG_LEN); ++ memcpy(ctx_buf, ptr, arg); + return 1; + default: + fprintf(stderr, "unsupported ctrl type: %d\n", type); +-- +2.25.1 + diff --git a/0061-aead-fix-for-aes-gcm-update-process.patch b/0061-aead-fix-for-aes-gcm-update-process.patch new file mode 100644 index 0000000..9faecfb --- /dev/null +++ b/0061-aead-fix-for-aes-gcm-update-process.patch @@ -0,0 +1,503 @@ +From a76e6fd7bf698c19a5195506f331c39c35b37e40 Mon Sep 17 00:00:00 2001 +From: Wenkai Lin +Date: Thu, 9 Nov 2023 11:23:43 +0800 +Subject: [PATCH 61/63] aead: fix for aes gcm update process + +According to openssl use mode, in the cipher update stage, the input +data length should be the same as the output length, however, cached data +is used for block mode now, this patch is intended to fix the problem. + +In the aead stream mode, the length of the final packet is 0 and can be +calculated in the final stage, in the block mode(like asynchronous and +aad 0-length scenarios), the calculation result must be returned +to the user in the update stage. + +However, this adds an additional restriction, user need to set the mac +before the update stage. + +Signed-off-by: Wenkai Lin +--- + src/uadk_aead.c | 278 +++++++++++++++++++++++++++--------------------- + 1 file changed, 159 insertions(+), 119 deletions(-) + +diff --git a/src/uadk_aead.c b/src/uadk_aead.c +index 00ba4d2..e27aba5 100644 +--- a/src/uadk_aead.c ++++ b/src/uadk_aead.c +@@ -28,6 +28,7 @@ + #include "uadk_utils.h" + + #define RET_FAIL -1 ++#define STATE_FAIL 0xFFFF + #define CTX_SYNC_ENC 0 + #define CTX_SYNC_DEC 1 + #define CTX_ASYNC_ENC 2 +@@ -50,7 +51,7 @@ struct aead_priv_ctx { + unsigned char *data; + unsigned char iv[AES_GCM_BLOCK_SIZE]; + unsigned char mac[AES_GCM_TAG_LEN]; +- size_t last_update_bufflen; ++ int taglen; + }; + + struct aead_engine { +@@ -267,10 +268,8 @@ static int uadk_e_ctx_init(struct aead_priv_ctx *priv, const unsigned char *ckey + int ret; + + ret = uadk_e_init_aead_cipher(); +- if (unlikely(!ret)) { +- fprintf(stderr, "uadk failed to init aead HW!\n"); ++ if (!ret) + return 0; +- } + + params.type = priv->req.op_type; + ret = uadk_e_is_env_enabled("aead"); +@@ -296,10 +295,14 @@ static int uadk_e_ctx_init(struct aead_priv_ctx *priv, const unsigned char *ckey + fprintf(stderr, "uadk engine failed to set ckey!\n"); + goto out; + } +- priv->data = malloc(AEAD_BLOCK_SIZE << 1); +- if (unlikely(!priv->data)) { +- fprintf(stderr, "uadk engine failed to alloc data!\n"); +- goto out; ++ ++ if (ASYNC_get_current_job()) { ++ /* Memory needs to be reserved for both input and output. */ ++ priv->data = malloc(AEAD_BLOCK_SIZE << 1); ++ if (unlikely(!priv->data)) { ++ fprintf(stderr, "uadk engine failed to alloc data!\n"); ++ goto out; ++ } + } + } + +@@ -313,10 +316,15 @@ out: + static int uadk_e_aes_gcm_init(EVP_CIPHER_CTX *ctx, const unsigned char *ckey, + const unsigned char *iv, int enc) + { +- struct aead_priv_ctx *priv = +- (struct aead_priv_ctx *)EVP_CIPHER_CTX_get_cipher_data(ctx); ++ struct aead_priv_ctx *priv; + int ret, ckey_len; + ++ priv = (struct aead_priv_ctx *)EVP_CIPHER_CTX_get_cipher_data(ctx); ++ if (!priv) { ++ fprintf(stderr, "invalid: aead priv ctx is NULL.\n"); ++ return 0; ++ } ++ + if (unlikely(!ckey)) + return 1; + +@@ -328,7 +336,6 @@ static int uadk_e_aes_gcm_init(EVP_CIPHER_CTX *ctx, const unsigned char *ckey, + priv->setup.dalg = 0; + priv->setup.dmode = 0; + +- priv->last_update_bufflen = 0; + priv->req.assoc_bytes = 0; + priv->req.out_bytes = 0; + priv->req.data_fmt = WD_FLAT_BUF; +@@ -339,6 +346,8 @@ static int uadk_e_aes_gcm_init(EVP_CIPHER_CTX *ctx, const unsigned char *ckey, + + priv->req.mac = priv->mac; + priv->req.mac_bytes = AES_GCM_TAG_LEN; ++ priv->taglen = 0; ++ priv->data = NULL; + + if (enc) + priv->req.op_type = WD_CIPHER_ENCRYPTION_DIGEST; +@@ -355,8 +364,13 @@ static int uadk_e_aes_gcm_init(EVP_CIPHER_CTX *ctx, const unsigned char *ckey, + + static int uadk_e_aes_gcm_cleanup(EVP_CIPHER_CTX *ctx) + { +- struct aead_priv_ctx *priv = +- (struct aead_priv_ctx *)EVP_CIPHER_CTX_get_cipher_data(ctx); ++ struct aead_priv_ctx *priv; ++ ++ priv = (struct aead_priv_ctx *)EVP_CIPHER_CTX_get_cipher_data(ctx); ++ if (!priv) { ++ fprintf(stderr, "invalid: aead priv ctx is NULL.\n"); ++ return 0; ++ } + + if (priv->sess) { + wd_aead_free_sess(priv->sess); +@@ -373,10 +387,15 @@ static int uadk_e_aes_gcm_cleanup(EVP_CIPHER_CTX *ctx) + + static int uadk_e_aes_gcm_set_ctrl(EVP_CIPHER_CTX *ctx, int type, int arg, void *ptr) + { +- struct aead_priv_ctx *priv = +- (struct aead_priv_ctx *)EVP_CIPHER_CTX_get_cipher_data(ctx); + void *ctx_buf = EVP_CIPHER_CTX_buf_noconst(ctx); + int enc = EVP_CIPHER_CTX_encrypting(ctx); ++ struct aead_priv_ctx *priv; ++ ++ priv = (struct aead_priv_ctx *)EVP_CIPHER_CTX_get_cipher_data(ctx); ++ if (!priv) { ++ fprintf(stderr, "invalid: aead priv ctx is NULL.\n"); ++ return 0; ++ } + + switch (type) { + case EVP_CTRL_INIT: +@@ -387,7 +406,7 @@ static int uadk_e_aes_gcm_set_ctrl(EVP_CIPHER_CTX *ctx, int type, int arg, void + return 1; + case EVP_CTRL_GCM_SET_IVLEN: + if (arg != AES_GCM_IV_LEN) { +- fprintf(stderr, "gcm only support 12 bytes.\n"); ++ fprintf(stderr, "invalid: aead gcm iv length only support 12B.\n"); + return 0; + } + return 1; +@@ -416,6 +435,7 @@ static int uadk_e_aes_gcm_set_ctrl(EVP_CIPHER_CTX *ctx, int type, int arg, void + } + + memcpy(ctx_buf, ptr, arg); ++ priv->taglen = arg; + return 1; + default: + fprintf(stderr, "unsupported ctrl type: %d\n", type); +@@ -423,18 +443,16 @@ static int uadk_e_aes_gcm_set_ctrl(EVP_CIPHER_CTX *ctx, int type, int arg, void + } + } + +-static int uadk_e_do_aes_gcm_first(EVP_CIPHER_CTX *ctx, unsigned char *out, ++static int uadk_e_do_aes_gcm_first(struct aead_priv_ctx *priv, unsigned char *out, + const unsigned char *in, size_t inlen) + { +- struct aead_priv_ctx *priv = +- (struct aead_priv_ctx *)EVP_CIPHER_CTX_get_cipher_data(ctx); + int ret; + + priv->req.assoc_bytes = inlen; + ++ /* Asynchronous jobs use the block mode. */ + if (ASYNC_get_current_job()) { +- memcpy(priv->data + priv->last_update_bufflen, in, inlen); +- priv->last_update_bufflen += inlen; ++ memcpy(priv->data, in, inlen); + return 1; + } + +@@ -442,68 +460,43 @@ static int uadk_e_do_aes_gcm_first(EVP_CIPHER_CTX *ctx, unsigned char *out, + priv->req.msg_state = AEAD_MSG_FIRST; + + ret = wd_do_aead_sync(priv->sess, &priv->req); +- if (ret < 0) { +- fprintf(stderr, "do sec aead first operation failed, ret:%d!\n", ret); ++ if (unlikely(ret < 0)) { ++ fprintf(stderr, "do aead first operation failed, ret: %d!\n", ret); + return RET_FAIL; + } + + return 1; + } + +-static int uadk_e_hw_update(struct aead_priv_ctx *priv, unsigned char *out, +- unsigned char *in, size_t inlen) ++static int do_aead_sync(struct aead_priv_ctx *priv, unsigned char *out, ++ const unsigned char *in, size_t inlen) + { + int ret; + +- priv->req.src = in; ++ /* Due to a hardware limitation, zero-length aad using block mode. */ ++ if (priv->req.assoc_bytes) ++ priv->req.msg_state = AEAD_MSG_MIDDLE; ++ else ++ priv->req.msg_state = AEAD_MSG_BLOCK; ++ ++ priv->req.src = (unsigned char *)in; + priv->req.dst = out; + priv->req.in_bytes = inlen; +- priv->req.msg_state = AEAD_MSG_MIDDLE; ++ priv->req.state = 0; + ret = wd_do_aead_sync(priv->sess, &priv->req); +- if (ret < 0) { +- fprintf(stderr, "do sec aead update operation failed, ret:%d!\n", ret); ++ if (ret < 0 || priv->req.state) { ++ fprintf(stderr, "do aead update operation failed, ret: %d, state: %u!\n", ++ ret, priv->req.state); + return RET_FAIL; + } + +- return 0; +-} +- +-static int uadk_e_cache_data(struct aead_priv_ctx *priv, const unsigned char *in, size_t inlen) +-{ +- if (ASYNC_get_current_job() || !priv->req.assoc_bytes) { +- if (priv->last_update_bufflen + inlen > AEAD_BLOCK_SIZE) { +- fprintf(stderr, "aead input data length is too long!\n"); +- return RET_FAIL; +- } +- memcpy(priv->data + priv->last_update_bufflen, in, inlen); +- priv->last_update_bufflen += inlen; +- return 0; +- } +- +- return 1; +-} +- +-static int uadk_e_do_aes_gcm_update(EVP_CIPHER_CTX *ctx, unsigned char *out, +- const unsigned char *in, size_t inlen) +-{ +- struct aead_priv_ctx *priv = +- (struct aead_priv_ctx *)EVP_CIPHER_CTX_get_cipher_data(ctx); +- int ret; +- +- ret = uadk_e_cache_data(priv, in, inlen); +- if (ret <= 0) +- return ret; +- +- ret = uadk_e_hw_update(priv, out, in, inlen); +- if (ret < 0) +- return RET_FAIL; +- + return inlen; + } + + static void *uadk_e_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) +@@ -513,6 +506,9 @@ static void *uadk_e_aead_cb(struct wd_aead_req *req, void *data) + 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; +@@ -523,35 +519,49 @@ static void *uadk_e_aead_cb(struct wd_aead_req *req, void *data) + return NULL; + } + +-static int do_aead_async(struct aead_priv_ctx *priv, struct async_op *op) ++static int 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 ret = 0; +- int idx; ++ int ret; + +- priv->req.in_bytes = priv->last_update_bufflen - priv->req.assoc_bytes; +- priv->req.dst = priv->data + AEAD_BLOCK_SIZE; ++ if (unlikely(priv->req.assoc_bytes + inlen > AEAD_BLOCK_SIZE)) { ++ fprintf(stderr, "aead input data length is too long!\n"); ++ return 0; ++ } ++ ++ 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; ++ } + + cb_param = malloc(sizeof(struct uadk_e_cb_info)); +- if (!cb_param) { ++ if (unlikely(!cb_param)) { + fprintf(stderr, "failed to alloc cb_param.\n"); +- return ret; ++ return 0; + } + + cb_param->op = op; +- cb_param->priv = priv; ++ cb_param->priv = &priv->req; + priv->req.cb = uadk_e_aead_cb; + priv->req.cb_param = cb_param; ++ priv->req.msg_state = AEAD_MSG_BLOCK; ++ priv->req.state = STATE_FAIL; + +- ret = async_get_free_task(&idx); +- if (!ret) ++ ret = async_get_free_task(&op->idx); ++ if (unlikely(!ret)) + goto free_cb_param; + +- op->idx = idx; + do { + ret = wd_do_aead_async(priv->sess, &priv->req); +- if (ret < 0 && ret != -EBUSY) { +- fprintf(stderr, "do sec aead async failed.\n"); ++ if (unlikely(ret < 0 && ret != -EBUSY)) { ++ fprintf(stderr, "do aead async operation failed.\n"); + async_free_poll_task(op->idx, 0); + ret = 0; + goto free_cb_param; +@@ -559,65 +569,59 @@ static int do_aead_async(struct aead_priv_ctx *priv, struct async_op *op) + } 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 = 0; ++ 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_e_do_aes_gcm_final(EVP_CIPHER_CTX *ctx, unsigned char *out, +- const unsigned char *in, size_t inlen) ++static int uadk_e_do_aes_gcm_update(EVP_CIPHER_CTX *ctx, struct aead_priv_ctx *priv, ++ unsigned char *out, const unsigned char *in, size_t inlen) + { +- struct aead_priv_ctx *priv = +- (struct aead_priv_ctx *)EVP_CIPHER_CTX_get_cipher_data(ctx); + unsigned char *ctx_buf = EVP_CIPHER_CTX_buf_noconst(ctx); + struct async_op *op; + int ret, enc; + +- op = malloc(sizeof(struct async_op)); +- if (!op) +- return RET_FAIL; +- +- ret = async_setup_async_event_notification(op); +- if (unlikely(!ret)) { +- fprintf(stderr, "failed to setup async event notification.\n"); +- free(op); +- return RET_FAIL; ++ enc = EVP_CIPHER_CTX_encrypting(ctx); ++ if (!enc) { ++ if (priv->taglen == AES_GCM_TAG_LEN) { ++ memcpy(priv->req.mac, ctx_buf, AES_GCM_TAG_LEN); ++ } else { ++ fprintf(stderr, "invalid: aead gcm mac length only support 16B.\n"); ++ return RET_FAIL; ++ } + } + +- if (priv->req.assoc_bytes && !op->job) +- priv->req.msg_state = AEAD_MSG_END; +- else +- priv->req.msg_state = AEAD_MSG_BLOCK; +- +- enc = EVP_CIPHER_CTX_encrypting(ctx); +- if (!enc) +- memcpy(priv->req.mac, ctx_buf, AES_GCM_TAG_LEN); ++ if (ASYNC_get_current_job()) { ++ op = malloc(sizeof(struct async_op)); ++ if (unlikely(!op)) ++ return RET_FAIL; + +- priv->req.src = priv->data; +- if (!op->job) { +- priv->req.in_bytes = priv->last_update_bufflen; +- priv->req.dst = out; +- ret = wd_do_aead_sync(priv->sess, &priv->req); +- if (ret < 0) { +- fprintf(stderr, "do sec aead final operation failed, ret: %d!\n", ret); +- goto out; ++ ret = async_setup_async_event_notification(op); ++ if (unlikely(!ret)) { ++ fprintf(stderr, "failed to setup async event notification.\n"); ++ free(op); ++ return RET_FAIL; + } +- } else { +- ret = do_aead_async(priv, op); +- if (!ret) ++ ++ ret = do_aead_async(priv, op, out, in, inlen); ++ if (unlikely(!ret)) + goto out; + +- memcpy(out, priv->req.dst + priv->req.assoc_bytes, priv->req.in_bytes); ++ free(op); ++ return inlen; + } + +- if (enc) +- memcpy(ctx_buf, priv->req.mac, AES_GCM_TAG_LEN); +- +- priv->last_update_bufflen = 0; +- +- free(op); +- return priv->req.in_bytes; ++ return do_aead_sync(priv, out, in, inlen); + + out: + (void)async_clear_async_event_notification(); +@@ -625,19 +629,55 @@ out: + return RET_FAIL; + } + ++static int uadk_e_do_aes_gcm_final(EVP_CIPHER_CTX *ctx, struct aead_priv_ctx *priv, ++ unsigned char *out, const unsigned char *in, size_t inlen) ++{ ++ unsigned char *ctx_buf = EVP_CIPHER_CTX_buf_noconst(ctx); ++ int ret, enc; ++ ++ enc = EVP_CIPHER_CTX_encrypting(ctx); ++ ++ if (ASYNC_get_current_job() || !priv->req.assoc_bytes) ++ goto out; ++ ++ priv->req.msg_state = AEAD_MSG_END; ++ priv->req.src = NULL; ++ priv->req.in_bytes = 0; ++ priv->req.dst = out; ++ priv->req.state = 0; ++ ret = wd_do_aead_sync(priv->sess, &priv->req); ++ if (ret < 0 || priv->req.state) { ++ fprintf(stderr, "do aead final operation failed, ret: %d, state: %u!\n", ++ ret, priv->req.state); ++ return RET_FAIL; ++ } ++ ++out: ++ if (enc) ++ memcpy(ctx_buf, priv->req.mac, AES_GCM_TAG_LEN); ++ ++ return 0; ++} ++ + static int uadk_e_do_aes_gcm(EVP_CIPHER_CTX *ctx, unsigned char *out, + const unsigned char *in, size_t inlen) + { +- int ret; ++ struct aead_priv_ctx *priv; ++ ++ priv = (struct aead_priv_ctx *)EVP_CIPHER_CTX_get_cipher_data(ctx); ++ if (unlikely(!priv)) { ++ fprintf(stderr, "invalid: aead priv ctx is NULL.\n"); ++ return 0; ++ } + + if (in) { + if (out == NULL) +- return uadk_e_do_aes_gcm_first(ctx, out, in, inlen); ++ return uadk_e_do_aes_gcm_first(priv, out, in, inlen); + +- return uadk_e_do_aes_gcm_update(ctx, out, in, inlen); ++ return uadk_e_do_aes_gcm_update(ctx, priv, out, in, inlen); + } + +- return uadk_e_do_aes_gcm_final(ctx, out, NULL, 0); ++ return uadk_e_do_aes_gcm_final(ctx, priv, out, NULL, 0); + } + + #define UADK_AEAD_DESCR(name, block_size, key_size, iv_len, flags, ctx_size, \ +-- +2.25.1 + diff --git a/0062-cipher-add-sm4-ecb-mode.patch b/0062-cipher-add-sm4-ecb-mode.patch new file mode 100644 index 0000000..174aa87 --- /dev/null +++ b/0062-cipher-add-sm4-ecb-mode.patch @@ -0,0 +1,47 @@ +From 1fd2648b118e62cff58c88e4ad71f1fe57d7905d Mon Sep 17 00:00:00 2001 +From: Wenkai Lin +Date: Thu, 9 Nov 2023 11:23:44 +0800 +Subject: [PATCH 62/63] cipher: add sm4 ecb mode + +The sm4 ecb disappeared in the previous modification +and added its support again. + +Signed-off-by: Wenkai Lin +--- + src/uadk_cipher.c | 7 +++++++ + src/uadk_cipher_adapter.c | 1 + + 2 files changed, 8 insertions(+) + +diff --git a/src/uadk_cipher.c b/src/uadk_cipher.c +index 63cc738..12830b7 100644 +--- a/src/uadk_cipher.c ++++ b/src/uadk_cipher.c +@@ -878,6 +878,13 @@ EVP_CIPHER *uadk_create_cipher_meth(int nid) + EVP_CIPHER_set_asn1_iv, EVP_CIPHER_get_asn1_iv); + cipher = uadk_sm4_cbc; + break; ++ case NID_sm4_ecb: ++ UADK_CIPHER_DESCR(sm4_ecb, 16, 16, 0, EVP_CIPH_ECB_MODE, ++ sizeof(struct cipher_priv_ctx), uadk_e_cipher_init, ++ uadk_e_do_cipher, uadk_e_cipher_cleanup, ++ EVP_CIPHER_set_asn1_iv, EVP_CIPHER_get_asn1_iv); ++ cipher = uadk_sm4_ecb; ++ break; + case NID_des_ede3_cbc: + UADK_CIPHER_DESCR(des_ede3_cbc, 8, 24, 8, EVP_CIPH_CBC_MODE, + sizeof(struct cipher_priv_ctx), uadk_e_cipher_init, +diff --git a/src/uadk_cipher_adapter.c b/src/uadk_cipher_adapter.c +index 2c4ed15..065575b 100644 +--- a/src/uadk_cipher_adapter.c ++++ b/src/uadk_cipher_adapter.c +@@ -32,6 +32,7 @@ static int cipher_hw_v2_nids[] = { + NID_aes_128_xts, + NID_aes_256_xts, + NID_sm4_cbc, ++ NID_sm4_ecb, + NID_des_ede3_cbc, + NID_des_ede3_ecb, + NID_aes_128_gcm, +-- +2.25.1 + diff --git a/0063-uadk-fix-EVP_CTRL_GET_IVLEN-not-find.patch b/0063-uadk-fix-EVP_CTRL_GET_IVLEN-not-find.patch new file mode 100644 index 0000000..0544b1b --- /dev/null +++ b/0063-uadk-fix-EVP_CTRL_GET_IVLEN-not-find.patch @@ -0,0 +1,31 @@ +From fec3d5c63da44062b9cf8726a20281e9ac955eda Mon Sep 17 00:00:00 2001 +From: Wenkai Lin +Date: Thu, 9 Nov 2023 16:46:01 +0800 +Subject: [PATCH 63/63] uadk: fix EVP_CTRL_GET_IVLEN not find + +EVP_CTRL_GET_IVLEN was not introduced in early versions. + +Signed-off-by: Wenkai Lin +--- + src/uadk_aead.c | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git a/src/uadk_aead.c b/src/uadk_aead.c +index e27aba5..c2646f1 100644 +--- a/src/uadk_aead.c ++++ b/src/uadk_aead.c +@@ -401,9 +401,11 @@ static int uadk_e_aes_gcm_set_ctrl(EVP_CIPHER_CTX *ctx, int type, int arg, void + case EVP_CTRL_INIT: + priv->req.iv_bytes = 0; + return 1; ++# if (OPENSSL_VERSION_NUMBER >= 0x1010106fL) + case EVP_CTRL_GET_IVLEN: + *(int *)ptr = priv->req.iv_bytes; + return 1; ++#endif + case EVP_CTRL_GCM_SET_IVLEN: + if (arg != AES_GCM_IV_LEN) { + fprintf(stderr, "invalid: aead gcm iv length only support 12B.\n"); +-- +2.25.1 + diff --git a/uadk_engine.spec b/uadk_engine.spec index e9428c9..cc0b761 100644 --- a/uadk_engine.spec +++ b/uadk_engine.spec @@ -1,7 +1,7 @@ Name: uadk_engine Summary: UADK Accelerator Engine Version: 1.2.0 -Release: 2 +Release: 3 License: Apache-2.0 Source: %{name}-%{version}.tar.gz ExclusiveOS: linux @@ -61,6 +61,21 @@ Patch0045: 0045-uadk_provider-add-DOPENSSL_SUPPRESS_DEPRECATED.patch Patch0046: 0046-uadk_prov_cipher-fix-build-warning.patch Patch0047: 0047-uadk_prov_init-change-name-more-informative.patch Patch0048: 0048-digest-alloc-session-and-data-when-copy-evp-context.patch +Patch0049: 0049-uadk_prov_init-remove-engine_uadk_id.patch +Patch0050: 0050-uadk_prov-reuse-OSSL_OP_STORE-from-default-provider.patch +Patch0051: 0051-uadk-add-uadk_prov_dh.patch +Patch0052: 0052-uadk-add-DH-sanity-test.patch +Patch0053: 0053-uadk-add-uadk_provider.cnf.patch +Patch0054: 0054-uadk-add-evp_test.sh.patch +Patch0055: 0055-uadk_engine-remove-redundant-param-of-async.patch +Patch0056: 0056-uadk_engine-support-aead-aes-gcm-algorithm.patch +Patch0057: 0057-cipher-fix-uadk_e_destroy_cipher-memory-leak.patch +Patch0058: 0058-aead-fix-for-engine-lock-is-not-initialized.patch +Patch0059: 0059-uadk-fix-cipher-switchover-to-software-calculation-f.patch +Patch0060: 0060-aead-fix-tag-length-check.patch +Patch0061: 0061-aead-fix-for-aes-gcm-update-process.patch +Patch0062: 0062-cipher-add-sm4-ecb-mode.patch +Patch0063: 0063-uadk-fix-EVP_CTRL_GET_IVLEN-not-find.patch %description This package contains the UADK Accelerator Engine @@ -110,6 +125,9 @@ fi /sbin/ldconfig %changelog +* Tue Nov 21 2023 JiangShui Yang 1.2.0-3 +- Backport uadk engine build patch + * Tue Oct 31 2023 JiangShui Yang 1.2.0-2 - Backport uadk engine build patch