diff --git a/ext/openssl/ossl_pkey.c b/ext/openssl/ossl_pkey.c index 24d0da468..1a8bc0294 100644 --- a/ext/openssl/ossl_pkey.c +++ b/ext/openssl/ossl_pkey.c @@ -104,7 +104,8 @@ ossl_pkey_read_generic(BIO *bio, VALUE pass) OSSL_BIO_reset(bio); if (OSSL_DECODER_CTX_set_input_type(dctx, "PEM") != 1) goto out; - while (OSSL_DECODER_from_bio(dctx, bio) != 1) { + for (;;) { + OSSL_DECODER_from_bio(dctx, bio); if (BIO_eof(bio)) goto out; pos2 = BIO_tell(bio); @@ -115,6 +116,17 @@ ossl_pkey_read_generic(BIO *bio, VALUE pass) out: OSSL_DECODER_CTX_free(dctx); + +#if !defined(OPENSSL_NO_EC) + if (pkey && EVP_PKEY_base_id(pkey) == EVP_PKEY_EC) { + const EC_KEY *ec_key = EVP_PKEY_get0_EC_KEY(pkey); + if (!EC_KEY_get0_public_key(ec_key) && !EC_KEY_get0_private_key(ec_key)) { + EVP_PKEY_free(pkey); + pkey = NULL; + } + } +#endif + return pkey; } #else diff --git a/test/openssl/test_pkey.rb b/test/openssl/test_pkey.rb index 544340e37..ca91ba6f7 100644 --- a/test/openssl/test_pkey.rb +++ b/test/openssl/test_pkey.rb @@ -147,6 +147,16 @@ def test_x25519 assert_equal [shared_secret].pack("H*"), alice.derive(bob) end + def test_invalid_pkey_valid_ecparam + priv_pem = <<~EOF + -----BEGIN EC PARAMETERS----- + BggqhkjOPQMBBw== + -----END EC PARAMETERS----- + EOF + + assert_raise(OpenSSL::PKey::PKeyError) { OpenSSL::PKey.read(priv_pem) } + end + def test_compare? key1 = Fixtures.pkey("rsa1024") key2 = Fixtures.pkey("rsa1024") diff --git a/test/openssl/test_pkey_ec.rb b/test/openssl/test_pkey_ec.rb index ffe5a94e5..877243016 100644 --- a/test/openssl/test_pkey_ec.rb +++ b/test/openssl/test_pkey_ec.rb @@ -199,6 +199,45 @@ def test_ECPrivateKey assert_equal pem, p256.export end + def test_ECPrivateKey_with_parameters + p256 = Fixtures.pkey("p256") + asn1 = OpenSSL::ASN1::Sequence([ + OpenSSL::ASN1::Integer(1), + OpenSSL::ASN1::OctetString(p256.private_key.to_s(2)), + OpenSSL::ASN1::ObjectId("prime256v1", 0, :EXPLICIT), + OpenSSL::ASN1::BitString(p256.public_key.to_octet_string(:uncompressed), + 1, :EXPLICIT) + ]) + key = OpenSSL::PKey::EC.new(asn1.to_der) + assert_predicate key, :private? + assert_same_ec p256, key + + in_pem = <<~EOF + -----BEGIN EC PARAMETERS----- + BggqhkjOPQMBBw== + -----END EC PARAMETERS----- + -----BEGIN EC PRIVATE KEY----- + MHcCAQEEIID49FDqcf1O1eO8saTgG70UbXQw9Fqwseliit2aWhH1oAoGCCqGSM49 + AwEHoUQDQgAEFglk2c+oVUIKQ64eZG9bhLNPWB7lSZ/ArK41eGy5wAzU/0G51Xtt + CeBUl+MahZtn9fO1JKdF4qJmS39dXnpENg== + -----END EC PRIVATE KEY----- + EOF + + out_pem = <<~EOF + -----BEGIN EC PRIVATE KEY----- + MHcCAQEEIID49FDqcf1O1eO8saTgG70UbXQw9Fqwseliit2aWhH1oAoGCCqGSM49 + AwEHoUQDQgAEFglk2c+oVUIKQ64eZG9bhLNPWB7lSZ/ArK41eGy5wAzU/0G51Xtt + CeBUl+MahZtn9fO1JKdF4qJmS39dXnpENg== + -----END EC PRIVATE KEY----- + EOF + + key = OpenSSL::PKey::EC.new(in_pem) + assert_same_ec p256, key + + assert_equal asn1.to_der, p256.to_der + assert_equal out_pem, p256.export + end + def test_ECPrivateKey_encrypted p256 = Fixtures.pkey("p256") # key = abcdef