From b8f7ba8e23fa63e9f7cebe62c7da8ee96d9279e6 Mon Sep 17 00:00:00 2001 From: Toddr Bot Date: Fri, 20 Mar 2026 07:13:46 +0000 Subject: [PATCH] fix: use canonical two-pass allocation in rsa_crypt() on 3.x On the OpenSSL 3.x path, rsa_crypt() pre-allocated the output buffer using EVP_PKEY_get_size() before calling the sizing pass. This meant: 1. A wasted alloc+free on the PSS padding early-exit path 2. A latent buffer overflow if the sizing call ever returned a value larger than EVP_PKEY_get_size() (not currently possible for RSA, but violates the API contract) 3. Inconsistency with sign(), which already uses the correct pattern Move the allocation into the version-specific blocks: - 3.x: allocate after the sizing call using the returned length - Pre-3.x: allocate with EVP_PKEY_get_size() as before (no sizing API) Initialize `to = NULL` so Safefree() in the error path is safe before allocation. Co-Authored-By: Claude Opus 4.6 --- RSA.xs | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/RSA.xs b/RSA.xs index 65c8078..c4948eb 100644 --- a/RSA.xs +++ b/RSA.xs @@ -350,7 +350,7 @@ SV* rsa_crypt(rsaData* p_rsa, SV* p_from, SIZE_T_INT to_length; int size; unsigned char* from; - UNSIGNED_CHAR *to; + UNSIGNED_CHAR *to = NULL; SV* sv; from = (unsigned char*) SvPV(p_from, from_length); @@ -361,11 +361,9 @@ SV* rsa_crypt(rsaData* p_rsa, SV* p_from, "Use use_pkcs1_oaep_padding() for encryption, or use_pkcs1_padding() with sign()/verify()."); } - CHECK_NEW(to, size, UNSIGNED_CHAR); #if OPENSSL_VERSION_NUMBER >= 0x30000000L if(p_rsa->padding == RSA_PKCS1_PSS_PADDING) { - Safefree(to); croak("PKCS#1 v2.1 RSA-PSS cannot be used for encryption operations call \"use_pkcs1_oaep_padding\" instead."); } @@ -387,6 +385,8 @@ SV* rsa_crypt(rsaData* p_rsa, SV* p_from, } THROW(EVP_PKEY_CTX_set_rsa_padding(ctx, crypt_pad) > 0); THROW(p_crypt(ctx, NULL, &to_length, from, from_length) == 1); + Newx(to, to_length, UNSIGNED_CHAR); + THROW(to); THROW(p_crypt(ctx, to, &to_length, from, from_length) == 1); EVP_PKEY_CTX_free(ctx); @@ -398,6 +398,7 @@ SV* rsa_crypt(rsaData* p_rsa, SV* p_from, CHECK_OPEN_SSL(0); crypt_done: #else + CHECK_NEW(to, size, UNSIGNED_CHAR); to_length = p_crypt( from_length, from, (unsigned char*) to, p_rsa->rsa, p_rsa->padding); #endif