From ee37304b67fec137b383552e9fc74dc90905883b Mon Sep 17 00:00:00 2001 From: Kazuki Yamaguchi Date: Tue, 6 Sep 2016 04:00:05 +0900 Subject: test/test_ssl: move DH and ECDH tests from test_pair.rb test_pair.rb is the file for tests of IO-like methods - the test cases in OpenSSL::TestPairM run twice with different underlying socket type. test_ssl.rb is more appropriate file for {EC,}DH tests. --- test/test_pair.rb | 141 ------------------------------------------------------ test/test_ssl.rb | 117 ++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 117 insertions(+), 141 deletions(-) (limited to 'test') diff --git a/test/test_pair.rb b/test/test_pair.rb index 92502229..73d3e8d4 100644 --- a/test/test_pair.rb +++ b/test/test_pair.rb @@ -344,147 +344,6 @@ module OpenSSL::TestPairM serv.close if serv && !serv.closed? end - def test_connect_works_when_setting_dh_callback_to_nil - ctx2 = OpenSSL::SSL::SSLContext.new - ctx2.ciphers = "DH" - ctx2.security_level = 0 - ctx2.tmp_dh_callback = nil - sock1, sock2 = tcp_pair - s2 = OpenSSL::SSL::SSLSocket.new(sock2, ctx2) - s2.accept_nonblock(exception: false) - - ctx1 = OpenSSL::SSL::SSLContext.new - ctx1.ciphers = "DH" - ctx1.security_level = 0 - ctx1.tmp_dh_callback = nil - s1 = OpenSSL::SSL::SSLSocket.new(sock1, ctx1) - t = Thread.new { s1.connect } - - EnvUtil.suppress_warning { # uses default callback - assert_nothing_raised { s2.accept } - } - assert_equal s1, t.value - ensure - t.join if t - s1.close if s1 - s2.close if s2 - sock1.close if sock1 - sock2.close if sock2 - end - - def test_connect_without_setting_dh_callback - ctx2 = OpenSSL::SSL::SSLContext.new - ctx2.ciphers = "DH" - ctx2.security_level = 0 - sock1, sock2 = tcp_pair - s2 = OpenSSL::SSL::SSLSocket.new(sock2, ctx2) - s2.accept_nonblock(exception: false) - - ctx1 = OpenSSL::SSL::SSLContext.new - ctx1.ciphers = "DH" - ctx1.security_level = 0 - s1 = OpenSSL::SSL::SSLSocket.new(sock1, ctx1) - t = Thread.new { s1.connect } - - EnvUtil.suppress_warning { # default DH - assert_nothing_raised { s2.accept } - } - assert_equal s1, t.value - ensure - t.join if t - s1.close if s1 - s2.close if s2 - sock1.close if sock1 - sock2.close if sock2 - end - - def test_ecdh_callback - return unless OpenSSL::SSL::SSLContext.instance_methods.include?(:tmp_ecdh_callback) - EnvUtil.suppress_warning do # tmp_ecdh_callback is deprecated (2016-05) - begin - called = false - ctx2 = OpenSSL::SSL::SSLContext.new - ctx2.ciphers = "ECDH" - # 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 = true - OpenSSL::PKey::EC.new "prime256v1" - } - - sock1, sock2 = tcp_pair - - s2 = OpenSSL::SSL::SSLSocket.new(sock2, ctx2) - ctx1 = OpenSSL::SSL::SSLContext.new - ctx1.ciphers = "ECDH" - ctx1.security_level = 0 - - s1 = OpenSSL::SSL::SSLSocket.new(sock1, ctx1) - th = Thread.new do - begin - rv = s1.connect_nonblock(exception: false) - case rv - when :wait_writable - IO.select(nil, [s1], nil, 5) - when :wait_readable - IO.select([s1], nil, nil, 5) - end - end until rv == s1 - end - - 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 - end - end - end - - def test_ecdh_curves - sock1, sock2 = tcp_pair - - ctx1 = OpenSSL::SSL::SSLContext.new - begin - ctx1.ciphers = "ECDH" - rescue OpenSSL::SSL::SSLError - pend "ECDH is not enabled in this OpenSSL" if $!.message =~ /no cipher match/ - raise - end - ctx1.ecdh_curves = "P-384:P-521" - ctx1.security_level = 0 - s1 = OpenSSL::SSL::SSLSocket.new(sock1, ctx1) - - ctx2 = OpenSSL::SSL::SSLContext.new - ctx2.ciphers = "ECDH" - ctx2.ecdh_curves = "P-256:P-384" - ctx2.security_level = 0 - s2 = OpenSSL::SSL::SSLSocket.new(sock2, ctx2) - - th = Thread.new { s1.accept } - s2.connect - - assert s2.cipher[0].start_with?("AECDH"), "AECDH should be used" - if s2.respond_to?(:tmp_key) - assert_equal "secp384r1", s2.tmp_key.group.curve_name - end - ensure - th.join if th - s1.close if s1 - s2.close if s2 - sock1.close if sock1 - sock2.close if sock2 - end - def test_connect_accept_nonblock_no_exception ctx2 = OpenSSL::SSL::SSLContext.new ctx2.ciphers = "ADH" diff --git a/test/test_ssl.rb b/test/test_ssl.rb index 3c0922f5..8e31b53f 100644 --- a/test/test_ssl.rb +++ b/test/test_ssl.rb @@ -1295,6 +1295,123 @@ end end end + def test_dh_callback + called = false + ctx_proc = -> ctx { + ctx.ciphers = "DH:!NULL" + ctx.tmp_dh_callback = ->(*args) { + called = true + OpenSSL::TestUtils::TEST_KEY_DH1024 + } + } + start_server(ctx_proc: ctx_proc) do |server, 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 + end + } + end + end + + def test_connect_works_when_setting_dh_callback_to_nil + ctx_proc = -> ctx { + ctx.ciphers = "DH:!NULL" # use DH + ctx.tmp_dh_callback = nil + } + start_server(ctx_proc: ctx_proc) do |server, port| + EnvUtil.suppress_warning { # uses default callback + assert_nothing_raised { + server_connect(port) { } + } + } + end + end + + def test_ecdh_callback + return unless OpenSSL::SSL::SSLContext.instance_methods.include?(:tmp_ecdh_callback) + EnvUtil.suppress_warning do # tmp_ecdh_callback is deprecated (2016-05) + begin + called = false + ctx2 = OpenSSL::SSL::SSLContext.new + ctx2.ciphers = "ECDH" + # 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 = 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 + end + end + end + + def test_ecdh_curves + 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 + ctx.ecdh_curves = "P-384:P-521" + } + start_server(ctx_proc: ctx_proc, ignore_listener_error: true) do |server, 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) + assert_equal "secp384r1", ssl.tmp_key.group.curve_name + end + } + + if OpenSSL::OPENSSL_VERSION_NUMBER >= 0x10002000 && + !OpenSSL::OPENSSL_VERSION.include?("LibreSSL") + ctx = OpenSSL::SSL::SSLContext.new + ctx.ecdh_curves = "P-256" + + assert_raise(OpenSSL::SSL::SSLError) { + server_connect(port, ctx) { } + } + + ctx = OpenSSL::SSL::SSLContext.new + ctx.ecdh_curves = "P-521:P-384" + + server_connect(port, ctx) { |ssl| + assert_equal "secp521r1", ssl.tmp_key.group.curve_name + } + end + end + end + def test_security_level ctx = OpenSSL::SSL::SSLContext.new begin -- cgit v1.2.3