[PATCH 00/17] uadk_provider: add switching software computation function

From: JiangShui Yang <yangjiangshui@h-partners.com> Chenghai Huang (4): uadk_provider: fix a memory leak issue in BIO_meth uadk_provider: add hmac alg for uadk_provider in openssl3.0 uadk_provider: add soft mac switching function for uadk_provider uadk_engine: fix a digest software switching issue in update Junchong Pan (1): uadk_engine - fix print format Qi Tao (2): uadk_provider: fix async packet reception timeout error uadk_prov: sec support switching to soft calculation Wenkai Lin (2): digest: fix for digest soft work digest: fix for digest soft init Zhiqi Song (1): uadk_provider: fix atomic compare parameter lizhi (7): uadk_provider: support switching to software in init uadk_provider/dh: add dh switching software computation function uadk_provider/rsa: add rsa switching software computation function uadk_provider/sm2: add sm2 switching software computation function uadk_provider/ecx: add x448 and x25519 switching software computation function uadk_provider/ecdsa: add ecdsa switching software computation function uadk_provider/ecdh: add ecdh switching software computation function src/Makefile.am | 3 +- src/uadk_async.h | 1 + src/uadk_digest.c | 108 ++-- src/uadk_ec.c | 2 +- src/uadk_prov.h | 11 + src/uadk_prov_aead.c | 340 ++++++++--- src/uadk_prov_cipher.c | 93 +++- src/uadk_prov_dh.c | 88 ++- src/uadk_prov_digest.c | 220 +++++--- src/uadk_prov_ec_kmgmt.c | 27 +- src/uadk_prov_ecdh_exch.c | 61 +- src/uadk_prov_ecdsa.c | 69 ++- src/uadk_prov_ecx.c | 242 +++++--- src/uadk_prov_hmac.c | 1115 +++++++++++++++++++++++++++++++++++++ src/uadk_prov_init.c | 171 ++++-- src/uadk_prov_pkey.c | 30 +- src/uadk_prov_pkey.h | 6 + src/uadk_prov_rsa.c | 182 +++--- src/uadk_prov_sm2.c | 241 +++++++- 19 files changed, 2526 insertions(+), 484 deletions(-) create mode 100644 src/uadk_prov_hmac.c -- 2.33.0

From: Chenghai Huang <huangchenghai2@huawei.com> After BIO_meth_new, it need to call BIO_meth_free to free the memery. Signed-off-by: Chenghai Huang <huangchenghai2@huawei.com> Signed-off-by: JiangShui Yang <yangjiangshui@h-partners.com> --- src/uadk_prov_init.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/uadk_prov_init.c b/src/uadk_prov_init.c index a6012ab..f3f360f 100644 --- a/src/uadk_prov_init.c +++ b/src/uadk_prov_init.c @@ -260,13 +260,17 @@ static void uadk_teardown(void *provctx) { struct uadk_prov_ctx *ctx = (struct uadk_prov_ctx *)provctx; + if (ctx) { + BIO_meth_free(ctx->corebiometh); + OPENSSL_free(ctx); + } + uadk_prov_destroy_digest(); uadk_prov_destroy_cipher(); uadk_prov_destroy_aead(); uadk_prov_destroy_rsa(); uadk_prov_ecc_uninit(); uadk_prov_dh_uninit(); - OPENSSL_free(ctx); OSSL_PROVIDER_unload(prov); async_module_uninit(); } -- 2.33.0

