From 345f876d8149f4450c4cc94eb47735c345da8311 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?K=C5=8Dan?= Date: Thu, 19 Feb 2026 00:23:05 -0700 Subject: [PATCH 1/3] fix: verify() resource leaks on error paths and dead cleanup (OpenSSL 3.x) Two issues in the OpenSSL 3.x verify path: 1. Error-path leaks: CHECK_OPEN_SSL during setup croaks immediately, leaking the EVP_PKEY_CTX and EVP_MD objects. 2. Dead cleanup code: EVP_MD_free and EVP_PKEY_CTX_free after the switch block were unreachable because XSRETURN_NO/XSRETURN_YES are longjmps that skip all subsequent code. Fix: use THROW/goto err pattern for setup errors, and free resources before the switch statement on the success path. Co-Authored-By: Claude Opus 4.6 --- RSA.xs | 33 +++++++++++++++++++++------------ 1 file changed, 21 insertions(+), 12 deletions(-) diff --git a/RSA.xs b/RSA.xs index 5033701..ded7987 100644 --- a/RSA.xs +++ b/RSA.xs @@ -1111,24 +1111,26 @@ PPCODE: #if OPENSSL_VERSION_NUMBER >= 0x30000000L { int verify_result; - EVP_PKEY_CTX *ctx; + int error = 0; + int verify_pad; + EVP_PKEY_CTX *ctx = NULL; + EVP_MD *md = NULL; + ctx = EVP_PKEY_CTX_new(p_rsa->rsa, NULL /* no engine */); - CHECK_OPEN_SSL(ctx); - CHECK_OPEN_SSL(EVP_PKEY_verify_init(ctx) == 1); - /* FIXME: Issue setting padding in some cases */ - int verify_pad = p_rsa->padding; + THROW(ctx); + THROW(EVP_PKEY_verify_init(ctx) == 1); + verify_pad = p_rsa->padding; if (p_rsa->padding != RSA_NO_PADDING) { verify_pad = RSA_PKCS1_PSS_PADDING; } - CHECK_OPEN_SSL(EVP_PKEY_CTX_set_rsa_padding(ctx, verify_pad) > 0); - EVP_MD* md = get_md_bynid(p_rsa->hashMode); - CHECK_OPEN_SSL(md != NULL); + THROW(EVP_PKEY_CTX_set_rsa_padding(ctx, verify_pad) > 0); + md = get_md_bynid(p_rsa->hashMode); + THROW(md != NULL); - int md_status; - CHECK_OPEN_SSL((md_status = EVP_PKEY_CTX_set_signature_md(ctx, md)) > 0); + THROW(EVP_PKEY_CTX_set_signature_md(ctx, md) > 0); if (p_rsa->padding == RSA_PKCS1_PSS_PADDING) { - CHECK_OPEN_SSL((md_status = EVP_PKEY_CTX_set_rsa_mgf1_md(ctx, md)) > 0); - CHECK_OPEN_SSL(EVP_PKEY_CTX_set_rsa_pss_saltlen(ctx, RSA_PSS_SALTLEN_DIGEST) > 0); + THROW(EVP_PKEY_CTX_set_rsa_mgf1_md(ctx, md) > 0); + THROW(EVP_PKEY_CTX_set_rsa_pss_saltlen(ctx, RSA_PSS_SALTLEN_DIGEST) > 0); } verify_result = EVP_PKEY_verify(ctx, sig, sig_length, digest, get_digest_length(p_rsa->hashMode)); @@ -1147,6 +1149,13 @@ PPCODE: CHECK_OPEN_SSL(0); break; } + + goto verify_done; + err: + if (md) EVP_MD_free(md); + if (ctx) EVP_PKEY_CTX_free(ctx); + CHECK_OPEN_SSL(0); + verify_done: ; } #else switch(RSA_verify(p_rsa->hashMode, From 2584807fb1265d7edf6eb6cef3e94e81e622d695 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?K=C5=8Dan?= Date: Wed, 11 Mar 2026 21:08:15 -0600 Subject: [PATCH 2/3] rebase: apply review feedback on #81 --- RSA.xs | 28 ++++++++-------------------- 1 file changed, 8 insertions(+), 20 deletions(-) diff --git a/RSA.xs b/RSA.xs index ded7987..34c07ce 100644 --- a/RSA.xs +++ b/RSA.xs @@ -1108,9 +1108,9 @@ PPCODE: } CHECK_OPEN_SSL(digest = get_message_digest(text_SV, p_rsa->hashMode)); -#if OPENSSL_VERSION_NUMBER >= 0x30000000L { int verify_result; +#if OPENSSL_VERSION_NUMBER >= 0x30000000L int error = 0; int verify_pad; EVP_PKEY_CTX *ctx = NULL; @@ -1136,34 +1136,22 @@ PPCODE: verify_result = EVP_PKEY_verify(ctx, sig, sig_length, digest, get_digest_length(p_rsa->hashMode)); EVP_MD_free(md); EVP_PKEY_CTX_free(ctx); - switch(verify_result) - { - case 0: - ERR_clear_error(); - XSRETURN_NO; - break; - case 1: - XSRETURN_YES; - break; - default: - CHECK_OPEN_SSL(0); - break; - } - goto verify_done; + goto verify_switch; err: if (md) EVP_MD_free(md); if (ctx) EVP_PKEY_CTX_free(ctx); CHECK_OPEN_SSL(0); - verify_done: ; - } + verify_switch: ; #else - switch(RSA_verify(p_rsa->hashMode, + verify_result = RSA_verify(p_rsa->hashMode, digest, get_digest_length(p_rsa->hashMode), sig, sig_length, - p_rsa->rsa)) + p_rsa->rsa); +#endif + switch(verify_result) { case 0: ERR_clear_error(); @@ -1176,7 +1164,7 @@ PPCODE: CHECK_OPEN_SSL(0); break; } -#endif + } } int From e69c9b0c527c8731f0b83ae6d0cfe5e5732d658d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?K=C5=8Dan?= Date: Sat, 14 Mar 2026 14:01:50 -0600 Subject: [PATCH 3/3] rebase: apply review feedback on #81 --- RSA.xs | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/RSA.xs b/RSA.xs index 34c07ce..a479548 100644 --- a/RSA.xs +++ b/RSA.xs @@ -1095,6 +1095,14 @@ verify(p_rsa, text_SV, sig_SV) rsaData* p_rsa; SV* text_SV; SV* sig_SV; +PREINIT: + int verify_result; +#if OPENSSL_VERSION_NUMBER >= 0x30000000L + int error = 0; + int verify_pad; + EVP_PKEY_CTX *ctx = NULL; + EVP_MD *md = NULL; +#endif PPCODE: { unsigned char* sig; @@ -1108,14 +1116,7 @@ PPCODE: } CHECK_OPEN_SSL(digest = get_message_digest(text_SV, p_rsa->hashMode)); - { - int verify_result; #if OPENSSL_VERSION_NUMBER >= 0x30000000L - int error = 0; - int verify_pad; - EVP_PKEY_CTX *ctx = NULL; - EVP_MD *md = NULL; - ctx = EVP_PKEY_CTX_new(p_rsa->rsa, NULL /* no engine */); THROW(ctx); THROW(EVP_PKEY_verify_init(ctx) == 1); @@ -1164,7 +1165,6 @@ PPCODE: CHECK_OPEN_SSL(0); break; } - } } int