If an exception is raised by the SSLContext#servername_cb proc, the
handshake should be canceled by sending an "unrecognized_name" alert to
the client, and the exception should be re-raised from SSLSocket#accept.
Add more direct assertions to confirm these behaviors.
https://github.com/ruby/openssl/commit/ac8df7f30f
RHEL 9.7 ships OpenSSL 3.5.1 with ML-DSA support, but it is disabled
for TLS by default, according to the system configuration file:
/etc/crypto-policies/back-ends/opensslcnf.config
Specify SSLContext#sigalgs to override the default list.
https://github.com/ruby/openssl/commit/fac3a26748
Freeze OpenSSL::SSL::SSLContext::DEFAULT_PARAMS so that it becomes
Ractor-shareable.
Also, prepare a new OpenSSL::X509::Store in Ractor-local storage, if
called from a non-main Ractor. OpenSSL::X509::Store currently is not a
shareable object.
https://github.com/ruby/openssl/commit/3d5271327c
Rely on OpenSSL's builtin DH parameters for TLS 1.2 and earlier instead
of providing a default SSLContext#tmp_dh_callback proc.
SSL_CTX_set_dh_auto() has been available since OpenSSL 1.1.0.
The parameters can still be overridden by specifying
SSLContext#tmp_dh_callback or #tmp_dh, as confirmed by existing tests.
SSLContext#tmp_dh_callback depends on a deprecated OpenSSL feature. We
also prefer not to hard-code parameters, which is a maintenance burden.
This change also improves Ractor compatibility by removing the
unshareable proc.
https://github.com/ruby/openssl/commit/9cfec9bf5e
test_post_connect_check_with_anon_ciphers:
test_tmp_dh_callback:
test_tmp_dh:
DH missing the q value on unknown named parameters (ciphers) is not
FIPS-approved, according to the FIPS-186-4 APPENDIX B: Key Pair Generation -
B.1.1 Key Pair Generation Using Extra Random Bits, the inputs p, q, and g are
required. However, TLS doesn't send q.
https://csrc.nist.gov/pubs/fips/186-4/final
OpenSSL has a special workaround to recover the missing "q" value for known
named parameters, which is the reason why other tests that use the default
parameters in `lib/openssl/ssl.rb` are working.
Note that the test_post_connect_check_with_anon_ciphers test got the following error on
`OpenSSL.debug = true` in FIPS.
```
/home/jaruga/var/git/ruby/openssl/lib/openssl/ssl.rb:551: warning: error on stack: error:0A0C0103:SSL routines:tls_construct_server_key_exchange:internal error
```
test_get_ephemeral_key:
kRSA (PKCS1-v1_5 padding) is not allowed in FIPS according to the
NIST SP 800-131A Rev. 2 - 6 Key Agreement and Key Transport Using RSA -
Table 5: Approval Status for the RSA-based Key Agreement and Key Transport
Schemes - PKCS1-v1_5 padding - Disallowed after 2023
https://csrc.nist.gov/pubs/sp/800/131/a/r2/final
Note that the test_get_ephemeral_key test got the following error on
`OpenSSL.debug = true` in FIPS.
```
test/openssl/test_ssl.rb:2326: warning: error on stack: error:1C8000A8:Provider routines:rsa_encrypt:invalid padding mode
```
https://github.com/ruby/openssl/commit/ac3559e51e
The key files were created by the following commands.
```
$ ${HOME}/.local/openssl-3.6.0-dev-fips-debug-8253b58d60/bin/openssl genpkey \
-algorithm mldsa65 \
-out mldsa65-1.pem
$ ${HOME}/.local/openssl-3.6.0-dev-fips-debug-8253b58d60/bin/openssl genpkey \
-algorithm mldsa65 \
-out mldsa65-2.pem
```
PQC algorithms, ML-KEM (FIPS 203) and ML-DSA (FIPS 204) used in the PQC tests
are supported on OpenSSL 3.5 or later.
https://openssl-library.org/post/2025-04-08-openssl-35-final-release/https://github.com/ruby/openssl/commit/f3bb316018
TLS 1.3 renamed the "elliptic_curves" extension to "supported_groups"
to reflect that it now covers more than just ECDH groups. OpenSSL 1.1.1
followed this change by renaming the corresponding API from
SSL_CTX_set1_curves_list() to SSL_CTX_set1_groups_list().
Update ruby/openssl to use the new name, too. The current method name
SSLContext#ecdh_curves= is retained as an alias for #group=.
https://github.com/ruby/openssl/commit/59e98604e0
Add methods for setting supported signature algorithms, corresponding
to SSL_CTX_set1_sigalgs_list() and SSL_CTX_set1_client_sigalgs_list(),
respectively.
https://github.com/ruby/openssl/commit/6bbe58c492
Co-authored-by: Markus Jung <markus.jung@vivavis.com>
As reported in <https://github.com/ruby/ruby/pull/12823>,
check_supported_protocol_versions is unstable and occasionally fails
with Errno::ECONNABORTED during SSLSocket#connect on Windows.
When the server-side SSLContext specifies an unsupported SSL/TLS
protocol version, start_server accepts a TCP connection but closes it
without reading ClientHello, as SSLSocket#accept immediately raises an
exception. With Winsock, this can cause the client-side
SSLSocket#connect to raise Errno::ECONNABORTED.
While the simplest fix is to add rescue Errno::ECONNABORTED, this method
can be simplified. Instead, let's set up a server that accepts all
protocol versions and test client connections with different settings.
https://github.com/ruby/openssl/commit/aa7f03e18f
Starting with LibreSSL 3.5, OpenSSL::X509::ExtensionFactory refuses to
create SAN extensions that are not valid according to RFC 6125. While
this behavior makes sense, we need such invalid extensions to test our
own validation routine. Let's construct SAN extensions manually instead.
https://github.com/ruby/openssl/commit/b420d6d739
There are a few SSL discrepencies in AWS-LC when compared to OpenSSL.
1. AWS-LC has slightly different error messages (in all-caps).
2. AWS-LC has no support for DHE ciphersuites.
3. There are no concepts of SSL security levels within AWS-LC.
4. Similar to LibreSSL, there is no support for OPENSSL_CONF.
https://github.com/ruby/openssl/commit/a60d050342
OpenSSL::SSL::SSLContext#cert_store= uses SSL_CTX_set_cert_store(). The
store is used for verifying peer certificates and for building
certificate chains to be sent to the peer if there is no chain
explicitly provided by SSLContext#extra_chain_cert=.
Do not specify it in the common test helper start_server, as most
callers do not require either function. Instead, update individual test
cases that use client certificates to explicitly specify it in ctx_proc.
A more direct test case is added to verify the latter function.
https://github.com/ruby/openssl/commit/9daecee615
assert_handshake_error is useful for checking handshake failures
triggered by the peer, as the underlying socket may be closed
prematurely, leading to different exceptions depending on the platform
and timing.
However, when the local end aborts a handshake, the only possible
exception is OpenSSL::SSL::SSLError. Use stricter assertions in such
cases.
https://github.com/ruby/openssl/commit/637ba65818
The list of NPN protocols is validated in SSLContext#setup.
The assert_handshake_error is misleading. The client is unable to start
a handshake at all because the server is not running.
https://github.com/ruby/openssl/commit/e8db6ffd9e
Use start_server instead of start_server_version.
start_server_version is a wrapper around start_server that forces the
server to a specific protocol version using the now-deprecated method
SSLSocket#ssl_version=, but it does more than that. The slightly
different method signature and default values are confusing. Let's
use start_server directly.
https://github.com/ruby/openssl/commit/22ed31d77e
Make these methods simple wrappers around
SSL_CTX_set_{min,max}_proto_version().
When we introduced these methods in commit https://github.com/ruby/openssl/commit/18603949d316 [1], which went
to v2.1.0, we added a private method to SSLContext that set both the
minimum and maximum protocol versions at the same time. This was to
allow emulating the behavior using SSL options on older OpenSSL versions
that lack SSL_CTX_set_{min,max}_proto_version(). Since we no longer
support OpenSSL 1.0.2, the related code has already been removed.
In OpenSSL 1.1.1 or later, setting the minimum or maximum version to 0
is not equivalent to leaving it unset. Similar to SSL options, which we
avoid overwriting as of commit https://github.com/ruby/openssl/commit/00bec0d905d5 and commit https://github.com/ruby/openssl/commit/77c3db2d6587 [2],
a system-wide configuration file may define a default protocol version
bounds. Setting the minimum version should not unset the maximum
version, and vice versa.
[1] https://github.com/ruby/openssl/pull/142
[2] https://github.com/ruby/openssl/pull/767https://github.com/ruby/openssl/commit/5766386321
Commit https://github.com/ruby/openssl/commit/3bbf5178a90e made blocking methods on SSLSocket follow the
IO#timeout= value. The commit changed io_wait_readable() to potentially
raise an exception without unlocking the String.
The String is currently locked for the entire duration of a #sysread
method call. This does not seem to be necessary, as SSL_read() does not
require that the same buffer is specified when retrying. Locking the
String during each SSL_read() call should be sufficient.
https://github.com/ruby/openssl/commit/8f791d73f5
Drop support for OpenSSL 1.1.0. OpenSSL 1.1.0 was a non-LTS release and
it has reached upstream EOL in 2019-12 along with OpenSSL 1.0.2.
Distributions that shipped with OpenSSL 1.1.0 include:
- Debian 9 (EOL 2022-06)
- Ubuntu 18.04 LTS (EOL 2023-04)
https://github.com/ruby/openssl/commit/ba83abe920
Apply SSL options set in DEFAULT_PARAMS without clearing existing
options.
It currently clears options in order to avoid setting one of the
options included in OpenSSL::SSL::OP_ALL unless explicitly specified,
namely OpenSSL::SSL::OP_DONT_INSERT_EMPTY_FRAGMENTS. Now that
OpenSSL::SSL::OP_ALL has been removed from SSLContext#initialize, it is
no longer necessary.
https://github.com/ruby/openssl/commit/77c3db2d65
Respect the SSL options set by default by SSL_CTX() and by the
system-wide OpenSSL configuration file.
OpenSSL::SSL::SSLContext#initialize currently adds OpenSSL::SSL::OP_ALL
on top of the default SSL options. Let's stop doing it.
OpenSSL::SSL::OP_ALL is a set of options that changes OpenSSL's behavior
to workaround various TLS implementation bugs. Using it is considered
usually safe, but is not completely harmless.
https://github.com/ruby/openssl/commit/00bec0d905
When compiled with OpenSSL <= 1.1.1, OpenSSL::SSL::SSLContext#setup
does not raise an exception on an error return from
SSL_CTX_load_verify_locations(), but instead only prints a verbose-mode
warning. This is not helpful since it very likely indicates an actual
error, such as the specified file not being readable.
Also, OpenSSL's error queue is not correctly cleared:
$ ruby -w -ropenssl -e'OpenSSL.debug=true; ctx=OpenSSL::SSL::SSLContext.new; ctx.ca_file="bad-path"; ctx.setup; pp OpenSSL.errors'
-e:1: warning: can't set verify locations
["error:02001002:system library:fopen:No such file or directory",
"error:2006D080:BIO routines:BIO_new_file:no such file",
"error:0B084002:x509 certificate routines:X509_load_cert_crl_file: system lib"]
The behavior is currently different when compiled with OpenSSL >= 3.0:
SSLError is raised if SSL_CTX_load_verify_file() or
SSL_CTX_load_verify_dir() fails.
This inconsistency was unintentionally introduced by commit https://github.com/ruby/openssl/commit/5375a55ffc35
("ssl: use SSL_CTX_load_verify_{file,dir}() if available", 2020-02-22).
However, raising SSLError seems more appropriate in this situation.
Let's adjust the OpenSSL <= 1.1.1 code so that it behaves the same way
as the OpenSSL >= 3.0 code currently does.
Fixes: https://github.com/ruby/openssl/issues/649https://github.com/ruby/openssl/commit/7eb10f7b75
As noted in commit https://github.com/ruby/openssl/commit/a2ed156cc9f1 ("test/test_ssl: do not run NPN tests
for LibreSSL >= 2.6.1", 2017-08-13), NPN is known not to work properly
on LibreSSL.
Disable NPN support on LibreSSL, whether OPENSSL_NO_NEXTPROTONEG is
defined or not.
NPN is less relevant today anyway. Let's also silence test suite when
it's not available.
https://github.com/ruby/openssl/commit/289f6e0e1f
- This callback is invoked when TLS key material is generated or
received, in order to allow applications to store this keying material
for debugging purposes.
- It is invoked with an `SSLSocket` and a string containing the key
material in the format used by NSS for its SSLKEYLOGFILE debugging
output.
- This commit adds the Ruby binding `keylog_cb` and the related tests
- It is only compatible with OpenSSL >= 1.1.1. Even if LibreSSL implements
`SSL_CTX_set_keylog_callback()` from v3.4.2, it does nothing (see
648d39f0f0)
https://github.com/ruby/openssl/commit/3b63232cf1
RFC 6066 states how some wildcard SAN entries MAY be handled, but
it does not say they MUST be handled. LibreSSL 3.5.0 only handles
suffix wildcard SANs, not prefix wildcard SANs, or interior
wildcard SANs, so return early from the wildcard SAN tests on
LibreSSL 3.5.0.
Fixes#471https://github.com/ruby/openssl/commit/717d7009d6