From b503ff8b4336af550f48f3dc63c0c07c9d5fd0d1 Mon Sep 17 00:00:00 2001 From: nagachika Date: Mon, 19 Mar 2018 15:11:08 +0000 Subject: Update rubygems to 2.0.6. [Bug #13935] The patch is provided by Kazuki Yamaguchi. From: Kazuki Yamaguchi 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. git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/branches/ruby_2_4@62842 b2dd03c8-39d4-4d8f-98ff-823fe69b080e --- 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 ++++++++++++++------------------- version.h | 6 +- 43 files changed, 1248 insertions(+), 1139 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 8baa0208ea..d592bc6a1f 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 d773637c0e..b0dffefd3e 100644 --- a/ext/openssl/lib/openssl/buffering.rb +++ b/ext/openssl/lib/openssl/buffering.rb @@ -164,10 +164,9 @@ module OpenSSL::Buffering # 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 @@ module OpenSSL::Buffering # 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 7cbbfeb513..2af041ebde 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 @@ Gem::Specification.new do |s| 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 c22966df5a..88bb8f2101 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 c2f0927a75..36e42ede8c 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 f9c9d76fc2..aa2dbbc8f7 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 be3eebe1f2..7725bc0525 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 8dacc8266e..5b1481aea7 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 0000000000..f99c757f21 --- /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 0000000000..1bf498895e --- /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 0000000000..d9a407f736 --- /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 0000000000..962c41cc67 --- /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 0000000000..97c97d9f9d --- /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 0000000000..464de074be --- /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 0000000000..ac89cd88ed --- /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 91ae2cfd0c..55cb1f0bec 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 @@ rEzBQ0F9dUyqQ9gyRg8KHhDfv9HzT1d/rnUZMkoombwYBRIUChGCYV0GnJcan2Zm 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 37ba5e5595..5f3ae2b465 100644 --- a/test/openssl/test_bn.rb +++ b/test/openssl/test_bn.rb @@ -55,6 +55,7 @@ class OpenSSL::TestBN < OpenSSL::TestCase 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 f85353fc67..08735adda9 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 @@ class OpenSSL::TestBuffering < OpenSSL::TestCase 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 786bce9d2f..99dcc49727 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 @@ __EOC__ 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 @@ __EOC__ 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 @@ __EOC__ 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 @@ __EOC__ @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 9891d99ae3..c8817395bb 100644 --- a/test/openssl/test_digest.rb +++ b/test/openssl/test_digest.rb @@ -54,13 +54,10 @@ class OpenSSL::TestDigest < OpenSSL::TestCase 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 @@ class OpenSSL::TestDigest < OpenSSL::TestCase 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 @@ class OpenSSL::TestDigest < OpenSSL::TestCase 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 75e45eb7f0..801d1c8e1a 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 @@ class OpenSSL::TestEngine < OpenSSL::TestCase 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 @@ class OpenSSL::TestEngine < OpenSSL::TestCase 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 dbde97d9c9..4d06e47654 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 @@ class OpenSSL::TestHMAC < OpenSSL::TestCase 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 ac34613fc2..58e0f6498c 100644 --- a/test/openssl/test_ns_spki.rb +++ b/test/openssl/test_ns_spki.rb @@ -17,8 +17,8 @@ class OpenSSL::TestNSSPI < OpenSSL::TestCase 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 8881f25dd9..0440634ab0 100644 --- a/test/openssl/test_ocsp.rb +++ b/test/openssl/test_ocsp.rb @@ -13,7 +13,7 @@ class OpenSSL::TestOCSP < OpenSSL::TestCase # @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 @@ class OpenSSL::TestOCSP < OpenSSL::TestCase 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 @@ class OpenSSL::TestOCSP < OpenSSL::TestCase 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 @@ class OpenSSL::TestOCSP < OpenSSL::TestCase 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 9a5205f81c..ea5f0dcf9f 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 @@ end 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 @@ module OpenSSL::TestPairM } 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 @@ module OpenSSL::TestPairM 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 @@ module OpenSSL::TestPairM 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 @@ module OpenSSL::TestPairM 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 @@ module OpenSSL::TestPairM 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 @@ module OpenSSL::TestPairM 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 @@ module OpenSSL::TestPairM 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 403718b94f..3088823411 100644 --- a/test/openssl/test_pkcs12.rb +++ b/test/openssl/test_pkcs12.rb @@ -5,8 +5,6 @@ if defined?(OpenSSL::TestUtils) 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 @@ module OpenSSL ["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 @@ FJx7d3f29gkzynCLJDkCQGQZlEZJC4vWmWJGRKJ24P6MyQn3VsPfErSKOg4lvyM3 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 @@ Li8JsX5yIiuVYaBg/6ha3tOg4TCa5K/3r3tVliRZ2Es= 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 @@ Li8JsX5yIiuVYaBg/6ha3tOg4TCa5K/3r3tVliRZ2Es= pkcs12 = OpenSSL::PKCS12.create( "omg", "hello", - TEST_KEY_RSA1024, + @mykey, @mycert, chain ) @@ -94,7 +93,7 @@ Li8JsX5yIiuVYaBg/6ha3tOg4TCa5K/3r3tVliRZ2Es= pkcs12 = OpenSSL::PKCS12.create( passwd, "hello", - TEST_KEY_RSA1024, + @mykey, @mycert, chain ) @@ -104,7 +103,7 @@ Li8JsX5yIiuVYaBg/6ha3tOg4TCa5K/3r3tVliRZ2Es= 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 @@ Li8JsX5yIiuVYaBg/6ha3tOg4TCa5K/3r3tVliRZ2Es= OpenSSL::PKCS12.create( "omg", "hello", - TEST_KEY_RSA1024, + @mykey, @mycert, [], "foo" @@ -124,7 +123,7 @@ Li8JsX5yIiuVYaBg/6ha3tOg4TCa5K/3r3tVliRZ2Es= OpenSSL::PKCS12.create( "omg", "hello", - TEST_KEY_RSA1024, + @mykey, @mycert, [], nil, @@ -136,7 +135,7 @@ Li8JsX5yIiuVYaBg/6ha3tOg4TCa5K/3r3tVliRZ2Es= OpenSSL::PKCS12.create( "omg", "hello", - TEST_KEY_RSA1024, + @mykey, @mycert, [], nil, @@ -150,7 +149,7 @@ Li8JsX5yIiuVYaBg/6ha3tOg4TCa5K/3r3tVliRZ2Es= OpenSSL::PKCS12.create( "omg", "hello", - TEST_KEY_RSA1024, + @mykey, @mycert, [], nil, @@ -163,7 +162,7 @@ Li8JsX5yIiuVYaBg/6ha3tOg4TCa5K/3r3tVliRZ2Es= OpenSSL::PKCS12.create( "omg", "hello", - TEST_KEY_RSA1024, + @mykey, @mycert, [], nil, @@ -216,7 +215,7 @@ vyl2WuMdEwQIMWFFphPkIUICAggA 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 @@ Kw4DAhoFAAQUYAuwVtGD1TdgbFK4Yal2XBgwUR4ECEawsN3rNaa6AgIIAA== 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 ad8132c263..0919b9ce60 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 @@ class OpenSSL::TestPKCS5 < OpenSSL::TestCase 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 3219155462..026fe84797 100644 --- a/test/openssl/test_pkcs7.rb +++ b/test/openssl/test_pkcs7.rb @@ -6,8 +6,8 @@ if defined?(OpenSSL::TestUtils) 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 @@ class OpenSSL::TestPKCS7 < OpenSSL::TestCase @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 470c952e21..fb71381393 100644 --- a/test/openssl/test_pkey_dh.rb +++ b/test/openssl/test_pkey_dh.rb @@ -4,8 +4,6 @@ require_relative 'utils' 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 @@ class OpenSSL::TestPKeyDH < OpenSSL::PKeyTestCase 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 @@ class OpenSSL::TestPKeyDH < OpenSSL::PKeyTestCase -----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 @@ class OpenSSL::TestPKeyDH < OpenSSL::PKeyTestCase 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 a4ccd1d8f9..474f238885 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 @@ class OpenSSL::TestPKeyDSA < OpenSSL::PKeyTestCase 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 @@ class OpenSSL::TestPKeyDSA < OpenSSL::PKeyTestCase 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 @@ class OpenSSL::TestPKeyDSA < OpenSSL::PKeyTestCase -----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 @@ class OpenSSL::TestPKeyDSA < OpenSSL::PKeyTestCase -----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 @@ class OpenSSL::TestPKeyDSA < OpenSSL::PKeyTestCase -----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 c549d9c674..8119b77cc7 100644 --- a/test/openssl/test_pkey_ec.rb +++ b/test/openssl/test_pkey_ec.rb @@ -4,8 +4,6 @@ require_relative 'utils' 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 @@ class OpenSSL::TestEC < OpenSSL::PKeyTestCase 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 @@ class OpenSSL::TestEC < OpenSSL::PKeyTestCase 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 @@ class OpenSSL::TestEC < OpenSSL::PKeyTestCase -----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 @@ class OpenSSL::TestEC < OpenSSL::PKeyTestCase -----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 @@ class OpenSSL::TestEC < OpenSSL::PKeyTestCase -----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 @@ class OpenSSL::TestEC < OpenSSL::PKeyTestCase 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 93760f747e..c120556339 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 @@ class OpenSSL::TestPKeyRSA < OpenSSL::PKeyTestCase 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 @@ class OpenSSL::TestPKeyRSA < OpenSSL::PKeyTestCase 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 @@ class OpenSSL::TestPKeyRSA < OpenSSL::PKeyTestCase 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 @@ class OpenSSL::TestPKeyRSA < OpenSSL::PKeyTestCase -----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 @@ class OpenSSL::TestPKeyRSA < OpenSSL::PKeyTestCase -----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 @@ class OpenSSL::TestPKeyRSA < OpenSSL::PKeyTestCase -----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 @@ class OpenSSL::TestPKeyRSA < OpenSSL::PKeyTestCase ]), 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 @@ class OpenSSL::TestPKeyRSA < OpenSSL::PKeyTestCase -----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 6079461920..c0160f9a7a 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 @@ class OpenSSL::TestRandom < OpenSSL::TestCase 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 8c65df953d..7bb32adf92 100644 --- a/test/openssl/test_ssl.rb +++ b/test/openssl/test_ssl.rb @@ -35,7 +35,7 @@ class OpenSSL::TestSSL < OpenSSL::SSLTestCase 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 @@ class OpenSSL::TestSSL < OpenSSL::SSLTestCase 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 @@ class OpenSSL::TestSSL < OpenSSL::SSLTestCase 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 @@ class OpenSSL::TestSSL < OpenSSL::SSLTestCase 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 @@ class OpenSSL::TestSSL < OpenSSL::SSLTestCase 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 @@ class OpenSSL::TestSSL < OpenSSL::SSLTestCase 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 @@ class OpenSSL::TestSSL < OpenSSL::SSLTestCase 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 @@ class OpenSSL::TestSSL < OpenSSL::SSLTestCase 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 @@ class OpenSSL::TestSSL < OpenSSL::SSLTestCase 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 @@ class OpenSSL::TestSSL < OpenSSL::SSLTestCase 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 @@ class OpenSSL::TestSSL < OpenSSL::SSLTestCase 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 @@ class OpenSSL::TestSSL < OpenSSL::SSLTestCase 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 @@ class OpenSSL::TestSSL < OpenSSL::SSLTestCase 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 @@ class OpenSSL::TestSSL < OpenSSL::SSLTestCase 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 @@ class OpenSSL::TestSSL < OpenSSL::SSLTestCase 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 @@ class OpenSSL::TestSSL < OpenSSL::SSLTestCase 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 @@ class OpenSSL::TestSSL < OpenSSL::SSLTestCase 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 @@ class OpenSSL::TestSSL < OpenSSL::SSLTestCase ["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 @@ class OpenSSL::TestSSL < OpenSSL::SSLTestCase ["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 @@ class OpenSSL::TestSSL < OpenSSL::SSLTestCase 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 @@ class OpenSSL::TestSSL < OpenSSL::SSLTestCase 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 @@ class OpenSSL::TestSSL < OpenSSL::SSLTestCase 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 @@ class OpenSSL::TestSSL < OpenSSL::SSLTestCase 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 @@ class OpenSSL::TestSSL < OpenSSL::SSLTestCase 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 @@ class OpenSSL::TestSSL < OpenSSL::SSLTestCase # 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 @@ if OpenSSL::SSL::SSLContext::METHODS.include?(:TLSv1) && OpenSSL::SSL::SSLContex 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 @@ if OpenSSL::SSL::SSLContext::METHODS.include?(:TLSv1) && OpenSSL::SSL::SSLContex 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 @@ end 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 @@ if OpenSSL::SSL::SSLContext::METHODS.include?(:TLSv1_1) && OpenSSL::SSL::SSLCont 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 @@ end 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 @@ if OpenSSL::SSL::SSLContext::METHODS.include?(:TLSv1_2) && OpenSSL::SSL::SSLCont 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 @@ if OpenSSL::SSL::SSLContext::METHODS.include?(:TLSv1_2) && OpenSSL::SSL::SSLCont 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 @@ if OpenSSL::SSL::SSLContext::METHODS.include?(:TLSv1_2) && OpenSSL::SSL::SSLCont 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 @@ end 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 @@ if OpenSSL::OPENSSL_VERSION_NUMBER >= 0x10002000 } 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 @@ if OpenSSL::OPENSSL_VERSION_NUMBER >= 0x10002000 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 @@ if OpenSSL::OPENSSL_VERSION_NUMBER >= 0x10002000 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 @@ if OpenSSL::OPENSSL_VERSION_NUMBER > 0x10001000 && 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 @@ if OpenSSL::OPENSSL_VERSION_NUMBER > 0x10001000 && 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 @@ if OpenSSL::OPENSSL_VERSION_NUMBER > 0x10001000 && 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 @@ if OpenSSL::OPENSSL_VERSION_NUMBER > 0x10001000 && 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 @@ end } end - def test_close_and_socket_close_while_connecting - # test it doesn't cause a segmentation fault - ctx = OpenSSL::SSL::SSLContext.new - ctx.ciphers = "aNULL" - 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 @@ end 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 @@ end 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 @@ end 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 @@ end ) 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 7a99dca5ed..9d0e5a2db1 100644 --- a/test/openssl/test_ssl_session.rb +++ b/test/openssl/test_ssl_session.rb @@ -4,54 +4,12 @@ require_relative "utils" 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 @@ tddwpBAEDjcwMzA5NTYzMTU1MzAwpQMCARM= 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 @@ __EOS__ 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 @@ __EOS__ 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 5b2e712d2a..03650402fd 100644 --- a/test/openssl/test_x509cert.rb +++ b/test/openssl/test_x509cert.rb @@ -6,18 +6,14 @@ if defined?(OpenSSL::TestUtils) 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 44dfffc952..7d55e3c1cf 100644 --- a/test/openssl/test_x509crl.rb +++ b/test/openssl/test_x509crl.rb @@ -6,23 +6,15 @@ if defined?(OpenSSL::TestUtils) 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 60e8ddb8ac..c1dacf4fa1 100644 --- a/test/openssl/test_x509name.rb +++ b/test/openssl/test_x509name.rb @@ -306,7 +306,6 @@ class OpenSSL::TestX509Name < OpenSSL::TestCase 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 585dda1bc6..fcc3e2f10a 100644 --- a/test/openssl/test_x509req.rb +++ b/test/openssl/test_x509req.rb @@ -6,10 +6,10 @@ if defined?(OpenSSL::TestUtils) 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 c45233aaec..b40534c6db 100644 --- a/test/openssl/test_x509store.rb +++ b/test/openssl/test_x509store.rb @@ -6,10 +6,10 @@ if defined?(OpenSSL::TestUtils) 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 @@ class OpenSSL::TestX509Store < OpenSSL::TestCase 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 @@ class OpenSSL::TestX509Store < OpenSSL::TestCase 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 @@ class OpenSSL::TestX509Store < OpenSSL::TestCase 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 6de41c4a70..a49ad51336 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 @@ module OpenSSL::TestEOF end end end + +end diff --git a/test/openssl/utils.rb b/test/openssl/utils.rb index bbc9c7efc2..4331d8bd8d 100644 --- a/test/openssl/utils.rb +++ b/test/openssl/utils.rb @@ -9,120 +9,52 @@ begin 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 @@ AQjjxMXhwULlmuR/K+WwlaZPiLIBYalLAZQ7ZbOPeVkJ8ePao0eLAgEC 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 diff --git a/version.h b/version.h index d34b5ac49e..0caa0dc273 100644 --- a/version.h +++ b/version.h @@ -1,10 +1,10 @@ #define RUBY_VERSION "2.4.4" -#define RUBY_RELEASE_DATE "2018-03-18" -#define RUBY_PATCHLEVEL 263 +#define RUBY_RELEASE_DATE "2018-03-20" +#define RUBY_PATCHLEVEL 264 #define RUBY_RELEASE_YEAR 2018 #define RUBY_RELEASE_MONTH 3 -#define RUBY_RELEASE_DAY 18 +#define RUBY_RELEASE_DAY 20 #include "ruby/version.h" -- cgit v1.2.3