diff options
| author | Kazuki Yamaguchi <k@rhe.jp> | 2025-09-16 19:29:08 +0900 |
|---|---|---|
| committer | git <svn-admin@ruby-lang.org> | 2025-09-17 12:18:17 +0000 |
| commit | 08e7b5f2bdef276c7ea65fa3b01f53c1062acf8d (patch) | |
| tree | 4e74dfd8ecf60188b18975735c18e83f5d9dfb93 | |
| parent | 9c85a94f5f1b553ccac3e7f232087424d1854f97 (diff) | |
[ruby/openssl] Revert "pkey: stop retrying after non-retryable error from OSSL_DECODER"
This reverts commit https://github.com/ruby/openssl/commit/5347880c6eb0 and
https://github.com/ruby/openssl/commit/985ba27d6339.
These commits attempted to stop processing after the first relevant PEM
block, whether it is successful or not, when the input contains multiple
keys.
It turned out that it cannot be reliably determined using the
OSSL_DECODER API. There is an edge case where OSSL_DECODER_from_bio()
reports "unsupported" even though the input actually contains an error:
https://redirect.github.com/ruby/openssl/pull/931#discussion_r2347813807
Revert the changes for now and keep the existing behavior, as partial
support does not seem worth the added complexity.
https://github.com/ruby/openssl/commit/319cd4952a
| -rw-r--r-- | ext/openssl/ossl_pkey.c | 41 | ||||
| -rw-r--r-- | test/openssl/test_pkey.rb | 11 |
2 files changed, 14 insertions, 38 deletions
diff --git a/ext/openssl/ossl_pkey.c b/ext/openssl/ossl_pkey.c index ee6a7a988f..0fed03332f 100644 --- a/ext/openssl/ossl_pkey.c +++ b/ext/openssl/ossl_pkey.c @@ -83,15 +83,13 @@ ossl_pkey_wrap(EVP_PKEY *pkey) # include <openssl/decoder.h> static EVP_PKEY * -ossl_pkey_read(BIO *bio, const char *input_type, int selection, VALUE pass, - int *retryable) +ossl_pkey_read(BIO *bio, const char *input_type, int selection, VALUE pass) { void *ppass = (void *)pass; OSSL_DECODER_CTX *dctx; EVP_PKEY *pkey = NULL; int pos = 0, pos2; - *retryable = 0; dctx = OSSL_DECODER_CTX_new_for_pkey(&pkey, input_type, NULL, NULL, selection, NULL, NULL); if (!dctx) @@ -102,25 +100,17 @@ ossl_pkey_read(BIO *bio, const char *input_type, int selection, VALUE pass, goto out; while (1) { if (OSSL_DECODER_from_bio(dctx, bio) == 1) + goto out; + if (BIO_eof(bio)) break; - // Error queue may not be populated in OpenSSL < 3.0.11 and < 3.1.3 - // https://github.com/openssl/openssl/pull/21603 - unsigned long err = ERR_peek_error(); - if (err && ERR_GET_REASON(err) != ERR_R_UNSUPPORTED) - break; - if (BIO_eof(bio) == 1) { - *retryable = 1; - break; - } pos2 = BIO_tell(bio); - if (pos2 < 0 || pos2 <= pos) { - *retryable = 1; + if (pos2 < 0 || pos2 <= pos) break; - } ossl_clear_error(); pos = pos2; } out: + OSSL_BIO_reset(bio); OSSL_DECODER_CTX_free(dctx); return pkey; } @@ -128,6 +118,7 @@ ossl_pkey_read(BIO *bio, const char *input_type, int selection, VALUE pass, EVP_PKEY * ossl_pkey_read_generic(BIO *bio, VALUE pass) { + EVP_PKEY *pkey = NULL; /* First check DER, then check PEM. */ const char *input_types[] = {"DER", "PEM"}; int input_type_num = (int)(sizeof(input_types) / sizeof(char *)); @@ -176,22 +167,18 @@ ossl_pkey_read_generic(BIO *bio, VALUE pass) EVP_PKEY_PUBLIC_KEY }; int selection_num = (int)(sizeof(selections) / sizeof(int)); + int i, j; - for (int i = 0; i < input_type_num; i++) { - for (int j = 0; j < selection_num; j++) { - if (i || j) { - ossl_clear_error(); - BIO_reset(bio); + for (i = 0; i < input_type_num; i++) { + for (j = 0; j < selection_num; j++) { + pkey = ossl_pkey_read(bio, input_types[i], selections[j], pass); + if (pkey) { + goto out; } - - int retryable; - EVP_PKEY *pkey = ossl_pkey_read(bio, input_types[i], selections[j], - pass, &retryable); - if (pkey || !retryable) - return pkey; } } - return NULL; + out: + return pkey; } #else EVP_PKEY * diff --git a/test/openssl/test_pkey.rb b/test/openssl/test_pkey.rb index 24a595333b..8066c4dc19 100644 --- a/test/openssl/test_pkey.rb +++ b/test/openssl/test_pkey.rb @@ -124,17 +124,6 @@ class OpenSSL::TestPKey < OpenSSL::PKeyTestCase } } assert_equal(1, called) - - # Incorrect passphrase returned by the block. The input contains two PEM - # blocks. - called = 0 - assert_raise(OpenSSL::PKey::PKeyError) { - OpenSSL::PKey.read(encrypted_pem + encrypted_pem) { - called += 1 - "incorrect_passphrase" - } - } - assert_equal(1, called) end def test_s_read_passphrase_tty |
