diff --git a/ext/openssl/History.md b/ext/openssl/History.md index ad3417f9d0..ecc53fad3b 100644 --- a/ext/openssl/History.md +++ b/ext/openssl/History.md @@ -1,3 +1,9 @@ +Version 3.3.1 +============= + +Merged changes in 3.1.2 and 3.2.2. + + Version 3.3.0 ============= @@ -74,6 +80,12 @@ And various non-user-visible changes and bug fixes. Please see the commit history for more details. +Version 3.2.2 +============= + +Merged changes in 3.1.2. + + Version 3.2.1 ============= @@ -120,6 +132,23 @@ Notable changes [[GitHub #141]](https://github.com/ruby/openssl/pull/141) +Version 3.1.2 +============= + +Bug fixes +--------- + +* Fix crash when attempting to export an incomplete `OpenSSL::PKey::DSA` key. + [[GitHub #845]](https://github.com/ruby/openssl/issues/845) + [[GitHub #847]](https://github.com/ruby/openssl/pull/847) +* Remove the `OpenSSL::X509::V_FLAG_CRL_CHECK_ALL` flag from the default store + used by `OpenSSL::SSL::SSLContext#set_params`. It causes certificate + verification to fail with OpenSSL 3.6.0. It has no effect with any other + OpenSSL versions. + [[GitHub #949]](https://github.com/ruby/openssl/issues/949) + [[GitHub #950]](https://github.com/ruby/openssl/pull/950) + + Version 3.1.1 ============= diff --git a/ext/openssl/extconf.rb b/ext/openssl/extconf.rb index 2fcac85e68..adca064904 100644 --- a/ext/openssl/extconf.rb +++ b/ext/openssl/extconf.rb @@ -40,7 +40,7 @@ Logging::message "=== OpenSSL for Ruby configurator ===\n" $defs.push("-D""OPENSSL_SUPPRESS_DEPRECATED") -have_func("rb_io_descriptor", "ruby/io.h") +have_func("rb_io_descriptor") have_func("rb_io_maybe_wait(0, Qnil, Qnil, Qnil)", "ruby/io.h") # Ruby 3.1 have_func("rb_io_timeout", "ruby/io.h") diff --git a/ext/openssl/lib/openssl/ssl.rb b/ext/openssl/lib/openssl/ssl.rb index d6cb260f9a..72ad37aec0 100644 --- a/ext/openssl/lib/openssl/ssl.rb +++ b/ext/openssl/lib/openssl/ssl.rb @@ -92,7 +92,6 @@ ssbzSibBsu/6iGtCOGEoXJf//////////wIBAg== DEFAULT_CERT_STORE = OpenSSL::X509::Store.new # :nodoc: DEFAULT_CERT_STORE.set_default_paths - DEFAULT_CERT_STORE.flags = OpenSSL::X509::V_FLAG_CRL_CHECK_ALL # A callback invoked when DH parameters are required for ephemeral DH key # exchange. diff --git a/ext/openssl/lib/openssl/version.rb b/ext/openssl/lib/openssl/version.rb index 3398fe39cc..8672154c89 100644 --- a/ext/openssl/lib/openssl/version.rb +++ b/ext/openssl/lib/openssl/version.rb @@ -1,5 +1,5 @@ # frozen_string_literal: true module OpenSSL - VERSION = "3.3.0" + VERSION = "3.3.1" end diff --git a/ext/openssl/openssl.gemspec b/ext/openssl/openssl.gemspec index 9f7c718592..732007d8a9 100644 --- a/ext/openssl/openssl.gemspec +++ b/ext/openssl/openssl.gemspec @@ -1,6 +1,6 @@ Gem::Specification.new do |spec| spec.name = "openssl" - spec.version = "3.3.0" + spec.version = "3.3.1" spec.authors = ["Martin Bosslet", "SHIBATA Hiroshi", "Zachary Scott", "Kazuki Yamaguchi"] spec.email = ["ruby-core@ruby-lang.org"] spec.summary = %q{SSL/TLS and general-purpose cryptography for Ruby} diff --git a/ext/openssl/ossl_pkey.c b/ext/openssl/ossl_pkey.c index 6af2245f39..3e1f1e603b 100644 --- a/ext/openssl/ossl_pkey.c +++ b/ext/openssl/ossl_pkey.c @@ -937,6 +937,7 @@ ossl_pkey_export_spki(VALUE self, int to_der) BIO *bio; GetPKey(self, pkey); + ossl_pkey_check_public_key(pkey); bio = BIO_new(BIO_s_mem()); if (!bio) ossl_raise(ePKeyError, "BIO_new"); diff --git a/ext/openssl/ossl_ssl.c b/ext/openssl/ossl_ssl.c index 2525d0c872..b0980d4bba 100644 --- a/ext/openssl/ossl_ssl.c +++ b/ext/openssl/ossl_ssl.c @@ -1959,9 +1959,10 @@ ossl_ssl_read_internal(int argc, VALUE *argv, VALUE self, int nonblock) VALUE io = rb_attr_get(self, id_i_io); - rb_str_locktmp(str); for (;;) { + rb_str_locktmp(str); int nread = SSL_read(ssl, RSTRING_PTR(str), ilen); + rb_str_unlocktmp(str); cb_state = rb_attr_get(self, ID_callback_state); if (!NIL_P(cb_state)) { @@ -1972,32 +1973,27 @@ ossl_ssl_read_internal(int argc, VALUE *argv, VALUE self, int nonblock) switch (ssl_get_error(ssl, nread)) { case SSL_ERROR_NONE: - rb_str_unlocktmp(str); rb_str_set_len(str, nread); return str; case SSL_ERROR_ZERO_RETURN: - rb_str_unlocktmp(str); if (no_exception_p(opts)) { return Qnil; } rb_eof_error(); case SSL_ERROR_WANT_WRITE: if (nonblock) { - rb_str_unlocktmp(str); if (no_exception_p(opts)) { return sym_wait_writable; } write_would_block(nonblock); } io_wait_writable(io); - continue; + break; case SSL_ERROR_WANT_READ: if (nonblock) { - rb_str_unlocktmp(str); if (no_exception_p(opts)) { return sym_wait_readable; } read_would_block(nonblock); } io_wait_readable(io); - continue; + break; case SSL_ERROR_SYSCALL: if (!ERR_peek_error()) { - rb_str_unlocktmp(str); if (errno) rb_sys_fail(0); else { @@ -2014,9 +2010,13 @@ ossl_ssl_read_internal(int argc, VALUE *argv, VALUE self, int nonblock) } /* fall through */ default: - rb_str_unlocktmp(str); ossl_raise(eSSLError, "SSL_read"); } + + // Ensure the buffer is not modified during io_wait_*able() + rb_str_modify(str); + if (rb_str_capacity(str) < (size_t)ilen) + rb_raise(eSSLError, "read buffer was modified"); } } diff --git a/test/openssl/test_bn.rb b/test/openssl/test_bn.rb index 1217f250a7..457af41014 100644 --- a/test/openssl/test_bn.rb +++ b/test/openssl/test_bn.rb @@ -343,28 +343,36 @@ class OpenSSL::TestBN < OpenSSL::TestCase assert_equal(4, e.get_flags(OpenSSL::BN::CONSTTIME)) end - if respond_to?(:ractor) + if defined?(Ractor) && respond_to?(:ractor) + unless Ractor.method_defined?(:value) # Ruby 3.4 or earlier + using Module.new { + refine Ractor do + alias value take + end + } + end + ractor def test_ractor - assert_equal(@e1, Ractor.new { OpenSSL::BN.new("999") }.take) - assert_equal(@e3, Ractor.new { OpenSSL::BN.new("\a\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF", 2) }.take) - assert_equal("999", Ractor.new(@e1) { |e1| e1.to_s }.take) - assert_equal("07FFFFFFFFFFFFFFFFFFFFFFFFFF", Ractor.new(@e3) { |e3| e3.to_s(16) }.take) - assert_equal(2**107-1, Ractor.new(@e3) { _1.to_i }.take) - assert_equal([1000, -999], Ractor.new(@e2) { _1.coerce(1000) }.take) - assert_equal(false, Ractor.new { 1.to_bn.zero? }.take) - assert_equal(true, Ractor.new { 1.to_bn.one? }.take) - assert_equal(true, Ractor.new(@e2) { _1.negative? }.take) - assert_equal("-03E7", Ractor.new(@e2) { _1.to_s(16) }.take) - assert_equal(2**107-1, Ractor.new(@e3) { _1.to_i }.take) - assert_equal([1000, -999], Ractor.new(@e2) { _1.coerce(1000) }.take) - assert_equal(true, Ractor.new { 0.to_bn.zero? }.take) - assert_equal(true, Ractor.new { 1.to_bn.one? }.take ) - assert_equal(false,Ractor.new { 2.to_bn.odd? }.take) - assert_equal(true, Ractor.new(@e2) { _1.negative? }.take) - assert_include(128..255, Ractor.new { OpenSSL::BN.rand(8)}.take) - assert_include(0...2**32, Ractor.new { OpenSSL::BN.generate_prime(32) }.take) - assert_equal(0, Ractor.new { OpenSSL::BN.new(999).get_flags(OpenSSL::BN::CONSTTIME) }.take) + assert_equal(@e1, Ractor.new { OpenSSL::BN.new("999") }.value) + assert_equal(@e3, Ractor.new { OpenSSL::BN.new("\a\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF", 2) }.value) + assert_equal("999", Ractor.new(@e1) { |e1| e1.to_s }.value) + assert_equal("07FFFFFFFFFFFFFFFFFFFFFFFFFF", Ractor.new(@e3) { |e3| e3.to_s(16) }.value) + assert_equal(2**107-1, Ractor.new(@e3) { _1.to_i }.value) + assert_equal([1000, -999], Ractor.new(@e2) { _1.coerce(1000) }.value) + assert_equal(false, Ractor.new { 1.to_bn.zero? }.value) + assert_equal(true, Ractor.new { 1.to_bn.one? }.value) + assert_equal(true, Ractor.new(@e2) { _1.negative? }.value) + assert_equal("-03E7", Ractor.new(@e2) { _1.to_s(16) }.value) + assert_equal(2**107-1, Ractor.new(@e3) { _1.to_i }.value) + assert_equal([1000, -999], Ractor.new(@e2) { _1.coerce(1000) }.value) + assert_equal(true, Ractor.new { 0.to_bn.zero? }.value) + assert_equal(true, Ractor.new { 1.to_bn.one? }.value ) + assert_equal(false,Ractor.new { 2.to_bn.odd? }.value) + assert_equal(true, Ractor.new(@e2) { _1.negative? }.value) + assert_include(128..255, Ractor.new { OpenSSL::BN.rand(8)}.value) + assert_include(0...2**32, Ractor.new { OpenSSL::BN.generate_prime(32) }.value) + assert_equal(0, Ractor.new { OpenSSL::BN.new(999).get_flags(OpenSSL::BN::CONSTTIME) }.value) # test if shareable when frozen assert Ractor.shareable?(@e1.freeze) end diff --git a/test/openssl/test_ossl.rb b/test/openssl/test_ossl.rb index 3a90ead10a..9f4b39d4f5 100644 --- a/test/openssl/test_ossl.rb +++ b/test/openssl/test_ossl.rb @@ -42,12 +42,6 @@ class OpenSSL::OSSL < OpenSSL::SSLTestCase end def test_memcmp_timing - begin - require "benchmark" - rescue LoadError - pend "Benchmark is not available in this environment. Please install it with `gem install benchmark`." - end - # Ensure using fixed_length_secure_compare takes almost exactly the same amount of time to compare two different strings. # Regular string comparison will short-circuit on the first non-matching character, failing this test. # NOTE: this test may be susceptible to noise if the system running the tests is otherwise under load. @@ -58,8 +52,14 @@ class OpenSSL::OSSL < OpenSSL::SSLTestCase a_b_time = a_c_time = 0 100.times do - a_b_time += Benchmark.measure { 100.times { OpenSSL.fixed_length_secure_compare(a, b) } }.real - a_c_time += Benchmark.measure { 100.times { OpenSSL.fixed_length_secure_compare(a, c) } }.real + t1 = Process.clock_gettime(Process::CLOCK_MONOTONIC) + 100.times { OpenSSL.fixed_length_secure_compare(a, b) } + t2 = Process.clock_gettime(Process::CLOCK_MONOTONIC) + 100.times { OpenSSL.fixed_length_secure_compare(a, c) } + t3 = Process.clock_gettime(Process::CLOCK_MONOTONIC) + + a_b_time += t2 - t1 + a_c_time += t3 - t2 end assert_operator(a_b_time, :<, a_c_time * 10, "fixed_length_secure_compare timing test failed") assert_operator(a_c_time, :<, a_b_time * 10, "fixed_length_secure_compare timing test failed") diff --git a/test/openssl/test_pkey_dsa.rb b/test/openssl/test_pkey_dsa.rb index 3e8a83b2d0..cdaa8b32d4 100644 --- a/test/openssl/test_pkey_dsa.rb +++ b/test/openssl/test_pkey_dsa.rb @@ -33,6 +33,12 @@ class OpenSSL::TestPKeyDSA < OpenSSL::PKeyTestCase end end + def test_new_empty + key = OpenSSL::PKey::DSA.new + assert_nil(key.p) + assert_raise(OpenSSL::PKey::PKeyError) { key.to_der } + end + def test_generate # DSA.generate used to call DSA_generate_parameters_ex(), which adjusts the # size of q according to the size of p diff --git a/test/openssl/test_ssl.rb b/test/openssl/test_ssl.rb index 459efcc18e..225dd19e09 100644 --- a/test/openssl/test_ssl.rb +++ b/test/openssl/test_ssl.rb @@ -256,11 +256,16 @@ class OpenSSL::TestSSL < OpenSSL::SSLTestCase ssl.syswrite(str) assert_equal(str, ssl.sysread(str.bytesize)) - ssl.timeout = 1 - assert_raise(IO::TimeoutError) {ssl.read(1)} + ssl.timeout = 0.1 + assert_raise(IO::TimeoutError) { ssl.sysread(1) } ssl.syswrite(str) assert_equal(str, ssl.sysread(str.bytesize)) + + buf = "orig".b + assert_raise(IO::TimeoutError) { ssl.sysread(1, buf) } + assert_equal("orig", buf) + assert_nothing_raised { buf.clear } end end end