Commit graph

648 commits

Author SHA1 Message Date
Kazuki Yamaguchi
a61c16ba42 [ruby/openssl] pkey: simplify X25519/Ed25519 test cases
When these test cases were written, we did not know the exact OpenSSL
and LibreSSL version number in which they would be implemented. Now that
we know it, we can use that information to ensure the tests are run
whenever they should be.

 - OpenSSL 1.1.0 added X25519 support
 - OpenSSL 1.1.1 added Ed25519 support and
   EVP_PKEY_new_raw_private_key()
 - LibreSSL 3.7.0 added X25519 and Ed25519 support in EVP_PKEY and
   EVP_PKEY_new_raw_private_key()
 - LibreSSL 3.8.1 allowed ASN1_item_sign() to use Ed25519

6cb6663c91
2025-01-06 17:07:57 +00:00
Kazuki Yamaguchi
3da850104e [ruby/openssl] pkey: fix test case for new_raw_*key
Method names must start with "test_" to run.

fed9d09b76
2025-01-06 17:07:57 +00:00
Kazuki Yamaguchi
ff708f86fa [ruby/openssl] pkey/ec: use heredoc for invalid key example in test cases
test/openssl/fixtures/pkey/p256_too_large.pem and p384_invalid.pem are
invalid keys where the encoded public key doesn't match the private key.
They are only useful for test cases for OpenSSL::PKey::EC#check_key and
will not be reused elsewhere. Let's directly include the PEM encoding
as a heredoc for clarity.

p384_invalid.pem is dropped because it is redundant.

2f807ff30f
2025-01-06 17:07:56 +00:00
Kazuki Yamaguchi
f0095413a5 [ruby/openssl] x509cert: simplify test cases for Certificate.load_file
Remove files from test/openssl/fixtures/pkey/ which are not pkeys.
The test cases for OpenSSL::X509::Certificate.load_file can simply use
issue_cert and Tempfile.

11216b8bec
2025-01-06 17:07:56 +00:00
samuel40791765
5412501e36 [ruby/openssl] pkey: Use openssl generated pkcs8 key instead
6a6fac9958
2025-01-06 14:04:58 +00:00
Kazuki Yamaguchi
2a3f2412b7 [ruby/openssl] ssl: fix flaky test case test_ctx_client_session_cb_tls13_exception
In the test case, the client raises an exception in the session_new_cb
and may not cleanly close the connection. Let's ignore exceptions raised
at the server side.

Fixes: https://github.com/ruby/openssl/issues/828

210ba0334a
2024-12-22 03:33:03 +09:00
Kazuki Yamaguchi
637f019f1f [ruby/openssl] cipher: make output buffer String independent
OpenSSL::Cipher#update accepts a String as the second argument to be
used as the output buffer. The buffer must be directly writable, in
other words, it must not be frozen and not a shared string.

rb_str_resize() does not make the String independent if the String
already has the intended length. Use the rb_str_modify() family instead
to check it.

Fixes: https://bugs.ruby-lang.org/issues/20937

1de3b80a46
2024-12-22 03:33:03 +09:00
Kazuki Yamaguchi
c79b435407 [ruby/openssl] pkcs12: add PKCS12#set_mac
Add a binding for PKCS12_set_mac() to set MAC parameters and
(re-)calculate MAC for the content.

This allows generating PKCS #12 with consistent MAC parameters with
different OpenSSL versions. OpenSSL 3.0 changed the default hash
function used for HMAC and the KDF from SHA-1 to SHA-256.

Fixes: https://github.com/ruby/openssl/issues/772

f5ed2a74b6
2024-12-22 03:33:03 +09:00
Kazuki Yamaguchi
c9bbf7e3eb [ruby/openssl] ssl: do not clear existing SSL options in SSLContext#set_params
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.

77c3db2d65
2024-12-07 08:15:08 +00:00
Kazuki Yamaguchi
510c190739 [ruby/openssl] ssl: do not enable OpenSSL::SSL::OP_ALL by default
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.

