diff options
author | Kazuki Yamaguchi <k@rhe.jp> | 2022-09-08 20:50:19 +0900 |
---|---|---|
committer | Kazuki Yamaguchi <k@rhe.jp> | 2022-09-08 20:50:19 +0900 |
commit | 7f5b5adcc57ff1402e17c992009588441f85bf3f (patch) | |
tree | f04042f727e924b73b6aa8b82a08e869ef22d16c /ext/openssl/ossl_pkey.c | |
parent | ed8375999b4bbb4dbbc6151f160634c45a973495 (diff) | |
parent | e5bbd015dcb4fd2c3c31f9024ee1e476087c148d (diff) | |
download | ruby-openssl-7f5b5adcc57ff1402e17c992009588441f85bf3f.tar.gz |
Merge branch 'maint-3.0'
* maint-3.0:
Ruby/OpenSSL 3.0.1
Ruby/OpenSSL 2.2.2
Ruby/OpenSSL 2.1.4
Make GitHub Actions happy on 2.1/2.2 branches
test/openssl/test_cipher: skip AES-CCM tests on OpenSSL <= 1.1.1b
pkey/ec: check existence of public key component before exporting
pkey: restore support for decoding "openssl ecparam -genkey" output
pkey: clear error queue before each OSSL_DECODER_from_bio() call
pkey/dsa: let PKey::DSA.generate choose appropriate q size
hmac: use EVP_PKEY_new_raw_private_key() if available
x509*: fix error queue leak in #extensions= and #attributes= methods
Check if the option is an Hash in `pkey_ctx_apply_options0()`
Diffstat (limited to 'ext/openssl/ossl_pkey.c')
-rw-r--r-- | ext/openssl/ossl_pkey.c | 46 |
1 files changed, 43 insertions, 3 deletions
diff --git a/ext/openssl/ossl_pkey.c b/ext/openssl/ossl_pkey.c index 24d0da46..ec39e8bd 100644 --- a/ext/openssl/ossl_pkey.c +++ b/ext/openssl/ossl_pkey.c @@ -99,17 +99,56 @@ ossl_pkey_read_generic(BIO *bio, VALUE pass) /* First check DER */ if (OSSL_DECODER_from_bio(dctx, bio) == 1) goto out; + OSSL_BIO_reset(bio); /* Then check PEM; multiple OSSL_DECODER_from_bio() calls may be needed */ - OSSL_BIO_reset(bio); if (OSSL_DECODER_CTX_set_input_type(dctx, "PEM") != 1) goto out; - while (OSSL_DECODER_from_bio(dctx, bio) != 1) { - if (BIO_eof(bio)) + /* + * First check for private key formats. This is to keep compatibility with + * ruby/openssl < 3.0 which decoded the following as a private key. + * + * $ openssl ecparam -name prime256v1 -genkey -outform PEM + * -----BEGIN EC PARAMETERS----- + * BggqhkjOPQMBBw== + * -----END EC PARAMETERS----- + * -----BEGIN EC PRIVATE KEY----- + * MHcCAQEEIAG8ugBbA5MHkqnZ9ujQF93OyUfL9tk8sxqM5Wv5tKg5oAoGCCqGSM49 + * AwEHoUQDQgAEVcjhJfkwqh5C7kGuhAf8XaAjVuG5ADwb5ayg/cJijCgs+GcXeedj + * 86avKpGH84DXUlB23C/kPt+6fXYlitUmXQ== + * -----END EC PRIVATE KEY----- + * + * While the first PEM block is a proper encoding of ECParameters, thus + * OSSL_DECODER_from_bio() would pick it up, ruby/openssl used to return + * the latter instead. Existing applications expect this behavior. + * + * 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. + */ + OSSL_DECODER_CTX_set_selection(dctx, EVP_PKEY_KEYPAIR); + while (1) { + if (OSSL_DECODER_from_bio(dctx, bio) == 1) goto out; + if (BIO_eof(bio)) + break; pos2 = BIO_tell(bio); if (pos2 < 0 || pos2 <= pos) + break; + ossl_clear_error(); + pos = pos2; + } + + OSSL_BIO_reset(bio); + OSSL_DECODER_CTX_set_selection(dctx, 0); + while (1) { + if (OSSL_DECODER_from_bio(dctx, bio) == 1) goto out; + if (BIO_eof(bio)) + break; + pos2 = BIO_tell(bio); + if (pos2 < 0 || pos2 <= pos) + break; + ossl_clear_error(); pos = pos2; } @@ -200,6 +239,7 @@ static VALUE pkey_ctx_apply_options0(VALUE args_v) { VALUE *args = (VALUE *)args_v; + Check_Type(args[1], T_HASH); rb_block_call(args[1], rb_intern("each"), 0, NULL, pkey_ctx_apply_options_i, args[0]); |