diff options
author | Jun Aruga <[email protected]> | 2023-04-12 17:15:21 +0200 |
---|---|---|
committer | Kazuki Yamaguchi <[email protected]> | 2023-06-19 01:57:09 +0900 |
commit | 2a4834057b30a26c38ece3961b370c0b2ee59380 (patch) | |
tree | 477ee9bddab06e031a99f89a8016b94357bc9bef /ext/openssl/ossl_pkey.c | |
parent | 1965c09ee50b5202d45462cd8bc6224ca6e45ae9 (diff) |
[ruby/openssl] 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`.
https://github.com/ruby/openssl/commit/5ff4a31621
Diffstat (limited to 'ext/openssl/ossl_pkey.c')
-rw-r--r-- | ext/openssl/ossl_pkey.c | 26 |
1 files changed, 21 insertions, 5 deletions
diff --git a/ext/openssl/ossl_pkey.c b/ext/openssl/ossl_pkey.c index 0d16cce93b..a5baa21820 100644 --- a/ext/openssl/ossl_pkey.c +++ b/ext/openssl/ossl_pkey.c @@ -101,10 +101,9 @@ ossl_pkey_read_generic(BIO *bio, VALUE pass) goto out; OSSL_BIO_reset(bio); - /* Then check PEM; multiple OSSL_DECODER_from_bio() calls may be needed */ - if (OSSL_DECODER_CTX_set_input_type(dctx, "PEM") != 1) - goto out; /* + * Then check PEM; multiple OSSL_DECODER_from_bio() calls may be needed. + * * First check for private key formats. This is to keep compatibility with * ruby/openssl < 3.0 which decoded the following as a private key. * @@ -124,8 +123,19 @@ ossl_pkey_read_generic(BIO *bio, VALUE pass) * * Note that normally, the input is supposed to contain a single decodable * PEM block only, so this special handling should not create a new problem. + * + * Note that we need to create the OSSL_DECODER_CTX variable each time when + * we use the different selection as a workaround. + * https://github.com/openssl/openssl/issues/20657 */ - OSSL_DECODER_CTX_set_selection(dctx, EVP_PKEY_KEYPAIR); + OSSL_DECODER_CTX_free(dctx); + dctx = NULL; + dctx = OSSL_DECODER_CTX_new_for_pkey(&pkey, "PEM", NULL, NULL, + EVP_PKEY_KEYPAIR, NULL, NULL); + if (!dctx) + goto out; + if (OSSL_DECODER_CTX_set_pem_password_cb(dctx, ossl_pem_passwd_cb, ppass) != 1) + goto out; while (1) { if (OSSL_DECODER_from_bio(dctx, bio) == 1) goto out; @@ -139,7 +149,13 @@ ossl_pkey_read_generic(BIO *bio, VALUE pass) } OSSL_BIO_reset(bio); - OSSL_DECODER_CTX_set_selection(dctx, 0); + OSSL_DECODER_CTX_free(dctx); + dctx = NULL; + dctx = OSSL_DECODER_CTX_new_for_pkey(&pkey, "PEM", NULL, NULL, 0, NULL, NULL); + if (!dctx) + goto out; + if (OSSL_DECODER_CTX_set_pem_password_cb(dctx, ossl_pem_passwd_cb, ppass) != 1) + goto out; while (1) { if (OSSL_DECODER_from_bio(dctx, bio) == 1) goto out; |