00bec0d905
2024-12-07 08:15:08 +00:00
HoneyryderChuck
5444885726 [ruby/openssl] make configs shareable when frozen
654cb22e21
2024-12-07 07:52:02 +00:00
HoneyryderChuck
2a006fe54b [ruby/openssl] make config frozen on initialize
50599513cf
2024-12-07 07:52:01 +00:00
Kazuki Yamaguchi
06fc13a15c [ruby/openssl] ssl: handle callback exceptions in SSLSocket#sysread and #syswrite
Check the ID_callback_state ivar after SSL_read() or SSL_write()
returns, similar to what ossl_start_ssl() does.

Previously, callbacks that can raise a Ruby exception were only called
from ossl_start_ssl(). This has changed in OpenSSL 1.1.1. Particularly,
the session_new_cb will be called whenever a client receives a
NewSessionTicket message, which can happen at any time during a TLS 1.3
connection.

aac9ce1304
2024-12-07 07:37:32 +00:00
Josh Cooper
b4d13fac3d [ruby/openssl] Support signing CRLs using Ed25519
Allow CRLs to be signed using Ed25519 private keys by passing a nil digest.

b62375bcde
2024-11-22 17:26:03 +00:00
Josh Cooper
6389c9a395 [ruby/openssl] Support signing requests using Ed25519
Allow requests to be signed using Ed25519 private keys by passing a nil digest.
This is similar to commit b0fc100091 when signing certs.

Calling PKey#public_key is deprecated and does not work for Ed25519. The same
can be accomplished by passing the private key.

d96090320d
2024-11-22 17:26:02 +00:00
Josh Cooper
ce4906efb3 [ruby/openssl] Check for compatible openssl versions earlier
test_pkey wasn't checking for libressl as is done elsewhere.

Note the libressl version check is different when testing pkey, because
PKey#sign relies on EVP_PKey_sign, whereas signing an X509 cert/request/crl
relies on ASN1_item_sign.

f1db5c88a2
2024-11-22 17:26:02 +00:00
Kazuki Yamaguchi
a0f1f16145 asn1: fix ObjectId#==
Compare by the dotted decimal notation rather than the NID.

OpenSSL::ASN1::ObjectId can store OIDs that are not registered in
OpenSSL's internal table. NID is not defined for such an OID, but it is
not an error.

The == method also should not raise TypeError if the other object is
not an instance of OpenSSL::ASN1::ObjectId.

Fixes: https://github.com/ruby/openssl/issues/791
2024-11-14 11:21:39 +09:00
Kazuki Yamaguchi
419fb2f3b9 [ruby/openssl] x509: fix handling of multiple URIs in Certificate#crl_uris
The implementation of OpenSSL::X509::Certificate#crl_uris makes the
assumption that each DistributionPoint in the CRL distribution points
extension contains a single general name of type URI. This is not
guaranteed by RFC 5280. A DistributionPoint may contain zero or more
than one URIs.

Let's include all URIs found in the extension. If only non-URI pointers
are found, return nil.

Fixes: https://github.com/ruby/openssl/issues/775

71f4fef2fa
2024-11-14 11:21:39 +09:00
Kazuki Yamaguchi
97be56fc62 [ruby/openssl] test_x509cert.rb: break up test_extension into smaller units
test_extesion is testing too many features at once and is hard to
navigate. Let's split each chunk apart for more clarity.

461cfcb070
2024-11-14 11:21:39 +09:00
HoneyryderChuck
2335768437 [ruby/openssl] make bn shareable when frozen
d3c8e661e8
2024-11-13 07:25:51 +00:00
Kazuki Yamaguchi
27d77a9c73 [ruby/openssl] pkcs7: remove default cipher from PKCS7.encrypt
Require that users explicitly specify the desired algorithm. In my
opinion, we are not in a position to specify the default cipher.

When OpenSSL::PKCS7.encrypt is given only two arguments, it uses
"RC2-40-CBC" as the symmetric cipher algorithm. 40-bit RC2 is a US
export-grade cipher and considered insecure.

Although this is technically a breaking change, the impact should be
minimal. Even when OpenSSL is compiled with RC2 support and the macro
OPENSSL_NO_RC2 is not defined, it will not actually work on modern
systems because RC2 is part of the legacy provider.

