From 9088fe902908bc6ddf7cb062d7ec8fc40c0f5dc3 Mon Sep 17 00:00:00 2001 From: Kazuki Yamaguchi Date: Mon, 27 Sep 2021 01:09:59 +0900 Subject: test: adjust test cases for LibreSSL 3.2.4 This is a backport to the 2.1 branch of the following commits: - a0e98d48c91f ("Enhance TLS 1.3 support on LibreSSL 3.2/3.3", 2020-12-03) - a9954bac22ba ("test: adjust test cases for LibreSSL 3.2.4", 2021-02-25) --- ext/openssl/ossl_ssl.c | 6 ++++++ test/test_ssl.rb | 47 ++++++++++++++++++++++++++++++++++++----------- test/test_ssl_session.rb | 1 + test/utils.rb | 8 ++++++++ 4 files changed, 51 insertions(+), 11 deletions(-) diff --git a/ext/openssl/ossl_ssl.c b/ext/openssl/ossl_ssl.c index f4271369..a8386f72 100644 --- a/ext/openssl/ossl_ssl.c +++ b/ext/openssl/ossl_ssl.c @@ -13,6 +13,12 @@ #define numberof(ary) (int)(sizeof(ary)/sizeof((ary)[0])) +#if !defined(TLS1_3_VERSION) && \ + defined(LIBRESSL_VERSION_NUMBER) && \ + LIBRESSL_VERSION_NUMBER >= 0x3020000fL +# define TLS1_3_VERSION 0x0304 +#endif + #ifdef _WIN32 # define TO_SOCKET(s) _get_osfhandle(s) #else diff --git a/test/test_ssl.rb b/test/test_ssl.rb index 764416be..53457e21 100644 --- a/test/test_ssl.rb +++ b/test/test_ssl.rb @@ -207,7 +207,10 @@ class OpenSSL::TestSSL < OpenSSL::SSLTestCase def test_client_auth_success vflag = OpenSSL::SSL::VERIFY_PEER|OpenSSL::SSL::VERIFY_FAIL_IF_NO_PEER_CERT - start_server(verify_mode: vflag) { |port| + start_server(verify_mode: vflag, + ctx_proc: proc { |ctx| + ctx.max_version = OpenSSL::SSL::TLS1_2_VERSION if libressl?(3, 2, 0) + }) { |port| ctx = OpenSSL::SSL::SSLContext.new ctx.key = @cli_key ctx.cert = @cli_cert @@ -253,6 +256,8 @@ class OpenSSL::TestSSL < OpenSSL::SSLTestCase end def test_client_ca + pend "LibreSSL 3.2 has broken client CA support" if libressl?(3, 2, 0) + ctx_proc = Proc.new do |ctx| ctx.client_ca = [@ca_cert] end @@ -793,11 +798,13 @@ class OpenSSL::TestSSL < OpenSSL::SSLTestCase def test_verify_hostname_on_connect ctx_proc = proc { |ctx| + san = "DNS:a.example.com,DNS:*.b.example.com" + san += ",DNS:c*.example.com,DNS:d.*.example.com" unless libressl?(3, 2, 2) exts = [ ["keyUsage", "keyEncipherment,digitalSignature", true], - ["subjectAltName", "DNS:a.example.com,DNS:*.b.example.com," \ - "DNS:c*.example.com,DNS:d.*.example.com"], + ["subjectAltName", san], ] + ctx.cert = issue_cert(@svr, @svr_key, 4, exts, @ca_cert, @ca_key) ctx.key = @svr_key } @@ -818,6 +825,7 @@ class OpenSSL::TestSSL < OpenSSL::SSLTestCase ["cx.example.com", true], ["d.x.example.com", false], ].each do |name, expected_ok| + next if name.start_with?('cx') if libressl?(3, 2, 2) begin sock = TCPSocket.new("127.0.0.1", port) ssl = OpenSSL::SSL::SSLSocket.new(sock, ctx) @@ -1501,12 +1509,13 @@ end end end - def test_ecdh_curves + def test_ecdh_curves_tls12 pend "EC is disabled" unless defined?(OpenSSL::PKey::EC) ctx_proc = -> ctx { # Enable both ECDHE (~ TLS 1.2) cipher suites and TLS 1.3 - ctx.ciphers = "DEFAULT:!kRSA:!kEDH" + ctx.max_version = OpenSSL::SSL::TLS1_2_VERSION + ctx.ciphers = "kEECDH" ctx.ecdh_curves = "P-384:P-521" } start_server(ctx_proc: ctx_proc, ignore_listener_error: true) do |port| @@ -1515,13 +1524,9 @@ end server_connect(port, ctx) { |ssl| cs = ssl.cipher[0] - if /\ATLS/ =~ cs # Is TLS 1.3 is used? + assert_match (/\AECDH/), cs + if ssl.respond_to?(:tmp_key) 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 ssl.puts "abc"; assert_equal "abc\n", ssl.gets } @@ -1545,6 +1550,26 @@ end end end + def test_ecdh_curves_tls13 + pend "EC is disabled" unless defined?(OpenSSL::PKey::EC) + pend "TLS 1.3 not supported" unless tls13_supported? + + ctx_proc = -> ctx { + # Assume TLS 1.3 is enabled and chosen by default + ctx.ecdh_curves = "P-384:P-521" + } + 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 + + server_connect(port, ctx) { |ssl| + assert_equal "TLSv1.3", ssl.ssl_version + assert_equal "secp384r1", ssl.tmp_key.group.curve_name + ssl.puts "abc"; assert_equal "abc\n", ssl.gets + } + end + end + def test_security_level ctx = OpenSSL::SSL::SSLContext.new begin diff --git a/test/test_ssl_session.rb b/test/test_ssl_session.rb index e199f86d..1d82aebf 100644 --- a/test/test_ssl_session.rb +++ b/test/test_ssl_session.rb @@ -122,6 +122,7 @@ __EOS__ 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 + ctx.max_version = OpenSSL::SSL::TLS1_2_VERSION if libressl?(3, 2, 0) } start_server(ctx_proc: ctx_proc) do |port| sess1 = server_connect_with_session(port, nil, nil) { |ssl| diff --git a/test/utils.rb b/test/utils.rb index bf191630..34c89a2e 100644 --- a/test/utils.rb +++ b/test/utils.rb @@ -181,6 +181,14 @@ class OpenSSL::SSLTestCase < OpenSSL::TestCase rescue end + def tls13_supported? + return false unless defined?(OpenSSL::SSL::TLS1_3_VERSION) + ctx = OpenSSL::SSL::SSLContext.new + ctx.min_version = ctx.max_version = OpenSSL::SSL::TLS1_3_VERSION + true + rescue + end + def readwrite_loop(ctx, ssl) while line = ssl.gets ssl.write(line) -- cgit v1.2.3 From 57707fb354a28c86a32a4b989fbe53e88c6d2a93 Mon Sep 17 00:00:00 2001 From: Kazuki Yamaguchi Date: Mon, 27 Sep 2021 00:58:45 +0900 Subject: .github/workflows: update OpenSSL/LibreSSL versions --- .github/workflows/test.yml | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 48f59c5f..604a2a53 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -74,10 +74,11 @@ jobs: - openssl-1.0.1u # EOL - openssl-1.0.2u # EOL - openssl-1.1.0l # EOL - - openssl-1.1.1j + - openssl-1.1.1l - libressl-2.5.5 # EOL - - libressl-3.1.5 - - libressl-3.2.0 + - libressl-3.1.5 # EOL + - libressl-3.2.6 + - libressl-3.3.4 steps: - name: repo checkout uses: actions/checkout@v2 -- cgit v1.2.3 From 202ff1372a40a8adf9aac74bfe8a39141b0c57e5 Mon Sep 17 00:00:00 2001 From: Kazuki Yamaguchi Date: Mon, 27 Sep 2021 00:38:38 +0900 Subject: ext/openssl/extconf.rb: require OpenSSL version >= 1.0.1, < 3 Ruby/OpenSSL 2.1.x and 2.2.x will not support OpenSSL 3.0 API. Let's make extconf.rb explicitly check the version number to be within the acceptable range, since it will not compile anyway. Reference: https://bugs.ruby-lang.org/issues/18192 --- ext/openssl/extconf.rb | 43 +++++++++++++++++++++++++------------------ 1 file changed, 25 insertions(+), 18 deletions(-) diff --git a/ext/openssl/extconf.rb b/ext/openssl/extconf.rb index 264130bb..7e817ae2 100644 --- a/ext/openssl/extconf.rb +++ b/ext/openssl/extconf.rb @@ -37,9 +37,6 @@ if $mswin || $mingw have_library("ws2_32") end -Logging::message "=== Checking for required stuff... ===\n" -result = pkg_config("openssl") && have_header("openssl/ssl.h") - def find_openssl_library if $mswin || $mingw # required for static OpenSSL libraries @@ -90,19 +87,33 @@ def find_openssl_library return false end -unless result - unless find_openssl_library - Logging::message "=== Checking for required stuff failed. ===\n" - Logging::message "Makefile wasn't created. Fix the errors above.\n" - raise "OpenSSL library could not be found. You might want to use " \ - "--with-openssl-dir= option to specify the prefix where OpenSSL " \ - "is installed." - end +Logging::message "=== Checking for required stuff... ===\n" +pkg_config_found = pkg_config("openssl") && have_header("openssl/ssl.h") + +if !pkg_config_found && !find_openssl_library + Logging::message "=== Checking for required stuff failed. ===\n" + Logging::message "Makefile wasn't created. Fix the errors above.\n" + raise "OpenSSL library could not be found. You might want to use " \ + "--with-openssl-dir= option to specify the prefix where OpenSSL " \ + "is installed." end -unless checking_for("OpenSSL version is 1.0.1 or later") { - try_static_assert("OPENSSL_VERSION_NUMBER >= 0x10001000L", "openssl/opensslv.h") } - raise "OpenSSL >= 1.0.1 or LibreSSL is required" +version_ok = if have_macro("LIBRESSL_VERSION_NUMBER", "openssl/opensslv.h") + is_libressl = true + checking_for("LibreSSL version >= 2.5.0") { + try_static_assert("LIBRESSL_VERSION_NUMBER >= 0x20500000L", "openssl/opensslv.h") } +else + checking_for("OpenSSL version >= 1.0.1 and < 3.0.0") { + try_static_assert("OPENSSL_VERSION_NUMBER >= 0x10001000L", "openssl/opensslv.h") && + !try_static_assert("OPENSSL_VERSION_MAJOR >= 3", "openssl/opensslv.h") } +end +unless version_ok + raise "OpenSSL >= 1.0.1, < 3.0.0 or LibreSSL >= 2.5.0 is required" +end + +# Prevent wincrypt.h from being included, which defines conflicting macro with openssl/x509.h +if is_libressl && ($mswin || $mingw) + $defs.push("-DNOCRYPT") end Logging::message "=== Checking for OpenSSL features... ===\n" @@ -114,10 +125,6 @@ engines.each { |name| OpenSSL.check_func_or_macro("ENGINE_load_#{name}", "openssl/engine.h") } -if ($mswin || $mingw) && have_macro("LIBRESSL_VERSION_NUMBER", "openssl/opensslv.h") - $defs.push("-DNOCRYPT") -end - # added in 1.0.2 have_func("EC_curve_nist2nid") have_func("X509_REVOKED_dup") -- cgit v1.2.3