From f51e2f6539558c735493491e14bba670afd7517f Mon Sep 17 00:00:00 2001 From: nobu Date: Tue, 2 Feb 2016 23:25:40 +0000 Subject: Fix typo on OpenSSL::PKey doc [ci skip] * ext/openssl/ossl_pkey.c (Init_ossl_pkey): [DOC] Fix typo "encrypted" to "decrypted". [Fix GH-1235] git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@53723 b2dd03c8-39d4-4d8f-98ff-823fe69b080e --- ext/openssl/ossl_pkey.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ext/openssl/ossl_pkey.c b/ext/openssl/ossl_pkey.c index e758c9e3..7e3154af 100644 --- a/ext/openssl/ossl_pkey.c +++ b/ext/openssl/ossl_pkey.c @@ -374,7 +374,7 @@ Init_ossl_pkey(void) * algorithm consists of two parts: a public key that may be distributed * to others and a private key that needs to remain secret. * - * Messages encrypted with a public key can only be encrypted by + * Messages encrypted with a public key can only be decrypted by * recipients that are in possession of the associated private key. * Since public key algorithms are considerably slower than symmetric * key algorithms (cf. OpenSSL::Cipher) they are often used to establish -- cgit v1.2.3 From b9030f08f9d7eb081cf28a58e252ae61cf3590e4 Mon Sep 17 00:00:00 2001 From: nobu Date: Fri, 19 Feb 2016 07:45:58 +0000 Subject: test: use assert_not_* git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@53871 b2dd03c8-39d4-4d8f-98ff-823fe69b080e --- test/test_buffering.rb | 8 ++++---- test/test_cipher.rb | 4 ++-- test/test_ssl.rb | 2 +- 3 files changed, 7 insertions(+), 7 deletions(-) diff --git a/test/test_buffering.rb b/test/test_buffering.rb index fe07b46a..1f552c93 100644 --- a/test/test_buffering.rb +++ b/test/test_buffering.rb @@ -43,19 +43,19 @@ class OpenSSL::TestBuffering < Test::Unit::TestCase def test_flush @io.write 'a' - refute @io.sync + assert_not_predicate @io, :sync assert_empty @io.string assert_equal @io, @io.flush - refute @io.sync + assert_not_predicate @io, :sync assert_equal 'a', @io.string end def test_flush_error @io.write 'a' - refute @io.sync + assert_not_predicate @io, :sync assert_empty @io.string def @io.syswrite *a @@ -66,7 +66,7 @@ class OpenSSL::TestBuffering < Test::Unit::TestCase @io.flush end - refute @io.sync, 'sync must not change' + assert_not_predicate @io, :sync, 'sync must not change' end def test_getc diff --git a/test/test_cipher.rb b/test/test_cipher.rb index 89c176f4..dae069e4 100644 --- a/test/test_cipher.rb +++ b/test/test_cipher.rb @@ -143,9 +143,9 @@ class OpenSSL::TestCipher < Test::Unit::TestCase def test_authenticated cipher = OpenSSL::Cipher.new('aes-128-gcm') - assert(cipher.authenticated?) + assert_predicate(cipher, :authenticated?) cipher = OpenSSL::Cipher.new('aes-128-cbc') - refute(cipher.authenticated?) + assert_not_predicate(cipher, :authenticated?) end def test_aes_gcm diff --git a/test/test_ssl.rb b/test/test_ssl.rb index f5ca3e9f..cbffc981 100644 --- a/test/test_ssl.rb +++ b/test/test_ssl.rb @@ -752,7 +752,7 @@ class OpenSSL::TestSSL < OpenSSL::SSLTestCase ctx3 = OpenSSL::SSL::SSLContext.new ctx3.ciphers = "DH" - refute_predicate ctx3, :frozen? + assert_not_predicate ctx3, :frozen? ctx2 = OpenSSL::SSL::SSLContext.new ctx2.ciphers = "DH" -- cgit v1.2.3 From f26a186d95478b8acdc8fc8253ee4e09616c3c06 Mon Sep 17 00:00:00 2001 From: normal Date: Mon, 14 Mar 2016 01:20:14 +0000 Subject: document OpenSSL::SSL::SSLContext#setup as MT-unsafe On a cursory inspection, using rb_block_call for extra_chain_cert is thread-unsafe. There may be other instances of thread-unsafe behavior in this method, but one is enough. * ext/openssl/ossl_ssl.c (ossl_sslctx_setup): document as MT-unsafe [ruby-core:73803] [Bug #12069] git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@54097 b2dd03c8-39d4-4d8f-98ff-823fe69b080e --- ext/openssl/ossl_ssl.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/ext/openssl/ossl_ssl.c b/ext/openssl/ossl_ssl.c index 4075d6f0..90ce762a 100644 --- a/ext/openssl/ossl_ssl.c +++ b/ext/openssl/ossl_ssl.c @@ -687,8 +687,8 @@ ossl_sslctx_set_options(VALUE self, VALUE options) * ctx.setup => nil # thereafter * * This method is called automatically when a new SSLSocket is created. - * Normally you do not need to call this method (unless you are writing an - * extension in C). + * However, it is not thread-safe and must be called before creating + * SSLSocket objects in a multi-threaded program. */ static VALUE ossl_sslctx_setup(VALUE self) -- cgit v1.2.3 From 8a2328c6923a823f8a4b00e557728e4716825cc2 Mon Sep 17 00:00:00 2001 From: nobu Date: Fri, 25 Mar 2016 04:38:13 +0000 Subject: openssl: fix build when NPN is disabled by OpenSSL * ext/openssl/extconf.rb: check SSL_CTX_set_next_proto_select_cb function rather than OPENSSL_NPN_NEGOTIATED macro. it exists even if it is disabled by OpenSSL configuration. [ruby-core:74384] [Bug #12182] * ext/openssl/ossl_ssl.c: update #ifdef(s) as above. * test/openssl/test_ssl.rb: skip NPN tests if NPN is disabled. git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@54258 b2dd03c8-39d4-4d8f-98ff-823fe69b080e --- ext/openssl/extconf.rb | 2 +- ext/openssl/ossl_ssl.c | 39 ++++++++++++++++++++------------------- test/test_ssl.rb | 4 +++- 3 files changed, 24 insertions(+), 21 deletions(-) diff --git a/ext/openssl/extconf.rb b/ext/openssl/extconf.rb index 7bb6cd8f..0b7fa2aa 100644 --- a/ext/openssl/extconf.rb +++ b/ext/openssl/extconf.rb @@ -110,7 +110,7 @@ have_func("TLSv1_2_method") have_func("TLSv1_2_server_method") have_func("TLSv1_2_client_method") have_func("SSL_CTX_set_alpn_select_cb") -have_macro("OPENSSL_NPN_NEGOTIATED", ['openssl/ssl.h']) && $defs.push("-DHAVE_OPENSSL_NPN_NEGOTIATED") +have_func("SSL_CTX_set_next_proto_select_cb") unless have_func("SSL_set_tlsext_host_name", ['openssl/ssl.h']) have_macro("SSL_set_tlsext_host_name", ['openssl/ssl.h']) && $defs.push("-DHAVE_SSL_SET_TLSEXT_HOST_NAME") end diff --git a/ext/openssl/ossl_ssl.c b/ext/openssl/ossl_ssl.c index 90ce762a..0e01d7c0 100644 --- a/ext/openssl/ossl_ssl.c +++ b/ext/openssl/ossl_ssl.c @@ -544,7 +544,7 @@ ssl_renegotiation_cb(const SSL *ssl) (void) rb_funcall(cb, rb_intern("call"), 1, ssl_obj); } -#ifdef HAVE_OPENSSL_NPN_NEGOTIATED +#if defined(HAVE_SSL_CTX_SET_NEXT_PROTO_SELECT_CB) || defined(HAVE_SSL_CTX_SET_ALPN_SELECT_CB) static VALUE ssl_npn_encode_protocol_i(VALUE cur, VALUE encoded) { @@ -568,18 +568,6 @@ ssl_encode_npn_protocols(VALUE protocols) return encoded; } -static int -ssl_npn_advertise_cb(SSL *ssl, const unsigned char **out, unsigned int *outlen, void *arg) -{ - VALUE sslctx_obj = (VALUE) arg; - VALUE protocols = rb_iv_get(sslctx_obj, "@_protocols"); - - *out = (const unsigned char *) RSTRING_PTR(protocols); - *outlen = RSTRING_LENINT(protocols); - - return SSL_TLSEXT_ERR_OK; -} - static int ssl_npn_select_cb_common(VALUE cb, const unsigned char **out, unsigned char *outlen, const unsigned char *in, unsigned int inlen) { @@ -609,6 +597,19 @@ ssl_npn_select_cb_common(VALUE cb, const unsigned char **out, unsigned char *out return SSL_TLSEXT_ERR_OK; } +#ifdef HAVE_SSL_CTX_SET_NEXT_PROTO_SELECT_CB +static int +ssl_npn_advertise_cb(SSL *ssl, const unsigned char **out, unsigned int *outlen, void *arg) +{ + VALUE sslctx_obj = (VALUE) arg; + VALUE protocols = rb_iv_get(sslctx_obj, "@_protocols"); + + *out = (const unsigned char *) RSTRING_PTR(protocols); + *outlen = RSTRING_LENINT(protocols); + + return SSL_TLSEXT_ERR_OK; +} + static int ssl_npn_select_cb(SSL *s, unsigned char **out, unsigned char *outlen, const unsigned char *in, unsigned int inlen, void *arg) { @@ -619,6 +620,7 @@ ssl_npn_select_cb(SSL *s, unsigned char **out, unsigned char *outlen, const unsi return ssl_npn_select_cb_common(cb, (const unsigned char **)out, outlen, in, inlen); } +#endif #ifdef HAVE_SSL_CTX_SET_ALPN_SELECT_CB static int @@ -632,8 +634,7 @@ ssl_alpn_select_cb(SSL *ssl, const unsigned char **out, unsigned char *outlen, c return ssl_npn_select_cb_common(cb, out, outlen, in, inlen); } #endif - -#endif +#endif /* HAVE_SSL_CTX_SET_NEXT_PROTO_SELECT_CB || HAVE_SSL_CTX_SET_ALPN_SELECT_CB */ /* This function may serve as the entry point to support further * callbacks. */ @@ -793,7 +794,7 @@ ossl_sslctx_setup(VALUE self) val = ossl_sslctx_get_verify_dep(self); if(!NIL_P(val)) SSL_CTX_set_verify_depth(ctx, NUM2INT(val)); -#ifdef HAVE_OPENSSL_NPN_NEGOTIATED +#ifdef HAVE_SSL_CTX_SET_NEXT_PROTO_SELECT_CB val = rb_iv_get(self, "@npn_protocols"); if (!NIL_P(val)) { rb_iv_set(self, "@_protocols", ssl_encode_npn_protocols(val)); @@ -1861,7 +1862,7 @@ ossl_ssl_get_client_ca_list(VALUE self) return ossl_x509name_sk2ary(ca); } -# ifdef HAVE_OPENSSL_NPN_NEGOTIATED +# ifdef HAVE_SSL_CTX_SET_NEXT_PROTO_SELECT_CB /* * call-seq: * ssl.npn_protocol => String @@ -2132,7 +2133,7 @@ Init_ossl_ssl(void) * end */ rb_attr(cSSLContext, rb_intern("renegotiation_cb"), 1, 1, Qfalse); -#ifdef HAVE_OPENSSL_NPN_NEGOTIATED +#ifdef HAVE_SSL_CTX_SET_NEXT_PROTO_SELECT_CB /* * An Enumerable of Strings. Each String represents a protocol to be * advertised as the list of supported protocols for Next Protocol @@ -2307,7 +2308,7 @@ Init_ossl_ssl(void) # ifdef HAVE_SSL_CTX_SET_ALPN_SELECT_CB rb_define_method(cSSLSocket, "alpn_protocol", ossl_ssl_alpn_protocol, 0); # endif -# ifdef HAVE_OPENSSL_NPN_NEGOTIATED +# ifdef HAVE_SSL_CTX_SET_NEXT_PROTO_SELECT_CB rb_define_method(cSSLSocket, "npn_protocol", ossl_ssl_npn_protocol, 0); # endif #endif diff --git a/test/test_ssl.rb b/test/test_ssl.rb index cbffc981..7132dcc1 100644 --- a/test/test_ssl.rb +++ b/test/test_ssl.rb @@ -1064,7 +1064,9 @@ if OpenSSL::OPENSSL_VERSION_NUMBER >= 0x10002000 end end -if OpenSSL::OPENSSL_VERSION_NUMBER > 0x10001000 +if OpenSSL::OPENSSL_VERSION_NUMBER > 0x10001000 && + OpenSSL::SSL::SSLContext.method_defined?(:npn_select_cb) + # NPN may be disabled by OpenSSL configure option def test_npn_protocol_selection_ary advertised = ["http/1.1", "spdy/2"] -- cgit v1.2.3 From b0996b86f60389184a9c9f10040ceb820f2b9401 Mon Sep 17 00:00:00 2001 From: normal Date: Thu, 31 Mar 2016 20:33:55 +0000 Subject: openssl: accept moving write buffer for write_nonblock By setting the SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER flag. This flag was introduced at the same time as SSL_MODE_ENABLE_PARTIAL_WRITE in OpenSSL 0.9.4 and makes usage with non-blocking sockets much easier. Before this, a Rubyist would need to remember the exact object which failed to write and reuse it later when the socket became writable again. This causes problems when the buffer is given by another layer of the application (e.g. a buffer is given by a Rack middleware or application to a Rack web server). * ext/openssl/ossl_ssl.c (ossl_sslctx_s_alloc): enable SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER by default [Bug #12126] git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@54466 b2dd03c8-39d4-4d8f-98ff-823fe69b080e --- ext/openssl/ossl_ssl.c | 3 ++- test/test_pair.rb | 29 +++++++++++++++++++++++++++++ 2 files changed, 31 insertions(+), 1 deletion(-) diff --git a/ext/openssl/ossl_ssl.c b/ext/openssl/ossl_ssl.c index 0e01d7c0..5fcd2145 100644 --- a/ext/openssl/ossl_ssl.c +++ b/ext/openssl/ossl_ssl.c @@ -145,7 +145,8 @@ static VALUE ossl_sslctx_s_alloc(VALUE klass) { SSL_CTX *ctx; - long mode = SSL_MODE_ENABLE_PARTIAL_WRITE; + long mode = SSL_MODE_ENABLE_PARTIAL_WRITE | + SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER; VALUE obj; #ifdef SSL_MODE_RELEASE_BUFFERS diff --git a/test/test_pair.rb b/test/test_pair.rb index c7fc292e..f815eca0 100644 --- a/test/test_pair.rb +++ b/test/test_pair.rb @@ -280,6 +280,35 @@ module OpenSSL::TestPairM } end + def test_write_nonblock_retry + ssl_pair {|s1, s2| + # fill up a socket so we hit EAGAIN + written = String.new + n = 0 + buf = 'a' * 11 + case ret = s1.write_nonblock(buf, exception: false) + when :wait_readable then break + when :wait_writable then break + when Integer + written << buf + n += ret + exp = buf.bytesize + if ret != exp + buf = buf.byteslice(ret, exp - ret) + end + end while true + assert_kind_of Symbol, ret + + # make more space for subsequent write: + readed = s2.read(n) + assert_equal written, readed + + # this fails if SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER is missing: + buf2 = Marshal.load(Marshal.dump(buf)) + assert_kind_of Integer, s1.write_nonblock(buf2, exception: false) + } + end + def tcp_pair host = "127.0.0.1" serv = TCPServer.new(host, 0) -- cgit v1.2.3 From bd6a4954382b7b742575d5688bd9b93a597bcc24 Mon Sep 17 00:00:00 2001 From: nobu Date: Mon, 4 Apr 2016 15:06:46 +0000 Subject: openssl: Access to ephemeral TLS session key * ext/openssl/ossl_ssl.c (ossl_ssl_tmp_key): Access to ephemeral TLS session key in case of forward secrecy cipher. Only available since OpenSSL 1.0.2. [Fix GH-1318] * ext/openssl/extconf.rb: Check for SSL_get_server_tmp_key. git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@54485 b2dd03c8-39d4-4d8f-98ff-823fe69b080e --- ext/openssl/extconf.rb | 1 + ext/openssl/ossl_ssl.c | 22 ++++++++++++++++++++++ test/test_ssl.rb | 23 +++++++++++++++++++++++ test/utils.rb | 1 + 4 files changed, 47 insertions(+) diff --git a/ext/openssl/extconf.rb b/ext/openssl/extconf.rb index 0b7fa2aa..c36a7021 100644 --- a/ext/openssl/extconf.rb +++ b/ext/openssl/extconf.rb @@ -111,6 +111,7 @@ have_func("TLSv1_2_server_method") have_func("TLSv1_2_client_method") have_func("SSL_CTX_set_alpn_select_cb") have_func("SSL_CTX_set_next_proto_select_cb") +have_macro("SSL_get_server_tmp_key", ['openssl/ssl.h']) && $defs.push("-DHAVE_SSL_GET_SERVER_TMP_KEY") unless have_func("SSL_set_tlsext_host_name", ['openssl/ssl.h']) have_macro("SSL_set_tlsext_host_name", ['openssl/ssl.h']) && $defs.push("-DHAVE_SSL_SET_TLSEXT_HOST_NAME") end diff --git a/ext/openssl/ossl_ssl.c b/ext/openssl/ossl_ssl.c index 5fcd2145..96c79900 100644 --- a/ext/openssl/ossl_ssl.c +++ b/ext/openssl/ossl_ssl.c @@ -1912,6 +1912,25 @@ ossl_ssl_alpn_protocol(VALUE self) return rb_str_new((const char *) out, outlen); } # endif + +# ifdef HAVE_SSL_GET_SERVER_TMP_KEY +/* + * call-seq: + * ssl.tmp_key => PKey or nil + * + * Returns the ephemeral key used in case of forward secrecy cipher + */ +static VALUE +ossl_ssl_tmp_key(VALUE self) +{ + SSL *ssl; + EVP_PKEY *key; + ossl_ssl_data_get_struct(self, ssl); + if (!SSL_get_server_tmp_key(ssl, &key)) + return Qnil; + return ossl_pkey_new(key); +} +# endif /* defined(HAVE_SSL_GET_SERVER_TMP_KEY) */ #endif /* !defined(OPENSSL_NO_SOCK) */ void @@ -2306,6 +2325,9 @@ Init_ossl_ssl(void) rb_define_method(cSSLSocket, "session=", ossl_ssl_set_session, 1); rb_define_method(cSSLSocket, "verify_result", ossl_ssl_get_verify_result, 0); rb_define_method(cSSLSocket, "client_ca", ossl_ssl_get_client_ca_list, 0); +# ifdef HAVE_SSL_GET_SERVER_TMP_KEY + rb_define_method(cSSLSocket, "tmp_key", ossl_ssl_tmp_key, 0); +# endif # ifdef HAVE_SSL_CTX_SET_ALPN_SELECT_CB rb_define_method(cSSLSocket, "alpn_protocol", ossl_ssl_alpn_protocol, 0); # endif diff --git a/test/test_ssl.rb b/test/test_ssl.rb index 7132dcc1..db7ce33e 100644 --- a/test/test_ssl.rb +++ b/test/test_ssl.rb @@ -1169,6 +1169,29 @@ end } end + def test_get_ephemeral_key + return unless OpenSSL::SSL::SSLSocket.method_defined?(:tmp_key) + ciphers = { + 'ECDHE-RSA-AES128-SHA' => OpenSSL::PKey::EC, + 'DHE-RSA-AES128-SHA' => OpenSSL::PKey::DH, + 'AES128-SHA' => nil + } + conf_proc = Proc.new { |ctx| ctx.ciphers = 'ALL' } + start_server(OpenSSL::SSL::VERIFY_NONE, true, :ctx_proc => conf_proc) do |server, port| + ciphers.each do |cipher, ephemeral| + ctx = OpenSSL::SSL::SSLContext.new + ctx.ciphers = cipher + server_connect(port, ctx) do |ssl| + if ephemeral + assert_equal(ephemeral, ssl.tmp_key.class) + else + assert_nil(ssl.tmp_key) + end + end + end + end + end + private def start_server_version(version, ctx_proc=nil, server_proc=nil, &blk) diff --git a/test/utils.rb b/test/utils.rb index 2e9b7395..8e21b977 100644 --- a/test/utils.rb +++ b/test/utils.rb @@ -278,6 +278,7 @@ AQjjxMXhwULlmuR/K+WwlaZPiLIBYalLAZQ7ZbOPeVkJ8ePao0eLAgEC ctx.cert = @svr_cert ctx.key = @svr_key ctx.tmp_dh_callback = proc { OpenSSL::TestUtils::TEST_KEY_DH1024 } + ctx.tmp_ecdh_callback = proc { OpenSSL::TestUtils::TEST_KEY_EC_P256V1 } ctx.verify_mode = verify_mode ctx_proc.call(ctx) if ctx_proc -- cgit v1.2.3 From 9ef57cc80a4bbe4a9952b7f61029b397711ccda6 Mon Sep 17 00:00:00 2001 From: nobu Date: Mon, 4 Apr 2016 15:08:20 +0000 Subject: test_get_ephemeral_key: use assert_instance_of * test/openssl/test_ssl.rb (test_get_ephemeral_key): should use assert_instance_of instead of comparison of classes. git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@54487 b2dd03c8-39d4-4d8f-98ff-823fe69b080e --- test/test_ssl.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/test_ssl.rb b/test/test_ssl.rb index db7ce33e..5dcca146 100644 --- a/test/test_ssl.rb +++ b/test/test_ssl.rb @@ -1183,7 +1183,7 @@ end ctx.ciphers = cipher server_connect(port, ctx) do |ssl| if ephemeral - assert_equal(ephemeral, ssl.tmp_key.class) + assert_instance_of(ephemeral, ssl.tmp_key) else assert_nil(ssl.tmp_key) end -- cgit v1.2.3 From 7f6a6d5b8f207ed5aea6eef8291755aef3c43182 Mon Sep 17 00:00:00 2001 From: nobu Date: Wed, 6 Apr 2016 04:38:49 +0000 Subject: test_ssl.rb: skip unavailable pkeys * test/openssl/test_ssl.rb (test_get_ephemeral_key): skip unavailable public keys. [GH-1318] git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@54498 b2dd03c8-39d4-4d8f-98ff-823fe69b080e --- test/test_ssl.rb | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/test/test_ssl.rb b/test/test_ssl.rb index 5dcca146..f1e4ce3e 100644 --- a/test/test_ssl.rb +++ b/test/test_ssl.rb @@ -1171,9 +1171,10 @@ end def test_get_ephemeral_key return unless OpenSSL::SSL::SSLSocket.method_defined?(:tmp_key) + pkey = OpenSSL::PKey ciphers = { - 'ECDHE-RSA-AES128-SHA' => OpenSSL::PKey::EC, - 'DHE-RSA-AES128-SHA' => OpenSSL::PKey::DH, + 'ECDHE-RSA-AES128-SHA' => (pkey::EC if defined?(pkey::EC)), + 'DHE-RSA-AES128-SHA' => (pkey::DH if defined?(pkey::DH)), 'AES128-SHA' => nil } conf_proc = Proc.new { |ctx| ctx.ciphers = 'ALL' } -- cgit v1.2.3 From 9ed9fc536aafe134b899730a5b95e75dce033fe2 Mon Sep 17 00:00:00 2001 From: nobu Date: Thu, 7 Apr 2016 00:10:41 +0000 Subject: test_ssl.rb: skip unsupported ciphers * test/openssl/test_ssl.rb (test_get_ephemeral_key): skip unsupported ciphers. [GH-1318] git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@54506 b2dd03c8-39d4-4d8f-98ff-823fe69b080e --- test/test_ssl.rb | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/test/test_ssl.rb b/test/test_ssl.rb index f1e4ce3e..32f7cfde 100644 --- a/test/test_ssl.rb +++ b/test/test_ssl.rb @@ -1181,7 +1181,12 @@ end start_server(OpenSSL::SSL::VERIFY_NONE, true, :ctx_proc => conf_proc) do |server, port| ciphers.each do |cipher, ephemeral| ctx = OpenSSL::SSL::SSLContext.new - ctx.ciphers = cipher + begin + ctx.ciphers = cipher + rescue OpenSSL::SSL::SSLError => e + next if /no cipher match/ =~ e.message + raise + end server_connect(port, ctx) do |ssl| if ephemeral assert_instance_of(ephemeral, ssl.tmp_key) -- cgit v1.2.3 From dcbdb09b34c32864e87f09308b91d53aa2c13ed6 Mon Sep 17 00:00:00 2001 From: naruse Date: Sun, 8 May 2016 12:10:22 +0000 Subject: * ext/openssl/extconf.rb: asume it doesn't have SSLv2 related functions when OPENSSL_NO_SSL2 is defined. Usually openssl's header and the library (libssl) have the same set of functions, but on some environment the library has functions whose headers doesn't declare. (openssl/opensslconf.h and libsso.so aren't be synchronized) To detect such case explicitly check feature macro and remove related functions. git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@54950 b2dd03c8-39d4-4d8f-98ff-823fe69b080e --- ext/openssl/extconf.rb | 2 ++ 1 file changed, 2 insertions(+) diff --git a/ext/openssl/extconf.rb b/ext/openssl/extconf.rb index c36a7021..e293b730 100644 --- a/ext/openssl/extconf.rb +++ b/ext/openssl/extconf.rb @@ -152,6 +152,8 @@ have_struct_member("EVP_CIPHER_CTX", "engine", "openssl/evp.h") have_struct_member("X509_ATTRIBUTE", "single", "openssl/x509.h") have_macro("OPENSSL_FIPS", ['openssl/opensslconf.h']) && $defs.push("-DHAVE_OPENSSL_FIPS") have_macro("EVP_CTRL_GCM_GET_TAG", ['openssl/evp.h']) && $defs.push("-DHAVE_AUTHENTICATED_ENCRYPTION") +have_macro("OPENSSL_NO_SSL2","openssl/opensslconf.h") && $defs.reject!{|x|/HAVE_SSLV2_/===x} +have_macro("OPENSSL_NO_SSL3_METHOD","openssl/opensslconf.h") && $defs.reject!{|x|/HAVE_SSLV3_/===x} Logging::message "=== Checking done. ===\n" -- cgit v1.2.3 From 270124999f884807223eb3943c0ebfe7fcafcab3 Mon Sep 17 00:00:00 2001 From: nobu Date: Mon, 9 May 2016 00:05:33 +0000 Subject: openssl/extconf.rb: NO SSL macros first * ext/openssl/extconf.rb: check OPENSSL_NO_SSL{2,3} macros before checking related functions. git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@54959 b2dd03c8-39d4-4d8f-98ff-823fe69b080e --- ext/openssl/extconf.rb | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/ext/openssl/extconf.rb b/ext/openssl/extconf.rb index e293b730..9b3bdef0 100644 --- a/ext/openssl/extconf.rb +++ b/ext/openssl/extconf.rb @@ -97,12 +97,16 @@ have_func("OBJ_NAME_do_all_sorted") have_func("SSL_SESSION_get_id") have_func("SSL_SESSION_cmp") have_func("OPENSSL_cleanse") -have_func("SSLv2_method") -have_func("SSLv2_server_method") -have_func("SSLv2_client_method") -have_func("SSLv3_method") -have_func("SSLv3_server_method") -have_func("SSLv3_client_method") +unless have_macro("OPENSSL_NO_SSL2","openssl/opensslconf.h") + have_func("SSLv2_method") + have_func("SSLv2_server_method") + have_func("SSLv2_client_method") +end +unless have_macro("OPENSSL_NO_SSL3_METHOD","openssl/opensslconf.h") + have_func("SSLv3_method") + have_func("SSLv3_server_method") + have_func("SSLv3_client_method") +end have_func("TLSv1_1_method") have_func("TLSv1_1_server_method") have_func("TLSv1_1_client_method") @@ -152,8 +156,6 @@ have_struct_member("EVP_CIPHER_CTX", "engine", "openssl/evp.h") have_struct_member("X509_ATTRIBUTE", "single", "openssl/x509.h") have_macro("OPENSSL_FIPS", ['openssl/opensslconf.h']) && $defs.push("-DHAVE_OPENSSL_FIPS") have_macro("EVP_CTRL_GCM_GET_TAG", ['openssl/evp.h']) && $defs.push("-DHAVE_AUTHENTICATED_ENCRYPTION") -have_macro("OPENSSL_NO_SSL2","openssl/opensslconf.h") && $defs.reject!{|x|/HAVE_SSLV2_/===x} -have_macro("OPENSSL_NO_SSL3_METHOD","openssl/opensslconf.h") && $defs.reject!{|x|/HAVE_SSLV3_/===x} Logging::message "=== Checking done. ===\n" -- cgit v1.2.3 From 92812fddde3999cfe98af172c0e6ffa010a2cbf1 Mon Sep 17 00:00:00 2001 From: akr Date: Tue, 17 May 2016 13:15:57 +0000 Subject: Use Integer instead of Fixnum and Bignum. * object.c, numeric.c, enum.c, ext/-test-/bignum/mul.c, lib/rexml/quickpath.rb, lib/rexml/text.rb, lib/rexml/xpath_parser.rb, lib/rubygems/specification.rb, lib/uri/generic.rb, bootstraptest/test_eval.rb, basictest/test.rb, test/-ext-/bignum/test_big2str.rb, test/-ext-/bignum/test_div.rb, test/-ext-/bignum/test_mul.rb, test/-ext-/bignum/test_str2big.rb, test/csv/test_data_converters.rb, test/date/test_date.rb, test/json/test_json_generate.rb, test/minitest/test_minitest_mock.rb, test/openssl/test_cipher.rb, test/rexml/test_jaxen.rb, test/ruby/test_array.rb, test/ruby/test_basicinstructions.rb, test/ruby/test_bignum.rb, test/ruby/test_case.rb, test/ruby/test_class.rb, test/ruby/test_complex.rb, test/ruby/test_enum.rb, test/ruby/test_eval.rb, test/ruby/test_iseq.rb, test/ruby/test_literal.rb, test/ruby/test_math.rb, test/ruby/test_module.rb, test/ruby/test_numeric.rb, test/ruby/test_range.rb, test/ruby/test_rational.rb, test/ruby/test_refinement.rb, test/ruby/test_rubyvm.rb, test/ruby/test_struct.rb, test/ruby/test_variable.rb, test/rubygems/test_gem_specification.rb, test/thread/test_queue.rb: Use Integer instead of Fixnum and Bignum. git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@55029 b2dd03c8-39d4-4d8f-98ff-823fe69b080e --- test/test_cipher.rb | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test/test_cipher.rb b/test/test_cipher.rb index dae069e4..32f0d118 100644 --- a/test/test_cipher.rb +++ b/test/test_cipher.rb @@ -53,8 +53,8 @@ class OpenSSL::TestCipher < Test::Unit::TestCase def test_info assert_equal("DES-EDE3-CBC", @c1.name, "name") assert_equal("DES-EDE3-CBC", @c2.name, "name") - assert_kind_of(Fixnum, @c1.key_len, "key_len") - assert_kind_of(Fixnum, @c1.iv_len, "iv_len") + assert_kind_of(Integer, @c1.key_len, "key_len") + assert_kind_of(Integer, @c1.iv_len, "iv_len") end def test_dup -- cgit v1.2.3 From 494db323a5b7313321fb8145df6cf1800146e1cb Mon Sep 17 00:00:00 2001 From: rhe Date: Wed, 18 May 2016 02:55:45 +0000 Subject: openssl: fix equality test methods of OpenSSL::BN * ext/openssl/ossl_bn.c (try_convert_to_bnptr): Extracted from GetBNPtr(). This doesn't raise exception but returns NULL on error. (GetBNPtr): Raise TypeError if conversion fails. (ossl_bn_eq): Implement BN#==. (ossl_bn_eql): #eql? should not raise TypeError even if the argument is not compatible with BN. (ossl_bn_hash): Implement BN#hash. * ext/openssl/ossl_bn.c (Init_ossl_bn): Define #== and #hash. * test/openssl/test_bn.rb: Test BN#eql?, #== and #hash git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@55047 b2dd03c8-39d4-4d8f-98ff-823fe69b080e --- ext/openssl/ossl_bn.c | 90 +++++++++++++++++++++++++++++++++++++++++++-------- test/test_bn.rb | 16 ++++++--- 2 files changed, 89 insertions(+), 17 deletions(-) diff --git a/ext/openssl/ossl_bn.c b/ext/openssl/ossl_bn.c index fba86cdd..0af6c684 100644 --- a/ext/openssl/ossl_bn.c +++ b/ext/openssl/ossl_bn.c @@ -82,8 +82,8 @@ ossl_bn_new(const BIGNUM *bn) return obj; } -BIGNUM * -GetBNPtr(VALUE obj) +static BIGNUM * +try_convert_to_bnptr(VALUE obj) { BIGNUM *bn = NULL; VALUE newobj; @@ -100,14 +100,20 @@ GetBNPtr(VALUE obj) } SetBN(newobj, bn); /* Handle potencial mem leaks */ break; - case T_NIL: - break; - default: - ossl_raise(rb_eTypeError, "Cannot convert into OpenSSL::BN"); } return bn; } +BIGNUM * +GetBNPtr(VALUE obj) +{ + BIGNUM *bn = try_convert_to_bnptr(obj); + if (!bn) + ossl_raise(rb_eTypeError, "Cannot convert into OpenSSL::BN"); + + return bn; +} + /* * Private */ @@ -841,20 +847,77 @@ BIGNUM_CMP(ucmp) /* * call-seq: - * big.eql?(obj) => true or false + * bn == obj => true or false * - * Returns true only if obj is a - * Bignum with the same value as big. Contrast this + * Returns +true+ only if +obj+ has the same value as +bn+. Contrast this + * with OpenSSL::BN#eql?, which requires obj to be OpenSSL::BN. */ static VALUE -ossl_bn_eql(VALUE self, VALUE other) +ossl_bn_eq(VALUE self, VALUE other) { - if (ossl_bn_cmp(self, other) == INT2FIX(0)) { + BIGNUM *bn1, *bn2; + + GetBN(self, bn1); + /* BNPtr may raise, so we can't use here */ + bn2 = try_convert_to_bnptr(other); + + if (bn2 && !BN_cmp(bn1, bn2)) { return Qtrue; } return Qfalse; } +/* + * call-seq: + * bn.eql?(obj) => true or false + * + * Returns true only if obj is a + * OpenSSL::BN with the same value as big. Contrast this + * with OpenSSL::BN#==, which performs type conversions. + */ +static VALUE +ossl_bn_eql(VALUE self, VALUE other) +{ + BIGNUM *bn1, *bn2; + + if (!rb_obj_is_kind_of(other, cBN)) + return Qfalse; + GetBN(self, bn1); + GetBN(other, bn2); + + return BN_cmp(bn1, bn2) ? Qfalse : Qtrue; +} + +/* + * call-seq: + * bn.hash => Integer + * + * Returns a hash code for this object. + * + * See also Object#hash. + */ +static VALUE +ossl_bn_hash(VALUE self) +{ + BIGNUM *bn; + VALUE hash; + unsigned char *buf; + int len; + + GetBN(self, bn); + len = BN_num_bytes(bn); + buf = xmalloc(len); + if (BN_bn2bin(bn, buf) != len) { + xfree(buf); + ossl_raise(eBNError, NULL); + } + + hash = INT2FIX(rb_memhash(buf, len)); + xfree(buf); + + return hash; +} + /* * call-seq: * bn.prime? => true | false @@ -982,8 +1045,9 @@ Init_ossl_bn(void) rb_define_alias(cBN, "<=>", "cmp"); rb_define_method(cBN, "ucmp", ossl_bn_ucmp, 1); rb_define_method(cBN, "eql?", ossl_bn_eql, 1); - rb_define_alias(cBN, "==", "eql?"); - rb_define_alias(cBN, "===", "eql?"); + rb_define_method(cBN, "hash", ossl_bn_hash, 0); + rb_define_method(cBN, "==", ossl_bn_eq, 1); + rb_define_alias(cBN, "===", "=="); rb_define_method(cBN, "zero?", ossl_bn_is_zero, 0); rb_define_method(cBN, "one?", ossl_bn_is_one, 0); /* is_word */ diff --git a/test/test_bn.rb b/test/test_bn.rb index 848d1feb..415bd74c 100644 --- a/test/test_bn.rb +++ b/test/test_bn.rb @@ -43,10 +43,18 @@ class OpenSSL::TestBN < Test::Unit::TestCase assert_equal(true, OpenSSL::BN.new((2 ** 127 - 1).to_s(16), 16).prime?(1)) end - def test_cmp_nil - bn = OpenSSL::BN.new('1') - assert_equal(false, bn == nil) - assert_equal(true, bn != nil) + def test_cmp + bn1 = OpenSSL::BN.new('1') + bn2 = OpenSSL::BN.new('1') + bn3 = OpenSSL::BN.new('2') + assert_equal(false, bn1 == nil) + assert_equal(true, bn1 != nil) + assert_equal(true, bn1 == bn2) + assert_equal(false, bn1 == bn3) + assert_equal(true, bn1.eql?(bn2)) + assert_equal(false, bn1.eql?(bn3)) + assert_equal(bn1.hash, bn2.hash) + assert_not_equal(bn3.hash, bn1.hash) end end -- cgit v1.2.3 From faac6a620ca4d533e68daabce89994ff53e62b11 Mon Sep 17 00:00:00 2001 From: rhe Date: Wed, 18 May 2016 02:55:46 +0000 Subject: ext/openssl: refactor OpenSSL::PKey::EC::Point#mul * ext/openssl/ossl_pkey_ec.c (ossl_ec_point_mul): Validate the arguments before passing to EC_POINT(s)_mul(). Add description of this method. [ruby-core:65152] [Bug #10268] * test/openssl/test_pkey_ec.rb (test_ec_point_mul): Test that OpenSSL::PKey::EC::Point#mul works. git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@55048 b2dd03c8-39d4-4d8f-98ff-823fe69b080e --- ext/openssl/ossl_pkey_ec.c | 118 ++++++++++++++++++++++++--------------------- test/test_pkey_ec.rb | 45 ++++++++++++----- 2 files changed, 96 insertions(+), 67 deletions(-) diff --git a/ext/openssl/ossl_pkey_ec.c b/ext/openssl/ossl_pkey_ec.c index c93e3cfb..8f6edfab 100644 --- a/ext/openssl/ossl_pkey_ec.c +++ b/ext/openssl/ossl_pkey_ec.c @@ -1500,74 +1500,84 @@ static VALUE ossl_ec_point_to_bn(VALUE self) /* * call-seq: - * point.mul(bn) => point - * point.mul(bn, bn) => point - * point.mul([bn], [point]) => point - * point.mul([bn], [point], bn) => point + * point.mul(bn1 [, bn2]) => point + * point.mul(bns, points [, bn2]) => point + * + * Performs elliptic curve point multiplication. + * + * The first form calculates bn1 * point + bn2 * G, where +G+ is the + * generator of the group of +point+. +bn2+ may be ommitted, and in that case, + * the result is just bn1 * point. + * + * The second form calculates bns[0] * point + bns[1] * points[0] + ... + * + bns[-1] * points[-1] + bn2 * G. +bn2+ may be ommitted. +bns+ must be + * an array of OpenSSL::BN. +points+ must be an array of + * OpenSSL::PKey::EC::Point. Please note that points[0] is not + * multiplied by bns[0], but bns[1]. */ static VALUE ossl_ec_point_mul(int argc, VALUE *argv, VALUE self) { - EC_POINT *point1, *point2; + EC_POINT *point_self, *point_result; const EC_GROUP *group; VALUE group_v = rb_iv_get(self, "@group"); - VALUE bn_v1, bn_v2, r, points_v; - BIGNUM *bn1 = NULL, *bn2 = NULL; + VALUE arg1, arg2, arg3, result; + const BIGNUM *bn_g = NULL; - Require_EC_POINT(self, point1); + Require_EC_POINT(self, point_self); SafeRequire_EC_GROUP(group_v, group); - r = rb_obj_alloc(cEC_POINT); - ossl_ec_point_initialize(1, &group_v, r); - Require_EC_POINT(r, point2); + result = rb_obj_alloc(cEC_POINT); + ossl_ec_point_initialize(1, &group_v, result); + Require_EC_POINT(result, point_result); - argc = rb_scan_args(argc, argv, "12", &bn_v1, &points_v, &bn_v2); + rb_scan_args(argc, argv, "12", &arg1, &arg2, &arg3); + if (rb_obj_is_kind_of(arg1, cBN)) { + BIGNUM *bn = GetBNPtr(arg1); + if (argc >= 2) + bn_g = GetBNPtr(arg2); - if (rb_obj_is_kind_of(bn_v1, cBN)) { - bn1 = GetBNPtr(bn_v1); - if (argc >= 2) { - bn2 = GetBNPtr(points_v); - } - if (EC_POINT_mul(group, point2, bn2, point1, bn1, ossl_bn_ctx) != 1) - ossl_raise(eEC_POINT, "Multiplication failed"); + if (EC_POINT_mul(group, point_result, bn_g, point_self, bn, ossl_bn_ctx) != 1) + ossl_raise(eEC_POINT, NULL); } else { - size_t i, points_len, bignums_len; - const EC_POINT **points; - const BIGNUM **bignums; - - Check_Type(bn_v1, T_ARRAY); - bignums_len = RARRAY_LEN(bn_v1); - bignums = (const BIGNUM **)OPENSSL_malloc(bignums_len * (int)sizeof(BIGNUM *)); - - for (i = 0; i < bignums_len; ++i) { - bignums[i] = GetBNPtr(rb_ary_entry(bn_v1, i)); - } - - if (!rb_obj_is_kind_of(points_v, rb_cArray)) { - OPENSSL_free((void *)bignums); - rb_raise(rb_eTypeError, "Argument2 must be an array"); - } - - rb_ary_unshift(points_v, self); - points_len = RARRAY_LEN(points_v); - points = (const EC_POINT **)OPENSSL_malloc(points_len * (int)sizeof(EC_POINT *)); - - for (i = 0; i < points_len; ++i) { - Get_EC_POINT(rb_ary_entry(points_v, i), points[i]); - } + /* + * bignums | arg1[0] | arg1[1] | arg1[2] | ... + * points | self | arg2[0] | arg2[1] | ... + */ + int i, num; + VALUE tmp_p, tmp_b; + const EC_POINT **points; + const BIGNUM **bignums; + + if (!rb_obj_is_kind_of(arg1, rb_cArray) || + !rb_obj_is_kind_of(arg2, rb_cArray)) + ossl_raise(rb_eTypeError, "points must be array"); + if (RARRAY_LEN(arg1) != RARRAY_LEN(arg2) + 1) /* arg2 must be 1 larger */ + ossl_raise(rb_eArgError, "bns must be 1 longer than points; see the documentation"); + + num = RARRAY_LEN(arg1); + bignums = ALLOCV_N(const BIGNUM *, tmp_b, num); + for (i = 0; i < num; i++) + bignums[i] = GetBNPtr(RARRAY_AREF(arg1, i)); + + points = ALLOCV_N(const EC_POINT *, tmp_p, num); + points[0] = point_self; /* self */ + for (i = 0; i < num - 1; i++) + SafeRequire_EC_POINT(RARRAY_AREF(arg2, i), points[i + 1]); + + if (argc >= 3) + bn_g = GetBNPtr(arg3); + + if (EC_POINTs_mul(group, point_result, bn_g, num, points, bignums, ossl_bn_ctx) != 1) { + ALLOCV_END(tmp_b); + ALLOCV_END(tmp_p); + ossl_raise(eEC_POINT, NULL); + } - if (argc >= 3) { - bn2 = GetBNPtr(bn_v2); - } - if (EC_POINTs_mul(group, point2, bn2, points_len, points, bignums, ossl_bn_ctx) != 1) { - OPENSSL_free((void *)bignums); - OPENSSL_free((void *)points); - ossl_raise(eEC_POINT, "Multiplication failed"); - } - OPENSSL_free((void *)bignums); - OPENSSL_free((void *)points); + ALLOCV_END(tmp_b); + ALLOCV_END(tmp_p); } - return r; + return result; } static void no_copy(VALUE klass) diff --git a/test/test_pkey_ec.rb b/test/test_pkey_ec.rb index fe128fd4..d3edcc47 100644 --- a/test/test_pkey_ec.rb +++ b/test/test_pkey_ec.rb @@ -190,19 +190,38 @@ class OpenSSL::TestEC < Test::Unit::TestCase end def test_ec_point_mul - ec = OpenSSL::TestUtils::TEST_KEY_EC_P256V1 - p1 = ec.public_key - bn1 = OpenSSL::BN.new('10') - bn2 = OpenSSL::BN.new('20') - - p2 = p1.mul(bn1) - assert(p1.group == p2.group) - p2 = p1.mul(bn1, bn2) - assert(p1.group == p2.group) - p2 = p1.mul([bn1, bn2], [p1]) - assert(p1.group == p2.group) - p2 = p1.mul([bn1, bn2], [p1], bn2) - assert(p1.group == p2.group) + # y^2 = x^3 + 2x + 2 over F_17 + # generator is (5, 1) + group = OpenSSL::PKey::EC::Group.new(:GFp, 17, 2, 2) + gen = OpenSSL::PKey::EC::Point.new(group, OpenSSL::BN.new("040501", 16)) + group.set_generator(gen, 0, 0) + + # 3 * (6, 3) = (16, 13) + point_a = OpenSSL::PKey::EC::Point.new(group, OpenSSL::BN.new("040603", 16)) + result_a1 = point_a.mul(3.to_bn) + assert_equal("04100D", result_a1.to_bn.to_s(16)) + # 3 * (6, 3) + 3 * (5, 1) = (7, 6) + result_a2 = point_a.mul(3.to_bn, 3.to_bn) + assert_equal("040706", result_a2.to_bn.to_s(16)) + # 3 * point_a = 3 * (6, 3) = (16, 13) + result_b1 = point_a.mul([3.to_bn], []) + assert_equal("04100D", result_b1.to_bn.to_s(16)) + # 3 * point_a + 2 * point_a = 3 * (6, 3) + 2 * (6, 3) = (7, 11) + result_b1 = point_a.mul([3.to_bn, 2.to_bn], [point_a]) + assert_equal("04070B", result_b1.to_bn.to_s(16)) + # 3 * point_a + 5 * point_a.group.generator = 3 * (6, 3) + 5 * (5, 1) = (13, 10) + result_b1 = point_a.mul([3.to_bn], [], 5) + assert_equal("040D0A", result_b1.to_bn.to_s(16)) + + p256_key = OpenSSL::TestUtils::TEST_KEY_EC_P256V1 + p256_g = p256_key.group + assert_equal(p256_key.public_key, p256_g.generator.mul(p256_key.private_key)) + + # invalid argument + assert_raise(TypeError) { point_a.mul(nil) } + assert_raise(ArgumentError) { point_a.mul([1.to_bn], [point_a]) } + assert_raise(TypeError) { point_a.mul([1.to_bn], nil) } + assert_raise(TypeError) { point_a.mul([nil], []) } end # test Group: asn1_flag, point_conversion -- cgit v1.2.3 From d69c35f5e06fc8db8bd1e0362023f57861ae5692 Mon Sep 17 00:00:00 2001 From: rhe Date: Wed, 18 May 2016 04:07:45 +0000 Subject: openssl: report errors in OpenSSL error queue when clear it * ext/openssl/ossl.c (ossl_clear_error): Extracted from ossl_make_error(). This prints errors in the OpenSSL error queue if OpenSSL.debug is true, and clears the queue. (ossl_make_error): use ossl_clear_error(). * ext/openssl/ossl.h: add prototype declaration of ossl_make_error(). (OSSL_BIO_reset) use ossl_clear_error() to clear the queue. Clearing silently makes debugging difficult. * ext/openssl/ossl_engine.c (ossl_engine_s_by_id): ditto. * ext/openssl/ossl_ns_spki.c (ossl_spki_initialize): ditto. * ext/openssl/ossl_pkcs7.c (ossl_pkcs7_verify): ditto. * ext/openssl/ossl_pkey_dsa.c (ossl_dsa_initialize): ditto. * ext/openssl/ossl_pkey_ec.c (ossl_ec_key_initialize): ditto. (ossl_ec_group_initialize): ditto. * ext/openssl/ossl_ssl.c (ossl_ssl_shutdown): ditto. git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@55050 b2dd03c8-39d4-4d8f-98ff-823fe69b080e --- ext/openssl/ossl.c | 19 +++++++++++++------ ext/openssl/ossl.h | 8 ++++++-- ext/openssl/ossl_engine.c | 2 +- ext/openssl/ossl_ns_spki.c | 2 +- ext/openssl/ossl_pkcs7.c | 2 +- ext/openssl/ossl_pkey_dsa.c | 2 +- ext/openssl/ossl_pkey_ec.c | 4 ++-- ext/openssl/ossl_ssl.c | 2 +- 8 files changed, 26 insertions(+), 15 deletions(-) diff --git a/ext/openssl/ossl.c b/ext/openssl/ossl.c index d03dfa7a..ac828151 100644 --- a/ext/openssl/ossl.c +++ b/ext/openssl/ossl.c @@ -318,12 +318,7 @@ ossl_make_error(VALUE exc, const char *fmt, va_list args) rb_str_cat2(str, msg ? msg : "(null)"); } } - if (dOSSL == Qtrue){ /* show all errors on the stack */ - while ((e = ERR_get_error()) != 0){ - rb_warn("error on stack: %s", ERR_error_string(e, NULL)); - } - } - ERR_clear_error(); + ossl_clear_error(); if (NIL_P(str)) str = rb_str_new(0, 0); return rb_exc_new3(exc, str); @@ -351,6 +346,18 @@ ossl_exc_new(VALUE exc, const char *fmt, ...) return err; } +void +ossl_clear_error(void) +{ + if (dOSSL == Qtrue) { + long e; + while ((e = ERR_get_error())) { + rb_warn("error on stack: %s", ERR_error_string(e, NULL)); + } + } + ERR_clear_error(); +} + /* * call-seq: * OpenSSL.errors -> [String...] diff --git a/ext/openssl/ossl.h b/ext/openssl/ossl.h index 3be01b0c..a31ca951 100644 --- a/ext/openssl/ossl.h +++ b/ext/openssl/ossl.h @@ -154,8 +154,10 @@ int ossl_pem_passwd_cb(char *, int, int, void *); * Clear BIO* with this in PEM/DER fallback scenarios to avoid decoding * errors piling up in OpenSSL::Errors */ -#define OSSL_BIO_reset(bio) (void)BIO_reset((bio)); \ - ERR_clear_error(); +#define OSSL_BIO_reset(bio) do { \ + (void)BIO_reset((bio)); \ + ossl_clear_error(); \ +} while (0) /* * ERRor messages @@ -163,6 +165,8 @@ int ossl_pem_passwd_cb(char *, int, int, void *); #define OSSL_ErrMsg() ERR_reason_error_string(ERR_get_error()) NORETURN(void ossl_raise(VALUE, const char *, ...)); VALUE ossl_exc_new(VALUE, const char *, ...); +/* Clear OpenSSL error queue. If dOSSL is set, rb_warn() them. */ +void ossl_clear_error(void); /* * Verify callback diff --git a/ext/openssl/ossl_engine.c b/ext/openssl/ossl_engine.c index 890ec724..06ca0754 100644 --- a/ext/openssl/ossl_engine.c +++ b/ext/openssl/ossl_engine.c @@ -224,7 +224,7 @@ ossl_engine_s_by_id(VALUE klass, VALUE id) ossl_raise(eEngineError, NULL); ENGINE_ctrl(e, ENGINE_CTRL_SET_PASSWORD_CALLBACK, 0, NULL, (void(*)(void))ossl_pem_passwd_cb); - ERR_clear_error(); + ossl_clear_error(); return obj; } diff --git a/ext/openssl/ossl_ns_spki.c b/ext/openssl/ossl_ns_spki.c index 35c2e3e5..c6d2483b 100644 --- a/ext/openssl/ossl_ns_spki.c +++ b/ext/openssl/ossl_ns_spki.c @@ -94,7 +94,7 @@ ossl_spki_initialize(int argc, VALUE *argv, VALUE self) } NETSCAPE_SPKI_free(DATA_PTR(self)); DATA_PTR(self) = spki; - ERR_clear_error(); + ossl_clear_error(); return self; } diff --git a/ext/openssl/ossl_pkcs7.c b/ext/openssl/ossl_pkcs7.c index 9ca3abd7..ad794e71 100644 --- a/ext/openssl/ossl_pkcs7.c +++ b/ext/openssl/ossl_pkcs7.c @@ -779,7 +779,7 @@ ossl_pkcs7_verify(int argc, VALUE *argv, VALUE self) if (ok < 0) ossl_raise(ePKCS7Error, NULL); msg = ERR_reason_error_string(ERR_get_error()); ossl_pkcs7_set_err_string(self, msg ? rb_str_new2(msg) : Qnil); - ERR_clear_error(); + ossl_clear_error(); data = ossl_membio2str(out); ossl_pkcs7_set_data(self, data); sk_X509_pop_free(x509s, X509_free); diff --git a/ext/openssl/ossl_pkey_dsa.c b/ext/openssl/ossl_pkey_dsa.c index 04900cc6..2e42a0ce 100644 --- a/ext/openssl/ossl_pkey_dsa.c +++ b/ext/openssl/ossl_pkey_dsa.c @@ -244,7 +244,7 @@ ossl_dsa_initialize(int argc, VALUE *argv, VALUE self) } BIO_free(in); if (!dsa) { - ERR_clear_error(); + ossl_clear_error(); ossl_raise(eDSAError, "Neither PUB key nor PRIV key"); } } diff --git a/ext/openssl/ossl_pkey_ec.c b/ext/openssl/ossl_pkey_ec.c index 8f6edfab..a5bddd7d 100644 --- a/ext/openssl/ossl_pkey_ec.c +++ b/ext/openssl/ossl_pkey_ec.c @@ -213,7 +213,7 @@ static VALUE ossl_ec_key_initialize(int argc, VALUE *argv, VALUE self) const char *name = StringValueCStr(arg); int nid = OBJ_sn2nid(name); - (void)ERR_get_error(); + ossl_clear_error(); /* ignore errors in the previous d2i_EC_PUBKEY_bio() */ if (nid == NID_undef) ossl_raise(eECError, "unknown curve name (%s)\n", name); @@ -808,7 +808,7 @@ static VALUE ossl_ec_group_initialize(int argc, VALUE *argv, VALUE self) const char *name = StringValueCStr(arg1); int nid = OBJ_sn2nid(name); - (void)ERR_get_error(); + ossl_clear_error(); /* ignore errors in d2i_ECPKParameters_bio() */ if (nid == NID_undef) ossl_raise(eEC_GROUP, "unknown curve name (%s)", name); diff --git a/ext/openssl/ossl_ssl.c b/ext/openssl/ossl_ssl.c index 96c79900..10797109 100644 --- a/ext/openssl/ossl_ssl.c +++ b/ext/openssl/ossl_ssl.c @@ -1161,7 +1161,7 @@ ossl_ssl_shutdown(SSL *ssl) break; } SSL_clear(ssl); - ERR_clear_error(); + ossl_clear_error(); } } -- cgit v1.2.3 From 0789643d73334db4cd540d7981faa77c4acca3bc Mon Sep 17 00:00:00 2001 From: rhe Date: Wed, 18 May 2016 04:07:47 +0000 Subject: openssl: clear OpenSSL error queue before return to Ruby * ext/openssl/ossl_x509cert.c (ossl_x509_verify): X509_verify() family may put errors on 0 return (0 means verification failure). Clear OpenSSL error queue before return to Ruby. Since the queue is thread global, remaining errors in the queue can cause an unexpected error in the next OpenSSL operation. [ruby-core:48284] [Bug #7215] * ext/openssl/ossl_x509crl.c (ossl_x509crl_verify): ditto. * ext/openssl/ossl_x509req.c (ossl_x509req_verify): ditto. * ext/openssl/ossl_x509store.c (ossl_x509stctx_verify): ditto. * ext/openssl/ossl_pkey_dh.c (dh_generate): clear the OpenSSL error queue before re-raising exception. * ext/openssl/ossl_pkey_dsa.c (dsa_generate): ditto. * ext/openssl/ossl_pkey_rsa.c (rsa_generate): ditto. * ext/openssl/ossl_ssl.c (ossl_start_ssl): ditto. * test/openssl: check that OpenSSL.errors is empty every time after running a test case. git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@55051 b2dd03c8-39d4-4d8f-98ff-823fe69b080e --- ext/openssl/ossl_pkey_dh.c | 6 +++++- ext/openssl/ossl_pkey_dsa.c | 9 ++++++++- ext/openssl/ossl_pkey_rsa.c | 6 +++++- ext/openssl/ossl_ssl.c | 7 +++++-- ext/openssl/ossl_x509cert.c | 15 ++++++++------- ext/openssl/ossl_x509crl.c | 14 +++++++------- ext/openssl/ossl_x509req.c | 14 +++++++------- ext/openssl/ossl_x509store.c | 16 +++++++++++----- test/test_asn1.rb | 2 +- test/test_bn.rb | 2 +- test/test_buffering.rb | 2 +- test/test_cipher.rb | 3 ++- test/test_config.rb | 3 ++- test/test_digest.rb | 3 ++- test/test_engine.rb | 3 ++- test/test_fips.rb | 2 +- test/test_hmac.rb | 5 +---- test/test_ns_spki.rb | 2 +- test/test_ocsp.rb | 2 +- test/test_pair.rb | 12 ++++++------ test/test_pkcs12.rb | 2 +- test/test_pkcs5.rb | 2 +- test/test_pkcs7.rb | 2 +- test/test_pkey_dh.rb | 2 +- test/test_pkey_dsa.rb | 12 +----------- test/test_pkey_ec.rb | 7 +------ test/test_pkey_rsa.rb | 11 +---------- test/test_random.rb | 2 +- test/test_x509cert.rb | 5 +---- test/test_x509crl.rb | 5 +---- test/test_x509ext.rb | 5 +---- test/test_x509name.rb | 5 +---- test/test_x509req.rb | 2 +- test/test_x509store.rb | 5 +---- test/utils.rb | 12 ++++++++---- 35 files changed, 99 insertions(+), 108 deletions(-) diff --git a/ext/openssl/ossl_pkey_dh.c b/ext/openssl/ossl_pkey_dh.c index 2f79bfb2..19c517fd 100644 --- a/ext/openssl/ossl_pkey_dh.c +++ b/ext/openssl/ossl_pkey_dh.c @@ -129,7 +129,11 @@ dh_generate(int size, int gen) if (!gen_arg.result) { DH_free(dh); - if (cb_arg.state) rb_jump_tag(cb_arg.state); + if (cb_arg.state) { + /* Clear OpenSSL error queue before re-raising. */ + ossl_clear_error(); + rb_jump_tag(cb_arg.state); + } return 0; } #else diff --git a/ext/openssl/ossl_pkey_dsa.c b/ext/openssl/ossl_pkey_dsa.c index 2e42a0ce..4c0c3f1b 100644 --- a/ext/openssl/ossl_pkey_dsa.c +++ b/ext/openssl/ossl_pkey_dsa.c @@ -135,7 +135,14 @@ dsa_generate(int size) } if (!gen_arg.result) { DSA_free(dsa); - if (cb_arg.state) rb_jump_tag(cb_arg.state); + if (cb_arg.state) { + /* Clear OpenSSL error queue before re-raising. By the way, the + * documentation of DSA_generate_parameters_ex() says the error code + * can be obtained by ERR_get_error(), but the default + * implementation, dsa_builtin_paramgen() doesn't put any error... */ + ossl_clear_error(); + rb_jump_tag(cb_arg.state); + } return 0; } #else diff --git a/ext/openssl/ossl_pkey_rsa.c b/ext/openssl/ossl_pkey_rsa.c index 20b993ab..6ad9f3ed 100644 --- a/ext/openssl/ossl_pkey_rsa.c +++ b/ext/openssl/ossl_pkey_rsa.c @@ -139,7 +139,11 @@ rsa_generate(int size, unsigned long exp) if (!gen_arg.result) { BN_free(e); RSA_free(rsa); - if (cb_arg.state) rb_jump_tag(cb_arg.state); + if (cb_arg.state) { + /* must clear OpenSSL error stack */ + ossl_clear_error(); + rb_jump_tag(cb_arg.state); + } return 0; } diff --git a/ext/openssl/ossl_ssl.c b/ext/openssl/ossl_ssl.c index 10797109..938e36f1 100644 --- a/ext/openssl/ossl_ssl.c +++ b/ext/openssl/ossl_ssl.c @@ -1288,8 +1288,11 @@ ossl_start_ssl(VALUE self, int (*func)(), const char *funcname, VALUE opts) ret = func(ssl); cb_state = rb_ivar_get(self, ID_callback_state); - if (!NIL_P(cb_state)) - rb_jump_tag(NUM2INT(cb_state)); + if (!NIL_P(cb_state)) { + /* must cleanup OpenSSL error stack before re-raising */ + ossl_clear_error(); + rb_jump_tag(NUM2INT(cb_state)); + } if (ret > 0) break; diff --git a/ext/openssl/ossl_x509cert.c b/ext/openssl/ossl_x509cert.c index 4dafae17..226704ef 100644 --- a/ext/openssl/ossl_x509cert.c +++ b/ext/openssl/ossl_x509cert.c @@ -591,18 +591,19 @@ ossl_x509_verify(VALUE self, VALUE key) { X509 *x509; EVP_PKEY *pkey; - int i; pkey = GetPKeyPtr(key); /* NO NEED TO DUP */ GetX509(self, x509); - if ((i = X509_verify(x509, pkey)) < 0) { - ossl_raise(eX509CertError, NULL); - } - if (i > 0) { + + switch (X509_verify(x509, pkey)) { + case 1: return Qtrue; + case 0: + ossl_clear_error(); + return Qfalse; + default: + ossl_raise(eX509CertError, NULL); } - - return Qfalse; } /* diff --git a/ext/openssl/ossl_x509crl.c b/ext/openssl/ossl_x509crl.c index f64712ef..a660ccce 100644 --- a/ext/openssl/ossl_x509crl.c +++ b/ext/openssl/ossl_x509crl.c @@ -360,17 +360,17 @@ static VALUE ossl_x509crl_verify(VALUE self, VALUE key) { X509_CRL *crl; - int ret; GetX509CRL(self, crl); - if ((ret = X509_CRL_verify(crl, GetPKeyPtr(key))) < 0) { - ossl_raise(eX509CRLError, NULL); - } - if (ret == 1) { + switch (X509_CRL_verify(crl, GetPKeyPtr(key))) { + case 1: return Qtrue; + case 0: + ossl_clear_error(); + return Qfalse; + default: + ossl_raise(eX509CRLError, NULL); } - - return Qfalse; } static VALUE diff --git a/ext/openssl/ossl_x509req.c b/ext/openssl/ossl_x509req.c index e5ce088a..c1cdca5f 100644 --- a/ext/openssl/ossl_x509req.c +++ b/ext/openssl/ossl_x509req.c @@ -375,18 +375,18 @@ ossl_x509req_verify(VALUE self, VALUE key) { X509_REQ *req; EVP_PKEY *pkey; - int i; GetX509Req(self, req); pkey = GetPKeyPtr(key); /* NO NEED TO DUP */ - if ((i = X509_REQ_verify(req, pkey)) < 0) { - ossl_raise(eX509ReqError, NULL); - } - if (i > 0) { + switch (X509_REQ_verify(req, pkey)) { + case 1: return Qtrue; + case 0: + ossl_clear_error(); + return Qfalse; + default: + ossl_raise(eX509ReqError, NULL); } - - return Qfalse; } static VALUE diff --git a/ext/openssl/ossl_x509store.c b/ext/openssl/ossl_x509store.c index bb6fe14d..aca25b15 100644 --- a/ext/openssl/ossl_x509store.c +++ b/ext/openssl/ossl_x509store.c @@ -464,14 +464,20 @@ static VALUE ossl_x509stctx_verify(VALUE self) { X509_STORE_CTX *ctx; - int result; GetX509StCtx(self, ctx); X509_STORE_CTX_set_ex_data(ctx, ossl_verify_cb_idx, - (void*)rb_iv_get(self, "@verify_callback")); - result = X509_verify_cert(ctx); - - return result ? Qtrue : Qfalse; + (void *)rb_iv_get(self, "@verify_callback")); + + switch (X509_verify_cert(ctx)) { + case 1: + return Qtrue; + case 0: + ossl_clear_error(); + return Qfalse; + default: + ossl_raise(eX509CertError, NULL); + } } static VALUE diff --git a/test/test_asn1.rb b/test/test_asn1.rb index fd2118d8..9db9ec51 100644 --- a/test/test_asn1.rb +++ b/test/test_asn1.rb @@ -1,7 +1,7 @@ # frozen_string_literal: false require_relative 'utils' -class OpenSSL::TestASN1 < Test::Unit::TestCase +class OpenSSL::TestASN1 < OpenSSL::TestCase def test_decode subj = OpenSSL::X509::Name.parse("/DC=org/DC=ruby-lang/CN=TestCA") key = OpenSSL::TestUtils::TEST_KEY_RSA1024 diff --git a/test/test_bn.rb b/test/test_bn.rb index 415bd74c..37ba5e55 100644 --- a/test/test_bn.rb +++ b/test/test_bn.rb @@ -3,7 +3,7 @@ require_relative 'utils' if defined?(OpenSSL::TestUtils) -class OpenSSL::TestBN < Test::Unit::TestCase +class OpenSSL::TestBN < OpenSSL::TestCase def test_new_str e1 = OpenSSL::BN.new(999.to_s(16), 16) # OpenSSL::BN.new(str, 16) must be most stable e2 = OpenSSL::BN.new((2**107-1).to_s(16), 16) diff --git a/test/test_buffering.rb b/test/test_buffering.rb index 1f552c93..1f42cd3c 100644 --- a/test/test_buffering.rb +++ b/test/test_buffering.rb @@ -2,7 +2,7 @@ require_relative 'utils' require 'stringio' -class OpenSSL::TestBuffering < Test::Unit::TestCase +class OpenSSL::TestBuffering < OpenSSL::TestCase class IO include OpenSSL::Buffering diff --git a/test/test_cipher.rb b/test/test_cipher.rb index 32f0d118..dab64aa5 100644 --- a/test/test_cipher.rb +++ b/test/test_cipher.rb @@ -3,7 +3,7 @@ require_relative 'utils' if defined?(OpenSSL::TestUtils) -class OpenSSL::TestCipher < Test::Unit::TestCase +class OpenSSL::TestCipher < OpenSSL::TestCase class << self @@ -34,6 +34,7 @@ class OpenSSL::TestCipher < Test::Unit::TestCase end def teardown + super @c1 = @c2 = nil end diff --git a/test/test_config.rb b/test/test_config.rb index 812b28b9..3e2e1273 100644 --- a/test/test_config.rb +++ b/test/test_config.rb @@ -1,7 +1,7 @@ # frozen_string_literal: false require_relative 'utils' -class OpenSSL::TestConfig < Test::Unit::TestCase +class OpenSSL::TestConfig < OpenSSL::TestCase def setup file = Tempfile.open("openssl.cnf") file << <<__EOD__ @@ -18,6 +18,7 @@ __EOD__ end def teardown + super @tmpfile.close! end diff --git a/test/test_digest.rb b/test/test_digest.rb index 8b724a03..ba3e974b 100644 --- a/test/test_digest.rb +++ b/test/test_digest.rb @@ -3,7 +3,7 @@ require_relative 'utils' if defined?(OpenSSL::TestUtils) -class OpenSSL::TestDigest < Test::Unit::TestCase +class OpenSSL::TestDigest < OpenSSL::TestCase def setup @d1 = OpenSSL::Digest.new("MD5") @d2 = OpenSSL::Digest::MD5.new @@ -12,6 +12,7 @@ class OpenSSL::TestDigest < Test::Unit::TestCase end def teardown + super @d1 = @d2 = @md = nil end diff --git a/test/test_engine.rb b/test/test_engine.rb index 3521de63..9a0da340 100644 --- a/test/test_engine.rb +++ b/test/test_engine.rb @@ -1,9 +1,10 @@ # frozen_string_literal: false require_relative 'utils' -class OpenSSL::TestEngine < Test::Unit::TestCase +class OpenSSL::TestEngine < OpenSSL::TestCase def teardown + super OpenSSL::Engine.cleanup # [ruby-core:40669] assert_equal(0, OpenSSL::Engine.engines.size) end diff --git a/test/test_fips.rb b/test/test_fips.rb index 33769c93..534dade0 100644 --- a/test/test_fips.rb +++ b/test/test_fips.rb @@ -3,7 +3,7 @@ require_relative 'utils' if defined?(OpenSSL::TestUtils) -class OpenSSL::TestFIPS < Test::Unit::TestCase +class OpenSSL::TestFIPS < OpenSSL::TestCase def test_fips_mode_is_reentrant OpenSSL.fips_mode = false diff --git a/test/test_hmac.rb b/test/test_hmac.rb index 135d26f0..3c90a5de 100644 --- a/test/test_hmac.rb +++ b/test/test_hmac.rb @@ -3,7 +3,7 @@ require_relative 'utils' -class OpenSSL::TestHMAC < Test::Unit::TestCase +class OpenSSL::TestHMAC < OpenSSL::TestCase def setup @digest = OpenSSL::Digest::MD5 @key = "KEY" @@ -12,9 +12,6 @@ class OpenSSL::TestHMAC < Test::Unit::TestCase @h2 = OpenSSL::HMAC.new(@key, "MD5") end - def teardown - end - def test_hmac @h1.update(@data) @h2.update(@data) diff --git a/test/test_ns_spki.rb b/test/test_ns_spki.rb index 4f6e6f59..4740c0b2 100644 --- a/test/test_ns_spki.rb +++ b/test/test_ns_spki.rb @@ -3,7 +3,7 @@ require_relative 'utils' if defined?(OpenSSL::TestUtils) -class OpenSSL::TestNSSPI < Test::Unit::TestCase +class OpenSSL::TestNSSPI < OpenSSL::TestCase def setup # This request data is adopt from the specification of # "Netscape Extensions for User Key Generation". diff --git a/test/test_ocsp.rb b/test/test_ocsp.rb index 1a969fd7..d04b4216 100644 --- a/test/test_ocsp.rb +++ b/test/test_ocsp.rb @@ -3,7 +3,7 @@ require_relative "utils" if defined?(OpenSSL::TestUtils) -class OpenSSL::TestOCSP < Test::Unit::TestCase +class OpenSSL::TestOCSP < OpenSSL::TestCase def setup ca_subj = OpenSSL::X509::Name.parse("/DC=org/DC=ruby-lang/CN=TestCA") ca_key = OpenSSL::TestUtils::TEST_KEY_RSA1024 diff --git a/test/test_pair.rb b/test/test_pair.rb index f815eca0..4251f1ba 100644 --- a/test/test_pair.rb +++ b/test/test_pair.rb @@ -517,36 +517,36 @@ module OpenSSL::TestPairM end end -class OpenSSL::TestEOF1 < Test::Unit::TestCase +class OpenSSL::TestEOF1 < OpenSSL::TestCase include TestEOF include OpenSSL::SSLPair include OpenSSL::TestEOF1M end -class OpenSSL::TestEOF1LowlevelSocket < Test::Unit::TestCase +class OpenSSL::TestEOF1LowlevelSocket < OpenSSL::TestCase include TestEOF include OpenSSL::SSLPairLowlevelSocket include OpenSSL::TestEOF1M end -class OpenSSL::TestEOF2 < Test::Unit::TestCase +class OpenSSL::TestEOF2 < OpenSSL::TestCase include TestEOF include OpenSSL::SSLPair include OpenSSL::TestEOF2M end -class OpenSSL::TestEOF2LowlevelSocket < Test::Unit::TestCase +class OpenSSL::TestEOF2LowlevelSocket < OpenSSL::TestCase include TestEOF include OpenSSL::SSLPairLowlevelSocket include OpenSSL::TestEOF2M end -class OpenSSL::TestPair < Test::Unit::TestCase +class OpenSSL::TestPair < OpenSSL::TestCase include OpenSSL::SSLPair include OpenSSL::TestPairM end -class OpenSSL::TestPairLowlevelSocket < Test::Unit::TestCase +class OpenSSL::TestPairLowlevelSocket < OpenSSL::TestCase include OpenSSL::SSLPairLowlevelSocket include OpenSSL::TestPairM end diff --git a/test/test_pkcs12.rb b/test/test_pkcs12.rb index ba07d767..61fb4474 100644 --- a/test/test_pkcs12.rb +++ b/test/test_pkcs12.rb @@ -4,7 +4,7 @@ require_relative "utils" if defined?(OpenSSL::TestUtils) module OpenSSL - class TestPKCS12 < Test::Unit::TestCase + class TestPKCS12 < OpenSSL::TestCase include OpenSSL::TestUtils def setup diff --git a/test/test_pkcs5.rb b/test/test_pkcs5.rb index f38fd716..ad8132c2 100644 --- a/test/test_pkcs5.rb +++ b/test/test_pkcs5.rb @@ -1,7 +1,7 @@ # frozen_string_literal: false require_relative 'utils' -class OpenSSL::TestPKCS5 < Test::Unit::TestCase +class OpenSSL::TestPKCS5 < OpenSSL::TestCase def test_pbkdf2_hmac_sha1_rfc6070_c_1_len_20 p ="password" diff --git a/test/test_pkcs7.rb b/test/test_pkcs7.rb index ce99db50..dfe4c6ca 100644 --- a/test/test_pkcs7.rb +++ b/test/test_pkcs7.rb @@ -3,7 +3,7 @@ require_relative 'utils' if defined?(OpenSSL::TestUtils) -class OpenSSL::TestPKCS7 < Test::Unit::TestCase +class OpenSSL::TestPKCS7 < OpenSSL::TestCase def setup @rsa1024 = OpenSSL::TestUtils::TEST_KEY_RSA1024 @rsa2048 = OpenSSL::TestUtils::TEST_KEY_RSA2048 diff --git a/test/test_pkey_dh.rb b/test/test_pkey_dh.rb index a0eca53c..afd7a318 100644 --- a/test/test_pkey_dh.rb +++ b/test/test_pkey_dh.rb @@ -3,7 +3,7 @@ require_relative 'utils' if defined?(OpenSSL::TestUtils) -class OpenSSL::TestPKeyDH < Test::Unit::TestCase +class OpenSSL::TestPKeyDH < OpenSSL::TestCase NEW_KEYLEN = 256 diff --git a/test/test_pkey_dsa.rb b/test/test_pkey_dsa.rb index eb3e4f1c..2c0e1fc2 100644 --- a/test/test_pkey_dsa.rb +++ b/test/test_pkey_dsa.rb @@ -4,7 +4,7 @@ require 'base64' if defined?(OpenSSL::TestUtils) -class OpenSSL::TestPKeyDSA < Test::Unit::TestCase +class OpenSSL::TestPKeyDSA < OpenSSL::TestCase def test_private key = OpenSSL::PKey::DSA.new(256) assert(key.private?) @@ -20,7 +20,6 @@ class OpenSSL::TestPKeyDSA < Test::Unit::TestCase key = OpenSSL::PKey::DSA.new 256 pem = key.public_key.to_pem OpenSSL::PKey::DSA.new pem - assert_equal([], OpenSSL.errors) end def test_new_break @@ -84,7 +83,6 @@ end assert_equal(g, key.g) assert_equal(y, key.pub_key) assert_equal(nil, key.priv_key) - assert_equal([], OpenSSL.errors) end def test_read_DSAPublicKey_pem @@ -109,7 +107,6 @@ fWLOqqkzFeRrYMDzUpl36XktY6Yq8EJYlW9pCMmBVNy/dQ== assert_equal(g, key.g) assert_equal(y, key.pub_key) assert_equal(nil, key.priv_key) - assert_equal([], OpenSSL.errors) end def test_read_DSA_PUBKEY_pem @@ -135,7 +132,6 @@ YNMbNw== assert_equal(g, key.g) assert_equal(y, key.pub_key) assert_equal(nil, key.priv_key) - assert_equal([], OpenSSL.errors) end def test_export_format_is_DSA_PUBKEY_pem @@ -165,7 +161,6 @@ YNMbNw== pub_key = OpenSSL::ASN1.decode(seq[1].value) assert_equal(OpenSSL::ASN1::INTEGER, pub_key.tag) assert_equal(key.pub_key, pub_key.value) - assert_equal([], OpenSSL.errors) end def test_read_private_key_der @@ -174,7 +169,6 @@ YNMbNw== key2 = OpenSSL::PKey.read(der) assert(key2.private?) assert_equal(der, key2.to_der) - assert_equal([], OpenSSL.errors) end def test_read_private_key_pem @@ -183,7 +177,6 @@ YNMbNw== key2 = OpenSSL::PKey.read(pem) assert(key2.private?) assert_equal(pem, key2.to_pem) - assert_equal([], OpenSSL.errors) end def test_read_public_key_der @@ -192,7 +185,6 @@ YNMbNw== key2 = OpenSSL::PKey.read(der) assert(!key2.private?) assert_equal(der, key2.to_der) - assert_equal([], OpenSSL.errors) end def test_read_public_key_pem @@ -201,7 +193,6 @@ YNMbNw== key2 = OpenSSL::PKey.read(pem) assert(!key2.private?) assert_equal(pem, key2.to_pem) - assert_equal([], OpenSSL.errors) end def test_read_private_key_pem_pw @@ -216,7 +207,6 @@ YNMbNw== key2 = OpenSSL::PKey.read(pem, 'secret') assert(key2.private?) #omit pem equality check, will be different due to cipher iv - assert_equal([], OpenSSL.errors) end def test_export_password_length diff --git a/test/test_pkey_ec.rb b/test/test_pkey_ec.rb index d3edcc47..c530ee06 100644 --- a/test/test_pkey_ec.rb +++ b/test/test_pkey_ec.rb @@ -3,7 +3,7 @@ require_relative 'utils' if defined?(OpenSSL::TestUtils) && defined?(OpenSSL::PKey::EC) -class OpenSSL::TestEC < Test::Unit::TestCase +class OpenSSL::TestEC < OpenSSL::TestCase def setup @data1 = 'foo' @data2 = 'bar' * 1000 # data too long for DSA sig @@ -131,7 +131,6 @@ class OpenSSL::TestEC < Test::Unit::TestCase ec2 = OpenSSL::PKey.read(der) assert(ec2.private_key?) assert_equal(der, ec2.to_der) - assert_equal([], OpenSSL.errors) end def test_read_private_key_pem @@ -140,7 +139,6 @@ class OpenSSL::TestEC < Test::Unit::TestCase ec2 = OpenSSL::PKey.read(pem) assert(ec2.private_key?) assert_equal(pem, ec2.to_pem) - assert_equal([], OpenSSL.errors) end def test_read_public_key_der @@ -151,7 +149,6 @@ class OpenSSL::TestEC < Test::Unit::TestCase ec3 = OpenSSL::PKey.read(der) assert(!ec3.private_key?) assert_equal(der, ec3.to_der) - assert_equal([], OpenSSL.errors) end def test_read_public_key_pem @@ -162,7 +159,6 @@ class OpenSSL::TestEC < Test::Unit::TestCase ec3 = OpenSSL::PKey.read(pem) assert(!ec3.private_key?) assert_equal(pem, ec3.to_pem) - assert_equal([], OpenSSL.errors) end def test_read_private_key_pem_pw @@ -177,7 +173,6 @@ class OpenSSL::TestEC < Test::Unit::TestCase ec2 = OpenSSL::PKey.read(pem, 'secret') assert(ec2.private_key?) #omit pem equality check, will be different due to cipher iv - assert_equal([], OpenSSL.errors) end def test_export_password_length diff --git a/test/test_pkey_rsa.rb b/test/test_pkey_rsa.rb index 165b1ec9..54fce2f5 100644 --- a/test/test_pkey_rsa.rb +++ b/test/test_pkey_rsa.rb @@ -4,7 +4,7 @@ require 'base64' if defined?(OpenSSL::TestUtils) -class OpenSSL::TestPKeyRSA < Test::Unit::TestCase +class OpenSSL::TestPKeyRSA < OpenSSL::TestCase def test_padding key = OpenSSL::PKey::RSA.new(512, 3) @@ -180,7 +180,6 @@ AudJR1JobbIbDJrQu6AXnWh5k/YtAgMBAAE= assert_equal(nil, key.d) assert_equal(nil, key.p) assert_equal(nil, key.q) - assert_equal([], OpenSSL.errors) end def test_read_RSA_PUBKEY_pem @@ -201,7 +200,6 @@ AwEAAQ== assert_equal(nil, key.d) assert_equal(nil, key.p) assert_equal(nil, key.q) - assert_equal([], OpenSSL.errors) end def test_export_format_is_RSA_PUBKEY @@ -223,7 +221,6 @@ AwEAAQ== key = OpenSSL::PKey.read(der) assert(key.private?) assert_equal(der, key.to_der) - assert_equal([], OpenSSL.errors) end def test_read_private_key_pem @@ -231,7 +228,6 @@ AwEAAQ== key = OpenSSL::PKey.read(pem) assert(key.private?) assert_equal(pem, key.to_pem) - assert_equal([], OpenSSL.errors) end def test_read_public_key_der @@ -239,7 +235,6 @@ AwEAAQ== key = OpenSSL::PKey.read(der) assert(!key.private?) assert_equal(der, key.to_der) - assert_equal([], OpenSSL.errors) end def test_read_public_key_pem @@ -247,7 +242,6 @@ AwEAAQ== key = OpenSSL::PKey.read(pem) assert(!key.private?) assert_equal(pem, key.to_pem) - assert_equal([], OpenSSL.errors) end def test_read_private_key_pem_pw @@ -261,7 +255,6 @@ AwEAAQ== key = OpenSSL::PKey.read(pem, 'secret') assert(key.private?) #omit pem equality check, will be different due to cipher iv - assert_equal([], OpenSSL.errors) end def test_read_private_key_pem_pw_exception @@ -272,7 +265,6 @@ AwEAAQ== raise RuntimeError end end - assert_equal([], OpenSSL.errors) end def test_export_password_length @@ -306,7 +298,6 @@ AwEAAQ== assert_equal(key.n, pub_key.value[0].value) assert_equal(OpenSSL::ASN1::INTEGER, pub_key.value[1].tag) assert_equal(key.e, pub_key.value[1].value) - assert_equal([], OpenSSL.errors) end end diff --git a/test/test_random.rb b/test/test_random.rb index 8c69d543..defa09dd 100644 --- a/test/test_random.rb +++ b/test/test_random.rb @@ -4,7 +4,7 @@ begin rescue LoadError end -class OpenSSL::TestRandom < Test::Unit::TestCase +class OpenSSL::TestRandom < OpenSSL::TestCase def test_random_bytes assert_equal("", OpenSSL::Random.random_bytes(0)) assert_equal(12, OpenSSL::Random.random_bytes(12).bytesize) diff --git a/test/test_x509cert.rb b/test/test_x509cert.rb index 72cb9e60..ae7a0f08 100644 --- a/test/test_x509cert.rb +++ b/test/test_x509cert.rb @@ -3,7 +3,7 @@ require_relative "utils" if defined?(OpenSSL::TestUtils) -class OpenSSL::TestX509Certificate < Test::Unit::TestCase +class OpenSSL::TestX509Certificate < OpenSSL::TestCase def setup @rsa1024 = OpenSSL::TestUtils::TEST_KEY_RSA1024 @rsa2048 = OpenSSL::TestUtils::TEST_KEY_RSA2048 @@ -14,9 +14,6 @@ class OpenSSL::TestX509Certificate < Test::Unit::TestCase @ee2 = OpenSSL::X509::Name.parse("/DC=org/DC=ruby-lang/CN=EE2") end - def teardown - end - def issue_cert(*args) OpenSSL::TestUtils.issue_cert(*args) end diff --git a/test/test_x509crl.rb b/test/test_x509crl.rb index 7994ddea..fd66c975 100644 --- a/test/test_x509crl.rb +++ b/test/test_x509crl.rb @@ -3,7 +3,7 @@ require_relative "utils" if defined?(OpenSSL::TestUtils) -class OpenSSL::TestX509CRL < Test::Unit::TestCase +class OpenSSL::TestX509CRL < OpenSSL::TestCase def setup @rsa1024 = OpenSSL::TestUtils::TEST_KEY_RSA1024 @rsa2048 = OpenSSL::TestUtils::TEST_KEY_RSA2048 @@ -14,9 +14,6 @@ class OpenSSL::TestX509CRL < Test::Unit::TestCase @ee2 = OpenSSL::X509::Name.parse("/DC=org/DC=ruby-lang/CN=EE2") end - def teardown - end - def issue_crl(*args) OpenSSL::TestUtils.issue_crl(*args) end diff --git a/test/test_x509ext.rb b/test/test_x509ext.rb index e6d49bb6..99e2eda5 100644 --- a/test/test_x509ext.rb +++ b/test/test_x509ext.rb @@ -3,7 +3,7 @@ require_relative 'utils' if defined?(OpenSSL::TestUtils) -class OpenSSL::TestX509Extension < Test::Unit::TestCase +class OpenSSL::TestX509Extension < OpenSSL::TestCase def setup @basic_constraints_value = OpenSSL::ASN1::Sequence([ OpenSSL::ASN1::Boolean(true), # CA @@ -16,9 +16,6 @@ class OpenSSL::TestX509Extension < Test::Unit::TestCase ]) end - def teardown - end - def test_new ext = OpenSSL::X509::Extension.new(@basic_constraints.to_der) assert_equal("basicConstraints", ext.oid) diff --git a/test/test_x509name.rb b/test/test_x509name.rb index 56e79879..d26174ef 100644 --- a/test/test_x509name.rb +++ b/test/test_x509name.rb @@ -4,7 +4,7 @@ require_relative 'utils' if defined?(OpenSSL::TestUtils) -class OpenSSL::TestX509Name < Test::Unit::TestCase +class OpenSSL::TestX509Name < OpenSSL::TestCase OpenSSL::ASN1::ObjectId.register( "1.2.840.113549.1.9.1", "emailAddress", "emailAddress") OpenSSL::ASN1::ObjectId.register( @@ -15,9 +15,6 @@ class OpenSSL::TestX509Name < Test::Unit::TestCase @obj_type_tmpl.update(OpenSSL::X509::Name::OBJECT_TYPE_TEMPLATE) end - def teardown - end - def test_s_new dn = [ ["C", "JP"], ["O", "example"], ["CN", "www.example.jp"] ] name = OpenSSL::X509::Name.new(dn) diff --git a/test/test_x509req.rb b/test/test_x509req.rb index ee2347b5..c473b47a 100644 --- a/test/test_x509req.rb +++ b/test/test_x509req.rb @@ -3,7 +3,7 @@ require_relative "utils" if defined?(OpenSSL::TestUtils) -class OpenSSL::TestX509Request < Test::Unit::TestCase +class OpenSSL::TestX509Request < OpenSSL::TestCase def setup @rsa1024 = OpenSSL::TestUtils::TEST_KEY_RSA1024 @rsa2048 = OpenSSL::TestUtils::TEST_KEY_RSA2048 diff --git a/test/test_x509store.rb b/test/test_x509store.rb index 9964cc8f..6a443a7c 100644 --- a/test/test_x509store.rb +++ b/test/test_x509store.rb @@ -3,7 +3,7 @@ require_relative "utils" if defined?(OpenSSL::TestUtils) -class OpenSSL::TestX509Store < Test::Unit::TestCase +class OpenSSL::TestX509Store < OpenSSL::TestCase def setup @rsa1024 = OpenSSL::TestUtils::TEST_KEY_RSA1024 @rsa2048 = OpenSSL::TestUtils::TEST_KEY_RSA2048 @@ -15,9 +15,6 @@ class OpenSSL::TestX509Store < Test::Unit::TestCase @ee2 = OpenSSL::X509::Name.parse("/DC=org/DC=ruby-lang/CN=EE2") end - def teardown - end - def test_nosegv_on_cleanup cert = OpenSSL::X509::Certificate.new store = OpenSSL::X509::Store.new diff --git a/test/utils.rb b/test/utils.rb index 8e21b977..8ce53290 100644 --- a/test/utils.rb +++ b/test/utils.rb @@ -182,7 +182,14 @@ AQjjxMXhwULlmuR/K+WwlaZPiLIBYalLAZQ7ZbOPeVkJ8ePao0eLAgEC end end - class OpenSSL::SSLTestCase < Test::Unit::TestCase + class OpenSSL::TestCase < Test::Unit::TestCase + def teardown + # OpenSSL error stack must be empty + assert_equal([], OpenSSL.errors) + end + end + + class OpenSSL::SSLTestCase < OpenSSL::TestCase RUBY = EnvUtil.rubybin ITERATIONS = ($0 == __FILE__) ? 100 : 10 @@ -207,9 +214,6 @@ AQjjxMXhwULlmuR/K+WwlaZPiLIBYalLAZQ7ZbOPeVkJ8ePao0eLAgEC @server = nil end - def teardown - end - def issue_cert(*arg) OpenSSL::TestUtils.issue_cert(*arg) end -- cgit v1.2.3 From b98df238af74d2ea60b64abacba5bd0d4b125d96 Mon Sep 17 00:00:00 2001 From: nobu Date: Wed, 18 May 2016 04:36:02 +0000 Subject: ossl_pkey_ec.c: index types * ext/openssl/ossl_pkey_ec.c (ossl_ec_point_mul): fix index types. Array length is long, not int. git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@55052 b2dd03c8-39d4-4d8f-98ff-823fe69b080e --- ext/openssl/ossl_pkey_ec.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ext/openssl/ossl_pkey_ec.c b/ext/openssl/ossl_pkey_ec.c index a5bddd7d..26eb5e8a 100644 --- a/ext/openssl/ossl_pkey_ec.c +++ b/ext/openssl/ossl_pkey_ec.c @@ -1543,7 +1543,7 @@ static VALUE ossl_ec_point_mul(int argc, VALUE *argv, VALUE self) * bignums | arg1[0] | arg1[1] | arg1[2] | ... * points | self | arg2[0] | arg2[1] | ... */ - int i, num; + long i, num; VALUE tmp_p, tmp_b; const EC_POINT **points; const BIGNUM **bignums; -- cgit v1.2.3 From 43d7bd9973cc54cb88b493950f1696fe92d26d76 Mon Sep 17 00:00:00 2001 From: nobu Date: Wed, 18 May 2016 07:24:02 +0000 Subject: openssl/test_random.rb: requires utils.rb * test/openssl/test_random.rb: requires test/openssl/utils.rb for OpenSSL::TestCase now. git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@55056 b2dd03c8-39d4-4d8f-98ff-823fe69b080e --- test/test_random.rb | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/test/test_random.rb b/test/test_random.rb index defa09dd..e0c19cd3 100644 --- a/test/test_random.rb +++ b/test/test_random.rb @@ -1,8 +1,5 @@ # frozen_string_literal: false -begin - require "openssl" -rescue LoadError -end +require_relative "utils" class OpenSSL::TestRandom < OpenSSL::TestCase def test_random_bytes -- cgit v1.2.3 From c9d098b6053ba26aca6436a84abdde7c62394fe8 Mon Sep 17 00:00:00 2001 From: rhe Date: Wed, 18 May 2016 07:59:09 +0000 Subject: openssl: fix OpenSSL error queue leak in OpenSSL::PKCS12.new * ext/openssl/ossl_pkcs12.c (ossl_pkcs12_initialize): pop errors leaked by PKCS12_parse(). This is a bug in OpenSSL, which exists in the versions before the version 1.0.0t, 1.0.1p, 1.0.2d. git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@55057 b2dd03c8-39d4-4d8f-98ff-823fe69b080e --- ext/openssl/ossl_pkcs12.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/ext/openssl/ossl_pkcs12.c b/ext/openssl/ossl_pkcs12.c index e5052d47..fe4dadc1 100644 --- a/ext/openssl/ossl_pkcs12.c +++ b/ext/openssl/ossl_pkcs12.c @@ -165,8 +165,12 @@ ossl_pkcs12_initialize(int argc, VALUE *argv, VALUE self) BIO_free(in); pkey = cert = ca = Qnil; + /* OpenSSL's bug; PKCS12_parse() puts errors even if it succeeds. + * Fixed in OpenSSL 1.0.0t, 1.0.1p, 1.0.2d */ + ERR_set_mark(); if(!PKCS12_parse(pkcs, passphrase, &key, &x509, &x509s)) ossl_raise(ePKCS12Error, "PKCS12_parse"); + ERR_pop_to_mark(); pkey = rb_protect((VALUE(*)_((VALUE)))ossl_pkey_new, (VALUE)key, &st); /* NO DUP */ if(st) goto err; -- cgit v1.2.3 From e6d66d075f81d717dc8d6e1dcf4c3e298cc1792b Mon Sep 17 00:00:00 2001 From: nobu Date: Wed, 18 May 2016 08:06:23 +0000 Subject: test_random.rb: skip old OpenSSL * test/openssl/test_random.rb (OpenSSL::TestRandom): ignore out-of-date OpenSSL before 1.0, as well as other tests. git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@55058 b2dd03c8-39d4-4d8f-98ff-823fe69b080e --- test/test_random.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/test_random.rb b/test/test_random.rb index e0c19cd3..ca8427f7 100644 --- a/test/test_random.rb +++ b/test/test_random.rb @@ -11,4 +11,4 @@ class OpenSSL::TestRandom < OpenSSL::TestCase assert_equal("", OpenSSL::Random.pseudo_bytes(0)) assert_equal(12, OpenSSL::Random.pseudo_bytes(12).bytesize) end -end if defined?(OpenSSL::Random) +end if defined?(OpenSSL::TestCase) -- cgit v1.2.3 From dafb16f2a61aee79a81b537f36db23ac73766a22 Mon Sep 17 00:00:00 2001 From: rhe Date: Wed, 18 May 2016 08:52:37 +0000 Subject: openssl: fix test failure of OpenSSL::TestEC#test_ec_point_mul * test/openssl/test_pkey_ec.rb (test_ec_point_mul): CentOS 7 patches OpenSSL to reject curves defined over a small field. git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@55059 b2dd03c8-39d4-4d8f-98ff-823fe69b080e --- test/test_pkey_ec.rb | 49 +++++++++++++++++++++++++++---------------------- 1 file changed, 27 insertions(+), 22 deletions(-) diff --git a/test/test_pkey_ec.rb b/test/test_pkey_ec.rb index c530ee06..0a2351d9 100644 --- a/test/test_pkey_ec.rb +++ b/test/test_pkey_ec.rb @@ -185,28 +185,33 @@ class OpenSSL::TestEC < OpenSSL::TestCase end def test_ec_point_mul - # y^2 = x^3 + 2x + 2 over F_17 - # generator is (5, 1) - group = OpenSSL::PKey::EC::Group.new(:GFp, 17, 2, 2) - gen = OpenSSL::PKey::EC::Point.new(group, OpenSSL::BN.new("040501", 16)) - group.set_generator(gen, 0, 0) - - # 3 * (6, 3) = (16, 13) - point_a = OpenSSL::PKey::EC::Point.new(group, OpenSSL::BN.new("040603", 16)) - result_a1 = point_a.mul(3.to_bn) - assert_equal("04100D", result_a1.to_bn.to_s(16)) - # 3 * (6, 3) + 3 * (5, 1) = (7, 6) - result_a2 = point_a.mul(3.to_bn, 3.to_bn) - assert_equal("040706", result_a2.to_bn.to_s(16)) - # 3 * point_a = 3 * (6, 3) = (16, 13) - result_b1 = point_a.mul([3.to_bn], []) - assert_equal("04100D", result_b1.to_bn.to_s(16)) - # 3 * point_a + 2 * point_a = 3 * (6, 3) + 2 * (6, 3) = (7, 11) - result_b1 = point_a.mul([3.to_bn, 2.to_bn], [point_a]) - assert_equal("04070B", result_b1.to_bn.to_s(16)) - # 3 * point_a + 5 * point_a.group.generator = 3 * (6, 3) + 5 * (5, 1) = (13, 10) - result_b1 = point_a.mul([3.to_bn], [], 5) - assert_equal("040D0A", result_b1.to_bn.to_s(16)) + begin + # y^2 = x^3 + 2x + 2 over F_17 + # generator is (5, 1) + group = OpenSSL::PKey::EC::Group.new(:GFp, 17, 2, 2) + gen = OpenSSL::PKey::EC::Point.new(group, OpenSSL::BN.new("040501", 16)) + group.set_generator(gen, 0, 0) + + # 3 * (6, 3) = (16, 13) + point_a = OpenSSL::PKey::EC::Point.new(group, OpenSSL::BN.new("040603", 16)) + result_a1 = point_a.mul(3.to_bn) + assert_equal("04100D", result_a1.to_bn.to_s(16)) + # 3 * (6, 3) + 3 * (5, 1) = (7, 6) + result_a2 = point_a.mul(3.to_bn, 3.to_bn) + assert_equal("040706", result_a2.to_bn.to_s(16)) + # 3 * point_a = 3 * (6, 3) = (16, 13) + result_b1 = point_a.mul([3.to_bn], []) + assert_equal("04100D", result_b1.to_bn.to_s(16)) + # 3 * point_a + 2 * point_a = 3 * (6, 3) + 2 * (6, 3) = (7, 11) + result_b1 = point_a.mul([3.to_bn, 2.to_bn], [point_a]) + assert_equal("04070B", result_b1.to_bn.to_s(16)) + # 3 * point_a + 5 * point_a.group.generator = 3 * (6, 3) + 5 * (5, 1) = (13, 10) + result_b1 = point_a.mul([3.to_bn], [], 5) + assert_equal("040D0A", result_b1.to_bn.to_s(16)) + rescue OpenSSL::PKey::EC::Group::Error + # CentOS patches OpenSSL to reject curves defined over Fp where p < 256 bits + raise if e.message !~ /unsupported field/ + end p256_key = OpenSSL::TestUtils::TEST_KEY_EC_P256V1 p256_g = p256_key.group -- cgit v1.2.3 From ee4e04285760abbea1eb17b46cff5be0b540fb95 Mon Sep 17 00:00:00 2001 From: rhe Date: Wed, 18 May 2016 10:07:38 +0000 Subject: openssl: fix test failure due to the previous commit * test/openssl/test_pkey_ec.rb (test_ec_point_mul): My previous commit r55059 was broken. I should have been more careful. Sorry. git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@55060 b2dd03c8-39d4-4d8f-98ff-823fe69b080e --- test/test_pkey_ec.rb | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/test/test_pkey_ec.rb b/test/test_pkey_ec.rb index 0a2351d9..673b0d6f 100644 --- a/test/test_pkey_ec.rb +++ b/test/test_pkey_ec.rb @@ -210,7 +210,7 @@ class OpenSSL::TestEC < OpenSSL::TestCase assert_equal("040D0A", result_b1.to_bn.to_s(16)) rescue OpenSSL::PKey::EC::Group::Error # CentOS patches OpenSSL to reject curves defined over Fp where p < 256 bits - raise if e.message !~ /unsupported field/ + raise if $!.message !~ /unsupported field/ end p256_key = OpenSSL::TestUtils::TEST_KEY_EC_P256V1 @@ -218,10 +218,11 @@ class OpenSSL::TestEC < OpenSSL::TestCase assert_equal(p256_key.public_key, p256_g.generator.mul(p256_key.private_key)) # invalid argument - assert_raise(TypeError) { point_a.mul(nil) } - assert_raise(ArgumentError) { point_a.mul([1.to_bn], [point_a]) } - assert_raise(TypeError) { point_a.mul([1.to_bn], nil) } - assert_raise(TypeError) { point_a.mul([nil], []) } + point = p256_key.public_key + assert_raise(TypeError) { point.mul(nil) } + assert_raise(ArgumentError) { point.mul([1.to_bn], [point]) } + assert_raise(TypeError) { point.mul([1.to_bn], nil) } + assert_raise(TypeError) { point.mul([nil], []) } end # test Group: asn1_flag, point_conversion -- cgit v1.2.3 From 5c6494eff386176ffc45549c646c892aac4c08da Mon Sep 17 00:00:00 2001 From: rhe Date: Thu, 19 May 2016 04:12:57 +0000 Subject: openssl: check argument type in OpenSSL::X509::Attribute#value= * ext/openssl/ossl_x509attr.c (ossl_x509attr_set_value): check that the argument is an OpenSSL::ASN1::Data before converting to ASN1_TYPE. This fixes SEGV on OpenSSL::X509::Attribute#value=(non-asn1-value). * test/openssl/test_x509attr.rb: add tests for OpenSSL::X509::Attribute. git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@55071 b2dd03c8-39d4-4d8f-98ff-823fe69b080e --- ext/openssl/ossl_x509attr.c | 1 + test/test_x509attr.rb | 56 +++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 57 insertions(+) create mode 100644 test/test_x509attr.rb diff --git a/ext/openssl/ossl_x509attr.c b/ext/openssl/ossl_x509attr.c index d0f41c6b..be5f2dcf 100644 --- a/ext/openssl/ossl_x509attr.c +++ b/ext/openssl/ossl_x509attr.c @@ -196,6 +196,7 @@ ossl_x509attr_set_value(VALUE self, VALUE value) X509_ATTRIBUTE *attr; ASN1_TYPE *a1type; + OSSL_Check_Kind(value, cASN1Data); if(!(a1type = ossl_asn1_get_asn1type(value))) ossl_raise(eASN1Error, "could not get ASN1_TYPE"); if(ASN1_TYPE_get(a1type) == V_ASN1_SEQUENCE){ diff --git a/test/test_x509attr.rb b/test/test_x509attr.rb new file mode 100644 index 00000000..1ba8a875 --- /dev/null +++ b/test/test_x509attr.rb @@ -0,0 +1,56 @@ +# frozen_string_literal: false +require_relative "utils" + +if defined?(OpenSSL::TestUtils) + +class OpenSSL::TestX509Attribute < OpenSSL::TestCase + def test_new + ef = OpenSSL::X509::ExtensionFactory.new + val = OpenSSL::ASN1::Set.new([OpenSSL::ASN1::Sequence.new([ + ef.create_extension("keyUsage", "keyCertSign", true) + ])]) + attr = OpenSSL::X509::Attribute.new("extReq", val) + assert_equal("extReq", attr.oid) + assert_equal(val.to_der, attr.value.to_der) + end + + def test_from_der + # oid: challengePassword, values: Set[UTF8String<"abc123">] + test_der = "\x30\x15\x06\x09\x2a\x86\x48\x86\xf7\x0d\x01\x09\x07\x31\x08" \ + "\x0c\x06\x61\x62\x63\x31\x32\x33".b + attr = OpenSSL::X509::Attribute.new(test_der) + assert_equal(test_der, attr.to_der) + assert_equal("challengePassword", attr.oid) + assert_equal("abc123", attr.value.value[0].value) + end + + def test_to_der + ef = OpenSSL::X509::ExtensionFactory.new + val = OpenSSL::ASN1::Set.new([OpenSSL::ASN1::Sequence.new([ + ef.create_extension("keyUsage", "keyCertSign", true) + ])]) + attr = OpenSSL::X509::Attribute.new("extReq", val) + expected = OpenSSL::ASN1::Sequence.new([ + OpenSSL::ASN1::ObjectId.new("extReq"), + val + ]) + assert_equal(expected.to_der, attr.to_der) + end + + def test_invalid_value + # should not change the original value + test_der = "\x30\x15\x06\x09\x2a\x86\x48\x86\xf7\x0d\x01\x09\x07\x31\x08" \ + "\x0c\x06\x61\x62\x63\x31\x32\x33".b + attr = OpenSSL::X509::Attribute.new(test_der) + assert_raise(TypeError) { + attr.value = "1234" + } + assert_equal(test_der, attr.to_der) + assert_raise(OpenSSL::X509::AttributeError) { + attr.oid = "abc123" + } + assert_equal(test_der, attr.to_der) + end +end + +end -- cgit v1.2.3 From 76e933a5a517971327784ba7edc993f727ed0b35 Mon Sep 17 00:00:00 2001 From: rhe Date: Thu, 19 May 2016 04:53:05 +0000 Subject: openssl: register ex_data index for X509_STORE{_CTX,} respectively * ext/openssl/ossl.c (Init_openssl): register an ex_data index for X509_STORE and X509_STORE_CTX respectively. Since they don't share the ex_data index registry, we can't use the same index. (ossl_verify_cb): use the the correct index. * ext/openssl/ossl_ssl.c (ossl_ssl_verify_callback): ditto. * ext/openssl/ossl_x509store.c (ossl_x509store_set_vfy_cb): ditto. (ossl_x509stctx_verify): ditto. * ext/openssl/ossl.h (void ossl_clear_error): add extern declarations of ossl_store_{ctx_,}ex_verify_cb_idx. * ext/openssl/openssl_missing.c: remove X509_STORE_set_ex_data and X509_STORE_get_ex_data. * ext/openssl/openssl_missing.h: implement X509_STORE_get_ex_data, X509_STORE_set_ex_data and X509_STORE_get_ex_new_index as macros. git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@55074 b2dd03c8-39d4-4d8f-98ff-823fe69b080e --- ext/openssl/openssl_missing.c | 14 -------------- ext/openssl/openssl_missing.h | 9 +++++++-- ext/openssl/ossl.c | 15 +++++++++------ ext/openssl/ossl.h | 3 ++- ext/openssl/ossl_ssl.c | 2 +- ext/openssl/ossl_x509store.c | 4 ++-- 6 files changed, 21 insertions(+), 26 deletions(-) diff --git a/ext/openssl/openssl_missing.c b/ext/openssl/openssl_missing.c index bd8eef5e..31f2d0a5 100644 --- a/ext/openssl/openssl_missing.c +++ b/ext/openssl/openssl_missing.c @@ -34,20 +34,6 @@ HMAC_CTX_copy(HMAC_CTX *out, HMAC_CTX *in) #endif /* HAVE_HMAC_CTX_COPY */ #endif /* NO_HMAC */ -#if !defined(HAVE_X509_STORE_SET_EX_DATA) -int X509_STORE_set_ex_data(X509_STORE *str, int idx, void *data) -{ - return CRYPTO_set_ex_data(&str->ex_data, idx, data); -} -#endif - -#if !defined(HAVE_X509_STORE_GET_EX_DATA) -void *X509_STORE_get_ex_data(X509_STORE *str, int idx) -{ - return CRYPTO_get_ex_data(&str->ex_data, idx); -} -#endif - #if !defined(HAVE_EVP_MD_CTX_CREATE) EVP_MD_CTX * EVP_MD_CTX_create(void) diff --git a/ext/openssl/openssl_missing.h b/ext/openssl/openssl_missing.h index 2dc49d3f..955579cf 100644 --- a/ext/openssl/openssl_missing.h +++ b/ext/openssl/openssl_missing.h @@ -133,11 +133,16 @@ int EVP_CIPHER_CTX_copy(EVP_CIPHER_CTX *out, EVP_CIPHER_CTX *in); #endif #if !defined(HAVE_X509_STORE_GET_EX_DATA) -void *X509_STORE_get_ex_data(X509_STORE *str, int idx); +# define X509_STORE_get_ex_data(x, idx) \ + CRYPTO_get_ex_data(&(x)->ex_data, (idx)) #endif #if !defined(HAVE_X509_STORE_SET_EX_DATA) -int X509_STORE_set_ex_data(X509_STORE *str, int idx, void *data); +# define X509_STORE_set_ex_data(x, idx, data) \ + CRYPTO_set_ex_data(&(x)->ex_data, (idx), (data)) +# define X509_STORE_get_ex_new_index(l, p, newf, dupf, freef) \ + CRYPTO_get_ex_new_index(CRYPTO_EX_INDEX_X509_STORE, (l), (p), \ + (newf), (dupf), (freef)) #endif #if !defined(HAVE_X509_CRL_SET_VERSION) diff --git a/ext/openssl/ossl.c b/ext/openssl/ossl.c index ac828151..2b5579e3 100644 --- a/ext/openssl/ossl.c +++ b/ext/openssl/ossl.c @@ -198,7 +198,8 @@ ossl_pem_passwd_cb(char *buf, int max_len, int flag, void *pwd) /* * Verify callback */ -int ossl_verify_cb_idx; +int ossl_store_ctx_ex_verify_cb_idx; +int ossl_store_ex_verify_cb_idx; VALUE ossl_call_verify_cb_proc(struct ossl_verify_cb_args *args) @@ -214,10 +215,10 @@ ossl_verify_cb(int ok, X509_STORE_CTX *ctx) struct ossl_verify_cb_args args; int state = 0; - proc = (VALUE)X509_STORE_CTX_get_ex_data(ctx, ossl_verify_cb_idx); - if ((void*)proc == 0) - proc = (VALUE)X509_STORE_get_ex_data(ctx->ctx, ossl_verify_cb_idx); - if ((void*)proc == 0) + proc = (VALUE)X509_STORE_CTX_get_ex_data(ctx, ossl_store_ctx_ex_verify_cb_idx); + if (!proc) + proc = (VALUE)X509_STORE_get_ex_data(ctx->ctx, ossl_store_ex_verify_cb_idx); + if (!proc) return ok; if (!NIL_P(proc)) { ret = Qfalse; @@ -1137,8 +1138,10 @@ Init_openssl(void) /* * Verify callback Proc index for ext-data */ - if ((ossl_verify_cb_idx = X509_STORE_CTX_get_ex_new_index(0, (void *)"ossl_verify_cb_idx", 0, 0, 0)) < 0) + if ((ossl_store_ctx_ex_verify_cb_idx = X509_STORE_CTX_get_ex_new_index(0, (void *)"ossl_store_ctx_ex_verify_cb_idx", 0, 0, 0)) < 0) ossl_raise(eOSSLError, "X509_STORE_CTX_get_ex_new_index"); + if ((ossl_store_ex_verify_cb_idx = X509_STORE_get_ex_new_index(0, (void *)"ossl_store_ex_verify_cb_idx", 0, 0, 0)) < 0) + ossl_raise(eOSSLError, "X509_STORE_get_ex_new_index"); /* * Init debug core diff --git a/ext/openssl/ossl.h b/ext/openssl/ossl.h index a31ca951..5b2f6e11 100644 --- a/ext/openssl/ossl.h +++ b/ext/openssl/ossl.h @@ -171,7 +171,8 @@ void ossl_clear_error(void); /* * Verify callback */ -extern int ossl_verify_cb_idx; +extern int ossl_store_ctx_ex_verify_cb_idx; +extern int ossl_store_ex_verify_cb_idx; struct ossl_verify_cb_args { VALUE proc; diff --git a/ext/openssl/ossl_ssl.c b/ext/openssl/ossl_ssl.c index 938e36f1..87df7f9f 100644 --- a/ext/openssl/ossl_ssl.c +++ b/ext/openssl/ossl_ssl.c @@ -308,7 +308,7 @@ ossl_ssl_verify_callback(int preverify_ok, X509_STORE_CTX *ctx) ssl = X509_STORE_CTX_get_ex_data(ctx, SSL_get_ex_data_X509_STORE_CTX_idx()); cb = (VALUE)SSL_get_ex_data(ssl, ossl_ssl_ex_vcb_idx); - X509_STORE_CTX_set_ex_data(ctx, ossl_verify_cb_idx, (void*)cb); + X509_STORE_CTX_set_ex_data(ctx, ossl_store_ctx_ex_verify_cb_idx, (void *)cb); return ossl_verify_cb(preverify_ok, ctx); } diff --git a/ext/openssl/ossl_x509store.c b/ext/openssl/ossl_x509store.c index aca25b15..8d6f9de2 100644 --- a/ext/openssl/ossl_x509store.c +++ b/ext/openssl/ossl_x509store.c @@ -130,7 +130,7 @@ ossl_x509store_set_vfy_cb(VALUE self, VALUE cb) X509_STORE *store; GetX509Store(self, store); - X509_STORE_set_ex_data(store, ossl_verify_cb_idx, (void*)cb); + X509_STORE_set_ex_data(store, ossl_store_ex_verify_cb_idx, (void *)cb); rb_iv_set(self, "@verify_callback", cb); return cb; @@ -466,7 +466,7 @@ ossl_x509stctx_verify(VALUE self) X509_STORE_CTX *ctx; GetX509StCtx(self, ctx); - X509_STORE_CTX_set_ex_data(ctx, ossl_verify_cb_idx, + X509_STORE_CTX_set_ex_data(ctx, ossl_store_ctx_ex_verify_cb_idx, (void *)rb_iv_get(self, "@verify_callback")); switch (X509_verify_cert(ctx)) { -- cgit v1.2.3 From 012635971c01cefbfab15dc51edf1fe29661fc72 Mon Sep 17 00:00:00 2001 From: rhe Date: Fri, 20 May 2016 04:36:03 +0000 Subject: openssl: don't test default session lifetime value OpenSSL's default session timeout for TLS v1.0 method is not 300 seconds but 7200. The TLS v1.0 specification[1] mentions about it as just "An upper limit of 24 hours is suggested for session ID lifetimes,". And according to OpenSSL 1.0.2h source comment[2], the value 7200 is decided just because "the 24 hours mentioned in the TLSv1 spec is way too long for http, the cache would over fill". The reason why the default lifetime is set to 300 is maybe an OpenSSL bug. We always call SSL_CTX_new() with SSLv23_method(), and this set ssl_ctx->session to 300, the default value for SSLv23_method(). But the following SSL_set_ssl_method() call does not update it. By the way this will be fixed in OpenSSL 1.1.0. [1] https://tools.ietf.org/html/rfc2246#appendix-F.1.4 [2] https://git.openssl.org/?p=openssl.git;a=blob;f=ssl/t1_lib.c;h=dd5bd0050d89f5585c1b06a227eb8221ebf984f1;hb=5dd94f1847c744929a3bd24819f1c99644bb18c7#l193 * test/openssl/test_ssl_session.rb (test_session): remove assertion of the default session timeout. git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@55078 b2dd03c8-39d4-4d8f-98ff-823fe69b080e --- test/test_ssl_session.rb | 1 - 1 file changed, 1 deletion(-) diff --git a/test/test_ssl_session.rb b/test/test_ssl_session.rb index 3294aa7f..ee1a907f 100644 --- a/test/test_ssl_session.rb +++ b/test/test_ssl_session.rb @@ -55,7 +55,6 @@ tddwpBAEDjcwMzA5NTYzMTU1MzAwpQMCARM= session = ssl.session assert(session == OpenSSL::SSL::Session.new(session.to_pem)) assert(session == OpenSSL::SSL::Session.new(ssl)) - assert_equal(300, session.timeout) session.timeout = 5 assert_equal(5, session.timeout) assert_not_nil(session.time) -- cgit v1.2.3 From f38501249f33bff7ca9d208670b8cde695ea8b7b Mon Sep 17 00:00:00 2001 From: rhe Date: Fri, 20 May 2016 15:05:25 +0000 Subject: 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 --- ext/openssl/ossl.c | 57 ++++++++++++++++++++++++++++++++++++++------- ext/openssl/ossl.h | 13 ++++++----- ext/openssl/ossl_pkey.c | 24 +++++++------------ ext/openssl/ossl_pkey_dsa.c | 15 ++++-------- ext/openssl/ossl_pkey_ec.c | 28 +++++++--------------- ext/openssl/ossl_pkey_rsa.c | 15 ++++-------- test/test_pkey_dsa.rb | 12 ++++++++++ test/test_pkey_ec.rb | 12 ++++++++++ test/test_pkey_rsa.rb | 18 ++++++++++++++ 9 files changed, 124 insertions(+), 70 deletions(-) diff --git a/ext/openssl/ossl.c b/ext/openssl/ossl.c index 2b5579e3..a0a7574c 100644 --- a/ext/openssl/ossl.c +++ b/ext/openssl/ossl.c @@ -147,6 +147,31 @@ ossl_buf2str(char *buf, int len) /* * our default PEM callback */ + +/* + * OpenSSL requires passwords for PEM-encoded files to be at least four + * characters long. See crypto/pem/pem_lib.c (as of 1.0.2h) + */ +#define OSSL_MIN_PWD_LEN 4 + +VALUE +ossl_pem_passwd_value(VALUE pass) +{ + if (NIL_P(pass)) + return Qnil; + + StringValue(pass); + + if (RSTRING_LEN(pass) < OSSL_MIN_PWD_LEN) + ossl_raise(eOSSLError, "password must be at least %d bytes", OSSL_MIN_PWD_LEN); + /* PEM_BUFSIZE is currently used as the second argument of pem_password_cb, + * that is +max_len+ of ossl_pem_passwd_cb() */ + if (RSTRING_LEN(pass) > PEM_BUFSIZE) + ossl_raise(eOSSLError, "password must be shorter than %d bytes", PEM_BUFSIZE); + + return pass; +} + static VALUE ossl_pem_passwd_cb0(VALUE flag) { @@ -159,13 +184,29 @@ ossl_pem_passwd_cb0(VALUE flag) } int -ossl_pem_passwd_cb(char *buf, int max_len, int flag, void *pwd) +ossl_pem_passwd_cb(char *buf, int max_len, int flag, void *pwd_) { - int len, status = 0; - VALUE rflag, pass; + int len, status; + VALUE rflag, pass = (VALUE)pwd_; + + if (RTEST(pass)) { + /* PEM_def_callback(buf, max_len, flag, StringValueCStr(pass)) does not + * work because it does not allow NUL characters and truncates to 1024 + * bytes silently if the input is over 1024 bytes */ + if (RB_TYPE_P(pass, T_STRING)) { + len = RSTRING_LEN(pass); + if (len >= OSSL_MIN_PWD_LEN && len <= max_len) { + memcpy(buf, RSTRING_PTR(pass), len); + return len; + } + } + OSSL_Debug("passed data is not valid String???"); + return -1; + } - if (pwd || !rb_block_given_p()) - return PEM_def_callback(buf, max_len, flag, pwd); + if (!rb_block_given_p()) { + return PEM_def_callback(buf, max_len, flag, NULL); + } while (1) { /* @@ -181,12 +222,12 @@ ossl_pem_passwd_cb(char *buf, int max_len, int flag, void *pwd) return -1; } len = RSTRING_LENINT(pass); - if (len < 4) { /* 4 is OpenSSL hardcoded limit */ - rb_warning("password must be longer than 4 bytes"); + if (len < OSSL_MIN_PWD_LEN) { + rb_warning("password must be at least %d bytes", OSSL_MIN_PWD_LEN); continue; } if (len > max_len) { - rb_warning("password must be shorter then %d bytes", max_len-1); + rb_warning("password must be shorter than %d bytes", max_len); continue; } memcpy(buf, RSTRING_PTR(pass), len); diff --git a/ext/openssl/ossl.h b/ext/openssl/ossl.h index 5b2f6e11..25f2c857 100644 --- a/ext/openssl/ossl.h +++ b/ext/openssl/ossl.h @@ -77,11 +77,6 @@ extern "C" { # include #endif -/* OpenSSL requires passwords for PEM-encoded files to be at least four - * characters long - */ -#define OSSL_MIN_PWD_LEN 4 - /* * Common Module */ @@ -146,8 +141,14 @@ do{\ }while(0) /* - * our default PEM callback + * Our default PEM callback */ +/* Convert the argument to String and validate the length. Note this may raise. */ +VALUE ossl_pem_passwd_value(VALUE); +/* Can be casted to pem_password_cb. If a password (String) is passed as the + * "arbitrary data" (typically the last parameter of PEM_{read,write}_ + * functions), uses the value. If not, but a block is given, yields to it. + * If not either, fallbacks to PEM_def_callback() which reads from stdin. */ int ossl_pem_passwd_cb(char *, int, int, void *); /* diff --git a/ext/openssl/ossl_pkey.c b/ext/openssl/ossl_pkey.c index 7e3154af..7240de82 100644 --- a/ext/openssl/ossl_pkey.c +++ b/ext/openssl/ossl_pkey.c @@ -152,27 +152,21 @@ ossl_pkey_new_from_file(VALUE filename) static VALUE ossl_pkey_new_from_data(int argc, VALUE *argv, VALUE self) { - EVP_PKEY *pkey; - BIO *bio; - VALUE data, pass; - char *passwd = NULL; + EVP_PKEY *pkey; + BIO *bio; + VALUE data, pass; - rb_scan_args(argc, argv, "11", &data, &pass); + rb_scan_args(argc, argv, "11", &data, &pass); + pass = ossl_pem_passwd_value(pass); - bio = ossl_obj2bio(data); - if (!(pkey = d2i_PrivateKey_bio(bio, NULL))) { + bio = ossl_obj2bio(data); + if (!(pkey = d2i_PrivateKey_bio(bio, NULL))) { OSSL_BIO_reset(bio); - if (!NIL_P(pass)) { - passwd = StringValuePtr(pass); - } - if (!(pkey = PEM_read_bio_PrivateKey(bio, NULL, ossl_pem_passwd_cb, passwd))) { + if (!(pkey = PEM_read_bio_PrivateKey(bio, NULL, ossl_pem_passwd_cb, (void *)pass))) { OSSL_BIO_reset(bio); if (!(pkey = d2i_PUBKEY_bio(bio, NULL))) { OSSL_BIO_reset(bio); - if (!NIL_P(pass)) { - passwd = StringValuePtr(pass); - } - pkey = PEM_read_bio_PUBKEY(bio, NULL, ossl_pem_passwd_cb, passwd); + pkey = PEM_read_bio_PUBKEY(bio, NULL, ossl_pem_passwd_cb, (void *)pass); } } } diff --git a/ext/openssl/ossl_pkey_dsa.c b/ext/openssl/ossl_pkey_dsa.c index 4c0c3f1b..281d3a00 100644 --- a/ext/openssl/ossl_pkey_dsa.c +++ b/ext/openssl/ossl_pkey_dsa.c @@ -216,7 +216,6 @@ ossl_dsa_initialize(int argc, VALUE *argv, VALUE self) EVP_PKEY *pkey; DSA *dsa; BIO *in; - char *passwd = NULL; VALUE arg, pass; GetPKey(self, pkey); @@ -229,10 +228,10 @@ ossl_dsa_initialize(int argc, VALUE *argv, VALUE self) } } else { - if (!NIL_P(pass)) passwd = StringValuePtr(pass); + pass = ossl_pem_passwd_value(pass); arg = ossl_to_der_if_possible(arg); in = ossl_obj2bio(arg); - dsa = PEM_read_bio_DSAPrivateKey(in, NULL, ossl_pem_passwd_cb, passwd); + dsa = PEM_read_bio_DSAPrivateKey(in, NULL, ossl_pem_passwd_cb, (void *)pass); if (!dsa) { OSSL_BIO_reset(in); dsa = PEM_read_bio_DSA_PUBKEY(in, NULL, NULL, NULL); @@ -320,26 +319,20 @@ ossl_dsa_export(int argc, VALUE *argv, VALUE self) EVP_PKEY *pkey; BIO *out; const EVP_CIPHER *ciph = NULL; - char *passwd = NULL; VALUE cipher, pass, str; GetPKeyDSA(self, pkey); rb_scan_args(argc, argv, "02", &cipher, &pass); if (!NIL_P(cipher)) { ciph = GetCipherPtr(cipher); - if (!NIL_P(pass)) { - StringValue(pass); - if (RSTRING_LENINT(pass) < OSSL_MIN_PWD_LEN) - ossl_raise(eOSSLError, "OpenSSL requires passwords to be at least four characters long"); - passwd = RSTRING_PTR(pass); - } + pass = ossl_pem_passwd_value(pass); } if (!(out = BIO_new(BIO_s_mem()))) { ossl_raise(eDSAError, NULL); } if (DSA_HAS_PRIVATE(pkey->pkey.dsa)) { if (!PEM_write_bio_DSAPrivateKey(out, pkey->pkey.dsa, ciph, - NULL, 0, ossl_pem_passwd_cb, passwd)){ + NULL, 0, ossl_pem_passwd_cb, (void *)pass)){ BIO_free(out); ossl_raise(eDSAError, NULL); } diff --git a/ext/openssl/ossl_pkey_ec.c b/ext/openssl/ossl_pkey_ec.c index 26eb5e8a..d4153db6 100644 --- a/ext/openssl/ossl_pkey_ec.c +++ b/ext/openssl/ossl_pkey_ec.c @@ -168,7 +168,6 @@ static VALUE ossl_ec_key_initialize(int argc, VALUE *argv, VALUE self) EC_KEY *ec = NULL; VALUE arg, pass; VALUE group = Qnil; - char *passwd = NULL; GetPKey(self, pkey); if (pkey->pkey.ec) @@ -188,15 +187,15 @@ static VALUE ossl_ec_key_initialize(int argc, VALUE *argv, VALUE self) ec = EC_KEY_new(); group = arg; } else { - BIO *in = ossl_obj2bio(arg); + BIO *in; - if (!NIL_P(pass)) { - passwd = StringValuePtr(pass); - } - ec = PEM_read_bio_ECPrivateKey(in, NULL, ossl_pem_passwd_cb, passwd); + pass = ossl_pem_passwd_value(pass); + in = ossl_obj2bio(arg); + + ec = PEM_read_bio_ECPrivateKey(in, NULL, ossl_pem_passwd_cb, (void *)pass); if (!ec) { OSSL_BIO_reset(in); - ec = PEM_read_bio_EC_PUBKEY(in, NULL, ossl_pem_passwd_cb, passwd); + ec = PEM_read_bio_EC_PUBKEY(in, NULL, ossl_pem_passwd_cb, (void *)pass); } if (!ec) { OSSL_BIO_reset(in); @@ -473,7 +472,6 @@ static VALUE ossl_ec_key_to_string(VALUE self, VALUE ciph, VALUE pass, int forma BIO *out; int i = -1; int private = 0; - char *password = NULL; VALUE str; Require_EC_KEY(self, ec); @@ -493,20 +491,12 @@ static VALUE ossl_ec_key_to_string(VALUE self, VALUE ciph, VALUE pass, int forma switch(format) { case EXPORT_PEM: if (private) { - const EVP_CIPHER *cipher; + const EVP_CIPHER *cipher = NULL; if (!NIL_P(ciph)) { cipher = GetCipherPtr(ciph); - if (!NIL_P(pass)) { - StringValue(pass); - if (RSTRING_LENINT(pass) < OSSL_MIN_PWD_LEN) - ossl_raise(eOSSLError, "OpenSSL requires passwords to be at least four characters long"); - password = RSTRING_PTR(pass); - } - } - else { - cipher = NULL; + pass = ossl_pem_passwd_value(pass); } - i = PEM_write_bio_ECPrivateKey(out, ec, cipher, NULL, 0, NULL, password); + i = PEM_write_bio_ECPrivateKey(out, ec, cipher, NULL, 0, ossl_pem_passwd_cb, (void *)pass); } else { i = PEM_write_bio_EC_PUBKEY(out, ec); } diff --git a/ext/openssl/ossl_pkey_rsa.c b/ext/openssl/ossl_pkey_rsa.c index 6ad9f3ed..5219dbed 100644 --- a/ext/openssl/ossl_pkey_rsa.c +++ b/ext/openssl/ossl_pkey_rsa.c @@ -210,7 +210,6 @@ ossl_rsa_initialize(int argc, VALUE *argv, VALUE self) EVP_PKEY *pkey; RSA *rsa; BIO *in; - char *passwd = NULL; VALUE arg, pass; GetPKey(self, pkey); @@ -222,10 +221,10 @@ ossl_rsa_initialize(int argc, VALUE *argv, VALUE self) if (!rsa) ossl_raise(eRSAError, NULL); } else { - if (!NIL_P(pass)) passwd = StringValuePtr(pass); + pass = ossl_pem_passwd_value(pass); arg = ossl_to_der_if_possible(arg); in = ossl_obj2bio(arg); - rsa = PEM_read_bio_RSAPrivateKey(in, NULL, ossl_pem_passwd_cb, passwd); + rsa = PEM_read_bio_RSAPrivateKey(in, NULL, ossl_pem_passwd_cb, (void *)pass); if (!rsa) { OSSL_BIO_reset(in); rsa = PEM_read_bio_RSA_PUBKEY(in, NULL, NULL, NULL); @@ -310,7 +309,6 @@ ossl_rsa_export(int argc, VALUE *argv, VALUE self) EVP_PKEY *pkey; BIO *out; const EVP_CIPHER *ciph = NULL; - char *passwd = NULL; VALUE cipher, pass, str; GetPKeyRSA(self, pkey); @@ -319,19 +317,14 @@ ossl_rsa_export(int argc, VALUE *argv, VALUE self) if (!NIL_P(cipher)) { ciph = GetCipherPtr(cipher); - if (!NIL_P(pass)) { - StringValue(pass); - if (RSTRING_LENINT(pass) < OSSL_MIN_PWD_LEN) - ossl_raise(eOSSLError, "OpenSSL requires passwords to be at least four characters long"); - passwd = RSTRING_PTR(pass); - } + pass = ossl_pem_passwd_value(pass); } if (!(out = BIO_new(BIO_s_mem()))) { ossl_raise(eRSAError, NULL); } if (RSA_HAS_PRIVATE(pkey->pkey.rsa)) { if (!PEM_write_bio_RSAPrivateKey(out, pkey->pkey.rsa, ciph, - NULL, 0, ossl_pem_passwd_cb, passwd)) { + NULL, 0, ossl_pem_passwd_cb, (void *)pass)) { BIO_free(out); ossl_raise(eRSAError, NULL); } diff --git a/test/test_pkey_dsa.rb b/test/test_pkey_dsa.rb index 2c0e1fc2..680a1239 100644 --- a/test/test_pkey_dsa.rb +++ b/test/test_pkey_dsa.rb @@ -218,6 +218,18 @@ YNMbNw== assert(pem) end + def test_export_password_funny + key = OpenSSL::TestUtils::TEST_KEY_DSA256 + 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::DSA.new(pem, "pass\0wd") + assert(key3.private?) + end + private def check_sign_verify(digest) diff --git a/test/test_pkey_ec.rb b/test/test_pkey_ec.rb index 673b0d6f..23afed67 100644 --- a/test/test_pkey_ec.rb +++ b/test/test_pkey_ec.rb @@ -184,6 +184,18 @@ class OpenSSL::TestEC < OpenSSL::TestCase assert(pem) end + def test_export_password_funny + key = OpenSSL::TestUtils::TEST_KEY_EC_P256V1 + 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_key?) + key3 = OpenSSL::PKey::EC.new(pem, "pass\0wd") + assert(key3.private_key?) + end + def test_ec_point_mul begin # y^2 = x^3 + 2x + 2 over F_17 diff --git a/test/test_pkey_rsa.rb b/test/test_pkey_rsa.rb index 54fce2f5..c3532f63 100644 --- a/test/test_pkey_rsa.rb +++ b/test/test_pkey_rsa.rb @@ -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) -- cgit v1.2.3 From 103f911e59d6ceb25a604228dc60376638e61db8 Mon Sep 17 00:00:00 2001 From: nobu Date: Fri, 20 May 2016 15:29:41 +0000 Subject: ossl.c: suppress warnings * ext/openssl/ossl.c (ossl_pem_passwd_cb): check integer precision. git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@55089 b2dd03c8-39d4-4d8f-98ff-823fe69b080e --- ext/openssl/ossl.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ext/openssl/ossl.c b/ext/openssl/ossl.c index a0a7574c..b1a664ab 100644 --- a/ext/openssl/ossl.c +++ b/ext/openssl/ossl.c @@ -194,7 +194,7 @@ ossl_pem_passwd_cb(char *buf, int max_len, int flag, void *pwd_) * work because it does not allow NUL characters and truncates to 1024 * bytes silently if the input is over 1024 bytes */ if (RB_TYPE_P(pass, T_STRING)) { - len = RSTRING_LEN(pass); + len = RSTRING_LENINT(pass); if (len >= OSSL_MIN_PWD_LEN && len <= max_len) { memcpy(buf, RSTRING_PTR(pass), len); return len; -- cgit v1.2.3 From 146c2d3b94c1dd2f9d185a01728fabefcbce219c Mon Sep 17 00:00:00 2001 From: rhe Date: Sat, 21 May 2016 03:44:10 +0000 Subject: openssl: remove impossible EOFError raise in OpenSSL::Buffering * ext/openssl/lib/openssl/buffering.rb (read_nonblock, readpartial): Remove impossible EOFError raise. Patch by Zach Anker . [GH ruby/openssl#23] git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@55097 b2dd03c8-39d4-4d8f-98ff-823fe69b080e --- lib/openssl/buffering.rb | 2 -- 1 file changed, 2 deletions(-) diff --git a/lib/openssl/buffering.rb b/lib/openssl/buffering.rb index d0821990..61e1f43e 100644 --- a/lib/openssl/buffering.rb +++ b/lib/openssl/buffering.rb @@ -132,7 +132,6 @@ module OpenSSL::Buffering buf.replace(ret) ret = buf end - raise EOFError if ret.empty? ret end @@ -182,7 +181,6 @@ module OpenSSL::Buffering buf.replace(ret) ret = buf end - raise EOFError if ret.empty? ret end -- cgit v1.2.3 From 55888652e2972384588d349f49f133bb9ac4368b Mon Sep 17 00:00:00 2001 From: rhe Date: Sat, 21 May 2016 05:30:48 +0000 Subject: openssl: add OpenSSL::PKey::EC#private? and #public? * ext/openssl/ossl_pkey_ec.c: rename PKey::EC#private_key? and #public_key? to #private? and #public? for consistency with other PKey types. Old names remain as alias. [ruby-core:45541] [Bug #6567] * test/openssl/test_pkey_ec.rb (test_check_key): check private? and public? works correctly. git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@55098 b2dd03c8-39d4-4d8f-98ff-823fe69b080e --- ext/openssl/ossl_pkey_ec.c | 24 ++++++++++++++---------- test/test_pkey_ec.rb | 18 +++++++++++++++--- 2 files changed, 29 insertions(+), 13 deletions(-) diff --git a/ext/openssl/ossl_pkey_ec.c b/ext/openssl/ossl_pkey_ec.c index d4153db6..ef023b13 100644 --- a/ext/openssl/ossl_pkey_ec.c +++ b/ext/openssl/ossl_pkey_ec.c @@ -438,32 +438,34 @@ static VALUE ossl_ec_key_set_public_key(VALUE self, VALUE public_key) /* * call-seq: - * key.public_key? => true or false + * key.public? => true or false * - * Both public_key? and private_key? may return false at the same time unlike other PKey classes. + * Returns whether this EC instance has a public key. The public key + * (EC::Point) can be retrieved with EC#public_key. */ -static VALUE ossl_ec_key_is_public_key(VALUE self) +static VALUE ossl_ec_key_is_public(VALUE self) { EC_KEY *ec; Require_EC_KEY(self, ec); - return (EC_KEY_get0_public_key(ec) ? Qtrue : Qfalse); + return EC_KEY_get0_public_key(ec) ? Qtrue : Qfalse; } /* * call-seq: - * key.private_key? => true or false + * key.private? => true or false * - * Both public_key? and private_key? may return false at the same time unlike other PKey classes. + * Returns whether this EC instance has a private key. The private key (BN) can + * be retrieved with EC#private_key. */ -static VALUE ossl_ec_key_is_private_key(VALUE self) +static VALUE ossl_ec_key_is_private(VALUE self) { EC_KEY *ec; Require_EC_KEY(self, ec); - return (EC_KEY_get0_private_key(ec) ? Qtrue : Qfalse); + return EC_KEY_get0_private_key(ec) ? Qtrue : Qfalse; } static VALUE ossl_ec_key_to_string(VALUE self, VALUE ciph, VALUE pass, int format) @@ -1619,8 +1621,10 @@ void Init_ossl_ec(void) rb_define_method(cEC, "private_key=", ossl_ec_key_set_private_key, 1); rb_define_method(cEC, "public_key", ossl_ec_key_get_public_key, 0); rb_define_method(cEC, "public_key=", ossl_ec_key_set_public_key, 1); - rb_define_method(cEC, "private_key?", ossl_ec_key_is_private_key, 0); - rb_define_method(cEC, "public_key?", ossl_ec_key_is_public_key, 0); + rb_define_method(cEC, "private?", ossl_ec_key_is_private, 0); + rb_define_method(cEC, "public?", ossl_ec_key_is_public, 0); + rb_define_alias(cEC, "private_key?", "private?"); + rb_define_alias(cEC, "public_key?", "public?"); /* rb_define_method(cEC, "", ossl_ec_key_get_, 0); rb_define_method(cEC, "=", ossl_ec_key_set_ 1); set/get enc_flags diff --git a/test/test_pkey_ec.rb b/test/test_pkey_ec.rb index 23afed67..302259b2 100644 --- a/test/test_pkey_ec.rb +++ b/test/test_pkey_ec.rb @@ -40,9 +40,21 @@ class OpenSSL::TestEC < OpenSSL::TestCase def test_check_key for key in @keys - assert_equal(key.check_key, true) - assert_equal(key.private_key?, true) - assert_equal(key.public_key?, true) + assert_equal(true, key.check_key) + assert_equal(true, key.private?) + assert_equal(true, key.public?) + key2 = OpenSSL::PKey::EC.new(key.group) + assert_equal(false, key2.private?) + assert_equal(false, key2.public?) + key2.public_key = key.public_key + assert_equal(false, key2.private?) + assert_equal(true, key2.public?) + key2.private_key = key.private_key + assert_equal(true, key2.private?) + assert_equal(true, key2.public?) + assert_equal(true, key2.check_key) + key2.private_key += 1 + assert_raise(OpenSSL::PKey::ECError) { key2.check_key } end end -- cgit v1.2.3 From fbb063354800b4b561a6b64fccddfcaf8a5011f4 Mon Sep 17 00:00:00 2001 From: rhe Date: Sat, 21 May 2016 05:45:41 +0000 Subject: openssl: fix SSL client example in documentation [ci skip] * ext/openssl/ossl.c: [DOC] Fix SSL client example. The variable name was wrong. Patch by Andreas Tiefenthaler (@pxlpnk). [GH ruby/openssl#32] git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@55099 b2dd03c8-39d4-4d8f-98ff-823fe69b080e --- ext/openssl/ossl.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/ext/openssl/ossl.c b/ext/openssl/ossl.c index b1a664ab..1f62c57a 100644 --- a/ext/openssl/ossl.c +++ b/ext/openssl/ossl.c @@ -1067,8 +1067,8 @@ static void Init_ossl_locks(void) * * require 'socket' * - * tcp_client = TCPSocket.new 'localhost', 5000 - * ssl_client = OpenSSL::SSL::SSLSocket.new client_socket, context + * tcp_socket = TCPSocket.new 'localhost', 5000 + * ssl_client = OpenSSL::SSL::SSLSocket.new tcp_socket, context * ssl_client.connect * * ssl_client.puts "hello server!" @@ -1087,8 +1087,8 @@ static void Init_ossl_locks(void) * * require 'socket' * - * tcp_client = TCPSocket.new 'localhost', 5000 - * ssl_client = OpenSSL::SSL::SSLSocket.new client_socket, context + * tcp_socket = TCPSocket.new 'localhost', 5000 + * ssl_client = OpenSSL::SSL::SSLSocket.new tcp_socket, context * ssl_client.connect * * ssl_client.puts "hello server!" -- cgit v1.2.3 From 63f74fb70f8059e08a69dfe0aa8216ef2d9dd0d3 Mon Sep 17 00:00:00 2001 From: rhe Date: Sat, 21 May 2016 07:25:00 +0000 Subject: openssl: fix possible SEGV on race between SSLSocket#stop and #connect * ext/openssl/ossl_ssl.c (ossl_ssl_stop): Don't free the SSL struct here. Since some methods such as SSLSocket#connect releases GVL, there is a chance of use after free if we free the SSL from another thread. SSLSocket#stop was documented as "prepares it for another connection" so this is a slightly incompatible change. However when this sentence was added (r30090, Add toplevel documentation for OpenSSL, 2010-12-06), it didn't actually. The current behavior is from r40304 (Correct shutdown behavior w.r.t GC., 2013-04-15). [ruby-core:74978] [Bug #12292] * ext/openssl/lib/openssl/ssl.rb (sysclose): Update doc. * test/openssl/test_ssl.rb: Test this. git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@55100 b2dd03c8-39d4-4d8f-98ff-823fe69b080e --- ext/openssl/ossl_ssl.c | 14 ++++---------- lib/openssl/ssl.rb | 5 ++++- test/test_ssl.rb | 22 ++++++++++++++++++++++ 3 files changed, 30 insertions(+), 11 deletions(-) diff --git a/ext/openssl/ossl_ssl.c b/ext/openssl/ossl_ssl.c index 87df7f9f..d5ea1304 100644 --- a/ext/openssl/ossl_ssl.c +++ b/ext/openssl/ossl_ssl.c @@ -1601,23 +1601,17 @@ ossl_ssl_write_nonblock(int argc, VALUE *argv, VALUE self) * call-seq: * ssl.stop => nil * - * Stops the SSL connection and prepares it for another connection. + * Sends "close notify" to the peer and tries to shut down the SSL connection + * gracefully. */ static VALUE ossl_ssl_stop(VALUE self) { SSL *ssl; - /* ossl_ssl_data_get_struct() is not usable here because it may return - * from this function; */ - - GetSSL(self, ssl); + ossl_ssl_data_get_struct(self, ssl); - if (ssl) { - ossl_ssl_shutdown(ssl); - SSL_free(ssl); - } - DATA_PTR(self) = NULL; + ossl_ssl_shutdown(ssl); return Qnil; } diff --git a/lib/openssl/ssl.rb b/lib/openssl/ssl.rb index 57519f2c..98937570 100644 --- a/lib/openssl/ssl.rb +++ b/lib/openssl/ssl.rb @@ -290,7 +290,10 @@ module OpenSSL # call-seq: # ssl.sysclose => nil # - # Shuts down the SSL connection and prepares it for another connection. + # Sends "close notify" to the peer and tries to shut down the SSL + # connection gracefully. + # + # If sync_close is set to +true+, the underlying IO is also closed. def sysclose return if closed? stop diff --git a/test/test_ssl.rb b/test/test_ssl.rb index 32f7cfde..cb119dcd 100644 --- a/test/test_ssl.rb +++ b/test/test_ssl.rb @@ -1169,6 +1169,28 @@ end } end + def test_close_and_socket_close_while_connecting + # test it doesn't cause a segmentation fault + ctx = OpenSSL::SSL::SSLContext.new + ctx.ciphers = "aNULL" + + sock1, sock2 = socketpair + ssl1 = OpenSSL::SSL::SSLSocket.new(sock1, ctx) + ssl2 = OpenSSL::SSL::SSLSocket.new(sock2, ctx) + + t = Thread.new { ssl1.connect } + ssl2.accept + + ssl1.close + sock1.close + t.value rescue nil + ensure + ssl1.close if ssl1 + ssl2.close if ssl2 + sock1.close if sock1 + sock2.close if sock2 + end + def test_get_ephemeral_key return unless OpenSSL::SSL::SSLSocket.method_defined?(:tmp_key) pkey = OpenSSL::PKey -- cgit v1.2.3 From d955905ba85a4a6ff72ee8125a81c1ee66798d08 Mon Sep 17 00:00:00 2001 From: rhe Date: Mon, 23 May 2016 10:47:37 +0000 Subject: openssl: fix incorrect return value check of RAND_* functions * ext/openssl/ossl_rand.c (ossl_rand_egd, ossl_rand_egd_bytes): RAND_egd{_bytes,}() return -1 on failure, not 0. Patch by cremno phobia [ruby-core:63795] [Bug #10053] (ossl_pseudo_bytes): Similar, RAND_pseudo_bytes() may return 0 or -1 on failure. git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@55132 b2dd03c8-39d4-4d8f-98ff-823fe69b080e --- ext/openssl/ossl_rand.c | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/ext/openssl/ossl_rand.c b/ext/openssl/ossl_rand.c index daf866d7..7a01278a 100644 --- a/ext/openssl/ossl_rand.c +++ b/ext/openssl/ossl_rand.c @@ -114,10 +114,8 @@ ossl_rand_bytes(VALUE self, VALUE len) str = rb_str_new(0, n); ret = RAND_bytes((unsigned char *)RSTRING_PTR(str), n); - if (ret == 0){ - char buf[256]; - ERR_error_string_n(ERR_get_error(), buf, 256); - ossl_raise(eRandomError, "RAND_bytes error: %s", buf); + if (ret == 0) { + ossl_raise(eRandomError, "RAND_bytes"); } else if (ret == -1) { ossl_raise(eRandomError, "RAND_bytes is not supported"); } @@ -146,7 +144,7 @@ ossl_rand_pseudo_bytes(VALUE self, VALUE len) int n = NUM2INT(len); str = rb_str_new(0, n); - if (!RAND_pseudo_bytes((unsigned char *)RSTRING_PTR(str), n)) { + if (RAND_pseudo_bytes((unsigned char *)RSTRING_PTR(str), n) < 1) { ossl_raise(eRandomError, NULL); } @@ -165,7 +163,7 @@ ossl_rand_egd(VALUE self, VALUE filename) { SafeStringValue(filename); - if(!RAND_egd(RSTRING_PTR(filename))) { + if (RAND_egd(RSTRING_PTR(filename)) == -1) { ossl_raise(eRandomError, NULL); } return Qtrue; @@ -187,7 +185,7 @@ ossl_rand_egd_bytes(VALUE self, VALUE filename, VALUE len) SafeStringValue(filename); - if (!RAND_egd_bytes(RSTRING_PTR(filename), n)) { + if (RAND_egd_bytes(RSTRING_PTR(filename), n) == -1) { ossl_raise(eRandomError, NULL); } return Qtrue; -- cgit v1.2.3 From 63ac82669cea4603c414ca9c905cceee3d35bffb Mon Sep 17 00:00:00 2001 From: rhe Date: Mon, 23 May 2016 11:40:07 +0000 Subject: openssl: use StringValueCStr() where NUL-terminated string is expected * ext/openssl/ossl_asn1.c, ext/openssl/ossl_bn.c, ext/openssl/ossl_cipher.c, ext/openssl/ossl_digest.c ext/openssl/ossl_engine.c, ext/openssl/ossl_ns_spki.c ext/openssl/ossl_pkcs12.c, ext/openssl/ossl_pkcs7.c ext/openssl/ossl_pkey.c, ext/openssl/ossl_pkey_ec.c ext/openssl/ossl_rand.c, ext/openssl/ossl_ssl.c ext/openssl/ossl_x509attr.c, ext/openssl/ossl_x509cert.c ext/openssl/ossl_x509ext.c, ext/openssl/ossl_x509store.c: Use StringValueCStr() where NUL-terminated string is expected. git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@55134 b2dd03c8-39d4-4d8f-98ff-823fe69b080e --- ext/openssl/ossl_asn1.c | 16 ++++++++-------- ext/openssl/ossl_bn.c | 11 +++++------ ext/openssl/ossl_cipher.c | 4 ++-- ext/openssl/ossl_digest.c | 2 +- ext/openssl/ossl_engine.c | 32 +++++++++++++------------------- ext/openssl/ossl_ns_spki.c | 6 +++--- ext/openssl/ossl_pkcs12.c | 14 +++++++------- ext/openssl/ossl_pkcs7.c | 5 +++-- ext/openssl/ossl_pkey.c | 4 ++-- ext/openssl/ossl_pkey_ec.c | 8 ++++---- ext/openssl/ossl_rand.c | 17 +++++++++-------- ext/openssl/ossl_ssl.c | 13 ++++++------- ext/openssl/ossl_x509attr.c | 4 ++-- ext/openssl/ossl_x509cert.c | 4 ++-- ext/openssl/ossl_x509ext.c | 12 +++++++----- ext/openssl/ossl_x509store.c | 8 ++++---- 16 files changed, 78 insertions(+), 82 deletions(-) diff --git a/ext/openssl/ossl_asn1.c b/ext/openssl/ossl_asn1.c index 89da5949..cae6176c 100644 --- a/ext/openssl/ossl_asn1.c +++ b/ext/openssl/ossl_asn1.c @@ -140,7 +140,7 @@ num_to_asn1integer(VALUE obj, ASN1_INTEGER *ai) bn = GetBNPtr(obj); } else { obj = rb_String(obj); - if (!BN_dec2bn(&bn, StringValuePtr(obj))) { + if (!BN_dec2bn(&bn, StringValueCStr(obj))) { ossl_raise(eOSSLError, NULL); } } @@ -293,10 +293,10 @@ obj_to_asn1obj(VALUE obj) { ASN1_OBJECT *a1obj; - StringValue(obj); + StringValueCStr(obj); a1obj = OBJ_txt2obj(RSTRING_PTR(obj), 0); if(!a1obj) a1obj = OBJ_txt2obj(RSTRING_PTR(obj), 1); - if(!a1obj) ossl_raise(eASN1Error, "invalid OBJECT ID"); + if(!a1obj) ossl_raise(eASN1Error, "invalid OBJECT ID %"PRIsVALUE, obj); return a1obj; } @@ -1374,9 +1374,9 @@ ossl_asn1cons_each(VALUE self) static VALUE ossl_asn1obj_s_register(VALUE self, VALUE oid, VALUE sn, VALUE ln) { - StringValue(oid); - StringValue(sn); - StringValue(ln); + StringValueCStr(oid); + StringValueCStr(sn); + StringValueCStr(ln); if(!OBJ_create(RSTRING_PTR(oid), RSTRING_PTR(sn), RSTRING_PTR(ln))) ossl_raise(eASN1Error, NULL); @@ -1399,7 +1399,7 @@ ossl_asn1obj_get_sn(VALUE self) int nid; val = ossl_asn1_get_value(self); - if ((nid = OBJ_txt2nid(StringValuePtr(val))) != NID_undef) + if ((nid = OBJ_txt2nid(StringValueCStr(val))) != NID_undef) ret = rb_str_new2(OBJ_nid2sn(nid)); return ret; @@ -1420,7 +1420,7 @@ ossl_asn1obj_get_ln(VALUE self) int nid; val = ossl_asn1_get_value(self); - if ((nid = OBJ_txt2nid(StringValuePtr(val))) != NID_undef) + if ((nid = OBJ_txt2nid(StringValueCStr(val))) != NID_undef) ret = rb_str_new2(OBJ_nid2ln(nid)); return ret; diff --git a/ext/openssl/ossl_bn.c b/ext/openssl/ossl_bn.c index 0af6c684..5b4207ba 100644 --- a/ext/openssl/ossl_bn.c +++ b/ext/openssl/ossl_bn.c @@ -95,7 +95,7 @@ try_convert_to_bnptr(VALUE obj) case T_BIGNUM: obj = rb_String(obj); newobj = NewBN(cBN); /* GC bug */ - if (!BN_dec2bn(&bn, StringValuePtr(obj))) { + if (!BN_dec2bn(&bn, StringValueCStr(obj))) { ossl_raise(eBNError, NULL); } SetBN(newobj, bn); /* Handle potencial mem leaks */ @@ -209,26 +209,25 @@ ossl_bn_initialize(int argc, VALUE *argv, VALUE self) return self; } - StringValue(str); GetBN(self, bn); switch (base) { case 0: - if (!BN_mpi2bn((unsigned char *)RSTRING_PTR(str), RSTRING_LENINT(str), bn)) { + if (!BN_mpi2bn((unsigned char *)StringValuePtr(str), RSTRING_LENINT(str), bn)) { ossl_raise(eBNError, NULL); } break; case 2: - if (!BN_bin2bn((unsigned char *)RSTRING_PTR(str), RSTRING_LENINT(str), bn)) { + if (!BN_bin2bn((unsigned char *)StringValuePtr(str), RSTRING_LENINT(str), bn)) { ossl_raise(eBNError, NULL); } break; case 10: - if (!BN_dec2bn(&bn, RSTRING_PTR(str))) { + if (!BN_dec2bn(&bn, StringValueCStr(str))) { ossl_raise(eBNError, NULL); } break; case 16: - if (!BN_hex2bn(&bn, RSTRING_PTR(str))) { + if (!BN_hex2bn(&bn, StringValueCStr(str))) { ossl_raise(eBNError, NULL); } break; diff --git a/ext/openssl/ossl_cipher.c b/ext/openssl/ossl_cipher.c index 09b021d9..9aab8025 100644 --- a/ext/openssl/ossl_cipher.c +++ b/ext/openssl/ossl_cipher.c @@ -116,7 +116,7 @@ ossl_cipher_initialize(VALUE self, VALUE str) char *name; unsigned char key[EVP_MAX_KEY_LENGTH]; - name = StringValuePtr(str); + name = StringValueCStr(str); GetCipherInit(self, ctx); if (ctx) { ossl_raise(rb_eRuntimeError, "Cipher already inititalized!"); @@ -124,7 +124,7 @@ ossl_cipher_initialize(VALUE self, VALUE str) AllocCipher(self, ctx); EVP_CIPHER_CTX_init(ctx); if (!(cipher = EVP_get_cipherbyname(name))) { - ossl_raise(rb_eRuntimeError, "unsupported cipher algorithm (%s)", name); + ossl_raise(rb_eRuntimeError, "unsupported cipher algorithm (%"PRIsVALUE")", str); } /* * The EVP which has EVP_CIPH_RAND_KEY flag (such as DES3) allows diff --git a/ext/openssl/ossl_digest.c b/ext/openssl/ossl_digest.c index 44968dd9..d137dc57 100644 --- a/ext/openssl/ossl_digest.c +++ b/ext/openssl/ossl_digest.c @@ -61,7 +61,7 @@ GetDigestPtr(VALUE obj) ASN1_OBJECT_free(oid); } if(!md) - ossl_raise(rb_eRuntimeError, "Unsupported digest algorithm (%s).", name); + ossl_raise(rb_eRuntimeError, "Unsupported digest algorithm (%"PRIsVALUE").", obj); } else { EVP_MD_CTX *ctx; diff --git a/ext/openssl/ossl_engine.c b/ext/openssl/ossl_engine.c index 06ca0754..48847e67 100644 --- a/ext/openssl/ossl_engine.c +++ b/ext/openssl/ossl_engine.c @@ -96,7 +96,7 @@ ossl_engine_s_load(int argc, VALUE *argv, VALUE klass) ENGINE_load_builtin_engines(); return Qtrue; } - StringValue(name); + StringValueCStr(name); #ifndef OPENSSL_NO_STATIC_ENGINE #if HAVE_ENGINE_LOAD_DYNAMIC OSSL_ENGINE_LOAD_IF_MATCH(dynamic); @@ -148,7 +148,7 @@ ossl_engine_s_load(int argc, VALUE *argv, VALUE klass) OSSL_ENGINE_LOAD_IF_MATCH(openbsd_dev_crypto); #endif OSSL_ENGINE_LOAD_IF_MATCH(openssl); - rb_warning("no such builtin loader for `%s'", RSTRING_PTR(name)); + rb_warning("no such builtin loader for `%"PRIsVALUE"'", name); return Qnil; #endif /* HAVE_ENGINE_LOAD_BUILTIN_ENGINES */ } @@ -213,7 +213,7 @@ ossl_engine_s_by_id(VALUE klass, VALUE id) ENGINE *e; VALUE obj; - StringValue(id); + StringValueCStr(id); ossl_engine_s_load(1, &id, klass); obj = NewEngine(klass); if(!(e = ENGINE_by_id(RSTRING_PTR(id)))) @@ -318,12 +318,10 @@ ossl_engine_get_cipher(VALUE self, VALUE name) { ENGINE *e; const EVP_CIPHER *ciph, *tmp; - char *s; int nid; - s = StringValuePtr(name); - tmp = EVP_get_cipherbyname(s); - if(!tmp) ossl_raise(eEngineError, "no such cipher `%s'", s); + tmp = EVP_get_cipherbyname(StringValueCStr(name)); + if(!tmp) ossl_raise(eEngineError, "no such cipher `%"PRIsVALUE"'", name); nid = EVP_CIPHER_nid(tmp); GetEngine(self, e); ciph = ENGINE_get_cipher(e, nid); @@ -357,12 +355,10 @@ ossl_engine_get_digest(VALUE self, VALUE name) { ENGINE *e; const EVP_MD *md, *tmp; - char *s; int nid; - s = StringValuePtr(name); - tmp = EVP_get_digestbyname(s); - if(!tmp) ossl_raise(eEngineError, "no such digest `%s'", s); + tmp = EVP_get_digestbyname(StringValueCStr(name)); + if(!tmp) ossl_raise(eEngineError, "no such digest `%"PRIsVALUE"'", name); nid = EVP_MD_nid(tmp); GetEngine(self, e); md = ENGINE_get_digest(e, nid); @@ -393,8 +389,8 @@ ossl_engine_load_privkey(int argc, VALUE *argv, VALUE self) char *sid, *sdata; rb_scan_args(argc, argv, "02", &id, &data); - sid = NIL_P(id) ? NULL : StringValuePtr(id); - sdata = NIL_P(data) ? NULL : StringValuePtr(data); + sid = NIL_P(id) ? NULL : StringValueCStr(id); + sdata = NIL_P(data) ? NULL : StringValueCStr(data); GetEngine(self, e); #if OPENSSL_VERSION_NUMBER < 0x00907000L pkey = ENGINE_load_private_key(e, sid, sdata); @@ -427,8 +423,8 @@ ossl_engine_load_pubkey(int argc, VALUE *argv, VALUE self) char *sid, *sdata; rb_scan_args(argc, argv, "02", &id, &data); - sid = NIL_P(id) ? NULL : StringValuePtr(id); - sdata = NIL_P(data) ? NULL : StringValuePtr(data); + sid = NIL_P(id) ? NULL : StringValueCStr(id); + sdata = NIL_P(data) ? NULL : StringValueCStr(data); GetEngine(self, e); #if OPENSSL_VERSION_NUMBER < 0x00907000L pkey = ENGINE_load_public_key(e, sid, sdata); @@ -487,10 +483,8 @@ ossl_engine_ctrl_cmd(int argc, VALUE *argv, VALUE self) GetEngine(self, e); rb_scan_args(argc, argv, "11", &cmd, &val); - StringValue(cmd); - if (!NIL_P(val)) StringValue(val); - ret = ENGINE_ctrl_cmd_string(e, RSTRING_PTR(cmd), - NIL_P(val) ? NULL : RSTRING_PTR(val), 0); + ret = ENGINE_ctrl_cmd_string(e, StringValueCStr(cmd), + NIL_P(val) ? NULL : StringValueCStr(val), 0); if (!ret) ossl_raise(eEngineError, NULL); return self; diff --git a/ext/openssl/ossl_ns_spki.c b/ext/openssl/ossl_ns_spki.c index c6d2483b..e93b1b0a 100644 --- a/ext/openssl/ossl_ns_spki.c +++ b/ext/openssl/ossl_ns_spki.c @@ -86,15 +86,15 @@ ossl_spki_initialize(int argc, VALUE *argv, VALUE self) return self; } StringValue(buffer); - if (!(spki = NETSCAPE_SPKI_b64_decode(RSTRING_PTR(buffer), -1))) { + if (!(spki = NETSCAPE_SPKI_b64_decode(RSTRING_PTR(buffer), RSTRING_LENINT(buffer)))) { + ossl_clear_error(); p = (unsigned char *)RSTRING_PTR(buffer); if (!(spki = d2i_NETSCAPE_SPKI(NULL, &p, RSTRING_LEN(buffer)))) { ossl_raise(eSPKIError, NULL); } } NETSCAPE_SPKI_free(DATA_PTR(self)); - DATA_PTR(self) = spki; - ossl_clear_error(); + SetSPKI(self, spki); return self; } diff --git a/ext/openssl/ossl_pkcs12.c b/ext/openssl/ossl_pkcs12.c index fe4dadc1..5f849723 100644 --- a/ext/openssl/ossl_pkcs12.c +++ b/ext/openssl/ossl_pkcs12.c @@ -100,19 +100,19 @@ ossl_pkcs12_s_create(int argc, VALUE *argv, VALUE self) PKCS12 *p12; rb_scan_args(argc, argv, "46", &pass, &name, &pkey, &cert, &ca, &key_nid, &cert_nid, &key_iter, &mac_iter, &keytype); - passphrase = NIL_P(pass) ? NULL : StringValuePtr(pass); - friendlyname = NIL_P(name) ? NULL : StringValuePtr(name); + passphrase = NIL_P(pass) ? NULL : StringValueCStr(pass); + friendlyname = NIL_P(name) ? NULL : StringValueCStr(name); key = GetPKeyPtr(pkey); x509 = GetX509CertPtr(cert); x509s = NIL_P(ca) ? NULL : ossl_x509_ary2sk(ca); /* TODO: make a VALUE to nid function */ if (!NIL_P(key_nid)) { - if ((nkey = OBJ_txt2nid(StringValuePtr(key_nid))) == NID_undef) - ossl_raise(rb_eArgError, "Unknown PBE algorithm %s", StringValuePtr(key_nid)); + if ((nkey = OBJ_txt2nid(StringValueCStr(key_nid))) == NID_undef) + ossl_raise(rb_eArgError, "Unknown PBE algorithm %"PRIsVALUE, key_nid); } if (!NIL_P(cert_nid)) { - if ((ncert = OBJ_txt2nid(StringValuePtr(cert_nid))) == NID_undef) - ossl_raise(rb_eArgError, "Unknown PBE algorithm %s", StringValuePtr(cert_nid)); + if ((ncert = OBJ_txt2nid(StringValueCStr(cert_nid))) == NID_undef) + ossl_raise(rb_eArgError, "Unknown PBE algorithm %"PRIsVALUE, cert_nid); } if (!NIL_P(key_iter)) kiter = NUM2INT(key_iter); @@ -158,7 +158,7 @@ ossl_pkcs12_initialize(int argc, VALUE *argv, VALUE self) PKCS12 *pkcs = DATA_PTR(self); if(rb_scan_args(argc, argv, "02", &arg, &pass) == 0) return self; - passphrase = NIL_P(pass) ? NULL : StringValuePtr(pass); + passphrase = NIL_P(pass) ? NULL : StringValueCStr(pass); in = ossl_obj2bio(arg); d2i_PKCS12_bio(in, &pkcs); DATA_PTR(self) = pkcs; diff --git a/ext/openssl/ossl_pkcs7.c b/ext/openssl/ossl_pkcs7.c index ad794e71..10332d9e 100644 --- a/ext/openssl/ossl_pkcs7.c +++ b/ext/openssl/ossl_pkcs7.c @@ -429,12 +429,13 @@ ossl_pkcs7_sym2typeid(VALUE sym) { "digest", NID_pkcs7_digest }, }; - if (RB_TYPE_P(sym, T_SYMBOL)) sym = rb_sym2str(sym); + if (SYMBOL_P(sym)) sym = rb_sym2str(sym); else StringValue(sym); RSTRING_GETMEM(sym, s, l); + for(i = 0; ; i++){ if(i == numberof(p7_type_tab)) - ossl_raise(ePKCS7Error, "unknown type \"%s\"", s); + ossl_raise(ePKCS7Error, "unknown type \"%"PRIsVALUE"\"", sym); if(strlen(p7_type_tab[i].name) != l) continue; if(strcmp(p7_type_tab[i].name, s) == 0){ ret = p7_type_tab[i].nid; diff --git a/ext/openssl/ossl_pkey.c b/ext/openssl/ossl_pkey.c index 7240de82..fea90d7a 100644 --- a/ext/openssl/ossl_pkey.c +++ b/ext/openssl/ossl_pkey.c @@ -121,8 +121,8 @@ ossl_pkey_new_from_file(VALUE filename) FILE *fp; EVP_PKEY *pkey; - SafeStringValue(filename); - if (!(fp = fopen(RSTRING_PTR(filename), "r"))) { + rb_check_safe_obj(filename); + if (!(fp = fopen(StringValueCStr(filename), "r"))) { ossl_raise(ePKeyError, "%s", strerror(errno)); } rb_fd_fix_cloexec(fileno(fp)); diff --git a/ext/openssl/ossl_pkey_ec.c b/ext/openssl/ossl_pkey_ec.c index ef023b13..ab6209c7 100644 --- a/ext/openssl/ossl_pkey_ec.c +++ b/ext/openssl/ossl_pkey_ec.c @@ -214,10 +214,10 @@ static VALUE ossl_ec_key_initialize(int argc, VALUE *argv, VALUE self) ossl_clear_error(); /* ignore errors in the previous d2i_EC_PUBKEY_bio() */ if (nid == NID_undef) - ossl_raise(eECError, "unknown curve name (%s)\n", name); + ossl_raise(eECError, "unknown curve name (%"PRIsVALUE")", arg); if ((ec = EC_KEY_new_by_curve_name(nid)) == NULL) - ossl_raise(eECError, "unable to create curve (%s)\n", name); + ossl_raise(eECError, "unable to create curve (%"PRIsVALUE")\n", arg); EC_KEY_set_asn1_flag(ec, OPENSSL_EC_NAMED_CURVE); EC_KEY_set_conv_form(ec, POINT_CONVERSION_UNCOMPRESSED); @@ -802,11 +802,11 @@ static VALUE ossl_ec_group_initialize(int argc, VALUE *argv, VALUE self) ossl_clear_error(); /* ignore errors in d2i_ECPKParameters_bio() */ if (nid == NID_undef) - ossl_raise(eEC_GROUP, "unknown curve name (%s)", name); + ossl_raise(eEC_GROUP, "unknown curve name (%"PRIsVALUE")", arg1); group = EC_GROUP_new_by_curve_name(nid); if (group == NULL) - ossl_raise(eEC_GROUP, "unable to create curve (%s)", name); + ossl_raise(eEC_GROUP, "unable to create curve (%"PRIsVALUE")", arg1); EC_GROUP_set_asn1_flag(group, OPENSSL_EC_NAMED_CURVE); EC_GROUP_set_point_conversion_form(group, POINT_CONVERSION_UNCOMPRESSED); diff --git a/ext/openssl/ossl_rand.c b/ext/openssl/ossl_rand.c index 7a01278a..3a300d5e 100644 --- a/ext/openssl/ossl_rand.c +++ b/ext/openssl/ossl_rand.c @@ -67,9 +67,9 @@ ossl_rand_add(VALUE self, VALUE str, VALUE entropy) static VALUE ossl_rand_load_file(VALUE self, VALUE filename) { - SafeStringValue(filename); + rb_check_safe_obj(filename); - if(!RAND_load_file(RSTRING_PTR(filename), -1)) { + if(!RAND_load_file(StringValueCStr(filename), -1)) { ossl_raise(eRandomError, NULL); } return Qtrue; @@ -86,8 +86,9 @@ ossl_rand_load_file(VALUE self, VALUE filename) static VALUE ossl_rand_write_file(VALUE self, VALUE filename) { - SafeStringValue(filename); - if (RAND_write_file(RSTRING_PTR(filename)) == -1) { + rb_check_safe_obj(filename); + + if (RAND_write_file(StringValueCStr(filename)) == -1) { ossl_raise(eRandomError, NULL); } return Qtrue; @@ -161,9 +162,9 @@ ossl_rand_pseudo_bytes(VALUE self, VALUE len) static VALUE ossl_rand_egd(VALUE self, VALUE filename) { - SafeStringValue(filename); + rb_check_safe_obj(filename); - if (RAND_egd(RSTRING_PTR(filename)) == -1) { + if (RAND_egd(StringValueCStr(filename)) == -1) { ossl_raise(eRandomError, NULL); } return Qtrue; @@ -183,9 +184,9 @@ ossl_rand_egd_bytes(VALUE self, VALUE filename, VALUE len) { int n = NUM2INT(len); - SafeStringValue(filename); + rb_check_safe_obj(filename); - if (RAND_egd_bytes(RSTRING_PTR(filename), n) == -1) { + if (RAND_egd_bytes(StringValueCStr(filename), n) == -1) { ossl_raise(eRandomError, NULL); } return Qtrue; diff --git a/ext/openssl/ossl_ssl.c b/ext/openssl/ossl_ssl.c index d5ea1304..cf23f5c1 100644 --- a/ext/openssl/ossl_ssl.c +++ b/ext/openssl/ossl_ssl.c @@ -563,9 +563,8 @@ ssl_npn_encode_protocol_i(VALUE cur, VALUE encoded) static VALUE ssl_encode_npn_protocols(VALUE protocols) { - VALUE encoded = rb_str_new2(""); + VALUE encoded = rb_str_new(NULL, 0); rb_iterate(rb_each, protocols, ssl_npn_encode_protocol_i, encoded); - StringValueCStr(encoded); return encoded; } @@ -775,9 +774,9 @@ ossl_sslctx_setup(VALUE self) } val = ossl_sslctx_get_ca_file(self); - ca_file = NIL_P(val) ? NULL : StringValuePtr(val); + ca_file = NIL_P(val) ? NULL : StringValueCStr(val); val = ossl_sslctx_get_ca_path(self); - ca_path = NIL_P(val) ? NULL : StringValuePtr(val); + ca_path = NIL_P(val) ? NULL : StringValueCStr(val); if(ca_file || ca_path){ if (!SSL_CTX_load_verify_locations(ctx, ca_file, ca_path)) rb_warning("can't set verify locations"); @@ -812,7 +811,7 @@ ossl_sslctx_setup(VALUE self) val = rb_iv_get(self, "@alpn_protocols"); if (!NIL_P(val)) { VALUE rprotos = ssl_encode_npn_protocols(val); - SSL_CTX_set_alpn_protos(ctx, (const unsigned char *)StringValueCStr(rprotos), RSTRING_LENINT(rprotos)); + SSL_CTX_set_alpn_protos(ctx, (unsigned char *)RSTRING_PTR(rprotos), RSTRING_LENINT(rprotos)); OSSL_Debug("SSL ALPN values added"); } if (RTEST(rb_iv_get(self, "@alpn_select_cb"))) { @@ -947,7 +946,7 @@ ossl_sslctx_set_ciphers(VALUE self, VALUE v) ossl_raise(eSSLError, "SSL_CTX is not initialized."); return Qnil; } - if (!SSL_CTX_set_cipher_list(ctx, RSTRING_PTR(str))) { + if (!SSL_CTX_set_cipher_list(ctx, StringValueCStr(str))) { ossl_raise(eSSLError, "SSL_CTX_set_cipher_list"); } @@ -1210,7 +1209,7 @@ ossl_ssl_setup(VALUE self) #ifdef HAVE_SSL_SET_TLSEXT_HOST_NAME if (!NIL_P(hostname)) { - if (SSL_set_tlsext_host_name(ssl, StringValuePtr(hostname)) != 1) + if (SSL_set_tlsext_host_name(ssl, StringValueCStr(hostname)) != 1) ossl_raise(eSSLError, "SSL_set_tlsext_host_name"); } #endif diff --git a/ext/openssl/ossl_x509attr.c b/ext/openssl/ossl_x509attr.c index be5f2dcf..970a91eb 100644 --- a/ext/openssl/ossl_x509attr.c +++ b/ext/openssl/ossl_x509attr.c @@ -141,7 +141,7 @@ ossl_x509attr_set_oid(VALUE self, VALUE oid) ASN1_OBJECT *obj; char *s; - s = StringValuePtr(oid); + s = StringValueCStr(oid); obj = OBJ_txt2obj(s, 0); if(!obj) obj = OBJ_txt2obj(s, 1); if(!obj) ossl_raise(eX509AttrError, NULL); @@ -269,7 +269,7 @@ ossl_x509attr_to_der(VALUE self) p = (unsigned char *)RSTRING_PTR(str); if(i2d_X509_ATTRIBUTE(attr, &p) <= 0) ossl_raise(eX509AttrError, NULL); - rb_str_set_len(str, p - (unsigned char*)RSTRING_PTR(str)); + ossl_str_adjust(str, p); return str; } diff --git a/ext/openssl/ossl_x509cert.c b/ext/openssl/ossl_x509cert.c index 226704ef..34b8aae7 100644 --- a/ext/openssl/ossl_x509cert.c +++ b/ext/openssl/ossl_x509cert.c @@ -78,9 +78,9 @@ ossl_x509_new_from_file(VALUE filename) FILE *fp; VALUE obj; - SafeStringValue(filename); + rb_check_safe_obj(filename); obj = NewX509(cX509Cert); - if (!(fp = fopen(RSTRING_PTR(filename), "r"))) { + if (!(fp = fopen(StringValueCStr(filename), "r"))) { ossl_raise(eX509CertError, "%s", strerror(errno)); } rb_fd_fix_cloexec(fileno(fp)); diff --git a/ext/openssl/ossl_x509ext.c b/ext/openssl/ossl_x509ext.c index 70a117cc..d4f42e23 100644 --- a/ext/openssl/ossl_x509ext.c +++ b/ext/openssl/ossl_x509ext.c @@ -251,15 +251,18 @@ ossl_x509extfactory_create_ext(int argc, VALUE *argv, VALUE self) #endif rb_scan_args(argc, argv, "21", &oid, &value, &critical); - StringValue(oid); + StringValueCStr(oid); StringValue(value); if(NIL_P(critical)) critical = Qfalse; nid = OBJ_ln2nid(RSTRING_PTR(oid)); if(!nid) nid = OBJ_sn2nid(RSTRING_PTR(oid)); - if(!nid) ossl_raise(eX509ExtError, "unknown OID `%s'", RSTRING_PTR(oid)); + if(!nid) ossl_raise(eX509ExtError, "unknown OID `%"PRIsVALUE"'", oid); + valstr = rb_str_new2(RTEST(critical) ? "critical," : ""); rb_str_append(valstr, value); + StringValueCStr(valstr); + GetX509ExtFactory(self, ctx); obj = NewX509Ext(cX509Ext); #ifdef HAVE_X509V3_EXT_NCONF_NID @@ -271,8 +274,7 @@ ossl_x509extfactory_create_ext(int argc, VALUE *argv, VALUE self) ext = X509V3_EXT_conf_nid(empty_lhash, ctx, nid, RSTRING_PTR(valstr)); #endif if (!ext){ - ossl_raise(eX509ExtError, "%s = %s", - RSTRING_PTR(oid), RSTRING_PTR(value)); + ossl_raise(eX509ExtError, "%"PRIsVALUE" = %"PRIsVALUE, oid, valstr); } SetX509Ext(obj, ext); @@ -341,7 +343,7 @@ ossl_x509ext_set_oid(VALUE self, VALUE oid) ASN1_OBJECT *obj; char *s; - s = StringValuePtr(oid); + s = StringValueCStr(oid); obj = OBJ_txt2obj(s, 0); if(!obj) obj = OBJ_txt2obj(s, 1); if(!obj) ossl_raise(eX509ExtError, NULL); diff --git a/ext/openssl/ossl_x509store.c b/ext/openssl/ossl_x509store.c index 8d6f9de2..f3501e53 100644 --- a/ext/openssl/ossl_x509store.c +++ b/ext/openssl/ossl_x509store.c @@ -240,8 +240,8 @@ ossl_x509store_add_file(VALUE self, VALUE file) char *path = NULL; if(file != Qnil){ - SafeStringValue(file); - path = RSTRING_PTR(file); + rb_check_safe_obj(file); + path = StringValueCStr(file); } GetX509Store(self, store); lookup = X509_STORE_add_lookup(store, X509_LOOKUP_file()); @@ -261,8 +261,8 @@ ossl_x509store_add_path(VALUE self, VALUE dir) char *path = NULL; if(dir != Qnil){ - SafeStringValue(dir); - path = RSTRING_PTR(dir); + rb_check_safe_obj(dir); + path = StringValueCStr(dir); } GetX509Store(self, store); lookup = X509_STORE_add_lookup(store, X509_LOOKUP_hash_dir()); -- cgit v1.2.3 From e655faa38cdfbdd2da56c0b8db3a3fbb7094fa68 Mon Sep 17 00:00:00 2001 From: rhe Date: Mon, 23 May 2016 12:10:38 +0000 Subject: openssl: Avoid reference to unset global variable in Init_openssl() * ext/openssl/ossl.c (Init_openssl): Avoid reference to unset global variable. ossl_raise() may be called before dOSSL is set. Since global variables default to 0 and the default value of dOSSL set in Init_openssl() is also Qfalse, there is no real issue but confusing. Patch by Bertram Scharpf [ruby-core:58264] [Bug #9101] git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@55135 b2dd03c8-39d4-4d8f-98ff-823fe69b080e --- ext/openssl/ossl.c | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/ext/openssl/ossl.c b/ext/openssl/ossl.c index 1f62c57a..ad9c430d 100644 --- a/ext/openssl/ossl.c +++ b/ext/openssl/ossl.c @@ -1176,14 +1176,6 @@ Init_openssl(void) eOSSLError = rb_define_class_under(mOSSL,"OpenSSLError",rb_eStandardError); rb_global_variable(&eOSSLError); - /* - * Verify callback Proc index for ext-data - */ - if ((ossl_store_ctx_ex_verify_cb_idx = X509_STORE_CTX_get_ex_new_index(0, (void *)"ossl_store_ctx_ex_verify_cb_idx", 0, 0, 0)) < 0) - ossl_raise(eOSSLError, "X509_STORE_CTX_get_ex_new_index"); - if ((ossl_store_ex_verify_cb_idx = X509_STORE_get_ex_new_index(0, (void *)"ossl_store_ex_verify_cb_idx", 0, 0, 0)) < 0) - ossl_raise(eOSSLError, "X509_STORE_get_ex_new_index"); - /* * Init debug core */ @@ -1194,6 +1186,14 @@ Init_openssl(void) rb_define_module_function(mOSSL, "debug=", ossl_debug_set, 1); rb_define_module_function(mOSSL, "errors", ossl_get_errors, 0); + /* + * Verify callback Proc index for ext-data + */ + if ((ossl_store_ctx_ex_verify_cb_idx = X509_STORE_CTX_get_ex_new_index(0, (void *)"ossl_store_ctx_ex_verify_cb_idx", 0, 0, 0)) < 0) + ossl_raise(eOSSLError, "X509_STORE_CTX_get_ex_new_index"); + if ((ossl_store_ex_verify_cb_idx = X509_STORE_get_ex_new_index(0, (void *)"ossl_store_ex_verify_cb_idx", 0, 0, 0)) < 0) + ossl_raise(eOSSLError, "X509_STORE_get_ex_new_index"); + /* * Get ID of to_der */ -- cgit v1.2.3 From 5783408e86d4dd145e3263669f54f7269e00c500 Mon Sep 17 00:00:00 2001 From: rhe Date: Tue, 24 May 2016 12:39:57 +0000 Subject: openssl: avoid deprecated M_ASN1_* macros * ext/openssl/ossl_x509ext.c (ossl_x509ext_set_value): Use ASN1_OCTET_STRING_set() instead of M_ASN1_OCTET_STRING_set(). Macros prefixed by "M_" are discouraged to be used from outside OpenSSL library[1]. (ossl_x509ext_get_value): Likewise, use ASN1_STRING_print() instead of M_ASN1_OCTET_STRING_print(). [1] https://git.openssl.org/gitweb/?p=openssl.git;a=blob;f=CHANGES;h=bf61913d7b01212b4d8b2f3c13d71d645914f67c;hb=b6079a7835f61daa9fb2cbf9addfa86049523933#l878 * ext/openssl/ossl.h: Include openssl/asn1.h instead of openssl/asn1_mac.h. It just includes openssl/asn1.h and defines some additional "M_" macros. git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@55145 b2dd03c8-39d4-4d8f-98ff-823fe69b080e --- ext/openssl/ossl.h | 2 +- ext/openssl/ossl_x509ext.c | 11 ++--------- 2 files changed, 3 insertions(+), 10 deletions(-) diff --git a/ext/openssl/ossl.h b/ext/openssl/ossl.h index 25f2c857..8da2ab47 100644 --- a/ext/openssl/ossl.h +++ b/ext/openssl/ossl.h @@ -54,7 +54,7 @@ extern "C" { #endif #include #include -#include +#include #include #include #include diff --git a/ext/openssl/ossl_x509ext.c b/ext/openssl/ossl_x509ext.c index d4f42e23..e67da4ba 100644 --- a/ext/openssl/ossl_x509ext.c +++ b/ext/openssl/ossl_x509ext.c @@ -358,23 +358,16 @@ ossl_x509ext_set_value(VALUE self, VALUE data) { X509_EXTENSION *ext; ASN1_OCTET_STRING *asn1s; - char *s; data = ossl_to_der_if_possible(data); StringValue(data); - if(!(s = OPENSSL_malloc(RSTRING_LEN(data)))) - ossl_raise(eX509ExtError, "malloc error"); - memcpy(s, RSTRING_PTR(data), RSTRING_LEN(data)); if(!(asn1s = ASN1_OCTET_STRING_new())){ - OPENSSL_free(s); ossl_raise(eX509ExtError, NULL); } - if(!M_ASN1_OCTET_STRING_set(asn1s, s, RSTRING_LENINT(data))){ - OPENSSL_free(s); + if(!ASN1_STRING_set((ASN1_STRING *)asn1s, (unsigned char *)RSTRING_PTR(data), RSTRING_LENINT(data))){ ASN1_OCTET_STRING_free(asn1s); ossl_raise(eX509ExtError, NULL); } - OPENSSL_free(s); GetX509Ext(self, ext); X509_EXTENSION_set_data(ext, asn1s); @@ -426,7 +419,7 @@ ossl_x509ext_get_value(VALUE obj) if (!(out = BIO_new(BIO_s_mem()))) ossl_raise(eX509ExtError, NULL); if (!X509V3_EXT_print(out, ext, 0, 0)) - M_ASN1_OCTET_STRING_print(out, ext->value); + ASN1_STRING_print(out, (ASN1_STRING *)X509_EXTENSION_get_data(ext)); ret = ossl_membio2str(out); return ret; -- cgit v1.2.3 From f8eec6b558675eb8cedccdd904e833ed77151b42 Mon Sep 17 00:00:00 2001 From: rhe Date: Tue, 24 May 2016 13:09:03 +0000 Subject: openssl: make Cipher#key= and #iv= reject too long values * ext/openssl/ossl_cipher.c (ossl_cipher_set_key, ossl_cipher_set_iv): Reject too long values as well as too short ones. Currently they just truncate the input but this would hide bugs and lead to unexpected encryption/decryption results. * test/openssl/test_cipher.rb: Test that Cipher#key= and #iv= reject Strings with invalid length. git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@55146 b2dd03c8-39d4-4d8f-98ff-823fe69b080e --- ext/openssl/ossl_cipher.c | 14 +++++++++----- test/test_cipher.rb | 12 ++++++++++++ 2 files changed, 21 insertions(+), 5 deletions(-) diff --git a/ext/openssl/ossl_cipher.c b/ext/openssl/ossl_cipher.c index 9aab8025..43a8effa 100644 --- a/ext/openssl/ossl_cipher.c +++ b/ext/openssl/ossl_cipher.c @@ -480,15 +480,17 @@ static VALUE ossl_cipher_set_key(VALUE self, VALUE key) { EVP_CIPHER_CTX *ctx; + int key_len; StringValue(key); GetCipher(self, ctx); - if (RSTRING_LEN(key) < EVP_CIPHER_CTX_key_length(ctx)) - ossl_raise(eCipherError, "key length too short"); + key_len = EVP_CIPHER_CTX_key_length(ctx); + if (RSTRING_LEN(key) != key_len) + ossl_raise(rb_eArgError, "key must be %d bytes", key_len); if (EVP_CipherInit_ex(ctx, NULL, NULL, (unsigned char *)RSTRING_PTR(key), NULL, -1) != 1) - ossl_raise(eCipherError, NULL); + ossl_raise(eCipherError, NULL); return key; } @@ -512,12 +514,14 @@ static VALUE ossl_cipher_set_iv(VALUE self, VALUE iv) { EVP_CIPHER_CTX *ctx; + int iv_len; StringValue(iv); GetCipher(self, ctx); - if (RSTRING_LEN(iv) < EVP_CIPHER_CTX_iv_length(ctx)) - ossl_raise(eCipherError, "iv length too short"); + iv_len = EVP_CIPHER_CTX_iv_length(ctx); + if (RSTRING_LEN(iv) != iv_len) + ossl_raise(rb_eArgError, "iv must be %d bytes", iv_len); if (EVP_CipherInit_ex(ctx, NULL, NULL, NULL, (unsigned char *)RSTRING_PTR(iv), -1) != 1) ossl_raise(eCipherError, NULL); diff --git a/test/test_cipher.rb b/test/test_cipher.rb index dab64aa5..aec33fdd 100644 --- a/test/test_cipher.rb +++ b/test/test_cipher.rb @@ -80,6 +80,18 @@ class OpenSSL::TestCipher < OpenSSL::TestCase assert_equal(s1, s2, "encrypt reset") end + def test_key_iv_set + # default value for DES-EDE3-CBC + assert_equal(24, @c1.key_len) + assert_equal(8, @c1.iv_len) + assert_raise(ArgumentError) { @c1.key = "\x01" * 23 } + @c1.key = "\x01" * 24 + assert_raise(ArgumentError) { @c1.key = "\x01" * 25 } + assert_raise(ArgumentError) { @c1.iv = "\x01" * 7 } + @c1.iv = "\x01" * 8 + assert_raise(ArgumentError) { @c1.iv = "\x01" * 9 } + end + def test_empty_data @c1.encrypt assert_raise(ArgumentError){ @c1.update("") } -- cgit v1.2.3 From ca428e6777947d0da4f2bb435845c91f453da0b8 Mon Sep 17 00:00:00 2001 From: rhe Date: Tue, 24 May 2016 16:27:11 +0000 Subject: openssl: rename EC#generate_key to EC#generate_key! * ext/openssl/ossl_pkey_ec.c (ossl_ec_key_generate_key): Fix up RDoc. (Init_ossl_ec): Rename EC#generate_key to EC#generate_key!. Make the old name an alias of #generate_key!. This change is for consistency with other PKey types. [ruby-core:45541] [Bug #6567] * test/openssl/test_pkey_ec.rb: Use EC#generate_key! instead of EC#generate_key. git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@55151 b2dd03c8-39d4-4d8f-98ff-823fe69b080e --- ext/openssl/ossl_pkey_ec.c | 15 ++++++++++++--- test/test_pkey_ec.rb | 4 ++-- 2 files changed, 14 insertions(+), 5 deletions(-) diff --git a/ext/openssl/ossl_pkey_ec.c b/ext/openssl/ossl_pkey_ec.c index ab6209c7..74bc7abe 100644 --- a/ext/openssl/ossl_pkey_ec.c +++ b/ext/openssl/ossl_pkey_ec.c @@ -584,9 +584,17 @@ static VALUE ossl_ec_key_to_text(VALUE self) /* * call-seq: - * key.generate_key => self + * key.generate_key! => self * - * See the OpenSSL documentation for EC_KEY_generate_key() + * Generates a new random private and public key. + * + * See also the OpenSSL documentation for EC_KEY_generate_key() + * + * === Example + * ec = OpenSSL::PKey::EC.new("prime256v1") + * p ec.private_key # => nil + * ec.generate_key! + * p ec.private_key # => # */ static VALUE ossl_ec_key_generate_key(VALUE self) { @@ -1632,7 +1640,8 @@ void Init_ossl_ec(void) set/get asn1_flag (can use ruby to call self.group.asn1_flag) set/get precompute_mult */ - rb_define_method(cEC, "generate_key", ossl_ec_key_generate_key, 0); + rb_define_method(cEC, "generate_key!", ossl_ec_key_generate_key, 0); + rb_define_alias(cEC, "generate_key", "generate_key!"); rb_define_method(cEC, "check_key", ossl_ec_key_check_key, 0); rb_define_method(cEC, "dh_compute_key", ossl_ec_key_dh_compute_key, 1); diff --git a/test/test_pkey_ec.rb b/test/test_pkey_ec.rb index 302259b2..712507f6 100644 --- a/test/test_pkey_ec.rb +++ b/test/test_pkey_ec.rb @@ -16,7 +16,7 @@ class OpenSSL::TestEC < OpenSSL::TestCase group = OpenSSL::PKey::EC::Group.new(curve) key = OpenSSL::PKey::EC.new(group) - key.generate_key + key.generate_key! @groups << group @keys << key @@ -127,7 +127,7 @@ class OpenSSL::TestEC < OpenSSL::TestCase def test_dh_compute_key for key in @keys k = OpenSSL::PKey::EC.new(key.group) - k.generate_key + k.generate_key! puba = key.public_key pubb = k.public_key -- cgit v1.2.3 From 1ed0cf02869f3e25574da315e363d1a27d187315 Mon Sep 17 00:00:00 2001 From: rhe Date: Tue, 24 May 2016 16:30:15 +0000 Subject: openssl: add EC.generate * ext/openssl/ossl_pkey_ec.c (ec_key_new_from_group): Create a new EC_KEY on given EC group. Extracted from ossl_ec_key_initialize(). (ossl_ec_key_s_generate): Added. Create a new EC instance and generate a random private and public key. (ossl_ec_key_initialize): Use ec_key_new_from_group(). (Init_ossl_ec): Define the new method EC.generate. This change is for consistency with other PKey types. [ruby-core:45541] [Bug #6567] * test/openssl/test_pkey_ec.rb: Test that EC.generate works. git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@55152 b2dd03c8-39d4-4d8f-98ff-823fe69b080e --- ext/openssl/ossl_pkey_ec.c | 147 +++++++++++++++++++++++++++++---------------- test/test_pkey_ec.rb | 9 +++ 2 files changed, 105 insertions(+), 51 deletions(-) diff --git a/ext/openssl/ossl_pkey_ec.c b/ext/openssl/ossl_pkey_ec.c index 74bc7abe..9210ae48 100644 --- a/ext/openssl/ossl_pkey_ec.c +++ b/ext/openssl/ossl_pkey_ec.c @@ -149,6 +149,69 @@ VALUE ossl_ec_new(EVP_PKEY *pkey) return obj; } +/* + * Creates a new EC_KEY on the EC group obj. arg can be an EC::Group or a String + * representing an OID. + */ +static EC_KEY * +ec_key_new_from_group(VALUE arg) +{ + EC_KEY *ec; + + if (rb_obj_is_kind_of(arg, cEC_GROUP)) { + EC_GROUP *group; + + SafeRequire_EC_GROUP(arg, group); + + if (!(ec = EC_KEY_new())) + ossl_raise(eECError, NULL); + + if (!EC_KEY_set_group(ec, group)) { + EC_KEY_free(ec); + ossl_raise(eECError, NULL); + } + } else { + int nid = OBJ_sn2nid(StringValueCStr(arg)); + + if (nid == NID_undef) + ossl_raise(eECError, "invalid curve name"); + + if (!(ec = EC_KEY_new_by_curve_name(nid))) + ossl_raise(eECError, NULL); + + EC_KEY_set_asn1_flag(ec, OPENSSL_EC_NAMED_CURVE); + EC_KEY_set_conv_form(ec, POINT_CONVERSION_UNCOMPRESSED); + } + + return ec; +} + +/* + * call-seq: + * EC.generate(ec_group) -> ec + * EC.generate(string) -> ec + * + * Creates a new EC instance with a new random private and public key. + */ +static VALUE +ossl_ec_key_s_generate(VALUE klass, VALUE arg) +{ + EC_KEY *ec; + VALUE obj; + + ec = ec_key_new_from_group(arg); + + obj = ec_instance(klass, ec); + if (obj == Qfalse) { + EC_KEY_free(ec); + ossl_raise(eECError, NULL); + } + + if (!EC_KEY_generate_key(ec)) + ossl_raise(eECError, "EC_KEY_generate_key"); + + return obj; +} /* call-seq: * OpenSSL::PKey::EC.new() @@ -165,9 +228,8 @@ VALUE ossl_ec_new(EVP_PKEY *pkey) static VALUE ossl_ec_key_initialize(int argc, VALUE *argv, VALUE self) { EVP_PKEY *pkey; - EC_KEY *ec = NULL; + EC_KEY *ec; VALUE arg, pass; - VALUE group = Qnil; GetPKey(self, pkey); if (pkey->pkey.ec) @@ -176,58 +238,43 @@ static VALUE ossl_ec_key_initialize(int argc, VALUE *argv, VALUE self) rb_scan_args(argc, argv, "02", &arg, &pass); if (NIL_P(arg)) { - ec = EC_KEY_new(); + if (!(ec = EC_KEY_new())) + ossl_raise(eECError, NULL); + } else if (rb_obj_is_kind_of(arg, cEC)) { + EC_KEY *other_ec = NULL; + + SafeRequire_EC_KEY(arg, other_ec); + if (!(ec = EC_KEY_dup(other_ec))) + ossl_raise(eECError, NULL); + } else if (rb_obj_is_kind_of(arg, cEC_GROUP)) { + ec = ec_key_new_from_group(arg); } else { - if (rb_obj_is_kind_of(arg, cEC)) { - EC_KEY *other_ec = NULL; - - SafeRequire_EC_KEY(arg, other_ec); - ec = EC_KEY_dup(other_ec); - } else if (rb_obj_is_kind_of(arg, cEC_GROUP)) { - ec = EC_KEY_new(); - group = arg; - } else { - BIO *in; - - pass = ossl_pem_passwd_value(pass); - in = ossl_obj2bio(arg); - - ec = PEM_read_bio_ECPrivateKey(in, NULL, ossl_pem_passwd_cb, (void *)pass); - if (!ec) { - OSSL_BIO_reset(in); - ec = PEM_read_bio_EC_PUBKEY(in, NULL, ossl_pem_passwd_cb, (void *)pass); - } - if (!ec) { - OSSL_BIO_reset(in); - ec = d2i_ECPrivateKey_bio(in, NULL); - } - if (!ec) { - OSSL_BIO_reset(in); - ec = d2i_EC_PUBKEY_bio(in, NULL); - } - - BIO_free(in); - - if (ec == NULL) { - const char *name = StringValueCStr(arg); - int nid = OBJ_sn2nid(name); + BIO *in; - ossl_clear_error(); /* ignore errors in the previous d2i_EC_PUBKEY_bio() */ - if (nid == NID_undef) - ossl_raise(eECError, "unknown curve name (%"PRIsVALUE")", arg); + pass = ossl_pem_passwd_value(pass); + in = ossl_obj2bio(arg); - if ((ec = EC_KEY_new_by_curve_name(nid)) == NULL) - ossl_raise(eECError, "unable to create curve (%"PRIsVALUE")\n", arg); + ec = PEM_read_bio_ECPrivateKey(in, NULL, ossl_pem_passwd_cb, (void *)pass); + if (!ec) { + OSSL_BIO_reset(in); + ec = PEM_read_bio_EC_PUBKEY(in, NULL, ossl_pem_passwd_cb, (void *)pass); + } + if (!ec) { + OSSL_BIO_reset(in); + ec = d2i_ECPrivateKey_bio(in, NULL); + } + if (!ec) { + OSSL_BIO_reset(in); + ec = d2i_EC_PUBKEY_bio(in, NULL); + } + BIO_free(in); - EC_KEY_set_asn1_flag(ec, OPENSSL_EC_NAMED_CURVE); - EC_KEY_set_conv_form(ec, POINT_CONVERSION_UNCOMPRESSED); - } - } + if (!ec) { + ossl_clear_error(); + ec = ec_key_new_from_group(arg); + } } - if (ec == NULL) - ossl_raise(eECError, NULL); - if (!EVP_PKEY_assign_EC_KEY(pkey, ec)) { EC_KEY_free(ec); ossl_raise(eECError, "EVP_PKEY_assign_EC_KEY"); @@ -235,9 +282,6 @@ static VALUE ossl_ec_key_initialize(int argc, VALUE *argv, VALUE self) rb_iv_set(self, "@group", Qnil); - if (!NIL_P(group)) - rb_funcall(self, rb_intern("group="), 1, arg); - return self; } @@ -1620,6 +1664,7 @@ void Init_ossl_ec(void) rb_define_singleton_method(cEC, "builtin_curves", ossl_s_builtin_curves, 0); + rb_define_singleton_method(cEC, "generate", ossl_ec_key_s_generate, 1); rb_define_method(cEC, "initialize", ossl_ec_key_initialize, -1); /* copy/dup/cmp */ diff --git a/test/test_pkey_ec.rb b/test/test_pkey_ec.rb index 712507f6..4161e9b0 100644 --- a/test/test_pkey_ec.rb +++ b/test/test_pkey_ec.rb @@ -38,6 +38,15 @@ class OpenSSL::TestEC < OpenSSL::TestCase end end + def test_generate + assert_raise(OpenSSL::PKey::ECError) { OpenSSL::PKey::EC.generate("non-existent") } + g = OpenSSL::PKey::EC::Group.new("prime256v1") + ec = OpenSSL::PKey::EC.generate(g) + assert_equal(true, ec.private?) + ec = OpenSSL::PKey::EC.generate("prime256v1") + assert_equal(true, ec.private?) + end + def test_check_key for key in @keys assert_equal(true, key.check_key) -- cgit v1.2.3 From 90038a0dd090459099addabd885a275dcc848855 Mon Sep 17 00:00:00 2001 From: rhe Date: Wed, 25 May 2016 08:46:39 +0000 Subject: openssl: remove check of OPENSSL_FIPS macro in extconf.rb * ext/openssl/extconf.rb: Remove check of OPENSSL_FIPS macro. This is unneeded because we can check the macro directly in source code, just as we already do for OPENSSL_NO_* macros. * ext/openssl/ossl.c: Replace occurrences of HAVE_OPENSSL_FIPS with OPENSSL_FIPS. git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@55160 b2dd03c8-39d4-4d8f-98ff-823fe69b080e --- ext/openssl/extconf.rb | 1 - ext/openssl/ossl.c | 4 ++-- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/ext/openssl/extconf.rb b/ext/openssl/extconf.rb index 9b3bdef0..39543f30 100644 --- a/ext/openssl/extconf.rb +++ b/ext/openssl/extconf.rb @@ -154,7 +154,6 @@ have_struct_member("CRYPTO_THREADID", "ptr", "openssl/crypto.h") have_struct_member("EVP_CIPHER_CTX", "flags", "openssl/evp.h") have_struct_member("EVP_CIPHER_CTX", "engine", "openssl/evp.h") have_struct_member("X509_ATTRIBUTE", "single", "openssl/x509.h") -have_macro("OPENSSL_FIPS", ['openssl/opensslconf.h']) && $defs.push("-DHAVE_OPENSSL_FIPS") have_macro("EVP_CTRL_GCM_GET_TAG", ['openssl/evp.h']) && $defs.push("-DHAVE_AUTHENTICATED_ENCRYPTION") Logging::message "=== Checking done. ===\n" diff --git a/ext/openssl/ossl.c b/ext/openssl/ossl.c index ad9c430d..c06a579c 100644 --- a/ext/openssl/ossl.c +++ b/ext/openssl/ossl.c @@ -495,7 +495,7 @@ static VALUE ossl_fips_mode_set(VALUE self, VALUE enabled) { -#ifdef HAVE_OPENSSL_FIPS +#ifdef OPENSSL_FIPS if (RTEST(enabled)) { int mode = FIPS_mode(); if(!mode && !FIPS_mode_set(1)) /* turning on twice leads to an error */ @@ -1162,7 +1162,7 @@ Init_openssl(void) /* * Boolean indicating whether OpenSSL is FIPS-enabled or not */ -#ifdef HAVE_OPENSSL_FIPS +#ifdef OPENSSL_FIPS rb_define_const(mOSSL, "OPENSSL_FIPS", Qtrue); #else rb_define_const(mOSSL, "OPENSSL_FIPS", Qfalse); -- cgit v1.2.3 From e34610d8d5e49301157afe435803b185774f39a2 Mon Sep 17 00:00:00 2001 From: rhe Date: Wed, 25 May 2016 08:46:40 +0000 Subject: openssl: remove unnecessary 'extern "C"' blocks from local headers * ext/openssl/openssl_missing.h, ext/openssl/ossl.h: Remove unnecessary 'extern "C"' blocks. We don't use C++ and these headers are local to ext/openssl, so there is no need to enclose with it. git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@55161 b2dd03c8-39d4-4d8f-98ff-823fe69b080e --- ext/openssl/openssl_missing.h | 9 --------- ext/openssl/ossl.h | 8 -------- 2 files changed, 17 deletions(-) diff --git a/ext/openssl/openssl_missing.h b/ext/openssl/openssl_missing.h index 955579cf..b5bfd31e 100644 --- a/ext/openssl/openssl_missing.h +++ b/ext/openssl/openssl_missing.h @@ -10,10 +10,6 @@ #if !defined(_OSSL_OPENSSL_MISSING_H_) #define _OSSL_OPENSSL_MISSING_H_ -#if defined(__cplusplus) -extern "C" { -#endif - #ifndef TYPEDEF_D2I_OF typedef char *d2i_of_void(); #endif @@ -193,9 +189,4 @@ int PEM_def_callback(char *buf, int num, int w, void *key); int ASN1_put_eoc(unsigned char **pp); #endif -#if defined(__cplusplus) -} -#endif - - #endif /* _OSSL_OPENSSL_MISSING_H_ */ diff --git a/ext/openssl/ossl.h b/ext/openssl/ossl.h index 8da2ab47..4a538e9b 100644 --- a/ext/openssl/ossl.h +++ b/ext/openssl/ossl.h @@ -12,10 +12,6 @@ #include RUBY_EXTCONF_H -#if defined(__cplusplus) -extern "C" { -#endif - #if 0 mOSSL = rb_define_module("OpenSSL"); mX509 = rb_define_module_under(mOSSL, "X509"); @@ -247,8 +243,4 @@ void ossl_debug(const char *, ...); void Init_openssl(void); -#if defined(__cplusplus) -} -#endif - #endif /* _OSSL_H_ */ -- cgit v1.2.3 From c1d611158df3cd8ff2fa4964b029678c6b9f9fd6 Mon Sep 17 00:00:00 2001 From: rhe Date: Wed, 25 May 2016 08:50:03 +0000 Subject: openssl: drop OpenSSL 0.9.6/0.9.7 support * ext/openssl, test/openssl: Drop OpenSSL < 0.9.8 support. git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@55162 b2dd03c8-39d4-4d8f-98ff-823fe69b080e --- ext/openssl/deprecation.rb | 8 +- ext/openssl/extconf.rb | 134 ++++++----------- ext/openssl/openssl_missing.c | 318 +++-------------------------------------- ext/openssl/openssl_missing.h | 166 ++------------------- ext/openssl/ossl.c | 4 - ext/openssl/ossl.h | 21 +-- ext/openssl/ossl_asn1.c | 71 ++------- ext/openssl/ossl_cipher.c | 10 -- ext/openssl/ossl_engine.c | 24 +--- ext/openssl/ossl_ocsp.c | 4 +- ext/openssl/ossl_ocsp.h | 2 +- ext/openssl/ossl_pkcs5.c | 4 - ext/openssl/ossl_pkcs7.c | 24 +++- ext/openssl/ossl_pkey.c | 15 -- ext/openssl/ossl_pkey.h | 4 - ext/openssl/ossl_pkey_dh.c | 11 +- ext/openssl/ossl_pkey_dsa.c | 22 +-- ext/openssl/ossl_pkey_ec.c | 2 - ext/openssl/ossl_pkey_rsa.c | 6 - ext/openssl/ossl_ssl.c | 20 +-- ext/openssl/ossl_ssl_session.c | 7 - ext/openssl/ossl_x509.c | 10 -- ext/openssl/ossl_x509attr.c | 14 +- ext/openssl/ossl_x509ext.c | 13 -- ext/openssl/ossl_x509store.c | 29 ---- lib/openssl/ssl.rb | 9 +- test/test_cipher.rb | 62 ++++---- test/test_pkcs7.rb | 6 - test/test_ssl.rb | 6 +- test/test_ssl_session.rb | 15 +- test/test_x509store.rb | 2 - 31 files changed, 169 insertions(+), 874 deletions(-) diff --git a/ext/openssl/deprecation.rb b/ext/openssl/deprecation.rb index d7735367..7dfc87c1 100644 --- a/ext/openssl/deprecation.rb +++ b/ext/openssl/deprecation.rb @@ -16,7 +16,11 @@ module OpenSSL end def self.check_func(func, header) - have_func(func, header, deprecated_warning_flag) and - have_header(header, nil, deprecated_warning_flag) + have_func(func, header, deprecated_warning_flag) + end + + def self.check_func_or_macro(func, header) + check_func(func, header) or + have_macro(func, header) && $defs.push("-DHAVE_#{func.upcase}") end end diff --git a/ext/openssl/extconf.rb b/ext/openssl/extconf.rb index 39543f30..14daae97 100644 --- a/ext/openssl/extconf.rb +++ b/ext/openssl/extconf.rb @@ -19,12 +19,15 @@ dir_config("kerberos") Logging::message "=== OpenSSL for Ruby configurator ===\n" +# Add -Werror=deprecated-declarations to $warnflags if available +OpenSSL.deprecated_warning_flag + ## # Adds -DOSSL_DEBUG for compilation and some more targets when GCC is used # To turn it on, use: --with-debug or --enable-debug # if with_config("debug") or enable_config("debug") - $defs.push("-DOSSL_DEBUG") unless $defs.include? "-DOSSL_DEBUG" + $defs.push("-DOSSL_DEBUG") end Logging::message "=== Checking for system dependent stuff... ===\n" @@ -39,7 +42,6 @@ if $mingw end result = pkg_config("openssl") && have_header("openssl/ssl.h") - unless result result = have_header("openssl/ssl.h") result &&= %w[crypto libeay32].any? {|lib| have_library(lib, "OpenSSL_add_all_digests")} @@ -51,111 +53,59 @@ unless result end end -unless have_header("openssl/conf_api.h") - raise "OpenSSL 0.9.6 or later required." +result = checking_for("OpenSSL version is 0.9.8 or later") { + try_static_assert("OPENSSL_VERSION_NUMBER >= 0x00908000L", "openssl/opensslv.h") +} +unless result + raise "OpenSSL 0.9.8 or later required." end + unless OpenSSL.check_func("SSL_library_init()", "openssl/ssl.h") raise "Ignore OpenSSL broken by Apple.\nPlease use another openssl. (e.g. using `configure --with-openssl-dir=/path/to/openssl')" end Logging::message "=== Checking for OpenSSL features... ===\n" -have_func("ERR_peek_last_error") -have_func("ASN1_put_eoc") -have_func("BN_mod_add") -have_func("BN_mod_sqr") -have_func("BN_mod_sub") -have_func("BN_pseudo_rand_range") -have_func("BN_rand_range") -have_func("CONF_get1_default_config_file") -have_func("EVP_CIPHER_CTX_copy") -have_func("EVP_CIPHER_CTX_set_padding") -have_func("EVP_CipherFinal_ex") -have_func("EVP_CipherInit_ex") -have_func("EVP_DigestFinal_ex") -have_func("EVP_DigestInit_ex") -have_func("EVP_MD_CTX_cleanup") -have_func("EVP_MD_CTX_create") -have_func("EVP_MD_CTX_destroy") -have_func("EVP_MD_CTX_init") -have_func("HMAC_CTX_cleanup") -have_func("HMAC_CTX_copy") -have_func("HMAC_CTX_init") -have_func("PEM_def_callback") -have_func("PKCS5_PBKDF2_HMAC") -have_func("PKCS5_PBKDF2_HMAC_SHA1") -have_func("RAND_egd") -have_func("X509V3_set_nconf") -have_func("X509V3_EXT_nconf_nid") -have_func("X509_CRL_add0_revoked") -have_func("X509_CRL_set_issuer_name") -have_func("X509_CRL_set_version") -have_func("X509_CRL_sort") -have_func("X509_NAME_hash_old") -have_func("X509_STORE_get_ex_data") -have_func("X509_STORE_set_ex_data") -have_func("OBJ_NAME_do_all_sorted") -have_func("SSL_SESSION_get_id") -have_func("SSL_SESSION_cmp") -have_func("OPENSSL_cleanse") -unless have_macro("OPENSSL_NO_SSL2","openssl/opensslconf.h") +# compile options + +# check OPENSSL_NO_{SSL2,SSL3_METHOD} macro: on some environment, these symbols +# exist even if compiled with no-ssl2 or no-ssl3-method. +unless have_macro("OPENSSL_NO_SSL2", "openssl/opensslconf.h") have_func("SSLv2_method") - have_func("SSLv2_server_method") - have_func("SSLv2_client_method") end -unless have_macro("OPENSSL_NO_SSL3_METHOD","openssl/opensslconf.h") +unless have_macro("OPENSSL_NO_SSL3_METHOD", "openssl/opensslconf.h") have_func("SSLv3_method") - have_func("SSLv3_server_method") - have_func("SSLv3_client_method") end have_func("TLSv1_1_method") -have_func("TLSv1_1_server_method") -have_func("TLSv1_1_client_method") have_func("TLSv1_2_method") -have_func("TLSv1_2_server_method") -have_func("TLSv1_2_client_method") -have_func("SSL_CTX_set_alpn_select_cb") -have_func("SSL_CTX_set_next_proto_select_cb") -have_macro("SSL_get_server_tmp_key", ['openssl/ssl.h']) && $defs.push("-DHAVE_SSL_GET_SERVER_TMP_KEY") -unless have_func("SSL_set_tlsext_host_name", ['openssl/ssl.h']) - have_macro("SSL_set_tlsext_host_name", ['openssl/ssl.h']) && $defs.push("-DHAVE_SSL_SET_TLSEXT_HOST_NAME") -end -if have_header("openssl/engine.h") - have_func("ENGINE_add") - have_func("ENGINE_load_builtin_engines") - have_func("ENGINE_load_openbsd_dev_crypto") - have_func("ENGINE_get_digest") - have_func("ENGINE_get_cipher") - have_func("ENGINE_cleanup") - have_func("ENGINE_load_dynamic") - have_func("ENGINE_load_4758cca") - have_func("ENGINE_load_aep") - have_func("ENGINE_load_atalla") - have_func("ENGINE_load_chil") - have_func("ENGINE_load_cswift") - have_func("ENGINE_load_nuron") - have_func("ENGINE_load_sureware") - have_func("ENGINE_load_ubsec") - have_func("ENGINE_load_padlock") - have_func("ENGINE_load_capi") - have_func("ENGINE_load_gmp") - have_func("ENGINE_load_gost") - have_func("ENGINE_load_cryptodev") - have_func("ENGINE_load_aesni") -end -have_func("DH_generate_parameters_ex") -have_func("DSA_generate_parameters_ex") -have_func("RSA_generate_key_ex") -if checking_for('OpenSSL version is 0.9.7 or later') { - try_static_assert('OPENSSL_VERSION_NUMBER >= 0x00907000L', 'openssl/opensslv.h') - } - have_header("openssl/ocsp.h") -end +have_func("RAND_egd") +engines = %w{builtin_engines openbsd_dev_crypto dynamic 4758cca aep atalla chil + cswift nuron sureware ubsec padlock capi gmp gost cryptodev aesni} +engines.each { |name| + OpenSSL.check_func_or_macro("ENGINE_load_#{name}", "openssl/engine.h") +} + +# added in 1.0.0 +have_func("EVP_CIPHER_CTX_copy") +have_func("HMAC_CTX_copy") +have_func("PKCS5_PBKDF2_HMAC") +have_func("X509_NAME_hash_old") +have_func("SSL_SESSION_cmp") # removed +OpenSSL.check_func_or_macro("SSL_set_tlsext_host_name", "openssl/ssl.h") have_struct_member("CRYPTO_THREADID", "ptr", "openssl/crypto.h") -have_struct_member("EVP_CIPHER_CTX", "flags", "openssl/evp.h") -have_struct_member("EVP_CIPHER_CTX", "engine", "openssl/evp.h") -have_struct_member("X509_ATTRIBUTE", "single", "openssl/x509.h") + +# added in 1.0.1 +have_func("SSL_CTX_set_next_proto_select_cb") have_macro("EVP_CTRL_GCM_GET_TAG", ['openssl/evp.h']) && $defs.push("-DHAVE_AUTHENTICATED_ENCRYPTION") +# added in 1.0.2 +have_func("X509_REVOKED_dup") +have_func("SSL_CTX_set_alpn_select_cb") +OpenSSL.check_func_or_macro("SSL_get_server_tmp_key", "openssl/ssl.h") + +# added in 1.1.0 +have_func("X509_STORE_get_ex_data") +have_func("X509_STORE_set_ex_data") + Logging::message "=== Checking done. ===\n" create_header diff --git a/ext/openssl/openssl_missing.c b/ext/openssl/openssl_missing.c index 31f2d0a5..7b00ae4d 100644 --- a/ext/openssl/openssl_missing.c +++ b/ext/openssl/openssl_missing.c @@ -9,93 +9,18 @@ */ #include RUBY_EXTCONF_H -#if defined(HAVE_OPENSSL_ENGINE_H) && defined(HAVE_EVP_CIPHER_CTX_ENGINE) +#include /* memcpy() */ +#if !defined(OPENSSL_NO_ENGINE) # include #endif -#include - #if !defined(OPENSSL_NO_HMAC) -#include /* memcpy() */ -#include - -#include "openssl_missing.h" - -#if !defined(HAVE_HMAC_CTX_COPY) -void -HMAC_CTX_copy(HMAC_CTX *out, HMAC_CTX *in) -{ - if (!out || !in) return; - memcpy(out, in, sizeof(HMAC_CTX)); - - EVP_MD_CTX_copy(&out->md_ctx, &in->md_ctx); - EVP_MD_CTX_copy(&out->i_ctx, &in->i_ctx); - EVP_MD_CTX_copy(&out->o_ctx, &in->o_ctx); -} -#endif /* HAVE_HMAC_CTX_COPY */ -#endif /* NO_HMAC */ - -#if !defined(HAVE_EVP_MD_CTX_CREATE) -EVP_MD_CTX * -EVP_MD_CTX_create(void) -{ - EVP_MD_CTX *ctx = OPENSSL_malloc(sizeof(EVP_MD_CTX)); - if (!ctx) return NULL; - - memset(ctx, 0, sizeof(EVP_MD_CTX)); - - return ctx; -} -#endif - -#if !defined(HAVE_EVP_MD_CTX_CLEANUP) -int -EVP_MD_CTX_cleanup(EVP_MD_CTX *ctx) -{ - /* FIXME!!! */ - memset(ctx, 0, sizeof(EVP_MD_CTX)); - - return 1; -} -#endif - -#if !defined(HAVE_EVP_MD_CTX_DESTROY) -void -EVP_MD_CTX_destroy(EVP_MD_CTX *ctx) -{ - EVP_MD_CTX_cleanup(ctx); - OPENSSL_free(ctx); -} -#endif - -#if !defined(HAVE_EVP_MD_CTX_INIT) -void -EVP_MD_CTX_init(EVP_MD_CTX *ctx) -{ - memset(ctx, 0, sizeof(EVP_MD_CTX)); -} -#endif - -#if !defined(HAVE_HMAC_CTX_INIT) -void -HMAC_CTX_init(HMAC_CTX *ctx) -{ - EVP_MD_CTX_init(&ctx->i_ctx); - EVP_MD_CTX_init(&ctx->o_ctx); - EVP_MD_CTX_init(&ctx->md_ctx); -} +# include #endif +#include -#if !defined(HAVE_HMAC_CTX_CLEANUP) -void -HMAC_CTX_cleanup(HMAC_CTX *ctx) -{ - EVP_MD_CTX_cleanup(&ctx->i_ctx); - EVP_MD_CTX_cleanup(&ctx->o_ctx); - EVP_MD_CTX_cleanup(&ctx->md_ctx); - memset(ctx, 0, sizeof(HMAC_CTX)); -} -#endif +#include "openssl_missing.h" +/* added in 1.0.0 */ #if !defined(HAVE_EVP_CIPHER_CTX_COPY) /* * this function does not exist in OpenSSL yet... or ever?. @@ -103,11 +28,11 @@ HMAC_CTX_cleanup(HMAC_CTX *ctx) * tested on 0.9.7d. */ int -EVP_CIPHER_CTX_copy(EVP_CIPHER_CTX *out, EVP_CIPHER_CTX *in) +EVP_CIPHER_CTX_copy(EVP_CIPHER_CTX *out, const EVP_CIPHER_CTX *in) { memcpy(out, in, sizeof(EVP_CIPHER_CTX)); -#if defined(HAVE_ENGINE_ADD) && defined(HAVE_EVP_CIPHER_CTX_ENGINE) +#if !defined(OPENSSL_NO_ENGINE) if (in->engine) ENGINE_add(out->engine); if (in->cipher_data) { out->cipher_data = OPENSSL_malloc(in->cipher->ctx_size); @@ -119,222 +44,17 @@ EVP_CIPHER_CTX_copy(EVP_CIPHER_CTX *out, EVP_CIPHER_CTX *in) } #endif -#if !defined(HAVE_X509_CRL_SET_VERSION) -int -X509_CRL_set_version(X509_CRL *x, long version) -{ - if (x == NULL || x->crl == NULL) return 0; - if (x->crl->version == NULL) { - x->crl->version = M_ASN1_INTEGER_new(); - if (x->crl->version == NULL) return 0; - } - return ASN1_INTEGER_set(x->crl->version, version); -} -#endif - -#if !defined(HAVE_X509_CRL_SET_ISSUER_NAME) -int -X509_CRL_set_issuer_name(X509_CRL *x, X509_NAME *name) -{ - if (x == NULL || x->crl == NULL) return 0; - return X509_NAME_set(&x->crl->issuer, name); -} -#endif - -#if !defined(HAVE_X509_CRL_SORT) -int -X509_CRL_sort(X509_CRL *c) -{ - int i; - X509_REVOKED *r; - /* sort the data so it will be written in serial - * number order */ - sk_X509_REVOKED_sort(c->crl->revoked); - for (i=0; icrl->revoked); i++) { - r=sk_X509_REVOKED_value(c->crl->revoked, i); - r->sequence=i; - } - return 1; -} -#endif - -#if !defined(HAVE_X509_CRL_ADD0_REVOKED) -static int -OSSL_X509_REVOKED_cmp(const X509_REVOKED * const *a, const X509_REVOKED * const *b) -{ - return(ASN1_STRING_cmp( - (ASN1_STRING *)(*a)->serialNumber, - (ASN1_STRING *)(*b)->serialNumber)); -} - -int -X509_CRL_add0_revoked(X509_CRL *crl, X509_REVOKED *rev) -{ - X509_CRL_INFO *inf; - - inf = crl->crl; - if (!inf->revoked) - inf->revoked = sk_X509_REVOKED_new(OSSL_X509_REVOKED_cmp); - if (!inf->revoked || !sk_X509_REVOKED_push(inf->revoked, rev)) - return 0; - return 1; -} -#endif - -#if !defined(HAVE_BN_MOD_SQR) -int -BN_mod_sqr(BIGNUM *r, const BIGNUM *a, const BIGNUM *m, BN_CTX *ctx) -{ - if (!BN_sqr(r, (BIGNUM*)a, ctx)) return 0; - return BN_mod(r, r, m, ctx); -} -#endif - -#if !defined(HAVE_BN_MOD_ADD) || !defined(HAVE_BN_MOD_SUB) -int BN_nnmod(BIGNUM *r, const BIGNUM *m, const BIGNUM *d, BN_CTX *ctx) -{ - if (!BN_mod(r,m,d,ctx)) return 0; - if (!r->neg) return 1; - return (d->neg ? BN_sub : BN_add)(r, r, d); -} -#endif - -#if !defined(HAVE_BN_MOD_ADD) -int -BN_mod_add(BIGNUM *r, const BIGNUM *a, const BIGNUM *b, const BIGNUM *m, BN_CTX *ctx) -{ - if (!BN_add(r, a, b)) return 0; - return BN_nnmod(r, r, m, ctx); -} -#endif - -#if !defined(HAVE_BN_MOD_SUB) -int -BN_mod_sub(BIGNUM *r, const BIGNUM *a, const BIGNUM *b, const BIGNUM *m, BN_CTX *ctx) -{ - if (!BN_sub(r, a, b)) return 0; - return BN_nnmod(r, r, m, ctx); -} -#endif - -#if !defined(HAVE_BN_RAND_RANGE) || !defined(HAVE_BN_PSEUDO_RAND_RANGE) -static int -bn_rand_range(int pseudo, BIGNUM *r, BIGNUM *range) -{ - int (*bn_rand)(BIGNUM *, int, int, int) = pseudo ? BN_pseudo_rand : BN_rand; - int n; - - if (range->neg || BN_is_zero(range)) return 0; - - n = BN_num_bits(range); - - if (n == 1) { - if (!BN_zero(r)) return 0; - } else if (!BN_is_bit_set(range, n - 2) && !BN_is_bit_set(range, n - 3)) { - do { - if (!bn_rand(r, n + 1, -1, 0)) return 0; - if (BN_cmp(r ,range) >= 0) { - if (!BN_sub(r, r, range)) return 0; - if (BN_cmp(r, range) >= 0) - if (!BN_sub(r, r, range)) return 0; - } - } while (BN_cmp(r, range) >= 0); - } else { - do { - if (!bn_rand(r, n, -1, 0)) return 0; - } while (BN_cmp(r, range) >= 0); - } - - return 1; -} -#endif - -#if !defined(HAVE_BN_RAND_RANGE) -int -BN_rand_range(BIGNUM *r, BIGNUM *range) -{ - return bn_rand_range(0, r, range); -} -#endif - -#if !defined(HAVE_BN_PSEUDO_RAND_RANGE) -int -BN_pseudo_rand_range(BIGNUM *r, BIGNUM *range) -{ - return bn_rand_range(1, r, range); -} -#endif - -#if !defined(HAVE_CONF_GET1_DEFAULT_CONFIG_FILE) -#define OPENSSL_CONF "openssl.cnf" -char * -CONF_get1_default_config_file(void) -{ - char *file; - int len; - - file = getenv("OPENSSL_CONF"); - if (file) return BUF_strdup(file); - len = strlen(X509_get_default_cert_area()); -#ifndef OPENSSL_SYS_VMS - len++; -#endif - len += strlen(OPENSSL_CONF); - file = OPENSSL_malloc(len + 1); - if (!file) return NULL; - strcpy(file,X509_get_default_cert_area()); -#ifndef OPENSSL_SYS_VMS - strcat(file,"/"); -#endif - strcat(file,OPENSSL_CONF); - - return file; -} -#endif - -#if !defined(HAVE_PEM_DEF_CALLBACK) -#define OSSL_PASS_MIN_LENGTH 4 -int -PEM_def_callback(char *buf, int num, int w, void *key) +#if !defined(OPENSSL_NO_HMAC) +#if !defined(HAVE_HMAC_CTX_COPY) +void +HMAC_CTX_copy(HMAC_CTX *out, HMAC_CTX *in) { - int i,j; - const char *prompt; - - if (key) { - i = strlen(key); - i = (i > num) ? num : i; - memcpy(buf, key, i); - return i; - } - - prompt = EVP_get_pw_prompt(); - if (prompt == NULL) prompt = "Enter PEM pass phrase:"; - for (;;) { - i = EVP_read_pw_string(buf, num, prompt, w); - if (i != 0) { - memset(buf, 0, (unsigned int)num); - return(-1); - } - j = strlen(buf); - if (j < OSSL_PASS_MIN_LENGTH) { - fprintf(stderr, - "phrase is too short, needs to be at least %d chars\n", - OSSL_PASS_MIN_LENGTH); - } - else break; - } - return j; -} -#endif + if (!out || !in) return; + memcpy(out, in, sizeof(HMAC_CTX)); -#if !defined(HAVE_ASN1_PUT_EOC) -int -ASN1_put_eoc(unsigned char **pp) -{ - unsigned char *p = *pp; - *p++ = 0; - *p++ = 0; - *pp = p; - return 2; + EVP_MD_CTX_copy(&out->md_ctx, &in->md_ctx); + EVP_MD_CTX_copy(&out->i_ctx, &in->i_ctx); + EVP_MD_CTX_copy(&out->o_ctx, &in->o_ctx); } -#endif +#endif /* HAVE_HMAC_CTX_COPY */ +#endif /* NO_HMAC */ diff --git a/ext/openssl/openssl_missing.h b/ext/openssl/openssl_missing.h index b5bfd31e..0f82a180 100644 --- a/ext/openssl/openssl_missing.h +++ b/ext/openssl/openssl_missing.h @@ -10,124 +10,22 @@ #if !defined(_OSSL_OPENSSL_MISSING_H_) #define _OSSL_OPENSSL_MISSING_H_ -#ifndef TYPEDEF_D2I_OF -typedef char *d2i_of_void(); -#endif -#ifndef TYPEDEF_I2D_OF -typedef int i2d_of_void(); -#endif - -/* - * These functions are not included in headers of OPENSSL <= 0.9.6b - */ - -#if !defined(PEM_read_bio_DSAPublicKey) -# define PEM_read_bio_DSAPublicKey(bp,x,cb,u) (DSA *)PEM_ASN1_read_bio( \ - (d2i_of_void *)d2i_DSAPublicKey,PEM_STRING_DSA_PUBLIC,(bp),(void **)(x),(cb),(u)) -#endif - -#if !defined(PEM_write_bio_DSAPublicKey) -# define PEM_write_bio_DSAPublicKey(bp,x) \ - PEM_ASN1_write_bio((i2d_of_void *)i2d_DSAPublicKey,\ - PEM_STRING_DSA_PUBLIC,\ - (bp),(char *)(x), NULL, NULL, 0, NULL, NULL) -#endif - -#if !defined(DSAPrivateKey_dup) -# define DSAPrivateKey_dup(dsa) (DSA *)ASN1_dup((i2d_of_void *)i2d_DSAPrivateKey, \ - (d2i_of_void *)d2i_DSAPrivateKey,(char *)(dsa)) -#endif - -#if !defined(DSAPublicKey_dup) -# define DSAPublicKey_dup(dsa) (DSA *)ASN1_dup((i2d_of_void *)i2d_DSAPublicKey, \ - (d2i_of_void *)d2i_DSAPublicKey,(char *)(dsa)) -#endif - -#if !defined(X509_REVOKED_dup) -# define X509_REVOKED_dup(rev) (X509_REVOKED *)ASN1_dup((i2d_of_void *)i2d_X509_REVOKED, \ - (d2i_of_void *)d2i_X509_REVOKED, (char *)(rev)) -#endif - -#if !defined(PKCS7_SIGNER_INFO_dup) -# define PKCS7_SIGNER_INFO_dup(si) (PKCS7_SIGNER_INFO *)ASN1_dup((i2d_of_void *)i2d_PKCS7_SIGNER_INFO, \ - (d2i_of_void *)d2i_PKCS7_SIGNER_INFO, (char *)(si)) -#endif - -#if !defined(PKCS7_RECIP_INFO_dup) -# define PKCS7_RECIP_INFO_dup(ri) (PKCS7_RECIP_INFO *)ASN1_dup((i2d_of_void *)i2d_PKCS7_RECIP_INFO, \ - (d2i_of_void *)d2i_PKCS7_RECIP_INFO, (char *)(ri)) -#endif - -#if !defined(HAVE_HMAC_CTX_INIT) -void HMAC_CTX_init(HMAC_CTX *ctx); +/* added in 1.0.0 */ +#if !defined(HAVE_EVP_CIPHER_CTX_COPY) +int EVP_CIPHER_CTX_copy(EVP_CIPHER_CTX *out, const EVP_CIPHER_CTX *in); #endif #if !defined(HAVE_HMAC_CTX_COPY) void HMAC_CTX_copy(HMAC_CTX *out, HMAC_CTX *in); #endif -#if !defined(HAVE_HMAC_CTX_CLEANUP) -void HMAC_CTX_cleanup(HMAC_CTX *ctx); -#endif - -#if !defined(HAVE_EVP_MD_CTX_CREATE) -EVP_MD_CTX *EVP_MD_CTX_create(void); -#endif - -#if !defined(HAVE_EVP_MD_CTX_INIT) -void EVP_MD_CTX_init(EVP_MD_CTX *ctx); -#endif - -#if !defined(HAVE_EVP_MD_CTX_CLEANUP) -int EVP_MD_CTX_cleanup(EVP_MD_CTX *ctx); -#endif - -#if !defined(HAVE_EVP_MD_CTX_DESTROY) -void EVP_MD_CTX_destroy(EVP_MD_CTX *ctx); -#endif - -#if !defined(HAVE_EVP_CIPHER_CTX_COPY) -int EVP_CIPHER_CTX_copy(EVP_CIPHER_CTX *out, EVP_CIPHER_CTX *in); -#endif - -#if !defined(HAVE_EVP_DIGESTINIT_EX) -# define EVP_DigestInit_ex(ctx, md, engine) EVP_DigestInit((ctx), (md)) -#endif -#if !defined(HAVE_EVP_DIGESTFINAL_EX) -# define EVP_DigestFinal_ex(ctx, buf, len) EVP_DigestFinal((ctx), (buf), (len)) -#endif - -#if !defined(HAVE_EVP_CIPHERINIT_EX) -# define EVP_CipherInit_ex(ctx, type, impl, key, iv, enc) EVP_CipherInit((ctx), (type), (key), (iv), (enc)) -#endif -#if !defined(HAVE_EVP_CIPHERFINAL_EX) -# define EVP_CipherFinal_ex(ctx, outm, outl) EVP_CipherFinal((ctx), (outm), (outl)) -#endif - -#if !defined(EVP_CIPHER_name) -# define EVP_CIPHER_name(e) OBJ_nid2sn(EVP_CIPHER_nid(e)) -#endif - -#if !defined(EVP_MD_name) -# define EVP_MD_name(e) OBJ_nid2sn(EVP_MD_type(e)) -#endif - -#if !defined(HAVE_EVP_HMAC_INIT_EX) -# define HMAC_Init_ex(ctx, key, len, digest, engine) HMAC_Init((ctx), (key), (len), (digest)) -#endif - -#if !defined(PKCS7_is_detached) -# define PKCS7_is_detached(p7) (PKCS7_type_is_signed(p7) && PKCS7_get_detached(p7)) -#endif - -#if !defined(PKCS7_type_is_encrypted) -# define PKCS7_type_is_encrypted(a) (OBJ_obj2nid((a)->type) == NID_pkcs7_encrypted) -#endif - -#if !defined(HAVE_OPENSSL_CLEANSE) -#define OPENSSL_cleanse(p, l) memset((p), 0, (l)) +/* added in 1.0.2 */ +#if !defined(HAVE_X509_REVOKED_DUP) +# define X509_REVOKED_dup(rev) (X509_REVOKED *)ASN1_dup((i2d_of_void *)i2d_X509_REVOKED, \ + (d2i_of_void *)d2i_X509_REVOKED, (char *)(rev)) #endif +/* added in 1.1.0 */ #if !defined(HAVE_X509_STORE_GET_EX_DATA) # define X509_STORE_get_ex_data(x, idx) \ CRYPTO_get_ex_data(&(x)->ex_data, (idx)) @@ -141,52 +39,4 @@ int EVP_CIPHER_CTX_copy(EVP_CIPHER_CTX *out, EVP_CIPHER_CTX *in); (newf), (dupf), (freef)) #endif -#if !defined(HAVE_X509_CRL_SET_VERSION) -int X509_CRL_set_version(X509_CRL *x, long version); -#endif - -#if !defined(HAVE_X509_CRL_SET_ISSUER_NAME) -int X509_CRL_set_issuer_name(X509_CRL *x, X509_NAME *name); -#endif - -#if !defined(HAVE_X509_CRL_SORT) -int X509_CRL_sort(X509_CRL *c); -#endif - -#if !defined(HAVE_X509_CRL_ADD0_REVOKED) -int X509_CRL_add0_revoked(X509_CRL *crl, X509_REVOKED *rev); -#endif - -#if !defined(HAVE_BN_MOD_SQR) -int BN_mod_sqr(BIGNUM *r, const BIGNUM *a, const BIGNUM *m, BN_CTX *ctx); -#endif - -#if !defined(HAVE_BN_MOD_ADD) -int BN_mod_add(BIGNUM *r, const BIGNUM *a, const BIGNUM *b, const BIGNUM *m, BN_CTX *ctx); -#endif - -#if !defined(HAVE_BN_MOD_SUB) -int BN_mod_sub(BIGNUM *r, const BIGNUM *a, const BIGNUM *b, const BIGNUM *m, BN_CTX *ctx); -#endif - -#if !defined(HAVE_BN_RAND_RANGE) -int BN_rand_range(BIGNUM *r, BIGNUM *range); -#endif - -#if !defined(HAVE_BN_PSEUDO_RAND_RANGE) -int BN_pseudo_rand_range(BIGNUM *r, BIGNUM *range); -#endif - -#if !defined(HAVE_CONF_GET1_DEFAULT_CONFIG_FILE) -char *CONF_get1_default_config_file(void); -#endif - -#if !defined(HAVE_PEM_DEF_CALLBACK) -int PEM_def_callback(char *buf, int num, int w, void *key); -#endif - -#if !defined(HAVE_ASN1_PUT_EOC) -int ASN1_put_eoc(unsigned char **pp); -#endif - #endif /* _OSSL_OPENSSL_MISSING_H_ */ diff --git a/ext/openssl/ossl.c b/ext/openssl/ossl.c index c06a579c..3654b1e8 100644 --- a/ext/openssl/ossl.c +++ b/ext/openssl/ossl.c @@ -339,11 +339,7 @@ ossl_make_error(VALUE exc, const char *fmt, va_list args) const char *msg; long e; -#ifdef HAVE_ERR_PEEK_LAST_ERROR e = ERR_peek_last_error(); -#else - e = ERR_peek_error(); -#endif if (fmt) { str = rb_vsprintf(fmt, args); } diff --git a/ext/openssl/ossl.h b/ext/openssl/ossl.h index 4a538e9b..2317fa8b 100644 --- a/ext/openssl/ossl.h +++ b/ext/openssl/ossl.h @@ -27,11 +27,6 @@ #include #include -/* - * Check the OpenSSL version - * The only supported are: - * OpenSSL >= 0.9.7 - */ #include #ifdef HAVE_ASSERT_H @@ -42,7 +37,6 @@ #if defined(_WIN32) && !defined(LIBRESSL_VERSION_NUMBER) # include -# define OSSL_NO_CONF_API 1 # if !defined(OPENSSL_SYS_WIN32) # define OPENSSL_SYS_WIN32 1 # endif @@ -62,14 +56,10 @@ #if !defined(_WIN32) # include #endif -#undef X509_NAME -#undef PKCS7_SIGNER_INFO -#if defined(HAVE_OPENSSL_ENGINE_H) && defined(HAVE_EVP_CIPHER_CTX_ENGINE) -# define OSSL_ENGINE_ENABLED +#if !defined(OPENSSL_NO_ENGINE) # include #endif -#if defined(HAVE_OPENSSL_OCSP_H) -# define OSSL_OCSP_ENABLED +#if !defined(OPENSSL_NO_OCSP) # include #endif @@ -106,13 +96,6 @@ extern VALUE eOSSLError; }\ } while (0) -/* - * Compatibility - */ -#if OPENSSL_VERSION_NUMBER >= 0x10000000L -#define STACK _STACK -#endif - /* * String to HEXString conversion */ diff --git a/ext/openssl/ossl_asn1.c b/ext/openssl/ossl_asn1.c index cae6176c..e77adbf9 100644 --- a/ext/openssl/ossl_asn1.c +++ b/ext/openssl/ossl_asn1.c @@ -211,19 +211,6 @@ static ID sIMPLICIT, sEXPLICIT; static ID sUNIVERSAL, sAPPLICATION, sCONTEXT_SPECIFIC, sPRIVATE; static ID sivVALUE, sivTAG, sivTAG_CLASS, sivTAGGING, sivINFINITE_LENGTH, sivUNUSED_BITS; -/* - * We need to implement these for backward compatibility - * reasons, behavior of ASN1_put_object and ASN1_object_size - * for infinite length values is different in OpenSSL <= 0.9.7 - */ -#if OPENSSL_VERSION_NUMBER < 0x00908000L -#define ossl_asn1_object_size(cons, len, tag) (cons) == 2 ? (len) + ASN1_object_size((cons), 0, (tag)) : ASN1_object_size((cons), (len), (tag)) -#define ossl_asn1_put_object(pp, cons, len, tag, xc) (cons) == 2 ? ASN1_put_object((pp), (cons), 0, (tag), (xc)) : ASN1_put_object((pp), (cons), (len), (tag), (xc)) -#else -#define ossl_asn1_object_size(cons, len, tag) ASN1_object_size((cons), (len), (tag)) -#define ossl_asn1_put_object(pp, cons, len, tag, xc) ASN1_put_object((pp), (cons), (len), (tag), (xc)) -#endif - /* * Ruby to ASN1 converters */ @@ -233,11 +220,7 @@ obj_to_asn1bool(VALUE obj) if (NIL_P(obj)) ossl_raise(rb_eTypeError, "Can't convert nil into Boolean"); -#if OPENSSL_VERSION_NUMBER < 0x00907000L - return RTEST(obj) ? 0xff : 0x100; -#else return RTEST(obj) ? 0xff : 0x0; -#endif } static ASN1_INTEGER* @@ -778,11 +761,11 @@ ossl_asn1data_to_der(VALUE self) if (inf_length == Qtrue) { is_cons = 2; } - if((length = ossl_asn1_object_size(is_cons, RSTRING_LENINT(value), tag)) <= 0) + if((length = ASN1_object_size(is_cons, RSTRING_LENINT(value), tag)) <= 0) ossl_raise(eASN1Error, NULL); der = rb_str_new(0, length); p = (unsigned char *)RSTRING_PTR(der); - ossl_asn1_put_object(&p, is_cons, RSTRING_LENINT(value), tag, tag_class); + ASN1_put_object(&p, is_cons, RSTRING_LENINT(value), tag, tag_class); memcpy(p, RSTRING_PTR(value), RSTRING_LEN(value)); p += RSTRING_LEN(value); ossl_str_adjust(der, p); @@ -1184,30 +1167,6 @@ ossl_asn1eoc_initialize(VALUE self) { return self; } -static int -ossl_i2d_ASN1_TYPE(ASN1_TYPE *a, unsigned char **pp) -{ -#if OPENSSL_VERSION_NUMBER < 0x00907000L - if(!a) return 0; - if(a->type == V_ASN1_BOOLEAN) - return i2d_ASN1_BOOLEAN(a->value.boolean, pp); -#endif - return i2d_ASN1_TYPE(a, pp); -} - -static void -ossl_ASN1_TYPE_free(ASN1_TYPE *a) -{ -#if OPENSSL_VERSION_NUMBER < 0x00907000L - if(!a) return; - if(a->type == V_ASN1_BOOLEAN){ - OPENSSL_free(a); - return; - } -#endif - ASN1_TYPE_free(a); -} - /* * call-seq: * asn1.to_der => DER-encoded String @@ -1228,22 +1187,22 @@ ossl_asn1prim_to_der(VALUE self) explicit = ossl_asn1_is_explicit(self); asn1 = ossl_asn1_get_asn1type(self); - len = ossl_asn1_object_size(1, ossl_i2d_ASN1_TYPE(asn1, NULL), tn); + len = ASN1_object_size(1, i2d_ASN1_TYPE(asn1, NULL), tn); if(!(buf = OPENSSL_malloc(len))){ - ossl_ASN1_TYPE_free(asn1); + ASN1_TYPE_free(asn1); ossl_raise(eASN1Error, "cannot alloc buffer"); } p = buf; if (tc == V_ASN1_UNIVERSAL) { - ossl_i2d_ASN1_TYPE(asn1, &p); + i2d_ASN1_TYPE(asn1, &p); } else if (explicit) { - ossl_asn1_put_object(&p, 1, ossl_i2d_ASN1_TYPE(asn1, NULL), tn, tc); - ossl_i2d_ASN1_TYPE(asn1, &p); + ASN1_put_object(&p, 1, i2d_ASN1_TYPE(asn1, NULL), tn, tc); + i2d_ASN1_TYPE(asn1, &p); } else { - ossl_i2d_ASN1_TYPE(asn1, &p); + i2d_ASN1_TYPE(asn1, &p); *buf = tc | tn | (*buf & V_ASN1_CONSTRUCTED); } - ossl_ASN1_TYPE_free(asn1); + ASN1_TYPE_free(asn1); reallen = p - buf; assert(reallen <= len); str = ossl_buf2str((char *)buf, rb_long2int(reallen)); /* buf will be free in ossl_buf2str */ @@ -1309,19 +1268,19 @@ ossl_asn1cons_to_der(VALUE self) explicit = ossl_asn1_is_explicit(self); value = join_der(ossl_asn1_get_value(self)); - seq_len = ossl_asn1_object_size(constructed, RSTRING_LENINT(value), tag); - length = ossl_asn1_object_size(constructed, seq_len, tn); + seq_len = ASN1_object_size(constructed, RSTRING_LENINT(value), tag); + length = ASN1_object_size(constructed, seq_len, tn); str = rb_str_new(0, length); p = (unsigned char *)RSTRING_PTR(str); if(tc == V_ASN1_UNIVERSAL) - ossl_asn1_put_object(&p, constructed, RSTRING_LENINT(value), tn, tc); + ASN1_put_object(&p, constructed, RSTRING_LENINT(value), tn, tc); else{ if(explicit){ - ossl_asn1_put_object(&p, constructed, seq_len, tn, tc); - ossl_asn1_put_object(&p, constructed, RSTRING_LENINT(value), tag, V_ASN1_UNIVERSAL); + ASN1_put_object(&p, constructed, seq_len, tn, tc); + ASN1_put_object(&p, constructed, RSTRING_LENINT(value), tag, V_ASN1_UNIVERSAL); } else{ - ossl_asn1_put_object(&p, constructed, RSTRING_LENINT(value), tn, tc); + ASN1_put_object(&p, constructed, RSTRING_LENINT(value), tn, tc); } } memcpy(p, RSTRING_PTR(value), RSTRING_LEN(value)); diff --git a/ext/openssl/ossl_cipher.c b/ext/openssl/ossl_cipher.c index 43a8effa..d56b3411 100644 --- a/ext/openssl/ossl_cipher.c +++ b/ext/openssl/ossl_cipher.c @@ -158,16 +158,13 @@ ossl_cipher_copy(VALUE self, VALUE other) return self; } -#ifdef HAVE_OBJ_NAME_DO_ALL_SORTED static void* add_cipher_name_to_ary(const OBJ_NAME *name, VALUE ary) { rb_ary_push(ary, rb_str_new2(name->name)); return NULL; } -#endif -#ifdef HAVE_OBJ_NAME_DO_ALL_SORTED /* * call-seq: * OpenSSL::Cipher.ciphers -> array[string...] @@ -186,9 +183,6 @@ ossl_s_ciphers(VALUE self) return ary; } -#else -#define ossl_s_ciphers rb_f_notimplement -#endif /* * call-seq: @@ -723,7 +717,6 @@ ossl_cipher_set_key_length(VALUE self, VALUE key_length) return key_length; } -#if defined(HAVE_EVP_CIPHER_CTX_SET_PADDING) /* * call-seq: * cipher.padding = integer -> integer @@ -745,9 +738,6 @@ ossl_cipher_set_padding(VALUE self, VALUE padding) ossl_raise(eCipherError, NULL); return padding; } -#else -#define ossl_cipher_set_padding rb_f_notimplement -#endif #define CIPHER_0ARG_INT(func) \ static VALUE \ diff --git a/ext/openssl/ossl_engine.c b/ext/openssl/ossl_engine.c index 48847e67..f84b1cff 100644 --- a/ext/openssl/ossl_engine.c +++ b/ext/openssl/ossl_engine.c @@ -9,7 +9,7 @@ */ #include "ossl.h" -#if defined(OSSL_ENGINE_ENABLED) +#if !defined(OPENSSL_NO_ENGINE) #define NewEngine(klass) \ TypedData_Wrap_Struct((klass), &ossl_engine_type, 0) @@ -165,9 +165,7 @@ ossl_engine_s_load(int argc, VALUE *argv, VALUE klass) static VALUE ossl_engine_s_cleanup(VALUE self) { -#if defined(HAVE_ENGINE_CLEANUP) ENGINE_cleanup(); -#endif return Qnil; } @@ -296,7 +294,6 @@ ossl_engine_finish(VALUE self) return Qnil; } -#if defined(HAVE_ENGINE_GET_CIPHER) /* Document-method: OpenSSL::Engine#cipher * * call-seq: @@ -329,11 +326,7 @@ ossl_engine_get_cipher(VALUE self, VALUE name) return ossl_cipher_new(ciph); } -#else -#define ossl_engine_get_cipher rb_f_notimplement -#endif -#if defined(HAVE_ENGINE_GET_DIGEST) /* Document-method: OpenSSL::Engine#digest * * call-seq: @@ -366,9 +359,6 @@ ossl_engine_get_digest(VALUE self, VALUE name) return ossl_digest_new(md); } -#else -#define ossl_engine_get_digest rb_f_notimplement -#endif /* Document-method: OpenSSL::Engine#load_private_key * @@ -392,11 +382,7 @@ ossl_engine_load_privkey(int argc, VALUE *argv, VALUE self) sid = NIL_P(id) ? NULL : StringValueCStr(id); sdata = NIL_P(data) ? NULL : StringValueCStr(data); GetEngine(self, e); -#if OPENSSL_VERSION_NUMBER < 0x00907000L - pkey = ENGINE_load_private_key(e, sid, sdata); -#else pkey = ENGINE_load_private_key(e, sid, NULL, sdata); -#endif if (!pkey) ossl_raise(eEngineError, NULL); obj = ossl_pkey_new(pkey); OSSL_PKEY_SET_PRIVATE(obj); @@ -426,11 +412,7 @@ ossl_engine_load_pubkey(int argc, VALUE *argv, VALUE self) sid = NIL_P(id) ? NULL : StringValueCStr(id); sdata = NIL_P(data) ? NULL : StringValueCStr(data); GetEngine(self, e); -#if OPENSSL_VERSION_NUMBER < 0x00907000L - pkey = ENGINE_load_public_key(e, sid, sdata); -#else pkey = ENGINE_load_public_key(e, sid, NULL, sdata); -#endif if (!pkey) ossl_raise(eEngineError, NULL); return ossl_pkey_new(pkey); @@ -579,12 +561,8 @@ Init_ossl_engine(void) #ifdef ENGINE_METHOD_BN_MOD_EXP_CRT DefEngineConst(METHOD_BN_MOD_EXP_CRT); #endif -#ifdef ENGINE_METHOD_CIPHERS DefEngineConst(METHOD_CIPHERS); -#endif -#ifdef ENGINE_METHOD_DIGESTS DefEngineConst(METHOD_DIGESTS); -#endif DefEngineConst(METHOD_ALL); DefEngineConst(METHOD_NONE); } diff --git a/ext/openssl/ossl_ocsp.c b/ext/openssl/ossl_ocsp.c index 02b67429..9f44bc20 100644 --- a/ext/openssl/ossl_ocsp.c +++ b/ext/openssl/ossl_ocsp.c @@ -10,7 +10,7 @@ */ #include "ossl.h" -#if defined(OSSL_OCSP_ENABLED) +#if !defined(OPENSSL_NO_OCSP) #define NewOCSPReq(klass) \ TypedData_Wrap_Struct((klass), &ossl_ocsp_request_type, 0) @@ -1250,7 +1250,7 @@ Init_ossl_ocsp(void) rb_define_const(mOCSP, "V_RESPID_KEY", INT2NUM(V_OCSP_RESPID_KEY)); } -#else /* ! OSSL_OCSP_ENABLED */ +#else void Init_ossl_ocsp(void) { diff --git a/ext/openssl/ossl_ocsp.h b/ext/openssl/ossl_ocsp.h index c5064fbc..21e2c99a 100644 --- a/ext/openssl/ossl_ocsp.h +++ b/ext/openssl/ossl_ocsp.h @@ -11,7 +11,7 @@ #if !defined(_OSSL_OCSP_H_) #define _OSSL_OCSP_H_ -#if defined(OSSL_OCSP_ENABLED) +#if !defined(OPENSSL_NO_OCSP) extern VALUE mOCSP; extern VALUE cOPCSReq; extern VALUE cOPCSRes; diff --git a/ext/openssl/ossl_pkcs5.c b/ext/openssl/ossl_pkcs5.c index 73d989e1..56ed65fb 100644 --- a/ext/openssl/ossl_pkcs5.c +++ b/ext/openssl/ossl_pkcs5.c @@ -48,7 +48,6 @@ ossl_pkcs5_pbkdf2_hmac(VALUE self, VALUE pass, VALUE salt, VALUE iter, VALUE key #endif -#ifdef HAVE_PKCS5_PBKDF2_HMAC_SHA1 /* * call-seq: * PKCS5.pbkdf2_hmac_sha1(pass, salt, iter, keylen) => string @@ -81,9 +80,6 @@ ossl_pkcs5_pbkdf2_hmac_sha1(VALUE self, VALUE pass, VALUE salt, VALUE iter, VALU return str; } -#else -#define ossl_pkcs5_pbkdf2_hmac_sha1 rb_f_notimplement -#endif void Init_ossl_pkcs5(void) diff --git a/ext/openssl/ossl_pkcs7.c b/ext/openssl/ossl_pkcs7.c index 10332d9e..5b7c07de 100644 --- a/ext/openssl/ossl_pkcs7.c +++ b/ext/openssl/ossl_pkcs7.c @@ -127,6 +127,22 @@ static const rb_data_type_t ossl_pkcs7_recip_info_type = { * Public * (MADE PRIVATE UNTIL SOMEBODY WILL NEED THEM) */ +static PKCS7_SIGNER_INFO * +ossl_PKCS7_SIGNER_INFO_dup(const PKCS7_SIGNER_INFO *si) +{ + return (PKCS7_SIGNER_INFO *)ASN1_dup((i2d_of_void *)i2d_PKCS7_SIGNER_INFO, + (d2i_of_void *)d2i_PKCS7_SIGNER_INFO, + (char *)si); +} + +static PKCS7_RECIP_INFO * +ossl_PKCS7_RECIP_INFO_dup(const PKCS7_RECIP_INFO *si) +{ + return (PKCS7_RECIP_INFO *)ASN1_dup((i2d_of_void *)i2d_PKCS7_RECIP_INFO, + (d2i_of_void *)d2i_PKCS7_RECIP_INFO, + (char *)si); +} + static VALUE ossl_pkcs7si_new(PKCS7_SIGNER_INFO *p7si) { @@ -134,7 +150,7 @@ ossl_pkcs7si_new(PKCS7_SIGNER_INFO *p7si) VALUE obj; obj = NewPKCS7si(cPKCS7Signer); - pkcs7 = p7si ? PKCS7_SIGNER_INFO_dup(p7si) : PKCS7_SIGNER_INFO_new(); + pkcs7 = p7si ? ossl_PKCS7_SIGNER_INFO_dup(p7si) : PKCS7_SIGNER_INFO_new(); if (!pkcs7) ossl_raise(ePKCS7Error, NULL); SetPKCS7si(obj, pkcs7); @@ -147,7 +163,7 @@ DupPKCS7SignerPtr(VALUE obj) PKCS7_SIGNER_INFO *p7si, *pkcs7; SafeGetPKCS7si(obj, p7si); - if (!(pkcs7 = PKCS7_SIGNER_INFO_dup(p7si))) { + if (!(pkcs7 = ossl_PKCS7_SIGNER_INFO_dup(p7si))) { ossl_raise(ePKCS7Error, NULL); } @@ -161,7 +177,7 @@ ossl_pkcs7ri_new(PKCS7_RECIP_INFO *p7ri) VALUE obj; obj = NewPKCS7ri(cPKCS7Recipient); - pkcs7 = p7ri ? PKCS7_RECIP_INFO_dup(p7ri) : PKCS7_RECIP_INFO_new(); + pkcs7 = p7ri ? ossl_PKCS7_RECIP_INFO_dup(p7ri) : PKCS7_RECIP_INFO_new(); if (!pkcs7) ossl_raise(ePKCS7Error, NULL); SetPKCS7ri(obj, pkcs7); @@ -174,7 +190,7 @@ DupPKCS7RecipientPtr(VALUE obj) PKCS7_RECIP_INFO *p7ri, *pkcs7; SafeGetPKCS7ri(obj, p7ri); - if (!(pkcs7 = PKCS7_RECIP_INFO_dup(p7ri))) { + if (!(pkcs7 = ossl_PKCS7_RECIP_INFO_dup(p7ri))) { ossl_raise(ePKCS7Error, NULL); } diff --git a/ext/openssl/ossl_pkey.c b/ext/openssl/ossl_pkey.c index fea90d7a..e4ae549f 100644 --- a/ext/openssl/ossl_pkey.c +++ b/ext/openssl/ossl_pkey.c @@ -20,20 +20,6 @@ ID id_private_q; /* * callback for generating keys */ -void -ossl_generate_cb(int p, int n, void *arg) -{ - VALUE ary; - - ary = rb_ary_new2(2); - rb_ary_store(ary, 0, INT2NUM(p)); - rb_ary_store(ary, 1, INT2NUM(n)); - - rb_yield(ary); -} - -#if HAVE_BN_GENCB -/* OpenSSL 2nd version of GN generation callback */ int ossl_generate_cb_2(int p, int n, BN_GENCB *cb) { @@ -66,7 +52,6 @@ ossl_generate_cb_stop(void *ptr) struct ossl_generate_cb_arg *arg = (struct ossl_generate_cb_arg *)ptr; arg->stop = 1; } -#endif static void ossl_evp_pkey_free(void *ptr) diff --git a/ext/openssl/ossl_pkey.h b/ext/openssl/ossl_pkey.h index 7288d5af..b806d63e 100644 --- a/ext/openssl/ossl_pkey.h +++ b/ext/openssl/ossl_pkey.h @@ -40,9 +40,6 @@ extern const rb_data_type_t ossl_evp_pkey_type; GetPKey((obj), (pkey)); \ } while (0) -void ossl_generate_cb(int, int, void *); -#define HAVE_BN_GENCB defined(HAVE_RSA_GENERATE_KEY_EX) || defined(HAVE_DH_GENERATE_PARAMETERS_EX) || defined(HAVE_DSA_GENERATE_PARAMETERS_EX) -#if HAVE_BN_GENCB struct ossl_generate_cb_arg { int yield; int stop; @@ -50,7 +47,6 @@ struct ossl_generate_cb_arg { }; int ossl_generate_cb_2(int p, int n, BN_GENCB *cb); void ossl_generate_cb_stop(void *ptr); -#endif VALUE ossl_pkey_new(EVP_PKEY *); VALUE ossl_pkey_new_from_file(VALUE); diff --git a/ext/openssl/ossl_pkey_dh.c b/ext/openssl/ossl_pkey_dh.c index 19c517fd..fd2b8049 100644 --- a/ext/openssl/ossl_pkey_dh.c +++ b/ext/openssl/ossl_pkey_dh.c @@ -20,7 +20,7 @@ #define DH_HAS_PRIVATE(dh) ((dh)->priv_key) -#ifdef OSSL_ENGINE_ENABLED +#if !defined(OPENSSL_NO_ENGINE) # define DH_PRIVATE(dh) (DH_HAS_PRIVATE(dh) || (dh)->engine) #else # define DH_PRIVATE(dh) DH_HAS_PRIVATE(dh) @@ -82,7 +82,6 @@ ossl_dh_new(EVP_PKEY *pkey) /* * Private */ -#if defined(HAVE_DH_GENERATE_PARAMETERS_EX) && HAVE_BN_GENCB struct dh_blocking_gen_arg { DH *dh; int size; @@ -98,12 +97,10 @@ dh_blocking_gen(void *arg) gen->result = DH_generate_parameters_ex(gen->dh, gen->size, gen->gen, gen->cb); return 0; } -#endif static DH * dh_generate(int size, int gen) { -#if defined(HAVE_DH_GENERATE_PARAMETERS_EX) && HAVE_BN_GENCB BN_GENCB cb; struct ossl_generate_cb_arg cb_arg; struct dh_blocking_gen_arg gen_arg; @@ -136,12 +133,6 @@ dh_generate(int size, int gen) } return 0; } -#else - DH *dh; - - dh = DH_generate_parameters(size, gen, rb_block_given_p() ? ossl_generate_cb : NULL, NULL); - if (!dh) return 0; -#endif if (!DH_generate_key(dh)) { DH_free(dh); diff --git a/ext/openssl/ossl_pkey_dsa.c b/ext/openssl/ossl_pkey_dsa.c index 281d3a00..29033809 100644 --- a/ext/openssl/ossl_pkey_dsa.c +++ b/ext/openssl/ossl_pkey_dsa.c @@ -76,7 +76,6 @@ ossl_dsa_new(EVP_PKEY *pkey) /* * Private */ -#if defined(HAVE_DSA_GENERATE_PARAMETERS_EX) && HAVE_BN_GENCB struct dsa_blocking_gen_arg { DSA *dsa; int size; @@ -95,12 +94,10 @@ dsa_blocking_gen(void *arg) gen->result = DSA_generate_parameters_ex(gen->dsa, gen->size, gen->seed, gen->seed_len, gen->counter, gen->h, gen->cb); return 0; } -#endif static DSA * dsa_generate(int size) { -#if defined(HAVE_DSA_GENERATE_PARAMETERS_EX) && HAVE_BN_GENCB BN_GENCB cb; struct ossl_generate_cb_arg cb_arg; struct dsa_blocking_gen_arg gen_arg; @@ -145,19 +142,6 @@ dsa_generate(int size) } return 0; } -#else - DSA *dsa; - unsigned char seed[20]; - int seed_len = 20, counter; - unsigned long h; - - if (RAND_bytes(seed, seed_len) <= 0) { - return 0; - } - dsa = DSA_generate_parameters(size, seed, seed_len, &counter, &h, - rb_block_given_p() ? ossl_generate_cb : NULL, NULL); - if(!dsa) return 0; -#endif if (!DSA_generate_key(dsa)) { DSA_free(dsa); @@ -246,7 +230,10 @@ ossl_dsa_initialize(int argc, VALUE *argv, VALUE self) } if (!dsa) { OSSL_BIO_reset(in); +#define PEM_read_bio_DSAPublicKey(bp,x,cb,u) (DSA *)PEM_ASN1_read_bio( \ + (d2i_of_void *)d2i_DSAPublicKey, PEM_STRING_DSA_PUBLIC, (bp), (void **)(x), (cb), (u)) dsa = PEM_read_bio_DSAPublicKey(in, NULL, NULL, NULL); +#undef PEM_read_bio_DSAPublicKey } BIO_free(in); if (!dsa) { @@ -460,7 +447,10 @@ ossl_dsa_to_public_key(VALUE self) GetPKeyDSA(self, pkey); /* err check performed by dsa_instance */ +#define DSAPublicKey_dup(dsa) (DSA *)ASN1_dup( \ + (i2d_of_void *)i2d_DSAPublicKey, (d2i_of_void *)d2i_DSAPublicKey, (char *)(dsa)) dsa = DSAPublicKey_dup(pkey->pkey.dsa); +#undef DSAPublicKey_dup obj = dsa_instance(CLASS_OF(self), dsa); if (obj == Qfalse) { DSA_free(dsa); diff --git a/ext/openssl/ossl_pkey_ec.c b/ext/openssl/ossl_pkey_ec.c index 9210ae48..958e7105 100644 --- a/ext/openssl/ossl_pkey_ec.c +++ b/ext/openssl/ossl_pkey_ec.c @@ -1658,9 +1658,7 @@ void Init_ossl_ec(void) ID_compressed = rb_intern("compressed"); ID_hybrid = rb_intern("hybrid"); -#ifdef OPENSSL_EC_NAMED_CURVE rb_define_const(cEC, "NAMED_CURVE", ULONG2NUM(OPENSSL_EC_NAMED_CURVE)); -#endif rb_define_singleton_method(cEC, "builtin_curves", ossl_s_builtin_curves, 0); diff --git a/ext/openssl/ossl_pkey_rsa.c b/ext/openssl/ossl_pkey_rsa.c index 5219dbed..9cb50893 100644 --- a/ext/openssl/ossl_pkey_rsa.c +++ b/ext/openssl/ossl_pkey_rsa.c @@ -77,7 +77,6 @@ ossl_rsa_new(EVP_PKEY *pkey) /* * Private */ -#if defined(HAVE_RSA_GENERATE_KEY_EX) && HAVE_BN_GENCB struct rsa_blocking_gen_arg { RSA *rsa; BIGNUM *e; @@ -93,12 +92,10 @@ rsa_blocking_gen(void *arg) gen->result = RSA_generate_key_ex(gen->rsa, gen->size, gen->e, gen->cb); return 0; } -#endif static RSA * rsa_generate(int size, unsigned long exp) { -#if defined(HAVE_RSA_GENERATE_KEY_EX) && HAVE_BN_GENCB int i; BN_GENCB cb; struct ossl_generate_cb_arg cb_arg; @@ -149,9 +146,6 @@ rsa_generate(int size, unsigned long exp) BN_free(e); return rsa; -#else - return RSA_generate_key(size, exp, rb_block_given_p() ? ossl_generate_cb : NULL, NULL); -#endif } /* diff --git a/ext/openssl/ossl_ssl.c b/ext/openssl/ossl_ssl.c index cf23f5c1..c31a32f3 100644 --- a/ext/openssl/ossl_ssl.c +++ b/ext/openssl/ossl_ssl.c @@ -90,26 +90,22 @@ static const struct { OSSL_SSL_METHOD_ENTRY(TLSv1), OSSL_SSL_METHOD_ENTRY(TLSv1_server), OSSL_SSL_METHOD_ENTRY(TLSv1_client), -#if defined(HAVE_TLSV1_2_METHOD) && defined(HAVE_TLSV1_2_SERVER_METHOD) && \ - defined(HAVE_TLSV1_2_CLIENT_METHOD) +#if defined(HAVE_TLSV1_2_METHOD) OSSL_SSL_METHOD_ENTRY(TLSv1_2), OSSL_SSL_METHOD_ENTRY(TLSv1_2_server), OSSL_SSL_METHOD_ENTRY(TLSv1_2_client), #endif -#if defined(HAVE_TLSV1_1_METHOD) && defined(HAVE_TLSV1_1_SERVER_METHOD) && \ - defined(HAVE_TLSV1_1_CLIENT_METHOD) +#if defined(HAVE_TLSV1_1_METHOD) OSSL_SSL_METHOD_ENTRY(TLSv1_1), OSSL_SSL_METHOD_ENTRY(TLSv1_1_server), OSSL_SSL_METHOD_ENTRY(TLSv1_1_client), #endif -#if defined(HAVE_SSLV2_METHOD) && defined(HAVE_SSLV2_SERVER_METHOD) && \ - defined(HAVE_SSLV2_CLIENT_METHOD) +#if defined(HAVE_SSLV2_METHOD) OSSL_SSL_METHOD_ENTRY(SSLv2), OSSL_SSL_METHOD_ENTRY(SSLv2_server), OSSL_SSL_METHOD_ENTRY(SSLv2_client), #endif -#if defined(HAVE_SSLV3_METHOD) && defined(HAVE_SSLV3_SERVER_METHOD) && \ - defined(HAVE_SSLV3_CLIENT_METHOD) +#if defined(HAVE_SSLV3_METHOD) OSSL_SSL_METHOD_ENTRY(SSLv3), OSSL_SSL_METHOD_ENTRY(SSLv3_server), OSSL_SSL_METHOD_ENTRY(SSLv3_client), @@ -2347,25 +2343,17 @@ Init_ossl_ssl(void) ossl_ssl_def_const(OP_NETSCAPE_REUSE_CIPHER_CHANGE_BUG); ossl_ssl_def_const(OP_SSLREF2_REUSE_CERT_TYPE_BUG); ossl_ssl_def_const(OP_MICROSOFT_BIG_SSLV3_BUFFER); -#if defined(SSL_OP_MSIE_SSLV2_RSA_PADDING) ossl_ssl_def_const(OP_MSIE_SSLV2_RSA_PADDING); -#endif ossl_ssl_def_const(OP_SSLEAY_080_CLIENT_DH_BUG); ossl_ssl_def_const(OP_TLS_D5_BUG); ossl_ssl_def_const(OP_TLS_BLOCK_PADDING_BUG); ossl_ssl_def_const(OP_DONT_INSERT_EMPTY_FRAGMENTS); ossl_ssl_def_const(OP_ALL); -#if defined(SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION) ossl_ssl_def_const(OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION); -#endif -#if defined(SSL_OP_SINGLE_ECDH_USE) ossl_ssl_def_const(OP_SINGLE_ECDH_USE); -#endif ossl_ssl_def_const(OP_SINGLE_DH_USE); ossl_ssl_def_const(OP_EPHEMERAL_RSA); -#if defined(SSL_OP_CIPHER_SERVER_PREFERENCE) ossl_ssl_def_const(OP_CIPHER_SERVER_PREFERENCE); -#endif ossl_ssl_def_const(OP_TLS_ROLLBACK_BUG); ossl_ssl_def_const(OP_NO_SSLv2); ossl_ssl_def_const(OP_NO_SSLv3); diff --git a/ext/openssl/ossl_ssl_session.c b/ext/openssl/ossl_ssl_session.c index e1bbc6fb..d4090606 100644 --- a/ext/openssl/ossl_ssl_session.c +++ b/ext/openssl/ossl_ssl_session.c @@ -186,7 +186,6 @@ static VALUE ossl_ssl_session_set_timeout(VALUE self, VALUE time_v) return ossl_ssl_session_get_timeout(self); } -#ifdef HAVE_SSL_SESSION_GET_ID /* * call-seq: * session.id -> aString @@ -205,7 +204,6 @@ static VALUE ossl_ssl_session_get_id(VALUE self) return rb_str_new((const char *) p, i); } -#endif /* * call-seq: @@ -316,12 +314,7 @@ void Init_ossl_ssl_session(void) rb_define_method(cSSLSession, "time=", ossl_ssl_session_set_time, 1); rb_define_method(cSSLSession, "timeout", ossl_ssl_session_get_timeout, 0); rb_define_method(cSSLSession, "timeout=", ossl_ssl_session_set_timeout, 1); - -#ifdef HAVE_SSL_SESSION_GET_ID rb_define_method(cSSLSession, "id", ossl_ssl_session_get_id, 0); -#else - rb_undef_method(cSSLSession, "id"); -#endif rb_define_method(cSSLSession, "to_der", ossl_ssl_session_to_der, 0); rb_define_method(cSSLSession, "to_pem", ossl_ssl_session_to_pem, 0); rb_define_method(cSSLSession, "to_text", ossl_ssl_session_to_text, 0); diff --git a/ext/openssl/ossl_x509.c b/ext/openssl/ossl_x509.c index 2fd14566..cf62b53e 100644 --- a/ext/openssl/ossl_x509.c +++ b/ext/openssl/ossl_x509.c @@ -63,12 +63,8 @@ Init_ossl_x509(void) DefX509Const(V_ERR_KEYUSAGE_NO_CERTSIGN); DefX509Const(V_ERR_APPLICATION_VERIFICATION); -#if defined(X509_V_FLAG_CRL_CHECK) DefX509Const(V_FLAG_CRL_CHECK); -#endif -#if defined(X509_V_FLAG_CRL_CHECK_ALL) DefX509Const(V_FLAG_CRL_CHECK_ALL); -#endif DefX509Const(PURPOSE_SSL_CLIENT); DefX509Const(PURPOSE_SSL_SERVER); @@ -77,21 +73,15 @@ Init_ossl_x509(void) DefX509Const(PURPOSE_SMIME_ENCRYPT); DefX509Const(PURPOSE_CRL_SIGN); DefX509Const(PURPOSE_ANY); -#if defined(X509_PURPOSE_OCSP_HELPER) DefX509Const(PURPOSE_OCSP_HELPER); -#endif DefX509Const(TRUST_COMPAT); DefX509Const(TRUST_SSL_CLIENT); DefX509Const(TRUST_SSL_SERVER); DefX509Const(TRUST_EMAIL); DefX509Const(TRUST_OBJECT_SIGN); -#if defined(X509_TRUST_OCSP_SIGN) DefX509Const(TRUST_OCSP_SIGN); -#endif -#if defined(X509_TRUST_OCSP_REQUEST) DefX509Const(TRUST_OCSP_REQUEST); -#endif DefX509Default(CERT_AREA, cert_area); DefX509Default(CERT_DIR, cert_dir); diff --git a/ext/openssl/ossl_x509attr.c b/ext/openssl/ossl_x509attr.c index 970a91eb..7cd3fe6d 100644 --- a/ext/openssl/ossl_x509attr.c +++ b/ext/openssl/ossl_x509attr.c @@ -178,14 +178,6 @@ ossl_x509attr_get_oid(VALUE self) return ret; } -#if defined(HAVE_ST_X509_ATTRIBUTE_SINGLE) || defined(HAVE_ST_SINGLE) -# define OSSL_X509ATTR_IS_SINGLE(attr) ((attr)->single) -# define OSSL_X509ATTR_SET_SINGLE(attr) ((attr)->single = 1) -#else -# define OSSL_X509ATTR_IS_SINGLE(attr) (!(attr)->value.set) -# define OSSL_X509ATTR_SET_SINGLE(attr) ((attr)->value.set = 0) -#endif - /* * call-seq: * attr.value = asn1 => asn1 @@ -205,10 +197,10 @@ ossl_x509attr_set_value(VALUE self, VALUE value) } GetX509Attr(self, attr); if(attr->value.set){ - if(OSSL_X509ATTR_IS_SINGLE(attr)) ASN1_TYPE_free(attr->value.single); + if(attr->single) ASN1_TYPE_free(attr->value.single); else sk_ASN1_TYPE_free(attr->value.set); } - OSSL_X509ATTR_SET_SINGLE(attr); + attr->single = 1; attr->value.single = a1type; return value; @@ -228,7 +220,7 @@ ossl_x509attr_get_value(VALUE self) GetX509Attr(self, attr); if(attr->value.ptr == NULL) return Qnil; - if(OSSL_X509ATTR_IS_SINGLE(attr)){ + if(attr->single){ length = i2d_ASN1_TYPE(attr->value.single, NULL); str = rb_str_new(0, length); p = (unsigned char *)RSTRING_PTR(str); diff --git a/ext/openssl/ossl_x509ext.c b/ext/openssl/ossl_x509ext.c index e67da4ba..e5817543 100644 --- a/ext/openssl/ossl_x509ext.c +++ b/ext/openssl/ossl_x509ext.c @@ -188,7 +188,6 @@ ossl_x509extfactory_set_crl(VALUE self, VALUE crl) return crl; } -#ifdef HAVE_X509V3_SET_NCONF static VALUE ossl_x509extfactory_set_config(VALUE self, VALUE config) { @@ -202,9 +201,6 @@ ossl_x509extfactory_set_config(VALUE self, VALUE config) return config; } -#else -#define ossl_x509extfactory_set_config rb_f_notimplement -#endif static VALUE ossl_x509extfactory_initialize(int argc, VALUE *argv, VALUE self) @@ -243,12 +239,8 @@ ossl_x509extfactory_create_ext(int argc, VALUE *argv, VALUE self) X509_EXTENSION *ext; VALUE oid, value, critical, valstr, obj; int nid; -#ifdef HAVE_X509V3_EXT_NCONF_NID VALUE rconf; CONF *conf; -#else - static LHASH *empty_lhash; -#endif rb_scan_args(argc, argv, "21", &oid, &value, &critical); StringValueCStr(oid); @@ -265,14 +257,9 @@ ossl_x509extfactory_create_ext(int argc, VALUE *argv, VALUE self) GetX509ExtFactory(self, ctx); obj = NewX509Ext(cX509Ext); -#ifdef HAVE_X509V3_EXT_NCONF_NID rconf = rb_iv_get(self, "@config"); conf = NIL_P(rconf) ? NULL : GetConfigPtr(rconf); ext = X509V3_EXT_nconf_nid(conf, ctx, nid, RSTRING_PTR(valstr)); -#else - if (!empty_lhash) empty_lhash = lh_new(NULL, NULL); - ext = X509V3_EXT_conf_nid(empty_lhash, ctx, nid, RSTRING_PTR(valstr)); -#endif if (!ext){ ossl_raise(eX509ExtError, "%"PRIsVALUE" = %"PRIsVALUE, oid, valstr); } diff --git a/ext/openssl/ossl_x509store.c b/ext/openssl/ossl_x509store.c index f3501e53..767e30be 100644 --- a/ext/openssl/ossl_x509store.c +++ b/ext/openssl/ossl_x509store.c @@ -153,12 +153,6 @@ ossl_x509store_initialize(int argc, VALUE *argv, VALUE self) X509_STORE_set_verify_cb_func(store, ossl_verify_cb); ossl_x509store_set_vfy_cb(self, Qnil); -#if (OPENSSL_VERSION_NUMBER < 0x00907000L) - rb_iv_set(self, "@flags", INT2FIX(0)); - rb_iv_set(self, "@purpose", INT2FIX(0)); - rb_iv_set(self, "@trust", INT2FIX(0)); -#endif - /* last verification status */ rb_iv_set(self, "@error", Qnil); rb_iv_set(self, "@error_string", Qnil); @@ -171,15 +165,11 @@ ossl_x509store_initialize(int argc, VALUE *argv, VALUE self) static VALUE ossl_x509store_set_flags(VALUE self, VALUE flags) { -#if (OPENSSL_VERSION_NUMBER >= 0x00907000L) X509_STORE *store; long f = NUM2LONG(flags); GetX509Store(self, store); X509_STORE_set_flags(store, f); -#else - rb_iv_set(self, "@flags", flags); -#endif return flags; } @@ -187,15 +177,11 @@ ossl_x509store_set_flags(VALUE self, VALUE flags) static VALUE ossl_x509store_set_purpose(VALUE self, VALUE purpose) { -#if (OPENSSL_VERSION_NUMBER >= 0x00907000L) X509_STORE *store; int p = NUM2INT(purpose); GetX509Store(self, store); X509_STORE_set_purpose(store, p); -#else - rb_iv_set(self, "@purpose", purpose); -#endif return purpose; } @@ -203,15 +189,11 @@ ossl_x509store_set_purpose(VALUE self, VALUE purpose) static VALUE ossl_x509store_set_trust(VALUE self, VALUE trust) { -#if (OPENSSL_VERSION_NUMBER >= 0x00907000L) X509_STORE *store; int t = NUM2INT(trust); GetX509Store(self, store); X509_STORE_set_trust(store, t); -#else - rb_iv_set(self, "@trust", trust); -#endif return trust; } @@ -441,17 +423,10 @@ ossl_x509stctx_initialize(int argc, VALUE *argv, VALUE self) SafeGetX509Store(store, x509st); if(!NIL_P(cert)) x509 = DupX509CertPtr(cert); /* NEED TO DUP */ if(!NIL_P(chain)) x509s = ossl_x509_ary2sk(chain); -#if (OPENSSL_VERSION_NUMBER >= 0x00907000L) if(X509_STORE_CTX_init(ctx, x509st, x509, x509s) != 1){ sk_X509_pop_free(x509s, X509_free); ossl_raise(eX509StoreError, NULL); } -#else - X509_STORE_CTX_init(ctx, x509st, x509, x509s); - ossl_x509stctx_set_flags(self, rb_iv_get(store, "@flags")); - ossl_x509stctx_set_purpose(self, rb_iv_get(store, "@purpose")); - ossl_x509stctx_set_trust(self, rb_iv_get(store, "@trust")); -#endif if (!NIL_P(t = rb_iv_get(store, "@time"))) ossl_x509stctx_set_time(self, t); rb_iv_set(self, "@verify_callback", rb_iv_get(store, "@verify_callback")); @@ -562,16 +537,12 @@ ossl_x509stctx_get_curr_cert(VALUE self) static VALUE ossl_x509stctx_get_curr_crl(VALUE self) { -#if (OPENSSL_VERSION_NUMBER >= 0x00907000L) X509_STORE_CTX *ctx; GetX509StCtx(self, ctx); if(!ctx->current_crl) return Qnil; return ossl_x509crl_new(ctx->current_crl); -#else - return Qnil; -#endif } static VALUE diff --git a/lib/openssl/ssl.rb b/lib/openssl/ssl.rb index 98937570..a921379a 100644 --- a/lib/openssl/ssl.rb +++ b/lib/openssl/ssl.rb @@ -56,19 +56,16 @@ module OpenSSL }.join(":"), :options => -> { opts = OpenSSL::SSL::OP_ALL - opts &= ~OpenSSL::SSL::OP_DONT_INSERT_EMPTY_FRAGMENTS if defined?(OpenSSL::SSL::OP_DONT_INSERT_EMPTY_FRAGMENTS) + opts &= ~OpenSSL::SSL::OP_DONT_INSERT_EMPTY_FRAGMENTS opts |= OpenSSL::SSL::OP_NO_COMPRESSION if defined?(OpenSSL::SSL::OP_NO_COMPRESSION) - opts |= OpenSSL::SSL::OP_NO_SSLv2 if defined?(OpenSSL::SSL::OP_NO_SSLv2) - opts |= OpenSSL::SSL::OP_NO_SSLv3 if defined?(OpenSSL::SSL::OP_NO_SSLv3) + opts |= OpenSSL::SSL::OP_NO_SSLv2 | OpenSSL::SSL::OP_NO_SSLv3 opts }.call } DEFAULT_CERT_STORE = OpenSSL::X509::Store.new DEFAULT_CERT_STORE.set_default_paths - if defined?(OpenSSL::X509::V_FLAG_CRL_CHECK_ALL) - DEFAULT_CERT_STORE.flags = OpenSSL::X509::V_FLAG_CRL_CHECK_ALL - end + DEFAULT_CERT_STORE.flags = OpenSSL::X509::V_FLAG_CRL_CHECK_ALL INIT_VARS = ["cert", "key", "client_ca", "ca_file", "ca_path", "timeout", "verify_mode", "verify_depth", "renegotiation_cb", diff --git a/test/test_cipher.rb b/test/test_cipher.rb index aec33fdd..ec14f467 100644 --- a/test/test_cipher.rb +++ b/test/test_cipher.rb @@ -114,40 +114,38 @@ class OpenSSL::TestCipher < OpenSSL::TestCase end end if has_cipher?('aes-128-ctr') - if OpenSSL::OPENSSL_VERSION_NUMBER > 0x00907000 - def test_ciphers - OpenSSL::Cipher.ciphers.each{|name| - next if /netbsd/ =~ RUBY_PLATFORM && /idea|rc5/i =~ name - begin - assert_kind_of(OpenSSL::Cipher::Cipher, OpenSSL::Cipher::Cipher.new(name)) - rescue OpenSSL::Cipher::CipherError => e - next if /wrap/ =~ name and e.message == 'wrap mode not allowed' - raise - end - } - end + def test_ciphers + OpenSSL::Cipher.ciphers.each{|name| + next if /netbsd/ =~ RUBY_PLATFORM && /idea|rc5/i =~ name + begin + assert_kind_of(OpenSSL::Cipher::Cipher, OpenSSL::Cipher::Cipher.new(name)) + rescue OpenSSL::Cipher::CipherError => e + next if /wrap/ =~ name and e.message == 'wrap mode not allowed' + raise + end + } + end - def test_AES - pt = File.read(__FILE__) - %w(ECB CBC CFB OFB).each{|mode| - c1 = OpenSSL::Cipher::AES256.new(mode) - c1.encrypt - c1.pkcs5_keyivgen("passwd") - ct = c1.update(pt) + c1.final - - c2 = OpenSSL::Cipher::AES256.new(mode) - c2.decrypt - c2.pkcs5_keyivgen("passwd") - assert_equal(pt, c2.update(ct) + c2.final) - } - end + def test_AES + pt = File.read(__FILE__) + %w(ECB CBC CFB OFB).each{|mode| + c1 = OpenSSL::Cipher::AES256.new(mode) + c1.encrypt + c1.pkcs5_keyivgen("passwd") + ct = c1.update(pt) + c1.final + + c2 = OpenSSL::Cipher::AES256.new(mode) + c2.decrypt + c2.pkcs5_keyivgen("passwd") + assert_equal(pt, c2.update(ct) + c2.final) + } + end - def test_AES_crush - 500.times do - assert_nothing_raised("[Bug #2768]") do - # it caused OpenSSL SEGV by uninitialized key - OpenSSL::Cipher::AES128.new("ECB").update "." * 17 - end + def test_AES_crush + 500.times do + assert_nothing_raised("[Bug #2768]") do + # it caused OpenSSL SEGV by uninitialized key + OpenSSL::Cipher::AES128.new("ECB").update "." * 17 end end end diff --git a/test/test_pkcs7.rb b/test/test_pkcs7.rb index dfe4c6ca..def4910c 100644 --- a/test/test_pkcs7.rb +++ b/test/test_pkcs7.rb @@ -123,12 +123,6 @@ class OpenSSL::TestPKCS7 < OpenSSL::TestCase end def test_enveloped - if OpenSSL::OPENSSL_VERSION_NUMBER <= 0x0090704f - # PKCS7_encrypt() of OpenSSL-0.9.7d goes to SEGV. - # http://www.mail-archive.com/openssl-dev@openssl.org/msg17376.html - return - end - certs = [@ee1_cert, @ee2_cert] cipher = OpenSSL::Cipher::AES.new("128-CBC") data = "aaaaa\nbbbbb\nccccc\n" diff --git a/test/test_ssl.rb b/test/test_ssl.rb index cb119dcd..164a6aac 100644 --- a/test/test_ssl.rb +++ b/test/test_ssl.rb @@ -869,10 +869,8 @@ class OpenSSL::TestSSL < OpenSSL::SSLTestCase start_server(OpenSSL::SSL::VERIFY_NONE, true, :ctx_proc => ctx_proc, :server_proc => server_proc) do |server, port| 2.times do |i| ctx = OpenSSL::SSL::SSLContext.new - if defined?(OpenSSL::SSL::OP_NO_TICKET) - # disable RFC4507 support - ctx.options = OpenSSL::SSL::OP_NO_TICKET - end + # disable RFC4507 support + ctx.options = OpenSSL::SSL::OP_NO_TICKET server_connect(port, ctx) { |ssl| ssl.hostname = (i & 1 == 0) ? 'foo.example.com' : 'bar.example.com' str = "x" * 100 + "\n" diff --git a/test/test_ssl_session.rb b/test/test_ssl_session.rb index ee1a907f..cdcab02f 100644 --- a/test/test_ssl_session.rb +++ b/test/test_ssl_session.rb @@ -61,9 +61,7 @@ tddwpBAEDjcwMzA5NTYzMTU1MzAwpQMCARM= # SSL_SESSION_time keeps long value so we can't keep nsec fragment. session.time = t1 = Time.now.to_i assert_equal(Time.at(t1), session.time) - if session.respond_to?(:id) - assert_not_nil(session.id) - end + assert_not_nil(session.id) pem = session.to_pem assert_match(/\A-----BEGIN SSL SESSION PARAMETERS-----/, pem) assert_match(/-----END SSL SESSION PARAMETERS-----\Z/, pem) @@ -170,10 +168,7 @@ __EOS__ session = ssl.session if last_session assert(ssl.session_reused?) - - if session.respond_to?(:id) - assert_equal(session.id, last_session.id) - end + assert_equal(session.id, last_session.id) assert_equal(session.to_pem, last_session.to_pem) assert_equal(session.to_der, last_session.to_der) # Older version of OpenSSL may not be consistent. Look up which versions later. @@ -246,10 +241,8 @@ __EOS__ 10.times do |i| sock = TCPSocket.new("127.0.0.1", port) ctx = OpenSSL::SSL::SSLContext.new - if defined?(OpenSSL::SSL::OP_NO_TICKET) - # disable RFC4507 support - ctx.options = OpenSSL::SSL::OP_NO_TICKET - end + # disable RFC4507 support + ctx.options = OpenSSL::SSL::OP_NO_TICKET ssl = OpenSSL::SSL::SSLSocket.new(sock, ctx) ssl.sync_close = true ssl.session = first_session if first_session diff --git a/test/test_x509store.rb b/test/test_x509store.rb index 6a443a7c..8dee1679 100644 --- a/test/test_x509store.rb +++ b/test/test_x509store.rb @@ -148,8 +148,6 @@ class OpenSSL::TestX509Store < OpenSSL::TestCase assert_equal(false, store.verify(OpenSSL::X509::Certificate.new(ee1_cert))) assert_equal(OpenSSL::X509::V_ERR_CERT_NOT_YET_VALID, store.error) - return unless defined?(OpenSSL::X509::V_FLAG_CRL_CHECK) - store = OpenSSL::X509::Store.new store.purpose = OpenSSL::X509::PURPOSE_ANY store.flags = OpenSSL::X509::V_FLAG_CRL_CHECK -- cgit v1.2.3 From d65d34e6895da12e4cd02ad179983059b83f6b48 Mon Sep 17 00:00:00 2001 From: rhe Date: Thu, 26 May 2016 05:24:58 +0000 Subject: openssl: avoid NULL dereference in {DH,DSA,RSA}_size() * ext/openssl/ossl_pkey_dh.c (ossl_dh_compute_key): Check that the DH has 'p' (the prime) before calling DH_size(). We can create a DH with no parameter but DH_size() does not check and dereferences NULL. [ruby-core:75720] [Bug #12428] * ext/openssl/ossl_pkey_dsa.c (ossl_dsa_sign): Ditto. DSA_size() does not check dsa->q. * ext/openssl/ossl_pkey_rsa.c (ossl_rsa_public_encrypt, ossl_rsa_public_decrypt, ossl_rsa_private_encrypt, ossl_rsa_private_decrypt): Ditto. RSA_size() does not check rsa->n. git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@55175 b2dd03c8-39d4-4d8f-98ff-823fe69b080e --- ext/openssl/ossl_pkey_dh.c | 2 ++ ext/openssl/ossl_pkey_dsa.c | 7 ++++--- ext/openssl/ossl_pkey_rsa.c | 18 ++++++++++++------ 3 files changed, 18 insertions(+), 9 deletions(-) diff --git a/ext/openssl/ossl_pkey_dh.c b/ext/openssl/ossl_pkey_dh.c index fd2b8049..ac951a6e 100644 --- a/ext/openssl/ossl_pkey_dh.c +++ b/ext/openssl/ossl_pkey_dh.c @@ -501,6 +501,8 @@ ossl_dh_compute_key(VALUE self, VALUE pub) GetPKeyDH(self, pkey); dh = pkey->pkey.dh; + if (!dh->p) + ossl_raise(eDHError, "incomplete DH"); pub_key = GetBNPtr(pub); len = DH_size(dh); str = rb_str_new(0, len); diff --git a/ext/openssl/ossl_pkey_dsa.c b/ext/openssl/ossl_pkey_dsa.c index 29033809..704fad6d 100644 --- a/ext/openssl/ossl_pkey_dsa.c +++ b/ext/openssl/ossl_pkey_dsa.c @@ -488,10 +488,11 @@ ossl_dsa_sign(VALUE self, VALUE data) VALUE str; GetPKeyDSA(self, pkey); - StringValue(data); - if (!DSA_PRIVATE(self, pkey->pkey.dsa)) { + if (!pkey->pkey.dsa->q) + ossl_raise(eDSAError, "incomplete DSA"); + if (!DSA_PRIVATE(self, pkey->pkey.dsa)) ossl_raise(eDSAError, "Private DSA key needed!"); - } + StringValue(data); str = rb_str_new(0, ossl_dsa_buf_size(pkey)); if (!DSA_sign(0, (unsigned char *)RSTRING_PTR(data), RSTRING_LENINT(data), (unsigned char *)RSTRING_PTR(str), diff --git a/ext/openssl/ossl_pkey_rsa.c b/ext/openssl/ossl_pkey_rsa.c index 9cb50893..ea2af251 100644 --- a/ext/openssl/ossl_pkey_rsa.c +++ b/ext/openssl/ossl_pkey_rsa.c @@ -382,6 +382,8 @@ ossl_rsa_public_encrypt(int argc, VALUE *argv, VALUE self) VALUE str, buffer, padding; GetPKeyRSA(self, pkey); + if (!pkey->pkey.rsa->n) + ossl_raise(eRSAError, "incomplete RSA"); rb_scan_args(argc, argv, "11", &buffer, &padding); pad = (argc == 1) ? RSA_PKCS1_PADDING : NUM2INT(padding); StringValue(buffer); @@ -411,6 +413,8 @@ ossl_rsa_public_decrypt(int argc, VALUE *argv, VALUE self) VALUE str, buffer, padding; GetPKeyRSA(self, pkey); + if (!pkey->pkey.rsa->n) + ossl_raise(eRSAError, "incomplete RSA"); rb_scan_args(argc, argv, "11", &buffer, &padding); pad = (argc == 1) ? RSA_PKCS1_PADDING : NUM2INT(padding); StringValue(buffer); @@ -440,9 +444,10 @@ ossl_rsa_private_encrypt(int argc, VALUE *argv, VALUE self) VALUE str, buffer, padding; GetPKeyRSA(self, pkey); - if (!RSA_PRIVATE(self, pkey->pkey.rsa)) { - ossl_raise(eRSAError, "private key needed."); - } + if (!pkey->pkey.rsa->n) + ossl_raise(eRSAError, "incomplete RSA"); + if (!RSA_PRIVATE(self, pkey->pkey.rsa)) + ossl_raise(eRSAError, "private key needed"); rb_scan_args(argc, argv, "11", &buffer, &padding); pad = (argc == 1) ? RSA_PKCS1_PADDING : NUM2INT(padding); StringValue(buffer); @@ -472,9 +477,10 @@ ossl_rsa_private_decrypt(int argc, VALUE *argv, VALUE self) VALUE str, buffer, padding; GetPKeyRSA(self, pkey); - if (!RSA_PRIVATE(self, pkey->pkey.rsa)) { - ossl_raise(eRSAError, "private key needed."); - } + if (!pkey->pkey.rsa->n) + ossl_raise(eRSAError, "incomplete RSA"); + if (!RSA_PRIVATE(self, pkey->pkey.rsa)) + ossl_raise(eRSAError, "private key needed"); rb_scan_args(argc, argv, "11", &buffer, &padding); pad = (argc == 1) ? RSA_PKCS1_PADDING : NUM2INT(padding); StringValue(buffer); -- cgit v1.2.3 From 998d66712a78c623977db37fc8c6f95502b71d3c Mon Sep 17 00:00:00 2001 From: rhe Date: Sat, 28 May 2016 05:00:36 +0000 Subject: openssl: move SSLSocket#initialize to C extension * ext/openssl/lib/openssl/ssl.rb (SSLSocket): Move the implementation of SSLSocket#initialize to C. Initialize the SSL (OpenSSL object) in it. Currently this is delayed until ossl_ssl_setup(), which is called from SSLSocket#accept or #connect. Say we call SSLSocket#hostname= with an illegal value. We expect an exception to be raised in #hostname= but actually we get it in the later SSLSocket#connect. Because the SSL is not ready at #hostname=, the actual call of SSL_set_tlsext_host_name() is also delayed. This also fixes: [ruby-dev:49376] [Bug #11724] * ext/openssl/ossl_ssl.c (ossl_ssl_initialize): Added. Almost the same as the Ruby version but this instantiate the SSL object at the same time. (ossl_ssl_setup): Adjust to the changes. Just set the underlying IO to the SSL. (ssl_started): Added. Make use of SSL_get_fd(). This returns -1 if not yet set by SSL_set_fd(). (ossl_ssl_data_get_struct): Removed. Now GetSSL() checks that the SSL exists. (ossl_ssl_set_session): Don't call ossl_ssl_setup() here as now the SSL is already instantiated in #initialize. (ossl_ssl_shutdown, ossl_start_ssl, ossl_ssl_read_internal, ossl_ssl_write_internal, ossl_ssl_stop, ossl_ssl_get_cert, ossl_ssl_get_peer_cert, ossl_ssl_get_peer_cert_chain, ossl_ssl_get_version, ossl_ssl_get_cipher, ossl_ssl_get_state, ossl_ssl_pending, ossl_ssl_session_reused, ossl_ssl_get_verify_result, ossl_ssl_get_client_ca_list, ossl_ssl_npn_protocol, ossl_ssl_alpn_protocol, ossl_ssl_tmp_key): Use GetSSL() instead of ossl_ssl_data_get_struct(). Use ssl_started(). (Init_ossl_ssl): Add method declarations of SSLSocket#{initialize, hostname=}. * ext/openssl/ossl_ssl.h (GetSSL): Check that the SSL is not NULL. It should not be NULL because we now set it in #initialize. * ext/openssl/ossl_ssl_session.c (ossl_ssl_session_initialize): No need to check if the SSL is NULL. git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@55191 b2dd03c8-39d4-4d8f-98ff-823fe69b080e --- ext/openssl/ossl_ssl.c | 235 +++++++++++++++++++++++++---------------- ext/openssl/ossl_ssl.h | 3 + ext/openssl/ossl_ssl_session.c | 2 +- lib/openssl/ssl.rb | 41 ++----- 4 files changed, 156 insertions(+), 125 deletions(-) diff --git a/ext/openssl/ossl_ssl.c b/ext/openssl/ossl_ssl.c index c31a32f3..282ed291 100644 --- a/ext/openssl/ossl_ssl.c +++ b/ext/openssl/ossl_ssl.c @@ -70,6 +70,10 @@ static VALUE eSSLErrorWaitWritable; #define ossl_ssl_get_x509(o) rb_iv_get((o),"@x509") #define ossl_ssl_get_key(o) rb_iv_get((o),"@key") +#define ossl_ssl_set_io(o,v) rb_iv_set((o),"@io",(v)) +#define ossl_ssl_set_ctx(o,v) rb_iv_set((o),"@context",(v)) +#define ossl_ssl_set_sync_close(o,v) rb_iv_set((o),"@sync_close",(v)) +#define ossl_ssl_set_hostname_v(o,v) rb_iv_set((o),"@hostname",(v)) #define ossl_ssl_set_x509(o,v) rb_iv_set((o),"@x509",(v)) #define ossl_ssl_set_key(o,v) rb_iv_set((o),"@key",(v)) #define ossl_ssl_set_tmp_dh(o,v) rb_iv_set((o),"@tmp_dh",(v)) @@ -1139,25 +1143,29 @@ ossl_sslctx_flush_sessions(int argc, VALUE *argv, VALUE self) * SSLSocket class */ #ifndef OPENSSL_NO_SOCK +static inline int +ssl_started(SSL *ssl) +{ + /* the FD is set in ossl_ssl_setup(), called by #connect or #accept */ + return SSL_get_fd(ssl) >= 0; +} + static void ossl_ssl_shutdown(SSL *ssl) { - int i, rc; - - if (ssl) { - /* 4 is from SSL_smart_shutdown() of mod_ssl.c (v2.2.19) */ - /* It says max 2x pending + 2x data = 4 */ - for (i = 0; i < 4; ++i) { - /* - * Ignore the case SSL_shutdown returns -1. Empty handshake_func - * must not happen. - */ - if ((rc = SSL_shutdown(ssl)) != 0) - break; - } - SSL_clear(ssl); - ossl_clear_error(); + int i; + + /* 4 is from SSL_smart_shutdown() of mod_ssl.c (v2.2.19) */ + /* It says max 2x pending + 2x data = 4 */ + for (i = 0; i < 4; ++i) { + /* + * Ignore the case SSL_shutdown returns -1. Empty handshake_func + * must not happen. + */ + if (SSL_shutdown(ssl) != 0) + break; } + ossl_clear_error(); } static void @@ -1180,45 +1188,77 @@ ossl_ssl_s_alloc(VALUE klass) return TypedData_Wrap_Struct(klass, &ossl_ssl_type, NULL); } +/* + * call-seq: + * SSLSocket.new(io) => aSSLSocket + * SSLSocket.new(io, ctx) => aSSLSocket + * + * Creates a new SSL socket from +io+ which must be a real ruby object (not an + * IO-like object that responds to read/write). + * + * If +ctx+ is provided the SSL Sockets initial params will be taken from + * the context. + * + * The OpenSSL::Buffering module provides additional IO methods. + * + * This method will freeze the SSLContext if one is provided; + * however, session management is still allowed in the frozen SSLContext. + */ static VALUE -ossl_ssl_setup(VALUE self) +ossl_ssl_initialize(int argc, VALUE *argv, VALUE self) { - VALUE io, v_ctx, cb; + VALUE io, v_ctx, verify_cb; + SSL *ssl; SSL_CTX *ctx; + + TypedData_Get_Struct(self, SSL, &ossl_ssl_type, ssl); + if (ssl) + ossl_raise(eSSLError, "SSL already initialized"); + + if (rb_scan_args(argc, argv, "11", &io, &v_ctx) == 1) + v_ctx = rb_funcall(cSSLContext, rb_intern("new"), 0); + + GetSSLCTX(v_ctx, ctx); + ossl_ssl_set_ctx(self, v_ctx); + ossl_sslctx_setup(v_ctx); + + if (rb_respond_to(io, rb_intern("nonblock="))) + rb_funcall(io, rb_intern("nonblock="), 1, Qtrue); + ossl_ssl_set_io(self, io); + + ossl_ssl_set_sync_close(self, Qfalse); + + ssl = SSL_new(ctx); + if (!ssl) + ossl_raise(eSSLError, NULL); + RTYPEDDATA_DATA(self) = ssl; + + SSL_set_ex_data(ssl, ossl_ssl_ex_ptr_idx, (void *)self); + SSL_set_info_callback(ssl, ssl_info_cb); + verify_cb = ossl_sslctx_get_verify_cb(v_ctx); + SSL_set_ex_data(ssl, ossl_ssl_ex_vcb_idx, (void *)verify_cb); + + rb_call_super(0, NULL); + + return self; +} + +static VALUE +ossl_ssl_setup(VALUE self) +{ + VALUE io; SSL *ssl; rb_io_t *fptr; GetSSL(self, ssl); - if(!ssl){ -#ifdef HAVE_SSL_SET_TLSEXT_HOST_NAME - VALUE hostname = rb_iv_get(self, "@hostname"); -#endif - - v_ctx = ossl_ssl_get_ctx(self); - GetSSLCTX(v_ctx, ctx); + if (ssl_started(ssl)) + return Qtrue; - ssl = SSL_new(ctx); - if (!ssl) { - ossl_raise(eSSLError, "SSL_new"); - } - DATA_PTR(self) = ssl; - -#ifdef HAVE_SSL_SET_TLSEXT_HOST_NAME - if (!NIL_P(hostname)) { - if (SSL_set_tlsext_host_name(ssl, StringValueCStr(hostname)) != 1) - ossl_raise(eSSLError, "SSL_set_tlsext_host_name"); - } -#endif - io = ossl_ssl_get_io(self); - GetOpenFile(io, fptr); - rb_io_check_readable(fptr); - rb_io_check_writable(fptr); - SSL_set_fd(ssl, TO_SOCKET(FPTR_TO_FD(fptr))); - SSL_set_ex_data(ssl, ossl_ssl_ex_ptr_idx, (void*)self); - cb = ossl_sslctx_get_verify_cb(v_ctx); - SSL_set_ex_data(ssl, ossl_ssl_ex_vcb_idx, (void*)cb); - SSL_set_info_callback(ssl, ssl_info_cb); - } + io = ossl_ssl_get_io(self); + GetOpenFile(io, fptr); + rb_io_check_readable(fptr); + rb_io_check_writable(fptr); + SSL_set_fd(ssl, TO_SOCKET(FPTR_TO_FD(fptr))); return Qtrue; } @@ -1229,15 +1269,6 @@ ossl_ssl_setup(VALUE self) #define ssl_get_error(ssl, ret) SSL_get_error((ssl), (ret)) #endif -#define ossl_ssl_data_get_struct(v, ssl) \ -do { \ - GetSSL((v), (ssl)); \ - if (!(ssl)) { \ - rb_warning("SSL session is not started yet."); \ - return Qnil; \ - } \ -} while (0) - static void write_would_block(int nonblock) { @@ -1276,7 +1307,7 @@ ossl_start_ssl(VALUE self, int (*func)(), const char *funcname, VALUE opts) rb_ivar_set(self, ID_callback_state, Qnil); - ossl_ssl_data_get_struct(self, ssl); + GetSSL(self, ssl); GetOpenFile(ossl_ssl_get_io(self), fptr); for(;;){ @@ -1436,7 +1467,7 @@ ossl_ssl_read_internal(int argc, VALUE *argv, VALUE self, int nonblock) GetSSL(self, ssl); GetOpenFile(ossl_ssl_get_io(self), fptr); - if (ssl) { + if (ssl_started(ssl)) { if(!nonblock && SSL_pending(ssl) <= 0) rb_thread_wait_fd(FPTR_TO_FD(fptr)); for (;;){ @@ -1530,7 +1561,7 @@ ossl_ssl_write_internal(VALUE self, VALUE str, VALUE opts) GetSSL(self, ssl); GetOpenFile(ossl_ssl_get_io(self), fptr); - if (ssl) { + if (ssl_started(ssl)) { for (;;){ nwrite = SSL_write(ssl, RSTRING_PTR(str), RSTRING_LENINT(str)); switch(ssl_get_error(ssl, nwrite)){ @@ -1604,7 +1635,7 @@ ossl_ssl_stop(VALUE self) { SSL *ssl; - ossl_ssl_data_get_struct(self, ssl); + GetSSL(self, ssl); ossl_ssl_shutdown(ssl); @@ -1623,7 +1654,7 @@ ossl_ssl_get_cert(VALUE self) SSL *ssl; X509 *cert = NULL; - ossl_ssl_data_get_struct(self, ssl); + GetSSL(self, ssl); /* * Is this OpenSSL bug? Should add a ref? @@ -1650,7 +1681,7 @@ ossl_ssl_get_peer_cert(VALUE self) X509 *cert = NULL; VALUE obj; - ossl_ssl_data_get_struct(self, ssl); + GetSSL(self, ssl); cert = SSL_get_peer_certificate(ssl); /* Adds a ref => Safe to FREE. */ @@ -1678,7 +1709,7 @@ ossl_ssl_get_peer_cert_chain(VALUE self) VALUE ary; int i, num; - ossl_ssl_data_get_struct(self, ssl); + GetSSL(self, ssl); chain = SSL_get_peer_cert_chain(ssl); if(!chain) return Qnil; @@ -1704,7 +1735,7 @@ ossl_ssl_get_version(VALUE self) { SSL *ssl; - ossl_ssl_data_get_struct(self, ssl); + GetSSL(self, ssl); return rb_str_new2(SSL_get_version(ssl)); } @@ -1721,7 +1752,7 @@ ossl_ssl_get_cipher(VALUE self) SSL *ssl; SSL_CIPHER *cipher; - ossl_ssl_data_get_struct(self, ssl); + GetSSL(self, ssl); cipher = (SSL_CIPHER *)SSL_get_current_cipher(ssl); @@ -1740,7 +1771,7 @@ ossl_ssl_get_state(VALUE self) SSL *ssl; VALUE ret; - ossl_ssl_data_get_struct(self, ssl); + GetSSL(self, ssl); ret = rb_str_new2(SSL_state_string(ssl)); if (ruby_verbose) { @@ -1761,7 +1792,7 @@ ossl_ssl_pending(VALUE self) { SSL *ssl; - ossl_ssl_data_get_struct(self, ssl); + GetSSL(self, ssl); return INT2NUM(SSL_pending(ssl)); } @@ -1777,15 +1808,9 @@ ossl_ssl_session_reused(VALUE self) { SSL *ssl; - ossl_ssl_data_get_struct(self, ssl); - - switch(SSL_session_reused(ssl)) { - case 1: return Qtrue; - case 0: return Qfalse; - default: ossl_raise(eSSLError, "SSL_session_reused"); - } + GetSSL(self, ssl); - UNREACHABLE; + return SSL_session_reused(ssl) ? Qtrue : Qfalse; } /* @@ -1800,11 +1825,7 @@ ossl_ssl_set_session(VALUE self, VALUE arg1) SSL *ssl; SSL_SESSION *sess; -/* why is ossl_ssl_setup delayed? */ - ossl_ssl_setup(self); - - ossl_ssl_data_get_struct(self, ssl); - + GetSSL(self, ssl); SafeGetSSLSession(arg1, sess); if (SSL_set_session(ssl, sess) != 1) @@ -1813,6 +1834,35 @@ ossl_ssl_set_session(VALUE self, VALUE arg1) return arg1; } +/* + * call-seq: + * ssl.hostname = hostname -> hostname + * + * Sets the server hostname used for SNI. This needs to be set before + * SSLSocket#connect. + */ +#ifdef HAVE_SSL_SET_TLSEXT_HOST_NAME +static VALUE +ossl_ssl_set_hostname(VALUE self, VALUE arg) +{ + SSL *ssl; + char *hostname = NULL; + + GetSSL(self, ssl); + + if (!NIL_P(arg)) + hostname = StringValueCStr(arg); + + if (!SSL_set_tlsext_host_name(ssl, hostname)) + ossl_raise(eSSLError, NULL); + + /* for SSLSocket#hostname */ + ossl_ssl_set_hostname_v(self, arg); + + return arg; +} +#endif + /* * call-seq: * ssl.verify_result => Integer @@ -1827,7 +1877,7 @@ ossl_ssl_get_verify_result(VALUE self) { SSL *ssl; - ossl_ssl_data_get_struct(self, ssl); + GetSSL(self, ssl); return INT2FIX(SSL_get_verify_result(ssl)); } @@ -1849,7 +1899,7 @@ ossl_ssl_get_client_ca_list(VALUE self) SSL *ssl; STACK_OF(X509_NAME) *ca; - ossl_ssl_data_get_struct(self, ssl); + GetSSL(self, ssl); ca = SSL_get_client_CA_list(ssl); return ossl_x509name_sk2ary(ca); @@ -1870,7 +1920,7 @@ ossl_ssl_npn_protocol(VALUE self) const unsigned char *out; unsigned int outlen; - ossl_ssl_data_get_struct(self, ssl); + GetSSL(self, ssl); SSL_get0_next_proto_negotiated(ssl, &out, &outlen); if (!outlen) @@ -1895,7 +1945,7 @@ ossl_ssl_alpn_protocol(VALUE self) const unsigned char *out; unsigned int outlen; - ossl_ssl_data_get_struct(self, ssl); + GetSSL(self, ssl); SSL_get0_alpn_selected(ssl, &out, &outlen); if (!outlen) @@ -1915,12 +1965,13 @@ ossl_ssl_alpn_protocol(VALUE self) static VALUE ossl_ssl_tmp_key(VALUE self) { - SSL *ssl; - EVP_PKEY *key; - ossl_ssl_data_get_struct(self, ssl); - if (!SSL_get_server_tmp_key(ssl, &key)) - return Qnil; - return ossl_pkey_new(key); + SSL *ssl; + EVP_PKEY *key; + + GetSSL(self, ssl); + if (!SSL_get_server_tmp_key(ssl, &key)) + return Qnil; + return ossl_pkey_new(key); } # endif /* defined(HAVE_SSL_GET_SERVER_TMP_KEY) */ #endif /* !defined(OPENSSL_NO_SOCK) */ @@ -2293,9 +2344,11 @@ Init_ossl_ssl(void) cSSLSocket = rb_define_class_under(mSSL, "SSLSocket", rb_cObject); #ifdef OPENSSL_NO_SOCK rb_define_const(mSSLExtConfig, "OPENSSL_NO_SOCK", Qtrue); + rb_define_method(cSSLSocket, "initialize", rb_f_notimplement, -1); #else rb_define_const(mSSLExtConfig, "OPENSSL_NO_SOCK", Qfalse); rb_define_alloc_func(cSSLSocket, ossl_ssl_s_alloc); + rb_define_method(cSSLSocket, "initialize", ossl_ssl_initialize, -1); rb_define_method(cSSLSocket, "connect", ossl_ssl_connect, 0); rb_define_method(cSSLSocket, "connect_nonblock", ossl_ssl_connect_nonblock, -1); rb_define_method(cSSLSocket, "accept", ossl_ssl_accept, 0); @@ -2317,6 +2370,10 @@ Init_ossl_ssl(void) rb_define_method(cSSLSocket, "session=", ossl_ssl_set_session, 1); rb_define_method(cSSLSocket, "verify_result", ossl_ssl_get_verify_result, 0); rb_define_method(cSSLSocket, "client_ca", ossl_ssl_get_client_ca_list, 0); +#ifdef HAVE_SSL_SET_TLSEXT_HOST_NAME + /* #hostname is defined in lib/openssl/ssl.rb */ + rb_define_method(cSSLSocket, "hostname=", ossl_ssl_set_hostname, 1); +#endif # ifdef HAVE_SSL_GET_SERVER_TMP_KEY rb_define_method(cSSLSocket, "tmp_key", ossl_ssl_tmp_key, 0); # endif diff --git a/ext/openssl/ossl_ssl.h b/ext/openssl/ossl_ssl.h index 909f6798..c1a3cd6c 100644 --- a/ext/openssl/ossl_ssl.h +++ b/ext/openssl/ossl_ssl.h @@ -12,6 +12,9 @@ #define GetSSL(obj, ssl) do { \ TypedData_Get_Struct((obj), SSL, &ossl_ssl_type, (ssl)); \ + if (!(ssl)) { \ + ossl_raise(rb_eRuntimeError, "SSL is not initialized"); \ + } \ } while (0) #define GetSSLSession(obj, sess) do { \ diff --git a/ext/openssl/ossl_ssl_session.c b/ext/openssl/ossl_ssl_session.c index d4090606..1b6df55c 100644 --- a/ext/openssl/ossl_ssl_session.c +++ b/ext/openssl/ossl_ssl_session.c @@ -46,7 +46,7 @@ static VALUE ossl_ssl_session_initialize(VALUE self, VALUE arg1) GetSSL(arg1, ssl); - if (!ssl || (ctx = SSL_get1_session(ssl)) == NULL) + if ((ctx = SSL_get1_session(ssl)) == NULL) ossl_raise(eSSLSession, "no session available"); } else { BIO *in = ossl_obj2bio(arg1); diff --git a/lib/openssl/ssl.rb b/lib/openssl/ssl.rb index a921379a..00c32753 100644 --- a/lib/openssl/ssl.rb +++ b/lib/openssl/ssl.rb @@ -247,43 +247,14 @@ module OpenSSL include Buffering include SocketForwarder - if ExtConfig::OPENSSL_NO_SOCK - def initialize(io, ctx = nil); raise NotImplementedError; end - else - if ExtConfig::HAVE_TLSEXT_HOST_NAME - attr_accessor :hostname - end - - attr_reader :io, :context - attr_accessor :sync_close - alias :to_io :io - - # call-seq: - # SSLSocket.new(io) => aSSLSocket - # SSLSocket.new(io, ctx) => aSSLSocket - # - # Creates a new SSL socket from +io+ which must be a real ruby object (not an - # IO-like object that responds to read/write). - # - # If +ctx+ is provided the SSL Sockets initial params will be taken from - # the context. - # - # The OpenSSL::Buffering module provides additional IO methods. - # - # This method will freeze the SSLContext if one is provided; - # however, session management is still allowed in the frozen SSLContext. - - def initialize(io, context = OpenSSL::SSL::SSLContext.new) - @io = io - @context = context - @sync_close = false - @hostname = nil - @io.nonblock = true if @io.respond_to?(:nonblock=) - context.setup - super() - end + if ExtConfig::HAVE_TLSEXT_HOST_NAME + attr_reader :hostname end + attr_reader :io, :context + attr_accessor :sync_close + alias :to_io :io + # call-seq: # ssl.sysclose => nil # -- cgit v1.2.3 From fcb9b4a6b5c6e30a99d9acb8c73e62c3c7559001 Mon Sep 17 00:00:00 2001 From: rhe Date: Mon, 30 May 2016 09:30:38 +0000 Subject: openssl: add SSLContext#ecdh_curves= * ext/openssl/ossl_ssl.c (ossl_sslctx_s_alloc): Enable the automatic curve selection for ECDH by calling SSL_CTX_set_ecdh_auto(). With this a TLS server automatically selects a curve which both the client and the server support to use in ECDH. This changes the default behavior but users can still disable ECDH by excluding 'ECDH' cipher suites from the cipher list (with SSLContext#ciphers=). This commit also deprecate #tmp_ecdh_callback=. It was added in Ruby 2.3.0. It wraps SSL_CTX_set_tmp_ecdh_callback() which will be removed in OpenSSL 1.1.0. Its callback receives two values 'is_export' and 'keylength' but both are completely useless for determining a curve to use in ECDH. The automatic curve selection was introduced to replace this. (ossl_sslctx_setup): Deprecate SSLContext#tmp_ecdh_callback=. Emit a warning if this is in use. (ossl_sslctx_set_ecdh_curves): Add SSLContext#ecdh_curves=. Wrap SSL_CTX_set1_curves_list(). If it is not available, this falls back to SSL_CTX_set_tmp_ecdh(). (Init_ossl_ssl): Define SSLContext#ecdh_curves=. * ext/openssl/extconf.rb: Check the existence of EC_curve_nist2nid(), SSL_CTX_set1_curves_list(), SSL_CTX_set_ecdh_auto() and SSL_CTX_set_tmp_ecdh_callback(). * ext/openssl/openssl_missing.[ch]: Implement EC_curve_nist2nid() if missing. * test/openssl/test_pair.rb (test_ecdh_callback): Use EnvUtil.suppress_warning to suppress deprecated warning. (test_ecdh_curves): Test that SSLContext#ecdh_curves= works. * test/openssl/utils.rb (start_server): Use SSLContext#ecdh_curves=. git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@55214 b2dd03c8-39d4-4d8f-98ff-823fe69b080e --- ext/openssl/extconf.rb | 4 ++ ext/openssl/openssl_missing.c | 37 +++++++++++++ ext/openssl/openssl_missing.h | 6 +++ ext/openssl/ossl_ssl.c | 118 ++++++++++++++++++++++++++++++++++++++++-- test/test_pair.rb | 87 +++++++++++++++++++++---------- test/utils.rb | 2 +- 6 files changed, 221 insertions(+), 33 deletions(-) diff --git a/ext/openssl/extconf.rb b/ext/openssl/extconf.rb index 14daae97..eeeae448 100644 --- a/ext/openssl/extconf.rb +++ b/ext/openssl/extconf.rb @@ -98,13 +98,17 @@ have_func("SSL_CTX_set_next_proto_select_cb") have_macro("EVP_CTRL_GCM_GET_TAG", ['openssl/evp.h']) && $defs.push("-DHAVE_AUTHENTICATED_ENCRYPTION") # added in 1.0.2 +have_func("EC_curve_nist2nid") have_func("X509_REVOKED_dup") have_func("SSL_CTX_set_alpn_select_cb") +OpenSSL.check_func_or_macro("SSL_CTX_set1_curves_list", "openssl/ssl.h") +OpenSSL.check_func_or_macro("SSL_CTX_set_ecdh_auto", "openssl/ssl.h") OpenSSL.check_func_or_macro("SSL_get_server_tmp_key", "openssl/ssl.h") # added in 1.1.0 have_func("X509_STORE_get_ex_data") have_func("X509_STORE_set_ex_data") +OpenSSL.check_func_or_macro("SSL_CTX_set_tmp_ecdh_callback", "openssl/ssl.h") # removed Logging::message "=== Checking done. ===\n" diff --git a/ext/openssl/openssl_missing.c b/ext/openssl/openssl_missing.c index 7b00ae4d..796d8aa0 100644 --- a/ext/openssl/openssl_missing.c +++ b/ext/openssl/openssl_missing.c @@ -58,3 +58,40 @@ HMAC_CTX_copy(HMAC_CTX *out, HMAC_CTX *in) } #endif /* HAVE_HMAC_CTX_COPY */ #endif /* NO_HMAC */ + +/* added in 1.0.2 */ +#if !defined(OPENSSL_NO_EC) +#if !defined(HAVE_EC_CURVE_NIST2NID) +static struct { + const char *name; + int nid; +} nist_curves[] = { + {"B-163", NID_sect163r2}, + {"B-233", NID_sect233r1}, + {"B-283", NID_sect283r1}, + {"B-409", NID_sect409r1}, + {"B-571", NID_sect571r1}, + {"K-163", NID_sect163k1}, + {"K-233", NID_sect233k1}, + {"K-283", NID_sect283k1}, + {"K-409", NID_sect409k1}, + {"K-571", NID_sect571k1}, + {"P-192", NID_X9_62_prime192v1}, + {"P-224", NID_secp224r1}, + {"P-256", NID_X9_62_prime256v1}, + {"P-384", NID_secp384r1}, + {"P-521", NID_secp521r1} +}; + +int +EC_curve_nist2nid(const char *name) +{ + size_t i; + for (i = 0; i < (sizeof(nist_curves) / sizeof(nist_curves[0])); i++) { + if (!strcmp(nist_curves[i].name, name)) + return nist_curves[i].nid; + } + return NID_undef; +} +#endif +#endif diff --git a/ext/openssl/openssl_missing.h b/ext/openssl/openssl_missing.h index 0f82a180..b8f9d3d1 100644 --- a/ext/openssl/openssl_missing.h +++ b/ext/openssl/openssl_missing.h @@ -20,6 +20,12 @@ void HMAC_CTX_copy(HMAC_CTX *out, HMAC_CTX *in); #endif /* added in 1.0.2 */ +#if !defined(OPENSSL_NO_EC) +#if !defined(HAVE_EC_CURVE_NIST2NID) +int EC_curve_nist2nid(const char *); +#endif +#endif + #if !defined(HAVE_X509_REVOKED_DUP) # define X509_REVOKED_dup(rev) (X509_REVOKED *)ASN1_dup((i2d_of_void *)i2d_X509_REVOKED, \ (d2i_of_void *)d2i_X509_REVOKED, (char *)(rev)) diff --git a/ext/openssl/ossl_ssl.c b/ext/openssl/ossl_ssl.c index 282ed291..0f5313bd 100644 --- a/ext/openssl/ossl_ssl.c +++ b/ext/openssl/ossl_ssl.c @@ -162,6 +162,18 @@ ossl_sslctx_s_alloc(VALUE klass) RTYPEDDATA_DATA(obj) = ctx; SSL_CTX_set_ex_data(ctx, ossl_ssl_ex_ptr_idx, (void*)obj); +#if defined(HAVE_SSL_CTX_SET_ECDH_AUTO) + /* We use SSL_CTX_set1_curves_list() to specify the curve used in ECDH. It + * allows to specify multiple curve names and OpenSSL will select + * automatically from them. In OpenSSL 1.0.2, the automatic selection has to + * be enabled explicitly. But OpenSSL 1.1.0 removed the knob and it is + * always enabled. To uniform the behavior, we enable the automatic + * selection also in 1.0.2. Users can still disable ECDH by removing ECDH + * cipher suites by SSLContext#ciphers=. */ + if (!SSL_CTX_set_ecdh_auto(ctx, 1)) + ossl_raise(eSSLError, "SSL_CTX_set_ecdh_auto"); +#endif + return obj; } @@ -711,10 +723,24 @@ ossl_sslctx_setup(VALUE self) #endif #if !defined(OPENSSL_NO_EC) - if (RTEST(ossl_sslctx_get_tmp_ecdh_cb(self))){ + /* We added SSLContext#tmp_ecdh_callback= in Ruby 2.3.0, + * but SSL_CTX_set_tmp_ecdh_callback() was removed in OpenSSL 1.1.0. */ + if (RTEST(ossl_sslctx_get_tmp_ecdh_cb(self))) { +# if defined(HAVE_SSL_CTX_SET_TMP_ECDH_CALLBACK) + rb_warn("#tmp_ecdh_callback= is deprecated; use #ecdh_curves= instead"); SSL_CTX_set_tmp_ecdh_callback(ctx, ossl_tmp_ecdh_callback); +# if defined(HAVE_SSL_CTX_SET_ECDH_AUTO) + /* tmp_ecdh_callback and ecdh_auto conflict; OpenSSL ignores + * tmp_ecdh_callback. So disable ecdh_auto. */ + if (!SSL_CTX_set_ecdh_auto(ctx, 0)) + ossl_raise(eSSLError, "SSL_CTX_set_ecdh_auto"); +# endif +# else + ossl_raise(eSSLError, "OpenSSL does not support tmp_ecdh_callback; " + "use #ecdh_curves= instead"); +# endif } -#endif +#endif /* OPENSSL_NO_EC */ val = ossl_sslctx_get_cert_store(self); if(!NIL_P(val)){ @@ -953,6 +979,87 @@ ossl_sslctx_set_ciphers(VALUE self, VALUE v) return v; } +#if !defined(OPENSSL_NO_EC) +/* + * call-seq: + * ctx.ecdh_curves = curve_list -> curve_list + * + * Sets the list of "supported elliptic curves" for this context. + * + * For a TLS client, the list is directly used in the Supported Elliptic Curves + * Extension. For a server, the list is used by OpenSSL to determine the set of + * shared curves. OpenSSL will pick the most appropriate one from it. + * + * Note that this works differently with old OpenSSL (<= 1.0.1). Only one curve + * can be set, and this has no effect for TLS clients. + * + * === Example + * ctx1 = OpenSSL::SSL::SSLContext.new + * ctx1.ecdh_curves = "X25519:P-256:P-224" + * svr = OpenSSL::SSL::SSLServer.new(tcp_svr, ctx1) + * Thread.new { svr.accept } + * + * ctx2 = OpenSSL::SSL::SSLContext.new + * ctx2.ecdh_curves = "P-256" + * cli = OpenSSL::SSL::SSLSocket.new(tcp_sock, ctx2) + * cli.connect + * + * p cli.tmp_key.group.curve_name + * # => "prime256v1" (is an alias for NIST P-256) + */ +static VALUE +ossl_sslctx_set_ecdh_curves(VALUE self, VALUE arg) +{ + SSL_CTX *ctx; + + rb_check_frozen(self); + GetSSLCTX(self, ctx); + StringValueCStr(arg); + +#if defined(HAVE_SSL_CTX_SET1_CURVES_LIST) + if (!SSL_CTX_set1_curves_list(ctx, RSTRING_PTR(arg))) + ossl_raise(eSSLError, NULL); +#else + /* OpenSSL does not have SSL_CTX_set1_curves_list()... Fallback to + * SSL_CTX_set_tmp_ecdh(). So only the first curve is used. */ + { + VALUE curve, splitted; + EC_KEY *ec; + int nid; + + splitted = rb_str_split(arg, ":"); + if (!RARRAY_LEN(splitted)) + ossl_raise(eSSLError, "invalid input format"); + curve = RARRAY_AREF(splitted, 0); + StringValueCStr(curve); + + /* SSL_CTX_set1_curves_list() accepts NIST names */ + nid = EC_curve_nist2nid(RSTRING_PTR(curve)); + if (nid == NID_undef) + nid = OBJ_txt2nid(RSTRING_PTR(curve)); + if (nid == NID_undef) + ossl_raise(eSSLError, "unknown curve name"); + + ec = EC_KEY_new_by_curve_name(nid); + if (!ec) + ossl_raise(eSSLError, NULL); + EC_KEY_set_asn1_flag(ec, OPENSSL_EC_NAMED_CURVE); + SSL_CTX_set_tmp_ecdh(ctx, ec); +# if defined(HAVE_SSL_CTX_SET_ECDH_AUTO) + /* tmp_ecdh and ecdh_auto conflict. tmp_ecdh is ignored when ecdh_auto + * is enabled. So disable ecdh_auto. */ + if (!SSL_CTX_set_ecdh_auto(ctx, 0)) + ossl_raise(eSSLError, "SSL_CTX_set_ecdh_auto"); +# endif + } +#endif + + return arg; +} +#else +#define ossl_sslctx_set_ecdh_curves rb_f_notimplement +#endif + /* * call-seq: * ctx.session_add(session) -> true | false @@ -2119,6 +2226,7 @@ Init_ossl_ssl(void) */ rb_attr(cSSLContext, rb_intern("client_cert_cb"), 1, 1, Qfalse); +#if defined(HAVE_SSL_CTX_SET_TMP_ECDH_CALLBACK) /* * A callback invoked when ECDH parameters are required. * @@ -2126,10 +2234,11 @@ Init_ossl_ssl(void) * flag indicating the use of an export cipher and the keylength * required. * - * The callback must return an OpenSSL::PKey::EC instance of the correct - * key length. + * The callback is deprecated. This does not work with recent versions of + * OpenSSL. Use OpenSSL::SSL::SSLContext#ecdh_curves= instead. */ rb_attr(cSSLContext, rb_intern("tmp_ecdh_callback"), 1, 1, Qfalse); +#endif /* * Sets the context in which a session can be reused. This allows @@ -2265,6 +2374,7 @@ Init_ossl_ssl(void) rb_define_method(cSSLContext, "ssl_version=", ossl_sslctx_set_ssl_version, 1); rb_define_method(cSSLContext, "ciphers", ossl_sslctx_get_ciphers, 0); rb_define_method(cSSLContext, "ciphers=", ossl_sslctx_set_ciphers, 1); + rb_define_method(cSSLContext, "ecdh_curves=", ossl_sslctx_set_ecdh_curves, 1); rb_define_method(cSSLContext, "setup", ossl_sslctx_setup, 0); diff --git a/test/test_pair.rb b/test/test_pair.rb index 4251f1ba..b6b3b935 100644 --- a/test/test_pair.rb +++ b/test/test_pair.rb @@ -372,41 +372,73 @@ module OpenSSL::TestPairM end def test_ecdh_callback - called = false - ctx2 = OpenSSL::SSL::SSLContext.new - ctx2.ciphers = "ECDH" - ctx2.tmp_ecdh_callback = ->(*args) { - called = true - OpenSSL::PKey::EC.new "prime256v1" - } + return unless OpenSSL::SSL::SSLContext.instance_methods.include?(:tmp_ecdh_callback) + EnvUtil.suppress_warning do # tmp_ecdh_callback is deprecated (2016-05) + begin + called = false + ctx2 = OpenSSL::SSL::SSLContext.new + ctx2.ciphers = "ECDH" + ctx2.tmp_ecdh_callback = ->(*args) { + called = true + OpenSSL::PKey::EC.new "prime256v1" + } + + sock1, sock2 = tcp_pair + + s2 = OpenSSL::SSL::SSLSocket.new(sock2, ctx2) + ctx1 = OpenSSL::SSL::SSLContext.new + ctx1.ciphers = "ECDH" + + s1 = OpenSSL::SSL::SSLSocket.new(sock1, ctx1) + th = Thread.new do + begin + rv = s1.connect_nonblock(exception: false) + case rv + when :wait_writable + IO.select(nil, [s1], nil, 5) + when :wait_readable + IO.select([s1], nil, nil, 5) + end + end until rv == s1 + end + + accepted = s2.accept + assert called, 'ecdh callback should be called' + rescue OpenSSL::SSL::SSLError => e + if e.message =~ /no cipher match/ + skip "ECDH cipher not supported." + else + raise e + end + ensure + th.join if th + s1.close if s1 + s2.close if s2 + sock1.close if sock1 + sock2.close if sock2 + end + end + end + def test_ecdh_curves sock1, sock2 = tcp_pair - s2 = OpenSSL::SSL::SSLSocket.new(sock2, ctx2) ctx1 = OpenSSL::SSL::SSLContext.new ctx1.ciphers = "ECDH" - + ctx1.ecdh_curves = "P-384:P-224" s1 = OpenSSL::SSL::SSLSocket.new(sock1, ctx1) - th = Thread.new do - begin - rv = s1.connect_nonblock(exception: false) - case rv - when :wait_writable - IO.select(nil, [s1], nil, 5) - when :wait_readable - IO.select([s1], nil, nil, 5) - end - end until rv == s1 - end - accepted = s2.accept + ctx2 = OpenSSL::SSL::SSLContext.new + ctx2.ciphers = "ECDH" + ctx2.ecdh_curves = "P-256:P-384" + s2 = OpenSSL::SSL::SSLSocket.new(sock2, ctx2) - assert called, 'ecdh callback should be called' - rescue OpenSSL::SSL::SSLError => e - if e.message =~ /no cipher match/ - skip "ECDH cipher not supported." - else - raise e + th = Thread.new { s1.accept } + s2.connect + + assert s2.cipher[0].start_with?("AECDH"), "AECDH should be used" + if s2.respond_to?(:tmp_key) + assert_equal "secp384r1", s2.tmp_key.group.curve_name end ensure th.join if th @@ -414,7 +446,6 @@ module OpenSSL::TestPairM s2.close if s2 sock1.close if sock1 sock2.close if sock2 - accepted.close if accepted.respond_to?(:close) end def test_connect_accept_nonblock_no_exception diff --git a/test/utils.rb b/test/utils.rb index 8ce53290..b6cf6377 100644 --- a/test/utils.rb +++ b/test/utils.rb @@ -282,7 +282,7 @@ AQjjxMXhwULlmuR/K+WwlaZPiLIBYalLAZQ7ZbOPeVkJ8ePao0eLAgEC ctx.cert = @svr_cert ctx.key = @svr_key ctx.tmp_dh_callback = proc { OpenSSL::TestUtils::TEST_KEY_DH1024 } - ctx.tmp_ecdh_callback = proc { OpenSSL::TestUtils::TEST_KEY_EC_P256V1 } + ctx.ecdh_curves = "P-256" ctx.verify_mode = verify_mode ctx_proc.call(ctx) if ctx_proc -- cgit v1.2.3 From 96707e91668d7b17aa222e8beb6f925c4b3a77f3 Mon Sep 17 00:00:00 2001 From: rhe Date: Mon, 30 May 2016 13:02:13 +0000 Subject: openssl: use NUM2TIMET() to convert Integer to time_t * ext/openssl/ossl_asn1.c (time_to_time_t): Use NUM2TIMET() instead of NUM2LONG(). time_t may be larger than long. [ruby-core:45552] [Bug #6571] git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@55219 b2dd03c8-39d4-4d8f-98ff-823fe69b080e --- ext/openssl/ossl_asn1.c | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/ext/openssl/ossl_asn1.c b/ext/openssl/ossl_asn1.c index e77adbf9..43a3d2d8 100644 --- a/ext/openssl/ossl_asn1.c +++ b/ext/openssl/ossl_asn1.c @@ -75,15 +75,10 @@ asn1time_to_time(ASN1_TIME *time) return rb_funcall2(rb_cTime, rb_intern("utc"), 6, argv); } -/* - * This function is not exported in Ruby's *.h - */ -extern struct timeval rb_time_timeval(VALUE); - time_t time_to_time_t(VALUE time) { - return (time_t)NUM2LONG(rb_Integer(time)); + return (time_t)NUM2TIMET(rb_Integer(time)); } /* -- cgit v1.2.3 From 2293533fec90b4adc5368f2fd1ef0fec0832b2f4 Mon Sep 17 00:00:00 2001 From: rhe Date: Mon, 30 May 2016 16:52:10 +0000 Subject: openssl: fix test failure on Fedora 23 * test/openssl/test_pair.rb (test_ecdh_curves): Avoid P-224. The FIPS patch from RHEL disables it. The curve has to be chosen from: { secp256k1, secp384r1, secp521r1, prime256v1 }. git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@55224 b2dd03c8-39d4-4d8f-98ff-823fe69b080e --- test/test_pair.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/test_pair.rb b/test/test_pair.rb index b6b3b935..c8770690 100644 --- a/test/test_pair.rb +++ b/test/test_pair.rb @@ -425,7 +425,7 @@ module OpenSSL::TestPairM ctx1 = OpenSSL::SSL::SSLContext.new ctx1.ciphers = "ECDH" - ctx1.ecdh_curves = "P-384:P-224" + ctx1.ecdh_curves = "P-384:P-521" s1 = OpenSSL::SSL::SSLSocket.new(sock1, ctx1) ctx2 = OpenSSL::SSL::SSLContext.new -- cgit v1.2.3