439f456bfa
2024-10-31 08:31:16 +00:00
Jun Aruga
ad742de79b [ruby/openssl] Fix test_provider.rb in FIPS.
7bdbc52100
2024-09-06 16:58:18 +00:00
Jun Aruga
2e5680d304 [ruby/openssl] Fix test_pkey_rsa.rb in FIPS.
* test_sign_verify
  I created the signature text (`signature_encoded.txt`), that is used as a
  text to create the `signature0` in the `test_sign_verify` by the following
  steps with the `openssl` CLI on FIPS module.
  ```
  $ OPENSSL_DIR="${HOME}/.local/openssl-3.4.0-dev-fips-debug-3c6e114959"
  $ export OPENSSL_CONF="${OPENSSL_DIR}/ssl/openssl_fips.cnf"

  $ echo -n "Sign me!" > data.txt
  $ "${OPENSSL_DIR}/bin/openssl" dgst -sha256 -sign test/openssl/fixtures/pkey/rsa2048.pem data.txt > signature.txt
  $ cat signature.txt | base64 > signature_encoded.txt
  ```

091f3eb421
2024-09-05 08:41:30 +00:00
Hiroshi SHIBATA
1515353353 Make optional benchmark test in OpenSSL::OSSL#test_memcmp_timing 2024-08-29 17:37:44 +09:00
Jun Aruga
1917c8c8f3 [ruby/openssl] Remove test_ed25519_not_approved_on_fips.
This commit fixes the following failure on OpenSSL master FIPS case.

```
1) Failure: test_ed25519_not_approved_on_fips(OpenSSL::TestPKey): OpenSSL::PKey::PKeyError expected but nothing was raised.
/home/runner/work/openssl/openssl/vendor/bundle/ruby/3.0.0/gems/test-unit-ruby-core-1.0.6/lib/core_assertions.rb:462:in `assert_raise'
/home/runner/work/openssl/openssl/test/openssl/test_pkey.rb:174:in `test_ed25519_not_approved_on_fips'
     171:     MC4CAQAwBQYDK2VwBCIEIEzNCJso/5banbbDRuwRTg9bijGfNaumJNqM9u1PuKb7
     172:     -----END PRIVATE KEY-----
     173:     EOF
  => 174:     assert_raise(OpenSSL::PKey::PKeyError) do
     175:       OpenSSL::PKey.read(priv_pem)
     176:     end
     177:   end
```

Because FIPS compliance is a continually moving target. According to the [1],
FIPS 140-3 *currently* allows ED25519. The ED25519 is allowed again with the
latest OpenSSL FIPS by the commit [2], while it is not allowed in OpenSSL stable
version 3.x FIPS.

Remove this test because we want to keep our tests stable.

[1] https://github.com/openssl/openssl/discussions/22054
[2] 5f04124aab

d43904b834
2024-08-16 17:10:23 +00:00
Jun Aruga
08db4bc672 [ruby/openssl] test_s_generate_parameters: Consider a DSA error in FIPS.
DSA kengen is not FIPS-approved. The `EVP_PKEY_paramgen` in the
`OpenSSL::PKey.generate_parameters("DSA")` raises a DSA error in FIPS by the
following commit. Split the test for DSA.

49a35f0 (diff-605396c063194975af8ce31399d42690ab18186b422fb5012101cc9132660fe1R611-R614)

5ca6eb4eca
2024-08-16 06:09:15 +00:00
Kazuki Yamaguchi
65e3717db7 [ruby/openssl] test/openssl/test_pkey_dsa.rb: skip all tests in FIPS mode
OpenSSL running in the FIPS mode will stop supporting DSA key
generation and signature generation due to a FIPS 140-3 requirement.
Although it appears that FIPS 186-5 still allows signature
verification in some cases, there would be little point in writing such
a specific test case.

DSA will still be tested if OpenSSL is not running in the FIPS mode.

test_generate_on_non_fips is merged to test_generate again.

3651884fd2
2024-08-06 06:38:03 +00:00
Kazuki Yamaguchi
a1cf39bd36 [ruby/openssl] x509attr: avoid using OpenSSL::ASN1 internals in #value=
OpenSSL::ASN1 is being rewritten in Ruby. To make it easier, let's
remove dependency to the instance variables and the internal-use
function ossl_asn1_get_asn1type() outside OpenSSL::ASN1.

