From: Zhushuai Yin <yinzhushuai@huawei.com> When no SEC device is available and uadk_provider falls back to software computation, the HMAC soft path allocates a fresh OSSL_LIB_CTX per HMAC ctx and tears it down on every final. Each allocation forces OpenSSL to repopulate the OBJ/method name tables, showing up as OBJ_obj2txt / OPENSSL_LH_doall_arg / OSSL_LIB_CTX_free hotspots in flame graphs (nginx + no-device scenario accounts for ~8% of total time). Additionally, EVP_MAC_fetch with the provider libctx and NULL property recursively dispatches back to uadk_prov_hmac_newctx, causing stack overflow and coredump. The fix uses "provider=default" property filter, mirroring uadk_prov_aead.c's soft-path pattern. The OSSL_OP_MAC query case also lacks the version-check break gate present in OSSL_OP_DIGEST, so uadk_provider claims HMAC even when no device exists and sw_offload is enabled, adding per-request dispatch overhead. The _alg() calls for pkey operations are moved after version check to avoid unnecessary UACCE device list traversal when falling back to default provider. This patch: - Reuse the provider libctx with "provider=default" property filter instead of allocating a per-ctx OSSL_LIB_CTX in HMAC soft fallback - Add version-check break to OSSL_OP_MAC, aligning with OSSL_OP_DIGEST - Move _alg() calls after version check in OSSL_OP_SIGNATURE/KEYMGMT/ ASYM_CIPHER/KEYEXCH to skip device traversal when not needed - Fix uadk_unquery OSSL_OP_MAC to use needs_version_check pattern, avoiding unconditional OPENSSL_free on default provider's array Signed-off-by: Zhushuai Yin <yinzhushuai@huawei.com> --- src/uadk_prov_hmac.c | 37 +++++++++++++++++++------------------ src/uadk_prov_init.c | 25 ++++++++++++++----------- 2 files changed, 33 insertions(+), 29 deletions(-) diff --git a/src/uadk_prov_hmac.c b/src/uadk_prov_hmac.c index 3f7de9e..83b0809 100644 --- a/src/uadk_prov_hmac.c +++ b/src/uadk_prov_hmac.c @@ -76,7 +76,6 @@ struct hmac_priv_ctx { 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; @@ -124,12 +123,6 @@ static int uadk_create_hmac_soft_ctx(struct hmac_priv_ctx *priv) if (priv->soft_md) return UADK_P_SUCCESS; - priv->soft_libctx = OSSL_LIB_CTX_new(); - if (!priv->soft_libctx) { - UADK_ERR("new soft libctx failed.\n"); - return UADK_P_FAIL; - } - switch (priv->alg_id) { case NID_md5: case NID_sm3: @@ -140,7 +133,24 @@ static int uadk_create_hmac_soft_ctx(struct hmac_priv_ctx *priv) case NID_sha512: case NID_sha512_224: case NID_sha512_256: - priv->soft_md = EVP_MAC_fetch(priv->soft_libctx, "HMAC", NULL); + /* + * Reuse the provider libctx (already bootstrapped once at + * provider load and warm for the process lifetime) instead of + * allocating a fresh OSSL_LIB_CTX per HMAC ctx. A fresh libctx + * would force OpenSSL to repopulate the OBJ/method tables on + * every fetch and tear them down on every final, which shows up + * as OBJ_obj2txt / OPENSSL_LH_doall_arg / OSSL_LIB_CTX_free + * hotspots in flame graphs (nginx + no-device case). + * + * Must use "provider=default" property to explicitly fetch from + * the default provider, NOT uadk_provider itself. The provider + * libctx has "?provider=uadk_provider" as default property (see + * uadk_prov_init.c uadk_set_default_prov), so without this filter + * the fetch would recursively dispatch back to + * uadk_prov_hmac_newctx -> stack overflow -> coredump. + * This mirrors uadk_prov_aead.c's soft-path pattern. + */ + priv->soft_md = EVP_MAC_fetch(priv->libctx, "HMAC", "provider=default"); break; default: break; @@ -148,7 +158,7 @@ static int uadk_create_hmac_soft_ctx(struct hmac_priv_ctx *priv) if (unlikely(!priv->soft_md)) { UADK_ERR("hmac soft fetch failed.\n"); - goto free_libctx; + return UADK_P_FAIL; } priv->soft_ctx = EVP_MAC_CTX_new(priv->soft_md); @@ -162,9 +172,6 @@ static int uadk_create_hmac_soft_ctx(struct hmac_priv_ctx *priv) 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_P_FAIL; } @@ -236,11 +243,6 @@ static void hmac_soft_cleanup(struct hmac_priv_ctx *priv) priv->soft_md = NULL; } - if (priv->soft_libctx) { - OSSL_LIB_CTX_free(priv->soft_libctx); - priv->soft_libctx = NULL; - } - priv->switch_flag = 0; } @@ -827,7 +829,6 @@ static void *uadk_prov_hmac_dupctx(void *hctx) 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) { UADK_ERR("create soft_ctx failed in ctx copy.\n"); diff --git a/src/uadk_prov_init.c b/src/uadk_prov_init.c index 38d7426..6ab2c73 100644 --- a/src/uadk_prov_init.c +++ b/src/uadk_prov_init.c @@ -731,6 +731,9 @@ static const OSSL_ALGORITHM *uadk_query(void *provctx, int operation_id, break; return uadk_generate_digests_array(); case OSSL_OP_MAC: + ver = uadk_prov_digest_version(); + if (!ver && uadk_get_sw_offload_state()) + break; return uadk_generate_hmac_array(); case OSSL_OP_CIPHER: ver = uadk_prov_cipher_version(); @@ -740,35 +743,35 @@ static const OSSL_ALGORITHM *uadk_query(void *provctx, int operation_id, return uadk_generate_cipher_array_v2(); return uadk_generate_cipher_array_v3(); case OSSL_OP_SIGNATURE: - uadk_prov_signature_alg(); ver = uadk_prov_pkey_version(); if (!ver && uadk_get_sw_offload_state()) break; - else if (ver == HW_ASYM_ENC_V2) + uadk_prov_signature_alg(); + if (ver == HW_ASYM_ENC_V2) return uadk_generate_signature_array_v2(); return uadk_generate_signature_array_v3(); case OSSL_OP_KEYMGMT: - uadk_prov_keymgmt_alg(); ver = uadk_prov_pkey_version(); if (!ver && uadk_get_sw_offload_state()) break; - else if (ver == HW_ASYM_ENC_V2) + uadk_prov_keymgmt_alg(); + if (ver == HW_ASYM_ENC_V2) return uadk_generate_keymgmt_array_v2(); return uadk_generate_keymgmt_array_v3(); case OSSL_OP_ASYM_CIPHER: - uadk_prov_asym_cipher_alg(); ver = uadk_prov_pkey_version(); if (!ver && uadk_get_sw_offload_state()) break; - else if (ver == HW_ASYM_ENC_V2) + uadk_prov_asym_cipher_alg(); + if (ver == HW_ASYM_ENC_V2) return uadk_generate_asym_cipher_array_v2(); return uadk_generate_asym_cipher_array_v3(); case OSSL_OP_KEYEXCH: - uadk_prov_keyexch_alg(); ver = uadk_prov_pkey_version(); if (!ver && uadk_get_sw_offload_state()) break; - else if (ver == HW_ASYM_ENC_V2) + uadk_prov_keyexch_alg(); + if (ver == HW_ASYM_ENC_V2) return uadk_generate_keyexch_array_v2(); return uadk_generate_keyexch_array_v3(); default: @@ -829,9 +832,9 @@ static void uadk_unquery(void *provctx, int operation_id, needs_version_check = 1; break; case OSSL_OP_MAC: - if (algs) - OPENSSL_free((void *)algs); - return; + ver = uadk_prov_digest_version(); + needs_version_check = 1; + break; default: break; } -- 2.43.0