openssl: improve handling of password for encrypted PEM

* ext/openssl/ossl.c (ossl_pem_passwd_value): Added. Convert the
  argument to String with StringValue() and validate the length is in
  4..PEM_BUFSIZE. PEM_BUFSIZE is a macro defined in OpenSSL headers.
  (ossl_pem_passwd_cb): When reading/writing encrypted PEM format, we
  used to pass the password to PEM_def_callback() directly but it was
  problematic. It is not NUL character safe. And surprisingly, it
  silently truncates the password to 1024 bytes.  [GH ruby/openssl#51]

* ext/openssl/ossl.h: Add function prototype declaration of newly
  added ossl_pem_passwd_value().

* ext/openssl/ossl_pkey.c (ossl_pkey_new_from_data): Use
  ossl_pem_passwd_value() to validate the password String.

* ext/openssl/ossl_pkey_dsa.c (ossl_dsa_initialize, ossl_dsa_export):
  ditto.

* ext/openssl/ossl_pkey_ec.c (ossl_ec_key_initialize,
  ossl_ec_key_to_string): ditto.

* ext/openssl/ossl_pkey_rsa.c (ossl_rsa_initialize, ossl_rsa_export):
  ditto.

* test/openssl/test_pkey_{dsa,ec,rsa}.rb: test this.

git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@55087 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
This commit is contained in:
rhe 2016-05-20 15:05:25 +00:00
parent 02cafdf491
commit f52ab6e494
10 changed files with 151 additions and 70 deletions

View file

@ -276,6 +276,24 @@ AwEAAQ==
assert(pem)
end
def test_export_password_funny
key = OpenSSL::TestUtils::TEST_KEY_RSA1024
# this assertion may fail in the future because of OpenSSL change.
# the current upper limit is 1024
assert_raise(OpenSSL::OpenSSLError) do
key.export(OpenSSL::Cipher.new('AES-128-CBC'), 'secr' * 1024)
end
# password containing NUL byte
pem = key.export(OpenSSL::Cipher.new('AES-128-CBC'), "pass\0wd")
assert_raise(ArgumentError) do
OpenSSL::PKey.read(pem, "pass")
end
key2 = OpenSSL::PKey.read(pem, "pass\0wd")
assert(key2.private?)
key3 = OpenSSL::PKey::RSA.new(pem, "pass\0wd")
assert(key3.private?)
end
private
def check_PUBKEY(asn1, key)