This also fixes the insufficient validation of the passed value with
its tagging.

35a157462e
2024-07-24 16:50:01 +00:00
Grant Gardner
4d4ac00123 [ruby/openssl] Add SSLSocket#readbyte
Companion to getbyte but raise EOFError
Similar to https://github.com/ruby/openssl/pull/438

c40f70711a
2024-07-03 08:54:18 +00:00
gartens
c735f4947e [ruby/openssl] Pass through nil as digest when signing certificates
(https://github.com/ruby/openssl/pull/761)

In order to sign certificates with Ed25519 keys, NULL must be passed
as md to X509_sign.  This NULL is then passed
(via ASN1_item_sign_ex) as type to EVP_DigestSignInit.  The
documentation[1] of EVP_DigestSignInit states that type must be NULL
for various key types, including Ed25519.

[1]: https://www.openssl.org/docs/manmaster/man3/EVP_DigestSignInit.html

b0fc100091
2024-06-11 17:12:28 +00:00
Samuel Giddins
0b92929e52 [ruby/openssl] Add X509::Certificate#tbs_bytes
Ref https://github.com/ruby/openssl/issues/519

This makes verifying embedded certificate transparency signatures
significantly easier, as otherwise the alternative was manipulating the
ASN1 sequence, as in
656d992fa8

99128bea5d
2024-06-08 10:57:02 +00:00
KJ Tsanaktsidis
63e9eaa5be [ruby/openssl] Fix test_create_with_mac_iter accidently setting keytype not maciter
This test was accidentally passing the value 2048 into the keytype
parameter of PKCS12_create, not the mac_iter parameter (because it had
one too many `nil`s in the call). This value is invalid, and will make
OpenSSL perform an out-of-bounds read which is caught when compiling
with ASAN.

This commit fixes the tests, and also adds some validation to
PKCS12.create to make sure any keytype passed is actually valid. Since
there only two valid keytype constants, and the whole feature is an
export-grade crypto era thing only ever supported by old MSIE, it seems
far more likely that code in the whild is using keytype similarly by
mistake rather than as intended. So this validation might catch that.

47028686d2
2024-06-05 00:45:53 +00:00
Samuel Giddins
841b45a442 [ruby/openssl] Add to_text for PKCS7 and Timestamp::Response
71cd1e3f5c
2024-05-08 09:39:13 +00:00
Jean Boussier
7d42010fad [ruby/openssl] read: don't clear buffer when nothing can be read
To be consistent with regular Ruby IOs:

```ruby
r, _ = IO.pipe
buf = "garbage".b
r.read_nonblock(10, buf, exception: false) # => :wait_readable
p buf # => "garbage"
```

Ref: 98b8944460

08452993d6
2024-05-05 08:00:00 +00:00
Jeremy Evans
55720f372d [ruby/openssl] pkcs7: raise PKCS7Error for PKCS7 without content in PKCS7.read_smime
[pkuzco: expanded the fix for other content types]
[ky: adjusted formatting and the exception type]

07eceb7f63

Co-authored-by: pkuzco <b.naamneh@gmail.com>
Co-authored-by: Kazuki Yamaguchi <k@rhe.jp>
2024-05-02 16:26:11 +09:00
Jeremy Evans
c9aa63a9e0 [ruby/openssl] pkcs7: raise ArgumentError for PKCS7 with no content in PKCS7.new
Fixes [Bug #19974]

[pkuzco: expanded the fix for other content types]
[ky: adjusted formatting and the exception type]

27e11f2d1d

Co-authored-by: pkuzco <b.naamneh@gmail.com>
Co-authored-by: Kazuki Yamaguchi <k@rhe.jp>
2024-05-02 16:26:11 +09:00
Kazuki Yamaguchi
eb6f0000a4 [ruby/openssl] cipher: fix buffer overflow in Cipher#update
OpenSSL::Cipher#update currently allocates the output buffer with size
(input data length)+(the block size of the cipher). This is insufficient
for the id-aes{128,192,256}-wrap-pad (AES keywrap with padding) ciphers.
They have a block size of 8 bytes, but the output may be up to 15 bytes
larger than the input.

Use (input data length)+EVP_MAX_BLOCK_LENGTH (== 32) as the output
buffer size, instead. OpenSSL doesn't provide a generic way to tell the
maximum required buffer size for ciphers, but this is large enough for
all algorithms implemented in current versions of OpenSSL.

Fixes: https://bugs.ruby-lang.org/issues/20236

3035559f54
2024-05-02 16:26:11 +09:00
Peter Zhu
e0949c3f7c [ruby/openssl] Remove trailing space in test_ssl.rb
911a31335f
2024-04-30 15:23:15 +00:00
Bart de Water
cc6657e563 [ruby/openssl] Add OpenSSL::Digest.digests to get a list of available digests
08dd3c73b7
2024-04-30 15:05:50 +00:00
Samuel Williams
1699772ac4 [ruby/openssl] Introduce basic support for close_read and close_write.
c99d24cee9
2024-04-30 14:51:58 +00:00
Job Snijders
6b120135af [ruby/openssl] Only CSR version 1 (encoded as 0) is allowed by PKIX standards
RFC 2986, section 4.1 only defines version 1 for CSRs. This version
is encoded as a 0. Starting with OpenSSL 3.3, setting the CSR version
to anything but 1 fails.

Do not attempt to generate a CSR with invalid version (which now fails)
and invalidate the CSR in test_sign_and_verify_rsa_sha1 by changing its
subject rather than using an invalid version.

This commit fixes the following error.

```
 2) Error: test_version(OpenSSL::TestX509Request): OpenSSL::X509::RequestError:
X509_REQ_set_version: passed invalid argument
/home/runner/work/openssl/openssl/test/openssl/test_x509req.rb:18:in `version='
/home/runner/work/openssl/openssl/test/openssl/test_x509req.rb:18:in `issue_csr'
/home/runner/work/openssl/openssl/test/openssl/test_x509req.rb:43:in
`test_version'
     40:     req = OpenSSL::X509::Request.new(req.to_der)
     41:     assert_equal(0, req.version)
     42:
  => 43:     req = issue_csr(1, @dn, @rsa1024, OpenSSL::Digest.new('SHA256'))
     44:     assert_equal(1, req.version)
     45:     req = OpenSSL::X509::Request.new(req.to_der)
     46:     assert_equal(1, req.version)
```

c06fdeb091
2024-04-26 16:55:15 +00:00
Hiroshi SHIBATA
7630a89a4b Use www.rfc-editor.org for RFC text.
We use the following site for that now:

* https://tools.ietf.org/ or http
* https://datatracker.ietf.org or http

Today, IETF said the official site of RFC is www.rfc-editor.org.

FYI: https://authors.ietf.org/en/references-in-rfcxml

I replaced them to www.rfc-editor.org.
2024-03-28 11:44:45 +09:00
Jun Aruga
8896ac0289
[ruby/openssl] Fix test_pkey_dsa.rb in FIPS.
Note that I created the `dsa2048.pem` and signature text
(`signature_encoded.txt`), that is used as a text to create the `signature0` in
the `test_sign_verify` by the following steps with the `openssl` CLI on FIPS
module.

```
$ OPENSSL_DIR="${HOME}/.local/openssl-3.3.0-dev-fips-debug-1f03d33ef5"
$ export OPENSSL_CONF="${OPENSSL_DIR}/ssl/openssl_fips.cnf"

$ "${OPENSSL_DIR}/bin/openssl" dsaparam -out dsaparam2048.pem 2048
$ "${OPENSSL_DIR}/bin/openssl" gendsa -out dsa2048.pem dsaparam2048.pem

$ echo -n "Sign me!" > data.txt
$ "${OPENSSL_DIR}/bin/openssl" dgst -sha256 -sign dsa2048.pem data.txt > signature.txt
$ cat signature.txt | base64 > signature_encoded.txt
```

Skip the `test_DSAPrivateKey_encrypted` on FIPS because AES-128-CBC, the
password based encryption used in the PEM format uses MD5 for deriving the
encryption key from the password, and MD5 is not FIPS-approved.
See also the comment on the `test/openssl/utils.rb#omit_on_fips`.

4bdcb419a9
2024-03-27 12:16:11 +09:00
Jun Aruga
eb4082284a [ruby/openssl] test_provider.rb: Make a legacy provider test optional.
In some cases such as OpenSSL package in FreeBSD[1], the legacy provider is not
installed intentionally. So, we omit a test depending the legacy provider if the
legacy provider is not loadable.

For the test_openssl_provider_names test, we use base provider[2] instead of
legacy provider, because we would expect the base provider is always loadable
in OpenSSL 3 for now.

* [1] https://www.freshports.org/security/openssl/
* [2] https://wiki.openssl.org/index.php/OpenSSL_3.0#Providers

7223da7730
2024-03-13 15:47:27 +00:00
Jun Aruga
171791426b [ruby/openssl] Revert "omit tests related legacy provider"
This reverts commit 9b7543d588.

The case not providing the legacy provider can happen not only in FreeBSD but
also in other platforms. The fix is addressed in the next commit.

8c26fc26a1
2024-03-13 15:47:26 +00:00
Jun Aruga
dd5e625d7b [ruby/openssl] test_asn1.rb: Remove the assertions of the time string format without second.
This commit fixes the following errors in the tests.
Because the OpenSSL project changed the code to make the time string format
without second invalid. So, we drop the assertions.

```
1) Error: test_generalizedtime(OpenSSL::TestASN1): OpenSSL::ASN1::ASN1Error: generalizedtime is too short
/home/runner/work/ruby-openssl/ruby-openssl/test/openssl/test_asn1.rb:698:in `decode'
/home/runner/work/ruby-openssl/ruby-openssl/test/openssl/test_asn1.rb:698:in `decode_test'
/home/runner/work/ruby-openssl/ruby-openssl/test/openssl/test_asn1.rb:433:in `test_generalizedtime'
     430:       OpenSSL::ASN1::GeneralizedTime.new(Time.utc(9999, 9, 8, 23, 43, 39))
     431:     # LibreSSL 3.6.0 requires the seconds element
     432:     return if libressl?
  => 433:     decode_test B(%w{ 18 0D }) + "201612081934Z".b,
     434:       OpenSSL::ASN1::GeneralizedTime.new(Time.utc(2016, 12, 8, 19, 34, 0))
     435:     # not implemented
     436:     # decode_test B(%w{ 18 13 }) + "2016120819+0930".b,

2) Error: test_utctime(OpenSSL::TestASN1): OpenSSL::ASN1::ASN1Error: utctime is too short
/home/runner/work/ruby-openssl/ruby-openssl/test/openssl/test_asn1.rb:698:in `decode'
/home/runner/work/ruby-openssl/ruby-openssl/test/openssl/test_asn1.rb:698:in `decode_test'
/home/runner/work/ruby-openssl/ruby-openssl/test/openssl/test_asn1.rb:411:in `test_utctime'
     408:     end
     409:     # Seconds is omitted. LibreSSL 3.6.0 requires it
     410:     return if libressl?
  => 411:     decode_test B(%w{ 17 0B }) + "1609082343Z".b,
     412:       OpenSSL::ASN1::UTCTime.new(Time.utc(2016, 9, 8, 23, 43, 0))
     413:     # not implemented
     414:     # decode_test B(%w{ 17 11 }) + "5009082343+0930".b,
```

2e826d5715
2024-03-13 15:19:40 +00:00
Hiroshi SHIBATA
c14d295afd
Fix accidentally changed to rename test method at d95d3484a9 2024-02-19 11:05:13 +09:00
Hiroshi SHIBATA
d95d3484a9
omit tests related legacy provider
It failed with recent update of FreeBSD

20240207T023002Z.fail.html.gz
2024-02-07 16:06:01 +09:00
Kazuki Yamaguchi
e1751b2ec8 [ruby/openssl] test/openssl/test_ocsp.rb: fix flaky test
Fixes: https://github.com/ruby/openssl/issues/695

95281fe4a9
2024-01-17 17:13:16 +00:00
Samuel Williams
4f634d3c85 [ruby/openssl] Add support for IO#timeout.
(https://github.com/ruby/openssl/pull/714)

* Add support for IO#timeout.

3bbf5178a9
2024-01-17 17:09:03 +00:00