From: Zhiqi Song <songzhiqi1@huawei.com> Use explicit initialization values in __atomic_compare_exchange_n(). Signed-off-by: Zhiqi Song <songzhiqi1@huawei.com> Signed-off-by: JiangShui Yang <yangjiangshui@h-partners.com> --- src/uadk_prov_init.c | 17 +++++++++++------ 1 file changed, 11 insertions(+), 6 deletions(-) diff --git a/src/uadk_prov_init.c b/src/uadk_prov_init.c index f3f360f..54e3fcb 100644 --- a/src/uadk_prov_init.c +++ b/src/uadk_prov_init.c @@ -209,24 +209,29 @@ static const OSSL_ALGORITHM uadk_prov_keyexch[] = { static const OSSL_ALGORITHM *uadk_query(void *provctx, int operation_id, int *no_cache) { + OSSL_LIB_CTX *libctx; static int prov_init; int ver; - prov = OSSL_PROVIDER_load(NULL, "default"); - if (!prov_init) { - prov_init = 1; + if (__atomic_compare_exchange_n(&prov_init, &(int){0}, 1, false, __ATOMIC_SEQ_CST, + __ATOMIC_SEQ_CST)) { + libctx = prov_libctx_of(provctx); + prov = OSSL_PROVIDER_load(libctx, "default"); + if (!prov) { + fprintf(stderr, "failed to load default provider\n"); + return NULL; + } /* * uadk_provider takes the highest priority * and overwrite the openssl.cnf property. */ - EVP_set_default_properties(NULL, "?provider=uadk_provider"); + EVP_set_default_properties(libctx, "?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); + (void)RAND_set_DRBG_type(libctx, NULL, "provider=default", NULL, NULL); } *no_cache = 0; -- 2.33.0

From: lizhi <lizhi206@huawei.com> Switch to software computing when hardware device detection fails during initialization. Signed-off-by: lizhi <lizhi206@huawei.com> Signed-off-by: JiangShui Yang <yangjiangshui@h-partners.com> --- src/uadk_prov.h | 3 + src/uadk_prov_cipher.c | 2 +- src/uadk_prov_digest.c | 15 +++++ src/uadk_prov_init.c | 143 +++++++++++++++++++++++++++++++---------- src/uadk_prov_pkey.c | 28 +++++++- src/uadk_prov_pkey.h | 6 ++ 6 files changed, 160 insertions(+), 37 deletions(-) diff --git a/src/uadk_prov.h b/src/uadk_prov.h index 7cb1eee..47bfb43 100644 --- a/src/uadk_prov.h +++ b/src/uadk_prov.h @@ -198,6 +198,9 @@ void uadk_prov_destroy_dh(void); void uadk_prov_ecc_uninit(void); void uadk_prov_dh_uninit(void); int uadk_prov_cipher_version(void); +int uadk_prov_digest_version(void); +int uadk_get_sw_offload_state(void); +void uadk_set_sw_offload_state(int enable); /* offload small packets to sw */ extern int enable_sw_offload; diff --git a/src/uadk_prov_cipher.c b/src/uadk_prov_cipher.c index a779a3d..f63288f 100644 --- a/src/uadk_prov_cipher.c +++ b/src/uadk_prov_cipher.c @@ -1291,7 +1291,7 @@ int uadk_prov_cipher_version(void) dev = wd_get_accel_dev("cipher"); if (!dev) { - fprintf(stderr, "no device available!\n"); + fprintf(stderr, "no cipher device available!\n"); return 0; } diff --git a/src/uadk_prov_digest.c b/src/uadk_prov_digest.c index caac877..921c3db 100644 --- a/src/uadk_prov_digest.c +++ b/src/uadk_prov_digest.c @@ -956,3 +956,18 @@ UADK_PROVIDER_IMPLEMENTATION(sha384, NID_sha384, 48, 128); UADK_PROVIDER_IMPLEMENTATION(sha512, NID_sha512, 64, 128); UADK_PROVIDER_IMPLEMENTATION(sha512_224, NID_sha512_224, 28, 128); UADK_PROVIDER_IMPLEMENTATION(sha512_256, NID_sha512_256, 32, 128); + +int uadk_prov_digest_version(void) +{ + struct uacce_dev *dev; + + dev = wd_get_accel_dev("digest"); + if (!dev) { + fprintf(stderr, "no digest device available!\n"); + return UADK_DIGEST_FAIL; + } + + free(dev); + + return UADK_DIGEST_SUCCESS; +} diff --git a/src/uadk_prov_init.c b/src/uadk_prov_init.c index 54e3fcb..b5588f2 100644 --- a/src/uadk_prov_init.c +++ b/src/uadk_prov_init.c @@ -33,7 +33,7 @@ #include "uadk_prov_pkey.h" static const char UADK_DEFAULT_PROPERTIES[] = "provider=uadk_provider"; -static OSSL_PROVIDER *prov; +static OSSL_PROVIDER *default_prov; /* Functions provided by the core */ static OSSL_FUNC_core_gettable_params_fn *c_gettable_params; @@ -48,11 +48,11 @@ struct uadk_provider_params { int enable_sw_offload; const OSSL_ALGORITHM uadk_prov_digests[] = { - { OSSL_DIGEST_NAME_MD5, UADK_DEFAULT_PROPERTIES, + { PROV_NAMES_MD5, UADK_DEFAULT_PROPERTIES, uadk_md5_functions, "uadk_provider md5" }, - { OSSL_DIGEST_NAME_SM3, UADK_DEFAULT_PROPERTIES, + { PROV_NAMES_SM3, UADK_DEFAULT_PROPERTIES, uadk_sm3_functions, "uadk_provider sm3" }, - { OSSL_DIGEST_NAME_SHA1, UADK_DEFAULT_PROPERTIES, + { PROV_NAMES_SHA1, UADK_DEFAULT_PROPERTIES, uadk_sha1_functions, "uadk_provider sha1" }, { PROV_NAMES_SHA2_224, UADK_DEFAULT_PROPERTIES, uadk_sha224_functions, "uadk_provider sha2-224" }, @@ -62,9 +62,9 @@ const OSSL_ALGORITHM uadk_prov_digests[] = { uadk_sha384_functions, "uadk_provider sha2-384" }, { PROV_NAMES_SHA2_512, UADK_DEFAULT_PROPERTIES, uadk_sha512_functions, "uadk_provider sha2-512" }, - { "SHA2-512/224:SHA-512/224:SHA512-224", UADK_DEFAULT_PROPERTIES, + { PROV_NAMES_SHA2_512_224, UADK_DEFAULT_PROPERTIES, uadk_sha512_224_functions, "uadk_provider sha2-512-224" }, - { "SHA2-512/256:SHA-512/256:SHA512-256", UADK_DEFAULT_PROPERTIES, + { PROV_NAMES_SHA2_512_256, UADK_DEFAULT_PROPERTIES, uadk_sha512_256_functions, "uadk_provider sha2-512-256" }, { NULL, NULL, NULL } }; @@ -161,7 +161,13 @@ const OSSL_ALGORITHM uadk_prov_ciphers_v3[] = { { NULL, NULL, NULL } }; -static const OSSL_ALGORITHM uadk_prov_signature[] = { +static const OSSL_ALGORITHM uadk_prov_signature_v2[] = { + { "RSA", UADK_DEFAULT_PROPERTIES, + uadk_rsa_signature_functions, "uadk_provider rsa_signature" }, + { NULL, NULL, NULL } +}; + +static const OSSL_ALGORITHM uadk_prov_signature_v3[] = { { "RSA", UADK_DEFAULT_PROPERTIES, uadk_rsa_signature_functions, "uadk_provider rsa_signature" }, { "SM2", UADK_DEFAULT_PROPERTIES, @@ -171,7 +177,14 @@ static const OSSL_ALGORITHM uadk_prov_signature[] = { { NULL, NULL, NULL } }; -static const OSSL_ALGORITHM uadk_prov_keymgmt[] = { +static const OSSL_ALGORITHM uadk_prov_keymgmt_v2[] = { + { "RSA", UADK_DEFAULT_PROPERTIES, + uadk_rsa_keymgmt_functions, "uadk RSA Keymgmt implementation." }, + { "DH", UADK_DEFAULT_PROPERTIES, uadk_dh_keymgmt_functions }, + { NULL, NULL, NULL } +}; + +static const OSSL_ALGORITHM uadk_prov_keymgmt_v3[] = { { "RSA", UADK_DEFAULT_PROPERTIES, uadk_rsa_keymgmt_functions, "uadk RSA Keymgmt implementation." }, { "DH", UADK_DEFAULT_PROPERTIES, uadk_dh_keymgmt_functions }, @@ -186,7 +199,13 @@ static const OSSL_ALGORITHM uadk_prov_keymgmt[] = { { NULL, NULL, NULL } }; -static const OSSL_ALGORITHM uadk_prov_asym_cipher[] = { +static const OSSL_ALGORITHM uadk_prov_asym_cipher_v2[] = { + { "RSA", UADK_DEFAULT_PROPERTIES, + uadk_rsa_asym_cipher_functions, "uadk RSA asym cipher implementation." }, + { NULL, NULL, NULL } +}; + +static const OSSL_ALGORITHM uadk_prov_asym_cipher_v3[] = { { "RSA", UADK_DEFAULT_PROPERTIES, uadk_rsa_asym_cipher_functions, "uadk RSA asym cipher implementation." }, { "SM2", UADK_DEFAULT_PROPERTIES, @@ -194,7 +213,13 @@ static const OSSL_ALGORITHM uadk_prov_asym_cipher[] = { { NULL, NULL, NULL } }; -static const OSSL_ALGORITHM uadk_prov_keyexch[] = { +static const OSSL_ALGORITHM uadk_prov_keyexch_v2[] = { + { "DH", UADK_DEFAULT_PROPERTIES, + uadk_dh_keyexch_functions, "UADK DH keyexch implementation"}, + { NULL, NULL, NULL } +}; + +static const OSSL_ALGORITHM uadk_prov_keyexch_v3[] = { { "DH", UADK_DEFAULT_PROPERTIES, uadk_dh_keyexch_functions, "UADK DH keyexch implementation"}, { "ECDH", UADK_DEFAULT_PROPERTIES, @@ -216,8 +241,8 @@ static const OSSL_ALGORITHM *uadk_query(void *provctx, int operation_id, if (__atomic_compare_exchange_n(&prov_init, &(int){0}, 1, false, __ATOMIC_SEQ_CST, __ATOMIC_SEQ_CST)) { libctx = prov_libctx_of(provctx); - prov = OSSL_PROVIDER_load(libctx, "default"); - if (!prov) { + default_prov = OSSL_PROVIDER_load(libctx, "default"); + if (!default_prov) { fprintf(stderr, "failed to load default provider\n"); return NULL; } @@ -234,31 +259,59 @@ static const OSSL_ALGORITHM *uadk_query(void *provctx, int operation_id, (void)RAND_set_DRBG_type(libctx, NULL, "provider=default", NULL, NULL); } - *no_cache = 0; + if (no_cache) + *no_cache = 0; + switch (operation_id) { case OSSL_OP_DIGEST: + ver = uadk_prov_digest_version(); + if (!ver && uadk_get_sw_offload_state()) + break; return uadk_prov_digests; case OSSL_OP_CIPHER: ver = uadk_prov_cipher_version(); - if (ver == HW_SEC_V3) + if (!ver && uadk_get_sw_offload_state()) + break; + else if (ver == HW_SEC_V3) return uadk_prov_ciphers_v3; return uadk_prov_ciphers_v2; case OSSL_OP_SIGNATURE: uadk_prov_signature_alg(); - return uadk_prov_signature; + ver = uadk_prov_pkey_version(); + if (!ver && uadk_get_sw_offload_state()) + break; + else if (ver == HW_PKEY_V3) + return uadk_prov_signature_v3; + return uadk_prov_signature_v2; case OSSL_OP_KEYMGMT: uadk_prov_keymgmt_alg(); - return uadk_prov_keymgmt; + ver = uadk_prov_pkey_version(); + if (!ver && uadk_get_sw_offload_state()) + break; + else if (ver == HW_PKEY_V3) + return uadk_prov_keymgmt_v3; + return uadk_prov_keymgmt_v2; case OSSL_OP_ASYM_CIPHER: uadk_prov_asym_cipher_alg(); - return uadk_prov_asym_cipher; + ver = uadk_prov_pkey_version(); + if (!ver && uadk_get_sw_offload_state()) + break; + else if (ver == HW_PKEY_V3) + return uadk_prov_asym_cipher_v3; + return uadk_prov_asym_cipher_v2; case OSSL_OP_KEYEXCH: uadk_prov_keyexch_alg(); - return uadk_prov_keyexch; - case OSSL_OP_STORE: - return prov->query_operation(provctx, operation_id, no_cache); + ver = uadk_prov_pkey_version(); + if (!ver && uadk_get_sw_offload_state()) + break; + else if (ver == HW_PKEY_V3) + return uadk_prov_keyexch_v3; + return uadk_prov_keyexch_v2; + default: + break; } - return NULL; + + return OSSL_PROVIDER_query_operation(default_prov, operation_id, no_cache); } static void uadk_teardown(void *provctx) @@ -276,36 +329,60 @@ static void uadk_teardown(void *provctx) uadk_prov_destroy_rsa(); uadk_prov_ecc_uninit(); uadk_prov_dh_uninit(); - OSSL_PROVIDER_unload(prov); async_module_uninit(); + if (default_prov) { + OSSL_PROVIDER_unload(default_prov); + default_prov = NULL; + } +} + +static int uadk_get_params(OSSL_PARAM params[]) +{ + return UADK_P_SUCCESS; } static const OSSL_DISPATCH uadk_dispatch_table[] = { { OSSL_FUNC_PROVIDER_QUERY_OPERATION, (void (*)(void))uadk_query }, { OSSL_FUNC_PROVIDER_TEARDOWN, (void (*)(void))uadk_teardown }, + { OSSL_FUNC_PROVIDER_GET_PARAMS, (void (*)(void))uadk_get_params }, { 0, NULL } }; +int uadk_get_sw_offload_state(void) +{ + return enable_sw_offload; +} + +/* enable = 0 means disable sw offload, enable = 1 means enable sw offload */ +void uadk_set_sw_offload_state(int enable) +{ + enable_sw_offload = enable; +} + int uadk_get_params_from_core(const OSSL_CORE_HANDLE *handle) { OSSL_PARAM core_params[2], *p = core_params; + if (handle == NULL) { + fprintf(stderr, "invalid: OSSL_CORE_HANDLE is NULL\n"); + return UADK_P_FAIL; + } + *p++ = OSSL_PARAM_construct_utf8_ptr( "enable_sw_offload", (char **)&uadk_params.enable_sw_offload, 0); - *p = OSSL_PARAM_construct_end(); if (!c_get_params(handle, core_params)) { fprintf(stderr, "WARN: UADK get parameters from core is failed.\n"); - return 0; + return UADK_P_FAIL; } if (uadk_params.enable_sw_offload) - enable_sw_offload = atoi(uadk_params.enable_sw_offload); + uadk_set_sw_offload_state(atoi(uadk_params.enable_sw_offload)); - return 1; + return UADK_P_SUCCESS; } static void provider_init_child_at_fork_handler(void) @@ -324,12 +401,12 @@ static int uadk_prov_ctx_set_core_bio_method(struct uadk_prov_ctx *ctx) core_bio = ossl_bio_prov_init_bio_method(); if (core_bio == NULL) { fprintf(stderr, "failed to set bio from dispatch\n"); - return 0; + return UADK_P_FAIL; } ctx->corebiometh = core_bio; - return 1; + return UADK_P_SUCCESS; } static void ossl_prov_core_from_dispatch(const OSSL_DISPATCH *fns) @@ -363,7 +440,7 @@ int OSSL_provider_init(const OSSL_CORE_HANDLE *handle, if (oin == NULL) { fprintf(stderr, "failed to get dispatch in\n"); - return 0; + return UADK_P_FAIL; } ossl_prov_bio_from_dispatch(oin); @@ -371,12 +448,12 @@ int OSSL_provider_init(const OSSL_CORE_HANDLE *handle, /* get parameters from uadk_provider.cnf */ if (!uadk_get_params_from_core(handle)) - return 0; + return UADK_P_FAIL; ctx = OPENSSL_zalloc(sizeof(*ctx)); if (ctx == NULL) { fprintf(stderr, "failed to alloc ctx\n"); - return 0; + return UADK_P_FAIL; } /* Set handle from core to get core functions */ @@ -385,7 +462,7 @@ int OSSL_provider_init(const OSSL_CORE_HANDLE *handle, ret = uadk_prov_ctx_set_core_bio_method(ctx); if (!ret) - return 0; + return UADK_P_FAIL; ret = async_module_init(); if (!ret) @@ -395,5 +472,5 @@ int OSSL_provider_init(const OSSL_CORE_HANDLE *handle, *provctx = (void *)ctx; *out = uadk_dispatch_table; - return 1; + return UADK_P_SUCCESS; } diff --git a/src/uadk_prov_pkey.c b/src/uadk_prov_pkey.c index ee702e1..1323cfd 100644 --- a/src/uadk_prov_pkey.c +++ b/src/uadk_prov_pkey.c @@ -869,7 +869,7 @@ int uadk_prov_ecc_bit_check(const EC_GROUP *group) fprintf(stderr, "invalid: unsupport key bits %d!\n", bits); - return UADK_P_FAIL; + return UADK_DO_SOFT; } /* Currently, disable the security checks in the default provider and uadk provider */ @@ -906,8 +906,8 @@ int uadk_prov_ecc_check_key(OSSL_LIB_CTX *ctx, const EC_KEY *ec, int protect) curve_name = EC_curve_nid2nist(nid); if (!curve_name) { - fprintf(stderr, "invalid: Curve %s is not approved in FIPS mode!\n", - curve_name); + fprintf(stderr, "invalid: Curve NID %d is not approved in FIPS mode!\n", + nid); return UADK_P_FAIL; } @@ -936,3 +936,25 @@ int uadk_prov_ecc_check_key(OSSL_LIB_CTX *ctx, const EC_KEY *ec, int protect) return UADK_P_SUCCESS; } #endif /* OPENSSL_NO_FIPS_SECURITYCHECKS */ + +int uadk_prov_pkey_version(void) +{ + struct uacce_dev *dev1, *dev2; + + dev1 = wd_get_accel_dev("rsa"); + if (!dev1) { + fprintf(stderr, "no pkey device available!\n"); + return HW_PKEY_INVALID; + } + + dev2 = wd_get_accel_dev("sm2"); + if (!dev2) { + free(dev1); + return HW_PKEY_V2; + } + + free(dev1); + free(dev2); + + return HW_PKEY_V3; +} diff --git a/src/uadk_prov_pkey.h b/src/uadk_prov_pkey.h index 0f01baf..1886117 100644 --- a/src/uadk_prov_pkey.h +++ b/src/uadk_prov_pkey.h @@ -41,6 +41,7 @@ #define UADK_ECC_MAX_KEY_BITS 521 #define UADK_ECC_MAX_KEY_BYTES 66 #define UADK_ECC_CV_PARAM_NUM 6 +#define UADK_DO_SOFT (-0xE0) #define UADK_P_SUCCESS 1 #define UADK_P_FAIL 0 #define UADK_P_INVALID (-1) @@ -65,6 +66,9 @@ #define TRANS_BITS_BYTES_SHIFT 3 #define GET_MS_BYTE(n) ((n) >> 8) #define GET_LS_BYTE(n) ((n) & 0xFF) +#define HW_PKEY_V2 2 +#define HW_PKEY_V3 3 +#define HW_PKEY_INVALID 0 enum { KEYMGMT_SM2 = 0x0, @@ -400,6 +404,7 @@ typedef struct { const char *description; OSSL_PROVIDER *prov; int refcnt; + void *lock; OSSL_FUNC_keyexch_newctx_fn *newctx; OSSL_FUNC_keyexch_init_fn *init; @@ -467,5 +472,6 @@ int uadk_prov_get_affine_coordinates(const EC_GROUP *group, const EC_POINT *p, BIGNUM *x, BIGNUM *y, BN_CTX *ctx); int uadk_prov_securitycheck_enabled(OSSL_LIB_CTX *ctx); int uadk_prov_ecc_check_key(OSSL_LIB_CTX *ctx, const EC_KEY *ec, int protect); +int uadk_prov_pkey_version(void); #endif -- 2.33.0

Async packet reception timeout without timely failure return can lead to issues such as software calculation failure. First initialize the value of req.state to -1. If the value of req.state is not 0 after async_pause_job(), it indicates an exception in packet reception, and the function can directly return an error. Signed-off-by: Qi Tao <taoqi10@huawei.com> Signed-off-by: JiangShui Yang <yangjiangshui@h-partners.com> --- src/uadk_prov.h | 1 + src/uadk_prov_aead.c | 26 ++++++++------------------ src/uadk_prov_cipher.c | 8 ++++++-- src/uadk_prov_dh.c | 2 +- src/uadk_prov_digest.c | 6 +++++- src/uadk_prov_pkey.c | 2 +- src/uadk_prov_rsa.c | 2 +- 7 files changed, 23 insertions(+), 24 deletions(-) diff --git a/src/uadk_prov.h b/src/uadk_prov.h index 47bfb43..b6c236a 100644 --- a/src/uadk_prov.h +++ b/src/uadk_prov.h @@ -28,6 +28,7 @@ #define UADK_DEVICE_ERROR 3 #define HW_SEC_V2 2 #define HW_SEC_V3 3 +#define POLL_ERROR (-1) /* Copy openssl/providers/implementations/include/prov/names.h */ #define PROV_NAMES_SHA2_224 "SHA2-224:SHA-224:SHA224:2.16.840.1.101.3.4.2.4" diff --git a/src/uadk_prov_aead.c b/src/uadk_prov_aead.c index 1163328..6f33f43 100644 --- a/src/uadk_prov_aead.c +++ b/src/uadk_prov_aead.c @@ -360,7 +360,7 @@ static int uadk_do_aead_sync(struct aead_priv_ctx *priv, unsigned char *out, static int uadk_do_aead_async(struct aead_priv_ctx *priv, struct async_op *op, unsigned char *out, const unsigned char *in, size_t inlen) { - struct uadk_e_cb_info *cb_param; + struct uadk_e_cb_info cb_param; int cnt = 0; int ret; @@ -376,22 +376,16 @@ static int uadk_do_aead_async(struct aead_priv_ctx *priv, struct async_op *op, uadk_do_aead_async_prepare(priv, out, in, inlen); - cb_param = malloc(sizeof(struct uadk_e_cb_info)); - if (unlikely(!cb_param)) { - fprintf(stderr, "failed to alloc cb_param.\n"); - return UADK_AEAD_FAIL; - } - - cb_param->op = op; - cb_param->priv = &priv->req; + cb_param.op = op; + cb_param.priv = &priv->req; priv->req.cb = uadk_prov_aead_cb; - priv->req.cb_param = cb_param; + priv->req.cb_param = &cb_param; priv->req.msg_state = AEAD_MSG_BLOCK; - priv->req.state = UADK_AEAD_FAIL; + priv->req.state = POLL_ERROR; ret = async_get_free_task(&op->idx); if (unlikely(!ret)) - goto free_cb_param; + return UADK_AEAD_FAIL; do { ret = wd_do_aead_async(priv->sess, &priv->req); @@ -404,8 +398,7 @@ static int uadk_do_aead_async(struct aead_priv_ctx *priv, struct async_op *op, continue; async_free_poll_task(op->idx, 0); - ret = UADK_AEAD_FAIL; - goto free_cb_param; + return UADK_AEAD_FAIL; } } while (ret == -EBUSY); @@ -413,15 +406,12 @@ static int uadk_do_aead_async(struct aead_priv_ctx *priv, struct async_op *op, if (unlikely(!ret || priv->req.state)) { fprintf(stderr, "do aead async job failed, ret: %d, state: %u!\n", ret, priv->req.state); - ret = UADK_AEAD_FAIL; - goto free_cb_param; + return UADK_AEAD_FAIL; } if (priv->req.assoc_bytes) memcpy(out, priv->req.dst + priv->req.assoc_bytes, inlen); -free_cb_param: - free(cb_param); return ret; } diff --git a/src/uadk_prov_cipher.c b/src/uadk_prov_cipher.c index f63288f..eb31f2d 100644 --- a/src/uadk_prov_cipher.c +++ b/src/uadk_prov_cipher.c @@ -418,12 +418,15 @@ static int uadk_prov_cipher_init(struct cipher_priv_ctx *priv, static void async_cb(struct wd_cipher_req *req, void *data) { struct uadk_e_cb_info *cipher_cb_param; + struct wd_cipher_req *req_origin; struct async_op *op; if (!req || !req->cb_param) return; cipher_cb_param = req->cb_param; + req_origin = cipher_cb_param->priv; + req_origin->state = req->state; op = cipher_cb_param->op; if (op && op->job && !op->done) { op->done = 1; @@ -454,9 +457,10 @@ static int uadk_do_cipher_async(struct cipher_priv_ctx *priv, struct async_op *o } cb_param.op = op; - cb_param.priv = priv; + cb_param.priv = &priv->req; priv->req.cb = (void *)async_cb; priv->req.cb_param = &cb_param; + priv->req.state = POLL_ERROR; ret = async_get_free_task(&idx); if (!ret) return UADK_P_FAIL; @@ -472,7 +476,7 @@ static int uadk_do_cipher_async(struct cipher_priv_ctx *priv, struct async_op *o } while (ret == -EBUSY); ret = async_pause_job(priv, op, ASYNC_TASK_CIPHER); - if (!ret) + if (!ret || priv->req.state) return UADK_P_FAIL; return UADK_P_SUCCESS; diff --git a/src/uadk_prov_dh.c b/src/uadk_prov_dh.c index f3724ac..f6262d4 100644 --- a/src/uadk_prov_dh.c +++ b/src/uadk_prov_dh.c @@ -845,7 +845,7 @@ static int uadk_prov_dh_do_crypto(struct uadk_dh_sess *dh_sess) cb_param.priv = &dh_sess->req; dh_sess->req.cb = uadk_prov_dh_cb; dh_sess->req.cb_param = &cb_param; - dh_sess->req.status = -1; + dh_sess->req.status = POLL_ERROR; ret = async_get_free_task(&idx); if (!ret) goto err; diff --git a/src/uadk_prov_digest.c b/src/uadk_prov_digest.c index 921c3db..d6af557 100644 --- a/src/uadk_prov_digest.c +++ b/src/uadk_prov_digest.c @@ -497,12 +497,15 @@ soft_update: static void uadk_async_cb(struct wd_digest_req *req, void *data) { struct uadk_e_cb_info *digest_cb_param; + struct wd_digest_req *req_origin; struct async_op *op; if (!req || !req->cb_param) return; digest_cb_param = req->cb_param; + req_origin = digest_cb_param->priv; + req_origin->state = req->state; op = digest_cb_param->op; if (op && op->job && !op->done) { op->done = 1; @@ -540,9 +543,10 @@ static int uadk_do_digest_async(struct digest_priv_ctx *priv, struct async_op *o } cb_param.op = op; - cb_param.priv = priv; + cb_param.priv = &priv->req; priv->req.cb = (void *)uadk_async_cb; priv->req.cb_param = &cb_param; + priv->req.state = POLL_ERROR; ret = async_get_free_task(&idx); if (!ret) diff --git a/src/uadk_prov_pkey.c b/src/uadk_prov_pkey.c index 1323cfd..ca853ae 100644 --- a/src/uadk_prov_pkey.c +++ b/src/uadk_prov_pkey.c @@ -390,7 +390,7 @@ int uadk_prov_ecc_crypto(handle_t sess, struct wd_ecc_req *req, void *usr) cb_param.priv = req; req->cb = uadk_prov_ecc_cb; req->cb_param = &cb_param; - req->status = -1; + req->status = POLL_ERROR; ret = async_get_free_task(&idx); if (ret == 0) diff --git a/src/uadk_prov_rsa.c b/src/uadk_prov_rsa.c index eac4e46..8f7d734 100644 --- a/src/uadk_prov_rsa.c +++ b/src/uadk_prov_rsa.c @@ -1297,7 +1297,7 @@ static int rsa_do_crypto(struct uadk_rsa_sess *rsa_sess) cb_param.priv = &(rsa_sess->req); rsa_sess->req.cb = uadk_e_rsa_cb; rsa_sess->req.cb_param = &cb_param; - rsa_sess->req.status = -1; + rsa_sess->req.status = POLL_ERROR; ret = async_get_free_task(&idx); if (ret == 0) -- 2.33.0

From: Chenghai Huang <huangchenghai2@huawei.com> Add the HMAC mode for the following digest algorithm: md5 sm3 sha1 sha224 sha256 sha384 sha512 sha512_224 sha512_256 Signed-off-by: Chenghai Huang <huangchenghai2@huawei.com> Signed-off-by: JiangShui Yang <yangjiangshui@h-partners.com> --- src/Makefile.am | 3 +- src/uadk_async.h | 1 + src/uadk_prov.h | 7 + src/uadk_prov_digest.c | 6 +- src/uadk_prov_hmac.c | 834 +++++++++++++++++++++++++++++++++++++++++ src/uadk_prov_init.c | 9 + 6 files changed, 856 insertions(+), 4 deletions(-) create mode 100644 src/uadk_prov_hmac.c diff --git a/src/Makefile.am b/src/Makefile.am index c1863e1..b262319 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -67,7 +67,8 @@ 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_ecdsa.c + uadk_prov_ecx.c uadk_prov_ecdsa.c \ + uadk_prov_hmac.c uadk_provider_la_LDFLAGS=-module -version-number $(VERSION) uadk_provider_la_LIBADD=$(WD_LIBS) -lpthread diff --git a/src/uadk_async.h b/src/uadk_async.h index dcb94d3..8de3c3c 100644 --- a/src/uadk_async.h +++ b/src/uadk_async.h @@ -44,6 +44,7 @@ typedef int (*async_recv_t)(void *ctx); enum task_type { ASYNC_TASK_CIPHER = 0x1, ASYNC_TASK_DIGEST, + ASYNC_TASK_HMAC, ASYNC_TASK_AEAD, ASYNC_TASK_RSA, ASYNC_TASK_DH, diff --git a/src/uadk_prov.h b/src/uadk_prov.h index b6c236a..ac83ee5 100644 --- a/src/uadk_prov.h +++ b/src/uadk_prov.h @@ -31,10 +31,15 @@ #define POLL_ERROR (-1) /* Copy openssl/providers/implementations/include/prov/names.h */ +#define PROV_NAMES_MD5 "MD5:SSL3-MD5:1.2.840.113549.2.5" +#define PROV_NAMES_SM3 "SM3:1.2.156.10197.1.401" +#define PROV_NAMES_SHA1 "SHA1:SHA-1:SSL3-SHA1:1.3.14.3.2.26" #define PROV_NAMES_SHA2_224 "SHA2-224:SHA-224:SHA224:2.16.840.1.101.3.4.2.4" #define PROV_NAMES_SHA2_256 "SHA2-256:SHA-256:SHA256:2.16.840.1.101.3.4.2.1" #define PROV_NAMES_SHA2_384 "SHA2-384:SHA-384:SHA384:2.16.840.1.101.3.4.2.2" #define PROV_NAMES_SHA2_512 "SHA2-512:SHA-512:SHA512:2.16.840.1.101.3.4.2.3" +#define PROV_NAMES_SHA2_512_224 "SHA2-512/224:SHA-512/224:SHA512-224:2.16.840.1.101.3.4.2.5" +#define PROV_NAMES_SHA2_512_256 "SHA2-512/256:SHA-512/256:SHA512-256:2.16.840.1.101.3.4.2.6" typedef int CRYPTO_REF_COUNT; @@ -137,6 +142,7 @@ extern const OSSL_DISPATCH uadk_sha384_functions[FUNC_MAX_NUM]; extern const OSSL_DISPATCH uadk_sha512_functions[FUNC_MAX_NUM]; extern const OSSL_DISPATCH uadk_sha512_224_functions[FUNC_MAX_NUM]; extern const OSSL_DISPATCH uadk_sha512_256_functions[FUNC_MAX_NUM]; +extern const OSSL_DISPATCH uadk_hmac_functions[FUNC_MAX_NUM]; extern const OSSL_DISPATCH uadk_aes_128_cbc_functions[FUNC_MAX_NUM]; extern const OSSL_DISPATCH uadk_aes_192_cbc_functions[FUNC_MAX_NUM]; @@ -192,6 +198,7 @@ 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); +void uadk_prov_destroy_hmac(void); void uadk_prov_destroy_cipher(void); void uadk_prov_destroy_aead(void); void uadk_prov_destroy_rsa(void); diff --git a/src/uadk_prov_digest.c b/src/uadk_prov_digest.c index d6af557..562e786 100644 --- a/src/uadk_prov_digest.c +++ b/src/uadk_prov_digest.c @@ -309,8 +309,8 @@ static int uadk_prov_digest_dev_init(struct digest_priv_ctx *priv) 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"); + if (unlikely(ret && ret != -WD_EEXIST)) { + fprintf(stderr, "uadk failed to initialize digest dev, ret = %d\n", ret); goto free_nodemask; } ret = UADK_DIGEST_SUCCESS; @@ -568,7 +568,7 @@ static int uadk_do_digest_async(struct digest_priv_ctx *priv, struct async_op *o } while (ret == -EBUSY); ret = async_pause_job(priv, op, ASYNC_TASK_DIGEST); - if (!ret) + if (!ret || priv->req.state) return UADK_DIGEST_FAIL; return UADK_DIGEST_SUCCESS; diff --git a/src/uadk_prov_hmac.c b/src/uadk_prov_hmac.c new file mode 100644 index 0000000..3c70c5d --- /dev/null +++ b/src/uadk_prov_hmac.c @@ -0,0 +1,834 @@ +// SPDX-License-Identifier: Apache-2.0 +/* + * Copyright 2023-2024 Huawei Technologies Co.,Ltd. All rights reserved. + * Copyright 2023-2024 Linaro ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#include <stdio.h> +#include <stdbool.h> +#include <string.h> +#include <dlfcn.h> +#include <openssl/evp.h> +#include <openssl/core_names.h> +#include <openssl/proverr.h> +#include <uadk/wd_digest.h> +#include <uadk/wd_sched.h> +#include "uadk.h" +#include "uadk_async.h" +#include "uadk_prov.h" +#include "uadk_utils.h" + +#define UADK_HMAC_SUCCESS 1 +#define UADK_HMAC_FAIL 0 + +/* The max BD data length is 16M-512B */ +#define BUF_LEN 0xFFFE00 + +#define MAX_DIGEST_LENGTH 64 +#define MAX_KEY_LEN 144 +#define HMAC_BLOCK_SIZE (512 * 1024) +#define ALG_NAME_SIZE 128 + +#define KEY_4BYTE_ALIGN(keylen) ((keylen + 3) & ~3) + +#define UADK_DIGEST_DEF_CTXS 1 +#define UADK_DIGEST_OP_NUM 1 + +enum sec_digest_state { + SEC_DIGEST_INIT, + SEC_DIGEST_FIRST_UPDATING, + SEC_DIGEST_DOING, + SEC_DIGEST_FINAL +}; + +struct hmac_prov { + int pid; +}; + +static struct hmac_prov hprov; +static pthread_mutex_t hmac_mutex = PTHREAD_MUTEX_INITIALIZER; + +struct hmac_priv_ctx { + __u32 alg_id; + __u32 state; + size_t out_len; + size_t blk_size; + size_t keylen; + size_t last_update_bufflen; + size_t total_data_len; + OSSL_LIB_CTX *libctx; + handle_t sess; + struct wd_digest_sess_setup setup; + struct wd_digest_req req; + unsigned char *data; + unsigned char key[MAX_KEY_LEN]; + unsigned char out[MAX_DIGEST_LENGTH]; + char alg_name[ALG_NAME_SIZE]; + bool is_stream_copy; +}; + +struct hmac_info { + enum wd_digest_type alg; + __u32 alg_id; + size_t out_len; + size_t blk_size; + const char ossl_alg_name[ALG_NAME_SIZE]; +}; + +static struct hmac_info hmac_info_table[] = { + {WD_DIGEST_MD5, NID_md5, 16, 64, PROV_NAMES_MD5}, + {WD_DIGEST_SM3, NID_sm3, 32, 64, PROV_NAMES_SM3}, + {WD_DIGEST_SHA1, NID_sha1, 20, 64, PROV_NAMES_SHA1}, + {WD_DIGEST_SHA224, NID_sha224, 28, 64, PROV_NAMES_SHA2_224}, + {WD_DIGEST_SHA256, NID_sha256, 32, 64, PROV_NAMES_SHA2_256}, + {WD_DIGEST_SHA384, NID_sha384, 48, 64, PROV_NAMES_SHA2_384}, + {WD_DIGEST_SHA512, NID_sha512, 64, 128, PROV_NAMES_SHA2_512}, + {WD_DIGEST_SHA512_224, NID_sha512_224, 28, 128, PROV_NAMES_SHA2_512_224}, + {WD_DIGEST_SHA512_256, NID_sha512_256, 32, 128, PROV_NAMES_SHA2_512_256} +}; + +static OSSL_FUNC_mac_newctx_fn uadk_prov_hmac_newctx; +static OSSL_FUNC_mac_dupctx_fn uadk_prov_hmac_dupctx; +static OSSL_FUNC_mac_freectx_fn uadk_prov_hmac_freectx; +static OSSL_FUNC_mac_init_fn uadk_prov_hmac_init; +static OSSL_FUNC_mac_update_fn uadk_prov_hmac_update; +static OSSL_FUNC_mac_final_fn uadk_prov_hmac_final; +static OSSL_FUNC_mac_gettable_ctx_params_fn + uadk_prov_hmac_gettable_ctx_params; +static OSSL_FUNC_mac_get_ctx_params_fn uadk_prov_hmac_get_ctx_params; +static OSSL_FUNC_mac_settable_ctx_params_fn + uadk_prov_hmac_settable_ctx_params; +static OSSL_FUNC_mac_set_ctx_params_fn uadk_prov_hmac_set_ctx_params; + +static int uadk_hmac_poll(void *ctx) +{ + __u64 rx_cnt = 0; + __u32 recv = 0; + /* Poll one packet currently */ + __u32 expt = 1; + int ret; + + do { + ret = wd_digest_poll(expt, &recv); + if (ret < 0 || recv == expt) + return ret; + rx_cnt++; + } while (rx_cnt < ENGINE_RECV_MAX_CNT); + + fprintf(stderr, "failed to poll msg: timeout!\n"); + + return -ETIMEDOUT; +} + +static void uadk_fill_mac_buffer_len(struct hmac_priv_ctx *priv, bool is_end) +{ + /* Sha224 and Sha384 and Sha512-XXX need full length mac buffer as doing long hash */ + switch (priv->alg_id) { + case NID_sha224: + priv->req.out_bytes = is_end ? WD_DIGEST_SHA224_LEN : WD_DIGEST_SHA224_FULL_LEN; + break; + case NID_sha384: + priv->req.out_bytes = is_end ? WD_DIGEST_SHA384_LEN : WD_DIGEST_SHA384_FULL_LEN; + break; + case NID_sha512_224: + priv->req.out_bytes = is_end ? + WD_DIGEST_SHA512_224_LEN : WD_DIGEST_SHA512_224_FULL_LEN; + break; + case NID_sha512_256: + priv->req.out_bytes = is_end ? + WD_DIGEST_SHA512_256_LEN : WD_DIGEST_SHA512_256_FULL_LEN; + break; + default: + break; + } +} + +static void uadk_digest_set_msg_state(struct hmac_priv_ctx *priv, bool is_end) +{ + if (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_get_hmac_info(struct hmac_priv_ctx *priv) +{ + int digest_counts = ARRAY_SIZE(hmac_info_table); + int i; + + for (i = 0; i < digest_counts; i++) { + if (strstr(hmac_info_table[i].ossl_alg_name, priv->alg_name)) { + priv->alg_id = hmac_info_table[i].alg_id; + priv->out_len = hmac_info_table[i].out_len; + priv->blk_size = hmac_info_table[i].blk_size; + priv->setup.alg = hmac_info_table[i].alg; + priv->setup.mode = WD_DIGEST_HMAC; + priv->req.out_buf_bytes = MAX_DIGEST_LENGTH; + priv->req.out_bytes = hmac_info_table[i].out_len; + + return UADK_HMAC_SUCCESS; + } + } + + fprintf(stderr, "failed to setup the private ctx, algname = %s.\n", priv->alg_name); + return UADK_HMAC_FAIL; +} + +static const char *get_uadk_alg_name(__u32 alg_id) +{ + switch (alg_id) { + case NID_md5: + return "md5"; + case NID_sm3: + return "sm3"; + case NID_sha1: + return "sha1"; + case NID_sha224: + return "sha224"; + case NID_sha256: + return "sha256"; + case NID_sha384: + return "sha384"; + case NID_sha512: + return "sha512"; + case NID_sha512_224: + return "sha512-224"; + case NID_sha512_256: + return "sha512-256"; + default: + break; + } + + fprintf(stderr, "failed to find alg, nid = %u.\n", alg_id); + return NULL; +} + +static void uadk_hmac_mutex_infork(void) +{ + /* Release the replication lock of the child process */ + pthread_mutex_unlock(&hmac_mutex); +} + +static int uadk_prov_hmac_dev_init(struct hmac_priv_ctx *priv) +{ + struct wd_ctx_params cparams = {0}; + struct wd_ctx_nums ctx_set_num; + int ret = UADK_HMAC_SUCCESS; + const char *alg_name; + + pthread_atfork(NULL, NULL, uadk_hmac_mutex_infork); + pthread_mutex_lock(&hmac_mutex); + if (hprov.pid == getpid()) + goto mutex_unlock; + + alg_name = get_uadk_alg_name(priv->alg_id); + if (!alg_name) { + ret = UADK_HMAC_FAIL; + 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_HMAC_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_((char *)alg_name, TASK_MIX, SCHED_POLICY_RR, &cparams); + if (unlikely(ret && ret != -WD_EEXIST)) { + fprintf(stderr, "uadk failed to initialize hmac, ret = %d\n", ret); + goto free_nodemask; + } + ret = UADK_HMAC_SUCCESS; + + hprov.pid = getpid(); + async_register_poll_fn(ASYNC_TASK_HMAC, uadk_hmac_poll); + +free_nodemask: + numa_free_nodemask(cparams.bmp); +mutex_unlock: + pthread_mutex_unlock(&hmac_mutex); + return ret; +} + +static int uadk_prov_compute_key_hash(struct hmac_priv_ctx *priv, + const unsigned char *key, size_t keylen) +{ + int ret = UADK_HMAC_FAIL; + EVP_MD_CTX *ctx = NULL; + EVP_MD *key_md = NULL; + __u32 outlen = 0; + + key_md = EVP_MD_fetch(priv->libctx, priv->alg_name, NULL); + if (!key_md) + return UADK_HMAC_FAIL; + + ctx = EVP_MD_CTX_new(); + if (!ctx) + goto free_md; + + if (!EVP_DigestInit_ex2(ctx, key_md, NULL) + || !EVP_DigestUpdate(ctx, key, keylen) + || !EVP_DigestFinal_ex(ctx, priv->key, &outlen)) + goto free_ctx; + + priv->keylen = outlen; + ret = UADK_HMAC_SUCCESS; + +free_ctx: + EVP_MD_CTX_free(ctx); +free_md: + EVP_MD_free(key_md); + + return ret; +} + +static int uadk_hmac_ctx_init(struct hmac_priv_ctx *priv) +{ + struct sched_params params = {0}; + int ret; + + ret = uadk_prov_hmac_dev_init(priv); + if (unlikely(ret <= 0)) + return UADK_HMAC_FAIL; + + /* Use the default numa parameters */ + params.numa_id = -1; + priv->setup.sched_param = ¶ms; + + if (!priv->sess) { + priv->sess = wd_digest_alloc_sess(&priv->setup); + if (unlikely(!priv->sess)) { + fprintf(stderr, "uadk failed to alloc hmac sess.\n"); + return UADK_HMAC_FAIL; + } + + ret = wd_digest_set_key(priv->sess, priv->key, priv->keylen); + if (ret) { + fprintf(stderr, "uadk failed to set hmac key!\n"); + goto free_sess; + } + } + + return UADK_HMAC_SUCCESS; + +free_sess: + wd_digest_free_sess(priv->sess); + priv->sess = 0; + return UADK_HMAC_FAIL; +} + +static void uadk_hmac_async_cb(struct wd_digest_req *req, void *data) +{ + struct uadk_e_cb_info *hmac_cb_param; + struct wd_digest_req *req_origin; + struct async_op *op; + + if (!req || !req->cb_param) + return; + + hmac_cb_param = req->cb_param; + req_origin = hmac_cb_param->priv; + req_origin->state = req->state; + op = hmac_cb_param->op; + if (op && op->job && !op->done) { + op->done = 1; + async_free_poll_task(op->idx, 1); + async_wake_job(op->job); + } +} + +static int uadk_do_hmac_sync(struct hmac_priv_ctx *priv) +{ + int ret; + + ret = wd_do_digest_sync(priv->sess, &priv->req); + if (ret) { + fprintf(stderr, "do sec hmac sync failed.\n"); + return UADK_HMAC_FAIL; + } + + return UADK_HMAC_SUCCESS; +} + +static int uadk_do_hmac_async(struct hmac_priv_ctx *priv, struct async_op *op) +{ + struct uadk_e_cb_info cb_param; + int idx, ret; + int cnt = 0; + + cb_param.op = op; + cb_param.priv = &priv->req; + priv->req.cb = (void *)uadk_hmac_async_cb; + priv->req.cb_param = &cb_param; + priv->req.state = POLL_ERROR; + + ret = async_get_free_task(&idx); + if (!ret) + return UADK_HMAC_FAIL; + + op->idx = idx; + do { + ret = wd_do_digest_async(priv->sess, &priv->req); + if (ret < 0 && ret != -EBUSY) { + fprintf(stderr, "do sec digest async failed.\n"); + goto free_poll_task; + } + + if (unlikely(++cnt > ENGINE_SEND_MAX_CNT)) { + fprintf(stderr, "do digest async operation timeout.\n"); + goto free_poll_task; + } + } while (ret == -EBUSY); + + ret = async_pause_job(priv, op, ASYNC_TASK_HMAC); + if (!ret || priv->req.state) + return UADK_HMAC_FAIL; + + return UADK_HMAC_SUCCESS; + +free_poll_task: + async_free_poll_task(op->idx, 0); + return UADK_HMAC_FAIL; +} + +static int uadk_hmac_update_inner(struct hmac_priv_ctx *priv, const void *data, size_t data_len) +{ + unsigned char *input_data = (unsigned char *)data; + size_t remain_len = data_len; + size_t processing_len; + int ret; + + ret = uadk_hmac_ctx_init(priv); + if (ret != UADK_HMAC_SUCCESS) + return UADK_HMAC_FAIL; + + uadk_digest_set_msg_state(priv, false); + uadk_fill_mac_buffer_len(priv, false); + + do { + /* + * If there is data in the buffer, it will be filled and processed. Otherwise, it + * will be processed according to the UADK package len(16M-512Byte). Finally the + * remaining data less than the size of the buffer will be stored in the buffer. + */ + if (priv->last_update_bufflen != 0) { + processing_len = HMAC_BLOCK_SIZE - priv->last_update_bufflen; + uadk_memcpy(priv->data + priv->last_update_bufflen, input_data, + processing_len); + + priv->req.in_bytes = HMAC_BLOCK_SIZE; + priv->req.in = priv->data; + priv->last_update_bufflen = 0; + } else { + if (remain_len > BUF_LEN) + processing_len = BUF_LEN; + else + processing_len = remain_len - (remain_len % HMAC_BLOCK_SIZE); + + priv->req.in_bytes = processing_len; + priv->req.in = input_data; + } + + if (priv->state == SEC_DIGEST_INIT) + priv->state = SEC_DIGEST_FIRST_UPDATING; + else if (priv->state == SEC_DIGEST_FIRST_UPDATING) + priv->state = SEC_DIGEST_DOING; + + priv->req.out = priv->out; + + ret = uadk_do_hmac_sync(priv); + if (!ret) { + fprintf(stderr, "do sec digest update failed.\n"); + return UADK_HMAC_FAIL; + } + + remain_len -= processing_len; + input_data += processing_len; + } while (remain_len > HMAC_BLOCK_SIZE); + + priv->last_update_bufflen = remain_len; + uadk_memcpy(priv->data, input_data, priv->last_update_bufflen); + + return UADK_HMAC_SUCCESS; +} + +static int uadk_hmac_update(struct hmac_priv_ctx *priv, const void *data, size_t data_len) +{ + if (!priv->data) { + fprintf(stderr, "failed to do digest update, data in CTX is NULL.\n"); + return UADK_HMAC_FAIL; + } + + priv->total_data_len += data_len; + + if (priv->last_update_bufflen + data_len <= HMAC_BLOCK_SIZE) { + uadk_memcpy(priv->data + priv->last_update_bufflen, data, data_len); + priv->last_update_bufflen += data_len; + return UADK_HMAC_SUCCESS; + } + + return uadk_hmac_update_inner(priv, data, data_len); +} + +static int uadk_hmac_final(struct hmac_priv_ctx *priv, unsigned char *digest) +{ + struct async_op op; + int ret; + + if (!priv->data) { + fprintf(stderr, "failed to do digest final, data in CTX is NULL.\n"); + return UADK_HMAC_FAIL; + } + + ret = uadk_hmac_ctx_init(priv); + if (!ret) + return UADK_HMAC_FAIL; + + priv->req.in = priv->data; + priv->req.out = priv->state == SEC_DIGEST_INIT ? digest : priv->out; + priv->req.in_bytes = priv->last_update_bufflen; + + uadk_digest_set_msg_state(priv, true); + uadk_fill_mac_buffer_len(priv, true); + + ret = async_setup_async_event_notification(&op); + if (unlikely(!ret)) { + fprintf(stderr, "failed to setup async event notification.\n"); + return UADK_HMAC_FAIL; + } + + if (!op.job) + ret = uadk_do_hmac_sync(priv); + else + ret = uadk_do_hmac_async(priv, &op); + + if (!ret) + goto clear; + + if (priv->state != SEC_DIGEST_INIT) + memcpy(digest, priv->req.out, priv->req.out_bytes); + + return UADK_HMAC_SUCCESS; + +clear: + async_clear_async_event_notification(); + return ret; +} + +static void *uadk_prov_hmac_dupctx(void *hctx) +{ + struct hmac_priv_ctx *dst_ctx, *src_ctx; + + if (!hctx) + return NULL; + + src_ctx = (struct hmac_priv_ctx *)hctx; + dst_ctx = OPENSSL_memdup(src_ctx, sizeof(struct hmac_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, HMAC_BLOCK_SIZE); + if (!dst_ctx->data) + goto free_ctx; + + return dst_ctx; + +free_data: + OPENSSL_clear_free(dst_ctx->data, HMAC_BLOCK_SIZE); +free_ctx: + OPENSSL_clear_free(dst_ctx, sizeof(*dst_ctx)); + return NULL; +} + +static void uadk_hmac_cleanup(struct hmac_priv_ctx *priv) +{ + if (priv->sess) + wd_digest_free_sess(priv->sess); + + if (priv->data) + OPENSSL_clear_free(priv->data, HMAC_BLOCK_SIZE); +} + +static void uadk_prov_hmac_freectx(void *hctx) +{ + struct hmac_priv_ctx *priv = (struct hmac_priv_ctx *)hctx; + + if (!hctx) { + fprintf(stderr, "the CTX to be free is NULL.\n"); + return; + } + + uadk_hmac_cleanup(priv); + OPENSSL_clear_free(priv, sizeof(*priv)); +} + +static int uadk_prov_hmac_setkey(struct hmac_priv_ctx *priv, + const unsigned char *key, size_t keylen) +{ + size_t padding; + + if (priv->key) + memset(priv->key, 0, MAX_KEY_LEN); + + if (keylen > priv->blk_size) + return uadk_prov_compute_key_hash(priv, key, keylen); + + padding = KEY_4BYTE_ALIGN(keylen); + memcpy(priv->key, key, keylen); + priv->keylen = padding; + + return UADK_HMAC_SUCCESS; +} + +static int uadk_prov_hmac_init(void *hctx, const unsigned char *key, + size_t keylen, const OSSL_PARAM params[]) +{ + struct hmac_priv_ctx *priv = (struct hmac_priv_ctx *)hctx; + int ret; + + if (!hctx) { + fprintf(stderr, "CTX is NULL.\n"); + return UADK_HMAC_FAIL; + } + + ret = uadk_prov_hmac_set_ctx_params(hctx, params); + if (unlikely(!ret)) + return UADK_HMAC_FAIL; + + ret = uadk_get_hmac_info(priv); + if (unlikely(!ret)) + return UADK_HMAC_FAIL; + + if (key) { + ret = uadk_prov_hmac_setkey(priv, key, keylen); + if (!ret) + return UADK_HMAC_FAIL; + } + + ret = uadk_prov_hmac_dev_init(priv); + if (unlikely(ret <= 0)) + return UADK_HMAC_FAIL; + + return UADK_HMAC_SUCCESS; +} + +static int uadk_prov_hmac_update(void *hctx, const unsigned char *data, size_t datalen) +{ + if (!hctx || !data) { + fprintf(stderr, "CTX or input data is NULL.\n"); + return UADK_HMAC_FAIL; + } + + return uadk_hmac_update((struct hmac_priv_ctx *)hctx, data, datalen); +} + +/* + * Note: + * The I<hctx> parameter contains a pointer to the provider side context. + * The digest should be written to I<*out> and the length of the digest to I<*outl>. + * The digest should not exceed I<outsz> bytes. + */ +static int uadk_prov_hmac_final(void *hctx, unsigned char *out, size_t *outl, + size_t outsize) +{ + struct hmac_priv_ctx *priv = (struct hmac_priv_ctx *)hctx; + int ret; + + if (!hctx) { + fprintf(stderr, "hmac CTX or output data is NULL.\n"); + return UADK_HMAC_FAIL; + } + + if (out && outsize > 0) { + ret = uadk_hmac_final(priv, out); + if (!ret) + return ret; + } + + if (outl) + *outl = priv->out_len; + + return UADK_HMAC_SUCCESS; +} + +void uadk_prov_destroy_hmac(void) +{ + pthread_mutex_lock(&hmac_mutex); + if (hprov.pid == getpid()) { + wd_digest_uninit2(); + hprov.pid = 0; + } + pthread_mutex_unlock(&hmac_mutex); +} + +static const OSSL_PARAM uadk_prov_hmac_known_gettable_ctx_params[] = { + OSSL_PARAM_size_t(OSSL_MAC_PARAM_SIZE, NULL), + OSSL_PARAM_size_t(OSSL_MAC_PARAM_BLOCK_SIZE, NULL), + OSSL_PARAM_END +}; + +static const OSSL_PARAM *uadk_prov_hmac_gettable_ctx_params(ossl_unused void *ctx, + ossl_unused void *provctx) +{ + return uadk_prov_hmac_known_gettable_ctx_params; +} + +static int uadk_prov_hmac_get_ctx_params(void *hctx, OSSL_PARAM params[]) +{ + struct hmac_priv_ctx *priv = (struct hmac_priv_ctx *)hctx; + OSSL_PARAM *p = NULL; + + if (!hctx) + return UADK_HMAC_FAIL; + + p = OSSL_PARAM_locate(params, OSSL_MAC_PARAM_SIZE); + if (p && !OSSL_PARAM_set_size_t(p, priv->out_len)) + return UADK_HMAC_FAIL; + + p = OSSL_PARAM_locate(params, OSSL_MAC_PARAM_BLOCK_SIZE); + if (p && !OSSL_PARAM_set_size_t(p, priv->blk_size)) + return UADK_HMAC_FAIL; + + return UADK_HMAC_SUCCESS; +} + +static const OSSL_PARAM uadk_prov_settable_ctx_params[] = { + OSSL_PARAM_utf8_string(OSSL_MAC_PARAM_DIGEST, NULL, 0), + OSSL_PARAM_octet_string(OSSL_MAC_PARAM_KEY, NULL, 0), + OSSL_PARAM_END +}; + +static const OSSL_PARAM *uadk_prov_hmac_settable_ctx_params(ossl_unused void *ctx, + ossl_unused void *provctx) +{ + return uadk_prov_settable_ctx_params; +} + +static void uadk_hmac_name_uppercase(char *str) +{ + size_t length = strlen(str); + + for (size_t i = 0; i < length; i++) + str[i] = toupper(str[i]); +} + +/* + * ALL parameters should be set before init(). + */ +static int uadk_prov_hmac_set_ctx_params(void *hctx, const OSSL_PARAM params[]) +{ + struct hmac_priv_ctx *priv = (struct hmac_priv_ctx *)hctx; + const OSSL_PARAM *p; + int ret; + + if (!params || !params->key) + return UADK_HMAC_SUCCESS; + + if (!hctx) + return UADK_HMAC_FAIL; + + p = OSSL_PARAM_locate_const(params, OSSL_ALG_PARAM_DIGEST); + if (p) { + if (p->data_type != OSSL_PARAM_UTF8_STRING || + strlen((char *)p->data) > ALG_NAME_SIZE - 1) + return UADK_HMAC_FAIL; + + /* + * For subsequent character string matching, no end flag is added, + * and the length will be within the value of ALG_NAME_SIZE. + */ + ret = snprintf(priv->alg_name, ALG_NAME_SIZE, "%s", p->data); + if (ret < 0) { + fprintf(stderr, "Invalid alg name %s.\n", p->data); + return UADK_HMAC_FAIL; + } + + uadk_hmac_name_uppercase(priv->alg_name); + } + + p = OSSL_PARAM_locate_const(params, OSSL_MAC_PARAM_KEY); + if (p) { + if (p->data_type != OSSL_PARAM_OCTET_STRING) + return UADK_HMAC_FAIL; + + if (!uadk_prov_hmac_setkey(priv, p->data, p->data_size)) + return UADK_HMAC_FAIL; + } + + return UADK_HMAC_SUCCESS; +} + +static void *uadk_prov_hmac_newctx(void *hctx) +{ + struct hmac_priv_ctx *ctx; + + ctx = OPENSSL_zalloc(sizeof(*ctx)); + if (!ctx) + return NULL; + + ctx->libctx = prov_libctx_of(hctx); + + ctx->data = OPENSSL_zalloc(HMAC_BLOCK_SIZE); + if (!ctx->data) { + OPENSSL_free(ctx); + return NULL; + } + + return ctx; +} + +const OSSL_DISPATCH uadk_hmac_functions[] = { + { OSSL_FUNC_MAC_NEWCTX, (void (*)(void))uadk_prov_hmac_newctx }, + { OSSL_FUNC_MAC_DUPCTX, (void (*)(void))uadk_prov_hmac_dupctx }, + { OSSL_FUNC_MAC_FREECTX, (void (*)(void))uadk_prov_hmac_freectx }, + { OSSL_FUNC_MAC_INIT, (void (*)(void))uadk_prov_hmac_init }, + { OSSL_FUNC_MAC_UPDATE, (void (*)(void))uadk_prov_hmac_update }, + { OSSL_FUNC_MAC_FINAL, (void (*)(void))uadk_prov_hmac_final }, + { OSSL_FUNC_MAC_GETTABLE_CTX_PARAMS, + (void (*)(void))uadk_prov_hmac_gettable_ctx_params }, + { OSSL_FUNC_MAC_GET_CTX_PARAMS, + (void (*)(void))uadk_prov_hmac_get_ctx_params }, + { OSSL_FUNC_MAC_SETTABLE_CTX_PARAMS, + (void (*)(void))uadk_prov_hmac_settable_ctx_params }, + { OSSL_FUNC_MAC_SET_CTX_PARAMS, + (void (*)(void))uadk_prov_hmac_set_ctx_params }, + { 0, NULL } +}; diff --git a/src/uadk_prov_init.c b/src/uadk_prov_init.c index b5588f2..c29500b 100644 --- a/src/uadk_prov_init.c +++ b/src/uadk_prov_init.c @@ -69,6 +69,12 @@ const OSSL_ALGORITHM uadk_prov_digests[] = { { NULL, NULL, NULL } }; +const OSSL_ALGORITHM uadk_prov_hmac[] = { + { "HMAC", UADK_DEFAULT_PROPERTIES, + uadk_hmac_functions, "uadk_provider hmac" }, + { NULL, NULL, NULL } +}; + const OSSL_ALGORITHM uadk_prov_ciphers_v2[] = { { "AES-128-CBC", UADK_DEFAULT_PROPERTIES, uadk_aes_128_cbc_functions, "uadk_provider aes-128-cbc" }, @@ -268,6 +274,8 @@ static const OSSL_ALGORITHM *uadk_query(void *provctx, int operation_id, if (!ver && uadk_get_sw_offload_state()) break; return uadk_prov_digests; + case OSSL_OP_MAC: + return uadk_prov_hmac; case OSSL_OP_CIPHER: ver = uadk_prov_cipher_version(); if (!ver && uadk_get_sw_offload_state()) @@ -324,6 +332,7 @@ static void uadk_teardown(void *provctx) } uadk_prov_destroy_digest(); + uadk_prov_destroy_hmac(); uadk_prov_destroy_cipher(); uadk_prov_destroy_aead(); uadk_prov_destroy_rsa(); -- 2.33.0

From: Chenghai Huang <huangchenghai2@huawei.com> When HW hmac processing failed, uadk_provider could switch to soft mac to keep the work success. When HMAC switches to software, if the new libctx is not used, the digest of hardware is used for software computing. For the uadk, hmac and digest are the same module. When any fault occurs, do not try to use hardware again. Signed-off-by: Chenghai Huang <huangchenghai2@huawei.com> Signed-off-by: JiangShui Yang <yangjiangshui@h-partners.com> --- src/uadk_prov_hmac.c | 333 +++++++++++++++++++++++++++++++++++++++---- 1 file changed, 307 insertions(+), 26 deletions(-) diff --git a/src/uadk_prov_hmac.c b/src/uadk_prov_hmac.c index 3c70c5d..3e57012 100644 --- a/src/uadk_prov_hmac.c +++ b/src/uadk_prov_hmac.c @@ -31,6 +31,7 @@ #include "uadk_prov.h" #include "uadk_utils.h" +#define UADK_DO_SOFT (-0xE0) #define UADK_HMAC_SUCCESS 1 #define UADK_HMAC_FAIL 0 @@ -41,8 +42,14 @@ #define MAX_KEY_LEN 144 #define HMAC_BLOCK_SIZE (512 * 1024) #define ALG_NAME_SIZE 128 +#define PARAMS_SIZE 2 #define KEY_4BYTE_ALIGN(keylen) ((keylen + 3) & ~3) +#define SW_SWITCH_PRINT_ENABLE(SW) (SW ? ", switch to soft hmac" : "") + +#define SM3_SMALL_PACKET_OFFLOAD_THRESHOLD_DEFAULT (512) +#define MD5_SMALL_PACKET_OFFLOAD_THRESHOLD_DEFAULT (8 * 1024) +#define SHA_SMALL_PACKET_OFFLOAD_THRESHOLD_DEFAULT (512) #define UADK_DIGEST_DEF_CTXS 1 #define UADK_DIGEST_OP_NUM 1 @@ -64,12 +71,17 @@ static pthread_mutex_t hmac_mutex = PTHREAD_MUTEX_INITIALIZER; struct hmac_priv_ctx { __u32 alg_id; __u32 state; + int switch_flag; size_t out_len; size_t blk_size; size_t keylen; size_t last_update_bufflen; size_t total_data_len; + size_t switch_threshold; OSSL_LIB_CTX *libctx; + OSSL_LIB_CTX *soft_libctx; + EVP_MAC_CTX *soft_ctx; + EVP_MAC *soft_md; handle_t sess; struct wd_digest_sess_setup setup; struct wd_digest_req req; @@ -83,23 +95,185 @@ struct hmac_priv_ctx { struct hmac_info { enum wd_digest_type alg; __u32 alg_id; + __u32 threshold; size_t out_len; size_t blk_size; const char ossl_alg_name[ALG_NAME_SIZE]; }; static struct hmac_info hmac_info_table[] = { - {WD_DIGEST_MD5, NID_md5, 16, 64, PROV_NAMES_MD5}, - {WD_DIGEST_SM3, NID_sm3, 32, 64, PROV_NAMES_SM3}, - {WD_DIGEST_SHA1, NID_sha1, 20, 64, PROV_NAMES_SHA1}, - {WD_DIGEST_SHA224, NID_sha224, 28, 64, PROV_NAMES_SHA2_224}, - {WD_DIGEST_SHA256, NID_sha256, 32, 64, PROV_NAMES_SHA2_256}, - {WD_DIGEST_SHA384, NID_sha384, 48, 64, PROV_NAMES_SHA2_384}, - {WD_DIGEST_SHA512, NID_sha512, 64, 128, PROV_NAMES_SHA2_512}, - {WD_DIGEST_SHA512_224, NID_sha512_224, 28, 128, PROV_NAMES_SHA2_512_224}, - {WD_DIGEST_SHA512_256, NID_sha512_256, 32, 128, PROV_NAMES_SHA2_512_256} + {WD_DIGEST_MD5, NID_md5, MD5_SMALL_PACKET_OFFLOAD_THRESHOLD_DEFAULT, + 16, 64, PROV_NAMES_MD5}, + {WD_DIGEST_SM3, NID_sm3, SM3_SMALL_PACKET_OFFLOAD_THRESHOLD_DEFAULT, + 32, 64, PROV_NAMES_SM3}, + {WD_DIGEST_SHA1, NID_sha1, SHA_SMALL_PACKET_OFFLOAD_THRESHOLD_DEFAULT, + 20, 64, PROV_NAMES_SHA1}, + {WD_DIGEST_SHA224, NID_sha224, SHA_SMALL_PACKET_OFFLOAD_THRESHOLD_DEFAULT, + 28, 64, PROV_NAMES_SHA2_224}, + {WD_DIGEST_SHA256, NID_sha256, SHA_SMALL_PACKET_OFFLOAD_THRESHOLD_DEFAULT, + 32, 64, PROV_NAMES_SHA2_256}, + {WD_DIGEST_SHA384, NID_sha384, SHA_SMALL_PACKET_OFFLOAD_THRESHOLD_DEFAULT, + 48, 64, PROV_NAMES_SHA2_384}, + {WD_DIGEST_SHA512, NID_sha512, SHA_SMALL_PACKET_OFFLOAD_THRESHOLD_DEFAULT, + 64, 128, PROV_NAMES_SHA2_512}, + {WD_DIGEST_SHA512_224, NID_sha512_224, SHA_SMALL_PACKET_OFFLOAD_THRESHOLD_DEFAULT, + 28, 128, PROV_NAMES_SHA2_512_224}, + {WD_DIGEST_SHA512_256, NID_sha512_256, SHA_SMALL_PACKET_OFFLOAD_THRESHOLD_DEFAULT, + 32, 128, PROV_NAMES_SHA2_512_256} }; +static int uadk_create_hmac_soft_ctx(struct hmac_priv_ctx *priv) +{ + if (priv->soft_md) + return UADK_HMAC_SUCCESS; + + priv->soft_libctx = OSSL_LIB_CTX_new(); + if (!priv->soft_libctx) { + fprintf(stderr, "new soft libctx failed.\n"); + return UADK_HMAC_FAIL; + } + + switch (priv->alg_id) { + case NID_md5: + case NID_sm3: + case NID_sha1: + case NID_sha224: + case NID_sha256: + case NID_sha384: + case NID_sha512: + case NID_sha512_224: + case NID_sha512_256: + priv->soft_md = EVP_MAC_fetch(priv->soft_libctx, "HMAC", NULL); + break; + default: + break; + } + + if (unlikely(!priv->soft_md)) { + fprintf(stderr, "hmac soft fetch failed.\n"); + goto free_libctx; + } + + priv->soft_ctx = EVP_MAC_CTX_new(priv->soft_md); + if (!priv->soft_ctx) { + fprintf(stderr, "hmac soft new ctx failed.\n"); + goto free_mac_md; + } + + return UADK_HMAC_SUCCESS; + +free_mac_md: + EVP_MAC_free(priv->soft_md); + priv->soft_md = NULL; +free_libctx: + OSSL_LIB_CTX_free(priv->soft_libctx); + priv->soft_libctx = NULL; + + return UADK_HMAC_FAIL; +} + +static int uadk_hmac_soft_init(struct hmac_priv_ctx *priv) +{ + OSSL_PARAM params[PARAMS_SIZE]; + OSSL_PARAM *p = params; + int ret; + + if (!priv->soft_md) + return UADK_HMAC_FAIL; + + /* The underlying digest to be used */ + *p++ = OSSL_PARAM_construct_utf8_string(OSSL_MAC_PARAM_DIGEST, priv->alg_name, + sizeof(priv->alg_name)); + *p = OSSL_PARAM_construct_end(); + + ret = EVP_MAC_init(priv->soft_ctx, priv->key, priv->keylen, params); + if (!ret) { + fprintf(stderr, "do soft hmac init failed!\n"); + return UADK_HMAC_FAIL; + } + + priv->switch_flag = UADK_DO_SOFT; + + return ret; +} + +static int uadk_hmac_soft_update(struct hmac_priv_ctx *priv, + const void *data, size_t len) +{ + int ret; + + if (!priv->soft_md) + return UADK_HMAC_FAIL; + + ret = EVP_MAC_update(priv->soft_ctx, data, len); + if (!ret) + fprintf(stderr, "do soft hmac update failed!\n"); + + return ret; +} + +static int uadk_hmac_soft_final(struct hmac_priv_ctx *priv, unsigned char *out) +{ + size_t hmac_length; + int ret; + + if (!priv->soft_md) + return UADK_HMAC_FAIL; + + ret = EVP_MAC_final(priv->soft_ctx, out, &hmac_length, priv->out_len); + if (!ret) + fprintf(stderr, "do soft hmac final failed!\n"); + + return ret; +} + +static void hmac_soft_cleanup(struct hmac_priv_ctx *priv) +{ + if (priv->soft_ctx) { + EVP_MAC_CTX_free(priv->soft_ctx); + priv->soft_ctx = NULL; + } + + if (priv->soft_md) { + EVP_MAC_free(priv->soft_md); + priv->soft_md = NULL; + } + + if (priv->soft_libctx) { + OSSL_LIB_CTX_free(priv->soft_libctx); + priv->soft_libctx = NULL; + } + + priv->switch_flag = 0; +} + +static int uadk_hmac_soft_work(struct hmac_priv_ctx *priv, int inl, + unsigned char *out) +{ + int ret; + + if (!priv->soft_md) + return UADK_HMAC_FAIL; + + if (!priv->switch_flag) { + ret = uadk_hmac_soft_init(priv); + if (unlikely(!ret)) + return UADK_HMAC_FAIL; + } + + if (inl) { + ret = uadk_hmac_soft_update(priv, priv->data, inl); + if (unlikely(!ret)) + goto out; + } + + ret = uadk_hmac_soft_final(priv, out); + +out: + hmac_soft_cleanup(priv); + return ret; +} + static OSSL_FUNC_mac_newctx_fn uadk_prov_hmac_newctx; static OSSL_FUNC_mac_dupctx_fn uadk_prov_hmac_dupctx; static OSSL_FUNC_mac_freectx_fn uadk_prov_hmac_freectx; @@ -180,6 +354,7 @@ static int uadk_get_hmac_info(struct hmac_priv_ctx *priv) priv->setup.mode = WD_DIGEST_HMAC; priv->req.out_buf_bytes = MAX_DIGEST_LENGTH; priv->req.out_bytes = hmac_info_table[i].out_len; + priv->switch_threshold = hmac_info_table[i].threshold; return UADK_HMAC_SUCCESS; } @@ -310,9 +485,15 @@ static int uadk_hmac_ctx_init(struct hmac_priv_ctx *priv) struct sched_params params = {0}; int ret; + if (enable_sw_offload) + uadk_create_hmac_soft_ctx(priv); + ret = uadk_prov_hmac_dev_init(priv); - if (unlikely(ret <= 0)) - return UADK_HMAC_FAIL; + if (unlikely(ret <= 0)) { + fprintf(stderr, "uadk failed to initialize hmac%s.\n", + SW_SWITCH_PRINT_ENABLE(enable_sw_offload)); + goto soft_init; + } /* Use the default numa parameters */ params.numa_id = -1; @@ -321,13 +502,15 @@ static int uadk_hmac_ctx_init(struct hmac_priv_ctx *priv) if (!priv->sess) { priv->sess = wd_digest_alloc_sess(&priv->setup); if (unlikely(!priv->sess)) { - fprintf(stderr, "uadk failed to alloc hmac sess.\n"); - return UADK_HMAC_FAIL; + fprintf(stderr, "uadk failed to alloc hmac sess%s.\n", + SW_SWITCH_PRINT_ENABLE(enable_sw_offload)); + goto soft_init; } ret = wd_digest_set_key(priv->sess, priv->key, priv->keylen); if (ret) { - fprintf(stderr, "uadk failed to set hmac key!\n"); + fprintf(stderr, "uadk failed to set hmac key%s.\n", + SW_SWITCH_PRINT_ENABLE(enable_sw_offload)); goto free_sess; } } @@ -337,7 +520,9 @@ static int uadk_hmac_ctx_init(struct hmac_priv_ctx *priv) free_sess: wd_digest_free_sess(priv->sess); priv->sess = 0; - return UADK_HMAC_FAIL; + +soft_init: + return uadk_hmac_soft_init(priv); } static void uadk_hmac_async_cb(struct wd_digest_req *req, void *data) @@ -364,6 +549,11 @@ static int uadk_do_hmac_sync(struct hmac_priv_ctx *priv) { int ret; + if (priv->soft_md && + priv->req.in_bytes <= priv->switch_threshold && + priv->state == SEC_DIGEST_INIT) + return UADK_HMAC_FAIL; + ret = wd_do_digest_sync(priv->sess, &priv->req); if (ret) { fprintf(stderr, "do sec hmac sync failed.\n"); @@ -379,6 +569,11 @@ static int uadk_do_hmac_async(struct hmac_priv_ctx *priv, struct async_op *op) int idx, ret; int cnt = 0; + if (unlikely(priv->switch_flag == UADK_DO_SOFT)) { + fprintf(stderr, "soft switching is not supported in asynchronous mode.\n"); + return UADK_HMAC_FAIL; + } + cb_param.op = op; cb_param.priv = &priv->req; priv->req.cb = (void *)uadk_hmac_async_cb; @@ -461,8 +656,9 @@ static int uadk_hmac_update_inner(struct hmac_priv_ctx *priv, const void *data, ret = uadk_do_hmac_sync(priv); if (!ret) { - fprintf(stderr, "do sec digest update failed.\n"); - return UADK_HMAC_FAIL; + fprintf(stderr, "do sec hmac update failed%s.\n", + SW_SWITCH_PRINT_ENABLE(enable_sw_offload)); + goto do_soft_hmac; } remain_len -= processing_len; @@ -473,6 +669,39 @@ static int uadk_hmac_update_inner(struct hmac_priv_ctx *priv, const void *data, uadk_memcpy(priv->data, input_data, priv->last_update_bufflen); return UADK_HMAC_SUCCESS; + +do_soft_hmac: + if (priv->state == SEC_DIGEST_FIRST_UPDATING) { + ret = uadk_hmac_soft_init(priv); + if (!ret) + return ret; + + /* + * If the hardware fails to process the data in the cache, + * the software computing needs to finish the cached data first. + */ + if (processing_len < HMAC_BLOCK_SIZE) { + ret = uadk_hmac_soft_update(priv, priv->data, HMAC_BLOCK_SIZE); + if (!ret) + goto err_out; + + remain_len -= processing_len; + input_data += processing_len; + } + + ret = uadk_hmac_soft_update(priv, input_data, remain_len); + if (!ret) + goto err_out; + + /* the soft ctx will be free in the final stage. */ + return ret; + } + + return UADK_HMAC_FAIL; + +err_out: + hmac_soft_cleanup(priv); + return ret; } static int uadk_hmac_update(struct hmac_priv_ctx *priv, const void *data, size_t data_len) @@ -482,6 +711,9 @@ static int uadk_hmac_update(struct hmac_priv_ctx *priv, const void *data, size_t return UADK_HMAC_FAIL; } + if (unlikely(priv->switch_flag == UADK_DO_SOFT)) + goto soft_update; + priv->total_data_len += data_len; if (priv->last_update_bufflen + data_len <= HMAC_BLOCK_SIZE) { @@ -491,6 +723,9 @@ static int uadk_hmac_update(struct hmac_priv_ctx *priv, const void *data, size_t } return uadk_hmac_update_inner(priv, data, data_len); + +soft_update: + return uadk_hmac_soft_update(priv, data, data_len); } static int uadk_hmac_final(struct hmac_priv_ctx *priv, unsigned char *digest) @@ -503,9 +738,12 @@ static int uadk_hmac_final(struct hmac_priv_ctx *priv, unsigned char *digest) return UADK_HMAC_FAIL; } - ret = uadk_hmac_ctx_init(priv); - if (!ret) - return UADK_HMAC_FAIL; + /* It dose not need to be initialized again if the software calculation is applied. */ + if (priv->switch_flag != UADK_DO_SOFT) { + ret = uadk_hmac_ctx_init(priv); + if (!ret) + return UADK_HMAC_FAIL; + } priv->req.in = priv->data; priv->req.out = priv->state == SEC_DIGEST_INIT ? digest : priv->out; @@ -520,19 +758,37 @@ static int uadk_hmac_final(struct hmac_priv_ctx *priv, unsigned char *digest) return UADK_HMAC_FAIL; } - if (!op.job) + if (!op.job) { + /* Synchronous, only the synchronous mode supports soft computing */ + if (unlikely(priv->switch_flag == UADK_DO_SOFT)) { + ret = uadk_hmac_soft_final(priv, digest); + hmac_soft_cleanup(priv); + goto clear; + } + ret = uadk_do_hmac_sync(priv); - else + if (!ret) + goto do_hmac_err; + } else { ret = uadk_do_hmac_async(priv, &op); - - if (!ret) - goto clear; + if (!ret) + goto clear; + } if (priv->state != SEC_DIGEST_INIT) memcpy(digest, priv->req.out, priv->req.out_bytes); return UADK_HMAC_SUCCESS; +do_hmac_err: + if (priv->state == SEC_DIGEST_INIT) { + fprintf(stderr, "do sec digest final failed%s.\n", + SW_SWITCH_PRINT_ENABLE(enable_sw_offload)); + ret = uadk_hmac_soft_work(priv, priv->req.in_bytes, digest); + } else { + ret = UADK_HMAC_FAIL; + fprintf(stderr, "do sec digest final failed.\n"); + } clear: async_clear_async_event_notification(); return ret; @@ -541,6 +797,7 @@ clear: static void *uadk_prov_hmac_dupctx(void *hctx) { struct hmac_priv_ctx *dst_ctx, *src_ctx; + int ret; if (!hctx) return NULL; @@ -569,8 +826,23 @@ static void *uadk_prov_hmac_dupctx(void *hctx) if (!dst_ctx->data) goto free_ctx; + if (dst_ctx->soft_ctx) { + dst_ctx->soft_libctx = NULL; + dst_ctx->soft_ctx = EVP_MAC_CTX_dup(src_ctx->soft_ctx); + if (!dst_ctx->soft_ctx) { + fprintf(stderr, "create soft_ctx failed in ctx copy.\n"); + goto free_data; + } + + ret = EVP_MAC_up_ref(dst_ctx->soft_md); + if (!ret) + goto free_dup; + } + return dst_ctx; +free_dup: + EVP_MAC_CTX_free(dst_ctx->soft_ctx); free_data: OPENSSL_clear_free(dst_ctx->data, HMAC_BLOCK_SIZE); free_ctx: @@ -596,6 +868,7 @@ static void uadk_prov_hmac_freectx(void *hctx) return; } + hmac_soft_cleanup(priv); uadk_hmac_cleanup(priv); OPENSSL_clear_free(priv, sizeof(*priv)); } @@ -637,6 +910,9 @@ static int uadk_prov_hmac_init(void *hctx, const unsigned char *key, if (unlikely(!ret)) return UADK_HMAC_FAIL; + if (enable_sw_offload) + uadk_create_hmac_soft_ctx(hctx); + if (key) { ret = uadk_prov_hmac_setkey(priv, key, keylen); if (!ret) @@ -645,9 +921,14 @@ static int uadk_prov_hmac_init(void *hctx, const unsigned char *key, ret = uadk_prov_hmac_dev_init(priv); if (unlikely(ret <= 0)) - return UADK_HMAC_FAIL; + goto soft_init; return UADK_HMAC_SUCCESS; + +soft_init: + fprintf(stderr, "uadk failed to initialize dev%s.\n", + SW_SWITCH_PRINT_ENABLE(enable_sw_offload)); + return uadk_hmac_soft_init(priv); } static int uadk_prov_hmac_update(void *hctx, const unsigned char *data, size_t datalen) -- 2.33.0

From: lizhi <lizhi206@huawei.com> When hardware failures occur, or in cases of insufficient queue resources or unsupported algorithm specifications, the uadk provider can switch dh to openssl soft computation. Signed-off-by: lizhi <lizhi206@huawei.com> Signed-off-by: JiangShui Yang <yangjiangshui@h-partners.com> --- src/uadk_prov_dh.c | 86 ++++++++++++++++++++++++++++++++++++++-------- 1 file changed, 71 insertions(+), 15 deletions(-) diff --git a/src/uadk_prov_dh.c b/src/uadk_prov_dh.c index f6262d4..c75c386 100644 --- a/src/uadk_prov_dh.c +++ b/src/uadk_prov_dh.c @@ -60,6 +60,28 @@ UADK_PKEY_KEYMGMT_DESCR(dh, DH); UADK_PKEY_KEYEXCH_DESCR(dh, DH); static pthread_mutex_t dh_mutex = PTHREAD_MUTEX_INITIALIZER; +static pthread_mutex_t dh_default_mutex = PTHREAD_MUTEX_INITIALIZER; +static UADK_PKEY_KEYEXCH get_default_dh_keyexch(void) +{ + static UADK_PKEY_KEYEXCH s_keyexch; + static int initilazed; + + pthread_mutex_lock(&dh_default_mutex); + if (!initilazed) { + UADK_PKEY_KEYEXCH *keyexch = + (UADK_PKEY_KEYEXCH *)EVP_KEYEXCH_fetch(NULL, "dh", "provider=default"); + if (keyexch) { + s_keyexch = *keyexch; + EVP_KEYEXCH_free((EVP_KEYEXCH *)keyexch); + initilazed = 1; + } else { + fprintf(stderr, "failed to EVP_KEYEXCH_fetch default dh provider\n"); + } + } + pthread_mutex_unlock(&dh_default_mutex); + + return s_keyexch; +} struct dh_st { /* @@ -705,7 +727,7 @@ static int uadk_prov_dh_prepare_data(const BIGNUM *g, DH *dh, struct uadk_dh_ses ret = check_dh_bit_useful(bits); if (ret == UADK_P_FAIL) { fprintf(stderr, "invalid: dh%u is not supported by uadk provider\n", bits); - return UADK_P_FAIL; + return UADK_DO_SOFT; } *dh_sess = uadk_prov_dh_new_session(dh, bits, is_g2); @@ -916,7 +938,7 @@ static int uadk_prov_dh_generate_key(DH *dh) ret = uadk_prov_dh_init(); if (ret) { fprintf(stderr, "failed to init dh\n"); - return UADK_P_FAIL; + return UADK_DO_SOFT; } uadk_DH_get0_pqg(dh, &p, NULL, &g); @@ -927,7 +949,7 @@ static int uadk_prov_dh_generate_key(DH *dh) /* Get session and prepare private key */ ret = uadk_prov_dh_prepare_data(g, dh, &dh_sess, &prikey); - if (ret == UADK_P_FAIL) { + if (ret != UADK_P_SUCCESS) { fprintf(stderr, "failed to prepare dh data\n"); return ret; } @@ -939,8 +961,9 @@ static int uadk_prov_dh_generate_key(DH *dh) } ret = uadk_prov_dh_do_crypto(dh_sess); - if (ret == UADK_P_FAIL) { + if (ret != UADK_P_SUCCESS) { fprintf(stderr, "failed to generate DH key\n"); + ret = UADK_DO_SOFT; goto free_req; } @@ -964,7 +987,7 @@ free_req: free_data: uadk_prov_dh_free_prepare_data(dh_sess, prikey); - return UADK_P_FAIL; + return ret; } static int dh_gencb(int p, int n, BN_GENCB *cb) @@ -1081,7 +1104,7 @@ static DH *uadk_prov_dh_gen_params_with_group(PROV_DH_KEYMGMT_CTX *gctx, FFC_PAR fprintf(stderr, "failed to get dh from libctx\n"); return NULL; } - + dh->meth = DH_get_default_method(); ossl_ffc_named_group_set(&dh->params, group); dh->params.nid = ossl_ffc_named_group_get_uid(group); dh->dirty_cnt++; @@ -1094,6 +1117,8 @@ static DH *uadk_prov_dh_gen_params_with_group(PROV_DH_KEYMGMT_CTX *gctx, FFC_PAR return NULL; } + dh->meth = DH_get_default_method(); + return dh; } @@ -1234,6 +1259,15 @@ static void uadk_prov_dh_free_params(DH *dh, BN_GENCB *gencb) uadk_prov_dh_free_params_cb(gencb); } +static void *uadk_dh_sw_gen(void *genctx, OSSL_CALLBACK *cb, void *cb_params) +{ + if (!enable_sw_offload || !get_default_dh_keymgmt().gen) + return NULL; + + fprintf(stderr, "switch to openssl software calculation in dh generation.\n"); + return get_default_dh_keymgmt().gen(genctx, cb, cb_params); +} + static void *uadk_keymgmt_dh_gen(void *genctx, OSSL_CALLBACK *cb, void *cb_params) { PROV_DH_KEYMGMT_CTX *gctx = (PROV_DH_KEYMGMT_CTX *)genctx; @@ -1256,9 +1290,10 @@ static void *uadk_keymgmt_dh_gen(void *genctx, OSSL_CALLBACK *cb, void *cb_param gctx->gen_type = DH_PARAMGEN_TYPE_GROUP; dh = uadk_prov_dh_gen_params(gctx, &ffc, cb, cb_params, gencb); - if (dh == NULL || ffc == NULL) - return NULL; - + if (dh == NULL || ffc == NULL) { + ret = UADK_DO_SOFT; + goto free_gen_params; + } /* DH key generation */ if ((gctx->selection & OSSL_KEYMGMT_SELECT_KEYPAIR) != 0) { if (ffc->p == NULL || ffc->g == NULL) { @@ -1273,7 +1308,7 @@ static void *uadk_keymgmt_dh_gen(void *genctx, OSSL_CALLBACK *cb, void *cb_param gctx->gen_type == DH_PARAMGEN_TYPE_FIPS_186_2); ret = uadk_prov_dh_generate_key(dh); - if (ret == UADK_P_FAIL) { + if (ret != UADK_P_SUCCESS) { fprintf(stderr, "failed to do dh generation key\n"); goto free_gen_params; } @@ -1287,6 +1322,9 @@ static void *uadk_keymgmt_dh_gen(void *genctx, OSSL_CALLBACK *cb, void *cb_param free_gen_params: uadk_prov_dh_free_params(dh, gencb); + + if (ret == UADK_DO_SOFT) + return uadk_dh_sw_gen(genctx, cb, cb_params); return NULL; } @@ -1525,11 +1563,11 @@ static int uadk_dh_compute_key(unsigned char *key, const BIGNUM *pubkey, DH *dh) ret = uadk_prov_dh_init(); if (ret) { fprintf(stderr, "failed to init\n"); - return UADK_P_FAIL; + return UADK_DO_SOFT; } ret = uadk_prov_dh_prepare_data(g, dh, &dh_sess, &prikey); - if (ret == UADK_P_FAIL) { + if (ret != UADK_P_SUCCESS) { fprintf(stderr, "failed to prepare dh data\n"); return ret; } @@ -1541,8 +1579,9 @@ static int uadk_dh_compute_key(unsigned char *key, const BIGNUM *pubkey, DH *dh) } ret = uadk_prov_dh_do_crypto(dh_sess); - if (ret == UADK_P_FAIL) { + if (ret != UADK_P_SUCCESS) { fprintf(stderr, "failed to generate DH shared key\n"); + ret = UADK_DO_SOFT; goto free_req; } @@ -1712,12 +1751,14 @@ static int uadk_prov_dh_X9_42_kdf_derive(PROV_DH_KEYEXCH_CTX *pdhctx, unsigned c return UADK_P_FAIL; } - if (uadk_prov_dh_plain_derive(pdhctx, stmp, &stmplen, stmplen, USE_PAD) == UADK_P_FAIL) + ret = uadk_prov_dh_plain_derive(pdhctx, stmp, &stmplen, stmplen, USE_PAD); + if (ret != UADK_P_SUCCESS) goto end; /* Do KDF stuff */ if (pdhctx->kdf_type == PROV_DH_KDF_X9_42_ASN1) { if (ossl_dh_kdf_X9_42_asn1(secret, pdhctx, stmp, stmplen, NULL) == UADK_P_FAIL) { + ret = UADK_P_FAIL; fprintf(stderr, "failed to do ossl_dh_kdf_X9_42_asn1\n"); goto end; } @@ -1732,6 +1773,16 @@ end: return ret; } +static int uadk_dh_sw_derive(void *dhctx, unsigned char *secret, + size_t *psecretlen, size_t outlen) +{ + if (!enable_sw_offload || !get_default_dh_keyexch().derive) + return UADK_P_FAIL; + + fprintf(stderr, "switch to openssl software calculation in dh derivation.\n"); + return get_default_dh_keyexch().derive(dhctx, secret, psecretlen, outlen); +} + static int uadk_keyexch_dh_derive(void *dhctx, unsigned char *secret, size_t *psecretlen, size_t outlen) { @@ -1752,10 +1803,15 @@ static int uadk_keyexch_dh_derive(void *dhctx, unsigned char *secret, break; default: fprintf(stderr, "invalid: unsupport kdf type\n"); + ret = UADK_DO_SOFT; break; } - return ret; + if (ret == UADK_P_SUCCESS) + return UADK_P_SUCCESS; + if (ret == UADK_DO_SOFT) + return uadk_dh_sw_derive(dhctx, secret, psecretlen, outlen); + return UADK_P_FAIL; } static void *uadk_keyexch_dh_dupctx(void *dhctx) -- 2.33.0

From: lizhi <lizhi206@huawei.com> When hardware failures occur, or in cases of insufficient queue resources or unsupported algorithm specifications, the uadk provider can switch rsa to openssl soft computation. Signed-off-by: lizhi <lizhi206@huawei.com> Signed-off-by: JiangShui Yang <yangjiangshui@h-partners.com> --- src/uadk_prov_rsa.c | 180 ++++++++++++++++++++++++++------------------ 1 file changed, 105 insertions(+), 75 deletions(-) diff --git a/src/uadk_prov_rsa.c b/src/uadk_prov_rsa.c index 8f7d734..65e78c3 100644 --- a/src/uadk_prov_rsa.c +++ b/src/uadk_prov_rsa.c @@ -62,7 +62,6 @@ #define GENCB_NEXT 2 #define GENCB_RETRY 3 #define PRIME_CHECK_BIT_NUM 4 -#define SOFT_SWITCH 0 UADK_PKEY_KEYMGMT_DESCR(rsa, RSA); UADK_PKEY_SIGNATURE_DESCR(rsa, RSA); @@ -284,11 +283,14 @@ enum { MAX_CODE, }; +static pthread_mutex_t sig_mutex = PTHREAD_MUTEX_INITIALIZER; +static pthread_mutex_t asym_mutex = PTHREAD_MUTEX_INITIALIZER; + static UADK_PKEY_SIGNATURE get_default_rsa_signature(void) { static UADK_PKEY_SIGNATURE s_signature; static int initilazed; - + pthread_mutex_lock(&sig_mutex); if (!initilazed) { UADK_PKEY_SIGNATURE *signature = (UADK_PKEY_SIGNATURE *)EVP_SIGNATURE_fetch(NULL, "RSA", "provider=default"); @@ -301,6 +303,7 @@ static UADK_PKEY_SIGNATURE get_default_rsa_signature(void) fprintf(stderr, "failed to EVP_SIGNATURE_fetch default RSA provider\n"); } } + pthread_mutex_unlock(&sig_mutex); return s_signature; } @@ -308,7 +311,7 @@ static UADK_PKEY_ASYM_CIPHER get_default_rsa_asym_cipher(void) { static UADK_PKEY_ASYM_CIPHER s_asym_cipher; static int initilazed; - + pthread_mutex_lock(&asym_mutex); if (!initilazed) { UADK_PKEY_ASYM_CIPHER *asym_cipher = (UADK_PKEY_ASYM_CIPHER *)EVP_ASYM_CIPHER_fetch(NULL, "RSA", @@ -322,6 +325,7 @@ static UADK_PKEY_ASYM_CIPHER get_default_rsa_asym_cipher(void) fprintf(stderr, "failed to EVP_ASYM_CIPHER_fetch default RSA provider\n"); } } + pthread_mutex_unlock(&asym_mutex); return s_asym_cipher; } @@ -2001,6 +2005,17 @@ static int uadk_signature_rsa_verify_init(void *vprsactx, void *vrsa, return uadk_rsa_init(vprsactx, vrsa, params, EVP_PKEY_OP_VERIFY); } +static int uadk_rsa_sw_verify(void *vprsactx, const unsigned char *sig, + size_t siglen, const unsigned char *tbs, + size_t tbslen) +{ + if (!enable_sw_offload || !get_default_rsa_signature().verify) + return UADK_E_FAIL; + + fprintf(stderr, "switch to openssl software calculation in verifaction.\n"); + return get_default_rsa_signature().verify(vprsactx, sig, siglen, tbs, tbslen); +} + static int uadk_signature_rsa_verify(void *vprsactx, const unsigned char *sig, size_t siglen, const unsigned char *tbs, size_t tbslen) @@ -2008,10 +2023,10 @@ static int uadk_signature_rsa_verify(void *vprsactx, const unsigned char *sig, PROV_RSA_SIG_CTX *priv = (PROV_RSA_SIG_CTX *)vprsactx; size_t rslen = 0; - if (priv->soft && SOFT_SWITCH) - goto soft; - else if (priv->soft && !SOFT_SWITCH) - return UADK_E_FAIL; + if (priv->soft) { + rslen = UADK_DO_SOFT; + goto exe_soft; + } /* todo call public_verify */ if (priv->md != NULL) { @@ -2021,12 +2036,8 @@ static int uadk_signature_rsa_verify(void *vprsactx, const unsigned char *sig, return UADK_E_FAIL; rslen = uadk_prov_rsa_public_verify(siglen, sig, priv->tbuf, priv->rsa, priv->pad_mode); - if (rslen == UADK_DO_SOFT || rslen == UADK_E_FAIL) { - if (rslen == UADK_DO_SOFT && SOFT_SWITCH) - goto soft; - else - return UADK_E_FAIL; - } + if (rslen == UADK_DO_SOFT || rslen == UADK_E_FAIL) + goto exe_soft; } if ((rslen != tbslen) || memcmp(tbs, priv->tbuf, rslen)) @@ -2034,12 +2045,21 @@ static int uadk_signature_rsa_verify(void *vprsactx, const unsigned char *sig, return UADK_E_SUCCESS; -soft: - fprintf(stderr, "switch to execute openssl software calculation.\n"); - if (!get_default_rsa_signature().verify) +exe_soft: + if (rslen == UADK_DO_SOFT) + return uadk_rsa_sw_verify(vprsactx, sig, siglen, tbs, tbslen); + return UADK_E_FAIL; +} + +static int uadk_rsa_sw_sign(void *vprsactx, unsigned char *sig, + size_t *siglen, size_t sigsize, + const unsigned char *tbs, size_t tbslen) +{ + if (!enable_sw_offload || !get_default_rsa_signature().sign) return UADK_E_FAIL; - return get_default_rsa_signature().verify(vprsactx, sig, siglen, tbs, tbslen); + fprintf(stderr, "switch to openssl software calculation in rsa signature.\n"); + return get_default_rsa_signature().sign(vprsactx, sig, siglen, sigsize, tbs, tbslen); } static int uadk_signature_rsa_sign(void *vprsactx, unsigned char *sig, @@ -2050,10 +2070,10 @@ static int uadk_signature_rsa_sign(void *vprsactx, unsigned char *sig, size_t rsasize = uadk_rsa_size(priv->rsa); int ret; - if (priv->soft && SOFT_SWITCH) - goto soft; - else if (priv->soft && !SOFT_SWITCH) - return UADK_E_FAIL; + if (priv->soft) { + ret = UADK_DO_SOFT; + goto exe_soft; + } if (sig == NULL) { *siglen = rsasize; @@ -2067,12 +2087,8 @@ static int uadk_signature_rsa_sign(void *vprsactx, unsigned char *sig, } ret = uadk_prov_rsa_private_sign(tbslen, tbs, sig, priv->rsa, priv->pad_mode); - if (ret == UADK_DO_SOFT || ret == UADK_E_FAIL) { - if (ret == UADK_DO_SOFT && SOFT_SWITCH) - goto soft; - else - return UADK_E_FAIL; - } + if (ret == UADK_DO_SOFT || ret == UADK_E_FAIL) + goto exe_soft; if (ret < 0) return ret; @@ -2080,12 +2096,10 @@ static int uadk_signature_rsa_sign(void *vprsactx, unsigned char *sig, *siglen = ret; return UADK_E_SUCCESS; -soft: - fprintf(stderr, "switch to execute openssl software calculation.\n"); - if (!get_default_rsa_signature().sign) - return UADK_E_FAIL; - - return get_default_rsa_signature().sign(vprsactx, sig, siglen, sigsize, tbs, tbslen); +exe_soft: + if (ret == UADK_DO_SOFT) + return uadk_rsa_sw_sign(vprsactx, sig, siglen, sigsize, tbs, tbslen); + return UADK_E_FAIL; } static int uadk_signature_rsa_sign_init(void *vprsactx, void *vrsa, const OSSL_PARAM params[]) @@ -2355,6 +2369,17 @@ static int uadk_asym_cipher_rsa_decrypt_init(void *vprsactx, void *vrsa, return uadk_rsa_asym_init(vprsactx, vrsa, params, EVP_PKEY_OP_DECRYPT); } +static int uadk_rsa_sw_encrypt(void *vprsactx, unsigned char *out, + size_t *outlen, size_t outsize, + const unsigned char *in, size_t inlen) +{ + if (!enable_sw_offload || !get_default_rsa_asym_cipher().encrypt) + return UADK_E_FAIL; + + fprintf(stderr, "switch to openssl software calculation in rsa encryption.\n"); + return get_default_rsa_asym_cipher().encrypt(vprsactx, out, outlen, outsize, in, inlen); +} + static int uadk_asym_cipher_rsa_encrypt(void *vprsactx, unsigned char *out, size_t *outlen, size_t outsize, const unsigned char *in, size_t inlen) @@ -2363,10 +2388,10 @@ static int uadk_asym_cipher_rsa_encrypt(void *vprsactx, unsigned char *out, size_t len; int ret; - if (priv->soft && SOFT_SWITCH) - goto soft; - else if (priv->soft && !SOFT_SWITCH) - return UADK_E_FAIL; + if (priv->soft) { + ret = UADK_DO_SOFT; + goto exe_soft; + } if (out == NULL) { len = uadk_rsa_size(priv->rsa); @@ -2379,22 +2404,27 @@ static int uadk_asym_cipher_rsa_encrypt(void *vprsactx, unsigned char *out, } ret = uadk_prov_rsa_public_encrypt(inlen, in, out, priv->rsa, priv->pad_mode); - if (ret == UADK_DO_SOFT || ret == UADK_E_FAIL) { - if (ret == UADK_DO_SOFT && SOFT_SWITCH) - goto soft; - else - return UADK_E_FAIL; - } + if (ret == UADK_DO_SOFT || ret == UADK_E_FAIL) + goto exe_soft; *outlen = ret; return UADK_E_SUCCESS; -soft: - fprintf(stderr, "switch to execute openssl software calculation.\n"); - if (!get_default_rsa_asym_cipher().encrypt) +exe_soft: + if (ret == UADK_DO_SOFT) + return uadk_rsa_sw_encrypt(vprsactx, out, outlen, outsize, in, inlen); + return UADK_E_FAIL; +} + +static int uadk_rsa_sw_decrypt(void *vprsactx, unsigned char *out, + size_t *outlen, size_t outsize, + const unsigned char *in, size_t inlen) +{ + if (!enable_sw_offload || !get_default_rsa_asym_cipher().decrypt) return UADK_E_FAIL; - return get_default_rsa_asym_cipher().encrypt(vprsactx, out, outlen, outsize, in, inlen); + fprintf(stderr, "switch to openssl software calculation in rsa decryption.\n"); + return get_default_rsa_asym_cipher().decrypt(vprsactx, out, outlen, outsize, in, inlen); } static int uadk_asym_cipher_rsa_decrypt(void *vprsactx, unsigned char *out, @@ -2405,10 +2435,10 @@ static int uadk_asym_cipher_rsa_decrypt(void *vprsactx, unsigned char *out, size_t len = uadk_rsa_size(priv->rsa); int ret; - if (priv->soft && SOFT_SWITCH) - goto soft; - else if (priv->soft && !SOFT_SWITCH) - return UADK_E_FAIL; + if (priv->soft) { + ret = UADK_DO_SOFT; + goto exe_soft; + } if (out == NULL) { if (len == 0) { @@ -2425,21 +2455,16 @@ static int uadk_asym_cipher_rsa_decrypt(void *vprsactx, unsigned char *out, } ret = uadk_prov_rsa_private_decrypt(inlen, in, out, priv->rsa, priv->pad_mode); - if (ret == UADK_DO_SOFT || ret == UADK_E_FAIL) { - if (ret == UADK_DO_SOFT && SOFT_SWITCH) - goto soft; - else - return UADK_E_FAIL; - } + if (ret == UADK_DO_SOFT || ret == UADK_E_FAIL) + goto exe_soft; + *outlen = ret; return UADK_E_SUCCESS; -soft: - fprintf(stderr, "switch to execute openssl software calculation.\n"); - if (!get_default_rsa_asym_cipher().decrypt) - return UADK_E_FAIL; - - return get_default_rsa_asym_cipher().decrypt(vprsactx, out, outlen, outsize, in, inlen); +exe_soft: + if (ret == UADK_DO_SOFT) + return uadk_rsa_sw_decrypt(vprsactx, out, outlen, outsize, in, inlen); + return UADK_E_FAIL; } static int uadk_asym_cipher_rsa_get_ctx_params(void *vprsactx, OSSL_PARAM *params) @@ -2588,10 +2613,20 @@ static RSA *ossl_rsa_new_with_ctx(OSSL_LIB_CTX *libctx) } ret->libctx = libctx; + ret->meth = RSA_get_default_method(); return ret; } +static void *uadk_rsa_sw_gen(void *genctx, OSSL_CALLBACK *osslcb, void *cbarg) +{ + if (!enable_sw_offload || !get_default_rsa_keymgmt().gen) + return NULL; + + fprintf(stderr, "switch to openssl software calculation in rsa key generation.\n"); + return get_default_rsa_keymgmt().gen(genctx, osslcb, cbarg); +} + static void *uadk_keymgmt_rsa_gen(void *genctx, OSSL_CALLBACK *osslcb, void *cbarg) { struct rsa_gen_ctx *gctx = genctx; @@ -2603,10 +2638,10 @@ static void *uadk_keymgmt_rsa_gen(void *genctx, OSSL_CALLBACK *osslcb, void *cba return NULL; ret = uadk_prov_rsa_init(); - if (ret && SOFT_SWITCH) + if (ret) { + ret = UADK_DO_SOFT; goto exe_soft; - else if (ret && !SOFT_SWITCH) - return NULL; + } rsa = ossl_rsa_new_with_ctx(gctx->libctx); if (rsa == NULL) @@ -2622,11 +2657,7 @@ static void *uadk_keymgmt_rsa_gen(void *genctx, OSSL_CALLBACK *osslcb, void *cba if (ret == UADK_DO_SOFT || ret == UADK_E_FAIL) { BN_GENCB_free(gencb); uadk_keymgmt_rsa_free(rsa); - - if (ret == UADK_DO_SOFT && SOFT_SWITCH) - goto exe_soft; - else - return NULL; + goto exe_soft; } uadk_rsa_clear_flags(rsa, RSA_FLAG_TYPE_MASK); @@ -2636,10 +2667,9 @@ static void *uadk_keymgmt_rsa_gen(void *genctx, OSSL_CALLBACK *osslcb, void *cba return rsa; exe_soft: - fprintf(stderr, "switch to execute openssl software calculation.\n"); - if (!get_default_rsa_keymgmt().gen) - return NULL; - return get_default_rsa_keymgmt().gen(genctx, osslcb, cbarg); + if (ret == UADK_DO_SOFT) + return uadk_rsa_sw_gen(genctx, osslcb, cbarg); + return NULL; } static void uadk_keymgmt_rsa_gen_cleanup(void *genctx) -- 2.33.0

From: lizhi <lizhi206@huawei.com> When hardware failures occur, or in cases of insufficient queue resources or unsupported algorithm specifications, the uadk provider can switch sm2 to openssl soft computation. Signed-off-by: lizhi <lizhi206@huawei.com> Signed-off-by: JiangShui Yang <yangjiangshui@h-partners.com> --- src/uadk_prov_sm2.c | 241 +++++++++++++++++++++++++++++++++++++++----- 1 file changed, 214 insertions(+), 27 deletions(-) diff --git a/src/uadk_prov_sm2.c b/src/uadk_prov_sm2.c index df753bd..9fcefc6 100644 --- a/src/uadk_prov_sm2.c +++ b/src/uadk_prov_sm2.c @@ -144,11 +144,29 @@ typedef struct { SM2_PROV_CTX *sm2_pctx; } PROV_SM2_SIGN_CTX; +/* + * To stay same structure with openssl sm2 cipher context, + * add openssl PROV_DIGEST type to uadk provider. + * It will not be used in uadk provider, so set it all zero. + */ +struct PROV_DIGEST { + const EVP_MD *md; + EVP_MD *alloc_md; + + ENGINE *engine; + + /* The resv is additional field, not in openssl structure. + * Add it to prevent possible field changes of openssl in future. + */ + char resv[OSSL_MAX_NAME_SIZE]; +}; + typedef struct { OSSL_LIB_CTX *libctx; /* Use EC_KEY refer to keymgmt */ EC_KEY *key; - char mdname[OSSL_MAX_NAME_SIZE]; + /* The md will used by openssl, but not used by uadk provider */ + struct PROV_DIGEST md; SM2_PROV_CTX *sm2_pctx; } PROV_SM2_ASYM_CTX; @@ -597,6 +615,16 @@ error: return UADK_P_FAIL; } +static void *uadk_keymgmt_sm2_gen_sw(void *genctx, OSSL_CALLBACK *osslcb, void *cbarg) +{ + if (uadk_get_sw_offload_state()) { + fprintf(stderr, "switch to software sm2 keygen.\n"); + return get_default_sm2_keymgmt().gen(genctx, osslcb, cbarg); + } + + return NULL; +} + /** * @brief Generate SM2 key pair. * @@ -632,14 +660,14 @@ static void *uadk_keymgmt_sm2_gen(void *genctx, OSSL_CALLBACK *osslcb, void *cba ret = uadk_prov_keymgmt_get_support_state(KEYMGMT_SM2); if (ret == UADK_P_FAIL) { fprintf(stderr, "failed to get hardware sm2 keygen support\n"); - goto free_ec_key; + goto do_soft; } /* SM2 hardware init */ ret = uadk_prov_ecc_init("sm2"); if (ret == UADK_P_FAIL) { fprintf(stderr, "failed to init sm2\n"); - goto free_ec_key; + goto do_soft; } /* Do sm2 keygen with hardware */ @@ -651,17 +679,41 @@ static void *uadk_keymgmt_sm2_gen(void *genctx, OSSL_CALLBACK *osslcb, void *cba ret = uadk_prov_sm2_keygen(ec); if (ret == UADK_P_FAIL) { fprintf(stderr, "failed to generate sm2 key\n"); - goto free_ec_key; + goto do_soft; } return ec; +do_soft: + EC_KEY_free(ec); + return uadk_keymgmt_sm2_gen_sw(genctx, osslcb, cbarg); free_ec_key: /* Something went wrong, throw the key away */ EC_KEY_free(ec); return NULL; } +static UADK_PKEY_SIGNATURE get_default_sm2_signature(void) +{ + static UADK_PKEY_SIGNATURE s_signature; + static int initilazed; + + if (__atomic_compare_exchange_n(&initilazed, &(int){0}, 1, false, __ATOMIC_SEQ_CST, + __ATOMIC_SEQ_CST)) { + UADK_PKEY_SIGNATURE *signature = + (UADK_PKEY_SIGNATURE *)EVP_SIGNATURE_fetch(NULL, "SM2", "provider=default"); + + if (signature) { + s_signature = *signature; + EVP_SIGNATURE_free((EVP_SIGNATURE *)signature); + } else { + __atomic_store_n(&initilazed, 0, __ATOMIC_SEQ_CST); + fprintf(stderr, "failed to EVP_SIGNATURE_fetch default SM2 provider\n"); + } + } + return s_signature; +} + static void *uadk_signature_sm2_newctx(void *provctx, const char *propq) { PROV_SM2_SIGN_CTX *psm2ctx = OPENSSL_zalloc(sizeof(PROV_SM2_SIGN_CTX)); @@ -919,6 +971,17 @@ static int uadk_prov_sm2_update_sess(SM2_PROV_CTX *smctx) return UADK_P_SUCCESS; } +static int uadk_signature_sm2_sign_init_sw(void *vpsm2ctx, void *ec, + const OSSL_PARAM params[]) +{ + if (uadk_get_sw_offload_state()) { + fprintf(stderr, "switch to software sm2 sign_init.\n"); + return get_default_sm2_signature().sign_init(vpsm2ctx, ec, params); + } + + return UADK_P_FAIL; +} + static int uadk_signature_sm2_sign_init(void *vpsm2ctx, void *ec, const OSSL_PARAM params[]) { @@ -956,20 +1019,20 @@ static int uadk_signature_sm2_sign_init(void *vpsm2ctx, void *ec, ret = uadk_signature_sm2_set_ctx_params((void *)psm2ctx, params); if (ret == UADK_P_FAIL) { fprintf(stderr, "failed to set sm2 sig ctx params\n"); - return ret; + goto do_soft; } ret = uadk_prov_signature_get_support_state(SIGNATURE_SM2); if (ret == UADK_P_FAIL) { fprintf(stderr, "failed to get hardware sm2 signature support\n"); - return ret; + goto do_soft; } /* Init with UADK */ ret = uadk_prov_ecc_init("sm2"); if (ret == UADK_P_FAIL) { fprintf(stderr, "failed to init sm2\n"); - return ret; + goto do_soft; } psm2ctx->sm2_pctx->init_status = CTX_INIT_SUCC; @@ -977,10 +1040,13 @@ static int uadk_signature_sm2_sign_init(void *vpsm2ctx, void *ec, ret = uadk_prov_sm2_update_sess(psm2ctx->sm2_pctx); if (ret == UADK_P_FAIL) { fprintf(stderr, "failed to update sess in sign init\n"); - return ret; + goto do_soft; } return UADK_P_SUCCESS; + +do_soft: + return uadk_signature_sm2_sign_init_sw(vpsm2ctx, ec, params); } static int uadk_signature_sm2_verify_init(void *vpsm2ctx, void *ec, @@ -1124,9 +1190,11 @@ static int uadk_prov_sm2_sign_bin_to_ber(struct wd_dtb *r, struct wd_dtb *s, sltmp = i2d_ECDSA_SIG(e_sig, &sig); if (sltmp < 0) { fprintf(stderr, "failed to i2d_ECDSA_SIG\n"); - goto free_s; + /* bs and br set to e_sig, use unified interface to prevent double release. */ + goto free_sig; } *siglen = (size_t)sltmp; + ECDSA_SIG_free(e_sig); return UADK_P_SUCCESS; @@ -1248,6 +1316,18 @@ uninit_iot: return UADK_P_FAIL; } +static int uadk_signature_sm2_sign_sw(void *vpsm2ctx, unsigned char *sig, size_t *siglen, + size_t sigsize, const unsigned char *tbs, size_t tbslen) +{ + if (uadk_get_sw_offload_state()) { + fprintf(stderr, "switch to soft sm2 sign\n"); + return get_default_sm2_signature().sign(vpsm2ctx, sig, siglen, sigsize, + tbs, tbslen); + } + + return UADK_P_FAIL; +} + static int uadk_signature_sm2_sign(void *vpsm2ctx, unsigned char *sig, size_t *siglen, size_t sigsize, const unsigned char *tbs, size_t tbslen) { @@ -1283,24 +1363,27 @@ static int uadk_signature_sm2_sign(void *vpsm2ctx, unsigned char *sig, size_t *s if (sigsize < (size_t)ecsize) { fprintf(stderr, "sigsize(%zu) < ecsize(%d)\n", sigsize, ecsize); - return UADK_P_FAIL; + goto do_soft; } ret = uadk_prov_sm2_check_tbs_params(psm2ctx, tbs, tbslen); if (ret == UADK_P_FAIL) { fprintf(stderr, "failed to check sm2 signature params\n"); - return ret; + goto do_soft; } ret = uadk_prov_sm2_sign(psm2ctx, sig, &sltmp, tbs, tbslen); if (ret == UADK_P_FAIL) { fprintf(stderr, "failed to do sm2 sign\n"); - return ret; + goto do_soft; } *siglen = sltmp; return UADK_P_SUCCESS; + +do_soft: + return uadk_signature_sm2_sign_sw(vpsm2ctx, sig, siglen, sigsize, tbs, tbslen); } static int uadk_prov_sm2_verify_init_iot(handle_t sess, struct wd_ecc_req *req, @@ -1415,6 +1498,17 @@ uninit_iot: return UADK_P_FAIL; } +static int uadk_signature_sm2_verify_sw(void *vpsm2ctx, const unsigned char *sig, size_t siglen, + const unsigned char *tbs, size_t tbslen) +{ + if (uadk_get_sw_offload_state()) { + fprintf(stderr, "switch to soft sm2 verify\n"); + return get_default_sm2_signature().verify(vpsm2ctx, sig, siglen, tbs, tbslen); + } + + return UADK_P_FAIL; +} + static int uadk_signature_sm2_verify(void *vpsm2ctx, const unsigned char *sig, size_t siglen, const unsigned char *tbs, size_t tbslen) { @@ -1435,10 +1529,13 @@ static int uadk_signature_sm2_verify(void *vpsm2ctx, const unsigned char *sig, s ret = uadk_prov_sm2_verify(psm2ctx, sig, siglen, tbs, tbslen); if (ret == UADK_P_FAIL) { fprintf(stderr, "failed to do sm2 verify\n"); - return ret; + goto do_soft; } return UADK_P_SUCCESS; + +do_soft: + return uadk_signature_sm2_verify_sw(vpsm2ctx, sig, siglen, tbs, tbslen); } static int uadk_signature_sm2_digest_sign_init(void *vpsm2ctx, const char *mdname, @@ -2076,6 +2173,16 @@ static int uadk_prov_sm2_locate_id_digest(PROV_SM2_SIGN_CTX *psm2ctx, const OSS return UADK_P_SUCCESS; } +static int uadk_signature_sm2_set_ctx_params_sw(void *vpsm2ctx, const OSSL_PARAM params[]) +{ + if (uadk_get_sw_offload_state()) { + fprintf(stderr, "switch to software sm2 set_ctx_params\n"); + return get_default_sm2_signature().set_ctx_params(vpsm2ctx, params); + } + + return UADK_P_FAIL; +} + static int uadk_signature_sm2_set_ctx_params(void *vpsm2ctx, const OSSL_PARAM params[]) { PROV_SM2_SIGN_CTX *psm2ctx = (PROV_SM2_SIGN_CTX *)vpsm2ctx; @@ -2110,11 +2217,14 @@ static int uadk_signature_sm2_set_ctx_params(void *vpsm2ctx, const OSSL_PARAM pa ret = uadk_prov_sm2_update_sess(smctx); if (ret == UADK_P_FAIL) { fprintf(stderr, "failed to update sess in set_ctx\n"); - return ret; + goto do_soft; } } return UADK_P_SUCCESS; + +do_soft: + return uadk_signature_sm2_set_ctx_params_sw(vpsm2ctx, params); } static int uadk_signature_sm2_get_ctx_params(void *vpsm2ctx, OSSL_PARAM *params) @@ -2250,6 +2360,28 @@ static int uadk_signature_sm2_verify_recover(void *vpsm2ctx, unsigned char *rout return UADK_P_SUCCESS; } +static UADK_PKEY_ASYM_CIPHER get_default_sm2_asym_cipher(void) +{ + static UADK_PKEY_ASYM_CIPHER s_asym_cipher; + static int initilazed; + + if (__atomic_compare_exchange_n(&initilazed, &(int){0}, 1, false, __ATOMIC_SEQ_CST, + __ATOMIC_SEQ_CST)) { + UADK_PKEY_ASYM_CIPHER *asym_cipher = + (UADK_PKEY_ASYM_CIPHER *)EVP_ASYM_CIPHER_fetch(NULL, "SM2", + "provider=default"); + + if (asym_cipher) { + s_asym_cipher = *asym_cipher; + EVP_ASYM_CIPHER_free((EVP_ASYM_CIPHER *)asym_cipher); + } else { + __atomic_store_n(&initilazed, 0, __ATOMIC_SEQ_CST); + fprintf(stderr, "failed to EVP_ASYM_CIPHER_fetch default SM2 provider\n"); + } + } + return s_asym_cipher; +} + static void *uadk_asym_cipher_sm2_newctx(void *provctx) { PROV_SM2_ASYM_CTX *psm2ctx = OPENSSL_zalloc(sizeof(PROV_SM2_ASYM_CTX)); @@ -2275,7 +2407,6 @@ static void *uadk_asym_cipher_sm2_newctx(void *provctx) } /* Use SM3 in default, other digest can be set with set_ctx_params API. */ smctx->sm2_md->mdsize = SM3_DIGEST_LENGTH; - strcpy(psm2ctx->mdname, OSSL_DIGEST_NAME_SM3); smctx->sm2_pd = OPENSSL_zalloc(sizeof(SM2_PKEY_DATA)); if (smctx->sm2_pd == NULL) { @@ -2332,6 +2463,17 @@ static void uadk_prov_sm2_set_default_md(PROV_SM2_ASYM_CTX *psm2ctx) smd->md_nid = NID_sm3; } +static int uadk_asym_cipher_sm2_encrypt_init_sw(void *vpsm2ctx, void *vkey, + const OSSL_PARAM params[]) +{ + if (uadk_get_sw_offload_state()) { + fprintf(stderr, "switch to software sm2 encrypt init\n"); + return get_default_sm2_asym_cipher().encrypt_init(vpsm2ctx, vkey, params); + } + + return UADK_P_FAIL; +} + static int uadk_asym_cipher_sm2_encrypt_init(void *vpsm2ctx, void *vkey, const OSSL_PARAM params[]) { @@ -2363,20 +2505,20 @@ static int uadk_asym_cipher_sm2_encrypt_init(void *vpsm2ctx, void *vkey, ret = uadk_asym_cipher_sm2_set_ctx_params(psm2ctx, params); if (ret == UADK_P_FAIL) { fprintf(stderr, "failed to set_ctx_params\n"); - return ret; + goto do_soft; } ret = uadk_prov_asym_cipher_get_support_state(SIGNATURE_SM2); if (ret == UADK_P_FAIL) { fprintf(stderr, "failed to get hardware sm2 signature support\n"); - return ret; + goto do_soft; } /* Init with UADK */ ret = uadk_prov_ecc_init("sm2"); if (ret == UADK_P_FAIL) { fprintf(stderr, "failed to init sm2\n"); - return ret; + goto do_soft; } smctx->init_status = CTX_INIT_SUCC; @@ -2384,10 +2526,13 @@ static int uadk_asym_cipher_sm2_encrypt_init(void *vpsm2ctx, void *vkey, ret = uadk_prov_sm2_update_sess(smctx); if (ret == UADK_P_FAIL) { fprintf(stderr, "failed to update sess\n"); - return ret; + goto do_soft; } return UADK_P_SUCCESS; + +do_soft: + return uadk_asym_cipher_sm2_encrypt_init_sw(vpsm2ctx, vkey, params); } static int uadk_prov_sm2_encrypt_check(PROV_SM2_ASYM_CTX *psm2ctx, @@ -2524,6 +2669,18 @@ free_x1: return ret; } +static int uadk_prov_sm2_encrypt_sw(PROV_SM2_ASYM_CTX *vpsm2ctx, + unsigned char *out, size_t *outlen, + const unsigned char *in, size_t inlen) +{ + if (uadk_get_sw_offload_state()) { + fprintf(stderr, "switch to software sm2 encrypt\n"); + return get_default_sm2_asym_cipher().encrypt(vpsm2ctx, out, outlen, 0, in, inlen); + } + + return UADK_P_FAIL; +} + static int uadk_prov_sm2_encrypt(PROV_SM2_ASYM_CTX *vpsm2ctx, unsigned char *out, size_t *outlen, const unsigned char *in, size_t inlen) @@ -2538,7 +2695,7 @@ static int uadk_prov_sm2_encrypt(PROV_SM2_ASYM_CTX *vpsm2ctx, ret = uadk_prov_sm2_encrypt_init_iot(smctx->sess, &req, (void *)in, inlen); if (ret == UADK_P_FAIL) - return ret; + goto do_soft; ret = uadk_prov_sm2_update_public_key(smctx, vpsm2ctx->key); if (ret == UADK_P_FAIL) @@ -2551,8 +2708,10 @@ static int uadk_prov_sm2_encrypt(PROV_SM2_ASYM_CTX *vpsm2ctx, } wd_sm2_get_enc_out_params(req.dst, &c1, &c2, &c3); - if (c1 == NULL || c2 == NULL || c3 == NULL) + if (c1 == NULL || c2 == NULL || c3 == NULL) { + ret = UADK_P_FAIL; goto uninit_iot; + } ret = uadk_prov_sm2_asym_bin_to_ber(c1, c2, c3, out, outlen); if (ret == UADK_P_FAIL) @@ -2562,6 +2721,7 @@ static int uadk_prov_sm2_encrypt(PROV_SM2_ASYM_CTX *vpsm2ctx, md_size = EVP_MD_size(md); if (c3->dsize != md_size) { fprintf(stderr, "invalid: c3 dsize(%u) != hash_size(%d)\n", c3->dsize, md_size); + ret = UADK_P_FAIL; goto uninit_iot; } @@ -2573,8 +2733,8 @@ static int uadk_prov_sm2_encrypt(PROV_SM2_ASYM_CTX *vpsm2ctx, uninit_iot: wd_ecc_del_in(smctx->sess, req.src); wd_ecc_del_out(smctx->sess, req.dst); - - return UADK_P_FAIL; +do_soft: + return uadk_prov_sm2_encrypt_sw(vpsm2ctx, out, outlen, in, inlen); } static size_t uadk_prov_ec_field_size(const EC_GROUP *group) @@ -2792,10 +2952,23 @@ static int uadk_prov_sm2_get_plaintext(struct wd_ecc_req *req, return UADK_P_SUCCESS; } +static int uadk_prov_sm2_decrypt_sw(PROV_SM2_ASYM_CTX *ctx, + unsigned char *out, size_t *outlen, + const unsigned char *in, size_t inlen) +{ + if (uadk_get_sw_offload_state()) { + fprintf(stderr, "switch to software sm2 decrypt\n"); + return get_default_sm2_asym_cipher().decrypt(ctx, out, outlen, 0, in, inlen); + } + + return UADK_P_FAIL; +} + static int uadk_prov_sm2_decrypt(PROV_SM2_ASYM_CTX *ctx, unsigned char *out, size_t *outlen, const unsigned char *in, size_t inlen) { + const unsigned char *original_in = in; SM2_PROV_CTX *smctx = ctx->sm2_pctx; struct sm2_ciphertext *ctext; struct wd_ecc_req req = {0}; @@ -2806,11 +2979,11 @@ static int uadk_prov_sm2_decrypt(PROV_SM2_ASYM_CTX *ctx, ret = uadk_prov_sm2_decrypt_check(smctx, out, outlen, in, inlen); if (ret == UADK_P_FAIL) - return ret; + goto do_soft; ctext = d2i_SM2_Ciphertext(NULL, &in, inlen); if (ctext == NULL) - return UADK_P_FAIL; + goto do_soft; md = (smctx->sm2_md->md == NULL) ? EVP_sm3() : smctx->sm2_md->md; ret = uadk_prov_sm2_asym_ber_to_bin(md, ctext, &c1, &c2, &c3); @@ -2849,7 +3022,8 @@ free_c1: free(c1.x.data); free_ctext: SM2_Ciphertext_free(ctext); - return UADK_P_FAIL; +do_soft: + return uadk_prov_sm2_decrypt_sw(ctx, out, outlen, original_in, inlen); } static int uadk_prov_sm2_plaintext_size(const unsigned char *ct, size_t ct_size, size_t *pt_size) @@ -3043,6 +3217,16 @@ static EVP_MD *uadk_prov_load_digest_from_params(SM2_MD_DATA *smd, const OSSL_PA return smd->md; } +static int uadk_asym_cipher_sm2_set_ctx_params_sw(void *vpsm2ctx, const OSSL_PARAM params[]) +{ + if (uadk_get_sw_offload_state()) { + fprintf(stderr, "switch to software sm2 set ctx params\n"); + return get_default_sm2_asym_cipher().set_ctx_params(vpsm2ctx, params); + } + + return UADK_P_FAIL; +} + static int uadk_asym_cipher_sm2_set_ctx_params(void *vpsm2ctx, const OSSL_PARAM params[]) { PROV_SM2_ASYM_CTX *psm2ctx = (PROV_SM2_ASYM_CTX *)vpsm2ctx; @@ -3084,11 +3268,14 @@ static int uadk_asym_cipher_sm2_set_ctx_params(void *vpsm2ctx, const OSSL_PARAM ret = uadk_prov_sm2_update_sess(smctx); if (ret == UADK_P_FAIL) { fprintf(stderr, "failed to update sess\n"); - return ret; + goto do_soft; } } return UADK_P_SUCCESS; + +do_soft: + return uadk_asym_cipher_sm2_set_ctx_params_sw(vpsm2ctx, params); } static const OSSL_PARAM *uadk_asym_cipher_sm2_gettable_ctx_params(ossl_unused void *vpsm2ctx, -- 2.33.0

From: lizhi <lizhi206@huawei.com> When hardware failures occur, or in cases of insufficient queue resources or unsupported algorithm specifications, the uadk provider can switch ecx to openssl soft computation. Signed-off-by: lizhi <lizhi206@huawei.com> Signed-off-by: JiangShui Yang <yangjiangshui@h-partners.com> --- src/uadk_prov_ecx.c | 242 ++++++++++++++++++++++++++++++-------------- 1 file changed, 166 insertions(+), 76 deletions(-) diff --git a/src/uadk_prov_ecx.c b/src/uadk_prov_ecx.c index 47fe1a9..3cc7fa1 100644 --- a/src/uadk_prov_ecx.c +++ b/src/uadk_prov_ecx.c @@ -50,14 +50,56 @@ static inline int UADK_CRYPTO_DOWN_REF(int *val, int *ret, __atomic_thread_fence(__ATOMIC_ACQUIRE); return 1; } +static pthread_mutex_t x25519_mutex = PTHREAD_MUTEX_INITIALIZER; +static pthread_mutex_t x448_mutex = PTHREAD_MUTEX_INITIALIZER; UADK_PKEY_KEYMGMT_DESCR(x448, X448); UADK_PKEY_KEYEXCH_DESCR(x448, X448); +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"); + if (keyexch) { + s_keyexch = *keyexch; + EVP_KEYEXCH_free((EVP_KEYEXCH *)keyexch); + initilazed = 1; + } else { + fprintf(stderr, "failed to EVP_KEYEXCH_fetch default X448 provider\n"); + } + } + pthread_mutex_unlock(&x448_mutex); + + return s_keyexch; +} + UADK_PKEY_KEYMGMT_DESCR(x25519, X25519); UADK_PKEY_KEYEXCH_DESCR(x25519, X25519); +static UADK_PKEY_KEYEXCH get_default_x25519_keyexch(void) +{ + static UADK_PKEY_KEYEXCH s_keyexch; + static int initilazed; -static pthread_mutex_t x25519_mutex = PTHREAD_MUTEX_INITIALIZER; -static pthread_mutex_t x448_mutex = PTHREAD_MUTEX_INITIALIZER; + 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; +} typedef enum { ECX_KEY_TYPE_X25519 = 0x0, @@ -706,44 +748,89 @@ static int uadk_prov_ecx_keygen_set_prikey(PROV_ECX_KEYMGMT_CTX *gctx, ECX_KEY * return UADK_P_SUCCESS; } -static void *uadk_prov_ecx_keygen(PROV_ECX_KEYMGMT_CTX *gctx) +static int uadk_prov_ecx_keygen(PROV_ECX_KEYMGMT_CTX *gctx, ECX_KEY **ecx_key) { struct wd_ecc_req req = {0}; - ECX_KEY *ecx_key = NULL; int ret; - ecx_key = uadk_prov_ecx_create_prikey(gctx); if (ecx_key == NULL) - return NULL; + return UADK_P_FAIL; + + *ecx_key = uadk_prov_ecx_create_prikey(gctx); + if (*ecx_key == NULL) + return UADK_P_FAIL; ret = uadk_prov_ecx_keygen_init_iot(gctx->sess, &req); if (ret == UADK_P_FAIL) goto free_prikey; - ret = uadk_prov_ecx_keygen_set_prikey(gctx, ecx_key); + ret = uadk_prov_ecx_keygen_set_prikey(gctx, *ecx_key); if (ret == UADK_P_FAIL) goto uninit_iot; ret = uadk_prov_ecc_crypto(gctx->sess, &req, (void *)gctx->sess); - if (ret == UADK_P_FAIL) + if (ret != UADK_P_SUCCESS) { + ret = UADK_DO_SOFT; goto uninit_iot; - - ret = uadk_prov_ecx_set_pkey(gctx, &req, ecx_key); + } + ret = uadk_prov_ecx_set_pkey(gctx, &req, *ecx_key); if (ret == UADK_P_FAIL) goto uninit_iot; - ecx_key->haspubkey = 1; + (*ecx_key)->haspubkey = 1; uadk_prov_ecx_keygen_uninit_iot(gctx->sess, &req); - return ecx_key; + return UADK_P_SUCCESS; uninit_iot: uadk_prov_ecx_keygen_uninit_iot(gctx->sess, &req); free_prikey: - uadk_prov_ecx_free_prikey(ecx_key); + uadk_prov_ecx_free_prikey(*ecx_key); - return NULL; + return ret; +} + +static void *uadk_ecx_sw_gen(void *genctx, OSSL_CALLBACK *cb, void *cb_params, + ECX_KEY_TYPE alg_type) +{ + if (!enable_sw_offload) + return NULL; + + fprintf(stderr, "switch to openssl software calculation in ecx generation.\n"); + switch (alg_type) { + case ECX_KEY_TYPE_X448: + if (!get_default_x448_keymgmt().gen) + return NULL; + return get_default_x448_keymgmt().gen(genctx, cb, cb_params); + case ECX_KEY_TYPE_X25519: + if (!get_default_x25519_keymgmt().gen) + return NULL; + return get_default_x25519_keymgmt().gen(genctx, cb, cb_params); + default: + return NULL; + } +} + +static int uadk_ecx_sw_derive(void *vecxctx, unsigned char *secret, size_t *secretlen, + size_t outlen, ECX_KEY_TYPE alg_type) +{ + if (!enable_sw_offload) + return UADK_P_FAIL; + + fprintf(stderr, "switch to openssl software calculation in ecx derivation.\n"); + switch (alg_type) { + case ECX_KEY_TYPE_X448: + if (!get_default_x448_keyexch().derive) + return UADK_P_FAIL; + return get_default_x448_keyexch().derive(vecxctx, secret, secretlen, outlen); + case ECX_KEY_TYPE_X25519: + if (!get_default_x25519_keyexch().derive) + return UADK_P_FAIL; + return get_default_x25519_keyexch().derive(vecxctx, secret, secretlen, outlen); + default: + return UADK_P_FAIL; + } } static void *uadk_keymgmt_x448_gen(void *genctx, OSSL_CALLBACK *cb, void *cb_params) @@ -765,50 +852,39 @@ static void *uadk_keymgmt_x448_gen(void *genctx, OSSL_CALLBACK *cb, void *cb_par ret = uadk_prov_keymgmt_get_support_state(KEYMGMT_X448); if (ret == UADK_P_FAIL) { fprintf(stderr, "failed to get hardware x448 keygen support\n"); - return NULL; + ret = UADK_DO_SOFT; + goto exe_soft; } ret = uadk_prov_ecc_init("x448"); if (ret != UADK_P_SUCCESS) { fprintf(stderr, "failed to init x448\n"); - return NULL; + ret = UADK_DO_SOFT; + goto exe_soft; } 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; + ret = UADK_P_FAIL; + goto exe_soft; } - ecx_key = uadk_prov_ecx_keygen(gctx); - if (ecx_key == NULL) + ret = uadk_prov_ecx_keygen(gctx, &ecx_key); + if (ret != UADK_P_SUCCESS) { fprintf(stderr, "failed to generate x448 key\n"); + uadk_prov_ecx_free_sess(gctx->sess); + goto exe_soft; + } uadk_prov_ecx_free_sess(gctx->sess); return ecx_key; -} - -static UADK_PKEY_KEYEXCH get_default_x448_keyexch(void) -{ - static UADK_PKEY_KEYEXCH s_keyexch; - static int initilazed; - - pthread_mutex_lock(&x448_mutex); - if (!initilazed) { - UADK_PKEY_KEYEXCH *keyexch = - (UADK_PKEY_KEYEXCH *)EVP_KEYEXCH_fetch(NULL, "X448", "provider=default"); - if (keyexch) { - s_keyexch = *keyexch; - EVP_KEYEXCH_free((EVP_KEYEXCH *)keyexch); - initilazed = 1; - } else { - fprintf(stderr, "failed to EVP_KEYEXCH_fetch default X448 provider\n"); - } - } - pthread_mutex_unlock(&x448_mutex); - return s_keyexch; +exe_soft: + if (ret == UADK_DO_SOFT) + return uadk_ecx_sw_gen(genctx, cb, cb_params, ECX_KEY_TYPE_X448); + return NULL; } static void *uadk_keyexch_x448_newctx(void *provctx) @@ -1101,12 +1177,15 @@ static int uadk_prov_ecx_derive(PROV_ECX_KEYEXCH_CTX *ecxctx, unsigned char *key goto uninit_iot; ret = uadk_prov_ecc_crypto(ecxctx->sess, &req, (void *)ecxctx); - if (ret == UADK_P_FAIL) + if (ret != UADK_P_SUCCESS) { + ret = UADK_DO_SOFT; goto uninit_iot; - + } wd_ecxdh_get_out_params(req.dst, &s_key); - if (!s_key) + if (!s_key) { + ret = UADK_P_FAIL; goto uninit_iot; + } ret = uadk_prov_reverse_bytes((unsigned char *)s_key->x.data, s_key->x.dsize); if (ret == UADK_P_FAIL) @@ -1155,30 +1234,41 @@ static int uadk_keyexch_x448_derive(void *vecxctx, unsigned char *secret, size_t ret = uadk_prov_keyexch_get_support_state(KEYEXCH_X448); if (ret == UADK_P_FAIL) { fprintf(stderr, "failed to get hardware x448 keyexch support\n"); - return UADK_P_FAIL; + ret = UADK_DO_SOFT; + goto exe_soft; } ret = uadk_prov_ecc_init("x448"); if (ret != UADK_P_SUCCESS) { fprintf(stderr, "failed to init x448\n"); - return UADK_P_FAIL; + ret = UADK_DO_SOFT; + goto exe_soft; } 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; + ret = UADK_P_FAIL; + goto exe_soft; } ret = uadk_prov_ecx_derive(ecxctx, secret, &ecxctx->keylen); - if (ret == UADK_P_FAIL) + if (ret != UADK_P_SUCCESS) { fprintf(stderr, "failed to do x448 derive\n"); + uadk_prov_ecx_free_sess(ecxctx->sess); + goto exe_soft; + } *secretlen = ecxctx->keylen; uadk_prov_ecx_free_sess(ecxctx->sess); return ret; + +exe_soft: + if (ret == UADK_DO_SOFT) + return uadk_ecx_sw_derive(vecxctx, secret, secretlen, outlen, ECX_KEY_TYPE_X448); + return UADK_P_FAIL; } static void *uadk_keyexch_ecx_dupctx(void *vecxctx) @@ -1409,50 +1499,39 @@ static void *uadk_keymgmt_x25519_gen(void *genctx, OSSL_CALLBACK *cb, void *cb_p 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_DO_SOFT; + goto exe_soft; } ret = uadk_prov_ecc_init("x25519"); if (ret != UADK_P_SUCCESS) { fprintf(stderr, "failed to init x25519\n"); - return NULL; + ret = UADK_DO_SOFT; + goto exe_soft; } 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"); + ret = UADK_P_FAIL; return NULL; } - ecx_key = uadk_prov_ecx_keygen(gctx); - if (ecx_key == NULL) + ret = uadk_prov_ecx_keygen(gctx, &ecx_key); + if (ret != UADK_P_SUCCESS) { fprintf(stderr, "failed to generate x25519 key\n"); + uadk_prov_ecx_free_sess(gctx->sess); + goto exe_soft; + } 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; +exe_soft: + if (ret == UADK_DO_SOFT) + return uadk_ecx_sw_gen(genctx, cb, cb_params, ECX_KEY_TYPE_X25519); + return NULL; } static void *uadk_keyexch_x25519_newctx(void *provctx) @@ -1559,30 +1638,41 @@ static int uadk_keyexch_x25519_derive(void *vecxctx, unsigned char *secret, size 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_DO_SOFT; + goto exe_soft; } ret = uadk_prov_ecc_init("x25519"); if (ret != UADK_P_SUCCESS) { fprintf(stderr, "failed to init x25519\n"); - return UADK_P_FAIL; + ret = UADK_DO_SOFT; + goto exe_soft; } 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_P_FAIL; + goto exe_soft; } ret = uadk_prov_ecx_derive(ecxctx, secret, &ecxctx->keylen); - if (ret == UADK_P_FAIL) + if (ret != UADK_P_SUCCESS) { fprintf(stderr, "failed to do x25519 derive\n"); + uadk_prov_ecx_free_sess(ecxctx->sess); + goto exe_soft; + } *secretlen = ecxctx->keylen; uadk_prov_ecx_free_sess(ecxctx->sess); return ret; + +exe_soft: + if (ret == UADK_DO_SOFT) + return uadk_ecx_sw_derive(vecxctx, secret, secretlen, outlen, ECX_KEY_TYPE_X25519); + return UADK_P_FAIL; } static void *uadk_keyexch_x25519_dupctx(void *vecxctx) -- 2.33.0

From: lizhi <lizhi206@huawei.com> When hardware failures occur, or in cases of insufficient queue resources or unsupported algorithm specifications, the uadk provider can switch ecdsa to openssl soft computation. Signed-off-by: lizhi <lizhi206@huawei.com> Signed-off-by: JiangShui Yang <yangjiangshui@h-partners.com> --- src/uadk_prov_ecdsa.c | 69 +++++++++++++++++++++++++++++++++++-------- 1 file changed, 57 insertions(+), 12 deletions(-) diff --git a/src/uadk_prov_ecdsa.c b/src/uadk_prov_ecdsa.c index 774e8ee..7ea5567 100644 --- a/src/uadk_prov_ecdsa.c +++ b/src/uadk_prov_ecdsa.c @@ -344,6 +344,37 @@ static int uadk_signature_ecdsa_verify_init(void *vctx, void *ec, const OSSL_PAR return ecdsa_signverify_init(vctx, ec, params, EVP_PKEY_OP_VERIFY); } +static int ecdsa_soft_sign(struct ecdsa_ctx *ctx, unsigned char *sig, size_t *siglen, + size_t sigsize, const unsigned char *tbs, size_t tbslen) +{ + unsigned int tmplen; + int ret; + + if (!enable_sw_offload) + return UADK_P_FAIL; + + fprintf(stderr, "switch to openssl software calculation in ecdsa signature.\n"); + + ret = ECDSA_sign_ex(0, tbs, tbslen, sig, &tmplen, ctx->kinv, ctx->r, ctx->ec); + if (ret <= 0) + return UADK_P_FAIL; + + *siglen = (size_t)tmplen; + + return UADK_P_SUCCESS; +} + +static int ecdsa_soft_verify(struct ecdsa_ctx *ctx, const unsigned char *sig, size_t siglen, + const unsigned char *tbs, size_t tbslen) +{ + if (!enable_sw_offload) + return UADK_P_FAIL; + + fprintf(stderr, "switch to openssl software calculation in ecdsa verification.\n"); + + return ECDSA_verify(0, tbs, tbslen, sig, siglen, ctx->ec); +} + static int ecdsa_common_params_check(struct ecdsa_ctx *ctx, struct ecdsa_opdata *opdata) { @@ -371,7 +402,7 @@ static int ecdsa_common_params_check(struct ecdsa_ctx *ctx, type = EC_METHOD_get_field_type(EC_GROUP_method_of(group)); if (type != NID_X9_62_prime_field) { fprintf(stderr, "invalid: uadk unsupport Field GF(2m)!\n"); - return UADK_P_FAIL; + return UADK_DO_SOFT; } opdata->ec = ctx->ec; @@ -563,7 +594,7 @@ static int ecdsa_hw_sign(struct ecdsa_opdata *opdata) sess = ecdsa_alloc_sess(opdata->ec); if (unlikely(!sess)) { fprintf(stderr, "failed to alloc ecdsa sess!\n"); - return UADK_P_FAIL; + return UADK_DO_SOFT; } ret = ecdsa_sign_init_iot(sess, &req, opdata); @@ -579,8 +610,9 @@ static int ecdsa_hw_sign(struct ecdsa_opdata *opdata) } ret = uadk_prov_ecc_crypto(sess, &req, (void *)sess); - if (unlikely(!ret)) { - fprintf(stderr, "failed to sign!\n"); + if (unlikely(!ret || req.status)) { + fprintf(stderr, "failed to hardware sign!\n"); + ret = UADK_DO_SOFT; goto free_iot; } @@ -639,13 +671,13 @@ static int uadk_signature_ecdsa_sign(void *vctx, unsigned char *sig, size_t *sig ret = ecdsa_sign_params_check(ctx, &opdata, sig, siglen, sigsize); if (ret == UADK_SIGN_SIG_NULL) { return UADK_P_SUCCESS; - } else if (unlikely(!ret)) { + } else if (unlikely(ret != UADK_P_SUCCESS)) { fprintf(stderr, "failed to check params to sign!\n"); goto err; } ret = ecdsa_hw_sign(&opdata); - if (unlikely(!ret)) + if (unlikely(ret != UADK_P_SUCCESS)) goto err; ret = i2d_ECDSA_SIG(opdata.sig, &sig); /* ECDSA_SIG_free will free br and bs applied for in ecdsa_get_sign_data() */ @@ -659,6 +691,10 @@ static int uadk_signature_ecdsa_sign(void *vctx, unsigned char *sig, size_t *sig err: if (siglen) *siglen = 0; + + if (ret == UADK_DO_SOFT) + return ecdsa_soft_sign(ctx, sig, siglen, sigsize, tbs, tbslen); + return UADK_P_FAIL; } @@ -706,20 +742,24 @@ static int ecdsa_hw_verify(struct ecdsa_opdata *opdata) int ret; sess = ecdsa_alloc_sess(opdata->ec); - if (!sess) { + if (unlikely(!sess)) { fprintf(stderr, "failed to alloc ecdsa sess!\n"); - return UADK_P_FAIL; + return UADK_DO_SOFT; } ret = ecdsa_verify_init_iot(sess, &req, opdata); - if (!ret) + if (unlikely(!ret)) goto free_sess; ret = uadk_prov_ecc_set_public_key(sess, opdata->ec); - if (!ret) + if (unlikely(!ret)) goto free_iot; ret = uadk_prov_ecc_crypto(sess, &req, (void *)sess); + if (unlikely(ret != UADK_P_SUCCESS || req.status)) { + fprintf(stderr, "failed to hardware verify!\n"); + ret = UADK_DO_SOFT; + } free_iot: ecdsa_uninit_req_iot(sess, &req); @@ -791,9 +831,9 @@ static int uadk_signature_ecdsa_verify(void *vctx, const unsigned char *sig, opdata.tbs = tbs; opdata.tbslen = tbslen; ret = ecdsa_verify_params_check(ctx, &opdata, sig, siglen); - if (!ret) { + if (ret != UADK_P_SUCCESS) { fprintf(stderr, "failed to check params to sign!\n"); - return UADK_P_FAIL; + goto err; } opdata.sig = ecdsa_create_sig(sig, siglen); @@ -805,6 +845,11 @@ static int uadk_signature_ecdsa_verify(void *vctx, const unsigned char *sig, ret = ecdsa_hw_verify(&opdata); ECDSA_SIG_free(opdata.sig); + +err: + if (ret == UADK_DO_SOFT) + return ecdsa_soft_verify(ctx, sig, siglen, tbs, tbslen); + return ret; } -- 2.33.0

From: lizhi <lizhi206@huawei.com> When hardware failures occur, or in cases of insufficient queue resources or unsupported algorithm specifications, the uadk provider can switch ecdh to openssl soft computation. Signed-off-by: lizhi <lizhi206@huawei.com> Signed-off-by: JiangShui Yang <yangjiangshui@h-partners.com> --- src/uadk_prov_ec_kmgmt.c | 27 +++++++++++++---- src/uadk_prov_ecdh_exch.c | 61 +++++++++++++++++++++++++++++++++------ 2 files changed, 73 insertions(+), 15 deletions(-) diff --git a/src/uadk_prov_ec_kmgmt.c b/src/uadk_prov_ec_kmgmt.c index 355d601..01bcc50 100644 --- a/src/uadk_prov_ec_kmgmt.c +++ b/src/uadk_prov_ec_kmgmt.c @@ -54,10 +54,12 @@ static int ec_param_check(struct ec_gen_ctx *gctx, EC_KEY *ec) type = EC_METHOD_get_field_type(EC_GROUP_method_of(group)); if (type != NID_X9_62_prime_field) { fprintf(stderr, "invalid: uadk unsupport Field GF(2m)!\n"); - return UADK_P_FAIL; + return UADK_DO_SOFT; } - return uadk_prov_ecc_bit_check(group); + ret = uadk_prov_ecc_bit_check(group); + + return ret; } static int ec_set_public_key(EC_KEY *ec, struct wd_ecc_out *ec_out) @@ -235,7 +237,7 @@ static int ec_hw_keygen(EC_KEY *ec, BIGNUM *priv_key) sess = ec_alloc_sess(ec, &ec_out); if (!sess) { fprintf(stderr, "failed to alloc sess!\n"); - return UADK_P_FAIL; + return UADK_DO_SOFT; } ret = ec_update_private_key(ec, sess, priv_key); @@ -246,8 +248,9 @@ static int ec_hw_keygen(EC_KEY *ec, BIGNUM *priv_key) uadk_prov_ecc_fill_req(&req, WD_ECXDH_GEN_KEY, NULL, ec_out); ret = uadk_prov_ecc_crypto(sess, &req, (void *)sess); - if (!ret) { + if (ret != UADK_P_SUCCESS) { fprintf(stderr, "failed to generate key!\n"); + ret = UADK_DO_SOFT; goto free_sess; } @@ -319,6 +322,15 @@ static int ec_set_check_group_type(EC_KEY *ec, const char *name) return UADK_P_SUCCESS; } +static void *uadk_ec_sw_gen(void *genctx, OSSL_CALLBACK *osslcb, void *cbarg) +{ + if (!enable_sw_offload || !get_default_ec_keymgmt().gen) + return NULL; + + fprintf(stderr, "switch to openssl software calculation in ecx generation.\n"); + return get_default_ec_keymgmt().gen(genctx, osslcb, cbarg); +} + static void *uadk_keymgmt_ec_gen(void *genctx, OSSL_CALLBACK *osslcb, void *cbarg) { struct ec_gen_ctx *gctx = genctx; @@ -337,7 +349,7 @@ static void *uadk_keymgmt_ec_gen(void *genctx, OSSL_CALLBACK *osslcb, void *cbar } ret = ec_param_check(genctx, ec); - if (!ret) { + if (ret != UADK_P_SUCCESS) { fprintf(stderr, "failed to check genctx!\n"); goto free_ec_key; } @@ -345,7 +357,7 @@ static void *uadk_keymgmt_ec_gen(void *genctx, OSSL_CALLBACK *osslcb, void *cbar /* Whether you want it or not, you get a keypair, not just one half */ if ((gctx->selection & OSSL_KEYMGMT_SELECT_KEYPAIR) != 0) { ret = ec_hw_keygen(ec, gctx->priv_key); - if (!ret) { + if (ret != UADK_P_SUCCESS) { fprintf(stderr, "failed to gen public key!\n"); goto free_ec_key; } @@ -367,6 +379,9 @@ static void *uadk_keymgmt_ec_gen(void *genctx, OSSL_CALLBACK *osslcb, void *cbar free_ec_key: EC_KEY_free(ec); + + if (ret == UADK_DO_SOFT) + return uadk_ec_sw_gen(genctx, osslcb, cbarg); return NULL; } diff --git a/src/uadk_prov_ecdh_exch.c b/src/uadk_prov_ecdh_exch.c index 9ac8e58..f3b2e68 100644 --- a/src/uadk_prov_ecdh_exch.c +++ b/src/uadk_prov_ecdh_exch.c @@ -72,6 +72,28 @@ struct ecdh_sess_ctx { }; UADK_PKEY_KEYEXCH_DESCR(ecdh, ECDH); +static pthread_mutex_t ecdh_mutex = PTHREAD_MUTEX_INITIALIZER; +static UADK_PKEY_KEYEXCH get_default_ecdh_keyexch(void) +{ + static UADK_PKEY_KEYEXCH s_keyexch; + static int initilazed; + + pthread_mutex_lock(&ecdh_mutex); + if (!initilazed) { + UADK_PKEY_KEYEXCH *keyexch = + (UADK_PKEY_KEYEXCH *)EVP_KEYEXCH_fetch(NULL, "ecdh", "provider=default"); + if (keyexch) { + s_keyexch = *keyexch; + EVP_KEYEXCH_free((EVP_KEYEXCH *)keyexch); + initilazed = 1; + } else { + fprintf(stderr, "failed to EVP_KEYEXCH_fetch default X448 provider\n"); + } + } + pthread_mutex_unlock(&ecdh_mutex); + + return s_keyexch; +} static size_t ecdh_get_ec_size(const EC_GROUP *group) { @@ -114,12 +136,15 @@ static int ecdh_param_check(struct ecdh_ctx *pecdhctx, struct ecdh_sess_ctx *ses type = EC_METHOD_get_field_type(EC_GROUP_method_of(group)); if (type != NID_X9_62_prime_field) { fprintf(stderr, "invalid: uadk unsupport Field GF(2m)!\n"); - return UADK_P_FAIL; + return UADK_DO_SOFT; } sess_ctx->group = group; - return uadk_prov_ecc_bit_check(group); + if (uadk_prov_ecc_bit_check(group) != UADK_P_SUCCESS) + return UADK_DO_SOFT; + + return UADK_P_SUCCESS; } static int ecdh_set_privk(struct ecdh_ctx *pecdhctx, @@ -276,7 +301,7 @@ static int ecdh_compute_key(struct ecdh_sess_ctx *sess_ctx, sess = ecdh_alloc_sess(sess_ctx->privk); if (!sess) { fprintf(stderr, "failed to alloc sess to compute key!\n"); - return UADK_P_FAIL; + return UADK_DO_SOFT; } ret = uadk_prov_ecc_set_private_key(sess, sess_ctx->privk); @@ -292,8 +317,9 @@ static int ecdh_compute_key(struct ecdh_sess_ctx *sess_ctx, } ret = uadk_prov_ecc_crypto(sess, &req, (void *)sess); - if (!ret) { + if (ret != UADK_P_SUCCESS) { fprintf(stderr, "failed to calculate shared key!\n"); + ret = UADK_DO_SOFT; goto uninit_req; } @@ -315,7 +341,7 @@ static int ecdh_plain_derive(struct ecdh_ctx *pecdhctx, int ret; ret = ecdh_param_check(pecdhctx, &sess_ctx); - if (!ret) + if (ret != UADK_P_SUCCESS) return ret; ec_size = ecdh_get_ec_size(sess_ctx.group); @@ -389,13 +415,13 @@ static int ecdh_X9_63_kdf_derive(struct ecdh_ctx *pecdhctx, unsigned char *secre } if (outlen < pecdhctx->kdf_outlen) { - fprintf(stderr, "invalid: outlen %lu is less than kdf_outlen %lu!\n", + fprintf(stderr, "invalid: outlen %zu is less than kdf_outlen %zu!\n", outlen, pecdhctx->kdf_outlen); return UADK_P_FAIL; } ret = ecdh_plain_derive(pecdhctx, NULL, &stmplen, 0); - if (!ret) + if (ret != UADK_P_SUCCESS) return ret; stmp = OPENSSL_secure_malloc(stmplen); @@ -419,10 +445,21 @@ static int ecdh_X9_63_kdf_derive(struct ecdh_ctx *pecdhctx, unsigned char *secre return ret; } +static int uadk_ecdh_sw_derive(void *vpecdhctx, unsigned char *secret, + size_t *psecretlen, size_t outlen) +{ + if (!enable_sw_offload || !get_default_ecdh_keyexch().derive) + return UADK_P_FAIL; + + fprintf(stderr, "switch to openssl software calculation in ecdh derivation.\n"); + return get_default_ecdh_keyexch().derive(vpecdhctx, secret, psecretlen, outlen); +} + static int uadk_keyexch_ecdh_derive(void *vpecdhctx, unsigned char *secret, size_t *psecretlen, size_t outlen) { struct ecdh_ctx *pecdhctx = vpecdhctx; + int ret; if (!pecdhctx) { fprintf(stderr, "invalid: vpecdhctx is NULL to derive!\n"); @@ -431,13 +468,19 @@ static int uadk_keyexch_ecdh_derive(void *vpecdhctx, unsigned char *secret, switch (pecdhctx->kdf_type) { case PROV_ECDH_KDF_NONE: - return ecdh_plain_derive(pecdhctx, secret, psecretlen, outlen); + ret = ecdh_plain_derive(pecdhctx, secret, psecretlen, outlen); + break; case PROV_ECDH_KDF_X9_63: - return ecdh_X9_63_kdf_derive(pecdhctx, secret, psecretlen, outlen); + ret = ecdh_X9_63_kdf_derive(pecdhctx, secret, psecretlen, outlen); + break; default: break; } + if (ret == UADK_P_SUCCESS) + return UADK_P_SUCCESS; + if (ret == UADK_DO_SOFT) + return uadk_ecdh_sw_derive(vpecdhctx, secret, psecretlen, outlen); return UADK_P_FAIL; } -- 2.33.0

From: Wenkai Lin <linwenkai6@hisilicon.com> In the event of a soft failure, an error should be returned to avoid errors such as empty addresses in subsequent steps. Signed-off-by: Wenkai Lin <linwenkai6@hisilicon.com> Signed-off-by: JiangShui Yang <yangjiangshui@h-partners.com> --- src/uadk_digest.c | 38 ++++++++++++++++++++++++++++---------- src/uadk_prov_digest.c | 40 ++++++++++++++++++++++++++++++---------- 2 files changed, 58 insertions(+), 20 deletions(-) diff --git a/src/uadk_digest.c b/src/uadk_digest.c index ed68ee2..cb593a8 100644 --- a/src/uadk_digest.c +++ b/src/uadk_digest.c @@ -321,16 +321,23 @@ static void digest_soft_cleanup(struct digest_priv_ctx *md_ctx) static int uadk_e_digest_soft_work(struct digest_priv_ctx *md_ctx, int len, unsigned char *digest) { - (void)digest_soft_init(md_ctx); + int ret; - if (len != 0) - (void)digest_soft_update(md_ctx, md_ctx->data, len); + ret = digest_soft_init(md_ctx); + if (unlikely(!ret)) + return 0; - (void)digest_soft_final(md_ctx, digest); + if (len != 0) { + ret = digest_soft_update(md_ctx, md_ctx->data, len); + if (unlikely(!ret)) + goto out; + } - digest_soft_cleanup(md_ctx); + ret = digest_soft_final(md_ctx, digest); - return 1; +out: + digest_soft_cleanup(md_ctx); + return ret; } static int uadk_engine_digests(ENGINE *e, const EVP_MD **digest, @@ -730,19 +737,30 @@ static int digest_update_inner(EVP_MD_CTX *ctx, const void *data, size_t data_le do_soft_digest: if (priv->state == SEC_DIGEST_FIRST_UPDATING) { priv->switch_flag = UADK_DO_SOFT; - (void)digest_soft_init(priv); + ret = digest_soft_init(priv); + if (!ret) + return ret; /* filling buf has been executed */ if (processing_len < DIGEST_BLOCK_SIZE) { ret = digest_soft_update(priv, priv->data, DIGEST_BLOCK_SIZE); - if (ret != 1) - return ret; + if (!ret) + goto out; } - return digest_soft_update(priv, tmpdata, left_len); + ret = digest_soft_update(priv, tmpdata, left_len); + if (!ret) + goto out; + + /* the soft ctx will be free in the final stage. */ + return ret; } fprintf(stderr, "do soft digest failed during updating!\n"); return 0; + +out: + digest_soft_cleanup(priv); + return ret; } static int uadk_e_digest_update(EVP_MD_CTX *ctx, const void *data, size_t data_len) diff --git a/src/uadk_prov_digest.c b/src/uadk_prov_digest.c index 562e786..a2a5f09 100644 --- a/src/uadk_prov_digest.c +++ b/src/uadk_prov_digest.c @@ -218,18 +218,26 @@ static void digest_soft_cleanup(struct digest_priv_ctx *priv) static int uadk_digest_soft_work(struct digest_priv_ctx *priv, int len, unsigned char *digest) { + int ret; + if (!priv->soft_md) return UADK_DIGEST_FAIL; - uadk_digest_soft_init(priv); + ret = uadk_digest_soft_init(priv); + if (unlikely(ret == UADK_DIGEST_FAIL)) + return UADK_DIGEST_FAIL; - if (len != 0) - uadk_digest_soft_update(priv, priv->data, len); + if (len != 0) { + ret = uadk_digest_soft_update(priv, priv->data, len); + if (unlikely(ret == UADK_DIGEST_FAIL)) + goto out; + } - uadk_digest_soft_final(priv, digest); - digest_soft_cleanup(priv); + ret = uadk_digest_soft_final(priv, digest); - return UADK_DIGEST_SUCCESS; +out: + digest_soft_cleanup(priv); + return ret; } static int uadk_digest_poll(void *ctx) @@ -455,19 +463,31 @@ static int uadk_digest_update_inner(struct digest_priv_ctx *priv, const void *da do_soft_digest: if (priv->state == SEC_DIGEST_FIRST_UPDATING) { priv->switch_flag = UADK_DO_SOFT; - uadk_digest_soft_init(priv); + ret = uadk_digest_soft_init(priv); + if (!ret) + return ret; + /* filling buf has been executed */ if (processing_len < DIGEST_BLOCK_SIZE) { ret = uadk_digest_soft_update(priv, priv->data, DIGEST_BLOCK_SIZE); - if (ret != 1) - return ret; + if (!ret) + goto out; } - return uadk_digest_soft_update(priv, input_data, remain_len); + ret = uadk_digest_soft_update(priv, input_data, remain_len); + if (!ret) + goto out; + + /* the soft ctx will be free in the final stage. */ + return ret; } fprintf(stderr, "do soft digest failed during updating!\n"); return UADK_DIGEST_FAIL; + +out: + digest_soft_cleanup(priv); + return ret; } static int uadk_digest_update(struct digest_priv_ctx *priv, const void *data, size_t data_len) -- 2.33.0

From: Wenkai Lin <linwenkai6@hisilicon.com> Ensure that soft_ctx is initialized before invoking software calculation and reduces repeated judgments for digest soft init. Signed-off-by: Wenkai Lin <linwenkai6@hisilicon.com> Signed-off-by: JiangShui Yang <yangjiangshui@h-partners.com> --- src/uadk_digest.c | 62 ++++++++++++++++++----------------------------- 1 file changed, 24 insertions(+), 38 deletions(-) diff --git a/src/uadk_digest.c b/src/uadk_digest.c index cb593a8..c93b0ca 100644 --- a/src/uadk_digest.c +++ b/src/uadk_digest.c @@ -187,72 +187,55 @@ static EVP_MD *uadk_sha256; static EVP_MD *uadk_sha384; static EVP_MD *uadk_sha512; +/* OpenSSL 3.0 has no app_datasize, need set manually, + * check crypto/evp/legacy_md5.c: md5_md as example. + */ +#define SET_APP_DATASIZE(ctx_type) \ +do {\ + app_datasize = EVP_MD_meth_get_app_datasize(priv->soft_md); \ + if (!app_datasize) \ + app_datasize = sizeof(EVP_MD *) + sizeof(ctx_type); \ +} while (0) + static int uadk_e_digests_soft_md(struct digest_priv_ctx *priv) { - int app_datasize = 0; + int app_datasize; - if (priv->soft_md) + if (priv->soft_md && priv->soft_ctx) return 1; switch (priv->e_nid) { case NID_sm3: priv->soft_md = EVP_sm3(); + SET_APP_DATASIZE(SM3_CTX); break; case NID_md5: priv->soft_md = EVP_md5(); + SET_APP_DATASIZE(MD5_CTX); break; case NID_sha1: priv->soft_md = EVP_sha1(); + SET_APP_DATASIZE(SHA_CTX); break; case NID_sha224: priv->soft_md = EVP_sha224(); + SET_APP_DATASIZE(SHA256_CTX); break; case NID_sha256: priv->soft_md = EVP_sha256(); + SET_APP_DATASIZE(SHA256_CTX); break; case NID_sha384: priv->soft_md = EVP_sha384(); + SET_APP_DATASIZE(SHA512_CTX); break; case NID_sha512: priv->soft_md = EVP_sha512(); + SET_APP_DATASIZE(SHA512_CTX); break; default: - break; - } - - if (unlikely(priv->soft_md == NULL)) + fprintf(stderr, "digest nid %d is invalid.\n", priv->e_nid); return 0; - - app_datasize = EVP_MD_meth_get_app_datasize(priv->soft_md); - if (app_datasize == 0) { - /* OpenSSL 3.0 has no app_datasize, need set manually - * check crypto/evp/legacy_md5.c: md5_md as example - */ - switch (priv->e_nid) { - case NID_sm3: - app_datasize = sizeof(EVP_MD *) + sizeof(SM3_CTX); - break; - case NID_md5: - app_datasize = sizeof(EVP_MD *) + sizeof(MD5_CTX); - break; - case NID_sha1: - app_datasize = sizeof(EVP_MD *) + sizeof(SHA_CTX); - break; - case NID_sha224: - app_datasize = sizeof(EVP_MD *) + sizeof(SHA256_CTX); - break; - case NID_sha256: - app_datasize = sizeof(EVP_MD *) + sizeof(SHA256_CTX); - break; - case NID_sha384: - app_datasize = sizeof(EVP_MD *) + sizeof(SHA512_CTX); - break; - case NID_sha512: - app_datasize = sizeof(EVP_MD *) + sizeof(SHA512_CTX); - break; - default: - break; - } } if (priv->soft_ctx == NULL) { @@ -262,8 +245,10 @@ static int uadk_e_digests_soft_md(struct digest_priv_ctx *priv) return 0; ctx->md_data = OPENSSL_malloc(app_datasize); - if (ctx->md_data == NULL) + if (ctx->md_data == NULL) { + EVP_MD_CTX_free(ctx); return 0; + } priv->soft_ctx = ctx; priv->app_datasize = app_datasize; @@ -1033,6 +1018,7 @@ static int uadk_e_digest_copy(EVP_MD_CTX *to, const EVP_MD_CTX *from) } if (t->soft_ctx) { + t->soft_md = NULL; t->soft_ctx = NULL; ret = digest_soft_init(t); if (!ret) -- 2.33.0

From: Junchong Pan <panjunchong@h-partners.com> Fix printf format issues and Null pointer dereference. Signed-off-by: Junchong Pan <panjunchong@h-partners.com> Signed-off-by: Weili Qian <qianweili@huawei.com> Signed-off-by: JiangShui Yang <yangjiangshui@h-partners.com> --- src/uadk_digest.c | 2 +- src/uadk_ec.c | 2 +- src/uadk_prov_aead.c | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/uadk_digest.c b/src/uadk_digest.c index c93b0ca..01d05ee 100644 --- a/src/uadk_digest.c +++ b/src/uadk_digest.c @@ -234,7 +234,7 @@ static int uadk_e_digests_soft_md(struct digest_priv_ctx *priv) SET_APP_DATASIZE(SHA512_CTX); break; default: - fprintf(stderr, "digest nid %d is invalid.\n", priv->e_nid); + fprintf(stderr, "digest nid %u is invalid.\n", priv->e_nid); return 0; } diff --git a/src/uadk_ec.c b/src/uadk_ec.c index b1dbdfe..aaf0127 100644 --- a/src/uadk_ec.c +++ b/src/uadk_ec.c @@ -1192,7 +1192,7 @@ static int ecdh_get_shared_key(const EC_KEY *ecdh, *out = OPENSSL_zalloc(*outlen); if (!*out) { - fprintf(stderr, "failed to alloc output key, outlen = %lu\n", + fprintf(stderr, "failed to alloc output key, outlen = %zu\n", *outlen); return 0; } diff --git a/src/uadk_prov_aead.c b/src/uadk_prov_aead.c index 6f33f43..ce71c15 100644 --- a/src/uadk_prov_aead.c +++ b/src/uadk_prov_aead.c @@ -421,7 +421,7 @@ static int uadk_prov_do_aes_gcm_first(struct aead_priv_ctx *priv, unsigned char int ret; if (inlen > MAX_AAD_LEN) { - fprintf(stderr, "the aad len is out of range, aad len = %lu.\n", inlen); + fprintf(stderr, "the aad len is out of range, aad len = %zu.\n", inlen); return UADK_AEAD_FAIL; } -- 2.33.0

When hardware failures, insufficient queue resources, or small packet lengths occur, the service can switch to OpenSSL soft calculation. Signed-off-by: Qi Tao <taoqi10@huawei.com> Signed-off-by: JiangShui Yang <yangjiangshui@h-partners.com> --- src/uadk_prov_aead.c | 312 ++++++++++++++++++++++++++++++++++------- src/uadk_prov_cipher.c | 83 +++++++---- src/uadk_prov_digest.c | 153 ++++++++++++-------- 3 files changed, 416 insertions(+), 132 deletions(-) diff --git a/src/uadk_prov_aead.c b/src/uadk_prov_aead.c index ce71c15..54e0115 100644 --- a/src/uadk_prov_aead.c +++ b/src/uadk_prov_aead.c @@ -40,6 +40,7 @@ #define UADK_OSSL_FAIL 0 #define UADK_AEAD_SUCCESS 1 +#define SWITCH_TO_SOFT 2 #define UADK_AEAD_FAIL (-1) #define UNINITIALISED_SIZET ((size_t)-1) @@ -52,6 +53,8 @@ #define PROV_CIPHER_FLAG_CUSTOM_IV 0x0002 #define AEAD_FLAGS (PROV_CIPHER_FLAG_AEAD | PROV_CIPHER_FLAG_CUSTOM_IV) +#define UADK_DO_SOFT (-0xE0) +#define UADK_DO_HW (-0xF0) #define UADK_AEAD_DEF_CTXS 2 #define UADK_AEAD_OP_NUM 1 @@ -94,6 +97,10 @@ struct aead_priv_ctx { struct wd_aead_req req; enum uadk_aead_mode mode; handle_t sess; + + int stream_switch_flag; /* soft calculation switch flag for stream mode */ + EVP_CIPHER_CTX *sw_ctx; + EVP_CIPHER *sw_aead; }; struct aead_info { @@ -108,6 +115,18 @@ static struct aead_info aead_info_table[] = { { NID_aes_256_gcm, WD_CIPHER_AES, WD_CIPHER_GCM } }; +static EVP_CIPHER_CTX *EVP_CIPHER_CTX_dup(const EVP_CIPHER_CTX *in) +{ + EVP_CIPHER_CTX *out = EVP_CIPHER_CTX_new(); + + if (out != NULL && !EVP_CIPHER_CTX_copy(out, in)) { + EVP_CIPHER_CTX_free(out); + out = NULL; + } + + return out; +} + static int uadk_aead_poll(void *ctx) { __u64 rx_cnt = 0; @@ -134,6 +153,128 @@ static void uadk_aead_mutex_infork(void) pthread_mutex_unlock(&aead_mutex); } +static int uadk_fetch_sw_aead(struct aead_priv_ctx *priv) +{ + if (priv->sw_aead) + return UADK_AEAD_SUCCESS; + + switch (priv->nid) { + case NID_aes_128_gcm: + priv->sw_aead = EVP_CIPHER_fetch(NULL, "AES-128-GCM", "provider=default"); + break; + case NID_aes_192_gcm: + priv->sw_aead = EVP_CIPHER_fetch(NULL, "AES-192-GCM", "provider=default"); + break; + case NID_aes_256_gcm: + priv->sw_aead = EVP_CIPHER_fetch(NULL, "AES-256-GCM", "provider=default"); + break; + default: + break; + } + + if (unlikely(priv->sw_aead == NULL)) { + fprintf(stderr, "aead failed to fetch\n"); + return UADK_AEAD_FAIL; + } + + return UADK_AEAD_SUCCESS; +} + +static int uadk_prov_aead_soft_init(struct aead_priv_ctx *priv, const unsigned char *key, + const unsigned char *iv, const OSSL_PARAM *params) +{ + int ret; + + if (!priv->sw_aead || !priv->sw_ctx) + return UADK_AEAD_FAIL; + + if (priv->req.op_type == WD_CIPHER_ENCRYPTION_DIGEST) + ret = EVP_EncryptInit_ex2(priv->sw_ctx, priv->sw_aead, key, iv, params); + else + ret = EVP_DecryptInit_ex2(priv->sw_ctx, priv->sw_aead, key, iv, params); + + if (!ret) { + fprintf(stderr, "aead soft init error!\n"); + return UADK_AEAD_FAIL; + } + + priv->stream_switch_flag = UADK_DO_SOFT; + + return UADK_AEAD_SUCCESS; +} + +static int uadk_aead_soft_update(struct aead_priv_ctx *priv, unsigned char *out, + int *outl, const unsigned char *in, size_t len) +{ + int ret; + + if (!priv->sw_aead || !priv->sw_ctx) + return UADK_AEAD_FAIL; + + if (priv->req.op_type == WD_CIPHER_ENCRYPTION_DIGEST) + ret = EVP_EncryptUpdate(priv->sw_ctx, out, outl, in, len); + else + ret = EVP_DecryptUpdate(priv->sw_ctx, out, outl, in, len); + + if (!ret) { + fprintf(stderr, "aead soft update error.\n"); + return UADK_AEAD_FAIL; + } + + priv->stream_switch_flag = UADK_DO_SOFT; + + return UADK_AEAD_SUCCESS; +} + +static int uadk_aead_soft_final(struct aead_priv_ctx *priv, unsigned char *digest, size_t *outl) +{ + int ret; + + if (!priv->sw_aead || !priv->sw_ctx) + goto error; + + if (priv->req.op_type == WD_CIPHER_ENCRYPTION_DIGEST) { + ret = EVP_EncryptFinal_ex(priv->sw_ctx, digest, (int *)outl); + if (!ret) + goto error; + + ret = EVP_CIPHER_CTX_ctrl(priv->sw_ctx, EVP_CTRL_GCM_GET_TAG, + priv->taglen, priv->buf); + if (!ret) + goto error; + } else { + ret = EVP_CIPHER_CTX_ctrl(priv->sw_ctx, EVP_CTRL_GCM_SET_TAG, + priv->taglen, priv->buf); + if (!ret) + goto error; + + ret = EVP_DecryptFinal_ex(priv->sw_ctx, digest, (int *)outl); + if (!ret) + goto error; + } + + priv->stream_switch_flag = 0; + + return UADK_AEAD_SUCCESS; + +error: + fprintf(stderr, "aead soft final failed.\n"); + return UADK_AEAD_FAIL; +} + +static void uadk_aead_soft_cleanup(struct aead_priv_ctx *priv) +{ + if (priv->sw_ctx) { + EVP_CIPHER_CTX_free(priv->sw_ctx); + priv->sw_ctx = NULL; + } + + if (priv->sw_aead) { + EVP_CIPHER_free(priv->sw_aead); + priv->sw_aead = NULL; + } +} + static int uadk_prov_aead_dev_init(struct aead_priv_ctx *priv) { struct wd_ctx_nums ctx_set_num; @@ -293,7 +434,8 @@ static void uadk_do_aead_async_prepare(struct aead_priv_ctx *priv, unsigned char } static int uadk_do_aead_sync_inner(struct aead_priv_ctx *priv, unsigned char *out, - const unsigned char *in, size_t inlen, enum wd_aead_msg_state state) + const unsigned char *in, size_t inlen, + enum wd_aead_msg_state state) { int ret; @@ -315,21 +457,17 @@ static int uadk_do_aead_sync_inner(struct aead_priv_ctx *priv, unsigned char *ou return UADK_AEAD_FAIL; } - return inlen; + return UADK_AEAD_SUCCESS; } static int uadk_do_aead_sync(struct aead_priv_ctx *priv, unsigned char *out, - const unsigned char *in, size_t inlen) + const unsigned char *in, size_t inlen) { size_t nbytes, tail, processing_len, max_mid_len; const unsigned char *in_block = in; unsigned char *out_block = out; int ret; - /* Due to a hardware limitation, zero-length aad using block mode. */ - if (!priv->req.assoc_bytes) - return uadk_do_aead_sync_inner(priv, out, in, inlen, AEAD_MSG_BLOCK); - tail = inlen % AES_BLOCK_SIZE; nbytes = inlen - tail; max_mid_len = AEAD_BLOCK_SIZE - priv->req.assoc_bytes; @@ -354,11 +492,11 @@ static int uadk_do_aead_sync(struct aead_priv_ctx *priv, unsigned char *out, return UADK_AEAD_FAIL; } - return inlen; + return UADK_AEAD_SUCCESS; } static int uadk_do_aead_async(struct aead_priv_ctx *priv, struct async_op *op, - unsigned char *out, const unsigned char *in, size_t inlen) + unsigned char *out, const unsigned char *in, size_t inlen) { struct uadk_e_cb_info cb_param; int cnt = 0; @@ -416,11 +554,14 @@ static int uadk_do_aead_async(struct aead_priv_ctx *priv, struct async_op *op, } static int uadk_prov_do_aes_gcm_first(struct aead_priv_ctx *priv, unsigned char *out, - const unsigned char *in, size_t inlen) + const unsigned char *in, size_t inlen) { int ret; if (inlen > MAX_AAD_LEN) { + if (priv->mode != ASYNC_MODE) + return SWITCH_TO_SOFT; + fprintf(stderr, "the aad len is out of range, aad len = %zu.\n", inlen); return UADK_AEAD_FAIL; } @@ -428,20 +569,23 @@ static int uadk_prov_do_aes_gcm_first(struct aead_priv_ctx *priv, unsigned char priv->req.assoc_bytes = inlen; /* Asynchronous jobs use the block mode. */ - if (priv->mode == ASYNC_MODE || !priv->req.assoc_bytes) { + if (priv->mode == ASYNC_MODE) { memcpy(priv->data, in, inlen); return UADK_AEAD_SUCCESS; } + if (!priv->req.assoc_bytes) + return SWITCH_TO_SOFT; + ret = uadk_do_aead_sync_inner(priv, out, in, inlen, AEAD_MSG_FIRST); if (unlikely(ret < 0)) - return UADK_AEAD_FAIL; + return SWITCH_TO_SOFT; return UADK_AEAD_SUCCESS; } static int uadk_prov_do_aes_gcm_update(struct aead_priv_ctx *priv, unsigned char *out, - const unsigned char *in, size_t inlen) + const unsigned char *in, size_t inlen) { struct async_op *op; int ret; @@ -464,9 +608,12 @@ static int uadk_prov_do_aes_gcm_update(struct aead_priv_ctx *priv, unsigned char } free(op); - return inlen; + return UADK_AEAD_SUCCESS; } + if (priv->stream_switch_flag == UADK_DO_SOFT) + return SWITCH_TO_SOFT; + return uadk_do_aead_sync(priv, out, in, inlen); free_notification: @@ -477,7 +624,7 @@ free_op: } static int uadk_prov_do_aes_gcm_final(struct aead_priv_ctx *priv, unsigned char *out, - const unsigned char *in, size_t inlen) + const unsigned char *in, size_t inlen) { int ret; @@ -500,8 +647,8 @@ out: } static int uadk_prov_do_aes_gcm(struct aead_priv_ctx *priv, unsigned char *out, - size_t *outl, size_t outsize, - const unsigned char *in, size_t inlen) + size_t *outl, size_t outsize, + const unsigned char *in, size_t inlen) { int ret; @@ -543,8 +690,8 @@ static OSSL_FUNC_cipher_set_ctx_params_fn uadk_prov_aead_set_ctx_params; static OSSL_FUNC_cipher_settable_ctx_params_fn uadk_prov_aead_settable_ctx_params; static int uadk_prov_aead_cipher(void *vctx, unsigned char *out, size_t *outl, - size_t outsize, const unsigned char *in, - size_t inl) + size_t outsize, const unsigned char *in, + size_t inl) { struct aead_priv_ctx *priv = (struct aead_priv_ctx *)vctx; int ret; @@ -566,11 +713,11 @@ static int uadk_prov_aead_cipher(void *vctx, unsigned char *out, size_t *outl, } static int uadk_prov_aead_stream_update(void *vctx, unsigned char *out, - size_t *outl, size_t outsize, - const unsigned char *in, size_t inl) + size_t *outl, size_t outsize, + const unsigned char *in, size_t inl) { struct aead_priv_ctx *priv = (struct aead_priv_ctx *)vctx; - int ret; + int ret, outlen; if (!vctx) return UADK_OSSL_FAIL; @@ -580,18 +727,36 @@ static int uadk_prov_aead_stream_update(void *vctx, unsigned char *out, return UADK_OSSL_FAIL; } + if (priv->stream_switch_flag == UADK_DO_SOFT) + goto do_soft; ret = uadk_prov_do_aes_gcm(priv, out, outl, outsize, in, inl); - if (ret < 0) { + if (ret == SWITCH_TO_SOFT) + goto do_soft; + else if (ret < 0) { fprintf(stderr, "stream data update failed.\n"); return UADK_OSSL_FAIL; + } else { + *outl = inl; + return UADK_AEAD_SUCCESS; } - *outl = inl; +do_soft: + if (priv->stream_switch_flag != UADK_DO_SOFT) { + ret = uadk_prov_aead_soft_init(priv, priv->key, priv->iv, NULL); + if (ret <= 0) + return UADK_OSSL_FAIL; + } + + ret = uadk_aead_soft_update(priv, out, &outlen, in, inl); + if (ret <= 0) + return UADK_OSSL_FAIL; + + *outl = outlen; return UADK_AEAD_SUCCESS; } static int uadk_prov_aead_stream_final(void *vctx, unsigned char *out, - size_t *outl, size_t outsize) + size_t *outl, size_t outsize) { struct aead_priv_ctx *priv = (struct aead_priv_ctx *)vctx; int ret; @@ -599,6 +764,9 @@ static int uadk_prov_aead_stream_final(void *vctx, unsigned char *out, if (!vctx || !out || !outl) return UADK_OSSL_FAIL; + if (priv->stream_switch_flag == UADK_DO_SOFT) + goto do_soft; + ret = uadk_prov_do_aes_gcm(priv, out, outl, outsize, NULL, 0); if (ret < 0) { fprintf(stderr, "stream data final failed, ret = %d\n", ret); @@ -607,6 +775,15 @@ static int uadk_prov_aead_stream_final(void *vctx, unsigned char *out, *outl = 0; return UADK_AEAD_SUCCESS; + +do_soft: + ret = uadk_aead_soft_final(priv, out, outl); + if (ret) { + *outl = 0; + return UADK_AEAD_SUCCESS; + } + + return UADK_OSSL_FAIL; } static int uadk_get_aead_info(struct aead_priv_ctx *priv) @@ -630,9 +807,8 @@ static int uadk_get_aead_info(struct aead_priv_ctx *priv) return UADK_AEAD_SUCCESS; } -static int uadk_prov_aead_init(struct aead_priv_ctx *priv, - const unsigned char *key, size_t keylen, - const unsigned char *iv, size_t ivlen) +static int uadk_prov_aead_init(struct aead_priv_ctx *priv, const unsigned char *key, size_t keylen, + const unsigned char *iv, size_t ivlen, const OSSL_PARAM *params) { int ret; @@ -655,16 +831,26 @@ static int uadk_prov_aead_init(struct aead_priv_ctx *priv, priv->key_set = KEY_STATE_SET; } + priv->stream_switch_flag = 0; + + if (uadk_get_sw_offload_state()) + uadk_fetch_sw_aead(priv); + ret = uadk_prov_aead_dev_init(priv); - if (unlikely(ret < 0)) - return UADK_OSSL_FAIL; + if (unlikely(ret < 0)) { + if (ASYNC_get_current_job()) + return UADK_OSSL_FAIL; + + fprintf(stderr, "aead switch to soft init.!\n"); + return uadk_prov_aead_soft_init(priv, key, iv, params); + } return UADK_AEAD_SUCCESS; } static int uadk_prov_aead_einit(void *vctx, const unsigned char *key, size_t keylen, - const unsigned char *iv, size_t ivlen, - const OSSL_PARAM params[]) + const unsigned char *iv, size_t ivlen, + const OSSL_PARAM params[]) { struct aead_priv_ctx *priv = (struct aead_priv_ctx *)vctx; @@ -674,12 +860,12 @@ static int uadk_prov_aead_einit(void *vctx, const unsigned char *key, size_t key priv->req.op_type = WD_CIPHER_ENCRYPTION_DIGEST; priv->enc = 1; - return uadk_prov_aead_init(priv, key, keylen, iv, ivlen); + return uadk_prov_aead_init(priv, key, keylen, iv, ivlen, params); } static int uadk_prov_aead_dinit(void *vctx, const unsigned char *key, size_t keylen, - const unsigned char *iv, size_t ivlen, - const OSSL_PARAM params[]) + const unsigned char *iv, size_t ivlen, + const OSSL_PARAM params[]) { struct aead_priv_ctx *priv = (struct aead_priv_ctx *)vctx; @@ -689,7 +875,7 @@ static int uadk_prov_aead_dinit(void *vctx, const unsigned char *key, size_t key priv->req.op_type = WD_CIPHER_DECRYPTION_DIGEST; priv->enc = 0; - return uadk_prov_aead_init(priv, key, keylen, iv, ivlen); + return uadk_prov_aead_init(priv, key, keylen, iv, ivlen, params); } static const OSSL_PARAM uadk_prov_settable_ctx_params[] = { @@ -869,8 +1055,8 @@ static const OSSL_PARAM *uadk_prov_aead_gettable_params(ossl_unused void *provct } static int uadk_cipher_aead_get_params(OSSL_PARAM params[], unsigned int md, - uint64_t flags, size_t kbits, - size_t blkbits, size_t ivbits) + uint64_t flags, size_t kbits, + size_t blkbits, size_t ivbits) { OSSL_PARAM *p; @@ -910,24 +1096,46 @@ static int uadk_cipher_aead_get_params(OSSL_PARAM params[], unsigned int md, static void *uadk_prov_aead_dupctx(void *ctx) { - struct aead_priv_ctx *priv, *ret; + struct aead_priv_ctx *dst_ctx, *src_ctx; + int ret; - priv = (struct aead_priv_ctx *)ctx; - if (!priv) + src_ctx = (struct aead_priv_ctx *)ctx; + if (!src_ctx) return NULL; - ret = OPENSSL_memdup(priv, sizeof(*priv)); - if (!ret) + dst_ctx = OPENSSL_memdup(src_ctx, sizeof(*src_ctx)); + if (!dst_ctx) return NULL; - ret->sess = 0; - ret->data = OPENSSL_memdup(priv->data, AEAD_BLOCK_SIZE << 1); - if (!ret->data) { - OPENSSL_clear_free(ret, sizeof(*ret)); - return NULL; + dst_ctx->sess = 0; + dst_ctx->data = OPENSSL_memdup(src_ctx->data, AEAD_BLOCK_SIZE << 1); + if (!dst_ctx->data) + goto free_ctx; + + if (dst_ctx->sw_ctx) { + dst_ctx->sw_ctx = EVP_CIPHER_CTX_dup(src_ctx->sw_ctx); + if (!dst_ctx->sw_ctx) { + fprintf(stderr, "EVP_CIPHER_CTX_dup failed in ctx copy.\n"); + goto free_data; + } } - return ret; + if (dst_ctx->sw_aead) { + ret = EVP_CIPHER_up_ref(dst_ctx->sw_aead); + if (!ret) + goto free_dup; + } + + return dst_ctx; + +free_dup: + if (dst_ctx->sw_ctx) + EVP_CIPHER_CTX_free(dst_ctx->sw_ctx); +free_data: + OPENSSL_clear_free(dst_ctx->data, AEAD_BLOCK_SIZE << 1); +free_ctx: + OPENSSL_clear_free(dst_ctx, sizeof(*dst_ctx)); + return NULL; } static void uadk_prov_aead_freectx(void *ctx) @@ -943,6 +1151,9 @@ static void uadk_prov_aead_freectx(void *ctx) if (priv->data) OPENSSL_clear_free(priv->data, AEAD_BLOCK_SIZE << 1); + if (priv->sw_ctx) + uadk_aead_soft_cleanup(priv); + OPENSSL_clear_free(priv, sizeof(*priv)); } @@ -965,6 +1176,9 @@ static void *uadk_##nm##_newctx(void *provctx) \ ctx->ivlen = iv_len; \ ctx->nid = e_nid; \ ctx->taglen = tag_len; \ + ctx->sw_ctx = EVP_CIPHER_CTX_new(); \ + if (ctx->sw_ctx == NULL) \ + fprintf(stderr, "EVP_AEAD_CTX_new failed.\n"); \ strncpy(ctx->alg_name, #algnm, ALG_NAME_SIZE - 1); \ \ return ctx; \ diff --git a/src/uadk_prov_cipher.c b/src/uadk_prov_cipher.c index eb31f2d..db4a957 100644 --- a/src/uadk_prov_cipher.c +++ b/src/uadk_prov_cipher.c @@ -180,7 +180,7 @@ static struct cts_mode_name2id_st cts_modes[] = { { WD_CIPHER_CBC_CS3, OSSL_CIPHER_CTS_MODE_CS3, UADK_CIPHER_CTS_CS3_NAME }, }; -const char *ossl_cipher_cbc_cts_mode_id2name(unsigned int id) +static const char *ossl_cipher_cbc_cts_mode_id2name(unsigned int id) { size_t i; @@ -191,7 +191,7 @@ const char *ossl_cipher_cbc_cts_mode_id2name(unsigned int id) return NULL; } -int ossl_cipher_cbc_cts_mode_name2id(const char *name) +static int ossl_cipher_cbc_cts_mode_name2id(const char *name) { size_t i; @@ -283,12 +283,20 @@ static int uadk_fetch_sw_cipher(struct cipher_priv_ctx *priv) case ID_sm4_ctr: priv->sw_cipher = EVP_CIPHER_fetch(NULL, "SM4-CTR", "provider=default"); break; + case ID_aes_128_xts: + priv->sw_cipher = EVP_CIPHER_fetch(NULL, "AES-128-XTS", "provider=default"); + break; + case ID_aes_256_xts: + priv->sw_cipher = EVP_CIPHER_fetch(NULL, "AES-256-XTS", "provider=default"); + break; default: break; } - if (unlikely(priv->sw_cipher == NULL)) + if (unlikely(priv->sw_cipher == NULL)) { + fprintf(stderr, "cipher failed to fetch\n"); return UADK_P_FAIL; + } return UADK_P_SUCCESS; } @@ -297,28 +305,34 @@ static int uadk_prov_cipher_sw_init(struct cipher_priv_ctx *priv, const unsigned char *key, const unsigned char *iv) { - if (!uadk_fetch_sw_cipher(priv)) + if (!priv->sw_cipher || !priv->sw_ctx) return UADK_P_FAIL; if (!EVP_CipherInit_ex2(priv->sw_ctx, priv->sw_cipher, key, iv, priv->enc, NULL)) { - fprintf(stderr, "SW cipher init error!\n"); + fprintf(stderr, "cipher soft init failed!\n"); return UADK_P_FAIL; } - priv->switch_threshold = SMALL_PACKET_OFFLOAD_THRESHOLD_DEFAULT; + priv->switch_flag = UADK_DO_SOFT; return UADK_P_SUCCESS; } -static int uadk_prov_cipher_soft_work(struct cipher_priv_ctx *priv, unsigned char *out, - int *outl, const unsigned char *in, size_t len) +static int uadk_prov_cipher_soft_update(struct cipher_priv_ctx *priv, unsigned char *out, + int *outl, const unsigned char *in, size_t len) { - if (priv->sw_cipher == NULL) + if (!priv->sw_cipher || !priv->sw_ctx) return UADK_P_FAIL; + if (!EVP_CipherInit_ex2(priv->sw_ctx, priv->sw_cipher, priv->key, priv->iv, + priv->enc, NULL)) { + fprintf(stderr, "cipher soft init error!\n"); + return UADK_P_FAIL; + } + if (!EVP_CipherUpdate(priv->sw_ctx, out, outl, in, len)) { - fprintf(stderr, "EVP_CipherUpdate sw_ctx failed.\n"); + fprintf(stderr, "cipher soft update error!\n"); return UADK_P_FAIL; } @@ -328,22 +342,25 @@ static int uadk_prov_cipher_soft_work(struct cipher_priv_ctx *priv, unsigned cha } static int uadk_prov_cipher_soft_final(struct cipher_priv_ctx *priv, unsigned char *out, - size_t *outl) + size_t *outl) { int sw_final_len = 0; - if (priv->sw_cipher == NULL) + if (!priv->sw_cipher || !priv->sw_ctx) return UADK_P_FAIL; if (!EVP_CipherFinal_ex(priv->sw_ctx, out, &sw_final_len)) { - fprintf(stderr, "EVP_CipherFinal_ex sw_ctx failed.\n"); + fprintf(stderr, "cipher soft final failed.\n"); return UADK_P_FAIL; } + *outl = sw_final_len; + priv->switch_flag = 0; + return UADK_P_SUCCESS; } -static void uadk_prov_cipher_dev_init(struct cipher_priv_ctx *priv); +static int uadk_prov_cipher_dev_init(struct cipher_priv_ctx *priv); static int uadk_cipher_poll(void *ctx) { @@ -407,10 +424,17 @@ static int uadk_prov_cipher_init(struct cipher_priv_ctx *priv, priv->key_set = 1; } - if (enable_sw_offload) - return uadk_prov_cipher_sw_init(priv, key, iv); + priv->switch_flag = 0; + priv->switch_threshold = SMALL_PACKET_OFFLOAD_THRESHOLD_DEFAULT; - uadk_prov_cipher_dev_init(priv); + if (uadk_get_sw_offload_state()) + uadk_fetch_sw_cipher(priv); + + ret = uadk_prov_cipher_dev_init(priv); + if (unlikely(ret <= 0)) { + fprintf(stderr, "cipher switch to soft init!\n"); + return uadk_prov_cipher_sw_init(priv, key, iv); + } return UADK_P_SUCCESS; } @@ -488,7 +512,7 @@ static void uadk_cipher_mutex_infork(void) pthread_mutex_unlock(&cipher_mutex); } -static void uadk_prov_cipher_dev_init(struct cipher_priv_ctx *priv) +static int uadk_prov_cipher_dev_init(struct cipher_priv_ctx *priv) { int ret; @@ -501,6 +525,7 @@ static void uadk_prov_cipher_dev_init(struct cipher_priv_ctx *priv) ctx_set_num = calloc(UADK_CIPHER_OP_NUM, sizeof(*ctx_set_num)); if (!ctx_set_num) { fprintf(stderr, "failed to alloc ctx_set_size!\n"); + ret = UADK_P_FAIL; goto init_err; } @@ -510,6 +535,7 @@ static void uadk_prov_cipher_dev_init(struct cipher_priv_ctx *priv) if (!cparams.bmp) { fprintf(stderr, "failed to create nodemask!\n"); free(ctx_set_num); + ret = UADK_P_FAIL; goto init_err; } @@ -524,6 +550,7 @@ static void uadk_prov_cipher_dev_init(struct cipher_priv_ctx *priv) if (unlikely(ret)) { fprintf(stderr, "failed to init cipher!\n"); + ret = UADK_P_FAIL; goto init_err; } @@ -531,8 +558,11 @@ static void uadk_prov_cipher_dev_init(struct cipher_priv_ctx *priv) async_register_poll_fn(ASYNC_TASK_CIPHER, uadk_cipher_poll); } + ret = UADK_P_SUCCESS; + init_err: pthread_mutex_unlock(&cipher_mutex); + return ret; } static int uadk_prov_cipher_ctx_init(struct cipher_priv_ctx *priv) @@ -552,7 +582,9 @@ static int uadk_prov_cipher_ctx_init(struct cipher_priv_ctx *priv) if (priv->switch_flag == UADK_DO_SOFT) return UADK_P_FAIL; - uadk_prov_cipher_dev_init(priv); + ret = uadk_prov_cipher_dev_init(priv); + if (ret <= 0) + return UADK_P_FAIL; /* dec and enc use the same op */ params.type = 0; @@ -802,13 +834,12 @@ do_soft: * 1. small packets * 2. already choose DO_SOFT, can be hw fail case or following sw case */ - ret = uadk_prov_cipher_soft_work(priv, out, &outlint, in, inlen); + ret = uadk_prov_cipher_soft_update(priv, out, &outlint, in, inlen); if (ret) { *outl = outlint; return UADK_P_SUCCESS; } - fprintf(stderr, "do soft ciphers failed.\n"); return UADK_P_FAIL; } @@ -859,8 +890,8 @@ static int uadk_prov_cipher_cipher(void *vctx, unsigned char *output, size_t *ou return UADK_P_SUCCESS; } -static int uadk_prov_cipher_block_encrypto(struct cipher_priv_ctx *priv, - unsigned char *out, size_t *outl, size_t outsize) +static int uadk_prov_cipher_block_encrypto(struct cipher_priv_ctx *priv, unsigned char *out, + size_t *outl, size_t outsize) { size_t blksz = priv->blksize; int ret; @@ -891,8 +922,8 @@ static int uadk_prov_cipher_block_encrypto(struct cipher_priv_ctx *priv, return UADK_P_SUCCESS; } -static int uadk_prov_cipher_block_decrypto(struct cipher_priv_ctx *priv, - unsigned char *out, size_t *outl, size_t outsize) +static int uadk_prov_cipher_block_decrypto(struct cipher_priv_ctx *priv, unsigned char *out, + size_t *outl, size_t outsize) { size_t blksz = priv->blksize; int ret; @@ -1012,7 +1043,7 @@ static int uadk_prov_cipher_stream_update(void *vctx, unsigned char *output, do_soft: /* have isseu if both using hw and soft partly */ - ret = uadk_prov_cipher_soft_work(priv, output, &len, input, inl); + ret = uadk_prov_cipher_soft_update(priv, output, &len, input, inl); if (ret) { *outl = len; return UADK_P_SUCCESS; diff --git a/src/uadk_prov_digest.c b/src/uadk_prov_digest.c index a2a5f09..7a5bfff 100644 --- a/src/uadk_prov_digest.c +++ b/src/uadk_prov_digest.c @@ -70,18 +70,6 @@ struct digest_prov { static struct digest_prov dprov; static pthread_mutex_t digest_mutex = PTHREAD_MUTEX_INITIALIZER; -struct evp_md_ctx_st { - const EVP_MD *digest; - /* Functional reference if 'digest' is ENGINE-provided */ - ENGINE *engine; - unsigned long flags; - void *md_data; - /* Public key context for sign/verify */ - EVP_PKEY_CTX *pctx; - /* Update function: usually copied from EVP_MD */ - int (*update)(EVP_MD_CTX *ctx, const void *data, size_t count); -}; - struct digest_priv_ctx { handle_t sess; struct wd_digest_sess_setup setup; @@ -131,6 +119,17 @@ static struct digest_info digest_info_table[] = { 32, SHA_SMALL_PACKET_OFFLOAD_THRESHOLD_DEFAULT}, }; +static EVP_MD_CTX *EVP_MD_CTX_dup(const EVP_MD_CTX *in) +{ + EVP_MD_CTX *out = EVP_MD_CTX_new(); + + if (out != NULL && !EVP_MD_CTX_copy_ex(out, in)) { + EVP_MD_CTX_free(out); + out = NULL; + } + return out; +} + static int uadk_digests_soft_md(struct digest_priv_ctx *priv) { if (priv->soft_md) @@ -147,53 +146,83 @@ static int uadk_digests_soft_md(struct digest_priv_ctx *priv) priv->soft_md = EVP_MD_fetch(NULL, OSSL_DIGEST_NAME_SHA1, "provider=default"); break; case NID_sha224: - priv->soft_md = EVP_MD_fetch(NULL, OSSL_DIGEST_NAME_SHA3_224, "provider=default"); + priv->soft_md = EVP_MD_fetch(NULL, OSSL_DIGEST_NAME_SHA2_224, "provider=default"); break; case NID_sha256: - priv->soft_md = EVP_MD_fetch(NULL, OSSL_DIGEST_NAME_SHA3_256, "provider=default"); + priv->soft_md = EVP_MD_fetch(NULL, OSSL_DIGEST_NAME_SHA2_256, "provider=default"); break; case NID_sha384: - priv->soft_md = EVP_MD_fetch(NULL, OSSL_DIGEST_NAME_SHA3_384, "provider=default"); + priv->soft_md = EVP_MD_fetch(NULL, OSSL_DIGEST_NAME_SHA2_384, "provider=default"); break; case NID_sha512: - priv->soft_md = EVP_MD_fetch(NULL, OSSL_DIGEST_NAME_SHA3_512, "provider=default"); + priv->soft_md = EVP_MD_fetch(NULL, OSSL_DIGEST_NAME_SHA2_512, "provider=default"); + break; + case NID_sha512_224: + priv->soft_md = EVP_MD_fetch(NULL, OSSL_DIGEST_NAME_SHA2_512_224, + "provider=default"); + break; + case NID_sha512_256: + priv->soft_md = EVP_MD_fetch(NULL, OSSL_DIGEST_NAME_SHA2_512_256, + "provider=default"); break; default: break; } - if (unlikely(priv->soft_md == NULL)) + if (unlikely(priv->soft_md == NULL)) { + fprintf(stderr, "digest failed to fetch\n"); return UADK_DIGEST_FAIL; + } return UADK_DIGEST_SUCCESS; } static int uadk_digest_soft_init(struct digest_priv_ctx *priv) { - if (priv->soft_md) - return EVP_DigestInit_ex(priv->soft_ctx, priv->soft_md, NULL); + if (!priv->soft_md || !priv->soft_ctx) + return UADK_DIGEST_FAIL; - return UADK_DIGEST_FAIL; + if (!EVP_DigestInit_ex(priv->soft_ctx, priv->soft_md, NULL)) { + fprintf(stderr, "soft digest init failed.\n"); + return UADK_DIGEST_FAIL; + } + + priv->switch_flag = UADK_DO_SOFT; + + return UADK_DIGEST_SUCCESS; } static int uadk_digest_soft_update(struct digest_priv_ctx *priv, const void *data, size_t len) { - if (priv->soft_md) - return EVP_DigestUpdate(priv->soft_ctx, data, len); + if (priv->soft_md == NULL) + return UADK_DIGEST_FAIL; - return UADK_DIGEST_FAIL; + if (!EVP_DigestUpdate(priv->soft_ctx, data, len)) { + fprintf(stderr, "soft digest update failed.\n"); + return UADK_DIGEST_FAIL; + } + + priv->switch_flag = UADK_DO_SOFT; + + return UADK_DIGEST_SUCCESS; } static int uadk_digest_soft_final(struct digest_priv_ctx *priv, unsigned char *digest) { - if (priv->soft_md) { - unsigned int digest_length; + unsigned int digest_length; - return EVP_DigestFinal_ex(priv->soft_ctx, digest, &digest_length); + if (priv->soft_md == NULL) + return UADK_DIGEST_FAIL; + + if (!EVP_DigestFinal_ex(priv->soft_ctx, digest, &digest_length)) { + fprintf(stderr, "soft digest final failed.\n"); + return UADK_DIGEST_FAIL; } - return UADK_DIGEST_FAIL; + priv->switch_flag = 0; + + return UADK_DIGEST_SUCCESS; } static void digest_soft_cleanup(struct digest_priv_ctx *priv) @@ -201,12 +230,8 @@ static void digest_soft_cleanup(struct digest_priv_ctx *priv) EVP_MD_CTX *ctx = priv->soft_ctx; if (ctx != NULL) { - if (ctx->md_data) { - OPENSSL_free(ctx->md_data); - ctx->md_data = NULL; - } EVP_MD_CTX_free(ctx); - ctx = NULL; + priv->soft_ctx = NULL; } if (priv->soft_md) { @@ -216,7 +241,7 @@ static void digest_soft_cleanup(struct digest_priv_ctx *priv) } static int uadk_digest_soft_work(struct digest_priv_ctx *priv, int len, - unsigned char *digest) + unsigned char *digest) { int ret; @@ -341,7 +366,7 @@ static int uadk_digest_ctx_init(struct digest_priv_ctx *priv) ret = uadk_prov_digest_dev_init(priv); if (unlikely(ret <= 0)) - goto soft_init; + return UADK_DIGEST_FAIL; /* Use the default numa parameters */ params.numa_id = -1; @@ -357,15 +382,7 @@ static int uadk_digest_ctx_init(struct digest_priv_ctx *priv) } } - if (enable_sw_offload) - uadk_digests_soft_md(priv); - return UADK_DIGEST_SUCCESS; - -soft_init: - pthread_mutex_unlock(&digest_mutex); - fprintf(stderr, "uadk failed to initialize digest.\n"); - return uadk_digest_soft_init(priv); } static void uadk_fill_mac_buffer_len(struct digest_priv_ctx *priv, bool is_end) @@ -445,14 +462,15 @@ static int uadk_digest_update_inner(struct digest_priv_ctx *priv, const void *da priv->state = SEC_DIGEST_DOING; priv->req.out = priv->out; - remain_len -= processing_len; - input_data += processing_len; ret = wd_do_digest_sync(priv->sess, &priv->req); if (ret) { fprintf(stderr, "do sec digest update failed, switch to soft digest.\n"); goto do_soft_digest; } + + remain_len -= processing_len; + input_data += processing_len; } while (remain_len > DIGEST_BLOCK_SIZE); priv->last_update_bufflen = remain_len; @@ -462,7 +480,6 @@ static int uadk_digest_update_inner(struct digest_priv_ctx *priv, const void *da do_soft_digest: if (priv->state == SEC_DIGEST_FIRST_UPDATING) { - priv->switch_flag = UADK_DO_SOFT; ret = uadk_digest_soft_init(priv); if (!ret) return ret; @@ -472,6 +489,9 @@ do_soft_digest: ret = uadk_digest_soft_update(priv, priv->data, DIGEST_BLOCK_SIZE); if (!ret) goto out; + + remain_len -= processing_len; + input_data += processing_len; } ret = uadk_digest_soft_update(priv, input_data, remain_len); @@ -548,6 +568,7 @@ static int uadk_do_digest_sync(struct digest_priv_ctx *priv) fprintf(stderr, "do sec digest sync failed, switch to soft digest.\n"); return UADK_DIGEST_FAIL; } + return UADK_DIGEST_SUCCESS; } @@ -558,7 +579,7 @@ static int uadk_do_digest_async(struct digest_priv_ctx *priv, struct async_op *o int cnt = 0; if (unlikely(priv->switch_flag == UADK_DO_SOFT)) { - fprintf(stderr, "async cipher init failed.\n"); + fprintf(stderr, "digest soft switching is not supported in asynchronous mode.\n"); return UADK_DIGEST_FAIL; } @@ -608,9 +629,11 @@ 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; + if (unlikely(priv->switch_flag != UADK_DO_SOFT)) { + ret = uadk_digest_ctx_init(priv); + if (ret != UADK_DIGEST_SUCCESS) + return UADK_DIGEST_FAIL; + } priv->req.in = priv->data; priv->req.out = priv->out; @@ -657,8 +680,8 @@ clear: return ret; } -static int uadk_digest_digest(struct digest_priv_ctx *priv, const void *data, size_t data_len, - unsigned char *digest) +static int uadk_digest_digest(struct digest_priv_ctx *priv, const void *data, + size_t data_len, unsigned char *digest) { struct async_op op; int ret; @@ -706,8 +729,7 @@ static void uadk_digest_cleanup(struct digest_priv_ctx *priv) if (priv->data) OPENSSL_clear_free(priv->data, DIGEST_BLOCK_SIZE); - if (priv->soft_ctx) - OPENSSL_clear_free(priv->soft_ctx, sizeof(EVP_MD_CTX)); + digest_soft_cleanup(priv); } static OSSL_FUNC_digest_freectx_fn uadk_prov_freectx; @@ -780,6 +802,7 @@ static void uadk_prov_freectx(void *dctx) static void *uadk_prov_dupctx(void *dctx) { struct digest_priv_ctx *dst_ctx, *src_ctx; + int ret; src_ctx = (struct digest_priv_ctx *)dctx; if (!dctx) @@ -809,15 +832,24 @@ static void *uadk_prov_dupctx(void *dctx) goto free_ctx; if (dst_ctx->soft_ctx) { - dst_ctx->soft_ctx = EVP_MD_CTX_new(); + dst_ctx->soft_ctx = EVP_MD_CTX_dup(src_ctx->soft_ctx); if (!dst_ctx->soft_ctx) { fprintf(stderr, "EVP_MD_CTX_new failed in ctx copy.\n"); goto free_data; } } + if (dst_ctx->soft_md) { + ret = EVP_MD_up_ref(dst_ctx->soft_md); + if (!ret) + goto free_dup; + } + return dst_ctx; +free_dup: + if (dst_ctx->soft_ctx) + EVP_MD_CTX_free(dst_ctx->soft_ctx); free_data: OPENSSL_clear_free(dst_ctx->data, DIGEST_BLOCK_SIZE); free_ctx: @@ -835,13 +867,20 @@ static int uadk_prov_init(void *dctx, const OSSL_PARAM params[]) return UADK_DIGEST_FAIL; } + if (uadk_get_sw_offload_state()) + uadk_digests_soft_md(priv); + ret = uadk_get_digest_info(priv); if (unlikely(!ret)) return UADK_DIGEST_FAIL; + priv->state = SEC_DIGEST_INIT; + ret = uadk_prov_digest_dev_init(priv); - if (unlikely(ret <= 0)) - return UADK_DIGEST_FAIL; + if (unlikely(ret <= 0)) { + fprintf(stderr, "digest switch to soft init!\n"); + return uadk_digest_soft_init(priv); + } return UADK_DIGEST_SUCCESS; } @@ -879,7 +918,7 @@ static int uadk_prov_final(void *dctx, unsigned char *out, return ret; } - if (unlikely(outl != NULL)) + if (outl) *outl = priv->md_size; return UADK_DIGEST_SUCCESS; -- 2.33.0

From: Chenghai Huang <huangchenghai2@huawei.com> The length information needs to be updated during software calculation. Signed-off-by: Chenghai Huang <huangchenghai2@huawei.com> Signed-off-by: JiangShui Yang <yangjiangshui@h-partners.com> --- src/uadk_digest.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/src/uadk_digest.c b/src/uadk_digest.c index 01d05ee..e07667d 100644 --- a/src/uadk_digest.c +++ b/src/uadk_digest.c @@ -705,14 +705,15 @@ static int digest_update_inner(EVP_MD_CTX *ctx, const void *data, size_t data_le priv->state = SEC_DIGEST_DOING; priv->req.out = priv->out; - left_len -= processing_len; - tmpdata += processing_len; ret = wd_do_digest_sync(priv->sess, &priv->req); if (ret) { fprintf(stderr, "do sec digest sync failed, switch to soft digest.\n"); goto do_soft_digest; } + + left_len -= processing_len; + tmpdata += processing_len; } while (left_len > DIGEST_BLOCK_SIZE); priv->last_update_bufflen = left_len; @@ -730,6 +731,9 @@ do_soft_digest: ret = digest_soft_update(priv, priv->data, DIGEST_BLOCK_SIZE); if (!ret) goto out; + + left_len -= processing_len; + tmpdata += processing_len; } ret = digest_soft_update(priv, tmpdata, left_len); -- 2.33.0
participants (1)
-
Qi Tao