From ad494b3f423850dd333e5cd4c482f6a3c7098165 Mon Sep 17 00:00:00 2001 From: Eingesch <884071658@qq.com> Date: Thu, 27 Feb 2025 09:41:22 +0800 Subject: [PATCH] uadk_provider: the x25519 and ecdsa algorithms are supported. --- ...dsa-support-ecdsa-signature-and-veri.patch | 1386 +++++++++++++++++ ...adk_async-check-type-and-ctx-in-task.patch | 45 + ...e-default-provider-to-get-random-dat.patch | 63 + ...vider_aead-cleanup-functions-in-aead.patch | 186 +++ ...-fix-the-fork-function-of-the-digest.patch | 214 +++ ...x-the-ctx-copy-function-of-the-diges.patch | 190 +++ ...der-code-cleanup-for-digest-and-aead.patch | 183 +++ ...ine_rsa-fix-memory-leak-of-pkey-meth.patch | 44 + ...engine-fix-memory-leak-in-fork-scene.patch | 60 + 0018-uadk_provider-support-X25519.patch | 904 +++++++++++ ...adk_engine_rsa-add-rsa-finish-method.patch | 31 + uadk_engine.spec | 16 +- 12 files changed, 3321 insertions(+), 1 deletion(-) create mode 100644 0009-uadk_provider_ecdsa-support-ecdsa-signature-and-veri.patch create mode 100644 0010-uadk_async-check-type-and-ctx-in-task.patch create mode 100644 0011-uadk_provider-use-default-provider-to-get-random-dat.patch create mode 100644 0012-uadk_provider_aead-cleanup-functions-in-aead.patch create mode 100644 0013-uadk_provider-fix-the-fork-function-of-the-digest.patch create mode 100644 0014-uadk_provider-fix-the-ctx-copy-function-of-the-diges.patch create mode 100644 0015-uadk_provider-code-cleanup-for-digest-and-aead.patch create mode 100644 0016-uadk_engine_rsa-fix-memory-leak-of-pkey-meth.patch create mode 100644 0017-uadk_engine-fix-memory-leak-in-fork-scene.patch create mode 100644 0018-uadk_provider-support-X25519.patch create mode 100644 0019-uadk_engine_rsa-add-rsa-finish-method.patch diff --git a/0009-uadk_provider_ecdsa-support-ecdsa-signature-and-veri.patch b/0009-uadk_provider_ecdsa-support-ecdsa-signature-and-veri.patch new file mode 100644 index 0000000..dd8c6f3 --- /dev/null +++ b/0009-uadk_provider_ecdsa-support-ecdsa-signature-and-veri.patch @@ -0,0 +1,1386 @@ +From f3acc762cec28cb9807c9a664e39662d797eff9a Mon Sep 17 00:00:00 2001 +From: Weili Qian +Date: Fri, 24 Jan 2025 09:14:03 +0800 +Subject: [PATCH 09/19] uadk_provider_ecdsa: support ecdsa signature and verify + +Support ecdsa signature and verify. + +openssl speed -provider uadk_provider -seconds 10 ecdsap521 + +Signed-off-by: Weili Qian +Signed-off-by: JiangShui Yang +--- + src/Makefile.am | 2 +- + src/uadk_prov.h | 2 + + src/uadk_prov_der_writer.c | 112 +++- + src/uadk_prov_der_writer.h | 2 + + src/uadk_prov_ecdsa.c | 1151 ++++++++++++++++++++++++++++++++++++ + src/uadk_prov_init.c | 2 + + src/uadk_prov_pkey.c | 2 +- + src/uadk_prov_pkey.h | 1 + + 8 files changed, 1269 insertions(+), 5 deletions(-) + create mode 100644 src/uadk_prov_ecdsa.c + +diff --git a/src/Makefile.am b/src/Makefile.am +index a165d3a..c1863e1 100644 +--- a/src/Makefile.am ++++ b/src/Makefile.am +@@ -67,7 +67,7 @@ uadk_provider_la_SOURCES=uadk_prov_init.c uadk_async.c uadk_utils.c \ + uadk_prov_pkey.c uadk_prov_sm2.c \ + uadk_prov_ffc.c uadk_prov_aead.c \ + uadk_prov_ec_kmgmt.c uadk_prov_ecdh_exch.c \ +- uadk_prov_ecx.c ++ uadk_prov_ecx.c uadk_prov_ecdsa.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 84a3f01..2786e79 100644 +--- a/src/uadk_prov.h ++++ b/src/uadk_prov.h +@@ -185,6 +185,8 @@ extern const OSSL_DISPATCH uadk_ecdh_keyexch_functions[FUNC_MAX_NUM]; + extern const OSSL_DISPATCH uadk_x448_keymgmt_functions[FUNC_MAX_NUM]; + extern const OSSL_DISPATCH uadk_x448_keyexch_functions[FUNC_MAX_NUM]; + ++extern const OSSL_DISPATCH uadk_ecdsa_signature_functions[FUNC_MAX_NUM]; ++ + void uadk_prov_destroy_digest(void); + void uadk_prov_destroy_cipher(void); + void uadk_prov_destroy_aead(void); +diff --git a/src/uadk_prov_der_writer.c b/src/uadk_prov_der_writer.c +index e7e7e49..7e5ee31 100644 +--- a/src/uadk_prov_der_writer.c ++++ b/src/uadk_prov_der_writer.c +@@ -12,10 +12,66 @@ + #include + #include "uadk_prov_der_writer.h" + +-#define DER_OID_SZ_sm2_with_SM3 10 +-#define PACKET_LEN_TAG 30 ++#define PACKET_LEN_TAG 30 ++#define DER_P_OBJECT 6 ++#define DER_OID_SZ_sm2_with_SM3 10 ++#define DER_OID_SZ_ecdsa_with_SHA1 9 ++#define DER_OID_SZ_ecdsa_with_SHA224 10 ++#define DER_OID_SZ_ecdsa_with_SHA256 10 ++#define DER_OID_SZ_ecdsa_with_SHA384 10 ++#define DER_OID_SZ_ecdsa_with_SHA512 10 ++#define DER_OID_SZ_id_ecdsa_with_sha3_224 11 ++#define DER_OID_SZ_id_ecdsa_with_sha3_256 11 ++#define DER_OID_SZ_id_ecdsa_with_sha3_384 11 ++#define DER_OID_SZ_id_ecdsa_with_sha3_512 11 ++ ++static const unsigned char ++ossl_der_oid_id_ecdsa_with_sha1[DER_OID_SZ_ecdsa_with_SHA1] = { ++ DER_P_OBJECT, 7, 0x2A, 0x86, 0x48, 0xCE, 0x3D, 0x04, 0x01 ++}; ++ ++static const unsigned char ++ossl_der_oid_id_ecdsa_with_sha224[DER_OID_SZ_ecdsa_with_SHA224] = { ++ DER_P_OBJECT, 8, 0x2A, 0x86, 0x48, 0xCE, 0x3D, 0x04, 0x03, 0x01 ++}; ++ ++static const unsigned char ++ossl_der_oid_id_ecdsa_with_sha256[DER_OID_SZ_ecdsa_with_SHA256] = { ++ DER_P_OBJECT, 8, 0x2A, 0x86, 0x48, 0xCE, 0x3D, 0x04, 0x03, 0x02 ++}; + +-unsigned char ossl_der_oid_sm2_with_SM3[DER_OID_SZ_sm2_with_SM3] = { ++static const unsigned char ++ossl_der_oid_id_ecdsa_with_sha384[DER_OID_SZ_ecdsa_with_SHA384] = { ++ DER_P_OBJECT, 8, 0x2A, 0x86, 0x48, 0xCE, 0x3D, 0x04, 0x03, 0x03 ++}; ++ ++static const unsigned char ++ossl_der_oid_id_ecdsa_with_sha512[DER_OID_SZ_ecdsa_with_SHA384] = { ++ DER_P_OBJECT, 8, 0x2A, 0x86, 0x48, 0xCE, 0x3D, 0x04, 0x03, 0x04 ++}; ++ ++static const unsigned char ++ossl_der_oid_id_ecdsa_with_sha3_224[DER_OID_SZ_id_ecdsa_with_sha3_224] = { ++ DER_P_OBJECT, 9, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x03, 0x09 ++}; ++ ++static const unsigned char ++ossl_der_oid_id_ecdsa_with_sha3_256[DER_OID_SZ_id_ecdsa_with_sha3_256] = { ++ DER_P_OBJECT, 9, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x03, 0x0A ++}; ++ ++static const unsigned char ++ossl_der_oid_id_ecdsa_with_sha3_384[DER_OID_SZ_id_ecdsa_with_sha3_384] = { ++ DER_P_OBJECT, 9, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x03, 0x0B ++}; ++ ++static const unsigned char ++ossl_der_oid_id_ecdsa_with_sha3_512[DER_OID_SZ_id_ecdsa_with_sha3_512] = { ++ DER_P_OBJECT, 9, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x03, 0x0C ++}; ++ ++static const unsigned char ++ossl_der_oid_sm2_with_SM3[DER_OID_SZ_sm2_with_SM3] = { + 6, 8, 0x2A, 0x81, 0x1C, 0xCF, 0x55, 0x01, 0x83, 0x75 + }; + +@@ -234,3 +290,53 @@ int ossl_DER_w_algorithmIdentifier_SM2_with_MD(WPACKET *pkt, int cont, + && ossl_DER_w_precompiled(pkt, -1, precompiled, precompiled_sz) + && ossl_DER_w_end_sequence(pkt, cont); + } ++ ++int ossl_DER_w_algorithmIdentifier_ECDSA_with_MD(WPACKET *pkt, int cont, ++ EC_KEY *ec, int mdnid) ++{ ++ const unsigned char *precompiled = NULL; ++ size_t precompiled_sz = 0; ++ ++#define MD_CASE(name) \ ++do { \ ++ precompiled = ossl_der_oid_id_ecdsa_with_##name; \ ++ precompiled_sz = sizeof(ossl_der_oid_id_ecdsa_with_##name); \ ++} while (0) ++ ++ switch (mdnid) { ++ case NID_sha1: ++ MD_CASE(sha1); ++ break; ++ case NID_sha224: ++ MD_CASE(sha224); ++ break; ++ case NID_sha256: ++ MD_CASE(sha256); ++ break; ++ case NID_sha384: ++ MD_CASE(sha384); ++ break; ++ case NID_sha512: ++ MD_CASE(sha512); ++ break; ++ case NID_sha3_224: ++ MD_CASE(sha3_224); ++ break; ++ case NID_sha3_256: ++ MD_CASE(sha3_256); ++ break; ++ case NID_sha3_384: ++ MD_CASE(sha3_384); ++ break; ++ case NID_sha3_512: ++ MD_CASE(sha3_512); ++ break; ++ default: ++ return 0; ++ } ++ ++ return ossl_DER_w_begin_sequence(pkt, cont) && ++ /* No parameters (yet?) */ ++ ossl_DER_w_precompiled(pkt, -1, precompiled, precompiled_sz) && ++ ossl_DER_w_end_sequence(pkt, cont); ++} +diff --git a/src/uadk_prov_der_writer.h b/src/uadk_prov_der_writer.h +index 39308e0..4f0bab5 100644 +--- a/src/uadk_prov_der_writer.h ++++ b/src/uadk_prov_der_writer.h +@@ -126,4 +126,6 @@ int ossl_DER_w_end_sequence(WPACKET *pkt, int tag); + + int ossl_DER_w_algorithmIdentifier_SM2_with_MD(WPACKET *pkt, int cont, + EC_KEY *ec, int mdnid); ++int ossl_DER_w_algorithmIdentifier_ECDSA_with_MD(WPACKET *pkt, int cont, ++ EC_KEY *ec, int mdnid); + #endif +diff --git a/src/uadk_prov_ecdsa.c b/src/uadk_prov_ecdsa.c +new file mode 100644 +index 0000000..774e8ee +--- /dev/null ++++ b/src/uadk_prov_ecdsa.c +@@ -0,0 +1,1151 @@ ++// SPDX-License-Identifier: Apache-2.0 ++/* ++ * Copyright 2024 Huawei Technologies Co.,Ltd. All rights reserved. ++ * ++ * Licensed under the Apache License, Version 2.0 (the "License"); ++ * you may not use this file except in compliance with the License. ++ * You may obtain a copy of the License at ++ * ++ * http://www.apache.org/licenses/LICENSE-2.0 ++ * ++ * Unless required by applicable law or agreed to in writing, software ++ * distributed under the License is distributed on an "AS IS" BASIS, ++ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. ++ * See the License for the specific language governing permissions and ++ * limitations under the License. ++ * ++ */ ++ ++#include ++#include ++#include ++#include ++#include "uadk_async.h" ++#include "uadk_prov.h" ++#include "uadk_prov_der_writer.h" ++#include "uadk_prov_pkey.h" ++ ++#define DIGEST_MAX_NAME_SIZE 50 ++#define MAX_ALGORITHM_ID_SIZE 256 ++#define MAX_PROPQUERY_SIZE 256 ++#define UADK_SIGN_SIG_NULL 2 ++#define DGST_SHIFT_NUM(n) (8 - ((n) & 0x7)) ++#define UADK_PROV_ECDSA "ecdsa" ++ ++/* ++ * What's passed as an actual key is defined by the KEYMGMT interface. ++ * We happen to know that our KEYMGMT simply passes DSA structures, so ++ * we use that here too. ++ */ ++struct ecdsa_ctx { ++ OSSL_LIB_CTX *libctx; ++ char *propq; ++ EC_KEY *ec; ++ char mdname[DIGEST_MAX_NAME_SIZE]; ++ ++ /* ++ * Flag to determine if the hash function can be changed (true) or not (false) ++ * Because it's dangerous to change during a DigestSign or DigestVerify ++ * operation, this flag is cleared by their Init function, and set again ++ * by their Final function. ++ */ ++ bool flag_allow_md; ++ ++ /* The Algorithm Identifier of the combined signature algorithm */ ++ unsigned char aid_buf[MAX_ALGORITHM_ID_SIZE]; ++ unsigned char *aid; ++ size_t aid_len; ++ size_t mdsize; ++ int operation; ++ ++ EVP_MD *md; ++ EVP_MD_CTX *mdctx; ++ /* ++ * Internally used to cache the results of calling the EC group ++ * sign_setup() methods which are then passed to the sign operation. ++ * This is used by CAVS failure tests to terminate a loop if the signature ++ * is not valid. ++ * This could of also been done with a simple flag. ++ */ ++ BIGNUM *kinv; ++ BIGNUM *r; ++}; ++ ++struct ecdsa_opdata { ++ const unsigned char *tbs; ++ size_t tbslen; ++ ECDSA_SIG *sig; ++ EC_KEY *ec; ++}; ++ ++UADK_PKEY_SIGNATURE_DESCR(ecdsa, ECDSA); ++ ++static void *uadk_signature_ecdsa_newctx(void *provctx, const char *propq) ++{ ++ struct ecdsa_ctx *ctx; ++ ++ ctx = OPENSSL_zalloc(sizeof(*ctx)); ++ if (!ctx) ++ return NULL; ++ ++ ctx->flag_allow_md = true; ++ ctx->libctx = prov_libctx_of(provctx); ++ ++ if (propq) { ++ ctx->propq = OPENSSL_strdup(propq); ++ if (!ctx->propq) { ++ fprintf(stderr, "failed to strdup propq!\n"); ++ OPENSSL_free(ctx); ++ ctx = NULL; ++ } ++ } ++ ++ return ctx; ++} ++ ++static void uadk_signature_ecdsa_freectx(void *vctx) ++{ ++ struct ecdsa_ctx *ctx = (struct ecdsa_ctx *)vctx; ++ ++ if (!ctx) ++ return; ++ ++ OPENSSL_free(ctx->propq); ++ EVP_MD_CTX_free(ctx->mdctx); ++ EVP_MD_free(ctx->md); ++ EC_KEY_free(ctx->ec); ++ BN_clear_free(ctx->kinv); ++ BN_clear_free(ctx->r); ++ OPENSSL_clear_free(ctx, sizeof(*ctx)); ++} ++ ++static void *uadk_signature_ecdsa_dupctx(void *vctx) ++{ ++ struct ecdsa_ctx *src_ctx = (struct ecdsa_ctx *)vctx; ++ struct ecdsa_ctx *dst_ctx; ++ ++ if (!src_ctx) { ++ fprintf(stderr, "invalid: src ctx is NULL to dupctx!\n"); ++ return NULL; ++ } ++ ++ /* Test KATS should not need to be supported */ ++ if (src_ctx->kinv || src_ctx->r) { ++ fprintf(stderr, "invalid: src ctx kinv or r is not NULL!\n"); ++ return NULL; ++ } ++ ++ dst_ctx = OPENSSL_zalloc(sizeof(*dst_ctx)); ++ if (!dst_ctx) ++ return NULL; ++ ++ *dst_ctx = *src_ctx; ++ dst_ctx->ec = NULL; ++ dst_ctx->md = NULL; ++ dst_ctx->mdctx = NULL; ++ dst_ctx->propq = NULL; ++ ++ if (src_ctx->ec && !EC_KEY_up_ref(src_ctx->ec)) ++ goto err; ++ dst_ctx->ec = src_ctx->ec; ++ ++ if (src_ctx->md && !EVP_MD_up_ref(src_ctx->md)) ++ goto err; ++ dst_ctx->md = src_ctx->md; ++ ++ if (src_ctx->mdctx) { ++ dst_ctx->mdctx = EVP_MD_CTX_new(); ++ if (!dst_ctx->mdctx || !EVP_MD_CTX_copy_ex(dst_ctx->mdctx, src_ctx->mdctx)) ++ goto err; ++ } ++ ++ if (src_ctx->propq) { ++ dst_ctx->propq = OPENSSL_strdup(src_ctx->propq); ++ if (!dst_ctx->propq) ++ goto err; ++ } ++ ++ return dst_ctx; ++ ++err: ++ uadk_signature_ecdsa_freectx(dst_ctx); ++ return NULL; ++} ++ ++static void ecdsa_set_aid(struct ecdsa_ctx *ctx, int md_nid) ++{ ++ WPACKET pkt; ++ ++ ctx->aid_len = 0; ++ if (WPACKET_init_der(&pkt, ctx->aid_buf, sizeof(ctx->aid_buf)) && ++ ossl_DER_w_algorithmIdentifier_ECDSA_with_MD(&pkt, -1, ctx->ec, md_nid) && ++ WPACKET_finish(&pkt)) { ++ WPACKET_get_total_written(&pkt, &ctx->aid_len); ++ ctx->aid = WPACKET_get_curr(&pkt); ++ } ++ WPACKET_cleanup(&pkt); ++} ++ ++/* ++ * Internal library code deals with NIDs, so we need to translate from a name. ++ * We do so using EVP_MD_is_a(), and therefore need a name to NID map. ++ */ ++static int ecdsa_digest_md_to_nid(const EVP_MD *md, const OSSL_ITEM *it, size_t it_len) ++{ ++ size_t i; ++ ++ if (!md) ++ return NID_undef; ++ ++ for (i = 0; i < it_len; i++) ++ if (EVP_MD_is_a(md, it[i].ptr)) ++ return (int)it[i].id; ++ ++ return NID_undef; ++} ++ ++/* ++ * Retrieve one of the FIPS approved hash algorithms by nid. ++ * See FIPS 180-4 "Secure Hash Standard" and FIPS 202 - SHA-3. ++ */ ++static int ecdsa_digest_get_nid(const EVP_MD *md) ++{ ++ static const OSSL_ITEM name_to_nid[] = { ++ {NID_sha1, OSSL_DIGEST_NAME_SHA1}, ++ {NID_sha224, OSSL_DIGEST_NAME_SHA2_224}, ++ {NID_sha256, OSSL_DIGEST_NAME_SHA2_256}, ++ {NID_sha384, OSSL_DIGEST_NAME_SHA2_384}, ++ {NID_sha512, OSSL_DIGEST_NAME_SHA2_512}, ++ {NID_sha512_224, OSSL_DIGEST_NAME_SHA2_512_224}, ++ {NID_sha512_256, OSSL_DIGEST_NAME_SHA2_512_256}, ++ {NID_sha3_224, OSSL_DIGEST_NAME_SHA3_224}, ++ {NID_sha3_256, OSSL_DIGEST_NAME_SHA3_256}, ++ {NID_sha3_384, OSSL_DIGEST_NAME_SHA3_384}, ++ {NID_sha3_512, OSSL_DIGEST_NAME_SHA3_512}, ++ }; ++ ++ return ecdsa_digest_md_to_nid(md, name_to_nid, OSSL_NELEM(name_to_nid)); ++} ++ ++static int ecdsa_digest_get_approved_nid(struct ecdsa_ctx *ctx, const EVP_MD *md) ++{ ++ int mdnid = ecdsa_digest_get_nid(md); ++ ++#ifndef OPENSSL_NO_FIPS_SECURITYCHECKS ++ int sha1_allowed = (ctx->operation != EVP_PKEY_OP_SIGN); ++ ++ if (uadk_prov_securitycheck_enabled(ctx->libctx)) { ++ if (mdnid == NID_undef || (mdnid == NID_sha1 && !sha1_allowed)) ++ mdnid = -1; /* disallowed by security checks */ ++ } ++# endif /* OPENSSL_NO_FIPS_SECURITYCHECKS */ ++ ++ return mdnid; ++} ++ ++static int ecdsa_setup_md(struct ecdsa_ctx *ctx, const char *mdname, const char *mdprops) ++{ ++ size_t mdname_len; ++ EVP_MD *md = NULL; ++ int md_nid; ++ ++ if (!mdname) ++ return UADK_P_SUCCESS; ++ ++ mdname_len = strlen(mdname); ++ if (mdname_len >= DIGEST_MAX_NAME_SIZE) { ++ fprintf(stderr, "invalid: %s size %zu exceeds name buffer length %d!\n", ++ mdname, mdname_len, DIGEST_MAX_NAME_SIZE); ++ return UADK_P_FAIL; ++ } ++ ++ if (!mdprops) ++ mdprops = ctx->propq; ++ ++ md = EVP_MD_fetch(ctx->libctx, mdname, mdprops); ++ if (!md) { ++ fprintf(stderr, "failed to fetch %s!\n", mdname); ++ return UADK_P_FAIL; ++ } ++ ++ md_nid = ecdsa_digest_get_approved_nid(ctx, md); ++ if (md_nid < 0) { ++ fprintf(stderr, "digest %s not allowed!\n", mdname); ++ goto err; ++ } ++ ++ if (!ctx->flag_allow_md) { ++ if (ctx->mdname[0] != '\0' && !EVP_MD_is_a(md, ctx->mdname)) { ++ fprintf(stderr, "digest %s is not same ctx digest %s!\n", ++ mdname, ctx->mdname); ++ goto err; ++ } ++ EVP_MD_free(md); ++ return UADK_P_SUCCESS; ++ } ++ ++ EVP_MD_CTX_free(ctx->mdctx); ++ ctx->mdctx = NULL; ++ ++ EVP_MD_free(ctx->md); ++ ctx->md = md; ++ ctx->mdsize = EVP_MD_get_size(ctx->md); ++ OPENSSL_strlcpy(ctx->mdname, mdname, DIGEST_MAX_NAME_SIZE); ++ ++ ecdsa_set_aid(ctx, md_nid); ++ ++ return UADK_P_SUCCESS; ++ ++err: ++ EVP_MD_free(md); ++ return UADK_P_FAIL; ++} ++ ++static int ecdsa_signverify_init(void *vctx, void *ec, ++ const OSSL_PARAM params[], ++ int operation) ++{ ++ struct ecdsa_ctx *ctx = (struct ecdsa_ctx *)vctx; ++ const EC_KEY *eckey = (const EC_KEY *)ec; ++ int ret; ++ ++ if (!ctx || (!ec && !ctx->ec)) { ++ fprintf(stderr, "invalid: ctx or ec is NULL to digest init!\n"); ++ return UADK_P_FAIL; ++ } ++ ++ ret = uadk_signature_ecdsa_set_ctx_params(ctx, params); ++ if (!ret) ++ return ret; ++ ++ if (eckey) { ++ if (!uadk_prov_ecc_check_key(ctx->libctx, eckey, ++ operation == EVP_PKEY_OP_SIGN)) ++ return UADK_P_FAIL; ++ ++ if (!EC_KEY_up_ref(ec)) ++ return UADK_P_FAIL; ++ EC_KEY_free(ctx->ec); ++ ctx->ec = ec; ++ } ++ ++ ctx->operation = operation; ++ ++ return UADK_P_SUCCESS; ++} ++ ++static int uadk_signature_ecdsa_sign_init(void *vctx, void *ec, const OSSL_PARAM params[]) ++{ ++ return ecdsa_signverify_init(vctx, ec, params, EVP_PKEY_OP_SIGN); ++} ++ ++static int uadk_signature_ecdsa_verify_init(void *vctx, void *ec, const OSSL_PARAM params[]) ++{ ++ return ecdsa_signverify_init(vctx, ec, params, EVP_PKEY_OP_VERIFY); ++} ++ ++static int ecdsa_common_params_check(struct ecdsa_ctx *ctx, ++ struct ecdsa_opdata *opdata) ++{ ++ const EC_GROUP *group; ++ int type; ++ ++ if (unlikely(!opdata->tbs || !opdata->tbslen)) { ++ fprintf(stderr, "invalid: tbs is NULL or tbslen %zu error!\n", opdata->tbslen); ++ return UADK_P_FAIL; ++ } ++ ++ if (ctx->mdsize && opdata->tbslen != ctx->mdsize) { ++ fprintf(stderr, "invalid: ctx->mdsize %zu not equal tbslen %zu!\n", ++ ctx->mdsize, opdata->tbslen); ++ return UADK_P_FAIL; ++ } ++ ++ group = EC_KEY_get0_group(ctx->ec); ++ if (unlikely(!group)) { ++ fprintf(stderr, "invalid: group is NULL!\n"); ++ return UADK_P_FAIL; ++ } ++ ++ /* Field GF(2m) is not supported by uadk */ ++ type = EC_METHOD_get_field_type(EC_GROUP_method_of(group)); ++ if (type != NID_X9_62_prime_field) { ++ fprintf(stderr, "invalid: uadk unsupport Field GF(2m)!\n"); ++ return UADK_P_FAIL; ++ } ++ ++ opdata->ec = ctx->ec; ++ ++ return uadk_prov_ecc_bit_check(group); ++} ++ ++static handle_t ecdsa_alloc_sess(EC_KEY *ec) ++{ ++ int ret; ++ ++ ret = uadk_prov_signature_get_support_state(SIGNATURE_ECDSA); ++ if (!ret) { ++ fprintf(stderr, "failed to get hardware ecdsa support!\n"); ++ return ret; ++ } ++ ++ ret = uadk_prov_ecc_init(UADK_PROV_ECDSA); ++ if (!ret) { ++ fprintf(stderr, "failed to init ecdsa!\n"); ++ return ret; ++ } ++ ++ return uadk_prov_ecc_alloc_sess(ec, UADK_PROV_ECDSA); ++} ++ ++static void ecdsa_free_sess(handle_t sess) ++{ ++ wd_ecc_free_sess(sess); ++} ++ ++static bool ecdsa_data_is_all_zero(struct wd_dtb *e) ++{ ++ __u32 i; ++ ++ for (i = 0; i < e->dsize; i++) { ++ if (e->data[i]) ++ return false; ++ } ++ ++ return true; ++} ++ ++static int ecdsa_set_digest(struct ecdsa_opdata *opdata, struct wd_dtb *e) ++{ ++ const EC_GROUP *group = EC_KEY_get0_group(opdata->ec); ++ size_t order_bits = EC_GROUP_order_bits(group); ++ size_t data_len = opdata->tbslen; ++ BIGNUM *m; ++ ++ if (BYTES_TO_BITS(data_len) > order_bits) { ++ m = BN_new(); ++ if (!m) { ++ fprintf(stderr, "failed to BN_new m!\n"); ++ return UADK_P_FAIL; ++ } ++ ++ /* ++ * Need to truncate digest if it is too long: first truncate ++ * whole bytes ++ */ ++ data_len = BITS_TO_BYTES(order_bits); ++ if (!BN_bin2bn(opdata->tbs, data_len, m)) { ++ fprintf(stderr, "failed to BN_bin2bn tbs!\n"); ++ BN_free(m); ++ return UADK_P_FAIL; ++ } ++ ++ /* ++ * If the length of digest is still longer than the length ++ * of the base point order, truncate remaining bits with a ++ * shift to that length. ++ */ ++ if (BYTES_TO_BITS(data_len) > order_bits && ++ !BN_rshift(m, m, DGST_SHIFT_NUM(order_bits))) { ++ fprintf(stderr, "failed to truncate input tbs!\n"); ++ BN_free(m); ++ return UADK_P_FAIL; ++ } ++ e->dsize = BN_bn2bin(m, (void *)e->data); ++ e->bsize = UADK_ECC_MAX_KEY_BYTES; ++ BN_free(m); ++ } else { ++ e->data = (char *)opdata->tbs; ++ e->dsize = data_len; ++ e->bsize = data_len; ++ } ++ ++ if (ecdsa_data_is_all_zero(e)) ++ return UADK_P_FAIL; ++ ++ return UADK_P_SUCCESS; ++} ++ ++static int ecdsa_sign_init_iot(handle_t sess, struct wd_ecc_req *req, ++ struct ecdsa_opdata *opdata) ++{ ++ char buff[UADK_ECC_MAX_KEY_BYTES] = {0}; ++ struct wd_ecc_out *ecc_out; ++ struct wd_ecc_in *ecc_in; ++ struct wd_dtb e = {0}; ++ int ret; ++ ++ e.data = buff; ++ ret = ecdsa_set_digest(opdata, &e); ++ if (!ret) ++ return ret; ++ ++ ecc_in = wd_ecdsa_new_sign_in(sess, &e, NULL); ++ if (unlikely(!ecc_in)) { ++ fprintf(stderr, "failed to new ecdsa sign in!\n"); ++ return UADK_P_FAIL; ++ } ++ ++ ecc_out = wd_ecdsa_new_sign_out(sess); ++ if (unlikely(!ecc_out)) { ++ fprintf(stderr, "failed to new ecdsa sign out!\n"); ++ wd_ecc_del_in(sess, ecc_in); ++ return UADK_P_FAIL; ++ } ++ ++ uadk_prov_ecc_fill_req(req, WD_ECDSA_SIGN, ecc_in, ecc_out); ++ ++ return UADK_P_SUCCESS; ++} ++ ++static void ecdsa_uninit_req_iot(handle_t sess, struct wd_ecc_req *req) ++{ ++ if (req->src) ++ wd_ecc_del_in(sess, req->src); ++ if (req->dst) ++ wd_ecc_del_out(sess, req->dst); ++} ++ ++static ECDSA_SIG *ecdsa_get_sign_data(struct wd_ecc_req *req) ++{ ++ struct wd_dtb *r = NULL; ++ struct wd_dtb *s = NULL; ++ BIGNUM *br, *bs; ++ ECDSA_SIG *sig; ++ int ret; ++ ++ br = BN_new(); ++ bs = BN_new(); ++ if (unlikely(!br || !bs)) { ++ fprintf(stderr, "failed to new br or bs!\n"); ++ goto free_bn; ++ } ++ ++ wd_ecdsa_get_sign_out_params(req->dst, &r, &s); ++ if (unlikely(!r || !s)) { ++ fprintf(stderr, "failed to get r or s\n"); ++ goto free_bn; ++ } ++ ++ if (!BN_bin2bn((void *)r->data, r->dsize, br) || ++ !BN_bin2bn((void *)s->data, s->dsize, bs)) { ++ fprintf(stderr, "failed to BN_bin2bn r or s\n"); ++ goto free_bn; ++ } ++ ++ sig = ECDSA_SIG_new(); ++ if (unlikely(!sig)) { ++ fprintf(stderr, "failed to new sig!\n"); ++ goto free_bn; ++ } ++ ++ ret = ECDSA_SIG_set0(sig, br, bs); ++ if (unlikely(!ret)) { ++ fprintf(stderr, "failed to set br or bs to sig!\n"); ++ goto free_sig; ++ } ++ ++ return sig; ++free_sig: ++ ECDSA_SIG_free(sig); ++free_bn: ++ BN_clear_free(br); ++ BN_clear_free(bs); ++ return NULL; ++} ++ ++static int ecdsa_hw_sign(struct ecdsa_opdata *opdata) ++{ ++ struct wd_ecc_req req = {0}; ++ handle_t sess; ++ int ret; ++ ++ sess = ecdsa_alloc_sess(opdata->ec); ++ if (unlikely(!sess)) { ++ fprintf(stderr, "failed to alloc ecdsa sess!\n"); ++ return UADK_P_FAIL; ++ } ++ ++ ret = ecdsa_sign_init_iot(sess, &req, opdata); ++ if (unlikely(!ret)) { ++ fprintf(stderr, "failed to ecdsa_sign_init_iot!\n"); ++ goto free_sess; ++ } ++ ++ ret = uadk_prov_ecc_set_private_key(sess, opdata->ec); ++ if (unlikely(!ret)) { ++ fprintf(stderr, "failed to set private key!\n"); ++ goto free_iot; ++ } ++ ++ ret = uadk_prov_ecc_crypto(sess, &req, (void *)sess); ++ if (unlikely(!ret)) { ++ fprintf(stderr, "failed to sign!\n"); ++ goto free_iot; ++ } ++ ++ opdata->sig = ecdsa_get_sign_data(&req); ++ if (!opdata->sig) ++ ret = UADK_P_FAIL; ++ ++free_iot: ++ ecdsa_uninit_req_iot(sess, &req); ++free_sess: ++ ecdsa_free_sess(sess); ++ return ret; ++} ++ ++static int ecdsa_sign_params_check(struct ecdsa_ctx *ctx, ++ struct ecdsa_opdata *opdata, ++ unsigned char *sig, size_t *siglen, ++ size_t sigsize) ++{ ++ size_t ecsize; ++ ++ if (unlikely(!siglen)) { ++ fprintf(stderr, "invalid: siglen is NULL to sign!\n"); ++ return UADK_P_FAIL; ++ } ++ ++ if (unlikely(!ctx || !ctx->ec)) { ++ fprintf(stderr, "invalid: ctx or ec is NULL to sign!\n"); ++ return UADK_P_FAIL; ++ } ++ ++ ecsize = ECDSA_size(ctx->ec); ++ if (unlikely(!sig)) { ++ *siglen = ecsize; ++ return UADK_SIGN_SIG_NULL; ++ } ++ ++ if (unlikely(sigsize < ecsize)) { ++ fprintf(stderr, "invalid: sigsize %zu is less than ecsize %zu!\n", ++ sigsize, ecsize); ++ return UADK_P_FAIL; ++ } ++ ++ return ecdsa_common_params_check(ctx, opdata); ++} ++ ++static int uadk_signature_ecdsa_sign(void *vctx, unsigned char *sig, size_t *siglen, ++ size_t sigsize, const unsigned char *tbs, size_t tbslen) ++{ ++ struct ecdsa_ctx *ctx = (struct ecdsa_ctx *)vctx; ++ struct ecdsa_opdata opdata = {0}; ++ int ret; ++ ++ opdata.tbs = tbs; ++ opdata.tbslen = tbslen; ++ ret = ecdsa_sign_params_check(ctx, &opdata, sig, siglen, sigsize); ++ if (ret == UADK_SIGN_SIG_NULL) { ++ return UADK_P_SUCCESS; ++ } else if (unlikely(!ret)) { ++ fprintf(stderr, "failed to check params to sign!\n"); ++ goto err; ++ } ++ ++ ret = ecdsa_hw_sign(&opdata); ++ if (unlikely(!ret)) ++ goto err; ++ ret = i2d_ECDSA_SIG(opdata.sig, &sig); ++ /* ECDSA_SIG_free will free br and bs applied for in ecdsa_get_sign_data() */ ++ ECDSA_SIG_free(opdata.sig); ++ if (ret < 0) ++ goto err; ++ ++ *siglen = (size_t)ret; ++ ++ return UADK_P_SUCCESS; ++err: ++ if (siglen) ++ *siglen = 0; ++ return UADK_P_FAIL; ++} ++ ++static int ecdsa_verify_init_iot(handle_t sess, struct wd_ecc_req *req, ++ struct ecdsa_opdata *opdata) ++{ ++ char buf_r[UADK_ECC_MAX_KEY_BYTES] = {0}; ++ char buf_s[UADK_ECC_MAX_KEY_BYTES] = {0}; ++ char buf_e[UADK_ECC_MAX_KEY_BYTES] = {0}; ++ const BIGNUM *sig_r = NULL; ++ const BIGNUM *sig_s = NULL; ++ struct wd_ecc_in *ecc_in; ++ struct wd_dtb e = {0}; ++ struct wd_dtb r = {0}; ++ struct wd_dtb s = {0}; ++ int ret; ++ ++ e.data = buf_e; ++ ret = ecdsa_set_digest(opdata, &e); ++ if (!ret) ++ return ret; ++ ++ r.data = buf_r; ++ s.data = buf_s; ++ r.bsize = UADK_ECC_MAX_KEY_BYTES; ++ s.bsize = UADK_ECC_MAX_KEY_BYTES; ++ ECDSA_SIG_get0(opdata->sig, &sig_r, &sig_s); ++ r.dsize = BN_bn2bin(sig_r, (void *)r.data); ++ s.dsize = BN_bn2bin(sig_s, (void *)s.data); ++ ecc_in = wd_ecdsa_new_verf_in(sess, &e, &r, &s); ++ if (unlikely(!ecc_in)) { ++ fprintf(stderr, "failed to new ecdsa verf in\n"); ++ return UADK_P_FAIL; ++ } ++ ++ uadk_prov_ecc_fill_req(req, WD_ECDSA_VERIFY, ecc_in, NULL); ++ ++ return UADK_P_SUCCESS; ++} ++ ++static int ecdsa_hw_verify(struct ecdsa_opdata *opdata) ++{ ++ struct wd_ecc_req req = {0}; ++ handle_t sess; ++ int ret; ++ ++ sess = ecdsa_alloc_sess(opdata->ec); ++ if (!sess) { ++ fprintf(stderr, "failed to alloc ecdsa sess!\n"); ++ return UADK_P_FAIL; ++ } ++ ++ ret = ecdsa_verify_init_iot(sess, &req, opdata); ++ if (!ret) ++ goto free_sess; ++ ++ ret = uadk_prov_ecc_set_public_key(sess, opdata->ec); ++ if (!ret) ++ goto free_iot; ++ ++ ret = uadk_prov_ecc_crypto(sess, &req, (void *)sess); ++ ++free_iot: ++ ecdsa_uninit_req_iot(sess, &req); ++free_sess: ++ ecdsa_free_sess(sess); ++ return ret; ++} ++ ++static int ecdsa_verify_params_check(struct ecdsa_ctx *ctx, struct ecdsa_opdata *opdata, ++ const unsigned char *sig, size_t siglen) ++{ ++ if (!ctx || !ctx->ec) { ++ fprintf(stderr, "invalid: ctx or ec is NULL to verify!\n"); ++ return UADK_P_FAIL; ++ } ++ ++ if (!sig || !siglen) { ++ fprintf(stderr, "invalid: sig is NULL or siglen %zu error!\n", siglen); ++ return UADK_P_FAIL; ++ } ++ ++ return ecdsa_common_params_check(ctx, opdata); ++} ++ ++static ECDSA_SIG *ecdsa_create_sig(const unsigned char *sig, size_t siglen) ++{ ++ const unsigned char *p = sig; ++ unsigned char *der = NULL; ++ ECDSA_SIG *s; ++ int derlen; ++ ++ s = ECDSA_SIG_new(); ++ if (!s) { ++ fprintf(stderr, "failed to new s to verify!\n"); ++ return NULL; ++ } ++ ++ if (!d2i_ECDSA_SIG(&s, &p, siglen)) { ++ fprintf(stderr, "failed to d2i_ECDSA_SIG: siglen = %zu!\n", ++ siglen); ++ goto err; ++ } ++ ++ /* Ensure signature uses DER and doesn't have trailing garbage */ ++ derlen = i2d_ECDSA_SIG(s, &der); ++ if (derlen != siglen || memcmp(sig, der, derlen) != 0) { ++ fprintf(stderr, "sig have trailing garbage, derlen %d!\n", derlen); ++ OPENSSL_free(der); ++ goto err; ++ } ++ ++ OPENSSL_free(der); ++ ++ return s; ++ ++err: ++ ECDSA_SIG_free(s); ++ return NULL; ++} ++ ++static int uadk_signature_ecdsa_verify(void *vctx, const unsigned char *sig, ++ size_t siglen, const unsigned char *tbs, ++ size_t tbslen) ++{ ++ struct ecdsa_ctx *ctx = (struct ecdsa_ctx *)vctx; ++ struct ecdsa_opdata opdata = {0}; ++ int ret; ++ ++ opdata.tbs = tbs; ++ opdata.tbslen = tbslen; ++ ret = ecdsa_verify_params_check(ctx, &opdata, sig, siglen); ++ if (!ret) { ++ fprintf(stderr, "failed to check params to sign!\n"); ++ return UADK_P_FAIL; ++ } ++ ++ opdata.sig = ecdsa_create_sig(sig, siglen); ++ if (!opdata.sig) { ++ fprintf(stderr, "failed to create s to verify!\n"); ++ return UADK_P_FAIL; ++ } ++ ++ ret = ecdsa_hw_verify(&opdata); ++ ++ ECDSA_SIG_free(opdata.sig); ++ return ret; ++} ++ ++static int ecdsa_digest_singverify_init(void *vctx, const char *mdname, void *ec, ++ const OSSL_PARAM params[], int operation) ++{ ++ struct ecdsa_ctx *ctx = (struct ecdsa_ctx *)vctx; ++ int ret; ++ ++ ret = ecdsa_signverify_init(vctx, ec, params, operation); ++ if (!ret) ++ return ret; ++ ++ ret = ecdsa_setup_md(ctx, mdname, NULL); ++ if (!ret) ++ return ret; ++ ++ ctx->flag_allow_md = false; ++ if (!ctx->mdctx) { ++ ctx->mdctx = EVP_MD_CTX_new(); ++ if (!ctx->mdctx) ++ goto err; ++ } ++ ++ ret = EVP_DigestInit_ex2(ctx->mdctx, ctx->md, params); ++ if (!ret) ++ goto err; ++ ++ return UADK_P_SUCCESS; ++ ++err: ++ EVP_MD_CTX_free(ctx->mdctx); ++ ctx->mdctx = NULL; ++ return UADK_P_FAIL; ++} ++ ++static int uadk_signature_ecdsa_digest_sign_init(void *vctx, const char *mdname, ++ void *ec, const OSSL_PARAM params[]) ++{ ++ return ecdsa_digest_singverify_init(vctx, mdname, ec, params, EVP_PKEY_OP_SIGN); ++} ++ ++static int ecdsa_digest_signverify_update(void *vctx, const unsigned char *data, ++ size_t datalen) ++{ ++ struct ecdsa_ctx *ctx = (struct ecdsa_ctx *)vctx; ++ ++ if (!ctx || !ctx->mdctx) { ++ fprintf(stderr, "invalid: ctx or mdctx is NULL to digest update!\n"); ++ return UADK_P_FAIL; ++ } ++ ++ return EVP_DigestUpdate(ctx->mdctx, data, datalen); ++} ++ ++static int uadk_signature_ecdsa_digest_sign_update(void *vctx, const unsigned char *data, ++ size_t datalen) ++{ ++ return ecdsa_digest_signverify_update(vctx, data, datalen); ++} ++ ++static int uadk_signature_ecdsa_digest_sign_final(void *vctx, unsigned char *sig, ++ size_t *siglen, size_t sigsize) ++{ ++ struct ecdsa_ctx *ctx = (struct ecdsa_ctx *)vctx; ++ unsigned char digest[EVP_MAX_MD_SIZE]; ++ unsigned int dlen = 0; ++ ++ if (!ctx || !ctx->mdctx) { ++ fprintf(stderr, "invalid: ctx or mdctx is NULL to sign digest final!\n"); ++ return UADK_P_FAIL; ++ } ++ ++ /* ++ * If sig is NULL then we're just finding out the sig size. Other fields ++ * are ignored. Defer to uadk_signature_ecdsa_sign. ++ */ ++ if (sig && !EVP_DigestFinal_ex(ctx->mdctx, digest, &dlen)) ++ return UADK_P_FAIL; ++ ++ ctx->flag_allow_md = true; ++ ++ return uadk_signature_ecdsa_sign(vctx, sig, siglen, sigsize, digest, (size_t)dlen); ++} ++ ++static int uadk_signature_ecdsa_digest_verify_init(void *vctx, const char *mdname, ++ void *ec, const OSSL_PARAM params[]) ++{ ++ return ecdsa_digest_singverify_init(vctx, mdname, ec, params, EVP_PKEY_OP_VERIFY); ++} ++ ++static int uadk_signature_ecdsa_digest_verify_update(void *vctx, const unsigned char *data, ++ size_t datalen) ++{ ++ return ecdsa_digest_signverify_update(vctx, data, datalen); ++} ++ ++static int uadk_signature_ecdsa_digest_verify_final(void *vctx, const unsigned char *sig, ++ size_t siglen) ++{ ++ struct ecdsa_ctx *ctx = (struct ecdsa_ctx *)vctx; ++ unsigned char digest[EVP_MAX_MD_SIZE]; ++ unsigned int dlen = 0; ++ ++ if (!ctx || !ctx->mdctx) { ++ fprintf(stderr, "invalid: ctx or mdctx is NULL to verify digest final!\n"); ++ return UADK_P_FAIL; ++ } ++ ++ if (!EVP_DigestFinal_ex(ctx->mdctx, digest, &dlen)) ++ return UADK_P_FAIL; ++ ++ ctx->flag_allow_md = true; ++ ++ return uadk_signature_ecdsa_verify(vctx, sig, siglen, digest, (size_t)dlen); ++} ++ ++static int ecdsa_get_ctx_aid(struct ecdsa_ctx *ctx, OSSL_PARAM *params) ++{ ++ OSSL_PARAM *p; ++ ++ p = OSSL_PARAM_locate(params, OSSL_SIGNATURE_PARAM_ALGORITHM_ID); ++ if (!p) ++ return UADK_P_SUCCESS; ++ ++ return OSSL_PARAM_set_octet_string(p, ctx->aid, ctx->aid_len); ++} ++ ++static int ecdsa_get_ctx_digest_size(struct ecdsa_ctx *ctx, OSSL_PARAM *params) ++{ ++ OSSL_PARAM *p; ++ ++ p = OSSL_PARAM_locate(params, OSSL_SIGNATURE_PARAM_DIGEST_SIZE); ++ if (!p) ++ return UADK_P_SUCCESS; ++ ++ return OSSL_PARAM_set_size_t(p, ctx->mdsize); ++} ++ ++static int ecdsa_get_ctx_digest(struct ecdsa_ctx *ctx, OSSL_PARAM *params) ++{ ++ const char *mdname; ++ OSSL_PARAM *p; ++ ++ p = OSSL_PARAM_locate(params, OSSL_SIGNATURE_PARAM_DIGEST); ++ if (!p) ++ return UADK_P_SUCCESS; ++ ++ mdname = ctx->md ? EVP_MD_get0_name(ctx->md) : ctx->mdname; ++ ++ return OSSL_PARAM_set_utf8_string(p, mdname); ++} ++ ++static int uadk_signature_ecdsa_get_ctx_params(void *vctx, OSSL_PARAM *params) ++{ ++ struct ecdsa_ctx *ctx = (struct ecdsa_ctx *)vctx; ++ int ret; ++ ++ if (!ctx) { ++ fprintf(stderr, "invalid: ctx is NULL to get_ctx_params!\n"); ++ return UADK_P_FAIL; ++ } ++ ++ if (!params) ++ return UADK_P_SUCCESS; ++ ++ ret = ecdsa_get_ctx_digest(ctx, params); ++ if (!ret) ++ return ret; ++ ++ ret = ecdsa_get_ctx_digest_size(ctx, params); ++ if (!ret) ++ return ret; ++ ++ return ecdsa_get_ctx_aid(ctx, params); ++} ++ ++static const OSSL_PARAM known_gettable_ctx_params[] = { ++ OSSL_PARAM_octet_string(OSSL_SIGNATURE_PARAM_ALGORITHM_ID, NULL, 0), ++ OSSL_PARAM_size_t(OSSL_SIGNATURE_PARAM_DIGEST_SIZE, NULL), ++ OSSL_PARAM_utf8_string(OSSL_SIGNATURE_PARAM_DIGEST, NULL, 0), ++ OSSL_PARAM_END ++}; ++ ++static const OSSL_PARAM * ++uadk_signature_ecdsa_gettable_ctx_params(ossl_unused void *vctx, ++ ossl_unused void *provctx) ++{ ++ return known_gettable_ctx_params; ++} ++ ++static int ecdsa_set_ctx_digest(struct ecdsa_ctx *ctx, const OSSL_PARAM params[]) ++{ ++ char mdname[DIGEST_MAX_NAME_SIZE] = {0}; ++ char mdprops[MAX_PROPQUERY_SIZE] = {0}; ++ const OSSL_PARAM *p_digest, *propsp; ++ char *pmdprops = mdprops; ++ char *pmdname = mdname; ++ int ret; ++ ++ p_digest = OSSL_PARAM_locate_const(params, OSSL_SIGNATURE_PARAM_DIGEST); ++ if (!p_digest) ++ return UADK_P_SUCCESS; ++ ++ ret = OSSL_PARAM_get_utf8_string(p_digest, &pmdname, DIGEST_MAX_NAME_SIZE); ++ if (!ret) ++ return UADK_P_FAIL; ++ ++ propsp = OSSL_PARAM_locate_const(params, OSSL_SIGNATURE_PARAM_PROPERTIES); ++ if (propsp) { ++ ret = OSSL_PARAM_get_utf8_string(propsp, &pmdprops, MAX_PROPQUERY_SIZE); ++ if (!ret) ++ return UADK_P_FAIL; ++ } ++ ++ return ecdsa_setup_md(ctx, mdname, mdprops); ++} ++ ++static int ecdsa_set_ctx_digest_size(struct ecdsa_ctx *ctx, const OSSL_PARAM params[]) ++{ ++ const OSSL_PARAM *p; ++ size_t mdsize = 0; ++ int ret; ++ ++ p = OSSL_PARAM_locate_const(params, OSSL_SIGNATURE_PARAM_DIGEST_SIZE); ++ if (!p) ++ return UADK_P_SUCCESS; ++ ++ ret = OSSL_PARAM_get_size_t(p, &mdsize); ++ if (!ret) ++ return UADK_P_FAIL; ++ ++ if (!ctx->flag_allow_md && mdsize != ctx->mdsize) ++ return UADK_P_FAIL; ++ ++ ctx->mdsize = mdsize; ++ ++ return UADK_P_SUCCESS; ++} ++ ++static int uadk_signature_ecdsa_set_ctx_params(void *vctx, const OSSL_PARAM params[]) ++{ ++ struct ecdsa_ctx *ctx = (struct ecdsa_ctx *)vctx; ++ int ret; ++ ++ if (!ctx) { ++ fprintf(stderr, "invalid: ctx is NULL to set_ctx_params!\n"); ++ return UADK_P_FAIL; ++ } ++ ++ if (!params) ++ return UADK_P_SUCCESS; ++ ++ ret = ecdsa_set_ctx_digest(ctx, params); ++ if (!ret) ++ return ret; ++ ++ return ecdsa_set_ctx_digest_size(ctx, params); ++} ++ ++static const OSSL_PARAM settable_ctx_params[] = { ++ OSSL_PARAM_utf8_string(OSSL_SIGNATURE_PARAM_DIGEST, NULL, 0), ++ OSSL_PARAM_size_t(OSSL_SIGNATURE_PARAM_DIGEST_SIZE, NULL), ++ OSSL_PARAM_utf8_string(OSSL_SIGNATURE_PARAM_PROPERTIES, NULL, 0), ++ OSSL_PARAM_uint(OSSL_SIGNATURE_PARAM_KAT, NULL), ++ OSSL_PARAM_END ++}; ++ ++static const OSSL_PARAM settable_ctx_params_no_digest[] = { ++ OSSL_PARAM_uint(OSSL_SIGNATURE_PARAM_KAT, NULL), ++ OSSL_PARAM_END ++}; ++ ++static const OSSL_PARAM * ++uadk_signature_ecdsa_settable_ctx_params(void *vctx, ossl_unused void *provctx) ++{ ++ struct ecdsa_ctx *ctx = (struct ecdsa_ctx *)vctx; ++ ++ if (ctx && !ctx->flag_allow_md) ++ return settable_ctx_params_no_digest; ++ ++ return settable_ctx_params; ++} ++ ++static int uadk_signature_ecdsa_get_ctx_md_params(void *vctx, OSSL_PARAM *params) ++{ ++ struct ecdsa_ctx *ctx = (struct ecdsa_ctx *)vctx; ++ ++ if (!ctx || !ctx->mdctx) { ++ fprintf(stderr, "invalid: ctx or md ctx is NULL to get_ctx_md_params!\n"); ++ return UADK_P_FAIL; ++ } ++ ++ return EVP_MD_CTX_get_params(ctx->mdctx, params); ++} ++ ++static const OSSL_PARAM *uadk_signature_ecdsa_gettable_ctx_md_params(void *vctx) ++{ ++ struct ecdsa_ctx *ctx = (struct ecdsa_ctx *)vctx; ++ ++ if (!ctx || !ctx->md) { ++ fprintf(stderr, "invalid: ctx or md is NULL to gettable_ctx_md_params!\n"); ++ return NULL; ++ } ++ ++ return EVP_MD_gettable_ctx_params(ctx->md); ++} ++ ++static int uadk_signature_ecdsa_set_ctx_md_params(void *vctx, const OSSL_PARAM params[]) ++{ ++ struct ecdsa_ctx *ctx = (struct ecdsa_ctx *)vctx; ++ ++ if (!ctx || !ctx->mdctx) { ++ fprintf(stderr, "invalid: ctx or md ctx is NULL to set_ctx_md_params!\n"); ++ return UADK_P_FAIL; ++ } ++ ++ return EVP_MD_CTX_set_params(ctx->mdctx, params); ++} ++ ++static const OSSL_PARAM *uadk_signature_ecdsa_settable_ctx_md_params(void *vctx) ++{ ++ struct ecdsa_ctx *ctx = (struct ecdsa_ctx *)vctx; ++ ++ if (!ctx || !ctx->md) { ++ fprintf(stderr, "invalid: ctx or md is NULL to settable_ctx_md_params!\n"); ++ return NULL; ++ } ++ ++ return EVP_MD_settable_ctx_params(ctx->md); ++} ++ ++static int uadk_signature_ecdsa_verify_recover_init(void *vctx, void *vecdsa, ++ const OSSL_PARAM params[]) ++{ ++ return UADK_P_SUCCESS; ++} ++ ++static int uadk_signature_ecdsa_verify_recover(void *vctx, unsigned char *rout, ++ size_t *routlen, size_t routsize, ++ const unsigned char *sig, size_t siglen) ++{ ++ return UADK_P_SUCCESS; ++} +diff --git a/src/uadk_prov_init.c b/src/uadk_prov_init.c +index 9a2baeb..52d0b90 100644 +--- a/src/uadk_prov_init.c ++++ b/src/uadk_prov_init.c +@@ -165,6 +165,8 @@ static const OSSL_ALGORITHM uadk_prov_signature[] = { + uadk_rsa_signature_functions, "uadk_provider rsa_signature" }, + { "SM2", UADK_DEFAULT_PROPERTIES, + uadk_sm2_signature_functions, "uadk_provider sm2_signature" }, ++ { "ECDSA", UADK_DEFAULT_PROPERTIES, ++ uadk_ecdsa_signature_functions, "uadk_provider ecdsa_signature" }, + { NULL, NULL, NULL } + }; + +diff --git a/src/uadk_prov_pkey.c b/src/uadk_prov_pkey.c +index f654dd6..ebf90e4 100644 +--- a/src/uadk_prov_pkey.c ++++ b/src/uadk_prov_pkey.c +@@ -680,7 +680,7 @@ void uadk_prov_keymgmt_alg(void) + + void uadk_prov_signature_alg(void) + { +- static const char * const signature_alg[] = {"sm2"}; ++ static const char * const signature_alg[] = {"sm2", "ecdsa"}; + __u32 i, size; + bool sp; + +diff --git a/src/uadk_prov_pkey.h b/src/uadk_prov_pkey.h +index f40313d..38a67ac 100644 +--- a/src/uadk_prov_pkey.h ++++ b/src/uadk_prov_pkey.h +@@ -75,6 +75,7 @@ enum { + + enum { + SIGNATURE_SM2 = 0x0, ++ SIGNATURE_ECDSA = 0x1, + SIGNATURE_MAX = 0x3 + }; + +-- +2.25.1 + diff --git a/0010-uadk_async-check-type-and-ctx-in-task.patch b/0010-uadk_async-check-type-and-ctx-in-task.patch new file mode 100644 index 0000000..05be920 --- /dev/null +++ b/0010-uadk_async-check-type-and-ctx-in-task.patch @@ -0,0 +1,45 @@ +From 109a9b5f449d721469a70dffd504facc31987d23 Mon Sep 17 00:00:00 2001 +From: Weili Qian +Date: Fri, 24 Jan 2025 09:14:03 +0800 +Subject: [PATCH 10/19] uadk_async: check type and ctx in task + +Currently, the async_get_queue_task() only checks whether op in task +is NULL. However, instructions executed by the CPU core are out of order. +Therefore, it cannot be ensured that type and ctx are assigned values when +op is assigned values in async_add_poll_task(). If the value of ctx in the +task is NULL or the value of type is invalid, the CPU core will access an +abnormal address, resulting in segment error. Therefore, before using +ctx or type, check whether the value is valid. + +Signed-off-by: Weili Qian +Signed-off-by: JiangShui Yang +--- + src/uadk_async.c | 5 ++++- + 1 file changed, 4 insertions(+), 1 deletion(-) + +diff --git a/src/uadk_async.c b/src/uadk_async.c +index 4f2ec6a..7536bd5 100644 +--- a/src/uadk_async.c ++++ b/src/uadk_async.c +@@ -147,7 +147,8 @@ err: + if (pthread_mutex_unlock(&poll_queue.async_task_mutex)) + return NULL; + +- if (cur_task && !cur_task->op) ++ if (!cur_task || !cur_task->op || ++ !cur_task->ctx || cur_task->type == ASYNC_TASK_MAX) + return NULL; + + return cur_task; +@@ -197,6 +198,8 @@ int async_get_free_task(int *id) + task_queue = poll_queue.head; + task = &task_queue[idx]; + task->op = NULL; ++ task->ctx = NULL; ++ task->type = ASYNC_TASK_MAX; + ret = UADK_E_SUCCESS; + + out: +-- +2.25.1 + diff --git a/0011-uadk_provider-use-default-provider-to-get-random-dat.patch b/0011-uadk_provider-use-default-provider-to-get-random-dat.patch new file mode 100644 index 0000000..028f820 --- /dev/null +++ b/0011-uadk_provider-use-default-provider-to-get-random-dat.patch @@ -0,0 +1,63 @@ +From 3e5a64f69d8f7cc132ea092b42b304e7e7fbdd79 Mon Sep 17 00:00:00 2001 +From: Weili Qian +Date: Fri, 24 Jan 2025 09:14:03 +0800 +Subject: [PATCH 11/19] uadk_provider: use default provider to get random data + +In asynchronous scenarios, if random numbers are obtained using +uadk provider cipher, deadlocks may occur. Therefore, random numbers +are obtained using default provider cipher. + +logs like: +20808E99FFFF0000:error:1C8000B6:Provider routines:ossl_drbg_lock_parent: +parent locking not enabled:providers/implementations/rands/drbg.c:70: +20808E99FFFF0000:error:1C8000C9:Provider routines:get_parent_strength: +unable to lock parent:providers/implementations/rands/drbg.c:97: +20808E99FFFF0000:error:1C8000BD:Provider routines: +ossl_prov_drbg_instantiate: error retrieving entropy: +providers/implementations/rands/drbg.c:456: +20808E99FFFF0000:error:1C8000C0:Provider routines:ossl_prov_drbg_generate: +in error state:providers/implementations/rands/drbg.c:630: +20808E99FFFF0000:error:030000D6:digital envelope routines: +evp_rand_generate_locked:generate error:crypto/evp/evp_rand.c:560: + +Signed-off-by: Weili Qian +Signed-off-by: JiangShui Yang +--- + src/uadk_prov_init.c | 11 ++++++++++- + 1 file changed, 10 insertions(+), 1 deletion(-) + +diff --git a/src/uadk_prov_init.c b/src/uadk_prov_init.c +index 52d0b90..41733b5 100644 +--- a/src/uadk_prov_init.c ++++ b/src/uadk_prov_init.c +@@ -25,6 +25,7 @@ + #include + #include + #include ++#include + + #include "uadk_async.h" + #include "uadk_prov.h" +@@ -210,10 +211,18 @@ static const OSSL_ALGORITHM *uadk_query(void *provctx, int operation_id, + prov = OSSL_PROVIDER_load(NULL, "default"); + if (!prov_init) { + prov_init = 1; +- /* uadk_provider takes the highest priority ++ /* ++ * uadk_provider takes the highest priority + * and overwrite the openssl.cnf property. + */ + EVP_set_default_properties(NULL, "?provider=uadk_provider"); ++ /* ++ * In asynchronous scenarios, if random numbers are obtained using ++ * uadk provider cipher, deadlocks may occur. Therefore, random numbers are ++ * obtained using default provider cipher. ++ */ ++ (void)RAND_set_DRBG_type(prov_libctx_of(provctx), NULL, ++ "provider=default", NULL, NULL); + } + + *no_cache = 0; +-- +2.25.1 + diff --git a/0012-uadk_provider_aead-cleanup-functions-in-aead.patch b/0012-uadk_provider_aead-cleanup-functions-in-aead.patch new file mode 100644 index 0000000..d06b9fe --- /dev/null +++ b/0012-uadk_provider_aead-cleanup-functions-in-aead.patch @@ -0,0 +1,186 @@ +From 5935fd230da67146a3287caddef116c47f8472c8 Mon Sep 17 00:00:00 2001 +From: Chenghai Huang +Date: Fri, 24 Jan 2025 09:14:03 +0800 +Subject: [PATCH 12/19] uadk_provider_aead: cleanup functions in aead + +Modify redundant lines of code and extract the same code to +separate functions. + +Signed-off-by: Chenghai Huang +Signed-off-by: JiangShui Yang +--- + src/uadk_prov_aead.c | 88 +++++++++++++++++++++----------------------- + 1 file changed, 41 insertions(+), 47 deletions(-) + +diff --git a/src/uadk_prov_aead.c b/src/uadk_prov_aead.c +index d6e90ca..9861519 100644 +--- a/src/uadk_prov_aead.c ++++ b/src/uadk_prov_aead.c +@@ -178,7 +178,6 @@ mutex_unlock: + + static int uadk_prov_aead_ctx_init(struct aead_priv_ctx *priv) + { +- struct wd_aead_sess_setup setup = {0}; + struct sched_params params = {0}; + int ret; + +@@ -201,11 +200,10 @@ static int uadk_prov_aead_ctx_init(struct aead_priv_ctx *priv) + params.type = 0; + /* Use the default numa parameters */ + params.numa_id = -1; +- memcpy(&setup, &priv->setup, sizeof(struct wd_aead_sess_setup)); +- setup.sched_param = ¶ms; ++ priv->setup.sched_param = ¶ms; + + if (!priv->sess) { +- priv->sess = wd_aead_alloc_sess(&setup); ++ priv->sess = wd_aead_alloc_sess(&priv->setup); + if (!priv->sess) { + fprintf(stderr, "uadk failed to alloc session!\n"); + return UADK_AEAD_FAIL; +@@ -234,21 +232,17 @@ free_sess: + + static void *uadk_prov_aead_cb(struct wd_aead_req *req, void *data) + { +- struct uadk_e_cb_info *cb_param; ++ struct uadk_e_cb_info *aead_cb_param; + struct wd_aead_req *req_origin; + struct async_op *op; + +- if (!req) +- return NULL; +- +- cb_param = req->cb_param; +- if (!cb_param) ++ if (!req || !req->cb_param) + return NULL; + +- req_origin = cb_param->priv; ++ aead_cb_param = req->cb_param; ++ req_origin = aead_cb_param->priv; + req_origin->state = req->state; +- +- op = cb_param->op; ++ op = aead_cb_param->op; + if (op && op->job && !op->done) { + op->done = 1; + async_free_poll_task(op->idx, 1); +@@ -280,18 +274,18 @@ static int do_aes_gcm_prepare(struct aead_priv_ctx *priv) + return UADK_AEAD_SUCCESS; + } + +-static void uadk_do_aead_async_prepare(struct aead_priv_ctx *priv, unsigned char *out, +- const unsigned char *in, size_t inlen) ++static void uadk_do_aead_async_prepare(struct aead_priv_ctx *priv, unsigned char *output, ++ const unsigned char *input, size_t inlen) + { + priv->req.in_bytes = inlen; +- /* AAD data is input or output together with plaintext or ciphertext. */ ++ /* AAD data will be input and output together with plaintext or ciphertext. */ + if (priv->req.assoc_bytes) { +- memcpy(priv->data + priv->req.assoc_bytes, in, inlen); ++ memcpy(priv->data + priv->req.assoc_bytes, input, 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; ++ priv->req.src = (unsigned char *)input; ++ priv->req.dst = output; + } + } + +@@ -790,6 +784,25 @@ static const OSSL_PARAM *uadk_prov_aead_gettable_ctx_params(ossl_unused void *cc + return uadk_prov_aead_ctx_params; + } + ++static int uadk_prov_aead_get_ctx_iv(OSSL_PARAM *p, struct aead_priv_ctx *priv) ++{ ++ if (priv->iv_set == IV_STATE_UNINITIALISED) ++ return UADK_OSSL_FAIL; ++ ++ if (priv->ivlen > p->data_size) { ++ ERR_raise(ERR_LIB_PROV, PROV_R_INVALID_IV_LENGTH); ++ return UADK_OSSL_FAIL; ++ } ++ ++ if (!OSSL_PARAM_set_octet_string(p, priv->iv, priv->ivlen) ++ && !OSSL_PARAM_set_octet_ptr(p, &priv->iv, priv->ivlen)) { ++ ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_SET_PARAMETER); ++ return UADK_OSSL_FAIL; ++ } ++ ++ return UADK_AEAD_SUCCESS; ++} ++ + static int uadk_prov_aead_get_ctx_params(void *vctx, OSSL_PARAM params[]) + { + struct aead_priv_ctx *priv = (struct aead_priv_ctx *)vctx; +@@ -822,34 +835,12 @@ static int uadk_prov_aead_get_ctx_params(void *vctx, OSSL_PARAM params[]) + } + + p = OSSL_PARAM_locate(params, OSSL_CIPHER_PARAM_IV); +- if (p) { +- if (priv->iv_set == IV_STATE_UNINITIALISED) +- return UADK_OSSL_FAIL; +- if (priv->ivlen > p->data_size) { +- ERR_raise(ERR_LIB_PROV, PROV_R_INVALID_IV_LENGTH); +- return UADK_OSSL_FAIL; +- } +- if (!OSSL_PARAM_set_octet_string(p, priv->iv, priv->ivlen) +- && !OSSL_PARAM_set_octet_ptr(p, &priv->iv, priv->ivlen)) { +- ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_SET_PARAMETER); +- return UADK_OSSL_FAIL; +- } +- } ++ if (p && !uadk_prov_aead_get_ctx_iv(p, priv)) ++ return UADK_OSSL_FAIL; + + p = OSSL_PARAM_locate(params, OSSL_CIPHER_PARAM_UPDATED_IV); +- if (p) { +- if (priv->iv_set == IV_STATE_UNINITIALISED) +- return UADK_OSSL_FAIL; +- if (priv->ivlen > p->data_size) { +- ERR_raise(ERR_LIB_PROV, PROV_R_INVALID_IV_LENGTH); +- return UADK_OSSL_FAIL; +- } +- if (!OSSL_PARAM_set_octet_string(p, priv->iv, priv->ivlen) +- && !OSSL_PARAM_set_octet_ptr(p, &priv->iv, priv->ivlen)) { +- ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_SET_PARAMETER); +- return UADK_OSSL_FAIL; +- } +- } ++ if (p && !uadk_prov_aead_get_ctx_iv(p, priv)) ++ return UADK_OSSL_FAIL; + + p = OSSL_PARAM_locate(params, OSSL_CIPHER_PARAM_AEAD_TAG); + if (p) { +@@ -958,10 +949,13 @@ static void uadk_prov_aead_freectx(void *ctx) + priv->sess = 0; + } + ++ + if (priv->data) { + OPENSSL_clear_free(priv->data, AEAD_BLOCK_SIZE << 1); + priv->data = NULL; + } ++ ++ + OPENSSL_clear_free(priv, sizeof(*priv)); + } + +@@ -974,9 +968,9 @@ static void *uadk_##nm##_newctx(void *provctx) \ + if (!ctx) \ + return NULL; \ + \ +- ctx->data = OPENSSL_zalloc(AEAD_BLOCK_SIZE << 1); \ ++ ctx->data = OPENSSL_clear_free(ctx, sizeof(*ctx)); \ + if (!ctx->data) { \ +- OPENSSL_clear_free(ctx, sizeof(*ctx)); \ ++ OPENSSL_free(ctx); \ + return NULL; \ + } \ + \ +-- +2.25.1 + diff --git a/0013-uadk_provider-fix-the-fork-function-of-the-digest.patch b/0013-uadk_provider-fix-the-fork-function-of-the-digest.patch new file mode 100644 index 0000000..aacfbdb --- /dev/null +++ b/0013-uadk_provider-fix-the-fork-function-of-the-digest.patch @@ -0,0 +1,214 @@ +From 1e930be39a90d882ded0cbbca87c03d55da8e425 Mon Sep 17 00:00:00 2001 +From: Chenghai Huang +Date: Tue, 18 Feb 2025 19:41:23 +0800 +Subject: [PATCH 13/19] uadk_provider: fix the fork function of the digest + +1.Add unlock when fork to prevent deadlock. +2.Before executing uadk digest, check whether the pid is new. +If the process is a new process, initialize resources. + +Signed-off-by: Chenghai Huang +--- + src/uadk_prov_digest.c | 122 +++++++++++++++++++++++++++++++---------- + 1 file changed, 94 insertions(+), 28 deletions(-) + +diff --git a/src/uadk_prov_digest.c b/src/uadk_prov_digest.c +index 0fe31d2..2e197b2 100644 +--- a/src/uadk_prov_digest.c ++++ b/src/uadk_prov_digest.c +@@ -53,6 +53,9 @@ + #define DIGEST_BLOCK_SIZE (512 * 1024) + #define ALG_NAME_SIZE 128 + ++#define UADK_DIGEST_DEF_CTXS 1 ++#define UADK_DIGEST_OP_NUM 1 ++ + enum sec_digest_state { + SEC_DIGEST_INIT, + SEC_DIGEST_FIRST_UPDATING, +@@ -272,41 +275,76 @@ static int uadk_get_digest_info(struct digest_priv_ctx *priv) + return UADK_DIGEST_SUCCESS; + } + +-static int uadk_digest_init(struct digest_priv_ctx *priv) ++static void uadk_digest_mutex_infork(void) + { +- struct sched_params params = {0}; +- int ret; ++ /* Release the replication lock of the child process */ ++ pthread_mutex_unlock(&digest_mutex); ++} ++ ++static int uadk_prov_digest_dev_init(struct digest_priv_ctx *priv) ++{ ++ struct wd_ctx_params cparams = {0}; ++ struct wd_ctx_nums ctx_set_num; ++ int ret = UADK_DIGEST_SUCCESS; + ++ pthread_atfork(NULL, NULL, uadk_digest_mutex_infork); + pthread_mutex_lock(&digest_mutex); +- if (dprov.pid != getpid()) { +- ret = wd_digest_init2(priv->alg_name, 0, 0); +- if (unlikely(ret)) { +- priv->switch_flag = UADK_DO_SOFT; +- goto soft_init; +- } +- dprov.pid = getpid(); +- async_register_poll_fn(ASYNC_TASK_DIGEST, uadk_digest_poll); ++ if (dprov.pid == getpid()) ++ goto mutex_unlock; ++ ++ cparams.op_type_num = UADK_DIGEST_OP_NUM; ++ cparams.ctx_set_num = &ctx_set_num; ++ cparams.bmp = numa_allocate_nodemask(); ++ if (!cparams.bmp) { ++ ret = UADK_DIGEST_FAIL; ++ fprintf(stderr, "failed to create nodemask!\n"); ++ goto mutex_unlock; + } ++ ++ numa_bitmask_setall(cparams.bmp); ++ ++ ctx_set_num.sync_ctx_num = UADK_DIGEST_DEF_CTXS; ++ ctx_set_num.async_ctx_num = UADK_DIGEST_DEF_CTXS; ++ ++ ret = wd_digest_init2_(priv->alg_name, TASK_MIX, SCHED_POLICY_RR, &cparams); ++ if (unlikely(ret)) { ++ fprintf(stderr, "uadk failed to initialize digest.\n"); ++ goto free_nodemask; ++ } ++ ret = UADK_DIGEST_SUCCESS; ++ ++ dprov.pid = getpid(); ++ async_register_poll_fn(ASYNC_TASK_DIGEST, uadk_digest_poll); ++ ++free_nodemask: ++ numa_free_nodemask(cparams.bmp); ++mutex_unlock: + pthread_mutex_unlock(&digest_mutex); ++ return ret; ++} + +- ret = uadk_get_digest_info(priv); +- if (unlikely(!ret)) +- return ret; ++static int uadk_digest_ctx_init(struct digest_priv_ctx *priv) ++{ ++ struct wd_digest_sess_setup setup = {0}; ++ struct sched_params params = {0}; ++ int ret; ++ ++ ret = uadk_prov_digest_dev_init(priv); ++ if (unlikely(ret <= 0)) ++ goto soft_init; + + /* Use the default numa parameters */ + params.numa_id = -1; +- priv->setup.sched_param = ¶ms; +- priv->sess = wd_digest_alloc_sess(&priv->setup); +- if (unlikely(!priv->sess)) { +- fprintf(stderr, "uadk failed to alloc sess.\n"); +- return UADK_DIGEST_FAIL; +- } +- +- priv->data = OPENSSL_malloc(DIGEST_BLOCK_SIZE); +- if (unlikely(!priv->data)) { +- wd_digest_free_sess(priv->sess); +- fprintf(stderr, "uadk failed to apply mem for data storage.\n"); +- return UADK_DIGEST_FAIL; ++ setup.sched_param = ¶ms; ++ setup.alg = priv->setup.alg; ++ setup.mode = priv->setup.mode; ++ ++ if (!priv->sess) { ++ priv->sess = wd_digest_alloc_sess(&setup); ++ if (unlikely(!priv->sess)) { ++ fprintf(stderr, "uadk failed to alloc sess.\n"); ++ return UADK_DIGEST_FAIL; ++ } + } + + if (enable_sw_offload) +@@ -352,6 +390,10 @@ static int uadk_digest_update_inner(struct digest_priv_ctx *priv, const void *da + size_t processing_len; + int ret; + ++ ret = uadk_digest_ctx_init(priv); ++ if (ret != UADK_DIGEST_SUCCESS) ++ return UADK_DIGEST_FAIL; ++ + priv->req.has_next = DIGEST_DOING; + uadk_fill_mac_buffer_len(priv); + +@@ -530,6 +572,10 @@ static int uadk_digest_final(struct digest_priv_ctx *priv, unsigned char *digest + return UADK_DIGEST_FAIL; + } + ++ ret = uadk_digest_ctx_init(priv); ++ if (ret != UADK_DIGEST_SUCCESS) ++ return UADK_DIGEST_FAIL; ++ + priv->req.has_next = DIGEST_END; + priv->req.in = priv->data; + priv->req.out = priv->out; +@@ -586,6 +632,10 @@ static int uadk_digest_digest(struct digest_priv_ctx *priv, const void *data, si + return UADK_DIGEST_FAIL; + } + ++ ret = uadk_digest_ctx_init(priv); ++ if (ret != UADK_DIGEST_SUCCESS) ++ return UADK_DIGEST_FAIL; ++ + ret = async_setup_async_event_notification(&op); + if (unlikely(!ret)) { + fprintf(stderr, "failed to setup async event notification.\n"); +@@ -626,7 +676,7 @@ static void uadk_digest_cleanup(struct digest_priv_ctx *priv) + OPENSSL_free(priv->data); + + if (priv->soft_ctx) +- OPENSSL_free(priv->soft_ctx); ++ OPENSSL_free(priv->data); + } + + /* some params related code is copied from OpenSSL v3.0 prov/digestcommon.h */ +@@ -704,13 +754,22 @@ static void *uadk_prov_dupctx(void *dctx) + static int uadk_prov_init(void *dctx, const OSSL_PARAM params[]) + { + struct digest_priv_ctx *priv = (struct digest_priv_ctx *)dctx; ++ int ret; + + if (!dctx) { + fprintf(stderr, "CTX is NULL.\n"); + return UADK_DIGEST_FAIL; + } + +- return uadk_digest_init(priv); ++ ret = uadk_get_digest_info(priv); ++ if (unlikely(!ret)) ++ return UADK_DIGEST_FAIL; ++ ++ ret = uadk_prov_digest_dev_init(priv); ++ if (unlikely(ret <= 0)) ++ return UADK_DIGEST_FAIL; ++ ++ return UADK_DIGEST_SUCCESS; + } + + static int uadk_prov_update(void *dctx, const unsigned char *in, size_t inl) +@@ -808,6 +867,13 @@ static void *uadk_##name##_newctx(void *provctx) \ + char *ptr; \ + if (!ctx) \ + return NULL; \ ++ \ ++ ctx->data = OPENSSL_zalloc(DIGEST_BLOCK_SIZE); \ ++ if (!ctx->data) { \ ++ OPENSSL_free(ctx); \ ++ return NULL; \ ++ } \ ++ \ + ctx->blk_size = blksize; \ + ctx->md_size = mdsize; \ + ctx->e_nid = nid; \ +-- +2.25.1 + diff --git a/0014-uadk_provider-fix-the-ctx-copy-function-of-the-diges.patch b/0014-uadk_provider-fix-the-ctx-copy-function-of-the-diges.patch new file mode 100644 index 0000000..1059971 --- /dev/null +++ b/0014-uadk_provider-fix-the-ctx-copy-function-of-the-diges.patch @@ -0,0 +1,190 @@ +From 98bd0cdbac6149c748ed6a7add64cda2071b6565 Mon Sep 17 00:00:00 2001 +From: Chenghai Huang +Date: Fri, 24 Jan 2025 09:14:03 +0800 +Subject: [PATCH 14/19] uadk_provider: fix the ctx copy function of the digest + +After the ctx is copied, the data in the buffer of the ctx +needs to be copied to the new ctx. + +In addition, the value of total_data_len in the sess also needs +to be copied synchronously. The method is to change the NEXT +flag in the req to WD_DIGEST_XXX. The UADK will synchronizes +the long packet data to the new sess. + +Signed-off-by: Chenghai Huang +Signed-off-by: JiangShui Yang +--- + src/uadk_prov_digest.c | 84 ++++++++++++++++++++++++++++++++---------- + 1 file changed, 65 insertions(+), 19 deletions(-) + +diff --git a/src/uadk_prov_digest.c b/src/uadk_prov_digest.c +index 2e197b2..4b7d8c1 100644 +--- a/src/uadk_prov_digest.c ++++ b/src/uadk_prov_digest.c +@@ -98,6 +98,8 @@ struct digest_priv_ctx { + size_t md_size; + size_t blk_size; + char alg_name[ALG_NAME_SIZE]; ++ size_t total_data_len; ++ bool is_stream_copy; + }; + + struct digest_info { +@@ -358,24 +360,22 @@ soft_init: + return uadk_digest_soft_init(priv); + } + +-static void uadk_fill_mac_buffer_len(struct digest_priv_ctx *priv) ++static void uadk_fill_mac_buffer_len(struct digest_priv_ctx *priv, bool is_end) + { + /* Sha224 and Sha384 and Sha512-XXX need full length mac buffer as doing long hash */ + switch (priv->e_nid) { + case NID_sha224: +- priv->req.out_bytes = (priv->req.has_next == DIGEST_DOING) ? +- WD_DIGEST_SHA224_FULL_LEN : WD_DIGEST_SHA224_LEN; ++ priv->req.out_bytes = !is_end ? WD_DIGEST_SHA224_FULL_LEN : WD_DIGEST_SHA224_LEN; + break; + case NID_sha384: +- priv->req.out_bytes = (priv->req.has_next == DIGEST_DOING) ? +- WD_DIGEST_SHA384_FULL_LEN : WD_DIGEST_SHA384_LEN; ++ priv->req.out_bytes = !is_end ? WD_DIGEST_SHA384_FULL_LEN : WD_DIGEST_SHA384_LEN; + break; + case NID_sha512_224: +- priv->req.out_bytes = (priv->req.has_next == DIGEST_DOING) ? ++ priv->req.out_bytes = !is_end ? + WD_DIGEST_SHA512_224_FULL_LEN : WD_DIGEST_SHA512_224_LEN; + break; + case NID_sha512_256: +- priv->req.out_bytes = (priv->req.has_next == DIGEST_DOING) ? ++ priv->req.out_bytes = !is_end ? + WD_DIGEST_SHA512_256_FULL_LEN : WD_DIGEST_SHA512_256_LEN; + break; + default: +@@ -383,6 +383,16 @@ static void uadk_fill_mac_buffer_len(struct digest_priv_ctx *priv) + } + } + ++static void uadk_digest_set_msg_state(struct digest_priv_ctx *priv, bool is_end) ++{ ++ if (unlikely(priv->is_stream_copy)) { ++ priv->req.has_next = is_end ? WD_DIGEST_STREAM_END : WD_DIGEST_STREAM_DOING; ++ priv->is_stream_copy = false; ++ } else { ++ priv->req.has_next = is_end ? WD_DIGEST_END : WD_DIGEST_DOING; ++ } ++} ++ + static int uadk_digest_update_inner(struct digest_priv_ctx *priv, const void *data, size_t data_len) + { + unsigned char *input_data = (unsigned char *)data; +@@ -394,8 +404,8 @@ static int uadk_digest_update_inner(struct digest_priv_ctx *priv, const void *da + if (ret != UADK_DIGEST_SUCCESS) + return UADK_DIGEST_FAIL; + +- priv->req.has_next = DIGEST_DOING; +- uadk_fill_mac_buffer_len(priv); ++ uadk_digest_set_msg_state(priv, false); ++ uadk_fill_mac_buffer_len(priv, false); + + do { + /* +@@ -470,6 +480,8 @@ static int uadk_digest_update(struct digest_priv_ctx *priv, const void *data, si + if (unlikely(priv->switch_flag == UADK_DO_SOFT)) + goto soft_update; + ++ priv->total_data_len += data_len; ++ + if (priv->last_update_bufflen + data_len <= DIGEST_BLOCK_SIZE) { + uadk_memcpy(priv->data + priv->last_update_bufflen, data, data_len); + priv->last_update_bufflen += data_len; +@@ -576,12 +588,12 @@ static int uadk_digest_final(struct digest_priv_ctx *priv, unsigned char *digest + if (ret != UADK_DIGEST_SUCCESS) + return UADK_DIGEST_FAIL; + +- priv->req.has_next = DIGEST_END; + priv->req.in = priv->data; + priv->req.out = priv->out; + priv->req.in_bytes = priv->last_update_bufflen; + +- uadk_fill_mac_buffer_len(priv); ++ uadk_digest_set_msg_state(priv, true); ++ uadk_fill_mac_buffer_len(priv, true); + + ret = async_setup_async_event_notification(&op); + if (unlikely(!ret)) { +@@ -642,13 +654,13 @@ static int uadk_digest_digest(struct digest_priv_ctx *priv, const void *data, si + return UADK_DIGEST_FAIL; + } + +- priv->req.has_next = DIGEST_END; + priv->req.in = priv->data; + priv->req.out = priv->out; + priv->req.in_bytes = data_len; + uadk_memcpy(priv->data, data, data_len); + +- uadk_fill_mac_buffer_len(priv); ++ uadk_digest_set_msg_state(priv, true); ++ uadk_fill_mac_buffer_len(priv, true); + + if (op.job == NULL) + ret = uadk_do_digest_sync(priv); +@@ -739,16 +751,50 @@ static void uadk_prov_freectx(void *dctx) + + static void *uadk_prov_dupctx(void *dctx) + { +- struct digest_priv_ctx *in, *ret; ++ struct digest_priv_ctx *dst_ctx, *src_ctx; + ++ src_ctx = (struct digest_priv_ctx *)dctx; + if (!dctx) + return NULL; + +- in = (struct digest_priv_ctx *)dctx; +- ret = OPENSSL_malloc(sizeof(struct digest_priv_ctx)); +- if (ret) +- memcpy(ret, in, sizeof(struct digest_priv_ctx)); +- return ret; ++ dst_ctx = OPENSSL_memdup(src_ctx, sizeof(struct digest_priv_ctx)); ++ if (!dst_ctx) ++ return NULL; ++ ++ /* ++ * When a copy is performed during digest execution, ++ * the status in the sess needs to be synchronized. ++ */ ++ if (dst_ctx->sess && dst_ctx->state != SEC_DIGEST_INIT) { ++ dst_ctx->is_stream_copy = true; ++ /* ++ * Length that the hardware has processed should be equal to ++ * total input data length minus software cache data length. ++ */ ++ dst_ctx->req.long_data_len = dst_ctx->total_data_len ++ - dst_ctx->last_update_bufflen; ++ } ++ ++ dst_ctx->sess = 0; ++ dst_ctx->data = OPENSSL_memdup(src_ctx->data, DIGEST_BLOCK_SIZE); ++ if (!dst_ctx->data) ++ goto free_ctx; ++ ++ if (dst_ctx->soft_ctx) { ++ dst_ctx->soft_ctx = EVP_MD_CTX_new(); ++ if (!dst_ctx->soft_ctx) { ++ fprintf(stderr, "EVP_MD_CTX_new failed in ctx copy.\n"); ++ goto free_data; ++ } ++ } ++ ++ return dst_ctx; ++ ++free_data: ++ OPENSSL_clear_free(dst_ctx->data, DIGEST_BLOCK_SIZE); ++free_ctx: ++ OPENSSL_clear_free(dst_ctx, sizeof(*dst_ctx)); ++ return NULL; + } + + static int uadk_prov_init(void *dctx, const OSSL_PARAM params[]) +-- +2.25.1 + diff --git a/0015-uadk_provider-code-cleanup-for-digest-and-aead.patch b/0015-uadk_provider-code-cleanup-for-digest-and-aead.patch new file mode 100644 index 0000000..468fa90 --- /dev/null +++ b/0015-uadk_provider-code-cleanup-for-digest-and-aead.patch @@ -0,0 +1,183 @@ +From 70ac8271b5aab397ab729937f2aefe31c46f0793 Mon Sep 17 00:00:00 2001 +From: Chenghai Huang +Date: Tue, 18 Feb 2025 19:32:55 +0800 +Subject: [PATCH 15/19] uadk_provider: code cleanup for digest and aead +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +1.The input and output pointers of the digest_digest interface +can be directly used and do not need to be copied. +2. OPENSSL_clear_free can set pointer to zero and does not need +to be set to NULL. +3.Pointer type conversion is added to avoid compilation alarms +of inconsistent types. +4.Adjust the registration position of the digest function to +avoid compilation alarms: +note: previous definition of 'uadk_prov_freectx' was here +491 | static void uadk_prov_freectx(void *dctx) +| ^~~~~~~~~~~~~~~~~ +5.Add a NULL pointer checking for cipher freectx. + +Signed-off-by: Chenghai Huang +Signed-off-by: JiangShui Yang +--- + src/uadk_prov_aead.c | 19 ++++++++----------- + src/uadk_prov_cipher.c | 3 +++ + src/uadk_prov_digest.c | 35 +++++++++++++++-------------------- + 3 files changed, 26 insertions(+), 31 deletions(-) + +diff --git a/src/uadk_prov_aead.c b/src/uadk_prov_aead.c +index 9861519..1163328 100644 +--- a/src/uadk_prov_aead.c ++++ b/src/uadk_prov_aead.c +@@ -178,6 +178,7 @@ mutex_unlock: + + static int uadk_prov_aead_ctx_init(struct aead_priv_ctx *priv) + { ++ struct wd_aead_sess_setup setup = {0}; + struct sched_params params = {0}; + int ret; + +@@ -200,10 +201,12 @@ static int uadk_prov_aead_ctx_init(struct aead_priv_ctx *priv) + params.type = 0; + /* Use the default numa parameters */ + params.numa_id = -1; +- priv->setup.sched_param = ¶ms; ++ setup.sched_param = ¶ms; ++ setup.calg = priv->setup.calg; ++ setup.cmode = priv->setup.cmode; + + if (!priv->sess) { +- priv->sess = wd_aead_alloc_sess(&priv->setup); ++ priv->sess = wd_aead_alloc_sess(&setup); + if (!priv->sess) { + fprintf(stderr, "uadk failed to alloc session!\n"); + return UADK_AEAD_FAIL; +@@ -944,17 +947,11 @@ static void uadk_prov_aead_freectx(void *ctx) + if (!ctx) + return; + +- if (priv->sess) { ++ if (priv->sess) + wd_aead_free_sess(priv->sess); +- priv->sess = 0; +- } +- + +- if (priv->data) { ++ if (priv->data) + OPENSSL_clear_free(priv->data, AEAD_BLOCK_SIZE << 1); +- priv->data = NULL; +- } +- + + OPENSSL_clear_free(priv, sizeof(*priv)); + } +@@ -968,7 +965,7 @@ static void *uadk_##nm##_newctx(void *provctx) \ + if (!ctx) \ + return NULL; \ + \ +- ctx->data = OPENSSL_clear_free(ctx, sizeof(*ctx)); \ ++ ctx->data = OPENSSL_zalloc(AEAD_BLOCK_SIZE << 1); \ + if (!ctx->data) { \ + OPENSSL_free(ctx); \ + return NULL; \ +diff --git a/src/uadk_prov_cipher.c b/src/uadk_prov_cipher.c +index f4a182e..04a6489 100644 +--- a/src/uadk_prov_cipher.c ++++ b/src/uadk_prov_cipher.c +@@ -1265,6 +1265,9 @@ static void uadk_prov_cipher_freectx(void *ctx) + { + struct cipher_priv_ctx *priv = (struct cipher_priv_ctx *)ctx; + ++ if (ctx == NULL) ++ return; ++ + if (priv->sw_cipher) + EVP_CIPHER_free(priv->sw_cipher); + +diff --git a/src/uadk_prov_digest.c b/src/uadk_prov_digest.c +index 4b7d8c1..caac877 100644 +--- a/src/uadk_prov_digest.c ++++ b/src/uadk_prov_digest.c +@@ -639,7 +639,7 @@ static int uadk_digest_digest(struct digest_priv_ctx *priv, const void *data, si + struct async_op op; + int ret; + +- if (!priv->data) { ++ if (!data) { + fprintf(stderr, "failed to do single digest, data in CTX is NULL.\n"); + return UADK_DIGEST_FAIL; + } +@@ -654,11 +654,9 @@ static int uadk_digest_digest(struct digest_priv_ctx *priv, const void *data, si + return UADK_DIGEST_FAIL; + } + +- priv->req.in = priv->data; +- priv->req.out = priv->out; ++ priv->req.in = (void *)data; ++ priv->req.out = digest; + priv->req.in_bytes = data_len; +- uadk_memcpy(priv->data, data, data_len); +- + uadk_digest_set_msg_state(priv, true); + uadk_fill_mac_buffer_len(priv, true); + +@@ -672,25 +670,31 @@ static int uadk_digest_digest(struct digest_priv_ctx *priv, const void *data, si + async_clear_async_event_notification(); + return ret; + } +- memcpy(digest, priv->req.out, priv->req.out_bytes); + + return UADK_DIGEST_SUCCESS; + } + + static void uadk_digest_cleanup(struct digest_priv_ctx *priv) + { +- if (priv->sess) { ++ if (priv->sess) + wd_digest_free_sess(priv->sess); +- priv->sess = 0; +- } + + if (priv->data) +- OPENSSL_free(priv->data); ++ OPENSSL_clear_free(priv->data, DIGEST_BLOCK_SIZE); + + if (priv->soft_ctx) +- OPENSSL_free(priv->data); ++ OPENSSL_clear_free(priv->soft_ctx, sizeof(EVP_MD_CTX)); + } + ++static OSSL_FUNC_digest_freectx_fn uadk_prov_freectx; ++static OSSL_FUNC_digest_dupctx_fn uadk_prov_dupctx; ++static OSSL_FUNC_digest_init_fn uadk_prov_init; ++static OSSL_FUNC_digest_update_fn uadk_prov_update; ++static OSSL_FUNC_digest_final_fn uadk_prov_final; ++static OSSL_FUNC_digest_digest_fn uadk_prov_digest; ++static OSSL_FUNC_digest_gettable_params_fn ++ uadk_prov_gettable_params; ++ + /* some params related code is copied from OpenSSL v3.0 prov/digestcommon.h */ + static const OSSL_PARAM uadk_digest_default_known_gettable_params[] = { + OSSL_PARAM_size_t(OSSL_DIGEST_PARAM_BLOCK_SIZE, NULL), +@@ -896,15 +900,6 @@ void uadk_prov_destroy_digest(void) + pthread_mutex_unlock(&digest_mutex); + } + +-static OSSL_FUNC_digest_freectx_fn uadk_prov_freectx; +-static OSSL_FUNC_digest_dupctx_fn uadk_prov_dupctx; +-static OSSL_FUNC_digest_init_fn uadk_prov_init; +-static OSSL_FUNC_digest_update_fn uadk_prov_update; +-static OSSL_FUNC_digest_final_fn uadk_prov_final; +-static OSSL_FUNC_digest_digest_fn uadk_prov_digest; +-static OSSL_FUNC_digest_gettable_params_fn +- uadk_prov_gettable_params; +- + #define UADK_PROVIDER_IMPLEMENTATION(name, nid, mdsize, blksize) \ + static OSSL_FUNC_digest_newctx_fn uadk_##name##_newctx; \ + static void *uadk_##name##_newctx(void *provctx) \ +-- +2.25.1 + diff --git a/0016-uadk_engine_rsa-fix-memory-leak-of-pkey-meth.patch b/0016-uadk_engine_rsa-fix-memory-leak-of-pkey-meth.patch new file mode 100644 index 0000000..efe1eda --- /dev/null +++ b/0016-uadk_engine_rsa-fix-memory-leak-of-pkey-meth.patch @@ -0,0 +1,44 @@ +From 55db9e3df7e6a72b709e9ccd4071435047b3ed37 Mon Sep 17 00:00:00 2001 +From: Zhiqi Song +Date: Fri, 24 Jan 2025 09:14:03 +0800 +Subject: [PATCH 16/19] uadk_engine_rsa: fix memory leak of pkey meth + +The global pkey meth need to be released in destroy process. +Otherwise memory leakage occurs. + +Signed-off-by: Zhiqi Song +Signed-off-by: JiangShui Yang +--- + src/uadk_rsa.c | 9 +++++++++ + 1 file changed, 9 insertions(+) + +diff --git a/src/uadk_rsa.c b/src/uadk_rsa.c +index 81d633f..445b51b 100644 +--- a/src/uadk_rsa.c ++++ b/src/uadk_rsa.c +@@ -1938,6 +1938,14 @@ static EVP_PKEY_METHOD *uadk_rsa_get_pkey_meth(void) + return g_hpre_pkey_meth; + } + ++static void uadk_rsa_free_pkey_meth(EVP_PKEY_METHOD *pmeth) ++{ ++ if (g_hpre_pkey_meth) { ++ EVP_PKEY_meth_free(g_hpre_pkey_meth); ++ g_hpre_pkey_meth = NULL; ++ } ++} ++ + /** + * uadk_e_bind_rsa() - Set the access to get rsa methods to the ENGINE. + * @e: uadk engine +@@ -1951,6 +1959,7 @@ int uadk_e_bind_rsa(ENGINE *e) + void uadk_e_destroy_rsa(void) + { + pthread_spin_destroy(&g_rsa_res.lock); ++ uadk_rsa_free_pkey_meth(g_hpre_pkey_meth); + uadk_e_delete_rsa_meth(); + uadk_e_rsa_uninit(); + } +-- +2.25.1 + diff --git a/0017-uadk_engine-fix-memory-leak-in-fork-scene.patch b/0017-uadk_engine-fix-memory-leak-in-fork-scene.patch new file mode 100644 index 0000000..dc46298 --- /dev/null +++ b/0017-uadk_engine-fix-memory-leak-in-fork-scene.patch @@ -0,0 +1,60 @@ +From f3181440832c7df97265055df194931bb75d395a Mon Sep 17 00:00:00 2001 +From: Zhiqi Song +Date: Fri, 24 Jan 2025 09:14:03 +0800 +Subject: [PATCH 17/19] uadk_engine: fix memory leak in fork scene + +When enable 'dynamic_path' of uadk_engine in openssl.cnf, and execute +speed tool with '-multi' param, the uadk_engine will be bind and init +before fork() operation. The fork() operation will copy memory resources +from parent process and get a child process. + +As uadk_engine will register a function in child process with +pthread_atfork(), the child process will call the async_module_init() +and alloc new memory, the memory copied from parent process will leak. + +And in multi-engine and mulit-fork scenario, if resources have been +forked by other engines, and the uadk_engine performs the fork +operation and executes services at this time, the uadk_engine will +destroy the asynchronous resources from the fork in the subprocess. +If other engines are occupying the threads before the fork and do not end. +The pthread_join() in async_module_uninit() of the uadk_engine cannot wait +for the corresponding thread, and the entire service process is suspended. +The call stack when the program is suspended is as follows: + +Thread 2 (Thread 0xffff9b4ff0a0 (LWP 3242840) "openssl"): + 0 0x0000ffffa6423b00 in __futex_abstimed_wait_common64 + 1 __futex_abstimed_wait_common + 2 __GI___futex_abstimed_wait_cancelable64 + 3 0x0000ffffa642f3e4 in do_futex_wait + 4 0x0000ffffa642f4ac in __new_sem_wait_slow64 + 5 0x0000ffffa30a2170 in async_poll_process_func + 6 0x0000ffffa64272f8 in start_thread + 7 0x0000ffffa648ea1c in thread_start () + +To solve this, call uninit operation before creating subprocess to +prevent resource leakage after the fork subprocess and ensure that the +uadk_engine service can exit normally in multi-engine and multi-fork +scenarios. + +Signed-off-by: Zhiqi Song +Signed-off-by: JiangShui Yang +--- + src/uadk_engine_init.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/src/uadk_engine_init.c b/src/uadk_engine_init.c +index bba382f..1a2b1d4 100644 +--- a/src/uadk_engine_init.c ++++ b/src/uadk_engine_init.c +@@ -417,7 +417,7 @@ static int bind_fn(ENGINE *e, const char *id) + bind_fn_uadk_alg(e); + + if (uadk_cipher || uadk_digest || uadk_rsa || uadk_dh || uadk_ecc) +- pthread_atfork(NULL, NULL, engine_init_child_at_fork_handler); ++ pthread_atfork(async_module_uninit, NULL, engine_init_child_at_fork_handler); + + ret = ENGINE_set_ctrl_function(e, uadk_engine_ctrl); + if (ret != 1) { +-- +2.25.1 + diff --git a/0018-uadk_provider-support-X25519.patch b/0018-uadk_provider-support-X25519.patch new file mode 100644 index 0000000..eb239cd --- /dev/null +++ b/0018-uadk_provider-support-X25519.patch @@ -0,0 +1,904 @@ +From 23ec02c5d6ba821cdd6382cc54df399ff1976679 Mon Sep 17 00:00:00 2001 +From: Zhiqi Song +Date: Fri, 24 Jan 2025 09:14:03 +0800 +Subject: [PATCH 18/19] uadk_provider: support X25519 + +openssl genpkey -provider uadk_provider -algorithm X25519 \ + -out a_prikey_x25519.pem +openssl pkey -in a_prikey_x25519.pem -text +openssl pkey -in a_prikey_x25519.pem -pubout -out a_pubkey_x25519.pub +openssl genpkey -provider uadk_provider -algorithm x25519 \ + -out b_prikey_x25519.pem +openssl pkey -in b_prikey_x25519.pem -text +openssl pkey -in b_prikey_x25519.pem -pubout -out b_pubkey_x25519.pub +openssl pkeyutl -derive -out ab_x25519.key -inkey a_prikey_x25519.pem \ + -peerkey b_pubkey_x25519.pub -provider uadk_provider +openssl pkeyutl -derive -out ba_x25519.key -inkey b_prikey_x25519.pem \ + -peerkey a_pubkey_x25519.pub -provider uadk_provider + +cmp ab_x25519.key ba_x25519.key +xxd ab_x25519.key +xxd ba_x25519.key + +Signed-off-by: Zhiqi Song +Signed-off-by: JiangShui Yang +--- + src/uadk_prov.h | 3 + + src/uadk_prov_ecx.c | 517 +++++++++++++++++++++++++++++++++++++++---- + src/uadk_prov_init.c | 4 + + src/uadk_prov_pkey.c | 26 +-- + src/uadk_prov_pkey.h | 2 + + 5 files changed, 494 insertions(+), 58 deletions(-) + +diff --git a/src/uadk_prov.h b/src/uadk_prov.h +index 2786e79..7cb1eee 100644 +--- a/src/uadk_prov.h ++++ b/src/uadk_prov.h +@@ -185,6 +185,9 @@ extern const OSSL_DISPATCH uadk_ecdh_keyexch_functions[FUNC_MAX_NUM]; + extern const OSSL_DISPATCH uadk_x448_keymgmt_functions[FUNC_MAX_NUM]; + extern const OSSL_DISPATCH uadk_x448_keyexch_functions[FUNC_MAX_NUM]; + ++extern const OSSL_DISPATCH uadk_x25519_keymgmt_functions[FUNC_MAX_NUM]; ++extern const OSSL_DISPATCH uadk_x25519_keyexch_functions[FUNC_MAX_NUM]; ++ + extern const OSSL_DISPATCH uadk_ecdsa_signature_functions[FUNC_MAX_NUM]; + + void uadk_prov_destroy_digest(void); +diff --git a/src/uadk_prov_ecx.c b/src/uadk_prov_ecx.c +index d7954b7..47fe1a9 100644 +--- a/src/uadk_prov_ecx.c ++++ b/src/uadk_prov_ecx.c +@@ -34,6 +34,9 @@ + #define X448_KEYBITS 448 + #define ECX_MAX_KEYLEN 57 + #define X448_SECURITY_BITS 224 ++#define X25519_KEYBITS 256 ++#define X25519_KEYLEN 32 ++#define X25519_SECURITY_BITS 128 + + #define ECX_POSSIBLE_SELECTIONS (OSSL_KEYMGMT_SELECT_KEYPAIR) + +@@ -50,6 +53,11 @@ static inline int UADK_CRYPTO_DOWN_REF(int *val, int *ret, + + UADK_PKEY_KEYMGMT_DESCR(x448, X448); + UADK_PKEY_KEYEXCH_DESCR(x448, X448); ++UADK_PKEY_KEYMGMT_DESCR(x25519, X25519); ++UADK_PKEY_KEYEXCH_DESCR(x25519, X25519); ++ ++static pthread_mutex_t x25519_mutex = PTHREAD_MUTEX_INITIALIZER; ++static pthread_mutex_t x448_mutex = PTHREAD_MUTEX_INITIALIZER; + + typedef enum { + ECX_KEY_TYPE_X25519 = 0x0, +@@ -349,20 +357,26 @@ static int ossl_ecx_gen_set_params(void *genctx, const OSSL_PARAM params[]) + return UADK_P_SUCCESS; + } + +-static handle_t uadk_prov_x448_alloc_sess(void) ++static handle_t uadk_prov_ecx_alloc_sess(int type) + { + struct wd_ecc_sess_setup setup = {0}; + struct sched_params params = {0}; + +- setup.alg = "x448"; +- setup.key_bits = X448_KEYBITS; ++ if (type == ECX_KEY_TYPE_X448) { ++ setup.alg = "x448"; ++ setup.key_bits = X448_KEYBITS; ++ } else { ++ setup.alg = "x25519"; ++ setup.key_bits = X25519_KEYBITS; ++ } ++ + params.numa_id = -1; + setup.sched_param = ¶ms; + + return wd_ecc_alloc_sess(&setup); + } + +-static void uadk_prov_x448_free_sess(handle_t sess) ++static void uadk_prov_ecx_free_sess(handle_t sess) + { + if (sess) + wd_ecc_free_sess(sess); +@@ -431,14 +445,18 @@ static ECX_KEY *uadk_prov_ecx_key_new(OSSL_LIB_CTX *libctx, ECX_KEY_TYPE type, i + switch (type) { + case ECX_KEY_TYPE_X448: + ecx_key->keylen = X448_KEYLEN; +- ecx_key->type = type; +- ecx_key->references = 1; ++ break; ++ case ECX_KEY_TYPE_X25519: ++ ecx_key->keylen = X25519_KEYLEN; + break; + default: + fprintf(stderr, "invalid: unsupported ecx type\n"); + goto free_ecx_key; + } + ++ ecx_key->type = type; ++ ecx_key->references = 1; ++ + if (propq) { + ecx_key->propq = OPENSSL_strdup(propq); + if (ecx_key->propq == NULL) +@@ -493,7 +511,11 @@ static ECX_KEY *uadk_prov_ecx_create_prikey(PROV_ECX_KEYMGMT_CTX *gctx) + fprintf(stderr, "failed to new ecx_key\n"); + return UADK_P_FAIL; + } +- gctx->keylen = X448_KEYLEN; ++ ++ if (gctx->type == ECX_KEY_TYPE_X448) ++ gctx->keylen = X448_KEYLEN; ++ else ++ gctx->keylen = X25519_KEYLEN; + + /* If we're doing parameter generation then we just return a blank key */ + if ((gctx->selection & OSSL_KEYMGMT_SELECT_KEYPAIR) == 0) +@@ -637,7 +659,7 @@ static int uadk_prov_ecx_set_pkey(PROV_ECX_KEYMGMT_CTX *gctx, struct wd_ecc_req + return ret; + } + /* +- * This is a pretreatment of X448 described in RFC 7748. ++ * This is a pretreatment of X448 and X25519 described in RFC 7748. + * In order to decode the random bytes as an integer scaler, there + * are some special data processing. And use little-endian mode for + * decoding. +@@ -648,6 +670,14 @@ static int uadk_prov_ecx_set_pkey(PROV_ECX_KEYMGMT_CTX *gctx, struct wd_ecc_req + + /* Set the MSB of the last byte to 1 */ + ecx_key->privkey[X448_KEYLEN - 1] |= 0x80; ++ } else if (gctx->type == ECX_KEY_TYPE_X25519) { ++ ecx_key->privkey[0] &= 0xF8; ++ ++ /* Set the MSB of the last byte to 0 */ ++ ecx_key->privkey[X25519_KEYLEN - 1] &= 0x7F; ++ ++ /* Set the second MSB of the last byte to 1 */ ++ ecx_key->privkey[X25519_KEYLEN - 1] |= 0x40; + } else { + fprintf(stderr, "invalid: unsupported ecx type\n"); + return UADK_P_FAIL; +@@ -744,7 +774,7 @@ static void *uadk_keymgmt_x448_gen(void *genctx, OSSL_CALLBACK *cb, void *cb_par + return NULL; + } + +- gctx->sess = uadk_prov_x448_alloc_sess(); ++ gctx->sess = uadk_prov_ecx_alloc_sess(ECX_KEY_TYPE_X448); + if (gctx->sess == (handle_t)0) { + fprintf(stderr, "failed to alloc x448 sess\n"); + return NULL; +@@ -754,7 +784,7 @@ static void *uadk_keymgmt_x448_gen(void *genctx, OSSL_CALLBACK *cb, void *cb_par + if (ecx_key == NULL) + fprintf(stderr, "failed to generate x448 key\n"); + +- uadk_prov_x448_free_sess(gctx->sess); ++ uadk_prov_ecx_free_sess(gctx->sess); + + return ecx_key; + } +@@ -764,6 +794,7 @@ static UADK_PKEY_KEYEXCH get_default_x448_keyexch(void) + static UADK_PKEY_KEYEXCH s_keyexch; + static int initilazed; + ++ pthread_mutex_lock(&x448_mutex); + if (!initilazed) { + UADK_PKEY_KEYEXCH *keyexch = + (UADK_PKEY_KEYEXCH *)EVP_KEYEXCH_fetch(NULL, "X448", "provider=default"); +@@ -775,6 +806,8 @@ static UADK_PKEY_KEYEXCH get_default_x448_keyexch(void) + fprintf(stderr, "failed to EVP_KEYEXCH_fetch default X448 provider\n"); + } + } ++ pthread_mutex_unlock(&x448_mutex); ++ + return s_keyexch; + } + +@@ -838,7 +871,7 @@ static int uadk_keyexch_x448_get_ctx_params(void *ecxctx, OSSL_PARAM params[]) + return get_default_x448_keyexch().get_ctx_params(ecxctx, params); + } + +-static int uadk_keyexch_x448_init(void *vecxctx, void *vkey, ++static int uadk_keyexch_ecx_init(void *vecxctx, void *vkey, + ossl_unused const OSSL_PARAM params[]) + { + PROV_ECX_KEYEXCH_CTX *ecxctx = (PROV_ECX_KEYEXCH_CTX *)vecxctx; +@@ -866,6 +899,12 @@ static int uadk_keyexch_x448_init(void *vecxctx, void *vkey, + return UADK_P_SUCCESS; + } + ++static int uadk_keyexch_x448_init(void *vecxctx, void *vkey, ++ ossl_unused const OSSL_PARAM params[]) ++{ ++ return uadk_keyexch_ecx_init(vecxctx, vkey, params); ++} ++ + static int ossl_ecx_key_up_ref(ECX_KEY *key) + { + int i = 0; +@@ -876,33 +915,38 @@ static int ossl_ecx_key_up_ref(ECX_KEY *key) + return ((i > 1) ? UADK_P_SUCCESS : UADK_P_FAIL); + } + +-static int uadk_keyexch_x448_set_peer(void *vecxctx, void *vkey) ++static int uadk_keyexch_ecx_set_peer(void *vecxctx, void *vkey) + { + PROV_ECX_KEYEXCH_CTX *ecxctx = (PROV_ECX_KEYEXCH_CTX *)vecxctx; +- ECX_KEY *key = vkey; ++ ECX_KEY *peerkey = vkey; + + if (ecxctx == NULL) { + fprintf(stderr, "invalid: ecxctx is NULL\n"); + return UADK_P_FAIL; + } + +- if (key == NULL) { ++ if (peerkey == NULL) { + fprintf(stderr, "invalid: key is NULL\n"); + return UADK_P_FAIL; + } + +- if (key->keylen != ecxctx->keylen || !ossl_ecx_key_up_ref(key)) { +- fprintf(stderr, "invalid: key->keylen(%zu) != ecxctx->keylen(%zu)\n", +- key->keylen, ecxctx->keylen); ++ if (peerkey->keylen != ecxctx->keylen || !ossl_ecx_key_up_ref(peerkey)) { ++ fprintf(stderr, "invalid: peerkey->keylen(%zu) != ecxctx->keylen(%zu)\n", ++ peerkey->keylen, ecxctx->keylen); + return UADK_P_FAIL; + } + + uadk_prov_ecx_key_free(ecxctx->peerkey); +- ecxctx->peerkey = key; ++ ecxctx->peerkey = peerkey; + + return UADK_P_SUCCESS; + } + ++static int uadk_keyexch_x448_set_peer(void *vecxctx, void *vkey) ++{ ++ return uadk_keyexch_ecx_set_peer(vecxctx, vkey); ++} ++ + static int uadk_prov_ecx_compkey_init_iot(PROV_ECX_KEYEXCH_CTX *ecxctx, struct wd_ecc_req *req) + { + char buffer_y[ECX_MAX_KEYLEN] = {0}; +@@ -934,7 +978,7 @@ static int uadk_prov_ecx_compkey_init_iot(PROV_ECX_KEYEXCH_CTX *ecxctx, struct w + if (ecx_out == NULL) { + fprintf(stderr, "failed to new ecxdh out\n"); + ret = UADK_P_FAIL; +- goto del_in; ++ goto del_ecx_in; + } + + uadk_prov_ecc_fill_req(req, WD_ECXDH_COMPUTE_KEY, ecx_in, ecx_out); +@@ -942,15 +986,15 @@ static int uadk_prov_ecx_compkey_init_iot(PROV_ECX_KEYEXCH_CTX *ecxctx, struct w + /* Trans public key from big-endian to little-endian */ + ret = uadk_prov_reverse_bytes(ecxctx->peerkey->pubkey, ecxctx->keylen); + if (ret == UADK_P_FAIL) { +- fprintf(stderr, "failed to trans public key\n"); +- goto del_out; ++ fprintf(stderr, "failed to trans peer public key\n"); ++ goto del_ecx_out; + } + + return ret; + +-del_out: ++del_ecx_out: + wd_ecc_del_out(sess, ecx_out); +-del_in: ++del_ecx_in: + wd_ecc_del_in(sess, ecx_in); + + return ret; +@@ -995,25 +1039,31 @@ static int uadk_prov_ecx_derive_set_prikey(PROV_ECX_KEYEXCH_CTX *ecxctx) + return UADK_P_SUCCESS; + } + +-static void uadk_prov_x448_pad_out_key(unsigned char *dst_key, unsigned char *src_key, +- size_t len) ++static void uadk_prov_ecx_pad_out_key(unsigned char *dst, unsigned char *src, ++ size_t len, int type) + { + unsigned char x448_pad_key[X448_KEYLEN] = {0}; ++ unsigned char x25519_pad_key[X25519_KEYLEN] = {0}; + +- if (len != X448_KEYLEN) { +- memcpy(x448_pad_key, src_key, len); +- memcpy(dst_key, x448_pad_key, X448_KEYLEN); +- } else { +- memcpy(dst_key, src_key, X448_KEYLEN); +- } +-} +- +-static void uadk_prov_ecx_pad_out_key(unsigned char *dst_key, unsigned char *src_key, +- size_t len, int type) +-{ +- if (type == ECX_KEY_TYPE_X448) { +- uadk_prov_x448_pad_out_key(dst_key, src_key, len); +- return; ++ switch (type) { ++ case ECX_KEY_TYPE_X448: ++ if (len != X448_KEYLEN) { ++ memcpy(x448_pad_key, src, len); ++ memcpy(dst, x448_pad_key, X448_KEYLEN); ++ } else { ++ memcpy(dst, src, X448_KEYLEN); ++ } ++ break; ++ case ECX_KEY_TYPE_X25519: ++ if (len != X25519_KEYLEN) { ++ memcpy(x25519_pad_key, src, len); ++ memcpy(dst, x25519_pad_key, X25519_KEYLEN); ++ } else { ++ memcpy(dst, src, X25519_KEYLEN); ++ } ++ break; ++ default: ++ break; + } + } + +@@ -1078,12 +1128,11 @@ static int uadk_keyexch_x448_derive(void *vecxctx, unsigned char *secret, size_t + int ret; + + if (ecxctx == NULL) { +- fprintf(stderr, "invalid: ecxctx is NULL in derive op\n"); ++ fprintf(stderr, "invalid: ecxctx is NULL in x448 derive op\n"); + return UADK_P_FAIL; + } + +- if (ecxctx->key == NULL || ecxctx->key->privkey == NULL || +- ecxctx->peerkey == NULL) { ++ if (ecxctx->key == NULL || ecxctx->key->privkey == NULL || ecxctx->peerkey == NULL) { + ERR_raise(ERR_LIB_PROV, PROV_R_MISSING_KEY); + return UADK_P_FAIL; + } +@@ -1115,7 +1164,7 @@ static int uadk_keyexch_x448_derive(void *vecxctx, unsigned char *secret, size_t + return UADK_P_FAIL; + } + +- ecxctx->sess = uadk_prov_x448_alloc_sess(); ++ ecxctx->sess = uadk_prov_ecx_alloc_sess(ECX_KEY_TYPE_X448); + if (ecxctx->sess == (handle_t)0) { + fprintf(stderr, "failed to alloc sess\n"); + return UADK_P_FAIL; +@@ -1127,12 +1176,12 @@ static int uadk_keyexch_x448_derive(void *vecxctx, unsigned char *secret, size_t + + *secretlen = ecxctx->keylen; + +- uadk_prov_x448_free_sess(ecxctx->sess); ++ uadk_prov_ecx_free_sess(ecxctx->sess); + + return ret; + } + +-static void *uadk_keyexch_x448_dupctx(void *vecxctx) ++static void *uadk_keyexch_ecx_dupctx(void *vecxctx) + { + PROV_ECX_KEYEXCH_CTX *srcctx = (PROV_ECX_KEYEXCH_CTX *)vecxctx; + PROV_ECX_KEYEXCH_CTX *dstctx; +@@ -1162,3 +1211,381 @@ static void *uadk_keyexch_x448_dupctx(void *vecxctx) + + return dstctx; + } ++ ++static void *uadk_keyexch_x448_dupctx(void *vecxctx) ++{ ++ return uadk_keyexch_ecx_dupctx(vecxctx); ++} ++ ++static void *uadk_keymgmt_x25519_new(void *provctx) ++{ ++ if (get_default_x25519_keymgmt().new_fun == NULL) ++ return NULL; ++ ++ return get_default_x25519_keymgmt().new_fun(provctx); ++} ++ ++void uadk_keymgmt_x25519_free(void *keydata) ++{ ++ if (get_default_x25519_keymgmt().free == NULL) ++ return; ++ ++ get_default_x25519_keymgmt().free(keydata); ++} ++ ++static int uadk_keymgmt_x25519_has(const void *keydata, int selection) ++{ ++ if (get_default_x25519_keymgmt().has == NULL) ++ return UADK_P_FAIL; ++ ++ return get_default_x25519_keymgmt().has(keydata, selection); ++} ++ ++static int uadk_keymgmt_x25519_match(const void *keydata1, const void *keydata2, int selection) ++{ ++ if (get_default_x25519_keymgmt().match == NULL) ++ return UADK_P_FAIL; ++ ++ return get_default_x25519_keymgmt().match(keydata1, keydata2, selection); ++} ++ ++static int uadk_keymgmt_x25519_import(void *keydata, int selection, const OSSL_PARAM params[]) ++{ ++ if (get_default_x25519_keymgmt().import == NULL) ++ return UADK_P_FAIL; ++ ++ return get_default_x25519_keymgmt().import(keydata, selection, params); ++} ++ ++static int uadk_keymgmt_x25519_export(void *keydata, int selection, ++ OSSL_CALLBACK *cb, void *cb_params) ++{ ++ if (get_default_x25519_keymgmt().export_fun == NULL) ++ return UADK_P_FAIL; ++ ++ return get_default_x25519_keymgmt().export_fun(keydata, selection, cb, cb_params); ++} ++ ++static const OSSL_PARAM *uadk_keymgmt_x25519_import_types(int selection) ++{ ++ if (get_default_x25519_keymgmt().import_types == NULL) ++ return NULL; ++ ++ return get_default_x25519_keymgmt().import_types(selection); ++} ++ ++static const OSSL_PARAM *uadk_keymgmt_x25519_export_types(int selection) ++{ ++ if (get_default_x25519_keymgmt().export_types == NULL) ++ return NULL; ++ ++ return get_default_x25519_keymgmt().export_types(selection); ++} ++ ++void *uadk_keymgmt_x25519_load(const void *reference, size_t reference_sz) ++{ ++ if (get_default_x25519_keymgmt().load == NULL) ++ return NULL; ++ ++ return get_default_x25519_keymgmt().load(reference, reference_sz); ++} ++ ++static void *uadk_keymgmt_x25519_dup(const void *keydata_from, int selection) ++{ ++ if (get_default_x25519_keymgmt().dup == NULL) ++ return NULL; ++ ++ return get_default_x25519_keymgmt().dup(keydata_from, selection); ++} ++ ++static int uadk_keymgmt_x25519_validate(const void *keydata, int selection, int checktype) ++{ ++ if (get_default_x25519_keymgmt().validate == NULL) ++ return UADK_P_FAIL; ++ ++ return get_default_x25519_keymgmt().validate(keydata, selection, checktype); ++} ++ ++static const OSSL_PARAM *uadk_keymgmt_x25519_gettable_params(void *provctx) ++{ ++ if (get_default_x25519_keymgmt().gettable_params == NULL) ++ return NULL; ++ ++ return get_default_x25519_keymgmt().gettable_params(provctx); ++} ++ ++static int uadk_keymgmt_x25519_set_params(void *key, const OSSL_PARAM params[]) ++{ ++ if (get_default_x25519_keymgmt().set_params == NULL) ++ return UADK_P_FAIL; ++ ++ return get_default_x25519_keymgmt().set_params(key, params); ++} ++ ++static const OSSL_PARAM *uadk_keymgmt_x25519_settable_params(void *provctx) ++{ ++ if (get_default_x25519_keymgmt().settable_params == NULL) ++ return NULL; ++ ++ return get_default_x25519_keymgmt().settable_params(provctx); ++} ++ ++static int uadk_keymgmt_x25519_gen_set_params(void *genctx, ++ const OSSL_PARAM params[]) ++{ ++ if (get_default_x25519_keymgmt().gen_set_params == NULL) ++ return UADK_P_FAIL; ++ ++ return get_default_x25519_keymgmt().gen_set_params(genctx, params); ++} ++ ++static const OSSL_PARAM *uadk_keymgmt_x25519_gen_settable_params(ossl_unused void *genctx, ++ ossl_unused void *provctx) ++{ ++ if (get_default_x25519_keymgmt().gen_settable_params == NULL) ++ return NULL; ++ ++ return get_default_x25519_keymgmt().gen_settable_params(genctx, provctx); ++} ++ ++static int uadk_keymgmt_x25519_gen_set_template(void *genctx, void *templ) ++{ ++ if (get_default_x25519_keymgmt().gen_set_template == NULL) ++ return UADK_P_FAIL; ++ ++ return get_default_x25519_keymgmt().gen_set_template(genctx, templ); ++} ++ ++static const char *uadk_keymgmt_x25519_query_operation_name(int operation_id) ++{ ++ if (get_default_x25519_keymgmt().query_operation_name == NULL) ++ return NULL; ++ ++ return get_default_x25519_keymgmt().query_operation_name(operation_id); ++} ++ ++static int uadk_keymgmt_x25519_get_params(void *key, OSSL_PARAM params[]) ++{ ++ return uadk_prov_ecx_get_params(key, params, X25519_KEYBITS, X25519_SECURITY_BITS, ++ X25519_KEYLEN); ++} ++ ++static void uadk_keymgmt_x25519_gen_cleanup(void *genctx) ++{ ++ /* genctx will be freed in cleanup function */ ++ if (get_default_x25519_keymgmt().gen_cleanup == NULL) ++ return; ++ ++ get_default_x25519_keymgmt().gen_cleanup(genctx); ++} ++ ++static void *uadk_keymgmt_x25519_gen_init(void *provctx, int selection, ++ const OSSL_PARAM params[]) ++{ ++ if (provctx == NULL) { ++ fprintf(stderr, "invalid: provctx is NULL\n"); ++ return NULL; ++ } ++ ++ return ossl_ecx_gen_init(provctx, selection, params, ECX_KEY_TYPE_X25519); ++} ++ ++static void *uadk_keymgmt_x25519_gen(void *genctx, OSSL_CALLBACK *cb, void *cb_params) ++{ ++ PROV_ECX_KEYMGMT_CTX *gctx = (PROV_ECX_KEYMGMT_CTX *)genctx; ++ ECX_KEY *ecx_key = NULL; ++ int ret; ++ ++ if (gctx == NULL) { ++ fprintf(stderr, "invalid: ecx keygen ctx is NULL\n"); ++ return NULL; ++ } ++ ++ if (gctx->type != ECX_KEY_TYPE_X25519) { ++ fprintf(stderr, "invalid: unsupported ecx type\n"); ++ return NULL; ++ } ++ ++ ret = uadk_prov_keymgmt_get_support_state(KEYMGMT_X25519); ++ if (ret == UADK_P_FAIL) { ++ fprintf(stderr, "failed to get hardware x25519 keygen support\n"); ++ return NULL; ++ } ++ ++ ret = uadk_prov_ecc_init("x25519"); ++ if (ret != UADK_P_SUCCESS) { ++ fprintf(stderr, "failed to init x25519\n"); ++ return NULL; ++ } ++ ++ gctx->sess = uadk_prov_ecx_alloc_sess(ECX_KEY_TYPE_X25519); ++ if (gctx->sess == (handle_t)0) { ++ fprintf(stderr, "failed to alloc x25519 sess\n"); ++ return NULL; ++ } ++ ++ ecx_key = uadk_prov_ecx_keygen(gctx); ++ if (ecx_key == NULL) ++ fprintf(stderr, "failed to generate x25519 key\n"); ++ ++ uadk_prov_ecx_free_sess(gctx->sess); ++ ++ return ecx_key; ++} ++ ++static UADK_PKEY_KEYEXCH get_default_x25519_keyexch(void) ++{ ++ static UADK_PKEY_KEYEXCH s_keyexch; ++ static int initilazed; ++ ++ pthread_mutex_lock(&x25519_mutex); ++ if (!initilazed) { ++ UADK_PKEY_KEYEXCH *keyexch = ++ (UADK_PKEY_KEYEXCH *)EVP_KEYEXCH_fetch(NULL, "X25519", "provider=default"); ++ if (keyexch) { ++ s_keyexch = *keyexch; ++ EVP_KEYEXCH_free((EVP_KEYEXCH *)keyexch); ++ initilazed = 1; ++ } else { ++ fprintf(stderr, "failed to EVP_KEYEXCH_fetch default X25519 provider\n"); ++ } ++ } ++ pthread_mutex_unlock(&x25519_mutex); ++ ++ return s_keyexch; ++} ++ ++static void *uadk_keyexch_x25519_newctx(void *provctx) ++{ ++ PROV_ECX_KEYEXCH_CTX *ecxctx = NULL; ++ ++ ecxctx = OPENSSL_zalloc(sizeof(PROV_ECX_KEYEXCH_CTX)); ++ if (ecxctx == NULL) { ++ ERR_raise(ERR_LIB_PROV, ERR_R_MALLOC_FAILURE); ++ return NULL; ++ } ++ ++ ecxctx->keylen = X25519_KEYLEN; ++ ++ return ecxctx; ++} ++ ++static void uadk_keyexch_x25519_freectx(void *vecxctx) ++{ ++ PROV_ECX_KEYEXCH_CTX *ecxctx = (PROV_ECX_KEYEXCH_CTX *)vecxctx; ++ ++ if (ecxctx == NULL) ++ return; ++ ++ OPENSSL_free(ecxctx); ++} ++ ++static int uadk_keyexch_x25519_set_ctx_params(void *ecxctx, const OSSL_PARAM params[]) ++{ ++ if (get_default_x25519_keyexch().set_ctx_params == NULL) ++ return UADK_P_FAIL; ++ ++ return get_default_x25519_keyexch().set_ctx_params(ecxctx, params); ++} ++ ++static const OSSL_PARAM *uadk_keyexch_x25519_settable_ctx_params(ossl_unused void *ecxctx, ++ ossl_unused void *provctx) ++{ ++ if (get_default_x25519_keyexch().settable_ctx_params == NULL) ++ return NULL; ++ ++ return get_default_x25519_keyexch().settable_ctx_params(ecxctx, provctx); ++} ++ ++static const OSSL_PARAM *uadk_keyexch_x25519_gettable_ctx_params(ossl_unused void *ecxctx, ++ ossl_unused void *provctx) ++{ ++ if (get_default_x25519_keyexch().gettable_ctx_params == NULL) ++ return NULL; ++ ++ return get_default_x25519_keyexch().gettable_ctx_params(ecxctx, provctx); ++} ++ ++static int uadk_keyexch_x25519_get_ctx_params(void *ecxctx, OSSL_PARAM params[]) ++{ ++ if (get_default_x25519_keyexch().get_ctx_params == NULL) ++ return UADK_P_FAIL; ++ ++ return get_default_x25519_keyexch().get_ctx_params(ecxctx, params); ++} ++ ++static int uadk_keyexch_x25519_init(void *vecxctx, void *vkey, ++ ossl_unused const OSSL_PARAM params[]) ++{ ++ return uadk_keyexch_ecx_init(vecxctx, vkey, params); ++} ++ ++static int uadk_keyexch_x25519_set_peer(void *vecxctx, void *vkey) ++{ ++ return uadk_keyexch_ecx_set_peer(vecxctx, vkey); ++} ++ ++static int uadk_keyexch_x25519_derive(void *vecxctx, unsigned char *secret, size_t *secretlen, ++ size_t outlen) ++{ ++ PROV_ECX_KEYEXCH_CTX *ecxctx = (PROV_ECX_KEYEXCH_CTX *)vecxctx; ++ int ret; ++ ++ if (ecxctx == NULL) { ++ fprintf(stderr, "invalid: ecxctx is NULL in x25519 derive op\n"); ++ return UADK_P_FAIL; ++ } ++ ++ if (ecxctx->key == NULL || ecxctx->key->privkey == NULL || ecxctx->peerkey == NULL) { ++ ERR_raise(ERR_LIB_PROV, PROV_R_MISSING_KEY); ++ return UADK_P_FAIL; ++ } ++ ++ if (ecxctx->keylen != X25519_KEYLEN) { ++ ERR_raise(ERR_LIB_PROV, PROV_R_INVALID_KEY_LENGTH); ++ return UADK_P_FAIL; ++ } ++ ++ if (secret == NULL) { ++ *secretlen = ecxctx->keylen; ++ return UADK_P_SUCCESS; ++ } ++ ++ if (outlen < ecxctx->keylen) { ++ ERR_raise(ERR_LIB_PROV, PROV_R_OUTPUT_BUFFER_TOO_SMALL); ++ return UADK_P_FAIL; ++ } ++ ++ ret = uadk_prov_keyexch_get_support_state(KEYEXCH_X25519); ++ if (ret == UADK_P_FAIL) { ++ fprintf(stderr, "failed to get hardware x25519 keyexch support\n"); ++ return UADK_P_FAIL; ++ } ++ ++ ret = uadk_prov_ecc_init("x25519"); ++ if (ret != UADK_P_SUCCESS) { ++ fprintf(stderr, "failed to init x25519\n"); ++ return UADK_P_FAIL; ++ } ++ ++ ecxctx->sess = uadk_prov_ecx_alloc_sess(ECX_KEY_TYPE_X25519); ++ if (ecxctx->sess == (handle_t)0) { ++ fprintf(stderr, "failed to alloc sess\n"); ++ return UADK_P_FAIL; ++ } ++ ++ ret = uadk_prov_ecx_derive(ecxctx, secret, &ecxctx->keylen); ++ if (ret == UADK_P_FAIL) ++ fprintf(stderr, "failed to do x25519 derive\n"); ++ ++ *secretlen = ecxctx->keylen; ++ ++ uadk_prov_ecx_free_sess(ecxctx->sess); ++ ++ return ret; ++} ++ ++static void *uadk_keyexch_x25519_dupctx(void *vecxctx) ++{ ++ return uadk_keyexch_ecx_dupctx(vecxctx); ++} +diff --git a/src/uadk_prov_init.c b/src/uadk_prov_init.c +index 41733b5..a6012ab 100644 +--- a/src/uadk_prov_init.c ++++ b/src/uadk_prov_init.c +@@ -181,6 +181,8 @@ static const OSSL_ALGORITHM uadk_prov_keymgmt[] = { + uadk_ec_keymgmt_functions, "uadk EC Keymgmt implementation."}, + { "X448", UADK_DEFAULT_PROPERTIES, + uadk_x448_keymgmt_functions, "uadk X448 Keymgmt implementation."}, ++ { "X25519", UADK_DEFAULT_PROPERTIES, ++ uadk_x25519_keymgmt_functions, "uadk X25519 Keymgmt implementation."}, + { NULL, NULL, NULL } + }; + +@@ -199,6 +201,8 @@ static const OSSL_ALGORITHM uadk_prov_keyexch[] = { + uadk_ecdh_keyexch_functions, "uadk_provider ecdh_keyexch" }, + { "X448", UADK_DEFAULT_PROPERTIES, + uadk_x448_keyexch_functions, "uadk X448 keyexch implementation."}, ++ { "X25519", UADK_DEFAULT_PROPERTIES, ++ uadk_x25519_keyexch_functions, "uadk 25519 keyexch implementation."}, + { NULL, NULL, NULL } + }; + +diff --git a/src/uadk_prov_pkey.c b/src/uadk_prov_pkey.c +index ebf90e4..ee702e1 100644 +--- a/src/uadk_prov_pkey.c ++++ b/src/uadk_prov_pkey.c +@@ -209,13 +209,13 @@ static void uadk_prov_fill_ecc_cv_param(struct wd_ecc_curve *ecc_param, + { + ecc_param->p.dsize = BN_bn2bin(cv_param->p, (void *)ecc_param->p.data); + ecc_param->a.dsize = BN_bn2bin(cv_param->a, (void *)ecc_param->a.data); +- if (!ecc_param->a.dsize) { ++ if (ecc_param->a.dsize == 0) { + ecc_param->a.dsize = 1; + ecc_param->a.data[0] = 0; + } + + ecc_param->b.dsize = BN_bn2bin(cv_param->b, (void *)ecc_param->b.data); +- if (!ecc_param->b.dsize) { ++ if (ecc_param->b.dsize == 0) { + ecc_param->b.dsize = 1; + ecc_param->b.data[0] = 0; + } +@@ -235,33 +235,33 @@ static int uadk_prov_set_sess_setup_cv(const EC_GROUP *group, + BN_CTX *bn_ctx; + + bn_ctx = BN_CTX_new(); +- if (!bn_ctx) ++ if (bn_ctx == NULL) + return ret; + + BN_CTX_start(bn_ctx); + + cv_param = OPENSSL_malloc(sizeof(struct curve_param)); +- if (!cv_param) ++ if (cv_param == NULL) + goto free_ctx; + + cv_param->p = BN_CTX_get(bn_ctx); +- if (!cv_param->p) ++ if (cv_param->p == NULL) + goto free_cv; + + cv_param->a = BN_CTX_get(bn_ctx); +- if (!cv_param->a) ++ if (cv_param->a == NULL) + goto free_cv; + + cv_param->b = BN_CTX_get(bn_ctx); +- if (!cv_param->b) ++ if (cv_param->b == NULL) + goto free_cv; + + g_x = BN_CTX_get(bn_ctx); +- if (!g_x) ++ if (g_x == NULL) + goto free_cv; + + g_y = BN_CTX_get(bn_ctx); +- if (!g_y) ++ if (g_y == NULL) + goto free_cv; + + ret = uadk_prov_get_curve(group, cv_param->p, cv_param->a, cv_param->b, bn_ctx); +@@ -269,7 +269,7 @@ static int uadk_prov_set_sess_setup_cv(const EC_GROUP *group, + goto free_cv; + + cv_param->g = EC_GROUP_get0_generator(group); +- if (!cv_param->g) ++ if (cv_param->g == NULL) + goto free_cv; + + ret = uadk_prov_get_affine_coordinates(group, cv_param->g, g_x, g_y, bn_ctx); +@@ -277,7 +277,7 @@ static int uadk_prov_set_sess_setup_cv(const EC_GROUP *group, + goto free_cv; + + cv_param->order = EC_GROUP_get0_order(group); +- if (!cv_param->order) ++ if (cv_param->order == NULL) + goto free_cv; + + uadk_prov_fill_ecc_cv_param(ecc_param, cv_param, g_x, g_y); +@@ -665,7 +665,7 @@ static bool uadk_prov_support_algorithm(const char *alg) + + void uadk_prov_keymgmt_alg(void) + { +- static const char * const keymgmt_alg[] = {"sm2", "x448", "ecdh"}; ++ static const char * const keymgmt_alg[] = {"sm2", "x448", "ecdh", "x25519"}; + __u32 i, size; + bool sp; + +@@ -837,7 +837,7 @@ void uadk_prov_ecc_uninit(void) + + void uadk_prov_keyexch_alg(void) + { +- static const char * const keyexch_alg[] = {"x448", "ecdh"}; ++ static const char * const keyexch_alg[] = {"x448", "ecdh", "x25519"}; + __u32 i, size; + bool sp; + +diff --git a/src/uadk_prov_pkey.h b/src/uadk_prov_pkey.h +index 38a67ac..0f01baf 100644 +--- a/src/uadk_prov_pkey.h ++++ b/src/uadk_prov_pkey.h +@@ -70,6 +70,7 @@ enum { + KEYMGMT_SM2 = 0x0, + KEYMGMT_X448 = 0x1, + KEYMGMT_ECDH = 0x2, ++ KEYMGMT_X25519 = 0x3, + KEYMGMT_MAX = 0x6 + }; + +@@ -88,6 +89,7 @@ enum { + enum { + KEYEXCH_X448 = 0x0, + KEYEXCH_ECDH = 0x1, ++ KEYEXCH_X25519 = 0x2, + }; + + struct curve_param { +-- +2.25.1 + diff --git a/0019-uadk_engine_rsa-add-rsa-finish-method.patch b/0019-uadk_engine_rsa-add-rsa-finish-method.patch new file mode 100644 index 0000000..27b4810 --- /dev/null +++ b/0019-uadk_engine_rsa-add-rsa-finish-method.patch @@ -0,0 +1,31 @@ +From fed432c3d9861f4cc2bfbaac123c379dcb2f6e77 Mon Sep 17 00:00:00 2001 +From: Zhiqi Song +Date: Fri, 24 Jan 2025 09:14:03 +0800 +Subject: [PATCH 19/19] uadk_engine_rsa: add rsa finish method + +There will be memory allocation in OpenSSL mod_exp methods, these +resources need to be released by rsa_ossl_finish(), so add the rsa +finish method by RSA_meth_set_finish(). + +Signed-off-by: Zhiqi Song +Signed-off-by: JiangShui Yang +--- + src/uadk_rsa.c | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git a/src/uadk_rsa.c b/src/uadk_rsa.c +index 445b51b..76678a4 100644 +--- a/src/uadk_rsa.c ++++ b/src/uadk_rsa.c +@@ -1909,6 +1909,8 @@ static RSA_METHOD *uadk_e_get_rsa_methods(void) + RSA_PKCS1_OpenSSL())); + (void)RSA_meth_set_mod_exp(rsa_hw_meth, RSA_meth_get_mod_exp( + RSA_PKCS1_OpenSSL())); ++ (void)RSA_meth_set_finish(rsa_hw_meth, RSA_meth_get_finish( ++ RSA_PKCS1_OpenSSL())); + + return rsa_hw_meth; + } +-- +2.25.1 + diff --git a/uadk_engine.spec b/uadk_engine.spec index 3aed911..54bed1f 100644 --- a/uadk_engine.spec +++ b/uadk_engine.spec @@ -2,7 +2,7 @@ Name: uadk_engine Summary: UADK Accelerator Engine Version: 1.5.0 -Release: 1 +Release: 2 License: Apache-2.0 Source: %{name}-%{version}.tar.gz ExclusiveOS: linux @@ -22,6 +22,17 @@ Patch0005: 0005-uadk_provider-support-ecdh-keyexch-hardware-accelera.patch Patch0006: 0006-uadk_provider-support-x448-alg.patch Patch0007: 0007-uadk_engine-Clear-some-compilation-warnings-specific.patch Patch0008: 0008-uadk_provider_rsa-cleanup-variable-definition-and-re.patch +Patch0009: 0009-uadk_provider_ecdsa-support-ecdsa-signature-and-veri.patch +Patch0010: 0010-uadk_async-check-type-and-ctx-in-task.patch +Patch0011: 0011-uadk_provider-use-default-provider-to-get-random-dat.patch +Patch0012: 0012-uadk_provider_aead-cleanup-functions-in-aead.patch +Patch0013: 0013-uadk_provider-fix-the-fork-function-of-the-digest.patch +Patch0014: 0014-uadk_provider-fix-the-ctx-copy-function-of-the-diges.patch +Patch0015: 0015-uadk_provider-code-cleanup-for-digest-and-aead.patch +Patch0016: 0016-uadk_engine_rsa-fix-memory-leak-of-pkey-meth.patch +Patch0017: 0017-uadk_engine-fix-memory-leak-in-fork-scene.patch +Patch0018: 0018-uadk_provider-support-X25519.patch +Patch0019: 0019-uadk_engine_rsa-add-rsa-finish-method.patch %description This package contains the UADK Accelerator Engine. @@ -82,6 +93,9 @@ rm -rf ${RPM_BUILD_ROOT} /sbin/ldconfig %changelog +* Thu Feb 27 2025 JiangShui Yang 1.5.0-2 + - uadk_provider: the x25519 and ecdsa algorithms are supported. + * Wed Dec 11 2024 JiangShui Yang 1.5.0-1 - uadk_engine: adding the uadk_provider library -- Gitee