From a9954bac22ba8d9f9491732f3816bc1316eaa088 Mon Sep 17 00:00:00 2001 From: Kazuki Yamaguchi Date: Thu, 25 Feb 2021 17:28:23 +0900 Subject: test: adjust test cases for LibreSSL 3.2.4 LibreSSL 3.2.4 made the certificate verification logic back closer to pre-3.2.2 one, which is more compatible with OpenSSL. Part of the fixes added by commit a0e98d48c91f ("Enhance TLS 1.3 support on LibreSSL 3.2/3.3", 2020-12-03) is required for 3.2.2 and 3.2.3 only (and ~3.3.1, however 3.3 does not have a stable release yet). Since both releases are security fix, it should be safe to remove those special treatment from our test suite. While we are at it, TestSSL#test_ecdh_curves is split into TLS 1.2 and TLS 1.3 variants for clarity. --- .github/workflows/test.yml | 2 +- test/openssl/test_ssl.rb | 44 +++++++++++++++++++++++++++--------------- test/openssl/test_ts.rb | 2 -- test/openssl/test_x509store.rb | 37 ++++++++++++++--------------------- test/openssl/utils.rb | 8 ++++++++ 5 files changed, 52 insertions(+), 41 deletions(-) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 6d19e992..4ada7066 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -77,7 +77,7 @@ jobs: - openssl-1.1.1j - libressl-2.9.2 # EOL - libressl-3.1.5 - - libressl-3.2.0 + - libressl-3.2.4 steps: - name: repo checkout uses: actions/checkout@v2 diff --git a/test/openssl/test_ssl.rb b/test/openssl/test_ssl.rb index 750d64fa..50a16029 100644 --- a/test/openssl/test_ssl.rb +++ b/test/openssl/test_ssl.rb @@ -458,11 +458,7 @@ class OpenSSL::TestSSL < OpenSSL::SSLTestCase ssl.sync_close = true begin assert_raise(OpenSSL::SSL::SSLError){ ssl.connect } - assert_include( - [ - OpenSSL::X509::V_ERR_SELF_SIGNED_CERT_IN_CHAIN, - OpenSSL::X509::V_ERR_UNABLE_TO_GET_ISSUER_CERT_LOCALLY - ], ssl.verify_result) + assert_equal(OpenSSL::X509::V_ERR_SELF_SIGNED_CERT_IN_CHAIN, ssl.verify_result) ensure ssl.close end @@ -930,7 +926,7 @@ class OpenSSL::TestSSL < OpenSSL::SSLTestCase ["keyUsage", "keyEncipherment,digitalSignature", true], ["subjectAltName", san], ] - + ctx.cert = issue_cert(@svr, @svr_key, 4, exts, @ca_cert, @ca_key) ctx.key = @svr_key } @@ -1015,7 +1011,7 @@ class OpenSSL::TestSSL < OpenSSL::SSLTestCase start_server(ignore_listener_error: true) { |port| ctx = OpenSSL::SSL::SSLContext.new ctx.set_params - assert_raise_with_message(OpenSSL::SSL::SSLError, /self signed|unable to get local issuer certificate/) { + assert_raise_with_message(OpenSSL::SSL::SSLError, /self signed/) { server_connect(port, ctx) } } @@ -1617,13 +1613,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 if libressl?(3, 2, 0) + 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| @@ -1632,13 +1628,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 } @@ -1662,6 +1654,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/openssl/test_ts.rb b/test/openssl/test_ts.rb index 5c2d43eb..8e31a7d2 100644 --- a/test/openssl/test_ts.rb +++ b/test/openssl/test_ts.rb @@ -387,7 +387,6 @@ _end_of_pem_ end def test_verify_ee_wrong_root_no_intermediate - pend "LibreSSL 3.2.2 Timestamp Issue" if libressl?(3, 2, 2) assert_raise(OpenSSL::Timestamp::TimestampError) do ts, req = timestamp_ee ts.verify(req, intermediate_store) @@ -395,7 +394,6 @@ _end_of_pem_ end def test_verify_ee_wrong_root_wrong_intermediate - pend "LibreSSL 3.2.2 Timestamp Issue" if libressl?(3, 2, 2) assert_raise(OpenSSL::Timestamp::TimestampError) do ts, req = timestamp_ee ts.verify(req, intermediate_store, [ca_cert]) diff --git a/test/openssl/test_x509store.rb b/test/openssl/test_x509store.rb index 897f0f8b..d6c0e707 100644 --- a/test/openssl/test_x509store.rb +++ b/test/openssl/test_x509store.rb @@ -32,17 +32,15 @@ class OpenSSL::TestX509Store < OpenSSL::TestCase assert_equal true, store.verify(cert1) assert_equal true, store.verify(cert2) - unless libressl?(3, 2, 2) - # X509::Store#add_path - Dir.mktmpdir do |dir| - hash1 = "%08x.%d" % [cert1_subj.hash, 0] - File.write(File.join(dir, hash1), cert1.to_pem) - store = OpenSSL::X509::Store.new - store.add_path(dir) - - assert_equal true, store.verify(cert1) - assert_equal false, store.verify(cert2) - end + # X509::Store#add_path + Dir.mktmpdir do |dir| + hash1 = "%08x.%d" % [cert1_subj.hash, 0] + File.write(File.join(dir, hash1), cert1.to_pem) + store = OpenSSL::X509::Store.new + store.add_path(dir) + + assert_equal true, store.verify(cert1) + assert_equal false, store.verify(cert2) end # OpenSSL < 1.1.1 leaks an error on a duplicate certificate @@ -77,8 +75,8 @@ class OpenSSL::TestX509Store < OpenSSL::TestCase # Nothing trusted store = OpenSSL::X509::Store.new assert_equal(false, store.verify(ee1_cert, [ca2_cert, ca1_cert])) - assert_include([OpenSSL::X509::V_ERR_SELF_SIGNED_CERT_IN_CHAIN, OpenSSL::X509::V_ERR_UNABLE_TO_GET_ISSUER_CERT_LOCALLY], store.error) - assert_match(/self.signed|unable to get local issuer certificate/i, store.error_string) + assert_equal(OpenSSL::X509::V_ERR_SELF_SIGNED_CERT_IN_CHAIN, store.error) + assert_match(/self.signed/i, store.error_string) # CA1 trusted, CA2 missing store = OpenSSL::X509::Store.new @@ -188,7 +186,7 @@ class OpenSSL::TestX509Store < OpenSSL::TestCase store.purpose = OpenSSL::X509::PURPOSE_CRL_SIGN store.add_cert(ca1_cert) assert_equal(true, store.verify(ca1_cert)) - assert_equal(libressl?(3, 2, 2), store.verify(ee1_cert)) + assert_equal(false, store.verify(ee1_cert)) end def test_verify_validity_period @@ -284,7 +282,7 @@ class OpenSSL::TestX509Store < OpenSSL::TestCase store.flags = OpenSSL::X509::V_FLAG_CRL_CHECK store.add_cert(ca1_cert) assert_equal(false, store.verify(ca2_cert)) - assert_include([OpenSSL::X509::V_ERR_UNABLE_TO_GET_CRL, OpenSSL::X509::V_ERR_UNSPECIFIED], store.error) + assert_equal(OpenSSL::X509::V_ERR_UNABLE_TO_GET_CRL, store.error) # Intermediate CA revoked EE2 store = OpenSSL::X509::Store.new @@ -324,14 +322,9 @@ class OpenSSL::TestX509Store < OpenSSL::TestCase store.add_cert(ca2_cert) store.add_crl(ca1_crl1) store.add_crl(ca2_crl2) # issued by ca2 but expired - if libressl?(3, 2, 2) - assert_equal(false, store.verify(ca2_cert)) - assert_include([OpenSSL::X509::V_ERR_CRL_SIGNATURE_FAILURE, OpenSSL::X509::V_ERR_UNSPECIFIED], store.error) - else - assert_equal(true, store.verify(ca2_cert)) - end + assert_equal(true, store.verify(ca2_cert)) assert_equal(false, store.verify(ee1_cert)) - assert_include([OpenSSL::X509::V_ERR_CRL_HAS_EXPIRED, OpenSSL::X509::V_ERR_UNSPECIFIED], store.error) + assert_equal(OpenSSL::X509::V_ERR_CRL_HAS_EXPIRED, store.error) assert_equal(false, store.verify(ee2_cert)) end diff --git a/test/openssl/utils.rb b/test/openssl/utils.rb index c1d737b2..8ee01164 100644 --- a/test/openssl/utils.rb +++ b/test/openssl/utils.rb @@ -196,6 +196,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