Skip to content

Commit 5ff4a31

Browse files
committed
Workaround: Fix OpenSSL::PKey.read that cannot parse PKey in the FIPS mode.
This commit is a workaround to avoid the error below that the `OpenSSL::PKey.read` fails with the OpenSSL 3.0 FIPS mode. ``` $ openssl genrsa -out key.pem 4096 $ ruby -e "require 'openssl'; OpenSSL::PKey.read(File.read('key.pem'))" -e:1:in `read': Could not parse PKey (OpenSSL::PKey::PKeyError) from -e:1:in `<main>' ``` The root cause is on the OpenSSL side. The `OSSL_DECODER_CTX_set_selection` doesn't apply the selection value properly if there are multiple providers, and a provider (e.g. "base" provider) handles the decoder implementation, and another provider (e.g. "fips" provider) handles the keys. The workaround is to create `OSSL_DECODER_CTX` variable each time without using the `OSSL_DECODER_CTX_set_selection`.
1 parent 01f06fd commit 5ff4a31

File tree

1 file changed

+21
-5
lines changed

1 file changed

+21
-5
lines changed

ext/openssl/ossl_pkey.c

Lines changed: 21 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -101,10 +101,9 @@ ossl_pkey_read_generic(BIO *bio, VALUE pass)
101101
goto out;
102102
OSSL_BIO_reset(bio);
103103

104-
/* Then check PEM; multiple OSSL_DECODER_from_bio() calls may be needed */
105-
if (OSSL_DECODER_CTX_set_input_type(dctx, "PEM") != 1)
106-
goto out;
107104
/*
105+
* Then check PEM; multiple OSSL_DECODER_from_bio() calls may be needed.
106+
*
108107
* First check for private key formats. This is to keep compatibility with
109108
* ruby/openssl < 3.0 which decoded the following as a private key.
110109
*
@@ -124,8 +123,19 @@ ossl_pkey_read_generic(BIO *bio, VALUE pass)
124123
*
125124
* Note that normally, the input is supposed to contain a single decodable
126125
* PEM block only, so this special handling should not create a new problem.
126+
*
127+
* Note that we need to create the OSSL_DECODER_CTX variable each time when
128+
* we use the different selection as a workaround.
129+
* https://github.com/openssl/openssl/issues/20657
127130
*/
128-
OSSL_DECODER_CTX_set_selection(dctx, EVP_PKEY_KEYPAIR);
131+
OSSL_DECODER_CTX_free(dctx);
132+
dctx = NULL;
133+
dctx = OSSL_DECODER_CTX_new_for_pkey(&pkey, "PEM", NULL, NULL,
134+
EVP_PKEY_KEYPAIR, NULL, NULL);
135+
if (!dctx)
136+
goto out;
137+
if (OSSL_DECODER_CTX_set_pem_password_cb(dctx, ossl_pem_passwd_cb, ppass) != 1)
138+
goto out;
129139
while (1) {
130140
if (OSSL_DECODER_from_bio(dctx, bio) == 1)
131141
goto out;
@@ -139,7 +149,13 @@ ossl_pkey_read_generic(BIO *bio, VALUE pass)
139149
}
140150

141151
OSSL_BIO_reset(bio);
142-
OSSL_DECODER_CTX_set_selection(dctx, 0);
152+
OSSL_DECODER_CTX_free(dctx);
153+
dctx = NULL;
154+
dctx = OSSL_DECODER_CTX_new_for_pkey(&pkey, "PEM", NULL, NULL, 0, NULL, NULL);
155+
if (!dctx)
156+
goto out;
157+
if (OSSL_DECODER_CTX_set_pem_password_cb(dctx, ossl_pem_passwd_cb, ppass) != 1)
158+
goto out;
143159
while (1) {
144160
if (OSSL_DECODER_from_bio(dctx, bio) == 1)
145161
goto out;

0 commit comments

Comments
 (0)