Skip to content

Commit

Permalink
test: adjust test cases for LibreSSL 3.2.4
Browse files Browse the repository at this point in the history
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 a0e98d4 ("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.
  • Loading branch information
rhenium committed Feb 25, 2021
1 parent cde6e4a commit a9954ba
Show file tree
Hide file tree
Showing 5 changed files with 52 additions and 41 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
44 changes: 28 additions & 16 deletions test/openssl/test_ssl.rb
Original file line number Diff line number Diff line change
Expand Up @@ -458,11 +458,7 @@ def test_verify_result
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
Expand Down Expand Up @@ -930,7 +926,7 @@ def test_verify_hostname_on_connect
["keyUsage", "keyEncipherment,digitalSignature", true],
["subjectAltName", san],
]

ctx.cert = issue_cert(@svr, @svr_key, 4, exts, @ca_cert, @ca_key)
ctx.key = @svr_key
}
Expand Down Expand Up @@ -1015,7 +1011,7 @@ def test_connect_certificate_verify_failed_exception_message
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)
}
}
Expand Down Expand Up @@ -1617,13 +1613,13 @@ def test_connect_works_when_setting_dh_callback_to_nil
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|
Expand All @@ -1632,13 +1628,9 @@ def test_ecdh_curves

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
}
Expand All @@ -1662,6 +1654,26 @@ def test_ecdh_curves
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
Expand Down
2 changes: 0 additions & 2 deletions test/openssl/test_ts.rb
Original file line number Diff line number Diff line change
Expand Up @@ -387,15 +387,13 @@ def test_verify_ee_no_store
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)
end
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])
Expand Down
37 changes: 15 additions & 22 deletions test/openssl/test_x509store.rb
Original file line number Diff line number Diff line change
Expand Up @@ -32,17 +32,15 @@ def test_add_file_path
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
Expand Down Expand Up @@ -77,8 +75,8 @@ def test_verify_simple
# 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
Expand Down Expand Up @@ -188,7 +186,7 @@ def test_verify_purpose
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
Expand Down Expand Up @@ -284,7 +282,7 @@ def test_verify_with_crl
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
Expand Down Expand Up @@ -324,14 +322,9 @@ def test_verify_with_crl
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

Expand Down
8 changes: 8 additions & 0 deletions test/openssl/utils.rb
Original file line number Diff line number Diff line change
Expand Up @@ -196,6 +196,14 @@ def tls12_supported?
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)
Expand Down

0 comments on commit a9954ba

Please sign in to comment.