Skip to content

pkey: fix repeated passphrase prompts in OpenSSL::PKey.read #931

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 3 commits into
base: master
Choose a base branch
from

Conversation

rhenium
Copy link
Member

@rhenium rhenium commented Aug 12, 2025

This PR fixes two issues shown in #927, which affects OpenSSL 3.0 or later.


pkey: add more tests for OpenSSL::PKey.read

Add tests covering edge cases in the current behavior to prevent accidental regressions. The next patches will update the OpenSSL 3.x path.


pkey: pass pem_password_cb to OSSL_DECODER only when it is needed

Specify OSSL_DECODER_CTX_set_pem_password_cb() only when we expect a passphrase-protected private key.

OSSL_DECODER appears to try to decrypt every PEM block in the input even when the PEM header does not match the requested selection. This can cause repeated prompts for a passphrase in a single OpenSSL::PKey.read call.


pkey: stop retrying after non-retryable error from OSSL_DECODER

Continue processing only when OSSL_DECODER_from_bio() returns the error code ERR_R_UNSUPPORTED. Otherwise, raise an exception without retrying decoding the input in another format.

This fixes another case where OpenSSL::PKey.read prompts for a passphrase multiple times when the input contains more than one passphrase-protected PEM blocks and the first one cannot be decoded.

I am not entirely sure if error code ERR_R_UNSUPPORTED is considered part of the public interface of OpenSSL, but this seems to be the only option available and is the approach used internally by the PEM_read_bio_*() functions.


Fixes #927

Add tests covering edge cases in the current behavior to prevent
accidental regressions. The next patches will update the OpenSSL 3.x
path.
Specify OSSL_DECODER_CTX_set_pem_password_cb() only when we expect a
passphrase-protected private key.

OSSL_DECODER appears to try to decrypt every PEM block in the input even
when the PEM header does not match the requested selection. This can
cause repeated prompts for a passphrase in a single OpenSSL::PKey.read
call.
Continue processing only when OSSL_DECODER_from_bio() returns the error
code ERR_R_UNSUPPORTED. Otherwise, raise an exception without retrying
decoding the input in another format.

This fixes another case where OpenSSL::PKey.read prompts for a
passphrase multiple times when the input contains more than one
passphrase-protected PEM blocks and the first one cannot be decoded.

I am not entirely sure if error code ERR_R_UNSUPPORTED is considered
part of the public interface of OpenSSL, but this seems to be the only
option available and is the approach used internally by the
PEM_read_bio_*() functions.

Fixes ruby#927
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.

Enter PEM pass phrase does not work correctly
1 participant