Skip to content

fix: canonical two-pass buffer allocation in rsa_crypt()#131

Merged
timlegge merged 1 commit into
cpan-authors:mainfrom
toddr-bot:koan.toddr.bot/fix-rsa-crypt-buffer-alloc
Mar 21, 2026
Merged

fix: canonical two-pass buffer allocation in rsa_crypt()#131
timlegge merged 1 commit into
cpan-authors:mainfrom
toddr-bot:koan.toddr.bot/fix-rsa-crypt-buffer-alloc

Conversation

@toddr-bot
Copy link
Copy Markdown
Contributor

@toddr-bot toddr-bot commented Mar 20, 2026

What

Use OpenSSL 3.x's two-pass allocation pattern in rsa_crypt() — allocate after the sizing call, not before.

Why

The function pre-allocated the output buffer with EVP_PKEY_get_size() before calling the sizing pass. This:

  1. Wasted an alloc+free on the PSS early-exit path
  2. Created a latent buffer overflow if the sizing call ever returned larger than EVP_PKEY_get_size()
  3. Was inconsistent with sign(), which already uses the correct two-pass pattern

How

  • Moved CHECK_NEW into the pre-3.x #else block (where there's no sizing API)
  • On 3.x, allocate with Newx() after the sizing call using the returned to_length
  • Initialize to = NULL so Safefree() in the error path is safe before allocation
  • Removed the now-unnecessary Safefree(to) before the PSS croak

Testing

All 497 tests pass. The existing encrypt/decrypt/private_encrypt/public_decrypt tests with all padding modes exercise this code path thoroughly.

🤖 Generated with Claude Code


Quality Report

Changes: 1 file changed, 4 insertions(+), 3 deletions(-)

Code scan: clean

Tests: passed (OK)

Branch hygiene: clean

Generated by Kōan post-mission quality pipeline

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 <noreply@anthropic.com>
@timlegge timlegge marked this pull request as ready for review March 21, 2026 01:15
@timlegge timlegge merged commit ba0236b into cpan-authors:main Mar 21, 2026
81 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants