From 0bddaf6b35b1a2e26a43f838af3264be5756b648 Mon Sep 17 00:00:00 2001
From: Kazuki Yamaguchi <k@rhe.jp>
Date: Mon, 25 Sep 2017 01:32:02 +0900
Subject: [PATCH] openssl: import v2.0.6

Import Ruby/OpenSSL 2.0.6. This contains only bug fixes and test
improvements. The full commit log since v2.0.5 (imported at r59567, to
trunk) can be found at:

	https://github.com/ruby/openssl/compare/v2.0.5...v2.0.6

All the changes included in this patch are already imported to trunk by
r59734, r59751, r59857, and r60013.

----------------------------------------------------------------
Antonio Terceiro (1):
      test/test_ssl: explicitly accept TLS 1.1 in corresponding test

Kazuki Yamaguchi (31):
      ssl: do not call session_remove_cb during GC
      Backport "Merge branch 'topic/test-memory-leak'" to maint
      cipher: update the documentation for Cipher#auth_tag=
      Rakefile: let sync:to_ruby know about test/openssl/fixtures
      test: fix formatting
      test/utils: remove OpenSSL::TestUtils.silent
      test/utils: add SSLTestCase#tls12_supported?
      test/utils: have start_server yield only the port number
      test/utils: do not set ecdh_curves in start_server
      test/utils: let server_loop close socket
      test/utils: improve error handling in start_server
      test/utils: add OpenSSL::TestUtils.openssl? and .libressl?
      test/utils: do not use DSA certificates in SSL tests
      test/test_ssl: remove test_invalid_shutdown_by_gc
      test/test_ssl: move test_multibyte_read_write to test_pair
      test/test_ssl_session: rearrange tests
      test/test_pair, test/test_ssl: fix for TLS 1.3
      ssl: remove useless call to rb_thread_wait_fd()
      test/test_pair: fix test_write_nonblock{,_no_exceptions}
      test/test_ssl: suppress warning in test_alpn_protocol_selection_cancel
      test/test_pair: disable compression
      test/test_ssl: skip tmp_ecdh_callback test for LibreSSL >= 2.6.1
      test/test_ssl: do not run NPN tests for LibreSSL >= 2.6.1
      tool/ruby-openssl-docker: update
      test/test_pair: replace sleep with IO.select
      ssl: prevent SSLSocket#sysread* from leaking uninitialized data
      ossl.c: use struct CRYPTO_dynlock_value for non-dynamic locks
      ossl.c: make legacy locking callbacks reentrant
      test/test_engine: suppress stderr
      test/test_engine: check if RC4 is supported
      Ruby/OpenSSL 2.0.6

nobu (1):
      ruby.h: unnormalized Fixnum value
---
 ext/openssl/History.md                 |  20 ++
 ext/openssl/lib/openssl/buffering.rb   |   9 +-
 ext/openssl/openssl.gemspec            |   8 +-
 ext/openssl/ossl.c                     | 175 ++++++++++---
 ext/openssl/ossl_cipher.c              |  12 +-
 ext/openssl/ossl_ssl.c                 |  43 +--
 ext/openssl/ossl_version.h             |   2 +-
 ext/openssl/ruby_missing.h             |  10 +-
 test/openssl/fixtures/pkey/dh1024.pem  |   5 +
 test/openssl/fixtures/pkey/dsa1024.pem |  12 +
 test/openssl/fixtures/pkey/dsa256.pem  |   8 +
 test/openssl/fixtures/pkey/dsa512.pem  |   8 +
 test/openssl/fixtures/pkey/p256.pem    |   5 +
 test/openssl/fixtures/pkey/rsa1024.pem |  15 ++
 test/openssl/fixtures/pkey/rsa2048.pem |  27 ++
 test/openssl/test_asn1.rb              |   7 +-
 test/openssl/test_bn.rb                |   1 +
 test/openssl/test_buffering.rb         |   7 +-
 test/openssl/test_config.rb            |  12 +-
 test/openssl/test_digest.rb            |  65 ++---
 test/openssl/test_engine.rb            |  42 ++-
 test/openssl/test_hmac.rb              |   6 +-
 test/openssl/test_ns_spki.rb           |   4 +-
 test/openssl/test_ocsp.rb              |  10 +-
 test/openssl/test_pair.rb              | 212 ++++++++-------
 test/openssl/test_pkcs12.rb            |  43 ++-
 test/openssl/test_pkcs5.rb             |   6 +-
 test/openssl/test_pkcs7.rb             |   8 +-
 test/openssl/test_pkey_dh.rb           |  21 +-
 test/openssl/test_pkey_dsa.rb          |  65 ++---
 test/openssl/test_pkey_ec.rb           |  46 ++--
 test/openssl/test_pkey_rsa.rb          |  76 +++---
 test/openssl/test_random.rb            |   6 +-
 test/openssl/test_ssl.rb               | 445 +++++++++++++++----------------
 test/openssl/test_ssl_session.rb       | 403 ++++++++++++++--------------
 test/openssl/test_x509cert.rb          |  12 +-
 test/openssl/test_x509crl.rb           |  16 +-
 test/openssl/test_x509name.rb          |   1 -
 test/openssl/test_x509req.rb           |   8 +-
 test/openssl/test_x509store.rb         |  32 +--
 test/openssl/ut_eof.rb                 |   4 +
 test/openssl/utils.rb                  | 464 ++++++++++++++-------------------
 42 files changed, 1245 insertions(+), 1136 deletions(-)
 create mode 100644 test/openssl/fixtures/pkey/dh1024.pem
 create mode 100644 test/openssl/fixtures/pkey/dsa1024.pem
 create mode 100644 test/openssl/fixtures/pkey/dsa256.pem
 create mode 100644 test/openssl/fixtures/pkey/dsa512.pem
 create mode 100644 test/openssl/fixtures/pkey/p256.pem
 create mode 100644 test/openssl/fixtures/pkey/rsa1024.pem
 create mode 100644 test/openssl/fixtures/pkey/rsa2048.pem

diff --git a/ext/openssl/History.md b/ext/openssl/History.md
index 8baa0208ea8b..d592bc6a1f08 100644
--- a/ext/openssl/History.md
+++ b/ext/openssl/History.md
@@ -1,3 +1,23 @@
+Version 2.0.6
+=============
+
+Bug fixes
+---------
+
+* The session_remove_cb set to an OpenSSL::SSL::SSLContext is no longer called
+  during GC.
+* A possible deadlock in OpenSSL::SSL::SSLSocket#sysread is fixed.
+  [[GitHub #139]](https://github.com/ruby/openssl/pull/139)
+* OpenSSL::BN#hash could return an unnormalized fixnum value on Windows.
+  [[Bug #13877]](https://bugs.ruby-lang.org/issues/13877)
+* OpenSSL::SSL::SSLSocket#sysread and #sysread_nonblock set the length of the
+  destination buffer String to 0 on error.
+  [[GitHub #153]](https://github.com/ruby/openssl/pull/153)
+* Possible deadlock is fixed. This happened only when built with older versions
+  of OpenSSL (before 1.1.0) or LibreSSL.
+  [[GitHub #155]](https://github.com/ruby/openssl/pull/155)
+
+
 Version 2.0.5
 =============
 
diff --git a/ext/openssl/lib/openssl/buffering.rb b/ext/openssl/lib/openssl/buffering.rb
index d773637c0e52..b0dffefd3e9f 100644
--- a/ext/openssl/lib/openssl/buffering.rb
+++ b/ext/openssl/lib/openssl/buffering.rb
@@ -164,10 +164,9 @@ def readpartial(maxlen, buf=nil)
   # when the peer requests a new TLS/SSL handshake.  See openssl the FAQ for
   # more details.  http://www.openssl.org/support/faq.html
   #
-  # By specifying a keyword argument _exception_ to +false+, you can indicate
+  # By specifying `exception: false`, the options hash allows you to indicate
   # that read_nonblock should not raise an IO::Wait*able exception, but
-  # return the symbol +:wait_writable+ or +:wait_readable+ instead. At EOF,
-  # it will return +nil+ instead of raising EOFError.
+  # return the symbol :wait_writable or :wait_readable instead.
 
   def read_nonblock(maxlen, buf=nil, exception: true)
     if maxlen == 0
@@ -377,9 +376,9 @@ def write(s)
   # is when the peer requests a new TLS/SSL handshake.  See the openssl FAQ
   # for more details.  http://www.openssl.org/support/faq.html
   #
-  # By specifying a keyword argument _exception_ to +false+, you can indicate
+  # By specifying `exception: false`, the options hash allows you to indicate
   # that write_nonblock should not raise an IO::Wait*able exception, but
-  # return the symbol +:wait_writable+ or +:wait_readable+ instead.
+  # return the symbol :wait_writable or :wait_readable instead.
 
   def write_nonblock(s, exception: true)
     flush
diff --git a/ext/openssl/openssl.gemspec b/ext/openssl/openssl.gemspec
index 7cbbfeb51357..2af041ebde9b 100644
--- a/ext/openssl/openssl.gemspec
+++ b/ext/openssl/openssl.gemspec
@@ -1,16 +1,16 @@
 # -*- encoding: utf-8 -*-
-# stub: openssl 2.0.5 ruby lib
+# stub: openssl 2.0.6 ruby lib
 # stub: ext/openssl/extconf.rb
 
 Gem::Specification.new do |s|
   s.name = "openssl".freeze
-  s.version = "2.0.5"
+  s.version = "2.0.6"
 
   s.required_rubygems_version = Gem::Requirement.new(">= 0".freeze) if s.respond_to? :required_rubygems_version=
   s.metadata = { "msys2_mingw_dependencies" => "openssl" } if s.respond_to? :metadata=
   s.require_paths = ["lib".freeze]
   s.authors = ["Martin Bosslet".freeze, "SHIBATA Hiroshi".freeze, "Zachary Scott".freeze, "Kazuki Yamaguchi".freeze]
-  s.date = "2017-08-08"
+  s.date = "2017-09-24"
   s.description = "It wraps the OpenSSL library.".freeze
   s.email = ["ruby-core@ruby-lang.org".freeze]
   s.extensions = ["ext/openssl/extconf.rb".freeze]
@@ -20,7 +20,7 @@
   s.licenses = ["Ruby".freeze]
   s.rdoc_options = ["--main".freeze, "README.md".freeze]
   s.required_ruby_version = Gem::Requirement.new(">= 2.3.0".freeze)
-  s.rubygems_version = "2.6.12".freeze
+  s.rubygems_version = "2.6.13".freeze
   s.summary = "OpenSSL provides SSL, TLS and general purpose cryptography.".freeze
 
   if s.respond_to? :specification_version then
diff --git a/ext/openssl/ossl.c b/ext/openssl/ossl.c
index c22966df5a50..88bb8f210136 100644
--- a/ext/openssl/ossl.c
+++ b/ext/openssl/ossl.c
@@ -414,44 +414,123 @@ ossl_fips_mode_set(VALUE self, VALUE enabled)
 #endif
 }
 
+#if defined(OSSL_DEBUG)
+#if !defined(LIBRESSL_VERSION_NUMBER) && \
+    (OPENSSL_VERSION_NUMBER >= 0x10100000 && !defined(OPENSSL_NO_CRYPTO_MDEBUG) || \
+     defined(CRYPTO_malloc_debug_init))
+/*
+ * call-seq:
+ *   OpenSSL.mem_check_start -> nil
+ *
+ * Calls CRYPTO_mem_ctrl(CRYPTO_MEM_CHECK_ON). Starts tracking memory
+ * allocations. See also OpenSSL.print_mem_leaks.
+ *
+ * This is available only when built with a capable OpenSSL and --enable-debug
+ * configure option.
+ */
+static VALUE
+mem_check_start(VALUE self)
+{
+	CRYPTO_mem_ctrl(CRYPTO_MEM_CHECK_ON);
+	return Qnil;
+}
+
+/*
+ * call-seq:
+ *   OpenSSL.print_mem_leaks -> true | false
+ *
+ * For debugging the Ruby/OpenSSL library. Calls CRYPTO_mem_leaks_fp(stderr).
+ * Prints detected memory leaks to standard error. This cleans the global state
+ * up thus you cannot use any methods of the library after calling this.
+ *
+ * Returns true if leaks detected, false otherwise.
+ *
+ * This is available only when built with a capable OpenSSL and --enable-debug
+ * configure option.
+ *
+ * === Example
+ *   OpenSSL.mem_check_start
+ *   NOT_GCED = OpenSSL::PKey::RSA.new(256)
+ *
+ *   END {
+ *     GC.start
+ *     OpenSSL.print_mem_leaks # will print the leakage
+ *   }
+ */
+static VALUE
+print_mem_leaks(VALUE self)
+{
+#if OPENSSL_VERSION_NUMBER >= 0x10100000
+    int ret;
+#endif
+
+    BN_CTX_free(ossl_bn_ctx);
+    ossl_bn_ctx = NULL;
+
+#if OPENSSL_VERSION_NUMBER >= 0x10100000
+    ret = CRYPTO_mem_leaks_fp(stderr);
+    if (ret < 0)
+	ossl_raise(eOSSLError, "CRYPTO_mem_leaks_fp");
+    return ret ? Qfalse : Qtrue;
+#else
+    CRYPTO_mem_leaks_fp(stderr);
+    return Qnil;
+#endif
+}
+#endif
+#endif
+
 #if !defined(HAVE_OPENSSL_110_THREADING_API)
 /**
  * Stores locks needed for OpenSSL thread safety
  */
-static rb_nativethread_lock_t *ossl_locks;
+struct CRYPTO_dynlock_value {
+    rb_nativethread_lock_t lock;
+    rb_nativethread_id_t owner;
+    size_t count;
+};
 
 static void
-ossl_lock_unlock(int mode, rb_nativethread_lock_t *lock)
+ossl_lock_init(struct CRYPTO_dynlock_value *l)
 {
-    if (mode & CRYPTO_LOCK) {
-	rb_nativethread_lock_lock(lock);
-    } else {
-	rb_nativethread_lock_unlock(lock);
-    }
+    rb_nativethread_lock_initialize(&l->lock);
+    l->count = 0;
 }
 
 static void
-ossl_lock_callback(int mode, int type, const char *file, int line)
+ossl_lock_unlock(int mode, struct CRYPTO_dynlock_value *l)
 {
-    ossl_lock_unlock(mode, &ossl_locks[type]);
+    if (mode & CRYPTO_LOCK) {
+	/* TODO: rb_nativethread_id_t is not necessarily compared with ==. */
+	rb_nativethread_id_t tid = rb_nativethread_self();
+	if (l->count && l->owner == tid) {
+	    l->count++;
+	    return;
+	}
+	rb_nativethread_lock_lock(&l->lock);
+	l->owner = tid;
+	l->count = 1;
+    } else {
+	if (!--l->count)
+	    rb_nativethread_lock_unlock(&l->lock);
+    }
 }
 
-struct CRYPTO_dynlock_value {
-    rb_nativethread_lock_t lock;
-};
-
 static struct CRYPTO_dynlock_value *
 ossl_dyn_create_callback(const char *file, int line)
 {
-    struct CRYPTO_dynlock_value *dynlock = (struct CRYPTO_dynlock_value *)OPENSSL_malloc((int)sizeof(struct CRYPTO_dynlock_value));
-    rb_nativethread_lock_initialize(&dynlock->lock);
+    /* Do not use xmalloc() here, since it may raise NoMemoryError */
+    struct CRYPTO_dynlock_value *dynlock =
+	OPENSSL_malloc(sizeof(struct CRYPTO_dynlock_value));
+    if (dynlock)
+	ossl_lock_init(dynlock);
     return dynlock;
 }
 
 static void
 ossl_dyn_lock_callback(int mode, struct CRYPTO_dynlock_value *l, const char *file, int line)
 {
-    ossl_lock_unlock(mode, &l->lock);
+    ossl_lock_unlock(mode, l);
 }
 
 static void
@@ -475,21 +554,22 @@ static unsigned long ossl_thread_id(void)
 }
 #endif
 
+static struct CRYPTO_dynlock_value *ossl_locks;
+
+static void
+ossl_lock_callback(int mode, int type, const char *file, int line)
+{
+    ossl_lock_unlock(mode, &ossl_locks[type]);
+}
+
 static void Init_ossl_locks(void)
 {
     int i;
     int num_locks = CRYPTO_num_locks();
 
-    if ((unsigned)num_locks >= INT_MAX / (int)sizeof(VALUE)) {
-	rb_raise(rb_eRuntimeError, "CRYPTO_num_locks() is too big: %d", num_locks);
-    }
-    ossl_locks = (rb_nativethread_lock_t *) OPENSSL_malloc(num_locks * (int)sizeof(rb_nativethread_lock_t));
-    if (!ossl_locks) {
-	rb_raise(rb_eNoMemError, "CRYPTO_num_locks() is too big: %d", num_locks);
-    }
-    for (i = 0; i < num_locks; i++) {
-	rb_nativethread_lock_initialize(&ossl_locks[i]);
-    }
+    ossl_locks = ALLOC_N(struct CRYPTO_dynlock_value, num_locks);
+    for (i = 0; i < num_locks; i++)
+	ossl_lock_init(&ossl_locks[i]);
 
 #ifdef HAVE_CRYPTO_THREADID_PTR
     CRYPTO_THREADID_set_callback(ossl_threadid_func);
@@ -1114,15 +1194,40 @@ Init_openssl(void)
     Init_ossl_ocsp();
     Init_ossl_engine();
     Init_ossl_asn1();
-}
 
 #if defined(OSSL_DEBUG)
-/*
- * Check if all symbols are OK with 'make LDSHARED=gcc all'
- */
-int
-main(int argc, char *argv[])
-{
-    return 0;
+    /*
+     * For debugging Ruby/OpenSSL. Enable only when built with --enable-debug
+     */
+#if !defined(LIBRESSL_VERSION_NUMBER) && \
+    (OPENSSL_VERSION_NUMBER >= 0x10100000 && !defined(OPENSSL_NO_CRYPTO_MDEBUG) || \
+     defined(CRYPTO_malloc_debug_init))
+    rb_define_module_function(mOSSL, "mem_check_start", mem_check_start, 0);
+    rb_define_module_function(mOSSL, "print_mem_leaks", print_mem_leaks, 0);
+
+#if defined(CRYPTO_malloc_debug_init) /* <= 1.0.2 */
+    CRYPTO_malloc_debug_init();
+#endif
+
+#if defined(V_CRYPTO_MDEBUG_ALL) /* <= 1.0.2 */
+    CRYPTO_set_mem_debug_options(V_CRYPTO_MDEBUG_ALL);
+#endif
+
+#if OPENSSL_VERSION_NUMBER < 0x10100000 /* <= 1.0.2 */
+    {
+	int i;
+	/*
+	 * See crypto/ex_data.c; call def_get_class() immediately to avoid
+	 * allocations. 15 is the maximum number that is used as the class index
+	 * in OpenSSL 1.0.2.
+	 */
+	for (i = 0; i <= 15; i++) {
+	    if (CRYPTO_get_ex_new_index(i, 0, (void *)"ossl-mdebug-dummy", 0, 0, 0) < 0)
+		rb_raise(rb_eRuntimeError, "CRYPTO_get_ex_new_index for "
+			 "class index %d failed", i);
+	}
+    }
+#endif
+#endif
+#endif
 }
-#endif /* OSSL_DEBUG */
diff --git a/ext/openssl/ossl_cipher.c b/ext/openssl/ossl_cipher.c
index c2f0927a75d4..36e42ede8c92 100644
--- a/ext/openssl/ossl_cipher.c
+++ b/ext/openssl/ossl_cipher.c
@@ -631,13 +631,11 @@ ossl_cipher_get_auth_tag(int argc, VALUE *argv, VALUE self)
  *  call-seq:
  *     cipher.auth_tag = string -> string
  *
- *  Sets the authentication tag to verify the contents of the
- *  ciphertext. The tag must be set after calling Cipher#decrypt,
- *  Cipher#key= and Cipher#iv=, but before assigning the associated
- *  authenticated data using Cipher#auth_data= and of course, before
- *  decrypting any of the ciphertext. After all decryption is
- *  performed, the tag is verified automatically in the call to
- *  Cipher#final.
+ *  Sets the authentication tag to verify the integrity of the ciphertext.
+ *  This can be called only when the cipher supports AE. The tag must be set
+ *  after calling Cipher#decrypt, Cipher#key= and Cipher#iv=, but before
+ *  calling Cipher#final. After all decryption is performed, the tag is
+ *  verified automatically in the call to Cipher#final.
  *
  *  For OCB mode, the tag length must be supplied with #auth_tag_len=
  *  beforehand.
diff --git a/ext/openssl/ossl_ssl.c b/ext/openssl/ossl_ssl.c
index f9c9d76fc27b..aa2dbbc8f748 100644
--- a/ext/openssl/ossl_ssl.c
+++ b/ext/openssl/ossl_ssl.c
@@ -476,6 +476,13 @@ ossl_sslctx_session_remove_cb(SSL_CTX *ctx, SSL_SESSION *sess)
     void *ptr;
     int state = 0;
 
+    /*
+     * This callback is also called for all sessions in the internal store
+     * when SSL_CTX_free() is called.
+     */
+    if (rb_during_gc())
+	return;
+
     OSSL_Debug("SSL SESSION remove callback entered");
 
     if ((ptr = SSL_CTX_get_ex_data(ctx, ossl_ssl_ex_ptr_idx)) == NULL)
@@ -1601,10 +1608,10 @@ ossl_ssl_connect(VALUE self)
  *     retry
  *   end
  *
- * By specifying a keyword argument _exception_ to +false+, you can indicate
+ * By specifying `exception: false`, the options hash allows you to indicate
  * that connect_nonblock should not raise an IO::WaitReadable or
- * IO::WaitWritable exception, but return the symbol +:wait_readable+ or
- * +:wait_writable+ instead.
+ * IO::WaitWritable exception, but return the symbol :wait_readable or
+ * :wait_writable instead.
  */
 static VALUE
 ossl_ssl_connect_nonblock(int argc, VALUE *argv, VALUE self)
@@ -1649,10 +1656,10 @@ ossl_ssl_accept(VALUE self)
  *     retry
  *   end
  *
- * By specifying a keyword argument _exception_ to +false+, you can indicate
+ * By specifying `exception: false`, the options hash allows you to indicate
  * that accept_nonblock should not raise an IO::WaitReadable or
- * IO::WaitWritable exception, but return the symbol +:wait_readable+ or
- * +:wait_writable+ instead.
+ * IO::WaitWritable exception, but return the symbol :wait_readable or
+ * :wait_writable instead.
  */
 static VALUE
 ossl_ssl_accept_nonblock(int argc, VALUE *argv, VALUE self)
@@ -1681,22 +1688,26 @@ ossl_ssl_read_internal(int argc, VALUE *argv, VALUE self, int nonblock)
     }
 
     ilen = NUM2INT(len);
-    if(NIL_P(str)) str = rb_str_new(0, ilen);
-    else{
-        StringValue(str);
-        rb_str_modify(str);
-        rb_str_resize(str, ilen);
+    if (NIL_P(str))
+	str = rb_str_new(0, ilen);
+    else {
+	StringValue(str);
+	if (RSTRING_LEN(str) >= ilen)
+	    rb_str_modify(str);
+	else
+	    rb_str_modify_expand(str, ilen - RSTRING_LEN(str));
     }
-    if(ilen == 0) return str;
+    OBJ_TAINT(str);
+    rb_str_set_len(str, 0);
+    if (ilen == 0)
+	return str;
 
     GetSSL(self, ssl);
     io = rb_attr_get(self, id_i_io);
     GetOpenFile(io, fptr);
     if (ssl_started(ssl)) {
-	if(!nonblock && SSL_pending(ssl) <= 0)
-	    rb_thread_wait_fd(FPTR_TO_FD(fptr));
 	for (;;){
-	    nread = SSL_read(ssl, RSTRING_PTR(str), RSTRING_LENINT(str));
+	    nread = SSL_read(ssl, RSTRING_PTR(str), ilen);
 	    switch(ssl_get_error(ssl, nread)){
 	    case SSL_ERROR_NONE:
 		goto end;
@@ -1746,8 +1757,6 @@ ossl_ssl_read_internal(int argc, VALUE *argv, VALUE self, int nonblock)
 
   end:
     rb_str_set_len(str, nread);
-    OBJ_TAINT(str);
-
     return str;
 }
 
diff --git a/ext/openssl/ossl_version.h b/ext/openssl/ossl_version.h
index be3eebe1f269..7725bc05253e 100644
--- a/ext/openssl/ossl_version.h
+++ b/ext/openssl/ossl_version.h
@@ -10,6 +10,6 @@
 #if !defined(_OSSL_VERSION_H_)
 #define _OSSL_VERSION_H_
 
-#define OSSL_VERSION "2.0.5"
+#define OSSL_VERSION "2.0.6"
 
 #endif /* _OSSL_VERSION_H_ */
diff --git a/ext/openssl/ruby_missing.h b/ext/openssl/ruby_missing.h
index 8dacc8266e83..5b1481aea700 100644
--- a/ext/openssl/ruby_missing.h
+++ b/ext/openssl/ruby_missing.h
@@ -15,9 +15,15 @@
 
 #define FPTR_TO_FD(fptr) ((fptr)->fd)
 
+/* Ruby 2.4 */
 #ifndef RB_INTEGER_TYPE_P
-/* for Ruby 2.3 compatibility */
-#define RB_INTEGER_TYPE_P(obj) (RB_FIXNUM_P(obj) || RB_TYPE_P(obj, T_BIGNUM))
+# define RB_INTEGER_TYPE_P(obj) (RB_FIXNUM_P(obj) || RB_TYPE_P(obj, T_BIGNUM))
+#endif
+
+/* Ruby 2.5 */
+#ifndef ST2FIX
+# define RB_ST2FIX(h) LONG2FIX((long)(h))
+# define ST2FIX(h) RB_ST2FIX(h)
 #endif
 
 #endif /* _OSSL_RUBY_MISSING_H_ */
diff --git a/test/openssl/fixtures/pkey/dh1024.pem b/test/openssl/fixtures/pkey/dh1024.pem
new file mode 100644
index 000000000000..f99c757f21a4
--- /dev/null
+++ b/test/openssl/fixtures/pkey/dh1024.pem
@@ -0,0 +1,5 @@
+-----BEGIN DH PARAMETERS-----
+MIGHAoGBAKnKQ8MNK6nYZzLrrcuTsLxuiJGXoOO5gT+tljOTbHBuiktdMTITzIY0
+pFxIvjG05D7HoBZQfrR0c92NGWPkAiCkhQKB8JCbPVzwNLDy6DZ0pmofDKrEsYHG
+AQjjxMXhwULlmuR/K+WwlaZPiLIBYalLAZQ7ZbOPeVkJ8ePao0eLAgEC
+-----END DH PARAMETERS-----
diff --git a/test/openssl/fixtures/pkey/dsa1024.pem b/test/openssl/fixtures/pkey/dsa1024.pem
new file mode 100644
index 000000000000..1bf498895e2a
--- /dev/null
+++ b/test/openssl/fixtures/pkey/dsa1024.pem
@@ -0,0 +1,12 @@
+-----BEGIN DSA PRIVATE KEY-----
+MIIBugIBAAKBgQCH9aAoXvWWThIjkA6D+nI1F9ksF9iDq594rkiGNOT9sPDOdB+n
+D+qeeeeloRlj19ymCSADPI0ZLRgkchkAEnY2RnqnhHOjVf/roGgRbW+iQDMbQ9wa
+/pvc6/fAbsu1goE1hBYjm98/sZEeXavj8tR56IXnjF1b6Nx0+sgeUKFKEQIVAMiz
+4BJUFeTtddyM4uadBM7HKLPRAoGAZdLBSYNGiij7vAjesF5mGUKTIgPd+JKuBEDx
+OaBclsgfdoyoF/TMOkIty+PVlYD+//Vl2xnoUEIRaMXHwHfm0r2xUX++oeRaSScg
+YizJdUxe5jvBuBszGPRc/mGpb9YvP0sB+FL1KmuxYmdODfCe51zl8uM/CVhouJ3w
+DjmRGscCgYAuFlfC7p+e8huCKydfcv/beftqjewiOPpQ3u5uI6KPCtCJPpDhs3+4
+IihH2cPsAlqwGF4tlibW1+/z/OZ1AZinPK3y7b2jSJASEaPeEltVzB92hcd1khk2
+jTYcmSsV4VddplOPK9czytR/GbbibxsrhhgZUbd8LPbvIgaiadJ1PgIUBnJ/5vN2
+CVArsEzlPUCbohPvZnE=
+-----END DSA PRIVATE KEY-----
diff --git a/test/openssl/fixtures/pkey/dsa256.pem b/test/openssl/fixtures/pkey/dsa256.pem
new file mode 100644
index 000000000000..d9a407f73689
--- /dev/null
+++ b/test/openssl/fixtures/pkey/dsa256.pem
@@ -0,0 +1,8 @@
+-----BEGIN DSA PRIVATE KEY-----
+MIH3AgEAAkEAhk2libbY2a8y2Pt21+YPYGZeW6wzaW2yfj5oiClXro9XMR7XWLkE
+9B7XxLNFCS2gmCCdMsMW1HulaHtLFQmB2wIVAM43JZrcgpu6ajZ01VkLc93gu/Ed
+AkAOhujZrrKV5CzBKutKLb0GVyVWmdC7InoNSMZEeGU72rT96IjM59YzoqmD0pGM
+3I1o4cGqg1D1DfM1rQlnN1eSAkBq6xXfEDwJ1mLNxF6q8Zm/ugFYWR5xcX/3wFiT
+b4+EjHP/DbNh9Vm5wcfnDBJ1zKvrMEf2xqngYdrV/3CiGJeKAhRvL57QvJZcQGvn
+ISNX5cMzFHRW3Q==
+-----END DSA PRIVATE KEY-----
diff --git a/test/openssl/fixtures/pkey/dsa512.pem b/test/openssl/fixtures/pkey/dsa512.pem
new file mode 100644
index 000000000000..962c41cc67fc
--- /dev/null
+++ b/test/openssl/fixtures/pkey/dsa512.pem
@@ -0,0 +1,8 @@
+-----BEGIN DSA PRIVATE KEY-----
+MIH4AgEAAkEA5lB4GvEwjrsMlGDqGsxrbqeFRh6o9OWt6FgTYiEEHaOYhkIxv0Ok
+RZPDNwOG997mDjBnvDJ1i56OmS3MbTnovwIVAJgub/aDrSDB4DZGH7UyarcaGy6D
+AkB9HdFw/3td8K4l1FZHv7TCZeJ3ZLb7dF3TWoGUP003RCqoji3/lHdKoVdTQNuR
+S/m6DlCwhjRjiQ/lBRgCLCcaAkEAjN891JBjzpMj4bWgsACmMggFf57DS0Ti+5++
+Q1VB8qkJN7rA7/2HrCR3gTsWNb1YhAsnFsoeRscC+LxXoXi9OAIUBG98h4tilg6S
+55jreJD3Se3slps=
+-----END DSA PRIVATE KEY-----
diff --git a/test/openssl/fixtures/pkey/p256.pem b/test/openssl/fixtures/pkey/p256.pem
new file mode 100644
index 000000000000..97c97d9f9dd8
--- /dev/null
+++ b/test/openssl/fixtures/pkey/p256.pem
@@ -0,0 +1,5 @@
+-----BEGIN EC PRIVATE KEY-----
+MHcCAQEEIID49FDqcf1O1eO8saTgG70UbXQw9Fqwseliit2aWhH1oAoGCCqGSM49
+AwEHoUQDQgAEFglk2c+oVUIKQ64eZG9bhLNPWB7lSZ/ArK41eGy5wAzU/0G51Xtt
+CeBUl+MahZtn9fO1JKdF4qJmS39dXnpENg==
+-----END EC PRIVATE KEY-----
diff --git a/test/openssl/fixtures/pkey/rsa1024.pem b/test/openssl/fixtures/pkey/rsa1024.pem
new file mode 100644
index 000000000000..464de074be89
--- /dev/null
+++ b/test/openssl/fixtures/pkey/rsa1024.pem
@@ -0,0 +1,15 @@
+-----BEGIN RSA PRIVATE KEY-----
+MIICXgIBAAKBgQDLwsSw1ECnPtT+PkOgHhcGA71nwC2/nL85VBGnRqDxOqjVh7Cx
+aKPERYHsk4BPCkE3brtThPWc9kjHEQQ7uf9Y1rbCz0layNqHyywQEVLFmp1cpIt/
+Q3geLv8ZD9pihowKJDyMDiN6ArYUmZczvW4976MU3+l54E6lF/JfFEU5hwIDAQAB
+AoGBAKSl/MQarye1yOysqX6P8fDFQt68VvtXkNmlSiKOGuzyho0M+UVSFcs6k1L0
+maDE25AMZUiGzuWHyaU55d7RXDgeskDMakD1v6ZejYtxJkSXbETOTLDwUWTn618T
+gnb17tU1jktUtU67xK/08i/XodlgnQhs6VoHTuCh3Hu77O6RAkEA7+gxqBuZR572
+74/akiW/SuXm0SXPEviyO1MuSRwtI87B02D0qgV8D1UHRm4AhMnJ8MCs1809kMQE
+JiQUCrp9mQJBANlt2ngBO14us6NnhuAseFDTBzCHXwUUu1YKHpMMmxpnGqaldGgX
+sOZB3lgJsT9VlGf3YGYdkLTNVbogQKlKpB8CQQDiSwkb4vyQfDe8/NpU5Not0fII
+8jsDUCb+opWUTMmfbxWRR3FBNu8wnym/m19N4fFj8LqYzHX4KY0oVPu6qvJxAkEA
+wa5snNekFcqONLIE4G5cosrIrb74sqL8GbGb+KuTAprzj5z1K8Bm0UW9lTjVDjDi
+qRYgZfZSL+x1P/54+xTFSwJAY1FxA/N3QPCXCjPh5YqFxAMQs2VVYTfg+t0MEcJD
+dPMQD5JX6g5HKnHFg2mZtoXQrWmJSn7p8GJK8yNTopEErA==
+-----END RSA PRIVATE KEY-----
diff --git a/test/openssl/fixtures/pkey/rsa2048.pem b/test/openssl/fixtures/pkey/rsa2048.pem
new file mode 100644
index 000000000000..ac89cd88ed91
--- /dev/null
+++ b/test/openssl/fixtures/pkey/rsa2048.pem
@@ -0,0 +1,27 @@
+-----BEGIN RSA PRIVATE KEY-----
+MIIEpAIBAAKCAQEAuV9ht9J7k4NBs38jOXvvTKY9gW8nLICSno5EETR1cuF7i4pN
+s9I1QJGAFAX0BEO4KbzXmuOvfCpD3CU+Slp1enenfzq/t/e/1IRW0wkJUJUFQign
+4CtrkJL+P07yx18UjyPlBXb81ApEmAB5mrJVSrWmqbjs07JbuS4QQGGXLc+Su96D
+kYKmSNVjBiLxVVSpyZfAY3hD37d60uG+X8xdW5v68JkRFIhdGlb6JL8fllf/A/bl
+NwdJOhVr9mESHhwGjwfSeTDPfd8ZLE027E5lyAVX9KZYcU00mOX+fdxOSnGqS/8J
+DRh0EPHDL15RcJjV2J6vZjPb0rOYGDoMcH+94wIDAQABAoIBAAzsamqfYQAqwXTb
+I0CJtGg6msUgU7HVkOM+9d3hM2L791oGHV6xBAdpXW2H8LgvZHJ8eOeSghR8+dgq
+PIqAffo4x1Oma+FOg3A0fb0evyiACyrOk+EcBdbBeLo/LcvahBtqnDfiUMQTpy6V
+seSoFCwuN91TSCeGIsDpRjbG1vxZgtx+uI+oH5+ytqJOmfCksRDCkMglGkzyfcl0
+Xc5CUhIJ0my53xijEUQl19rtWdMnNnnkdbG8PT3LZlOta5Do86BElzUYka0C6dUc
+VsBDQ0Nup0P6rEQgy7tephHoRlUGTYamsajGJaAo1F3IQVIrRSuagi7+YpSpCqsW
+wORqorkCgYEA7RdX6MDVrbw7LePnhyuaqTiMK+055/R1TqhB1JvvxJ1CXk2rDL6G
+0TLHQ7oGofd5LYiemg4ZVtWdJe43BPZlVgT6lvL/iGo8JnrncB9Da6L7nrq/+Rvj
+XGjf1qODCK+LmreZWEsaLPURIoR/Ewwxb9J2zd0CaMjeTwafJo1CZvcCgYEAyCgb
+aqoWvUecX8VvARfuA593Lsi50t4MEArnOXXcd1RnXoZWhbx5rgO8/ATKfXr0BK/n
+h2GF9PfKzHFm/4V6e82OL7gu/kLy2u9bXN74vOvWFL5NOrOKPM7Kg+9I131kNYOw
+Ivnr/VtHE5s0dY7JChYWE1F3vArrOw3T00a4CXUCgYEA0SqY+dS2LvIzW4cHCe9k
+IQqsT0yYm5TFsUEr4sA3xcPfe4cV8sZb9k/QEGYb1+SWWZ+AHPV3UW5fl8kTbSNb
+v4ng8i8rVVQ0ANbJO9e5CUrepein2MPL0AkOATR8M7t7dGGpvYV0cFk8ZrFx0oId
+U0PgYDotF/iueBWlbsOM430CgYEAqYI95dFyPI5/AiSkY5queeb8+mQH62sdcCCr
+vd/w/CZA/K5sbAo4SoTj8dLk4evU6HtIa0DOP63y071eaxvRpTNqLUOgmLh+D6gS
+Cc7TfLuFrD+WDBatBd5jZ+SoHccVrLR/4L8jeodo5FPW05A+9gnKXEXsTxY4LOUC
+9bS4e1kCgYAqVXZh63JsMwoaxCYmQ66eJojKa47VNrOeIZDZvd2BPVf30glBOT41
+gBoDG3WMPZoQj9pb7uMcrnvs4APj2FIhMU8U15LcPAj59cD6S6rWnAxO8NFK7HQG
+4Jxg3JNNf8ErQoCHb1B3oVdXJkmbJkARoDpBKmTCgKtP8ADYLmVPQw==
+-----END RSA PRIVATE KEY-----
diff --git a/test/openssl/test_asn1.rb b/test/openssl/test_asn1.rb
index 91ae2cfd0cd5..55cb1f0bec3f 100644
--- a/test/openssl/test_asn1.rb
+++ b/test/openssl/test_asn1.rb
@@ -1,10 +1,12 @@
 # frozen_string_literal: false
 require_relative 'utils'
 
+if defined?(OpenSSL::TestUtils)
+
 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
+    key = Fixtures.pkey("rsa1024")
     now = Time.at(Time.now.to_i) # suppress usec
     s = 0xdeadbeafdeadbeafdeadbeafdeadbeaf
     exts = [
@@ -582,5 +584,6 @@ def assert_universal(tag, asn1)
     end
     assert_equal(:UNIVERSAL, asn1.tag_class)
   end
+end
 
-end if defined?(OpenSSL::TestUtils)
+end
diff --git a/test/openssl/test_bn.rb b/test/openssl/test_bn.rb
index 37ba5e5595d7..5f3ae2b46555 100644
--- a/test/openssl/test_bn.rb
+++ b/test/openssl/test_bn.rb
@@ -55,6 +55,7 @@ def test_cmp
     assert_equal(false, bn1.eql?(bn3))
     assert_equal(bn1.hash, bn2.hash)
     assert_not_equal(bn3.hash, bn1.hash)
+    assert_instance_of(String, bn1.hash.to_s)
   end
 end
 
diff --git a/test/openssl/test_buffering.rb b/test/openssl/test_buffering.rb
index f85353fc67e8..08735adda965 100644
--- a/test/openssl/test_buffering.rb
+++ b/test/openssl/test_buffering.rb
@@ -1,9 +1,9 @@
 # frozen_string_literal: false
 require_relative 'utils'
-require 'stringio'
 
-class OpenSSL::TestBuffering < OpenSSL::TestCase
+if defined?(OpenSSL::TestUtils)
 
+class OpenSSL::TestBuffering < OpenSSL::TestCase
   class IO
     include OpenSSL::Buffering
 
@@ -85,5 +85,6 @@ def test_each_byte
     end
     assert_equal([97, 98, 99], res)
   end
+end
 
-end if defined?(OpenSSL::TestUtils)
+end
diff --git a/test/openssl/test_config.rb b/test/openssl/test_config.rb
index 786bce9d2f1e..99dcc497271a 100644
--- a/test/openssl/test_config.rb
+++ b/test/openssl/test_config.rb
@@ -1,6 +1,8 @@
 # frozen_string_literal: false
 require_relative 'utils'
 
+if defined?(OpenSSL::TestUtils)
+
 class OpenSSL::TestConfig < OpenSSL::TestCase
   def setup
     super
@@ -171,7 +173,7 @@ def test_get_value_ENV
 
   def test_value
     # suppress deprecation warnings
-    OpenSSL::TestUtils.silent do
+    EnvUtil.suppress_warning do
       assert_equal('CA_default', @it.value('ca', 'default_ca'))
       assert_equal(nil, @it.value('ca', 'no such key'))
       assert_equal(nil, @it.value('no such section', 'no such key'))
@@ -184,7 +186,7 @@ def test_value
   end
 
   def test_value_ENV
-    OpenSSL::TestUtils.silent do
+    EnvUtil.suppress_warning do
       key = ENV.keys.first
       assert_not_nil(key) # make sure we have at least one ENV var.
       assert_equal(ENV[key], @it.value('ENV', key))
@@ -199,7 +201,7 @@ def test_aref
   end
 
   def test_section
-    OpenSSL::TestUtils.silent do
+    EnvUtil.suppress_warning do
       assert_equal({'HOME' => '.'}, @it.section('default'))
       assert_equal({'dir' => './demoCA', 'certs' => './certs'}, @it.section('CA_default'))
       assert_equal({}, @it.section('no_such_section'))
@@ -297,4 +299,6 @@ def test_clone
     @it['newsection'] = {'a' => 'b'}
     assert_not_equal(@it.sections.sort, c.sections.sort)
   end
-end if defined?(OpenSSL::TestUtils)
+end
+
+end
diff --git a/test/openssl/test_digest.rb b/test/openssl/test_digest.rb
index 9891d99ae3c8..c8817395bb9a 100644
--- a/test/openssl/test_digest.rb
+++ b/test/openssl/test_digest.rb
@@ -54,13 +54,10 @@ def test_reset
   end
 
   def test_digest_constants
-    algs = %w(MD4 MD5 RIPEMD160 SHA1)
-    if OpenSSL::OPENSSL_VERSION_NUMBER < 0x10100000
+    algs = %w(MD4 MD5 RIPEMD160 SHA1 SHA224 SHA256 SHA384 SHA512)
+    if !libressl? && !openssl?(1, 1, 0)
       algs += %w(DSS1 SHA)
     end
-    if OpenSSL::OPENSSL_VERSION_NUMBER > 0x00908000
-      algs += %w(SHA224 SHA256 SHA384 SHA512)
-    end
     algs.each do |alg|
       assert_not_nil(OpenSSL::Digest.new(alg))
       klass = OpenSSL::Digest.const_get(alg)
@@ -73,34 +70,32 @@ def test_digest_by_oid_and_name
     check_digest(OpenSSL::ASN1::ObjectId.new("SHA1"))
   end
 
-  if OpenSSL::OPENSSL_VERSION_NUMBER > 0x00908000
-    def encode16(str)
-      str.unpack("H*").first
-    end
+  def encode16(str)
+    str.unpack("H*").first
+  end
 
-    def test_098_features
-      sha224_a = "abd37534c7d9a2efb9465de931cd7055ffdb8879563ae98078d6d6d5"
-      sha256_a = "ca978112ca1bbdcafac231b39a23dc4da786eff8147c4e72b9807785afee48bb"
-      sha384_a = "54a59b9f22b0b80880d8427e548b7c23abd873486e1f035dce9cd697e85175033caa88e6d57bc35efae0b5afd3145f31"
-      sha512_a = "1f40fc92da241694750979ee6cf582f2d5d7d28e18335de05abc54d0560e0f5302860c652bf08d560252aa5e74210546f369fbbbce8c12cfc7957b2652fe9a75"
-
-      assert_equal(sha224_a, OpenSSL::Digest::SHA224.hexdigest("a"))
-      assert_equal(sha256_a, OpenSSL::Digest::SHA256.hexdigest("a"))
-      assert_equal(sha384_a, OpenSSL::Digest::SHA384.hexdigest("a"))
-      assert_equal(sha512_a, OpenSSL::Digest::SHA512.hexdigest("a"))
-
-      assert_equal(sha224_a, encode16(OpenSSL::Digest::SHA224.digest("a")))
-      assert_equal(sha256_a, encode16(OpenSSL::Digest::SHA256.digest("a")))
-      assert_equal(sha384_a, encode16(OpenSSL::Digest::SHA384.digest("a")))
-      assert_equal(sha512_a, encode16(OpenSSL::Digest::SHA512.digest("a")))
-    end
+  def test_sha2
+    sha224_a = "abd37534c7d9a2efb9465de931cd7055ffdb8879563ae98078d6d6d5"
+    sha256_a = "ca978112ca1bbdcafac231b39a23dc4da786eff8147c4e72b9807785afee48bb"
+    sha384_a = "54a59b9f22b0b80880d8427e548b7c23abd873486e1f035dce9cd697e85175033caa88e6d57bc35efae0b5afd3145f31"
+    sha512_a = "1f40fc92da241694750979ee6cf582f2d5d7d28e18335de05abc54d0560e0f5302860c652bf08d560252aa5e74210546f369fbbbce8c12cfc7957b2652fe9a75"
+
+    assert_equal(sha224_a, OpenSSL::Digest::SHA224.hexdigest("a"))
+    assert_equal(sha256_a, OpenSSL::Digest::SHA256.hexdigest("a"))
+    assert_equal(sha384_a, OpenSSL::Digest::SHA384.hexdigest("a"))
+    assert_equal(sha512_a, OpenSSL::Digest::SHA512.hexdigest("a"))
+
+    assert_equal(sha224_a, encode16(OpenSSL::Digest::SHA224.digest("a")))
+    assert_equal(sha256_a, encode16(OpenSSL::Digest::SHA256.digest("a")))
+    assert_equal(sha384_a, encode16(OpenSSL::Digest::SHA384.digest("a")))
+    assert_equal(sha512_a, encode16(OpenSSL::Digest::SHA512.digest("a")))
+  end
 
-    def test_digest_by_oid_and_name_sha2
-      check_digest(OpenSSL::ASN1::ObjectId.new("SHA224"))
-      check_digest(OpenSSL::ASN1::ObjectId.new("SHA256"))
-      check_digest(OpenSSL::ASN1::ObjectId.new("SHA384"))
-      check_digest(OpenSSL::ASN1::ObjectId.new("SHA512"))
-    end
+  def test_digest_by_oid_and_name_sha2
+    check_digest(OpenSSL::ASN1::ObjectId.new("SHA224"))
+    check_digest(OpenSSL::ASN1::ObjectId.new("SHA256"))
+    check_digest(OpenSSL::ASN1::ObjectId.new("SHA384"))
+    check_digest(OpenSSL::ASN1::ObjectId.new("SHA512"))
   end
 
   def test_openssl_digest
@@ -121,14 +116,6 @@ def check_digest(oid)
     d = OpenSSL::Digest.new(oid.oid)
     assert_not_nil(d)
   end
-
-  def libressl?
-    OpenSSL::OPENSSL_VERSION.include?('LibreSSL')
-  end
-
-  def version_since(verary)
-    (OpenSSL::OPENSSL_LIBRARY_VERSION.scan(/\d+/).map(&:to_i) <=> verary) != -1
-  end
 end
 
 end
diff --git a/test/openssl/test_engine.rb b/test/openssl/test_engine.rb
index 75e45eb7f0a9..801d1c8e1a91 100644
--- a/test/openssl/test_engine.rb
+++ b/test/openssl/test_engine.rb
@@ -1,8 +1,9 @@
 # frozen_string_literal: false
 require_relative 'utils'
 
-class OpenSSL::TestEngine < OpenSSL::TestCase
+if defined?(OpenSSL::TestUtils) && defined?(OpenSSL::Engine)
 
+class OpenSSL::TestEngine < OpenSSL::TestCase
   def test_engines_free # [ruby-dev:44173]
     with_openssl <<-'end;'
       OpenSSL::Engine.load("openssl")
@@ -51,32 +52,28 @@ def test_openssl_engine_digest_sha1
   end
 
   def test_openssl_engine_cipher_rc4
-    with_openssl <<-'end;'
-      begin
-        engine = get_engine
-        algo = "RC4" #AES is not supported by openssl Engine (<=1.0.0e)
-        data = "a" * 1000
-        key = OpenSSL::Random.random_bytes(16)
-        # suppress message from openssl Engine's RC4 cipher [ruby-core:41026]
-        err_back = $stderr.dup
-        $stderr.reopen(IO::NULL)
-        encrypted = crypt_data(data, key, :encrypt) { engine.cipher(algo) }
-        decrypted = crypt_data(encrypted, key, :decrypt) { OpenSSL::Cipher.new(algo) }
-        assert_equal(data, decrypted)
-      ensure
-        if err_back
-          $stderr.reopen(err_back)
-          err_back.close
-        end
-      end
+    begin
+      OpenSSL::Cipher.new("rc4")
+    rescue OpenSSL::Cipher::CipherError
+      pend "RC4 is not supported"
+    end
+
+    with_openssl(<<-'end;', ignore_stderr: true)
+      engine = get_engine
+      algo = "RC4"
+      data = "a" * 1000
+      key = OpenSSL::Random.random_bytes(16)
+      encrypted = crypt_data(data, key, :encrypt) { engine.cipher(algo) }
+      decrypted = crypt_data(encrypted, key, :decrypt) { OpenSSL::Cipher.new(algo) }
+      assert_equal(data, decrypted)
     end;
   end
 
   private
 
   # this is required because OpenSSL::Engine methods change global state
-  def with_openssl(code)
-    assert_separately([{ "OSSL_MDEBUG" => nil }, "-ropenssl"], <<~"end;")
+  def with_openssl(code, **opts)
+    assert_separately([{ "OSSL_MDEBUG" => nil }, "-ropenssl"], <<~"end;", **opts)
       require #{__FILE__.dump}
       include OpenSSL::TestEngine::Utils
       #{code}
@@ -95,5 +92,6 @@ def crypt_data(data, key, mode)
       cipher.update(data) + cipher.final
     end
   end
+end
 
-end if defined?(OpenSSL::TestUtils) && defined?(OpenSSL::Engine)
+end
diff --git a/test/openssl/test_hmac.rb b/test/openssl/test_hmac.rb
index dbde97d9c977..4d06e476540a 100644
--- a/test/openssl/test_hmac.rb
+++ b/test/openssl/test_hmac.rb
@@ -1,6 +1,8 @@
 # frozen_string_literal: false
 require_relative 'utils'
 
+if defined?(OpenSSL::TestUtils)
+
 class OpenSSL::TestHMAC < OpenSSL::TestCase
   def test_hmac
     # RFC 2202 2. Test Cases for HMAC-MD5
@@ -37,4 +39,6 @@ def test_reset_keep_key
     second = h1.update("test").hexdigest
     assert_equal first, second
   end
-end if defined?(OpenSSL::TestUtils)
+end
+
+end
diff --git a/test/openssl/test_ns_spki.rb b/test/openssl/test_ns_spki.rb
index ac34613fc29a..58e0f6498c50 100644
--- a/test/openssl/test_ns_spki.rb
+++ b/test/openssl/test_ns_spki.rb
@@ -17,8 +17,8 @@ def setup
   end
 
   def test_build_data
-    key1 = OpenSSL::TestUtils::TEST_KEY_RSA1024
-    key2 = OpenSSL::TestUtils::TEST_KEY_RSA2048
+    key1 = Fixtures.pkey("rsa1024")
+    key2 = Fixtures.pkey("rsa2048")
     spki = OpenSSL::Netscape::SPKI.new
     spki.challenge = "RandomString"
     spki.public_key = key1.public_key
diff --git a/test/openssl/test_ocsp.rb b/test/openssl/test_ocsp.rb
index 8881f25dd9a5..0440634ab0c8 100644
--- a/test/openssl/test_ocsp.rb
+++ b/test/openssl/test_ocsp.rb
@@ -13,7 +13,7 @@ def setup
     # @cert2   @ocsp_cert
 
     ca_subj = OpenSSL::X509::Name.parse("/DC=org/DC=ruby-lang/CN=TestCA")
-    @ca_key = OpenSSL::TestUtils::TEST_KEY_RSA1024
+    @ca_key = Fixtures.pkey("rsa1024")
     ca_exts = [
       ["basicConstraints", "CA:TRUE", true],
       ["keyUsage", "cRLSign,keyCertSign", true],
@@ -22,7 +22,7 @@ def setup
       ca_subj, @ca_key, 1, ca_exts, nil, nil)
 
     cert_subj = OpenSSL::X509::Name.parse("/DC=org/DC=ruby-lang/CN=TestCA2")
-    @cert_key = OpenSSL::TestUtils::TEST_KEY_RSA1024
+    @cert_key = Fixtures.pkey("rsa1024")
     cert_exts = [
       ["basicConstraints", "CA:TRUE", true],
       ["keyUsage", "cRLSign,keyCertSign", true],
@@ -31,14 +31,14 @@ def setup
       cert_subj, @cert_key, 5, cert_exts, @ca_cert, @ca_key)
 
     cert2_subj = OpenSSL::X509::Name.parse("/DC=org/DC=ruby-lang/CN=TestCert")
-    @cert2_key = OpenSSL::TestUtils::TEST_KEY_RSA1024
+    @cert2_key = Fixtures.pkey("rsa1024")
     cert2_exts = [
     ]
     @cert2 = OpenSSL::TestUtils.issue_cert(
       cert2_subj, @cert2_key, 10, cert2_exts, @cert, @cert_key)
 
     ocsp_subj = OpenSSL::X509::Name.parse("/DC=org/DC=ruby-lang/CN=TestCAOCSP")
-    @ocsp_key = OpenSSL::TestUtils::TEST_KEY_RSA2048
+    @ocsp_key = Fixtures.pkey("rsa2048")
     ocsp_exts = [
       ["extendedKeyUsage", "OCSPSigning", true],
     ]
@@ -122,7 +122,7 @@ def test_request_sign_verify
 
     assert_equal true, req.verify([@cert], store, OpenSSL::OCSP::NOINTERN)
     ret = req.verify([@cert], store)
-    if ret || OpenSSL::OPENSSL_VERSION =~ /OpenSSL/ && OpenSSL::OPENSSL_VERSION_NUMBER >= 0x10002000
+    if ret || openssl?(1, 0, 2) || libressl?(2, 4, 2)
       assert_equal true, ret
     else
       # RT2560; OCSP_request_verify() does not find signer cert from 'certs' when
diff --git a/test/openssl/test_pair.rb b/test/openssl/test_pair.rb
index 9a5205f81c41..ea5f0dcf9fcc 100644
--- a/test/openssl/test_pair.rb
+++ b/test/openssl/test_pair.rb
@@ -1,61 +1,46 @@
 # frozen_string_literal: false
 require_relative 'utils'
+require_relative 'ut_eof'
 
 if defined?(OpenSSL::TestUtils)
 
-require 'socket'
-require_relative 'ut_eof'
-
 module OpenSSL::SSLPairM
-  def server
-    host = "127.0.0.1"
-    port = 0
-    ctx = OpenSSL::SSL::SSLContext.new()
-    ctx.ciphers = "ADH"
-    ctx.security_level = 0
-    ctx.tmp_dh_callback = proc { OpenSSL::TestUtils::TEST_KEY_DH1024 }
-    tcps = create_tcp_server(host, port)
-    ssls = OpenSSL::SSL::SSLServer.new(tcps, ctx)
-    return ssls
+  def setup
+    svr_dn = OpenSSL::X509::Name.parse("/DC=org/DC=ruby-lang/CN=localhost")
+    ee_exts = [
+      ["keyUsage", "keyEncipherment,digitalSignature", true],
+    ]
+    @svr_key = OpenSSL::TestUtils::Fixtures.pkey("rsa1024")
+    @svr_cert = issue_cert(svr_dn, @svr_key, 1, ee_exts, nil, nil)
   end
 
-  def client(port)
+  def ssl_pair
     host = "127.0.0.1"
-    ctx = OpenSSL::SSL::SSLContext.new()
-    ctx.ciphers = "ADH"
-    ctx.security_level = 0
-    s = create_tcp_client(host, port)
-    ssl = OpenSSL::SSL::SSLSocket.new(s, ctx)
-    ssl.connect
-    ssl.sync_close = true
-    ssl
-  end
+    tcps = create_tcp_server(host, 0)
+    port = tcps.connect_address.ip_port
 
-  def ssl_pair
-    ssls = server
     th = Thread.new {
+      sctx = OpenSSL::SSL::SSLContext.new
+      sctx.cert = @svr_cert
+      sctx.key = @svr_key
+      sctx.tmp_dh_callback = proc { OpenSSL::TestUtils::Fixtures.pkey_dh("dh1024") }
+      sctx.options |= OpenSSL::SSL::OP_NO_COMPRESSION
+      ssls = OpenSSL::SSL::SSLServer.new(tcps, sctx)
       ns = ssls.accept
       ssls.close
       ns
     }
-    port = ssls.to_io.local_address.ip_port
-    c = client(port)
+
+    tcpc = create_tcp_client(host, port)
+    c = OpenSSL::SSL::SSLSocket.new(tcpc)
+    c.connect
     s = th.value
-    if block_given?
-      begin
-        yield c, s
-      ensure
-        c.close unless c.closed?
-        s.close unless s.closed?
-      end
-    else
-      return c, s
-    end
+
+    yield c, s
   ensure
-    if th&.alive?
-      th.kill
-      th.join
-    end
+    tcpc&.close
+    tcps&.close
+    s&.close
   end
 end
 
@@ -85,23 +70,27 @@ def create_tcp_client(host, port)
 
 module OpenSSL::TestEOF1M
   def open_file(content)
-    s1, s2 = ssl_pair
-    th = Thread.new { s2 << content; s2.close }
-    yield s1
-  ensure
-    th.join if th
-    s1.close
+    ssl_pair { |s1, s2|
+      begin
+        th = Thread.new { s2 << content; s2.close }
+        yield s1
+      ensure
+        th&.join
+      end
+    }
   end
 end
 
 module OpenSSL::TestEOF2M
   def open_file(content)
-    s1, s2 = ssl_pair
-    th = Thread.new { s1 << content; s1.close }
-    yield s2
-  ensure
-    th.join if th
-    s2.close
+    ssl_pair { |s1, s2|
+      begin
+        th = Thread.new { s1 << content; s1.close }
+        yield s2
+      ensure
+        th&.join
+      end
+    }
   end
 end
 
@@ -189,6 +178,27 @@ def test_puts_empty
     }
   end
 
+  def test_multibyte_read_write
+    # German a umlaut
+    auml = [%w{ C3 A4 }.join('')].pack('H*')
+    auml.force_encoding(Encoding::UTF_8)
+    bsize = auml.bytesize
+
+    ssl_pair { |s1, s2|
+      assert_equal bsize, s1.write(auml)
+      read = s2.read(bsize)
+      assert_equal Encoding::ASCII_8BIT, read.encoding
+      assert_equal bsize, read.bytesize
+      assert_equal auml, read.force_encoding(Encoding::UTF_8)
+
+      s1.puts(auml)
+      read = s2.gets
+      assert_equal Encoding::ASCII_8BIT, read.encoding
+      assert_equal bsize + 1, read.bytesize
+      assert_equal auml + "\n", read.force_encoding(Encoding::UTF_8)
+    }
+  end
+
   def test_read_nonblock
     ssl_pair {|s1, s2|
       err = nil
@@ -208,7 +218,7 @@ def test_read_nonblock
       assert_nothing_raised("[ruby-core:20298]") { ret = s2.read_nonblock(10) }
       assert_equal("def\n", ret)
       s1.close
-      sleep 0.1
+      IO.select([s2])
       assert_raise(EOFError) { s2.read_nonblock(10) }
     }
   end
@@ -224,49 +234,71 @@ def test_read_nonblock_no_exception
       assert_nothing_raised("[ruby-core:20298]") { ret = s2.read_nonblock(10, exception: false) }
       assert_equal("def\n", ret)
       s1.close
-      sleep 0.1
+      IO.select([s2])
       assert_equal(nil, s2.read_nonblock(10, exception: false))
     }
   end
 
-  def write_nonblock(socket, meth, str)
-    ret = socket.send(meth, str)
-    ret.is_a?(Symbol) ? 0 : ret
-  end
+  def test_read_with_outbuf
+    ssl_pair { |s1, s2|
+      s1.write("abc\n")
+      buf = ""
+      ret = s2.read(2, buf)
+      assert_same ret, buf
+      assert_equal "ab", ret
+
+      buf = "garbage"
+      ret = s2.read(2, buf)
+      assert_same ret, buf
+      assert_equal "c\n", ret
+
+      buf = "garbage"
+      assert_equal :wait_readable, s2.read_nonblock(100, buf, exception: false)
+      assert_equal "", buf
 
-  def write_nonblock_no_ex(socket, str)
-    ret = socket.write_nonblock str, exception: false
-    ret.is_a?(Symbol) ? 0 : ret
+      s1.close
+      buf = "garbage"
+      assert_equal nil, s2.read(100, buf)
+      assert_equal "", buf
+    }
   end
 
   def test_write_nonblock
     ssl_pair {|s1, s2|
-      n = 0
-      begin
-        n += write_nonblock s1, :write_nonblock, "a" * 100000
-        n += write_nonblock s1, :write_nonblock, "b" * 100000
-        n += write_nonblock s1, :write_nonblock, "c" * 100000
-        n += write_nonblock s1, :write_nonblock, "d" * 100000
-        n += write_nonblock s1, :write_nonblock, "e" * 100000
-        n += write_nonblock s1, :write_nonblock, "f" * 100000
-      rescue IO::WaitWritable
+      assert_equal 3, s1.write_nonblock("foo")
+      assert_equal "foo", s2.read(3)
+
+      data = "x" * 16384
+      written = 0
+      while true
+        begin
+          written += s1.write_nonblock(data)
+        rescue IO::WaitWritable, IO::WaitReadable
+          break
+        end
       end
-      s1.close
-      assert_equal(n, s2.read.length)
+      assert written > 0
+      assert_equal written, s2.read(written).bytesize
     }
   end
 
   def test_write_nonblock_no_exceptions
     ssl_pair {|s1, s2|
-      n = 0
-      n += write_nonblock_no_ex s1, "a" * 100000
-      n += write_nonblock_no_ex s1, "b" * 100000
-      n += write_nonblock_no_ex s1, "c" * 100000
-      n += write_nonblock_no_ex s1, "d" * 100000
-      n += write_nonblock_no_ex s1, "e" * 100000
-      n += write_nonblock_no_ex s1, "f" * 100000
-      s1.close
-      assert_equal(n, s2.read.length)
+      assert_equal 3, s1.write_nonblock("foo", exception: false)
+      assert_equal "foo", s2.read(3)
+
+      data = "x" * 16384
+      written = 0
+      while true
+        case ret = s1.write_nonblock(data, exception: false)
+        when :wait_readable, :wait_writable
+          break
+        else
+          written += ret
+        end
+      end
+      assert written > 0
+      assert_equal written, s2.read(written).bytesize
     }
   end
 
@@ -354,9 +386,9 @@ def tcp_pair
 
   def test_connect_accept_nonblock_no_exception
     ctx2 = OpenSSL::SSL::SSLContext.new
-    ctx2.ciphers = "ADH"
-    ctx2.security_level = 0
-    ctx2.tmp_dh_callback = proc { OpenSSL::TestUtils::TEST_KEY_DH1024 }
+    ctx2.cert = @svr_cert
+    ctx2.key = @svr_key
+    ctx2.tmp_dh_callback = proc { OpenSSL::TestUtils::Fixtures.pkey_dh("dh1024") }
 
     sock1, sock2 = tcp_pair
 
@@ -365,8 +397,6 @@ def test_connect_accept_nonblock_no_exception
     assert_equal :wait_readable, accepted
 
     ctx1 = OpenSSL::SSL::SSLContext.new
-    ctx1.ciphers = "ADH"
-    ctx1.security_level = 0
     s1 = OpenSSL::SSL::SSLSocket.new(sock1, ctx1)
     th = Thread.new do
       rets = []
@@ -404,9 +434,9 @@ def test_connect_accept_nonblock_no_exception
 
   def test_connect_accept_nonblock
     ctx = OpenSSL::SSL::SSLContext.new()
-    ctx.ciphers = "ADH"
-    ctx.security_level = 0
-    ctx.tmp_dh_callback = proc { OpenSSL::TestUtils::TEST_KEY_DH1024 }
+    ctx.cert = @svr_cert
+    ctx.key = @svr_key
+    ctx.tmp_dh_callback = proc { OpenSSL::TestUtils::Fixtures.pkey_dh("dh1024") }
 
     sock1, sock2 = tcp_pair
 
@@ -428,8 +458,6 @@ def test_connect_accept_nonblock
 
     sleep 0.1
     ctx = OpenSSL::SSL::SSLContext.new()
-    ctx.ciphers = "ADH"
-    ctx.security_level = 0
     s1 = OpenSSL::SSL::SSLSocket.new(sock1, ctx)
     begin
       sleep 0.2
diff --git a/test/openssl/test_pkcs12.rb b/test/openssl/test_pkcs12.rb
index 403718b94f00..3088823411f2 100644
--- a/test/openssl/test_pkcs12.rb
+++ b/test/openssl/test_pkcs12.rb
@@ -5,8 +5,6 @@
 
 module OpenSSL
   class TestPKCS12 < OpenSSL::TestCase
-    include OpenSSL::TestUtils
-
     def setup
       super
       ca = OpenSSL::X509::Name.parse("/DC=org/DC=ruby-lang/CN=CA")
@@ -16,7 +14,7 @@ def setup
         ["subjectKeyIdentifier","hash",false],
         ["authorityKeyIdentifier","keyid:always",false],
       ]
-      @cacert = issue_cert(ca, TEST_KEY_RSA2048, 1, ca_exts, nil, nil)
+      @cacert = issue_cert(ca, Fixtures.pkey("rsa2048"), 1, ca_exts, nil, nil)
 
       inter_ca = OpenSSL::X509::Name.parse("/DC=org/DC=ruby-lang/CN=Intermediate CA")
       inter_ca_key = OpenSSL::PKey.read <<-_EOS_
@@ -36,25 +34,26 @@ def setup
 Li8JsX5yIiuVYaBg/6ha3tOg4TCa5K/3r3tVliRZ2Es=
 -----END RSA PRIVATE KEY-----
       _EOS_
-      @inter_cacert = issue_cert(inter_ca, inter_ca_key, 2, ca_exts, @cacert, TEST_KEY_RSA2048)
+      @inter_cacert = issue_cert(inter_ca, inter_ca_key, 2, ca_exts, @cacert, Fixtures.pkey("rsa2048"))
 
       exts = [
         ["keyUsage","digitalSignature",true],
         ["subjectKeyIdentifier","hash",false],
       ]
       ee = OpenSSL::X509::Name.parse("/DC=org/DC=ruby-lang/CN=Ruby PKCS12 Test Certificate")
-      @mycert = issue_cert(ee, TEST_KEY_RSA1024, 3, exts, @inter_cacert, inter_ca_key)
+      @mykey = Fixtures.pkey("rsa1024")
+      @mycert = issue_cert(ee, @mykey, 3, exts, @inter_cacert, inter_ca_key)
     end
 
     def test_create
       pkcs12 = OpenSSL::PKCS12.create(
         "omg",
         "hello",
-        TEST_KEY_RSA1024,
+        @mykey,
         @mycert
       )
-      assert_equal @mycert, pkcs12.certificate
-      assert_equal TEST_KEY_RSA1024, pkcs12.key
+      assert_equal @mycert.to_der, pkcs12.certificate.to_der
+      assert_equal @mykey.to_der, pkcs12.key.to_der
       assert_nil pkcs12.ca_certs
     end
 
@@ -62,11 +61,11 @@ def test_create_no_pass
       pkcs12 = OpenSSL::PKCS12.create(
         nil,
         "hello",
-        TEST_KEY_RSA1024,
+        @mykey,
         @mycert
       )
-      assert_equal @mycert, pkcs12.certificate
-      assert_equal TEST_KEY_RSA1024, pkcs12.key
+      assert_equal @mycert.to_der, pkcs12.certificate.to_der
+      assert_equal @mykey.to_der, pkcs12.key.to_der
       assert_nil pkcs12.ca_certs
 
       decoded = OpenSSL::PKCS12.new(pkcs12.to_der)
@@ -79,7 +78,7 @@ def test_create_with_chain
       pkcs12 = OpenSSL::PKCS12.create(
         "omg",
         "hello",
-        TEST_KEY_RSA1024,
+        @mykey,
         @mycert,
         chain
       )
@@ -94,7 +93,7 @@ def test_create_with_chain_decode
       pkcs12 = OpenSSL::PKCS12.create(
         passwd,
         "hello",
-        TEST_KEY_RSA1024,
+        @mykey,
         @mycert,
         chain
       )
@@ -104,7 +103,7 @@ def test_create_with_chain_decode
       assert_include_cert @cacert, decoded.ca_certs
       assert_include_cert @inter_cacert, decoded.ca_certs
       assert_cert @mycert, decoded.certificate
-      assert_equal TEST_KEY_RSA1024.to_der, decoded.key.to_der
+      assert_equal @mykey.to_der, decoded.key.to_der
     end
 
     def test_create_with_bad_nid
@@ -112,7 +111,7 @@ def test_create_with_bad_nid
         OpenSSL::PKCS12.create(
           "omg",
           "hello",
-          TEST_KEY_RSA1024,
+          @mykey,
           @mycert,
           [],
           "foo"
@@ -124,7 +123,7 @@ def test_create_with_itr
       OpenSSL::PKCS12.create(
         "omg",
         "hello",
-        TEST_KEY_RSA1024,
+        @mykey,
         @mycert,
         [],
         nil,
@@ -136,7 +135,7 @@ def test_create_with_itr
         OpenSSL::PKCS12.create(
           "omg",
           "hello",
-          TEST_KEY_RSA1024,
+          @mykey,
           @mycert,
           [],
           nil,
@@ -150,7 +149,7 @@ def test_create_with_mac_itr
       OpenSSL::PKCS12.create(
         "omg",
         "hello",
-        TEST_KEY_RSA1024,
+        @mykey,
         @mycert,
         [],
         nil,
@@ -163,7 +162,7 @@ def test_create_with_mac_itr
         OpenSSL::PKCS12.create(
           "omg",
           "hello",
-          TEST_KEY_RSA1024,
+          @mykey,
           @mycert,
           [],
           nil,
@@ -216,7 +215,7 @@ def test_new_with_one_key_and_one_cert
       EOF
       p12 = OpenSSL::PKCS12.new(str, "abc123")
 
-      assert_equal TEST_KEY_RSA1024.to_der, p12.key.to_der
+      assert_equal @mykey.to_der, p12.key.to_der
       assert_equal @mycert.subject.to_der, p12.certificate.subject.to_der
       assert_equal [], Array(p12.ca_certs)
     end
@@ -275,13 +274,13 @@ def test_new_with_no_certs
       EOF
       p12 = OpenSSL::PKCS12.new(str, "abc123")
 
-      assert_equal TEST_KEY_RSA1024.to_der, p12.key.to_der
+      assert_equal @mykey.to_der, p12.key.to_der
       assert_equal nil, p12.certificate
       assert_equal [], Array(p12.ca_certs)
     end
 
     def test_dup
-      p12 = OpenSSL::PKCS12.create("pass", "name", TEST_KEY_RSA1024, @mycert)
+      p12 = OpenSSL::PKCS12.create("pass", "name", @mykey, @mycert)
       assert_equal p12.to_der, p12.dup.to_der
     end
 
diff --git a/test/openssl/test_pkcs5.rb b/test/openssl/test_pkcs5.rb
index ad8132c263ba..0919b9ce6040 100644
--- a/test/openssl/test_pkcs5.rb
+++ b/test/openssl/test_pkcs5.rb
@@ -1,8 +1,9 @@
 # frozen_string_literal: false
 require_relative 'utils'
 
-class OpenSSL::TestPKCS5 < OpenSSL::TestCase
+if defined?(OpenSSL::TestUtils)
 
+class OpenSSL::TestPKCS5 < OpenSSL::TestCase
   def test_pbkdf2_hmac_sha1_rfc6070_c_1_len_20
     p ="password"
     s = "salt"
@@ -94,5 +95,6 @@ def test_pbkdf2_hmac_sha256_c_20000_len_32
     value2 = OpenSSL::PKCS5.pbkdf2_hmac(p, s, c, dk_len, digest)
     assert_equal(value1, value2)
   end if OpenSSL::PKCS5.respond_to?(:pbkdf2_hmac)
+end
 
-end if defined?(OpenSSL::TestUtils)
+end
diff --git a/test/openssl/test_pkcs7.rb b/test/openssl/test_pkcs7.rb
index 3219155462d0..026fe8479703 100644
--- a/test/openssl/test_pkcs7.rb
+++ b/test/openssl/test_pkcs7.rb
@@ -6,8 +6,8 @@
 class OpenSSL::TestPKCS7 < OpenSSL::TestCase
   def setup
     super
-    @rsa1024 = OpenSSL::TestUtils::TEST_KEY_RSA1024
-    @rsa2048 = OpenSSL::TestUtils::TEST_KEY_RSA2048
+    @rsa1024 = Fixtures.pkey("rsa1024")
+    @rsa2048 = Fixtures.pkey("rsa2048")
     ca = OpenSSL::X509::Name.parse("/DC=org/DC=ruby-lang/CN=CA")
     ee1 = OpenSSL::X509::Name.parse("/DC=org/DC=ruby-lang/CN=EE1")
     ee2 = OpenSSL::X509::Name.parse("/DC=org/DC=ruby-lang/CN=EE2")
@@ -28,10 +28,6 @@ def setup
     @ee2_cert = issue_cert(ee2, @rsa1024, 3, ee_exts, @ca_cert, @rsa2048)
   end
 
-  def issue_cert(*args)
-    OpenSSL::TestUtils.issue_cert(*args)
-  end
-
   def test_signed
     store = OpenSSL::X509::Store.new
     store.add_cert(@ca_cert)
diff --git a/test/openssl/test_pkey_dh.rb b/test/openssl/test_pkey_dh.rb
index 470c952e2138..fb7138139375 100644
--- a/test/openssl/test_pkey_dh.rb
+++ b/test/openssl/test_pkey_dh.rb
@@ -4,8 +4,6 @@
 if defined?(OpenSSL::TestUtils)
 
 class OpenSSL::TestPKeyDH < OpenSSL::PKeyTestCase
-  DH1024 = OpenSSL::TestUtils::TEST_KEY_DH1024
-
   NEW_KEYLEN = 256
 
   def test_DEFAULT_parameters
@@ -37,12 +35,13 @@ def test_new_break
   end
 
   def test_DHparams
+    dh1024 = Fixtures.pkey_dh("dh1024")
     asn1 = OpenSSL::ASN1::Sequence([
-      OpenSSL::ASN1::Integer(DH1024.p),
-      OpenSSL::ASN1::Integer(DH1024.g)
+      OpenSSL::ASN1::Integer(dh1024.p),
+      OpenSSL::ASN1::Integer(dh1024.g)
     ])
     key = OpenSSL::PKey::DH.new(asn1.to_der)
-    assert_same_dh dup_public(DH1024), key
+    assert_same_dh dup_public(dh1024), key
 
     pem = <<~EOF
     -----BEGIN DH PARAMETERS-----
@@ -52,14 +51,14 @@ def test_DHparams
     -----END DH PARAMETERS-----
     EOF
     key = OpenSSL::PKey::DH.new(pem)
-    assert_same_dh dup_public(DH1024), key
+    assert_same_dh dup_public(dh1024), key
 
-    assert_equal asn1.to_der, DH1024.to_der
-    assert_equal pem, DH1024.export
+    assert_equal asn1.to_der, dh1024.to_der
+    assert_equal pem, dh1024.export
   end
 
   def test_public_key
-    dh = OpenSSL::TestUtils::TEST_KEY_DH1024
+    dh = Fixtures.pkey_dh("dh1024")
     public_key = dh.public_key
     assert_no_key(public_key) #implies public_key.public? is false!
     assert_equal(dh.to_der, public_key.to_der)
@@ -67,14 +66,14 @@ def test_public_key
   end
 
   def test_generate_key
-    dh = OpenSSL::TestUtils::TEST_KEY_DH1024.public_key # creates a copy
+    dh = Fixtures.pkey_dh("dh1024").public_key # creates a copy
     assert_no_key(dh)
     dh.generate_key!
     assert_key(dh)
   end
 
   def test_key_exchange
-    dh = OpenSSL::TestUtils::TEST_KEY_DH1024
+    dh = Fixtures.pkey_dh("dh1024")
     dh2 = dh.public_key
     dh.generate_key!
     dh2.generate_key!
diff --git a/test/openssl/test_pkey_dsa.rb b/test/openssl/test_pkey_dsa.rb
index a4ccd1d8f95b..474f23888566 100644
--- a/test/openssl/test_pkey_dsa.rb
+++ b/test/openssl/test_pkey_dsa.rb
@@ -1,12 +1,9 @@
 # frozen_string_literal: false
 require_relative 'utils'
-require 'base64'
 
 if defined?(OpenSSL::TestUtils)
 
 class OpenSSL::TestPKeyDSA < OpenSSL::PKeyTestCase
-  DSA512 = OpenSSL::TestUtils::TEST_KEY_DSA512
-
   def test_private
     key = OpenSSL::PKey::DSA.new(256)
     assert(key.private?)
@@ -37,27 +34,28 @@ def test_new_break
   end
 
   def test_sign_verify
+    dsa512 = Fixtures.pkey("dsa512")
     data = "Sign me!"
     if defined?(OpenSSL::Digest::DSS1)
-      signature = DSA512.sign(OpenSSL::Digest::DSS1.new, data)
-      assert_equal true, DSA512.verify(OpenSSL::Digest::DSS1.new, signature, data)
+      signature = dsa512.sign(OpenSSL::Digest::DSS1.new, data)
+      assert_equal true, dsa512.verify(OpenSSL::Digest::DSS1.new, signature, data)
     end
 
-    return if OpenSSL::OPENSSL_VERSION_NUMBER <= 0x010000000
-    signature = DSA512.sign("SHA1", data)
-    assert_equal true, DSA512.verify("SHA1", signature, data)
+    return unless openssl?(1, 0, 0)
+    signature = dsa512.sign("SHA1", data)
+    assert_equal true, dsa512.verify("SHA1", signature, data)
 
     signature0 = (<<~'end;').unpack("m")[0]
       MCwCFH5h40plgU5Fh0Z4wvEEpz0eE9SnAhRPbkRB8ggsN/vsSEYMXvJwjGg/
       6g==
     end;
-    assert_equal true, DSA512.verify("SHA256", signature0, data)
+    assert_equal true, dsa512.verify("SHA256", signature0, data)
     signature1 = signature0.succ
-    assert_equal false, DSA512.verify("SHA256", signature1, data)
+    assert_equal false, dsa512.verify("SHA256", signature1, data)
   end
 
   def test_sys_sign_verify
-    key = OpenSSL::TestUtils::TEST_KEY_DSA256
+    key = Fixtures.pkey("dsa256")
     data = 'Sign me!'
     digest = OpenSSL::Digest::SHA1.digest(data)
     sig = key.syssign(digest)
@@ -66,17 +64,18 @@ def test_sys_sign_verify
 
   def test_DSAPrivateKey
     # OpenSSL DSAPrivateKey format; similar to RSAPrivateKey
+    dsa512 = Fixtures.pkey("dsa512")
     asn1 = OpenSSL::ASN1::Sequence([
       OpenSSL::ASN1::Integer(0),
-      OpenSSL::ASN1::Integer(DSA512.p),
-      OpenSSL::ASN1::Integer(DSA512.q),
-      OpenSSL::ASN1::Integer(DSA512.g),
-      OpenSSL::ASN1::Integer(DSA512.pub_key),
-      OpenSSL::ASN1::Integer(DSA512.priv_key)
+      OpenSSL::ASN1::Integer(dsa512.p),
+      OpenSSL::ASN1::Integer(dsa512.q),
+      OpenSSL::ASN1::Integer(dsa512.g),
+      OpenSSL::ASN1::Integer(dsa512.pub_key),
+      OpenSSL::ASN1::Integer(dsa512.priv_key)
     ])
     key = OpenSSL::PKey::DSA.new(asn1.to_der)
     assert_predicate key, :private?
-    assert_same_dsa DSA512, key
+    assert_same_dsa dsa512, key
 
     pem = <<~EOF
     -----BEGIN DSA PRIVATE KEY-----
@@ -89,14 +88,15 @@ def test_DSAPrivateKey
     -----END DSA PRIVATE KEY-----
     EOF
     key = OpenSSL::PKey::DSA.new(pem)
-    assert_same_dsa DSA512, key
+    assert_same_dsa dsa512, key
 
-    assert_equal asn1.to_der, DSA512.to_der
-    assert_equal pem, DSA512.export
+    assert_equal asn1.to_der, dsa512.to_der
+    assert_equal pem, dsa512.export
   end
 
   def test_DSAPrivateKey_encrypted
     # key = abcdef
+    dsa512 = Fixtures.pkey("dsa512")
     pem = <<~EOF
     -----BEGIN DSA PRIVATE KEY-----
     Proc-Type: 4,ENCRYPTED
@@ -111,35 +111,36 @@ def test_DSAPrivateKey_encrypted
     -----END DSA PRIVATE KEY-----
     EOF
     key = OpenSSL::PKey::DSA.new(pem, "abcdef")
-    assert_same_dsa DSA512, key
+    assert_same_dsa dsa512, key
     key = OpenSSL::PKey::DSA.new(pem) { "abcdef" }
-    assert_same_dsa DSA512, key
+    assert_same_dsa dsa512, key
 
     cipher = OpenSSL::Cipher.new("aes-128-cbc")
-    exported = DSA512.to_pem(cipher, "abcdef\0\1")
-    assert_same_dsa DSA512, OpenSSL::PKey::DSA.new(exported, "abcdef\0\1")
+    exported = dsa512.to_pem(cipher, "abcdef\0\1")
+    assert_same_dsa dsa512, OpenSSL::PKey::DSA.new(exported, "abcdef\0\1")
     assert_raise(OpenSSL::PKey::DSAError) {
       OpenSSL::PKey::DSA.new(exported, "abcdef")
     }
   end
 
   def test_PUBKEY
+    dsa512 = Fixtures.pkey("dsa512")
     asn1 = OpenSSL::ASN1::Sequence([
       OpenSSL::ASN1::Sequence([
         OpenSSL::ASN1::ObjectId("DSA"),
         OpenSSL::ASN1::Sequence([
-          OpenSSL::ASN1::Integer(DSA512.p),
-          OpenSSL::ASN1::Integer(DSA512.q),
-          OpenSSL::ASN1::Integer(DSA512.g)
+          OpenSSL::ASN1::Integer(dsa512.p),
+          OpenSSL::ASN1::Integer(dsa512.q),
+          OpenSSL::ASN1::Integer(dsa512.g)
         ])
       ]),
       OpenSSL::ASN1::BitString(
-        OpenSSL::ASN1::Integer(DSA512.pub_key).to_der
+        OpenSSL::ASN1::Integer(dsa512.pub_key).to_der
       )
     ])
     key = OpenSSL::PKey::DSA.new(asn1.to_der)
     assert_not_predicate key, :private?
-    assert_same_dsa dup_public(DSA512), key
+    assert_same_dsa dup_public(dsa512), key
 
     pem = <<~EOF
     -----BEGIN PUBLIC KEY-----
@@ -152,10 +153,10 @@ def test_PUBKEY
     -----END PUBLIC KEY-----
     EOF
     key = OpenSSL::PKey::DSA.new(pem)
-    assert_same_dsa dup_public(DSA512), key
+    assert_same_dsa dup_public(dsa512), key
 
-    assert_equal asn1.to_der, dup_public(DSA512).to_der
-    assert_equal pem, dup_public(DSA512).export
+    assert_equal asn1.to_der, dup_public(dsa512).to_der
+    assert_equal pem, dup_public(dsa512).export
   end
 
   def test_read_DSAPublicKey_pem
diff --git a/test/openssl/test_pkey_ec.rb b/test/openssl/test_pkey_ec.rb
index c549d9c674f3..8119b77cc71e 100644
--- a/test/openssl/test_pkey_ec.rb
+++ b/test/openssl/test_pkey_ec.rb
@@ -4,8 +4,6 @@
 if defined?(OpenSSL::TestUtils) && defined?(OpenSSL::PKey::EC)
 
 class OpenSSL::TestEC < OpenSSL::PKeyTestCase
-  P256 = OpenSSL::TestUtils::TEST_KEY_EC_P256V1
-
   def test_ec_key
     builtin_curves = OpenSSL::PKey::EC.builtin_curves
     assert_not_empty builtin_curves
@@ -74,17 +72,18 @@ def test_check_key
   end
 
   def test_sign_verify
+    p256 = Fixtures.pkey("p256")
     data = "Sign me!"
-    signature = P256.sign("SHA1", data)
-    assert_equal true, P256.verify("SHA1", signature, data)
+    signature = p256.sign("SHA1", data)
+    assert_equal true, p256.verify("SHA1", signature, data)
 
     signature0 = (<<~'end;').unpack("m")[0]
       MEQCIEOTY/hD7eI8a0qlzxkIt8LLZ8uwiaSfVbjX2dPAvN11AiAQdCYx56Fq
       QdBp1B4sxJoA8jvODMMklMyBKVmudboA6A==
     end;
-    assert_equal true, P256.verify("SHA256", signature0, data)
+    assert_equal true, p256.verify("SHA256", signature0, data)
     signature1 = signature0.succ
-    assert_equal false, P256.verify("SHA256", signature1, data)
+    assert_equal false, p256.verify("SHA256", signature1, data)
   end
 
   def test_dsa_sign_verify
@@ -124,21 +123,22 @@ def test_dh_compute_key
   end
 
   def test_ECPrivateKey
+    p256 = Fixtures.pkey("p256")
     asn1 = OpenSSL::ASN1::Sequence([
       OpenSSL::ASN1::Integer(1),
-      OpenSSL::ASN1::OctetString(P256.private_key.to_s(2)),
+      OpenSSL::ASN1::OctetString(p256.private_key.to_s(2)),
       OpenSSL::ASN1::ASN1Data.new(
         [OpenSSL::ASN1::ObjectId("prime256v1")],
         0, :CONTEXT_SPECIFIC
       ),
       OpenSSL::ASN1::ASN1Data.new(
-        [OpenSSL::ASN1::BitString(P256.public_key.to_bn.to_s(2))],
+        [OpenSSL::ASN1::BitString(p256.public_key.to_bn.to_s(2))],
         1, :CONTEXT_SPECIFIC
       )
     ])
     key = OpenSSL::PKey::EC.new(asn1.to_der)
     assert_predicate key, :private?
-    assert_same_ec P256, key
+    assert_same_ec p256, key
 
     pem = <<~EOF
     -----BEGIN EC PRIVATE KEY-----
@@ -148,13 +148,14 @@ def test_ECPrivateKey
     -----END EC PRIVATE KEY-----
     EOF
     key = OpenSSL::PKey::EC.new(pem)
-    assert_same_ec P256, key
+    assert_same_ec p256, key
 
-    assert_equal asn1.to_der, P256.to_der
-    assert_equal pem, P256.export
+    assert_equal asn1.to_der, p256.to_der
+    assert_equal pem, p256.export
   end
 
   def test_ECPrivateKey_encrypted
+    p256 = Fixtures.pkey("p256")
     # key = abcdef
     pem = <<~EOF
     -----BEGIN EC PRIVATE KEY-----
@@ -167,31 +168,32 @@ def test_ECPrivateKey_encrypted
     -----END EC PRIVATE KEY-----
     EOF
     key = OpenSSL::PKey::EC.new(pem, "abcdef")
-    assert_same_ec P256, key
+    assert_same_ec p256, key
     key = OpenSSL::PKey::EC.new(pem) { "abcdef" }
-    assert_same_ec P256, key
+    assert_same_ec p256, key
 
     cipher = OpenSSL::Cipher.new("aes-128-cbc")
-    exported = P256.to_pem(cipher, "abcdef\0\1")
-    assert_same_ec P256, OpenSSL::PKey::EC.new(exported, "abcdef\0\1")
+    exported = p256.to_pem(cipher, "abcdef\0\1")
+    assert_same_ec p256, OpenSSL::PKey::EC.new(exported, "abcdef\0\1")
     assert_raise(OpenSSL::PKey::ECError) {
       OpenSSL::PKey::EC.new(exported, "abcdef")
     }
   end
 
   def test_PUBKEY
+    p256 = Fixtures.pkey("p256")
     asn1 = OpenSSL::ASN1::Sequence([
       OpenSSL::ASN1::Sequence([
         OpenSSL::ASN1::ObjectId("id-ecPublicKey"),
         OpenSSL::ASN1::ObjectId("prime256v1")
       ]),
       OpenSSL::ASN1::BitString(
-        P256.public_key.to_bn.to_s(2)
+        p256.public_key.to_bn.to_s(2)
       )
     ])
     key = OpenSSL::PKey::EC.new(asn1.to_der)
     assert_not_predicate key, :private?
-    assert_same_ec dup_public(P256), key
+    assert_same_ec dup_public(p256), key
 
     pem = <<~EOF
     -----BEGIN PUBLIC KEY-----
@@ -200,10 +202,10 @@ def test_PUBKEY
     -----END PUBLIC KEY-----
     EOF
     key = OpenSSL::PKey::EC.new(pem)
-    assert_same_ec dup_public(P256), key
+    assert_same_ec dup_public(p256), key
 
-    assert_equal asn1.to_der, dup_public(P256).to_der
-    assert_equal pem, dup_public(P256).export
+    assert_equal asn1.to_der, dup_public(p256).to_der
+    assert_equal pem, dup_public(p256).export
   end
 
   def test_ec_group
@@ -305,7 +307,7 @@ def test_ec_point_mul
       raise if $!.message !~ /unsupported field/
     end
 
-    p256_key = P256
+    p256_key = Fixtures.pkey("p256")
     p256_g = p256_key.group
     assert_equal(p256_key.public_key, p256_g.generator.mul(p256_key.private_key))
 
diff --git a/test/openssl/test_pkey_rsa.rb b/test/openssl/test_pkey_rsa.rb
index 93760f747efa..c120556339db 100644
--- a/test/openssl/test_pkey_rsa.rb
+++ b/test/openssl/test_pkey_rsa.rb
@@ -1,12 +1,9 @@
 # frozen_string_literal: false
-require_relative 'utils'
-require 'base64'
+require_relative "utils"
 
 if defined?(OpenSSL::TestUtils)
 
 class OpenSSL::TestPKeyRSA < OpenSSL::PKeyTestCase
-  RSA1024 = OpenSSL::TestUtils::TEST_KEY_RSA1024
-
   def test_padding
     key = OpenSSL::PKey::RSA.new(512, 3)
 
@@ -71,22 +68,23 @@ def test_new_break
   end
 
   def test_sign_verify
+    rsa1024 = Fixtures.pkey("rsa1024")
     data = "Sign me!"
-    signature = RSA1024.sign("SHA1", data)
-    assert_equal true, RSA1024.verify("SHA1", signature, data)
+    signature = rsa1024.sign("SHA1", data)
+    assert_equal true, rsa1024.verify("SHA1", signature, data)
 
     signature0 = (<<~'end;').unpack("m")[0]
       oLCgbprPvfhM4pjFQiDTFeWI9Sk+Og7Nh9TmIZ/xSxf2CGXQrptlwo7NQ28+
       WA6YQo8jPH4hSuyWIM4Gz4qRYiYRkl5TDMUYob94zm8Si1HxEiS9354tzvqS
       zS8MLW2BtNPuTubMxTItHGTnOzo9sUg0LAHVFt8kHG2NfKAw/gQ=
     end;
-    assert_equal true, RSA1024.verify("SHA256", signature0, data)
+    assert_equal true, rsa1024.verify("SHA256", signature0, data)
     signature1 = signature0.succ
-    assert_equal false, RSA1024.verify("SHA256", signature1, data)
+    assert_equal false, rsa1024.verify("SHA256", signature1, data)
   end
 
   def test_digest_state_irrelevant_sign
-    key = RSA1024
+    key = Fixtures.pkey("rsa1024")
     digest1 = OpenSSL::Digest::SHA1.new
     digest2 = OpenSSL::Digest::SHA1.new
     data = 'Sign me!'
@@ -97,7 +95,7 @@ def test_digest_state_irrelevant_sign
   end
 
   def test_digest_state_irrelevant_verify
-    key = RSA1024
+    key = Fixtures.pkey("rsa1024")
     digest1 = OpenSSL::Digest::SHA1.new
     digest2 = OpenSSL::Digest::SHA1.new
     data = 'Sign me!'
@@ -116,20 +114,21 @@ def test_verify_empty_rsa
   end
 
   def test_RSAPrivateKey
+    rsa1024 = Fixtures.pkey("rsa1024")
     asn1 = OpenSSL::ASN1::Sequence([
       OpenSSL::ASN1::Integer(0),
-      OpenSSL::ASN1::Integer(RSA1024.n),
-      OpenSSL::ASN1::Integer(RSA1024.e),
-      OpenSSL::ASN1::Integer(RSA1024.d),
-      OpenSSL::ASN1::Integer(RSA1024.p),
-      OpenSSL::ASN1::Integer(RSA1024.q),
-      OpenSSL::ASN1::Integer(RSA1024.dmp1),
-      OpenSSL::ASN1::Integer(RSA1024.dmq1),
-      OpenSSL::ASN1::Integer(RSA1024.iqmp)
+      OpenSSL::ASN1::Integer(rsa1024.n),
+      OpenSSL::ASN1::Integer(rsa1024.e),
+      OpenSSL::ASN1::Integer(rsa1024.d),
+      OpenSSL::ASN1::Integer(rsa1024.p),
+      OpenSSL::ASN1::Integer(rsa1024.q),
+      OpenSSL::ASN1::Integer(rsa1024.dmp1),
+      OpenSSL::ASN1::Integer(rsa1024.dmq1),
+      OpenSSL::ASN1::Integer(rsa1024.iqmp)
     ])
     key = OpenSSL::PKey::RSA.new(asn1.to_der)
     assert_predicate key, :private?
-    assert_same_rsa RSA1024, key
+    assert_same_rsa rsa1024, key
 
     pem = <<~EOF
     -----BEGIN RSA PRIVATE KEY-----
@@ -149,13 +148,14 @@ def test_RSAPrivateKey
     -----END RSA PRIVATE KEY-----
     EOF
     key = OpenSSL::PKey::RSA.new(pem)
-    assert_same_rsa RSA1024, key
+    assert_same_rsa rsa1024, key
 
-    assert_equal asn1.to_der, RSA1024.to_der
-    assert_equal pem, RSA1024.export
+    assert_equal asn1.to_der, rsa1024.to_der
+    assert_equal pem, rsa1024.export
   end
 
   def test_RSAPrivateKey_encrypted
+    rsa1024 = Fixtures.pkey("rsa1024")
     # key = abcdef
     pem = <<~EOF
     -----BEGIN RSA PRIVATE KEY-----
@@ -178,26 +178,27 @@ def test_RSAPrivateKey_encrypted
     -----END RSA PRIVATE KEY-----
     EOF
     key = OpenSSL::PKey::RSA.new(pem, "abcdef")
-    assert_same_rsa RSA1024, key
+    assert_same_rsa rsa1024, key
     key = OpenSSL::PKey::RSA.new(pem) { "abcdef" }
-    assert_same_rsa RSA1024, key
+    assert_same_rsa rsa1024, key
 
     cipher = OpenSSL::Cipher.new("aes-128-cbc")
-    exported = RSA1024.to_pem(cipher, "abcdef\0\1")
-    assert_same_rsa RSA1024, OpenSSL::PKey::RSA.new(exported, "abcdef\0\1")
+    exported = rsa1024.to_pem(cipher, "abcdef\0\1")
+    assert_same_rsa rsa1024, OpenSSL::PKey::RSA.new(exported, "abcdef\0\1")
     assert_raise(OpenSSL::PKey::RSAError) {
       OpenSSL::PKey::RSA.new(exported, "abcdef")
     }
   end
 
   def test_RSAPublicKey
+    rsa1024 = Fixtures.pkey("rsa1024")
     asn1 = OpenSSL::ASN1::Sequence([
-      OpenSSL::ASN1::Integer(RSA1024.n),
-      OpenSSL::ASN1::Integer(RSA1024.e)
+      OpenSSL::ASN1::Integer(rsa1024.n),
+      OpenSSL::ASN1::Integer(rsa1024.e)
     ])
     key = OpenSSL::PKey::RSA.new(asn1.to_der)
     assert_not_predicate key, :private?
-    assert_same_rsa dup_public(RSA1024), key
+    assert_same_rsa dup_public(rsa1024), key
 
     pem = <<~EOF
     -----BEGIN RSA PUBLIC KEY-----
@@ -207,10 +208,11 @@ def test_RSAPublicKey
     -----END RSA PUBLIC KEY-----
     EOF
     key = OpenSSL::PKey::RSA.new(pem)
-    assert_same_rsa dup_public(RSA1024), key
+    assert_same_rsa dup_public(rsa1024), key
   end
 
   def test_PUBKEY
+    rsa1024 = Fixtures.pkey("rsa1024")
     asn1 = OpenSSL::ASN1::Sequence([
       OpenSSL::ASN1::Sequence([
         OpenSSL::ASN1::ObjectId("rsaEncryption"),
@@ -218,14 +220,14 @@ def test_PUBKEY
       ]),
       OpenSSL::ASN1::BitString(
         OpenSSL::ASN1::Sequence([
-          OpenSSL::ASN1::Integer(RSA1024.n),
-          OpenSSL::ASN1::Integer(RSA1024.e)
+          OpenSSL::ASN1::Integer(rsa1024.n),
+          OpenSSL::ASN1::Integer(rsa1024.e)
         ]).to_der
       )
     ])
     key = OpenSSL::PKey::RSA.new(asn1.to_der)
     assert_not_predicate key, :private?
-    assert_same_rsa dup_public(RSA1024), key
+    assert_same_rsa dup_public(rsa1024), key
 
     pem = <<~EOF
     -----BEGIN PUBLIC KEY-----
@@ -236,14 +238,14 @@ def test_PUBKEY
     -----END PUBLIC KEY-----
     EOF
     key = OpenSSL::PKey::RSA.new(pem)
-    assert_same_rsa dup_public(RSA1024), key
+    assert_same_rsa dup_public(rsa1024), key
 
-    assert_equal asn1.to_der, dup_public(RSA1024).to_der
-    assert_equal pem, dup_public(RSA1024).export
+    assert_equal asn1.to_der, dup_public(rsa1024).to_der
+    assert_equal pem, dup_public(rsa1024).export
   end
 
   def test_pem_passwd
-    key = RSA1024
+    key = Fixtures.pkey("rsa1024")
     pem3c = key.to_pem("aes-128-cbc", "key")
     assert_match (/ENCRYPTED/), pem3c
     assert_equal key.to_der, OpenSSL::PKey.read(pem3c, "key").to_der
diff --git a/test/openssl/test_random.rb b/test/openssl/test_random.rb
index 607946192089..c0160f9a7a32 100644
--- a/test/openssl/test_random.rb
+++ b/test/openssl/test_random.rb
@@ -1,6 +1,8 @@
 # frozen_string_literal: false
 require_relative "utils"
 
+if defined?(OpenSSL::TestUtils)
+
 class OpenSSL::TestRandom < OpenSSL::TestCase
   def test_random_bytes
     assert_equal("", OpenSSL::Random.random_bytes(0))
@@ -12,4 +14,6 @@ def test_pseudo_bytes
     assert_equal("", OpenSSL::Random.pseudo_bytes(0))
     assert_equal(12, OpenSSL::Random.pseudo_bytes(12).bytesize)
   end if OpenSSL::Random.methods.include?(:pseudo_bytes)
-end if defined?(OpenSSL::TestCase)
+end
+
+end
diff --git a/test/openssl/test_ssl.rb b/test/openssl/test_ssl.rb
index 8c65df953d5f..7bb32adf92e2 100644
--- a/test/openssl/test_ssl.rb
+++ b/test/openssl/test_ssl.rb
@@ -35,7 +35,7 @@ def test_ssl_with_server_cert
 
       readwrite_loop(ctx, ssl)
     }
-    start_server(ctx_proc: ctx_proc, server_proc: server_proc) { |server, port|
+    start_server(ctx_proc: ctx_proc, server_proc: server_proc) { |port|
       begin
         sock = TCPSocket.new("127.0.0.1", port)
         ctx = OpenSSL::SSL::SSLContext.new
@@ -56,7 +56,7 @@ def test_ssl_with_server_cert
   end
 
   def test_sysread_and_syswrite
-    start_server { |server, port|
+    start_server { |port|
       server_connect(port) { |ssl|
         str = "x" * 100 + "\n"
         ssl.syswrite(str)
@@ -72,7 +72,7 @@ def test_sysread_and_syswrite
   end
 
   def test_sync_close
-    start_server { |server, port|
+    start_server { |port|
       begin
         sock = TCPSocket.new("127.0.0.1", port)
         ssl = OpenSSL::SSL::SSLSocket.new(sock)
@@ -97,7 +97,7 @@ def test_sync_close
   end
 
   def test_copy_stream
-    start_server do |server, port|
+    start_server do |port|
       server_connect(port) do |ssl|
         IO.pipe do |r, w|
           str = "hello world\n"
@@ -112,21 +112,16 @@ def test_copy_stream
 
   def test_client_auth_failure
     vflag = OpenSSL::SSL::VERIFY_PEER|OpenSSL::SSL::VERIFY_FAIL_IF_NO_PEER_CERT
-    start_server(verify_mode: vflag, ignore_listener_error: true) { |server, port|
-      sock = TCPSocket.new("127.0.0.1", port)
-      ssl = OpenSSL::SSL::SSLSocket.new(sock)
-      ssl.sync_close = true
-      begin
-        assert_handshake_error { ssl.connect }
-      ensure
-        ssl.close
-      end
+    start_server(verify_mode: vflag, ignore_listener_error: true) { |port|
+      assert_handshake_error {
+        server_connect(port) { |ssl| ssl.puts("abc"); ssl.gets }
+      }
     }
   end
 
   def test_client_auth_success
     vflag = OpenSSL::SSL::VERIFY_PEER|OpenSSL::SSL::VERIFY_FAIL_IF_NO_PEER_CERT
-    start_server(verify_mode: vflag) { |server, port|
+    start_server(verify_mode: vflag) { |port|
       ctx = OpenSSL::SSL::SSLContext.new
       ctx.key = @cli_key
       ctx.cert = @cli_cert
@@ -153,19 +148,21 @@ def test_client_auth_success
 
   def test_client_auth_public_key
     vflag = OpenSSL::SSL::VERIFY_PEER|OpenSSL::SSL::VERIFY_FAIL_IF_NO_PEER_CERT
-    start_server(verify_mode: vflag, ignore_listener_error: true) do |server, port|
+    start_server(verify_mode: vflag, ignore_listener_error: true) do |port|
       assert_raise(ArgumentError) {
         ctx = OpenSSL::SSL::SSLContext.new
         ctx.key = @cli_key.public_key
         ctx.cert = @cli_cert
-        server_connect(port, ctx) { }
+        server_connect(port, ctx) { |ssl| ssl.puts("abc"); ssl.gets }
       }
 
       ctx = OpenSSL::SSL::SSLContext.new
       ctx.client_cert_cb = Proc.new{ |ssl|
         [@cli_cert, @cli_key.public_key]
       }
-      assert_handshake_error { server_connect(port, ctx) }
+      assert_handshake_error {
+        server_connect(port, ctx) { |ssl| ssl.puts("abc"); ssl.gets }
+      }
     end
   end
 
@@ -175,7 +172,7 @@ def test_client_ca
     end
 
     vflag = OpenSSL::SSL::VERIFY_PEER|OpenSSL::SSL::VERIFY_FAIL_IF_NO_PEER_CERT
-    start_server(verify_mode: vflag, ctx_proc: ctx_proc) { |server, port|
+    start_server(verify_mode: vflag, ctx_proc: ctx_proc) { |port|
       ctx = OpenSSL::SSL::SSLContext.new
       client_ca_from_server = nil
       ctx.client_cert_cb = Proc.new do |sslconn|
@@ -187,8 +184,8 @@ def test_client_ca
   end
 
   def test_read_nonblock_without_session
-    OpenSSL::TestUtils.silent do
-      start_server(start_immediately: false) { |server, port|
+    EnvUtil.suppress_warning do
+      start_server(start_immediately: false) { |port|
         sock = TCPSocket.new("127.0.0.1", port)
         ssl = OpenSSL::SSL::SSLSocket.new(sock)
         ssl.sync_close = true
@@ -206,26 +203,21 @@ def test_read_nonblock_without_session
 
   def test_starttls
     server_proc = -> (ctx, ssl) {
-      begin
-        while line = ssl.gets
-          if line =~ /^STARTTLS$/
-            ssl.write("x")
-            ssl.flush
-            ssl.accept
-            next
-          end
-          ssl.write(line)
+      while line = ssl.gets
+        if line =~ /^STARTTLS$/
+          ssl.write("x")
+          ssl.flush
+          ssl.accept
+          break
         end
-      rescue OpenSSL::SSL::SSLError
-      rescue IOError
-      ensure
-        ssl.close rescue nil
+        ssl.write(line)
       end
+      readwrite_loop(ctx, ssl)
     }
 
     EnvUtil.suppress_warning do # read/write on not started session
       start_server(start_immediately: false,
-                   server_proc: server_proc) { |server, port|
+                   server_proc: server_proc) { |port|
         begin
           sock = TCPSocket.new("127.0.0.1", port)
           ssl = OpenSSL::SSL::SSLSocket.new(sock)
@@ -248,7 +240,7 @@ def test_starttls
   end
 
   def test_parallel
-    start_server { |server, port|
+    start_server { |port|
       ssls = []
       10.times{
         sock = TCPSocket.new("127.0.0.1", port)
@@ -269,7 +261,7 @@ def test_parallel
   end
 
   def test_verify_result
-    start_server(ignore_listener_error: true) { |server, port|
+    start_server(ignore_listener_error: true) { |port|
       sock = TCPSocket.new("127.0.0.1", port)
       ctx = OpenSSL::SSL::SSLContext.new
       ctx.verify_mode = OpenSSL::SSL::VERIFY_PEER
@@ -283,7 +275,7 @@ def test_verify_result
       end
     }
 
-    start_server { |server, port|
+    start_server { |port|
       sock = TCPSocket.new("127.0.0.1", port)
       ctx = OpenSSL::SSL::SSLContext.new
       ctx.verify_mode = OpenSSL::SSL::VERIFY_PEER
@@ -301,7 +293,7 @@ def test_verify_result
       end
     }
 
-    start_server(ignore_listener_error: true) { |server, port|
+    start_server(ignore_listener_error: true) { |port|
       sock = TCPSocket.new("127.0.0.1", port)
       ctx = OpenSSL::SSL::SSLContext.new
       ctx.verify_mode = OpenSSL::SSL::VERIFY_PEER
@@ -321,7 +313,7 @@ def test_verify_result
   end
 
   def test_exception_in_verify_callback_is_ignored
-    start_server(ignore_listener_error: true) { |server, port|
+    start_server(ignore_listener_error: true) { |port|
       sock = TCPSocket.new("127.0.0.1", port)
       ctx = OpenSSL::SSL::SSLContext.new
       ctx.verify_mode = OpenSSL::SSL::VERIFY_PEER
@@ -332,7 +324,7 @@ def test_exception_in_verify_callback_is_ignored
       ssl = OpenSSL::SSL::SSLSocket.new(sock, ctx)
       ssl.sync_close = true
       begin
-        OpenSSL::TestUtils.silent do
+        EnvUtil.suppress_warning do
           # SSLError, not RuntimeError
           assert_raise(OpenSSL::SSL::SSLError) { ssl.connect }
         end
@@ -359,13 +351,17 @@ def test_sslctx_set_params
   end
 
   def test_post_connect_check_with_anon_ciphers
+    pend "TLS 1.2 is not supported" unless tls12_supported?
+
     ctx_proc = -> ctx {
+      ctx.ssl_version = :TLSv1_2
       ctx.ciphers = "aNULL"
       ctx.security_level = 0
     }
 
-    start_server(ctx_proc: ctx_proc) { |server, port|
+    start_server(ctx_proc: ctx_proc) { |port|
       ctx = OpenSSL::SSL::SSLContext.new
+      ctx.ssl_version = :TLSv1_2
       ctx.ciphers = "aNULL"
       ctx.security_level = 0
       server_connect(port, ctx) { |ssl|
@@ -379,7 +375,7 @@ def test_post_connect_check_with_anon_ciphers
   def test_post_connection_check
     sslerr = OpenSSL::SSL::SSLError
 
-    start_server { |server, port|
+    start_server { |port|
       server_connect(port) { |ssl|
         assert_raise(sslerr){ssl.post_connection_check("localhost.localdomain")}
         assert_raise(sslerr){ssl.post_connection_check("127.0.0.1")}
@@ -400,7 +396,7 @@ def test_post_connection_check
       ["subjectAltName","IP:127.0.0.1",false],
     ]
     @svr_cert = issue_cert(@svr, @svr_key, 4, exts, @ca_cert, @ca_key)
-    start_server { |server, port|
+    start_server { |port|
       server_connect(port) { |ssl|
         assert(ssl.post_connection_check("localhost.localdomain"))
         assert(ssl.post_connection_check("127.0.0.1"))
@@ -420,7 +416,7 @@ def test_post_connection_check
       ["subjectAltName","DNS:*.localdomain",false],
     ]
     @svr_cert = issue_cert(@svr, @svr_key, 5, exts, @ca_cert, @ca_key)
-    start_server { |server, port|
+    start_server { |port|
       server_connect(port) { |ssl|
         assert(ssl.post_connection_check("localhost.localdomain"))
         assert_raise(sslerr){ssl.post_connection_check("127.0.0.1")}
@@ -623,48 +619,44 @@ def socketpair
   end
 
   def test_tlsext_hostname
-    ctx3 = OpenSSL::SSL::SSLContext.new
-    ctx3.ciphers = "ADH"
-    ctx3.tmp_dh_callback = proc { OpenSSL::TestUtils::TEST_KEY_DH1024 }
-    ctx3.security_level = 0
-    assert_not_predicate ctx3, :frozen?
+    fooctx = OpenSSL::SSL::SSLContext.new
+    fooctx.tmp_dh_callback = proc { Fixtures.pkey_dh("dh1024") }
+    fooctx.cert = @cli_cert
+    fooctx.key = @cli_key
 
-    ctx_proc = -> ctx {
-      ctx.ciphers = "ALL:!aNULL"
+    ctx_proc = proc { |ctx|
       ctx.servername_cb = proc { |ssl, servername|
         case servername
         when "foo.example.com"
-          ctx3
+          fooctx
         when "bar.example.com"
           nil
         else
-          raise "unknown hostname"
+          raise "unreachable"
         end
       }
     }
-    start_server(ctx_proc: ctx_proc) do |server, port|
-      ctx = OpenSSL::SSL::SSLContext.new
-      ctx.ciphers = "ALL"
-      ctx.security_level = 0
-
+    start_server(ctx_proc: ctx_proc) do |port|
       sock = TCPSocket.new("127.0.0.1", port)
       begin
-        ssl = OpenSSL::SSL::SSLSocket.new(sock, ctx)
+        ssl = OpenSSL::SSL::SSLSocket.new(sock)
         ssl.hostname = "foo.example.com"
         ssl.connect
-        assert_match (/^ADH-/), ssl.cipher[0], "the context returned by servername_cb is used"
-        assert_predicate ctx3, :frozen?
+        assert_equal @cli_cert.serial, ssl.peer_cert.serial
+        assert_predicate fooctx, :frozen?
       ensure
+        ssl&.close
         sock.close
       end
 
       sock = TCPSocket.new("127.0.0.1", port)
       begin
-        ssl = OpenSSL::SSL::SSLSocket.new(sock, ctx)
+        ssl = OpenSSL::SSL::SSLSocket.new(sock)
         ssl.hostname = "bar.example.com"
         ssl.connect
-        assert_not_match (/^A(EC)?DH-/), ssl.cipher[0], "the original context is used"
+        assert_equal @svr_cert.serial, ssl.peer_cert.serial
       ensure
+        ssl&.close
         sock.close
       end
     end
@@ -674,9 +666,9 @@ def test_servername_cb_raises_an_exception_on_unknown_objects
     hostname = 'example.org'
 
     ctx2 = OpenSSL::SSL::SSLContext.new
-    ctx2.ciphers = "aNULL"
-    ctx2.tmp_dh_callback = proc { OpenSSL::TestUtils::TEST_KEY_DH1024 }
-    ctx2.security_level = 0
+    ctx2.cert = @svr_cert
+    ctx2.key = @svr_key
+    ctx2.tmp_dh_callback = proc { Fixtures.pkey_dh("dh1024") }
     ctx2.servername_cb = lambda { |args| Object.new }
 
     sock1, sock2 = socketpair
@@ -684,8 +676,6 @@ def test_servername_cb_raises_an_exception_on_unknown_objects
     s2 = OpenSSL::SSL::SSLSocket.new(sock2, ctx2)
 
     ctx1 = OpenSSL::SSL::SSLContext.new
-    ctx1.ciphers = "aNULL"
-    ctx1.security_level = 0
 
     s1 = OpenSSL::SSL::SSLSocket.new(sock1, ctx1)
     s1.hostname = hostname
@@ -716,7 +706,7 @@ def test_verify_hostname_on_connect
       ctx.key = @svr_key
     }
 
-    start_server(ctx_proc: ctx_proc, ignore_listener_error: true) do |server, port|
+    start_server(ctx_proc: ctx_proc, ignore_listener_error: true) do |port|
       ctx = OpenSSL::SSL::SSLContext.new
       ctx.verify_hostname = true
       ctx.cert_store = OpenSSL::X509::Store.new
@@ -749,31 +739,6 @@ def test_verify_hostname_on_connect
     end
   end
 
-  def test_multibyte_read_write
-    #German a umlaut
-    auml = [%w{ C3 A4 }.join('')].pack('H*')
-    auml.force_encoding(Encoding::UTF_8)
-
-    [10, 1000, 100000].each {|i|
-      str = nil
-      num_written = nil
-      server_proc = Proc.new {|ctx, ssl|
-        cmp = ssl.read
-        raw_size = cmp.size
-        cmp.force_encoding(Encoding::UTF_8)
-        assert_equal(str, cmp)
-        assert_equal(num_written, raw_size)
-        ssl.close
-      }
-      start_server(server_proc: server_proc) { |server, port|
-        server_connect(port) { |ssl|
-          str = auml * i
-          num_written = ssl.write(str)
-        }
-      }
-    }
-  end
-
   def test_unset_OP_ALL
     ctx_proc = Proc.new { |ctx|
       # If OP_DONT_INSERT_EMPTY_FRAGMENTS is not defined, this test is
@@ -781,7 +746,7 @@ def test_unset_OP_ALL
       # But it also degrades gracefully, so keep it
       ctx.options = OpenSSL::SSL::OP_ALL
     }
-    start_server(ctx_proc: ctx_proc) { |server, port|
+    start_server(ctx_proc: ctx_proc) { |port|
       server_connect(port) { |ssl|
         ssl.puts('hello')
         assert_equal("hello\n", ssl.gets)
@@ -793,7 +758,7 @@ def test_unset_OP_ALL
 
   def test_forbid_ssl_v3_for_client
     ctx_proc = Proc.new { |ctx| ctx.options = OpenSSL::SSL::OP_ALL | OpenSSL::SSL::OP_NO_SSLv3 }
-    start_server_version(:SSLv23, ctx_proc) { |server, port|
+    start_server_version(:SSLv23, ctx_proc) { |port|
       ctx = OpenSSL::SSL::SSLContext.new
       ctx.ssl_version = :SSLv3
       assert_handshake_error { server_connect(port, ctx) }
@@ -801,7 +766,7 @@ def test_forbid_ssl_v3_for_client
   end
 
   def test_forbid_ssl_v3_from_server
-    start_server_version(:SSLv3) { |server, port|
+    start_server_version(:SSLv3) { |port|
       ctx = OpenSSL::SSL::SSLContext.new
       ctx.options = OpenSSL::SSL::OP_ALL | OpenSSL::SSL::OP_NO_SSLv3
       assert_handshake_error { server_connect(port, ctx) }
@@ -813,14 +778,15 @@ def test_forbid_ssl_v3_from_server
 if OpenSSL::SSL::SSLContext::METHODS.include?(:TLSv1_1) && OpenSSL::SSL::SSLContext::METHODS.include?(:TLSv1)
 
   def test_tls_v1_1
-    start_server_version(:TLSv1_1) { |server, port|
-      server_connect(port) { |ssl| assert_equal("TLSv1.1", ssl.ssl_version) }
+    start_server_version(:TLSv1_1) { |port|
+      ctx = OpenSSL::SSL::SSLContext.new(:TLSv1_1)
+      server_connect(port, ctx) { |ssl| assert_equal("TLSv1.1", ssl.ssl_version) }
     }
   end
 
   def test_forbid_tls_v1_for_client
     ctx_proc = Proc.new { |ctx| ctx.options = OpenSSL::SSL::OP_ALL | OpenSSL::SSL::OP_NO_TLSv1 }
-    start_server_version(:SSLv23, ctx_proc) { |server, port|
+    start_server_version(:SSLv23, ctx_proc) { |port|
       ctx = OpenSSL::SSL::SSLContext.new
       ctx.ssl_version = :TLSv1
       assert_handshake_error { server_connect(port, ctx) }
@@ -828,7 +794,7 @@ def test_forbid_tls_v1_for_client
   end
 
   def test_forbid_tls_v1_from_server
-    start_server_version(:TLSv1) { |server, port|
+    start_server_version(:TLSv1) { |port|
       ctx = OpenSSL::SSL::SSLContext.new
       ctx.options = OpenSSL::SSL::OP_ALL | OpenSSL::SSL::OP_NO_TLSv1
       assert_handshake_error { server_connect(port, ctx) }
@@ -840,16 +806,16 @@ def test_forbid_tls_v1_from_server
 if OpenSSL::SSL::SSLContext::METHODS.include?(:TLSv1_2) && OpenSSL::SSL::SSLContext::METHODS.include?(:TLSv1_1)
 
   def test_tls_v1_2
-    start_server_version(:TLSv1_2) { |server, port|
+    start_server_version(:TLSv1_2) { |port|
       ctx = OpenSSL::SSL::SSLContext.new
       ctx.ssl_version = :TLSv1_2_client
       server_connect(port, ctx) { |ssl| assert_equal("TLSv1.2", ssl.ssl_version) }
     }
-  end if OpenSSL::OPENSSL_VERSION_NUMBER > 0x10001000
+  end
 
   def test_forbid_tls_v1_1_for_client
     ctx_proc = Proc.new { |ctx| ctx.options = OpenSSL::SSL::OP_ALL | OpenSSL::SSL::OP_NO_TLSv1_1 }
-    start_server_version(:SSLv23, ctx_proc) { |server, port|
+    start_server_version(:SSLv23, ctx_proc) { |port|
       ctx = OpenSSL::SSL::SSLContext.new
       ctx.ssl_version = :TLSv1_1
       assert_handshake_error { server_connect(port, ctx) }
@@ -857,7 +823,7 @@ def test_forbid_tls_v1_1_for_client
   end if defined?(OpenSSL::SSL::OP_NO_TLSv1_1)
 
   def test_forbid_tls_v1_1_from_server
-    start_server_version(:TLSv1_1) { |server, port|
+    start_server_version(:TLSv1_1) { |port|
       ctx = OpenSSL::SSL::SSLContext.new
       ctx.options = OpenSSL::SSL::OP_ALL | OpenSSL::SSL::OP_NO_TLSv1_1
       assert_handshake_error { server_connect(port, ctx) }
@@ -866,7 +832,7 @@ def test_forbid_tls_v1_1_from_server
 
   def test_forbid_tls_v1_2_for_client
     ctx_proc = Proc.new { |ctx| ctx.options = OpenSSL::SSL::OP_ALL | OpenSSL::SSL::OP_NO_TLSv1_2 }
-    start_server_version(:SSLv23, ctx_proc) { |server, port|
+    start_server_version(:SSLv23, ctx_proc) { |port|
       ctx = OpenSSL::SSL::SSLContext.new
       ctx.ssl_version = :TLSv1_2
       assert_handshake_error { server_connect(port, ctx) }
@@ -874,7 +840,7 @@ def test_forbid_tls_v1_2_for_client
   end if defined?(OpenSSL::SSL::OP_NO_TLSv1_2)
 
   def test_forbid_tls_v1_2_from_server
-    start_server_version(:TLSv1_2) { |server, port|
+    start_server_version(:TLSv1_2) { |port|
       ctx = OpenSSL::SSL::SSLContext.new
       ctx.options = OpenSSL::SSL::OP_ALL | OpenSSL::SSL::OP_NO_TLSv1_2
       assert_handshake_error { server_connect(port, ctx) }
@@ -887,14 +853,14 @@ def test_renegotiation_cb
     num_handshakes = 0
     renegotiation_cb = Proc.new { |ssl| num_handshakes += 1 }
     ctx_proc = Proc.new { |ctx| ctx.renegotiation_cb = renegotiation_cb }
-    start_server_version(:SSLv23, ctx_proc) { |server, port|
+    start_server_version(:SSLv23, ctx_proc) { |port|
       server_connect(port) { |ssl|
         assert_equal(1, num_handshakes)
       }
     }
   end
 
-if OpenSSL::OPENSSL_VERSION_NUMBER >= 0x10002000
+if openssl?(1, 0, 2) || libressl?
   def test_alpn_protocol_selection_ary
     advertised = ["http/1.1", "spdy/2"]
     ctx_proc = Proc.new { |ctx|
@@ -903,7 +869,7 @@ def test_alpn_protocol_selection_ary
       }
       ctx.alpn_protocols = advertised
     }
-    start_server_version(:SSLv23, ctx_proc) { |server, port|
+    start_server_version(:SSLv23, ctx_proc) { |port|
       ctx = OpenSSL::SSL::SSLContext.new
       ctx.alpn_protocols = advertised
       server_connect(port, ctx) { |ssl|
@@ -916,14 +882,13 @@ def test_alpn_protocol_selection_cancel
     sock1, sock2 = socketpair
 
     ctx1 = OpenSSL::SSL::SSLContext.new
-    ctx1.ciphers = "aNULL"
-    ctx1.security_level = 0
+    ctx1.cert = @svr_cert
+    ctx1.key = @svr_key
+    ctx1.tmp_dh_callback = proc { Fixtures.pkey_dh("dh1024") }
     ctx1.alpn_select_cb = -> (protocols) { nil }
     ssl1 = OpenSSL::SSL::SSLSocket.new(sock1, ctx1)
 
     ctx2 = OpenSSL::SSL::SSLContext.new
-    ctx2.ciphers = "aNULL"
-    ctx2.security_level = 0
     ctx2.alpn_protocols = ["http/1.1"]
     ssl2 = OpenSSL::SSL::SSLSocket.new(sock2, ctx2)
 
@@ -942,14 +907,15 @@ def test_alpn_protocol_selection_cancel
   end
 end
 
-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
+    pend "TLS 1.2 is not supported" unless tls12_supported?
+    pend "NPN is not supported" unless \
+      OpenSSL::SSL::SSLContext.method_defined?(:npn_select_cb)
+    pend "LibreSSL 2.6 has broken NPN functions" if libressl?(2, 6, 1)
+
     advertised = ["http/1.1", "spdy/2"]
-    ctx_proc = Proc.new { |ctx| ctx.npn_protocols = advertised }
-    start_server_version(:SSLv23, ctx_proc) { |server, port|
+    ctx_proc = proc { |ctx| ctx.npn_protocols = advertised }
+    start_server_version(:TLSv1_2, ctx_proc) { |port|
       selector = lambda { |which|
         ctx = OpenSSL::SSL::SSLContext.new
         ctx.npn_select_cb = -> (protocols) { protocols.send(which) }
@@ -963,13 +929,18 @@ def test_npn_protocol_selection_ary
   end
 
   def test_npn_protocol_selection_enum
+    pend "TLS 1.2 is not supported" unless tls12_supported?
+    pend "NPN is not supported" unless \
+      OpenSSL::SSL::SSLContext.method_defined?(:npn_select_cb)
+    pend "LibreSSL 2.6 has broken NPN functions" if libressl?(2, 6, 1)
+
     advertised = Object.new
     def advertised.each
       yield "http/1.1"
       yield "spdy/2"
     end
     ctx_proc = Proc.new { |ctx| ctx.npn_protocols = advertised }
-    start_server_version(:SSLv23, ctx_proc) { |server, port|
+    start_server_version(:TLSv1_2, ctx_proc) { |port|
       selector = lambda { |selected, which|
         ctx = OpenSSL::SSL::SSLContext.new
         ctx.npn_select_cb = -> (protocols) { protocols.to_a.send(which) }
@@ -983,8 +954,13 @@ def advertised.each
   end
 
   def test_npn_protocol_selection_cancel
+    pend "TLS 1.2 is not supported" unless tls12_supported?
+    pend "NPN is not supported" unless \
+      OpenSSL::SSL::SSLContext.method_defined?(:npn_select_cb)
+    pend "LibreSSL 2.6 has broken NPN functions" if libressl?(2, 6, 1)
+
     ctx_proc = Proc.new { |ctx| ctx.npn_protocols = ["http/1.1"] }
-    start_server_version(:SSLv23, ctx_proc) { |server, port|
+    start_server_version(:TLSv1_2, ctx_proc) { |port|
       ctx = OpenSSL::SSL::SSLContext.new
       ctx.npn_select_cb = -> (protocols) { raise RuntimeError.new }
       assert_raise(RuntimeError) { server_connect(port, ctx) }
@@ -992,8 +968,13 @@ def test_npn_protocol_selection_cancel
   end
 
   def test_npn_advertised_protocol_too_long
+    pend "TLS 1.2 is not supported" unless tls12_supported?
+    pend "NPN is not supported" unless \
+      OpenSSL::SSL::SSLContext.method_defined?(:npn_select_cb)
+    pend "LibreSSL 2.6 has broken NPN functions" if libressl?(2, 6, 1)
+
     ctx_proc = Proc.new { |ctx| ctx.npn_protocols = ["a" * 256] }
-    start_server_version(:SSLv23, ctx_proc) { |server, port|
+    start_server_version(:TLSv1_2, ctx_proc) { |port|
       ctx = OpenSSL::SSL::SSLContext.new
       ctx.npn_select_cb = -> (protocols) { protocols.first }
       assert_handshake_error { server_connect(port, ctx) }
@@ -1001,32 +982,24 @@ def test_npn_advertised_protocol_too_long
   end
 
   def test_npn_selected_protocol_too_long
+    pend "TLS 1.2 is not supported" unless tls12_supported?
+    pend "NPN is not supported" unless \
+      OpenSSL::SSL::SSLContext.method_defined?(:npn_select_cb)
+    pend "LibreSSL 2.6 has broken NPN functions" if libressl?(2, 6, 1)
+
     ctx_proc = Proc.new { |ctx| ctx.npn_protocols = ["http/1.1"] }
-    start_server_version(:SSLv23, ctx_proc) { |server, port|
+    start_server_version(:TLSv1_2, ctx_proc) { |port|
       ctx = OpenSSL::SSL::SSLContext.new
       ctx.npn_select_cb = -> (protocols) { "a" * 256 }
       assert_handshake_error { server_connect(port, ctx) }
     }
   end
 
-end
-
-  def test_invalid_shutdown_by_gc
-    assert_nothing_raised {
-      start_server { |server, port|
-        10.times {
-          sock = TCPSocket.new("127.0.0.1", port)
-          ssl = OpenSSL::SSL::SSLSocket.new(sock)
-          GC.start
-          ssl.connect
-          sock.close
-        }
-      }
-    }
-  end
-
   def test_close_after_socket_close
-    start_server { |server, port|
+    server_proc = proc { |ctx, ssl|
+      # Do nothing
+    }
+    start_server(server_proc: server_proc) { |port|
       sock = TCPSocket.new("127.0.0.1", port)
       ssl = OpenSSL::SSL::SSLSocket.new(sock)
       ssl.sync_close = true
@@ -1047,84 +1020,90 @@ def test_sync_close_without_connect
     }
   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"
-    ctx.tmp_dh_callback = proc { OpenSSL::TestUtils::TEST_KEY_DH1024 }
-    ctx.security_level = 0
-
-    sock1, sock2 = socketpair
-    ssl1 = OpenSSL::SSL::SSLSocket.new(sock1, ctx)
-    ssl2 = OpenSSL::SSL::SSLSocket.new(sock2, ctx)
+  def test_get_ephemeral_key
+    # OpenSSL >= 1.0.2
+    unless OpenSSL::SSL::SSLSocket.method_defined?(:tmp_key)
+      pend "SSL_get_server_tmp_key() is not supported"
+    end
 
-    t = Thread.new { ssl1.connect }
-    ssl2.accept
+    if tls12_supported?
+      # kRSA
+      ctx_proc1 = proc { |ctx|
+        ctx.ssl_version = :TLSv1_2
+        ctx.ciphers = "kRSA"
+      }
+      start_server(ctx_proc: ctx_proc1) do |port|
+        ctx = OpenSSL::SSL::SSLContext.new
+        ctx.ssl_version = :TLSv1_2
+        ctx.ciphers = "kRSA"
+        server_connect(port, ctx) { |ssl| assert_nil ssl.tmp_key }
+      end
+    end
 
-    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
+    if defined?(OpenSSL::PKey::DH) && tls12_supported?
+      # DHE
+      # TODO: How to test this with TLS 1.3?
+      ctx_proc2 = proc { |ctx|
+        ctx.ssl_version = :TLSv1_2
+        ctx.ciphers = "EDH"
+      }
+      start_server(ctx_proc: ctx_proc2) do |port|
+        ctx = OpenSSL::SSL::SSLContext.new
+        ctx.ssl_version = :TLSv1_2
+        ctx.ciphers = "EDH"
+        server_connect(port, ctx) { |ssl|
+          assert_instance_of OpenSSL::PKey::DH, ssl.tmp_key
+        }
+      end
+    end
 
-  def test_get_ephemeral_key
-    return unless OpenSSL::SSL::SSLSocket.method_defined?(:tmp_key)
-    pkey = OpenSSL::PKey
-    ciphers = {
-        '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' }
-    start_server(ctx_proc: conf_proc) do |server, port|
-      ciphers.each do |cipher, ephemeral|
+    if defined?(OpenSSL::PKey::EC)
+      # ECDHE
+      ctx_proc3 = proc { |ctx|
+        ctx.ciphers = "DEFAULT:!kRSA:!kEDH"
+        ctx.ecdh_curves = "P-256"
+      }
+      start_server(ctx_proc: ctx_proc3) do |port|
         ctx = OpenSSL::SSL::SSLContext.new
-        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)
-          else
-            assert_nil(ssl.tmp_key)
-          end
-        end
+        ctx.ciphers = "DEFAULT:!kRSA:!kEDH"
+        server_connect(port, ctx) { |ssl|
+          assert_instance_of OpenSSL::PKey::EC, ssl.tmp_key
+        }
       end
     end
   end
 
   def test_dh_callback
+    pend "TLS 1.2 is not supported" unless tls12_supported?
+
     called = false
     ctx_proc = -> ctx {
+      ctx.ssl_version = :TLSv1_2
       ctx.ciphers = "DH:!NULL"
       ctx.tmp_dh_callback = ->(*args) {
         called = true
-        OpenSSL::TestUtils::TEST_KEY_DH1024
+        Fixtures.pkey_dh("dh1024")
       }
     }
-    start_server(ctx_proc: ctx_proc) do |server, port|
+    start_server(ctx_proc: ctx_proc) do |port|
       server_connect(port) { |ssl|
         assert called, "dh callback should be called"
         if ssl.respond_to?(:tmp_key)
-          assert_equal OpenSSL::TestUtils::TEST_KEY_DH1024.to_der, ssl.tmp_key.to_der
+          assert_equal Fixtures.pkey_dh("dh1024").to_der, ssl.tmp_key.to_der
         end
       }
     end
   end
 
   def test_connect_works_when_setting_dh_callback_to_nil
+    pend "TLS 1.2 is not supported" unless tls12_supported?
+
     ctx_proc = -> ctx {
+      ctx.ssl_version = :TLSv1_2
       ctx.ciphers = "DH:!NULL" # use DH
       ctx.tmp_dh_callback = nil
     }
-    start_server(ctx_proc: ctx_proc) do |server, port|
+    start_server(ctx_proc: ctx_proc) do |port|
       EnvUtil.suppress_warning { # uses default callback
         assert_nothing_raised {
           server_connect(port) { }
@@ -1133,73 +1112,55 @@ def test_connect_works_when_setting_dh_callback_to_nil
     end
   end
 
-  def test_ecdh_callback
-    return unless OpenSSL::SSL::SSLContext.instance_methods.include?(:tmp_ecdh_callback)
+  def test_tmp_ecdh_callback
+    pend "EC is disabled" unless defined?(OpenSSL::PKey::EC)
+    pend "tmp_ecdh_callback is not supported" unless \
+      OpenSSL::SSL::SSLContext.method_defined?(:tmp_ecdh_callback)
+    pend "LibreSSL 2.6 has broken SSL_CTX_set_tmp_ecdh_callback()" \
+      if libressl?(2, 6, 1)
+
     EnvUtil.suppress_warning do # tmp_ecdh_callback is deprecated (2016-05)
-      begin
-        called = false
-        ctx2 = OpenSSL::SSL::SSLContext.new
-        ctx2.ciphers = "ECDH"
-        # OpenSSL 1.1.0 doesn't have tmp_ecdh_callback so this shouldn't be required
-        ctx2.security_level = 0
-        ctx2.tmp_ecdh_callback = ->(*args) {
+      called = false
+      ctx_proc = -> ctx {
+        ctx.ciphers = "DEFAULT:!kRSA:!kEDH"
+        ctx.tmp_ecdh_callback = -> (*args) {
           called = true
           OpenSSL::PKey::EC.new "prime256v1"
         }
-
-        sock1, sock2 = socketpair
-
-        s2 = OpenSSL::SSL::SSLSocket.new(sock2, ctx2)
-        ctx1 = OpenSSL::SSL::SSLContext.new
-        ctx1.ciphers = "ECDH"
-        ctx1.security_level = 0
-
-        s1 = OpenSSL::SSL::SSLSocket.new(sock1, ctx1)
-        th = Thread.new do
-          s1.connect
-        end
-
-        s2.accept
-        assert called, 'ecdh callback should be called'
-      rescue OpenSSL::SSL::SSLError => e
-        if e.message =~ /no cipher match/
-          pend "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
+      }
+      start_server(ctx_proc: ctx_proc) do |port|
+        server_connect(port) { |s|
+          assert called, "tmp_ecdh_callback should be called"
+        }
       end
     end
   end
 
   def test_ecdh_curves
+    pend "EC is disabled" unless defined?(OpenSSL::PKey::EC)
+
     ctx_proc = -> ctx {
-      begin
-        ctx.ciphers = "ECDH:!NULL"
-      rescue OpenSSL::SSL::SSLError
-        pend "ECDH is not enabled in this OpenSSL" if $!.message =~ /no cipher match/
-        raise
-      end
+      # Enable both ECDHE (~ TLS 1.2) cipher suites and TLS 1.3
+      ctx.ciphers = "DEFAULT:!kRSA:!kEDH"
       ctx.ecdh_curves = "P-384:P-521"
     }
-    start_server(ctx_proc: ctx_proc, ignore_listener_error: true) do |server, port|
+    start_server(ctx_proc: ctx_proc, ignore_listener_error: true) do |port|
       ctx = OpenSSL::SSL::SSLContext.new
       ctx.ecdh_curves = "P-256:P-384" # disable P-521 for OpenSSL >= 1.0.2
 
       server_connect(port, ctx) { |ssl|
-        assert ssl.cipher[0].start_with?("ECDH"), "ECDH should be used"
-        if ssl.respond_to?(:tmp_key)
+        cs = ssl.cipher[0]
+        if /\ATLS/ =~ cs # Is TLS 1.3 is used?
           assert_equal "secp384r1", ssl.tmp_key.group.curve_name
+        else
+          assert_match (/\AECDH/), cs
+          if ssl.respond_to?(:tmp_key)
+            assert_equal "secp384r1", ssl.tmp_key.group.curve_name
+          end
         end
       }
 
-      if OpenSSL::OPENSSL_VERSION_NUMBER >= 0x10002000 &&
-          !OpenSSL::OPENSSL_VERSION.include?("LibreSSL")
+      if openssl?(1, 0, 2) || libressl?(2, 5, 1)
         ctx = OpenSSL::SSL::SSLContext.new
         ctx.ecdh_curves = "P-256"
 
@@ -1226,10 +1187,10 @@ def test_security_level
       return
     end
     assert_equal(1, ctx.security_level)
-    # assert_raise(OpenSSL::SSL::SSLError) { ctx.key = OpenSSL::TestUtils::TEST_KEY_DSA512 }
-    # ctx.key = OpenSSL::TestUtils::TEST_KEY_RSA1024
+    # assert_raise(OpenSSL::SSL::SSLError) { ctx.key = Fixtures.pkey("dsa512") }
+    # ctx.key = Fixtures.pkey("rsa1024")
     # ctx.security_level = 2
-    # assert_raise(OpenSSL::SSL::SSLError) { ctx.key = OpenSSL::TestUtils::TEST_KEY_RSA1024 }
+    # assert_raise(OpenSSL::SSL::SSLError) { ctx.key = Fixtures.pkey("rsa1024") }
     pend "FIXME: SSLContext#key= currently does not raise because SSL_CTX_use_certificate() is delayed"
   end
 
@@ -1248,7 +1209,7 @@ def test_dup
 
   def test_freeze_calls_setup
     bug = "[ruby/openssl#85]"
-    start_server(ignore_listener_error: true) { |server, port|
+    start_server(ignore_listener_error: true) { |port|
       ctx = OpenSSL::SSL::SSLContext.new
       ctx.verify_mode = OpenSSL::SSL::VERIFY_PEER
       ctx.freeze
@@ -1274,7 +1235,7 @@ def start_server_version(version, ctx_proc = nil,
     )
   end
 
-  def server_connect(port, ctx=nil)
+  def server_connect(port, ctx = nil)
     sock = TCPSocket.new("127.0.0.1", port)
     ssl = ctx ? OpenSSL::SSL::SSLSocket.new(sock, ctx) : OpenSSL::SSL::SSLSocket.new(sock)
     ssl.sync_close = true
diff --git a/test/openssl/test_ssl_session.rb b/test/openssl/test_ssl_session.rb
index 7a99dca5edc6..9d0e5a2db170 100644
--- a/test/openssl/test_ssl_session.rb
+++ b/test/openssl/test_ssl_session.rb
@@ -4,54 +4,12 @@
 if defined?(OpenSSL::TestUtils)
 
 class OpenSSL::TestSSLSession < OpenSSL::SSLTestCase
-  def test_session_equals
-    session = OpenSSL::SSL::Session.new <<-SESSION
------BEGIN SSL SESSION PARAMETERS-----
-MIIDFgIBAQICAwEEAgA5BCCY3pW6iTkPoD5SENuztz/gZjhvey6XnHbsxd22k0Ol
-dgQw8uaN3hCRnlhoIKPWInCFzrp/tQsDRFs9jDjc9pwpy/oKHmJdQQMQA1g8FYnO
-gpdVoQYCBE52ikKiBAICASyjggKOMIICijCCAXKgAwIBAgIBAjANBgkqhkiG9w0B
-AQUFADA9MRMwEQYKCZImiZPyLGQBGRYDb3JnMRkwFwYKCZImiZPyLGQBGRYJcnVi
-eS1sYW5nMQswCQYDVQQDDAJDQTAeFw0xMTA5MTkwMDE4MTBaFw0xMTA5MTkwMDQ4
-MTBaMEQxEzARBgoJkiaJk/IsZAEZFgNvcmcxGTAXBgoJkiaJk/IsZAEZFglydWJ5
-LWxhbmcxEjAQBgNVBAMMCWxvY2FsaG9zdDCBnzANBgkqhkiG9w0BAQEFAAOBjQAw
-gYkCgYEAy8LEsNRApz7U/j5DoB4XBgO9Z8Atv5y/OVQRp0ag8Tqo1YewsWijxEWB
-7JOATwpBN267U4T1nPZIxxEEO7n/WNa2ws9JWsjah8ssEBFSxZqdXKSLf0N4Hi7/
-GQ/aYoaMCiQ8jA4jegK2FJmXM71uPe+jFN/peeBOpRfyXxRFOYcCAwEAAaMSMBAw
-DgYDVR0PAQH/BAQDAgWgMA0GCSqGSIb3DQEBBQUAA4IBAQARC7GP7InX1t7VEXz2
-I8RI57S0/HSJL4fDIYP3zFpitHX1PZeo+7XuzMilvPjjBo/ky9Jzo8TYiY+N+JEz
-mY/A/zPA4ZsJ7KYj6/FEdIc/vRlS0CvsbClbNjw1jl/PoB2FLr2b3uuBcZEsyZeP
-yq154ijq37Ajf8K5Mi5FgshoP41BPtRPj+VVf61rv1IcEnNWdDCS6DR4XsaNC+zt
-G6AqCqkytIXWRuDw6n6vYLF3A/tn2sldLo7/scY0PMDNbo63O/LTxkDHmPhSkD68
-8m9SsMeTR+RCiDEZWFPVcAH/8mDfi+5k8uN3qS+gOU/PPrmHGgl5ykiSFgqs4v61
-tddwpBAEDjcwMzA5NTYzMTU1MzAwpQMCARM=
------END SSL SESSION PARAMETERS-----
-    SESSION
-
-    start_server(ignore_listener_error: true) { |_, port|
-      ctx = OpenSSL::SSL::SSLContext.new
-      ctx.session_cache_mode = OpenSSL::SSL::SSLContext::SESSION_CACHE_CLIENT
-      ctx.session_id_context = self.object_id.to_s
-
-      sock = TCPSocket.new '127.0.0.1', port
-      begin
-        ssl = OpenSSL::SSL::SSLSocket.new sock, ctx
-        ssl.session = session
-
-        assert_equal session, ssl.session
-      ensure
-        sock.close
-      end
-    }
-  end
-
   def test_session
-    Timeout.timeout(5) do
-      start_server do |server, port|
-        sock = TCPSocket.new("127.0.0.1", port)
-        ctx = OpenSSL::SSL::SSLContext.new
-        ssl = OpenSSL::SSL::SSLSocket.new(sock, ctx)
-        ssl.sync_close = true
-        ssl.connect
+    pend "TLS 1.2 is not supported" unless tls12_supported?
+
+    ctx_proc = proc { |ctx| ctx.ssl_version = :TLSv1_2 }
+    start_server(ctx_proc: ctx_proc) do |port|
+      server_connect_with_session(port, nil, nil) { |ssl|
         session = ssl.session
         assert(session == OpenSSL::SSL::Session.new(session.to_pem))
         assert(session == OpenSSL::SSL::Session.new(ssl))
@@ -68,8 +26,7 @@ def test_session
         pem.gsub!(/-----(BEGIN|END) SSL SESSION PARAMETERS-----/, '').gsub!(/[\r\n]+/m, '')
         assert_equal(session.to_der, pem.unpack('m*')[0])
         assert_not_nil(session.to_text)
-        ssl.close
-      end
+      }
     end
   end
 
@@ -150,222 +107,245 @@ def test_session_timeout
 
   def test_session_exts_read
     assert(OpenSSL::SSL::Session.new(DUMMY_SESSION))
-  end if OpenSSL::OPENSSL_VERSION_NUMBER >= 0x009080bf
-
-  def test_client_session
-    last_session = nil
-    start_server do |server, port|
-      2.times do
-        sock = TCPSocket.new("127.0.0.1", port)
-        ctx = OpenSSL::SSL::SSLContext.new
-        ssl = OpenSSL::SSL::SSLSocket.new(sock, ctx)
-        ssl.sync_close = true
-        ssl.session = last_session if last_session
-        ssl.connect
+  end
 
-        session = ssl.session
-        if last_session
-          assert(ssl.session_reused?)
-          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.
-          assert_equal(session.to_text, last_session.to_text)
-        else
-          assert(!ssl.session_reused?)
-        end
-        last_session = session
+  def test_resumption
+    non_resumable = nil
+    start_server { |port|
+      server_connect_with_session(port, nil, nil) { |ssl|
+        non_resumable = ssl.session
+      }
+    }
 
-        str = "x" * 100 + "\n"
-        ssl.puts(str)
-        assert_equal(str, ssl.gets)
+    ctx_proc = proc { |ctx|
+      ctx.options &= ~OpenSSL::SSL::OP_NO_TICKET
+      # Disable server-side session cache which is enabled by default
+      ctx.session_cache_mode = OpenSSL::SSL::SSLContext::SESSION_CACHE_OFF
+    }
+    start_server(ctx_proc: ctx_proc) do |port|
+      sess1 = server_connect_with_session(port, nil, nil) { |ssl|
+        ssl.puts("abc"); assert_equal "abc\n", ssl.gets
+        assert_equal false, ssl.session_reused?
+        ssl.session
+      }
 
-        ssl.close
-      end
+      server_connect_with_session(port, nil, non_resumable) { |ssl|
+        ssl.puts("abc"); assert_equal "abc\n", ssl.gets
+        assert_equal false, ssl.session_reused?
+      }
+
+      server_connect_with_session(port, nil, sess1) { |ssl|
+        ssl.puts("abc"); assert_equal "abc\n", ssl.gets
+        assert_equal true, ssl.session_reused?
+      }
     end
   end
 
-  def test_server_session
-    connections = 0
-    saved_session = nil
+  def test_server_session_cache
+    pend "TLS 1.2 is not supported" unless tls12_supported?
 
-    ctx_proc = Proc.new do |ctx, ssl|
-# add test for session callbacks here
+    ctx_proc = Proc.new do |ctx|
+      ctx.ssl_version = :TLSv1_2
+      ctx.options |= OpenSSL::SSL::OP_NO_TICKET
     end
 
+    connections = nil
+    saved_session = nil
     server_proc = Proc.new do |ctx, ssl|
-      session = ssl.session
       stats = ctx.session_cache_stats
 
       case connections
       when 0
-        assert_equal(stats[:cache_num], 1)
-        assert_equal(stats[:cache_hits], 0)
-        assert_equal(stats[:cache_misses], 0)
-        assert(!ssl.session_reused?)
+        assert_equal false, ssl.session_reused?
+        assert_equal 1, stats[:cache_num]
+        assert_equal 0, stats[:cache_hits]
+        assert_equal 0, stats[:cache_misses]
       when 1
-        assert_equal(stats[:cache_num], 1)
-        assert_equal(stats[:cache_hits], 1)
-        assert_equal(stats[:cache_misses], 0)
-        assert(ssl.session_reused?)
-        ctx.session_remove(session)
-        saved_session = session.to_der
+        assert_equal true, ssl.session_reused?
+        assert_equal 1, stats[:cache_num]
+        assert_equal 1, stats[:cache_hits]
+        assert_equal 0, stats[:cache_misses]
+
+        saved_session = ssl.session
+        assert_equal true, ctx.session_remove(ssl.session)
       when 2
-        assert_equal(stats[:cache_num], 1)
-        assert_equal(stats[:cache_hits], 1)
-        assert_equal(stats[:cache_misses], 1)
-        assert(!ssl.session_reused?)
-        ctx.session_add(OpenSSL::SSL::Session.new(saved_session))
+        assert_equal false, ssl.session_reused?
+        assert_equal 1, stats[:cache_num]
+        assert_equal 1, stats[:cache_hits]
+        assert_equal 1, stats[:cache_misses]
+
+        assert_equal true, ctx.session_add(saved_session.dup)
       when 3
-        assert_equal(stats[:cache_num], 2)
-        assert_equal(stats[:cache_hits], 2)
-        assert_equal(stats[:cache_misses], 1)
-        assert(ssl.session_reused?)
+        assert_equal true, ssl.session_reused?
+        assert_equal 2, stats[:cache_num]
+        assert_equal 2, stats[:cache_hits]
+        assert_equal 1, stats[:cache_misses]
+
         ctx.flush_sessions(Time.now + 10000)
       when 4
-        assert_equal(stats[:cache_num], 1)
-        assert_equal(stats[:cache_hits], 2)
-        assert_equal(stats[:cache_misses], 2)
-        assert(!ssl.session_reused?)
-        ctx.session_add(OpenSSL::SSL::Session.new(saved_session))
+        assert_equal false, ssl.session_reused?
+        assert_equal 1, stats[:cache_num]
+        assert_equal 2, stats[:cache_hits]
+        assert_equal 2, stats[:cache_misses]
+
+        assert_equal true, ctx.session_add(saved_session.dup)
       end
-      connections += 1
 
       readwrite_loop(ctx, ssl)
     end
 
-    first_session = nil
-    start_server(ctx_proc: ctx_proc, server_proc: server_proc) do |server, port|
+    start_server(ctx_proc: ctx_proc, server_proc: server_proc) do |port|
+      first_session = nil
       10.times do |i|
-        sock = TCPSocket.new("127.0.0.1", port)
-        ctx = OpenSSL::SSL::SSLContext.new
-        # 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
-        ssl.connect
-
-        session = ssl.session
-        if first_session
-          case i
-          when 1; assert(ssl.session_reused?)
-          when 2; assert(!ssl.session_reused?)
-          when 3; assert(ssl.session_reused?)
-          when 4; assert(!ssl.session_reused?)
-          when 5..10; assert(ssl.session_reused?)
+        connections = i
+        server_connect_with_session(port, nil, first_session) { |ssl|
+          ssl.puts("abc"); assert_equal "abc\n", ssl.gets
+          first_session ||= ssl.session
+
+          case connections
+          when 0;
+          when 1; assert_equal true, ssl.session_reused?
+          when 2; assert_equal false, ssl.session_reused?
+          when 3; assert_equal true, ssl.session_reused?
+          when 4; assert_equal false, ssl.session_reused?
+          when 5..9; assert_equal true, ssl.session_reused?
           end
-        end
-        first_session ||= session
-
-        str = "x" * 100 + "\n"
-        ssl.puts(str)
-        assert_equal(str, ssl.gets)
-
-        ssl.close
+        }
       end
     end
   end
 
   def test_ctx_client_session_cb
-    called = {}
-    ctx = OpenSSL::SSL::SSLContext.new
-    ctx.session_cache_mode = OpenSSL::SSL::SSLContext::SESSION_CACHE_CLIENT
-
-    ctx.session_new_cb = lambda { |ary|
-      sock, sess = ary
-      called[:new] = [sock, sess]
-    }
+    pend "TLS 1.2 is not supported" unless tls12_supported?
 
-    ctx.session_remove_cb = lambda { |ary|
-      ctx, sess = ary
-      called[:remove] = [ctx, sess]
-      # any resulting value is OK (ignored)
-    }
+    ctx_proc = proc { |ctx| ctx.ssl_version = :TLSv1_2 }
+    start_server(ctx_proc: ctx_proc) do |port|
+      called = {}
+      ctx = OpenSSL::SSL::SSLContext.new
+      ctx.session_cache_mode = OpenSSL::SSL::SSLContext::SESSION_CACHE_CLIENT
+      ctx.session_new_cb = lambda { |ary|
+        sock, sess = ary
+        called[:new] = [sock, sess]
+      }
+      ctx.session_remove_cb = lambda { |ary|
+        ctx, sess = ary
+        called[:remove] = [ctx, sess]
+        # any resulting value is OK (ignored)
+      }
 
-    start_server do |server, port|
-      sock = TCPSocket.new("127.0.0.1", port)
-      begin
-        ssl = OpenSSL::SSL::SSLSocket.new(sock, ctx)
-        ssl.sync_close = true
-        ssl.connect
+      server_connect_with_session(port, ctx, nil) { |ssl|
         assert_equal(1, ctx.session_cache_stats[:cache_num])
         assert_equal(1, ctx.session_cache_stats[:connect_good])
         assert_equal([ssl, ssl.session], called[:new])
         assert(ctx.session_remove(ssl.session))
         assert(!ctx.session_remove(ssl.session))
         assert_equal([ctx, ssl.session], called[:remove])
-        ssl.close
-      ensure
-        sock.close if !sock.closed?
-      end
+      }
     end
   end
 
   def test_ctx_server_session_cb
-    called = {}
+    pend "TLS 1.2 is not supported" unless tls12_supported?
 
-    ctx_proc = Proc.new { |ctx, ssl|
-      ctx.session_cache_mode = OpenSSL::SSL::SSLContext::SESSION_CACHE_SERVER
-      ctx.options = OpenSSL::SSL::OP_NO_TICKET
-      last_server_session = nil
+    connections = nil
+    called = {}
+    sctx = nil
+    ctx_proc = Proc.new { |ctx|
+      sctx = ctx
+      ctx.ssl_version = :TLSv1_2
+      ctx.options |= OpenSSL::SSL::OP_NO_TICKET
 
       # get_cb is called whenever a client proposed to resume a session but
       # the session could not be found in the internal session cache.
+      last_server_session = nil
       ctx.session_get_cb = lambda { |ary|
-        sess, data = ary
-        if last_server_session
-          called[:get2] = [sess, data]
-          last_server_session
+        _sess, data = ary
+        called[:get] = data
+
+        if connections == 2
+          last_server_session.dup
         else
-          called[:get1] = [sess, data]
-          last_server_session = sess
           nil
         end
       }
 
       ctx.session_new_cb = lambda { |ary|
-        sock, sess = ary
-        called[:new] = [sock, sess]
-        # SSL server doesn't cache sessions so get_cb is called next time.
-        ctx.session_remove(sess)
+        _sock, sess = ary
+        called[:new] = sess
+        last_server_session = sess
       }
 
       ctx.session_remove_cb = lambda { |ary|
-        ctx, sess = ary
-        called[:remove] = [ctx, sess]
+        _ctx, sess = ary
+        called[:remove] = sess
       }
     }
-
-    server_proc = Proc.new { |c, ssl|
-      ssl.session
-      c.session_cache_stats
-      readwrite_loop(c, ssl)
-    }
-    start_server(ctx_proc: ctx_proc, server_proc: server_proc) do |server, port|
-      last_client_session = nil
-      3.times do
-        sock = TCPSocket.new("127.0.0.1", port)
-        begin
-          ssl = OpenSSL::SSL::SSLSocket.new(sock, OpenSSL::SSL::SSLContext.new())
-          ssl.sync_close = true
-          ssl.session = last_client_session if last_client_session
-          ssl.connect
-          last_client_session = ssl.session
-          ssl.close
-          Timeout.timeout(5) do
-            Thread.pass until called.key?(:new)
-            assert(called.delete(:new))
-            Thread.pass until called.key?(:remove)
-            assert(called.delete(:remove))
-          end
-        ensure
-          sock.close if !sock.closed?
+    start_server(ctx_proc: ctx_proc) do |port|
+      connections = 0
+      sess0 = server_connect_with_session(port, nil, nil) { |ssl|
+        ssl.puts("abc"); assert_equal "abc\n", ssl.gets
+        assert_equal false, ssl.session_reused?
+        ssl.session
+      }
+      assert_nil called[:get]
+      assert_not_nil called[:new]
+      assert_equal sess0.id, called[:new].id
+      assert_nil called[:remove]
+      called.clear
+
+      # Internal cache hit
+      connections = 1
+      server_connect_with_session(port, nil, sess0.dup) { |ssl|
+        ssl.puts("abc"); assert_equal "abc\n", ssl.gets
+        assert_equal true, ssl.session_reused?
+        ssl.session
+      }
+      assert_nil called[:get]
+      assert_nil called[:new]
+      assert_nil called[:remove]
+      called.clear
+
+      sctx.flush_sessions(Time.now + 10000)
+      assert_not_nil called[:remove]
+      assert_equal sess0.id, called[:remove].id
+      called.clear
+
+      # External cache hit
+      connections = 2
+      sess2 = server_connect_with_session(port, nil, sess0.dup) { |ssl|
+        ssl.puts("abc"); assert_equal "abc\n", ssl.gets
+        if !ssl.session_reused? && openssl?(1, 1, 0) && !openssl?(1, 1, 0, 7)
+          # OpenSSL >= 1.1.0, < 1.1.0g
+          pend "External session cache is not working; " \
+            "see https://github.com/openssl/openssl/pull/4014"
         end
-      end
+        assert_equal true, ssl.session_reused?
+        ssl.session
+      }
+      assert_equal sess0.id, sess2.id
+      assert_equal sess0.id, called[:get]
+      assert_nil called[:new]
+      assert_nil called[:remove]
+      called.clear
+
+      sctx.flush_sessions(Time.now + 10000)
+      assert_not_nil called[:remove]
+      assert_equal sess0.id, called[:remove].id
+      called.clear
+
+      # Cache miss
+      connections = 3
+      sess3 = server_connect_with_session(port, nil, sess0.dup) { |ssl|
+        ssl.puts("abc"); assert_equal "abc\n", ssl.gets
+        assert_equal false, ssl.session_reused?
+        ssl.session
+      }
+      assert_not_equal sess0.id, sess3.id
+      assert_equal sess0.id, called[:get]
+      assert_not_nil called[:new]
+      assert_equal sess3.id, called[:new].id
+      assert_nil called[:remove]
     end
-    assert(called[:get1])
-    assert(called[:get2])
   end
 
   def test_dup
@@ -373,6 +353,21 @@ def test_dup
     sess_dup = sess_orig.dup
     assert_equal(sess_orig.to_der, sess_dup.to_der)
   end
+
+  private
+
+  def server_connect_with_session(port, ctx = nil, sess = nil)
+    sock = TCPSocket.new("127.0.0.1", port)
+    ctx ||= OpenSSL::SSL::SSLContext.new
+    ssl = OpenSSL::SSL::SSLSocket.new(sock, ctx)
+    ssl.session = sess if sess
+    ssl.sync_close = true
+    ssl.connect
+    yield ssl if block_given?
+  ensure
+    ssl&.close
+    sock&.close
+  end
 end
 
 end
diff --git a/test/openssl/test_x509cert.rb b/test/openssl/test_x509cert.rb
index 5b2e712d2a33..03650402fd21 100644
--- a/test/openssl/test_x509cert.rb
+++ b/test/openssl/test_x509cert.rb
@@ -6,18 +6,14 @@
 class OpenSSL::TestX509Certificate < OpenSSL::TestCase
   def setup
     super
-    @rsa1024 = OpenSSL::TestUtils::TEST_KEY_RSA1024
-    @rsa2048 = OpenSSL::TestUtils::TEST_KEY_RSA2048
-    @dsa256  = OpenSSL::TestUtils::TEST_KEY_DSA256
-    @dsa512  = OpenSSL::TestUtils::TEST_KEY_DSA512
+    @rsa1024 = Fixtures.pkey("rsa1024")
+    @rsa2048 = Fixtures.pkey("rsa2048")
+    @dsa256  = Fixtures.pkey("dsa256")
+    @dsa512  = Fixtures.pkey("dsa512")
     @ca = OpenSSL::X509::Name.parse("/DC=org/DC=ruby-lang/CN=CA")
     @ee1 = OpenSSL::X509::Name.parse("/DC=org/DC=ruby-lang/CN=EE1")
   end
 
-  def issue_cert(*args)
-    OpenSSL::TestUtils.issue_cert(*args)
-  end
-
   def test_serial
     [1, 2**32, 2**100].each{|s|
       cert = issue_cert(@ca, @rsa2048, s, [], nil, nil)
diff --git a/test/openssl/test_x509crl.rb b/test/openssl/test_x509crl.rb
index 44dfffc952cd..7d55e3c1cf81 100644
--- a/test/openssl/test_x509crl.rb
+++ b/test/openssl/test_x509crl.rb
@@ -6,23 +6,15 @@
 class OpenSSL::TestX509CRL < OpenSSL::TestCase
   def setup
     super
-    @rsa1024 = OpenSSL::TestUtils::TEST_KEY_RSA1024
-    @rsa2048 = OpenSSL::TestUtils::TEST_KEY_RSA2048
-    @dsa256  = OpenSSL::TestUtils::TEST_KEY_DSA256
-    @dsa512  = OpenSSL::TestUtils::TEST_KEY_DSA512
+    @rsa1024 = Fixtures.pkey("rsa1024")
+    @rsa2048 = Fixtures.pkey("rsa2048")
+    @dsa256  = Fixtures.pkey("dsa256")
+    @dsa512  = Fixtures.pkey("dsa512")
     @ca = OpenSSL::X509::Name.parse("/DC=org/DC=ruby-lang/CN=CA")
     @ee1 = OpenSSL::X509::Name.parse("/DC=org/DC=ruby-lang/CN=EE1")
     @ee2 = OpenSSL::X509::Name.parse("/DC=org/DC=ruby-lang/CN=EE2")
   end
 
-  def issue_crl(*args)
-    OpenSSL::TestUtils.issue_crl(*args)
-  end
-
-  def issue_cert(*args)
-    OpenSSL::TestUtils.issue_cert(*args)
-  end
-
   def test_basic
     now = Time.at(Time.now.to_i)
 
diff --git a/test/openssl/test_x509name.rb b/test/openssl/test_x509name.rb
index 60e8ddb8acfc..c1dacf4fa110 100644
--- a/test/openssl/test_x509name.rb
+++ b/test/openssl/test_x509name.rb
@@ -306,7 +306,6 @@ def test_add_entry
   end
 
   def test_add_entry_street
-    return if OpenSSL::OPENSSL_VERSION_NUMBER < 0x009080df # 0.9.8m
     # openssl/crypto/objects/obj_mac.h 1.83
     dn = [
       ["DC", "org"],
diff --git a/test/openssl/test_x509req.rb b/test/openssl/test_x509req.rb
index 585dda1bc6ac..fcc3e2f10a19 100644
--- a/test/openssl/test_x509req.rb
+++ b/test/openssl/test_x509req.rb
@@ -6,10 +6,10 @@
 class OpenSSL::TestX509Request < OpenSSL::TestCase
   def setup
     super
-    @rsa1024 = OpenSSL::TestUtils::TEST_KEY_RSA1024
-    @rsa2048 = OpenSSL::TestUtils::TEST_KEY_RSA2048
-    @dsa256  = OpenSSL::TestUtils::TEST_KEY_DSA256
-    @dsa512  = OpenSSL::TestUtils::TEST_KEY_DSA512
+    @rsa1024 = Fixtures.pkey("rsa1024")
+    @rsa2048 = Fixtures.pkey("rsa2048")
+    @dsa256  = Fixtures.pkey("dsa256")
+    @dsa512  = Fixtures.pkey("dsa512")
     @dn = OpenSSL::X509::Name.parse("/DC=org/DC=ruby-lang/CN=GOTOU Yuuzou")
   end
 
diff --git a/test/openssl/test_x509store.rb b/test/openssl/test_x509store.rb
index c45233aaecbb..b40534c6db4e 100644
--- a/test/openssl/test_x509store.rb
+++ b/test/openssl/test_x509store.rb
@@ -6,10 +6,10 @@
 class OpenSSL::TestX509Store < OpenSSL::TestCase
   def setup
     super
-    @rsa1024 = OpenSSL::TestUtils::TEST_KEY_RSA1024
-    @rsa2048 = OpenSSL::TestUtils::TEST_KEY_RSA2048
-    @dsa256  = OpenSSL::TestUtils::TEST_KEY_DSA256
-    @dsa512  = OpenSSL::TestUtils::TEST_KEY_DSA512
+    @rsa1024 = Fixtures.pkey("rsa1024")
+    @rsa2048 = Fixtures.pkey("rsa2048")
+    @dsa256  = Fixtures.pkey("dsa256")
+    @dsa512  = Fixtures.pkey("dsa512")
     @ca1 = OpenSSL::X509::Name.parse("/DC=org/DC=ruby-lang/CN=CA1")
     @ca2 = OpenSSL::X509::Name.parse("/DC=org/DC=ruby-lang/CN=CA2")
     @ee1 = OpenSSL::X509::Name.parse("/DC=org/DC=ruby-lang/CN=EE1")
@@ -26,14 +26,6 @@ def test_nosegv_on_cleanup
     ctx.verify
   end
 
-  def issue_cert(*args)
-    OpenSSL::TestUtils.issue_cert(*args)
-  end
-
-  def issue_crl(*args)
-    OpenSSL::TestUtils.issue_crl(*args)
-  end
-
   def test_add_file
     ca_exts = [
       ["basicConstraints", "CA:TRUE", true],
@@ -217,7 +209,7 @@ def test_verify
   end
 
   def test_set_errors
-    return if OpenSSL::OPENSSL_VERSION_NUMBER >= 0x10100000
+    return if openssl?(1, 1, 0) || libressl?
     now = Time.now
     ca1_cert = issue_cert(@ca1, @rsa2048, 1, [], nil, nil)
     store = OpenSSL::X509::Store.new
@@ -233,17 +225,9 @@ def test_set_errors
     crl2 = issue_crl(revoke_info, 2, now+1800, now+3600, [],
                      ca1_cert, @rsa2048, OpenSSL::Digest::SHA1.new)
     store.add_crl(crl1)
-    if /0\.9\.8.*-rhel/ =~ OpenSSL::OPENSSL_VERSION
-      # RedHat is distributing a patched version of OpenSSL that allows
-      # multiple CRL for a key (multi-crl.patch)
-      assert_nothing_raised do
-        store.add_crl(crl2) # add CRL issued by same CA twice.
-      end
-    else
-      assert_raise(OpenSSL::X509::StoreError){
-        store.add_crl(crl2) # add CRL issued by same CA twice.
-      }
-    end
+    assert_raise(OpenSSL::X509::StoreError){
+      store.add_crl(crl2) # add CRL issued by same CA twice.
+    }
   end
 
   def test_dup
diff --git a/test/openssl/ut_eof.rb b/test/openssl/ut_eof.rb
index 6de41c4a70d6..a49ad513365d 100644
--- a/test/openssl/ut_eof.rb
+++ b/test/openssl/ut_eof.rb
@@ -1,6 +1,8 @@
 # frozen_string_literal: false
 require 'test/unit'
 
+if defined?(OpenSSL::TestUtils)
+
 module OpenSSL::TestEOF
   def test_eof_0
     open_file("") {|f|
@@ -127,3 +129,5 @@ def test_eof_1_seek
     end
   end
 end
+
+end
diff --git a/test/openssl/utils.rb b/test/openssl/utils.rb
index bbc9c7efc2e9..4331d8bd8d95 100644
--- a/test/openssl/utils.rb
+++ b/test/openssl/utils.rb
@@ -9,120 +9,52 @@
 rescue LoadError
 end
 
+# Compile OpenSSL with crypto-mdebug and run this test suite with OSSL_MDEBUG=1
+# environment variable to enable memory leak check.
+if ENV["OSSL_MDEBUG"] == "1"
+  if OpenSSL.respond_to?(:print_mem_leaks)
+    OpenSSL.mem_check_start
+
+    END {
+      GC.start
+      case OpenSSL.print_mem_leaks
+      when nil
+        warn "mdebug: check what is printed"
+      when true
+        raise "mdebug: memory leaks detected"
+      end
+    }
+  else
+    warn "OSSL_MDEBUG=1 is specified but OpenSSL is not built with crypto-mdebug"
+  end
+end
+
 require "test/unit"
-require 'tempfile'
-require "rbconfig"
+require "tempfile"
 require "socket"
 require "envutil"
 
+if defined?(OpenSSL) && OpenSSL::OPENSSL_VERSION_NUMBER >= 0x10000000
+
 module OpenSSL::TestUtils
-  TEST_KEY_RSA1024 = OpenSSL::PKey::RSA.new <<-_end_of_pem_
------BEGIN RSA PRIVATE KEY-----
-MIICXgIBAAKBgQDLwsSw1ECnPtT+PkOgHhcGA71nwC2/nL85VBGnRqDxOqjVh7Cx
-aKPERYHsk4BPCkE3brtThPWc9kjHEQQ7uf9Y1rbCz0layNqHyywQEVLFmp1cpIt/
-Q3geLv8ZD9pihowKJDyMDiN6ArYUmZczvW4976MU3+l54E6lF/JfFEU5hwIDAQAB
-AoGBAKSl/MQarye1yOysqX6P8fDFQt68VvtXkNmlSiKOGuzyho0M+UVSFcs6k1L0
-maDE25AMZUiGzuWHyaU55d7RXDgeskDMakD1v6ZejYtxJkSXbETOTLDwUWTn618T
-gnb17tU1jktUtU67xK/08i/XodlgnQhs6VoHTuCh3Hu77O6RAkEA7+gxqBuZR572
-74/akiW/SuXm0SXPEviyO1MuSRwtI87B02D0qgV8D1UHRm4AhMnJ8MCs1809kMQE
-JiQUCrp9mQJBANlt2ngBO14us6NnhuAseFDTBzCHXwUUu1YKHpMMmxpnGqaldGgX
-sOZB3lgJsT9VlGf3YGYdkLTNVbogQKlKpB8CQQDiSwkb4vyQfDe8/NpU5Not0fII
-8jsDUCb+opWUTMmfbxWRR3FBNu8wnym/m19N4fFj8LqYzHX4KY0oVPu6qvJxAkEA
-wa5snNekFcqONLIE4G5cosrIrb74sqL8GbGb+KuTAprzj5z1K8Bm0UW9lTjVDjDi
-qRYgZfZSL+x1P/54+xTFSwJAY1FxA/N3QPCXCjPh5YqFxAMQs2VVYTfg+t0MEcJD
-dPMQD5JX6g5HKnHFg2mZtoXQrWmJSn7p8GJK8yNTopEErA==
------END RSA PRIVATE KEY-----
-  _end_of_pem_
-
-  TEST_KEY_RSA2048 = OpenSSL::PKey::RSA.new <<-_end_of_pem_
------BEGIN RSA PRIVATE KEY-----
-MIIEpAIBAAKCAQEAuV9ht9J7k4NBs38jOXvvTKY9gW8nLICSno5EETR1cuF7i4pN
-s9I1QJGAFAX0BEO4KbzXmuOvfCpD3CU+Slp1enenfzq/t/e/1IRW0wkJUJUFQign
-4CtrkJL+P07yx18UjyPlBXb81ApEmAB5mrJVSrWmqbjs07JbuS4QQGGXLc+Su96D
-kYKmSNVjBiLxVVSpyZfAY3hD37d60uG+X8xdW5v68JkRFIhdGlb6JL8fllf/A/bl
-NwdJOhVr9mESHhwGjwfSeTDPfd8ZLE027E5lyAVX9KZYcU00mOX+fdxOSnGqS/8J
-DRh0EPHDL15RcJjV2J6vZjPb0rOYGDoMcH+94wIDAQABAoIBAAzsamqfYQAqwXTb
-I0CJtGg6msUgU7HVkOM+9d3hM2L791oGHV6xBAdpXW2H8LgvZHJ8eOeSghR8+dgq
-PIqAffo4x1Oma+FOg3A0fb0evyiACyrOk+EcBdbBeLo/LcvahBtqnDfiUMQTpy6V
-seSoFCwuN91TSCeGIsDpRjbG1vxZgtx+uI+oH5+ytqJOmfCksRDCkMglGkzyfcl0
-Xc5CUhIJ0my53xijEUQl19rtWdMnNnnkdbG8PT3LZlOta5Do86BElzUYka0C6dUc
-VsBDQ0Nup0P6rEQgy7tephHoRlUGTYamsajGJaAo1F3IQVIrRSuagi7+YpSpCqsW
-wORqorkCgYEA7RdX6MDVrbw7LePnhyuaqTiMK+055/R1TqhB1JvvxJ1CXk2rDL6G
-0TLHQ7oGofd5LYiemg4ZVtWdJe43BPZlVgT6lvL/iGo8JnrncB9Da6L7nrq/+Rvj
-XGjf1qODCK+LmreZWEsaLPURIoR/Ewwxb9J2zd0CaMjeTwafJo1CZvcCgYEAyCgb
-aqoWvUecX8VvARfuA593Lsi50t4MEArnOXXcd1RnXoZWhbx5rgO8/ATKfXr0BK/n
-h2GF9PfKzHFm/4V6e82OL7gu/kLy2u9bXN74vOvWFL5NOrOKPM7Kg+9I131kNYOw
-Ivnr/VtHE5s0dY7JChYWE1F3vArrOw3T00a4CXUCgYEA0SqY+dS2LvIzW4cHCe9k
-IQqsT0yYm5TFsUEr4sA3xcPfe4cV8sZb9k/QEGYb1+SWWZ+AHPV3UW5fl8kTbSNb
-v4ng8i8rVVQ0ANbJO9e5CUrepein2MPL0AkOATR8M7t7dGGpvYV0cFk8ZrFx0oId
-U0PgYDotF/iueBWlbsOM430CgYEAqYI95dFyPI5/AiSkY5queeb8+mQH62sdcCCr
-vd/w/CZA/K5sbAo4SoTj8dLk4evU6HtIa0DOP63y071eaxvRpTNqLUOgmLh+D6gS
-Cc7TfLuFrD+WDBatBd5jZ+SoHccVrLR/4L8jeodo5FPW05A+9gnKXEXsTxY4LOUC
-9bS4e1kCgYAqVXZh63JsMwoaxCYmQ66eJojKa47VNrOeIZDZvd2BPVf30glBOT41
-gBoDG3WMPZoQj9pb7uMcrnvs4APj2FIhMU8U15LcPAj59cD6S6rWnAxO8NFK7HQG
-4Jxg3JNNf8ErQoCHb1B3oVdXJkmbJkARoDpBKmTCgKtP8ADYLmVPQw==
------END RSA PRIVATE KEY-----
-  _end_of_pem_
-
-  TEST_KEY_DSA256 = OpenSSL::PKey::DSA.new <<-_end_of_pem_
------BEGIN DSA PRIVATE KEY-----
-MIH3AgEAAkEAhk2libbY2a8y2Pt21+YPYGZeW6wzaW2yfj5oiClXro9XMR7XWLkE
-9B7XxLNFCS2gmCCdMsMW1HulaHtLFQmB2wIVAM43JZrcgpu6ajZ01VkLc93gu/Ed
-AkAOhujZrrKV5CzBKutKLb0GVyVWmdC7InoNSMZEeGU72rT96IjM59YzoqmD0pGM
-3I1o4cGqg1D1DfM1rQlnN1eSAkBq6xXfEDwJ1mLNxF6q8Zm/ugFYWR5xcX/3wFiT
-b4+EjHP/DbNh9Vm5wcfnDBJ1zKvrMEf2xqngYdrV/3CiGJeKAhRvL57QvJZcQGvn
-ISNX5cMzFHRW3Q==
------END DSA PRIVATE KEY-----
-  _end_of_pem_
-
-  TEST_KEY_DSA512 = OpenSSL::PKey::DSA.new <<-_end_of_pem_
------BEGIN DSA PRIVATE KEY-----
-MIH4AgEAAkEA5lB4GvEwjrsMlGDqGsxrbqeFRh6o9OWt6FgTYiEEHaOYhkIxv0Ok
-RZPDNwOG997mDjBnvDJ1i56OmS3MbTnovwIVAJgub/aDrSDB4DZGH7UyarcaGy6D
-AkB9HdFw/3td8K4l1FZHv7TCZeJ3ZLb7dF3TWoGUP003RCqoji3/lHdKoVdTQNuR
-S/m6DlCwhjRjiQ/lBRgCLCcaAkEAjN891JBjzpMj4bWgsACmMggFf57DS0Ti+5++
-Q1VB8qkJN7rA7/2HrCR3gTsWNb1YhAsnFsoeRscC+LxXoXi9OAIUBG98h4tilg6S
-55jreJD3Se3slps=
------END DSA PRIVATE KEY-----
-  _end_of_pem_
-
-  TEST_KEY_DSA1024 = OpenSSL::PKey::DSA.new <<-_end_of_pem_
------BEGIN DSA PRIVATE KEY-----
-MIIBugIBAAKBgQCH9aAoXvWWThIjkA6D+nI1F9ksF9iDq594rkiGNOT9sPDOdB+n
-D+qeeeeloRlj19ymCSADPI0ZLRgkchkAEnY2RnqnhHOjVf/roGgRbW+iQDMbQ9wa
-/pvc6/fAbsu1goE1hBYjm98/sZEeXavj8tR56IXnjF1b6Nx0+sgeUKFKEQIVAMiz
-4BJUFeTtddyM4uadBM7HKLPRAoGAZdLBSYNGiij7vAjesF5mGUKTIgPd+JKuBEDx
-OaBclsgfdoyoF/TMOkIty+PVlYD+//Vl2xnoUEIRaMXHwHfm0r2xUX++oeRaSScg
-YizJdUxe5jvBuBszGPRc/mGpb9YvP0sB+FL1KmuxYmdODfCe51zl8uM/CVhouJ3w
-DjmRGscCgYAuFlfC7p+e8huCKydfcv/beftqjewiOPpQ3u5uI6KPCtCJPpDhs3+4
-IihH2cPsAlqwGF4tlibW1+/z/OZ1AZinPK3y7b2jSJASEaPeEltVzB92hcd1khk2
-jTYcmSsV4VddplOPK9czytR/GbbibxsrhhgZUbd8LPbvIgaiadJ1PgIUBnJ/5vN2
-CVArsEzlPUCbohPvZnE=
------END DSA PRIVATE KEY-----
-  _end_of_pem_
-
-if defined?(OpenSSL::PKey::EC)
-
-  TEST_KEY_EC_P256V1 = OpenSSL::PKey::EC.new <<-_end_of_pem_
------BEGIN EC PRIVATE KEY-----
-MHcCAQEEIID49FDqcf1O1eO8saTgG70UbXQw9Fqwseliit2aWhH1oAoGCCqGSM49
-AwEHoUQDQgAEFglk2c+oVUIKQ64eZG9bhLNPWB7lSZ/ArK41eGy5wAzU/0G51Xtt
-CeBUl+MahZtn9fO1JKdF4qJmS39dXnpENg==
------END EC PRIVATE KEY-----
-  _end_of_pem_
+  module Fixtures
+    module_function
 
-end
+    def pkey(name)
+      OpenSSL::PKey.read(read_file("pkey", name))
+    end
 
-  TEST_KEY_DH1024 = OpenSSL::PKey::DH.new <<-_end_of_pem_
------BEGIN DH PARAMETERS-----
-MIGHAoGBAKnKQ8MNK6nYZzLrrcuTsLxuiJGXoOO5gT+tljOTbHBuiktdMTITzIY0
-pFxIvjG05D7HoBZQfrR0c92NGWPkAiCkhQKB8JCbPVzwNLDy6DZ0pmofDKrEsYHG
-AQjjxMXhwULlmuR/K+WwlaZPiLIBYalLAZQ7ZbOPeVkJ8ePao0eLAgEC
------END DH PARAMETERS-----
-  _end_of_pem_
+    def pkey_dh(name)
+      # DH parameters can be read by OpenSSL::PKey.read atm
+      OpenSSL::PKey::DH.new(read_file("pkey", name))
+    end
 
-  TEST_KEY_DH1024.set_key(OpenSSL::BN.new("556AF1598AE69899867CEBA9F29CE4862B884C2B43C9019EA0231908F6EFA785E3C462A6ECB16DF676866E997FFB72B487DC7967C58C3CA38CE974473BF19B2AA5DCBF102735572EBA6F353F6F0BBE7FF1DE1B07FE1381A355C275C33405004317F9491B5955F191F6615A63B30E55A027FB88A1A4B25608E09EEE68A7DF32D", 16),
-                          OpenSSL::BN.new("48561834C67E65FFD2A9B47F41E5E78FDC95C387428FDB1E4B0188B64D1643C3A8D3455B945B7E8C4D166010C7C2CE23BFB9BEF43D0348FE7FA5284B0225E7FE1537546D114E3D8A4411B9B9351AB451E1A358F50ED61B1F00DA29336EEBBD649980AC86D76AF8BBB065298C2052672EEF3EF13AB47A15275FC2836F3AC74CEA", 16))
+    def read_file(category, name)
+      @file_cache ||= {}
+      @file_cache[[category, name]] ||=
+        File.read(File.join(__dir__, "fixtures", category, name + ".pem"))
+    end
+  end
 
   DSA_SIGNATURE_DIGEST = OpenSSL::OPENSSL_VERSION_NUMBER > 0x10000000 ?
                          OpenSSL::Digest::SHA1 :
@@ -191,190 +123,188 @@ def get_subject_key_id(cert)
     OpenSSL::Digest::SHA1.hexdigest(pkvalue).scan(/../).join(":").upcase
   end
 
-  def silent
-    begin
-      back, $VERBOSE = $VERBOSE, nil
-      yield
-    ensure
-      $VERBOSE = back
-    end
+  def openssl?(major = nil, minor = nil, fix = nil, patch = 0)
+    return false if OpenSSL::OPENSSL_VERSION.include?("LibreSSL")
+    return true unless major
+    OpenSSL::OPENSSL_VERSION_NUMBER >=
+      major * 0x10000000 + minor * 0x100000 + fix * 0x1000 + patch * 0x10
   end
 
-  class OpenSSL::TestCase < Test::Unit::TestCase
-    def setup
-      if ENV["OSSL_GC_STRESS"] == "1"
-        GC.stress = true
-      end
-    end
-
-    def teardown
-      if ENV["OSSL_GC_STRESS"] == "1"
-        GC.stress = false
-      end
-      # OpenSSL error stack must be empty
-      assert_equal([], OpenSSL.errors)
-    end
+  def libressl?(major = nil, minor = nil, fix = nil)
+    version = OpenSSL::OPENSSL_VERSION.scan(/LibreSSL (\d+)\.(\d+)\.(\d+).*/)[0]
+    return false unless version
+    !major || (version.map(&:to_i) <=> [major, minor, fix]) >= 0
   end
+end
 
-  class OpenSSL::SSLTestCase < OpenSSL::TestCase
-    RUBY = EnvUtil.rubybin
-    ITERATIONS = ($0 == __FILE__) ? 100 : 10
-
-    def setup
-      super
-      @ca_key  = OpenSSL::TestUtils::TEST_KEY_RSA2048
-      @svr_key = OpenSSL::TestUtils::TEST_KEY_RSA1024
-      @cli_key = OpenSSL::TestUtils::TEST_KEY_DSA1024
-      @ca  = OpenSSL::X509::Name.parse("/DC=org/DC=ruby-lang/CN=CA")
-      @svr = OpenSSL::X509::Name.parse("/DC=org/DC=ruby-lang/CN=localhost")
-      @cli = OpenSSL::X509::Name.parse("/DC=org/DC=ruby-lang/CN=localhost")
-      ca_exts = [
-        ["basicConstraints","CA:TRUE",true],
-        ["keyUsage","cRLSign,keyCertSign",true],
-      ]
-      ee_exts = [
-        ["keyUsage","keyEncipherment,digitalSignature",true],
-      ]
-      @ca_cert  = issue_cert(@ca, @ca_key, 1, ca_exts, nil, nil)
-      @svr_cert = issue_cert(@svr, @svr_key, 2, ee_exts, @ca_cert, @ca_key)
-      @cli_cert = issue_cert(@cli, @cli_key, 3, ee_exts, @ca_cert, @ca_key)
-      @server = nil
-    end
+class OpenSSL::TestCase < Test::Unit::TestCase
+  include OpenSSL::TestUtils
+  extend OpenSSL::TestUtils
 
-    def issue_cert(*arg)
-      OpenSSL::TestUtils.issue_cert(*arg)
+  def setup
+    if ENV["OSSL_GC_STRESS"] == "1"
+      GC.stress = true
     end
+  end
 
-    def issue_crl(*arg)
-      OpenSSL::TestUtils.issue_crl(*arg)
+  def teardown
+    if ENV["OSSL_GC_STRESS"] == "1"
+      GC.stress = false
     end
+    # OpenSSL error stack must be empty
+    assert_equal([], OpenSSL.errors)
+  end
+end
 
-    def readwrite_loop(ctx, ssl)
-      while line = ssl.gets
-        ssl.write(line)
-      end
-    rescue OpenSSL::SSL::SSLError
-    rescue IOError
-    ensure
-      ssl.close rescue nil
-    end
+class OpenSSL::SSLTestCase < OpenSSL::TestCase
+  RUBY = EnvUtil.rubybin
+  ITERATIONS = ($0 == __FILE__) ? 100 : 10
+
+  def setup
+    super
+    @ca_key  = Fixtures.pkey("rsa2048")
+    @svr_key = Fixtures.pkey("rsa1024")
+    @cli_key = Fixtures.pkey("rsa2048")
+    @ca  = OpenSSL::X509::Name.parse("/DC=org/DC=ruby-lang/CN=CA")
+    @svr = OpenSSL::X509::Name.parse("/DC=org/DC=ruby-lang/CN=localhost")
+    @cli = OpenSSL::X509::Name.parse("/DC=org/DC=ruby-lang/CN=localhost")
+    ca_exts = [
+      ["basicConstraints","CA:TRUE",true],
+      ["keyUsage","cRLSign,keyCertSign",true],
+    ]
+    ee_exts = [
+      ["keyUsage","keyEncipherment,digitalSignature",true],
+    ]
+    @ca_cert  = issue_cert(@ca, @ca_key, 1, ca_exts, nil, nil)
+    @svr_cert = issue_cert(@svr, @svr_key, 2, ee_exts, @ca_cert, @ca_key)
+    @cli_cert = issue_cert(@cli, @cli_key, 3, ee_exts, @ca_cert, @ca_key)
+    @server = nil
+  end
 
-    def server_loop(ctx, ssls, stop_pipe_r, ignore_listener_error, server_proc, threads)
-      loop do
-        ssl = nil
-        begin
-          readable, = IO.select([ssls, stop_pipe_r])
-          if readable.include? stop_pipe_r
-            return
-          end
-          ssl = ssls.accept
-        rescue OpenSSL::SSL::SSLError, Errno::ECONNRESET
-          if ignore_listener_error
-            retry
-          else
-            raise
-          end
-        end
+  def tls12_supported?
+    OpenSSL::SSL::SSLContext::METHODS.include?(:TLSv1_2)
+  end
 
-        th = Thread.start do
-          server_proc.call(ctx, ssl)
-        end
-        threads << th
-      end
-    rescue Errno::EBADF, IOError, Errno::EINVAL, Errno::ECONNABORTED, Errno::ENOTSOCK, Errno::ECONNRESET
-      if !ignore_listener_error
-        raise
-      end
+  def readwrite_loop(ctx, ssl)
+    while line = ssl.gets
+      ssl.write(line)
     end
+  end
 
-    def start_server(verify_mode: OpenSSL::SSL::VERIFY_NONE, start_immediately: true,
-                     ctx_proc: nil, server_proc: method(:readwrite_loop),
-                     ignore_listener_error: false, &block)
-      IO.pipe {|stop_pipe_r, stop_pipe_w|
-        store = OpenSSL::X509::Store.new
-        store.add_cert(@ca_cert)
-        store.purpose = OpenSSL::X509::PURPOSE_SSL_CLIENT
-        ctx = OpenSSL::SSL::SSLContext.new
-        ctx.cert_store = store
-        ctx.cert = @svr_cert
-        ctx.key = @svr_key
-        ctx.tmp_dh_callback = proc { OpenSSL::TestUtils::TEST_KEY_DH1024 }
-        begin
-          ctx.ecdh_curves = "P-256"
-        rescue NotImplementedError
-        end
-        ctx.verify_mode = verify_mode
-        ctx_proc.call(ctx) if ctx_proc
-
-        Socket.do_not_reverse_lookup = true
-        tcps = nil
-        tcps = TCPServer.new("127.0.0.1", 0)
-        port = tcps.connect_address.ip_port
-
-        ssls = OpenSSL::SSL::SSLServer.new(tcps, ctx)
-        ssls.start_immediately = start_immediately
-
-        threads = []
-        begin
-          server = Thread.new do
-            begin
-              server_loop(ctx, ssls, stop_pipe_r, ignore_listener_error, server_proc, threads)
-            ensure
-              tcps.close
+  def start_server(verify_mode: OpenSSL::SSL::VERIFY_NONE, start_immediately: true,
+                   ctx_proc: nil, server_proc: method(:readwrite_loop),
+                   ignore_listener_error: false, &block)
+    IO.pipe {|stop_pipe_r, stop_pipe_w|
+      store = OpenSSL::X509::Store.new
+      store.add_cert(@ca_cert)
+      store.purpose = OpenSSL::X509::PURPOSE_SSL_CLIENT
+      ctx = OpenSSL::SSL::SSLContext.new
+      ctx.cert_store = store
+      ctx.cert = @svr_cert
+      ctx.key = @svr_key
+      ctx.tmp_dh_callback = proc { Fixtures.pkey_dh("dh1024") }
+      ctx.verify_mode = verify_mode
+      ctx_proc.call(ctx) if ctx_proc
+
+      Socket.do_not_reverse_lookup = true
+      tcps = TCPServer.new("127.0.0.1", 0)
+      port = tcps.connect_address.ip_port
+
+      ssls = OpenSSL::SSL::SSLServer.new(tcps, ctx)
+      ssls.start_immediately = start_immediately
+
+      threads = []
+      begin
+        server_thread = Thread.new do
+          begin
+            loop do
+              begin
+                readable, = IO.select([ssls, stop_pipe_r])
+                break if readable.include? stop_pipe_r
+                ssl = ssls.accept
+              rescue OpenSSL::SSL::SSLError, IOError, Errno::EBADF, Errno::EINVAL,
+                     Errno::ECONNABORTED, Errno::ENOTSOCK, Errno::ECONNRESET
+                retry if ignore_listener_error
+                raise
+              end
+
+              th = Thread.new do
+                begin
+                  server_proc.call(ctx, ssl)
+                ensure
+                  ssl.close
+                end
+                true
+              end
+              threads << th
             end
+          ensure
+            tcps.close
           end
-          threads.unshift server
-
-          $stderr.printf("SSL server started: pid=%d port=%d\n", $$, port) if $DEBUG
+        end
 
-          client = Thread.new do
-            begin
-              block.call(server, port.to_i)
-            ensure
-              stop_pipe_w.close
-            end
+        client_thread = Thread.new do
+          begin
+            block.call(port)
+          ensure
+            # Stop accepting new connection
+            stop_pipe_w.close
+            server_thread.join
           end
-          threads.unshift client
-        ensure
-          assert_join_threads(threads)
         end
-      }
-    end
+        threads.unshift client_thread
+      ensure
+        # Terminate existing connections. If a thread did 'pend', re-raise it.
+        pend = nil
+        threads.each { |th|
+          begin
+            th.join(10) or
+              th.raise(RuntimeError, "[start_server] thread did not exit in 10 secs")
+          rescue (defined?(MiniTest::Skip) ? MiniTest::Skip : Test::Unit::PendedError)
+            # MiniTest::Skip is for the Ruby tree
+            pend = $!
+          rescue Exception
+          end
+        }
+        raise pend if pend
+        assert_join_threads(threads)
+      end
+    }
   end
+end
 
-  class OpenSSL::PKeyTestCase < OpenSSL::TestCase
-    def check_component(base, test, keys)
-      keys.each { |comp|
-        assert_equal base.send(comp), test.send(comp)
-      }
-    end
+class OpenSSL::PKeyTestCase < OpenSSL::TestCase
+  def check_component(base, test, keys)
+    keys.each { |comp|
+      assert_equal base.send(comp), test.send(comp)
+    }
+  end
 
-    def dup_public(key)
-      case key
-      when OpenSSL::PKey::RSA
-        rsa = OpenSSL::PKey::RSA.new
-        rsa.set_key(key.n, key.e, nil)
-        rsa
-      when OpenSSL::PKey::DSA
-        dsa = OpenSSL::PKey::DSA.new
-        dsa.set_pqg(key.p, key.q, key.g)
-        dsa.set_key(key.pub_key, nil)
-        dsa
-      when OpenSSL::PKey::DH
-        dh = OpenSSL::PKey::DH.new
-        dh.set_pqg(key.p, nil, key.g)
-        dh
+  def dup_public(key)
+    case key
+    when OpenSSL::PKey::RSA
+      rsa = OpenSSL::PKey::RSA.new
+      rsa.set_key(key.n, key.e, nil)
+      rsa
+    when OpenSSL::PKey::DSA
+      dsa = OpenSSL::PKey::DSA.new
+      dsa.set_pqg(key.p, key.q, key.g)
+      dsa.set_key(key.pub_key, nil)
+      dsa
+    when OpenSSL::PKey::DH
+      dh = OpenSSL::PKey::DH.new
+      dh.set_pqg(key.p, nil, key.g)
+      dh
+    else
+      if defined?(OpenSSL::PKey::EC) && OpenSSL::PKey::EC === key
+        ec = OpenSSL::PKey::EC.new(key.group)
+        ec.public_key = key.public_key
+        ec
       else
-        if defined?(OpenSSL::PKey::EC) && OpenSSL::PKey::EC === key
-          ec = OpenSSL::PKey::EC.new(key.group)
-          ec.public_key = key.public_key
-          ec
-        else
-          raise "unknown key type"
-        end
+        raise "unknown key type"
       end
     end
   end
+end
 
-end if defined?(OpenSSL::OPENSSL_LIBRARY_VERSION) and
-  /\AOpenSSL +0\./ !~ OpenSSL::OPENSSL_LIBRARY_VERSION
+end
-- 
2.14.1.690.gbb1197296efa

