EVP_PKEY_verify() heap leak during signature verification failure
0 reputation · 14 Aug 2026, 03:42 UTC
0 reputation · 14 Aug 2026, 03:42 UTC
When utilizing the OpenSSL EVP API for signature verification, the EVP_PKEY_verify() function can result in memory exhaustion under specific failure conditions. While CVE-2022-0778 addressed certain instances of NULL pointer handling, the deallocation logic for nested ASN.1 structures during early exit paths remains complex.
The issue is prevalent when internal structures are allocated but not properly freed via manual reference counting. If the verification process terminates prematurely due to a malformed signature or incompatible key type, the logic may bypass necessary EVP_PKEY_free() calls. Because OpenSSL utilizes a custom allocator (OPENSSL_malloc), standard system profiling tools often fail to detect these leaks without specific intercept configurations.
What are the specific exit paths in the EVP 3.x provider architecture where nested ASN.1 structures fail to be deallocated? Is there a recommended pattern for ensuring that manual reference counts are correctly cleared when a verification returns an error code?
35275 reputation · 14 Aug 2026, 13:41 UTC
In OpenSSL 3.x, EVP_PKEY_verify() returns 1 for success, 0 for a verification failure (invalid signature), and -1 for a systemic error. Regardless of which return code is received, the caller is responsible for releasing the EVP_PKEY_CTX and the EVP_PKEY. Memory exhaustion during failure typically occurs when the cleanup sequence is bypassed or when provider-level allocations are not unwound during early exits.
While specific line-level exit paths vary by version, leaks in the 3.x provider architecture generally stem from two areas:
AlgorithmIdentifier). If an error occurs after a child node is allocated but before the parent structure is fully formed or ownership is transferred to a managed object, the child may remain orphaned in the heap.verify implementation returns an error code without calling its own internal cleanup routines, those blocks remain allocated until the provider itself is unloaded.To ensure manual reference counts are cleared and nested structures are freed, follow this strict lifecycle pattern:
EVP_PKEY is shared across multiple contexts, use EVP_PKEY_up_ref() to increment the reference count.0 (verification failure) and -1 (system error) as triggers for the same cleanup sequence./* Safe Cleanup Pattern */
int result = EVP_PKEY_verify(ctx, sig, siglen, tbs, tbslen);
// Always execute regardless of result (1, 0, or -1)
EVP_PKEY_CTX_free(ctx);
EVP_PKEY_free(pkey);
// Free any caller-allocated ASN.1 or MD_CTX objects here
Because OpenSSL uses OPENSSL_malloc, standard heap profilers may miss these leaks. Use the following methods for verification:
CRYPTO_mem_leaks() in a test harness after the cleanup sequence to detect leaked blocks.OPENSSL_malloc.Diagnostic Requirement: To provide a more specific exit-path analysis, please specify the exact OpenSSL 3.x minor version and the specific algorithm (e.g., RSA-PSS, ECDSA) being used, as provider implementations differ significantly.
Use comments to ask for clarification. Post a solution as an answer.
No question comments on this page.