From d4389b425de7e82031897288b730d49b4b4319c1 Mon Sep 17 00:00:00 2001 From: Jaymz Julian Date: Mon, 5 Feb 2024 15:00:47 -0800 Subject: Fix performance regression in do_write(s) This causes significant performance issues when using large (>10meg) writes Fix by adjusting the buffer write function to clear the buffer once, rather than piece by piece, avoiding a case where a large write (in our case, around 70mbytes) will consume 100% of CPU. This takes a webrick GET request via SSL from around 200kbyts/sec and consuming 100% of a core, to line speed on gigabit ethernet and 6% cpu utlization. --- lib/openssl/buffering.rb | 17 +++++++++++------ 1 file changed, 11 insertions(+), 6 deletions(-) diff --git a/lib/openssl/buffering.rb b/lib/openssl/buffering.rb index d47e1082..aa4adee3 100644 --- a/lib/openssl/buffering.rb +++ b/lib/openssl/buffering.rb @@ -348,13 +348,18 @@ module OpenSSL::Buffering @wbuffer << s @wbuffer.force_encoding(Encoding::BINARY) @sync ||= false - if @sync or @wbuffer.size > BLOCK_SIZE - until @wbuffer.empty? - begin - nwrote = syswrite(@wbuffer) - rescue Errno::EAGAIN - retry + buffer_size = @wbuffer.size + if @sync or buffer_size > BLOCK_SIZE + nwrote = 0 + begin + while nwrote < buffer_size do + begin + nwrote += syswrite(@wbuffer[nwrote, buffer_size - nwrote]) + rescue Errno::EAGAIN + retry + end end + ensure @wbuffer[0, nwrote] = "" end end -- cgit v1.2.3 From 3e3c7508a5098b531a6efa9936786d45b3ca0489 Mon Sep 17 00:00:00 2001 From: Theo Buehler Date: Thu, 10 Nov 2022 14:50:22 +0100 Subject: Use EVP_Digest{Sign,Verify} when available [ This is a backport to the 3.0 branch. ] LibreSSL 3.4 added EVP_DigestSign() and EVP_DigestVerify(). Use them when available to prepare for the addition of Ed25519 support in LibreSSL 3.7. (cherry picked from commit 475b2bf766d6093370e49abd5dce5436cc0034ca) --- ext/openssl/ossl_pkey.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/ext/openssl/ossl_pkey.c b/ext/openssl/ossl_pkey.c index ec39e8bd..47625667 100644 --- a/ext/openssl/ossl_pkey.c +++ b/ext/openssl/ossl_pkey.c @@ -951,7 +951,7 @@ ossl_pkey_sign(int argc, VALUE *argv, VALUE self) rb_jump_tag(state); } } -#if OPENSSL_VERSION_NUMBER >= 0x10101000 && !defined(LIBRESSL_VERSION_NUMBER) +#if OSSL_OPENSSL_PREREQ(1, 1, 1) || OSSL_LIBRESSL_PREREQ(3, 4, 0) if (EVP_DigestSign(ctx, NULL, &siglen, (unsigned char *)RSTRING_PTR(data), RSTRING_LEN(data)) < 1) { EVP_MD_CTX_free(ctx); @@ -1056,7 +1056,7 @@ ossl_pkey_verify(int argc, VALUE *argv, VALUE self) rb_jump_tag(state); } } -#if OPENSSL_VERSION_NUMBER >= 0x10101000 && !defined(LIBRESSL_VERSION_NUMBER) +#if OSSL_OPENSSL_PREREQ(1, 1, 1) || OSSL_LIBRESSL_PREREQ(3, 4, 0) ret = EVP_DigestVerify(ctx, (unsigned char *)RSTRING_PTR(sig), RSTRING_LEN(sig), (unsigned char *)RSTRING_PTR(data), RSTRING_LEN(data)); -- cgit v1.2.3 From 6a61507f0c85b1734336702bd63640fd75f70a5f Mon Sep 17 00:00:00 2001 From: Kazuki Yamaguchi Date: Mon, 17 Oct 2022 16:50:01 +0900 Subject: test/openssl/test_asn1.rb: skip failing tests on LibreSSL 3.6.0 [ This is a backport to the 3.0 branch. ] LibreSSL 3.6.0 expects the seconds part in UTCTime and GeneralizedTime to be always present. LibreSSL 3.6.0 release note [1] says: > - The ASN.1 time parser has been refactored and rewritten using CBS. > It has been made stricter in that it now enforces the rules from > RFC 5280. [1] https://ftp.openbsd.org/pub/OpenBSD/LibreSSL/libressl-3.6.0-relnotes.txt (cherry picked from commit bbc540fe83195e2a54cf40fab448cea2afe4df1d) --- test/openssl/test_asn1.rb | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/test/openssl/test_asn1.rb b/test/openssl/test_asn1.rb index 0fd79715..97f6f085 100644 --- a/test/openssl/test_asn1.rb +++ b/test/openssl/test_asn1.rb @@ -404,9 +404,6 @@ class OpenSSL::TestASN1 < OpenSSL::TestCase def test_utctime encode_decode_test B(%w{ 17 0D }) + "160908234339Z".b, OpenSSL::ASN1::UTCTime.new(Time.utc(2016, 9, 8, 23, 43, 39)) - # Seconds is omitted - decode_test B(%w{ 17 0B }) + "1609082343Z".b, - OpenSSL::ASN1::UTCTime.new(Time.utc(2016, 9, 8, 23, 43, 0)) begin # possible range of UTCTime is 1969-2068 currently encode_decode_test B(%w{ 17 0D }) + "690908234339Z".b, @@ -414,6 +411,10 @@ class OpenSSL::TestASN1 < OpenSSL::TestCase rescue OpenSSL::ASN1::ASN1Error pend "No negative time_t support?" end + # Seconds is omitted. LibreSSL 3.6.0 requires it + return if libressl? + decode_test B(%w{ 17 0B }) + "1609082343Z".b, + OpenSSL::ASN1::UTCTime.new(Time.utc(2016, 9, 8, 23, 43, 0)) # not implemented # decode_test B(%w{ 17 11 }) + "500908234339+0930".b, # OpenSSL::ASN1::UTCTime.new(Time.new(1950, 9, 8, 23, 43, 39, "+09:30")) @@ -432,6 +433,8 @@ class OpenSSL::TestASN1 < OpenSSL::TestCase OpenSSL::ASN1::GeneralizedTime.new(Time.utc(2016, 12, 8, 19, 34, 29)) encode_decode_test B(%w{ 18 0F }) + "99990908234339Z".b, OpenSSL::ASN1::GeneralizedTime.new(Time.utc(9999, 9, 8, 23, 43, 39)) + # LibreSSL 3.6.0 requires the seconds element + return if libressl? decode_test B(%w{ 18 0D }) + "201612081934Z".b, OpenSSL::ASN1::GeneralizedTime.new(Time.utc(2016, 12, 8, 19, 34, 0)) # not implemented -- cgit v1.2.3 From c6f82ebe641df5a48d786e3f14d20f34603b4bd9 Mon Sep 17 00:00:00 2001 From: Jun Aruga Date: Tue, 12 Mar 2024 14:39:05 +0100 Subject: test_asn1.rb: Remove the assertions of the time string format without second. [ This is a backport to the 3.0 branch. ] 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 }) + "20161208193439+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 }) + "500908234339+0930".b, ``` (cherry picked from commit 2e826d571546cdc3beaa884f9e522a102d531641) --- test/openssl/test_asn1.rb | 8 -------- 1 file changed, 8 deletions(-) diff --git a/test/openssl/test_asn1.rb b/test/openssl/test_asn1.rb index 97f6f085..7e5b9692 100644 --- a/test/openssl/test_asn1.rb +++ b/test/openssl/test_asn1.rb @@ -411,10 +411,6 @@ class OpenSSL::TestASN1 < OpenSSL::TestCase rescue OpenSSL::ASN1::ASN1Error pend "No negative time_t support?" end - # Seconds is omitted. LibreSSL 3.6.0 requires it - return if libressl? - decode_test B(%w{ 17 0B }) + "1609082343Z".b, - OpenSSL::ASN1::UTCTime.new(Time.utc(2016, 9, 8, 23, 43, 0)) # not implemented # decode_test B(%w{ 17 11 }) + "500908234339+0930".b, # OpenSSL::ASN1::UTCTime.new(Time.new(1950, 9, 8, 23, 43, 39, "+09:30")) @@ -433,10 +429,6 @@ class OpenSSL::TestASN1 < OpenSSL::TestCase OpenSSL::ASN1::GeneralizedTime.new(Time.utc(2016, 12, 8, 19, 34, 29)) encode_decode_test B(%w{ 18 0F }) + "99990908234339Z".b, OpenSSL::ASN1::GeneralizedTime.new(Time.utc(9999, 9, 8, 23, 43, 39)) - # LibreSSL 3.6.0 requires the seconds element - return if libressl? - decode_test B(%w{ 18 0D }) + "201612081934Z".b, - OpenSSL::ASN1::GeneralizedTime.new(Time.utc(2016, 12, 8, 19, 34, 0)) # not implemented # decode_test B(%w{ 18 13 }) + "20161208193439+0930".b, # OpenSSL::ASN1::GeneralizedTime.new(Time.new(2016, 12, 8, 19, 34, 39, "+09:30")) -- cgit v1.2.3 From cf229f5b11b9ad232998c27f63b5bc94dc283c88 Mon Sep 17 00:00:00 2001 From: Job Snijders Date: Mon, 25 Mar 2024 12:20:13 +0000 Subject: Only CSR version 1 (encoded as 0) is allowed by PKIX standards [ This is a backport to the 3.0 branch. ] 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) ``` (cherry picked from commit c06fdeb0912221d9a2888369bbf9c10704af021e) --- test/openssl/test_x509req.rb | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/test/openssl/test_x509req.rb b/test/openssl/test_x509req.rb index ee9c678f..bac9780d 100644 --- a/test/openssl/test_x509req.rb +++ b/test/openssl/test_x509req.rb @@ -39,11 +39,6 @@ class OpenSSL::TestX509Request < OpenSSL::TestCase assert_equal(0, req.version) req = OpenSSL::X509::Request.new(req.to_der) assert_equal(0, req.version) - - req = issue_csr(1, @dn, @rsa1024, OpenSSL::Digest.new('SHA1')) - assert_equal(1, req.version) - req = OpenSSL::X509::Request.new(req.to_der) - assert_equal(1, req.version) end def test_subject @@ -106,7 +101,7 @@ class OpenSSL::TestX509Request < OpenSSL::TestCase assert_equal(false, req.verify(@rsa2048)) assert_equal(false, request_error_returns_false { req.verify(@dsa256) }) assert_equal(false, request_error_returns_false { req.verify(@dsa512) }) - req.version = 1 + req.subject = OpenSSL::X509::Name.parse("/C=JP/CN=FooBarFooBar") assert_equal(false, req.verify(@rsa1024)) end -- cgit v1.2.3 From ee9e162de170f1af5c7c3d8cf4ecadf8d3000265 Mon Sep 17 00:00:00 2001 From: Kazuki Yamaguchi Date: Wed, 1 May 2024 00:20:39 +0900 Subject: .github/workflows/test.yml: synchronize with master [ This is a backport to the 3.0 branch. ] Backport changes made to .github/workflows/test.yml in master branch, except: - Minimum version is Ruby 2.6 - FIPS-mode related changes are excluded (as it's not supported) This includes the following commits: fcf53d5d6e88 CI: Remove workaround for Ruby-3.2 and 3.3 on Windows 567b412612c3 CI: Upgrade OpenSSL and LibreSSL versions. 405f1eee3dcf CI: Add OpenSSL no-legacy case. 9a995837ba7b CI: Upgrade OpenSSL and LibreSSL versions. 6feeeb821592 CI: Add the rubyinstaller2 issue link that legacy provider is not loaded. 7aed35ac969d Windows Ruby 3.3: Workaround: Set OPENSSL_MODULES to find providers. adfb6bb9e5b7 CI: Add OpenSSL 3.2.0. fafe1af4a96e CI: Change the openssl_fips.cnf.tmpl and openssl_fips.cnf directories. f07e6f5ff2e7 CI: Upgrade OpenSSL and LibreSSL versions. 0dda88d44811 Merge pull request #682 from ruby/dependabot/github_actions/actions/checkout-4 0b83eed154de Rakefile: Add test_fips task for convenience. b94314f7165f Bump actions/checkout from 3 to 4 8c7a6a17e2bd Remove OSSL_DEBUG compile-time option e35f19076aac CI: Replace "mode" in "FIPS mode" with "module". 61434f66d6a4 Rakefile: Print FIPS information in the `rake debug`. 7ec8024b1e9a CI: Add OpenSSL master branch head non-FIPS and FIPS cases. 24d8addd2ac9 CI: Upgrade OpenSSL versions. fddfc5585482 CI: Add OpenSSL 3.1 FIPS case. 58ce7fa4b90c .github/workflows/test.yml: add provider load path for Windows f6e57e1b9088 CI: Fix a typo in the comment. [ci skip] 52402f6a1cad CI: Check compiler warnings. f6ba75e51e05 Drop support for Ruby 2.6 3456770a4219 CI: Upgrade OpenSSL and LibreSSL versions. 79786cab6f77 CI: Rename the key name "foo_bar" (underscore) to "foo-bar" (hyphen). 8149cdf6e874 CI: Add the test/openssl/test_pkey.rb on the FIPS mode case. 08e19817b5d0 CI: Enable the verbose mode in the mkmf.rb by env MAKEFLAGS. 121b3b2a35ca Revert "CI: Enable the verbose mode in the mkmf.rb." a832f5cb98ee CI: Enable the verbose mode in the mkmf.rb. 18b017218ca8 CI: Add OpenSSL FIPS mode case. af27f509a147 .github/workflows/test.yml: Update OpenSSL versions d277123cb7bb skip failing test with truffleruby and ubuntu-22.04 25352f4f6c08 Exclude truffleruby with macos-latest d7f90c7c03b7 Fix missing needs call 064066437607 Try to run with TruffleRuby aeee125a7b3d Use ruby/actions/.github/workflows/ruby_versions.yml@master fd4074235877 .github/workflows/test.yml: update LibreSSL versions ff2fe4b4c5b3 Strip trailing spaces [ci skip] 9c24dccf5436 Actions - Use Ubuntu 20.04 for 1.1.1 CI, misc fixes cc876f58532c [CI] test.yml - test-openssls - use 1.1.1q, 3.0.5 0fb8d1b43aa5 [CI] add Ubuntu-22.04 and update mswin, all are OpenSSL 3 158868649532 Merge pull request #505 from ruby/update-actions 9f901dc05ce5 Test on LibreSSL 3.4 and 3.5 f2d072cad504 Use actions/checkout@v3 699e2749f525 Added 3.1 b28df9025f12 Install openssl with vcpkg on mswin --- .github/workflows/test.yml | 118 +++++++++++++++++++++++++++------------------ 1 file changed, 71 insertions(+), 47 deletions(-) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index f396c350..fc4e847c 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -3,19 +3,36 @@ name: CI on: [push, pull_request] jobs: + ruby-versions: + uses: ruby/actions/.github/workflows/ruby_versions.yml@master + with: + engine: cruby-truffleruby + min_version: 2.6 test: + needs: ruby-versions name: >- ${{ matrix.os }} ${{ matrix.ruby }} runs-on: ${{ matrix.os }} strategy: fail-fast: false matrix: - # ubuntu-latest is 22.04, uses OpenSSL 3 - os: [ ubuntu-20.04, macos-latest ] - ruby: [ head, "3.0", "2.7", "2.6" ] + # ubuntu-22.04 uses OpenSSL 3.0, ubuntu-20.04 uses OpenSSL 1.1.1 + os: [ ubuntu-22.04, ubuntu-20.04, macos-latest, windows-latest ] + ruby: ${{ fromJson(needs.ruby-versions.outputs.versions) }} + exclude: + # uses non-standard MSYS2 OpenSSL 3 package + - { os: windows-latest, ruby: head } + - { os: windows-latest, ruby: truffleruby } + - { os: windows-latest, ruby: truffleruby-head } + - { os: macos-latest, ruby: truffleruby } + - { os: ubuntu-20.04, ruby: truffleruby } + include: + - { os: windows-latest, ruby: ucrt } + - { os: windows-latest, ruby: mswin } + steps: - name: repo checkout - uses: actions/checkout@v3 + uses: actions/checkout@v4 - name: load ruby uses: ruby/setup-ruby@v1 @@ -25,47 +42,25 @@ jobs: - name: depends run: bundle install - - name: compile - run: rake compile -- --enable-debug + # Enable the verbose option in mkmf.rb to print the compiling commands. + - name: enable mkmf verbose + run: echo "MAKEFLAGS=V=1" >> $GITHUB_ENV + if: runner.os == 'Linux' || runner.os == 'macOS' - - name: test - run: rake test TESTOPTS="-v --no-show-detail-immediately" OSSL_MDEBUG=1 + - name: set flags to check compiler warnings. + run: echo "RUBY_OPENSSL_EXTCFLAGS=-Werror" >> $GITHUB_ENV + if: ${{ !matrix.skip-warnings }} - test-windows: - name: >- - ${{ matrix.os }} ${{ matrix.ruby }} - runs-on: ${{ matrix.os }} - strategy: - fail-fast: false - matrix: - os: [ windows-latest ] - # current mswin build uses OpenSSL 3 - ruby: [ mingw, "3.0", "2.7", "2.6" ] - steps: - - name: repo checkout - uses: actions/checkout@v3 - - - name: load ruby, install/update gcc, install openssl - uses: MSP-Greg/setup-ruby-pkgs@v1 - with: - ruby-version: ${{ matrix.ruby }} - mingw: _upgrade_ openssl - - - name: depends - run: bundle install - - # pkg-config is disabled because it can pick up the different OpenSSL installation - # SSL_DIR is set as needed by MSP-Greg/setup-ruby-pkgs - # only used with mswin - name: compile - run: rake compile -- --enable-debug --without-pkg-config $env:SSL_DIR + run: rake compile - name: test - run: rake test TESTOPTS="-v --no-show-detail-immediately" OSSL_MDEBUG=1 + run: rake test TESTOPTS="-v --no-show-detail-immediately" + timeout-minutes: 5 test-openssls: name: >- - ${{ matrix.openssl }} + ${{ matrix.openssl }} ${{ matrix.name-extra || '' }} runs-on: ${{ matrix.os }} strategy: fail-fast: false @@ -73,27 +68,47 @@ jobs: os: [ ubuntu-latest ] ruby: [ "3.0" ] openssl: + # https://www.openssl.org/source/ - openssl-1.0.2u # EOL - openssl-1.1.0l # EOL - - openssl-1.1.1l - - openssl-3.0.1 + - openssl-1.1.1w # EOL + - openssl-3.0.13 + - openssl-3.1.5 + - openssl-3.2.1 + - openssl-3.3.0 + # http://www.libressl.org/releases.html - libressl-3.1.5 # EOL - - libressl-3.2.6 - - libressl-3.3.4 + - libressl-3.2.7 # EOL + - libressl-3.3.6 # EOL + - libressl-3.4.3 # EOL + - libressl-3.5.3 # EOL + - libressl-3.6.3 # EOL + - libressl-3.7.3 # EOL + - libressl-3.8.4 + - libressl-3.9.1 steps: - name: repo checkout - uses: actions/checkout@v3 + uses: actions/checkout@v4 - name: prepare openssl run: | + # Enable Bash debugging option temporarily for debugging use. + set -x mkdir -p tmp/build-openssl && cd tmp/build-openssl case ${{ matrix.openssl }} in openssl-*) - curl -OL https://ftp.openssl.org/source/${{ matrix.openssl }}.tar.gz - tar xf ${{ matrix.openssl }}.tar.gz && cd ${{ matrix.openssl }} + if [ -z "${{ matrix.git }}" ]; then + curl -OL https://ftp.openssl.org/source/${{ matrix.openssl }}.tar.gz + tar xf ${{ matrix.openssl }}.tar.gz && cd ${{ matrix.openssl }} + else + git clone -b ${{ matrix.branch }} --depth 1 ${{ matrix.git }} ${{ matrix.openssl }} + cd ${{ matrix.openssl }} + # Log the commit hash. + echo "Git commit: $(git rev-parse HEAD)" + fi # shared is required for 1.0.x. ./Configure --prefix=$HOME/.openssl/${{ matrix.openssl }} --libdir=lib \ - shared linux-x86_64 + shared linux-x86_64 ${{ matrix.append-configure }} make depend ;; libressl-*) @@ -116,8 +131,17 @@ jobs: - name: depends run: bundle install + - name: enable mkmf verbose + run: echo "MAKEFLAGS=V=1" >> $GITHUB_ENV + if: runner.os == 'Linux' || runner.os == 'macOS' + + - name: set flags to check compiler warnings. + run: echo "RUBY_OPENSSL_EXTCFLAGS=-Werror" >> $GITHUB_ENV + if: ${{ !matrix.skip-warnings }} + - name: compile - run: rake compile -- --enable-debug --with-openssl-dir=$HOME/.openssl/${{ matrix.openssl }} + run: rake compile -- --with-openssl-dir=$HOME/.openssl/${{ matrix.openssl }} - name: test - run: rake test TESTOPTS="-v --no-show-detail-immediately" OSSL_MDEBUG=1 + run: rake test TESTOPTS="-v --no-show-detail-immediately" + timeout-minutes: 5 -- cgit v1.2.3 From 3bdde7d88dc12f8e25d42c100d4f5717b1e8853c Mon Sep 17 00:00:00 2001 From: Kazuki Yamaguchi Date: Wed, 1 May 2024 01:01:30 +0900 Subject: ssl: allow failure on test_connect_certificate_verify_failed_exception_message [ This patch only applies to the 3.0 and 3.1 branch. ] It is a test case for SSLSocket generating an informative error message on a certificate verification failure. A change in OpenSSL 3.1 broke it and a generic error message is currently generated. This is fixed in the 3.2 branch by commit 5113777e8271, but I decided not to backport the commit to the 3.0 branch because the diff doesn't apply cleanly. --- test/openssl/test_ssl.rb | 3 +++ 1 file changed, 3 insertions(+) diff --git a/test/openssl/test_ssl.rb b/test/openssl/test_ssl.rb index 39964bf4..7172d062 100644 --- a/test/openssl/test_ssl.rb +++ b/test/openssl/test_ssl.rb @@ -995,6 +995,9 @@ class OpenSSL::TestSSL < OpenSSL::SSLTestCase end def test_connect_certificate_verify_failed_exception_message + # Won't fix on the 3.0 branch + return if openssl?(3, 1, 0) + start_server(ignore_listener_error: true) { |port| ctx = OpenSSL::SSL::SSLContext.new ctx.set_params -- cgit v1.2.3 From 3035559f54eaa42347b9fe2d91bd25a7b0563a44 Mon Sep 17 00:00:00 2001 From: Kazuki Yamaguchi Date: Mon, 5 Feb 2024 21:54:32 +0900 Subject: 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 --- ext/openssl/ossl_cipher.c | 18 +++++++++++++++--- test/openssl/test_cipher.rb | 16 ++++++++++++++++ 2 files changed, 31 insertions(+), 3 deletions(-) diff --git a/ext/openssl/ossl_cipher.c b/ext/openssl/ossl_cipher.c index d9c78914..e5d0f5be 100644 --- a/ext/openssl/ossl_cipher.c +++ b/ext/openssl/ossl_cipher.c @@ -387,11 +387,23 @@ ossl_cipher_update(int argc, VALUE *argv, VALUE self) if ((in_len = RSTRING_LEN(data)) == 0) ossl_raise(rb_eArgError, "data must not be empty"); GetCipher(self, ctx); - out_len = in_len+EVP_CIPHER_CTX_block_size(ctx); - if (out_len <= 0) { + + /* + * As of OpenSSL 3.2, there is no reliable way to determine the required + * output buffer size for arbitrary cipher modes. + * https://github.com/openssl/openssl/issues/22628 + * + * in_len+block_size is usually sufficient, but AES key wrap with padding + * ciphers require in_len+15 even though they have a block size of 8 bytes. + * + * Using EVP_MAX_BLOCK_LENGTH (32) as a safe upper bound for ciphers + * currently implemented in OpenSSL, but this can change in the future. + */ + if (in_len > LONG_MAX - EVP_MAX_BLOCK_LENGTH) { ossl_raise(rb_eRangeError, "data too big to make output buffer: %ld bytes", in_len); } + out_len = in_len + EVP_MAX_BLOCK_LENGTH; if (NIL_P(str)) { str = rb_str_new(0, out_len); @@ -402,7 +414,7 @@ ossl_cipher_update(int argc, VALUE *argv, VALUE self) if (!ossl_cipher_update_long(ctx, (unsigned char *)RSTRING_PTR(str), &out_len, in, in_len)) ossl_raise(eCipherError, NULL); - assert(out_len < RSTRING_LEN(str)); + assert(out_len <= RSTRING_LEN(str)); rb_str_set_len(str, out_len); return str; diff --git a/test/openssl/test_cipher.rb b/test/openssl/test_cipher.rb index b5fdf0b3..ede97879 100644 --- a/test/openssl/test_cipher.rb +++ b/test/openssl/test_cipher.rb @@ -337,6 +337,22 @@ class OpenSSL::TestCipher < OpenSSL::TestCase assert_equal tag1, tag2 end + def test_aes_keywrap_pad + # RFC 5649 Section 6; The second example + kek = ["5840df6e29b02af1ab493b705bf16ea1ae8338f4dcc176a8"].pack("H*") + key = ["466f7250617369"].pack("H*") + wrap = ["afbeb0f07dfbf5419200f2ccb50bb24f"].pack("H*") + + begin + cipher = OpenSSL::Cipher.new("id-aes192-wrap-pad").encrypt + rescue OpenSSL::Cipher::CipherError, RuntimeError + omit "id-aes192-wrap-pad is not supported: #$!" + end + cipher.key = kek + ct = cipher.update(key) << cipher.final + assert_equal wrap, ct + end + def test_non_aead_cipher_set_auth_data assert_raise(OpenSSL::Cipher::CipherError) { cipher = OpenSSL::Cipher.new("aes-128-cfb").encrypt -- cgit v1.2.3 From 27e11f2d1dcd2fd367a2ec271a715708de22b7b9 Mon Sep 17 00:00:00 2001 From: Jeremy Evans Date: Fri, 27 Oct 2023 09:08:11 -0700 Subject: 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] Co-authored-by: pkuzco Co-authored-by: Kazuki Yamaguchi --- ext/openssl/ossl_pkcs7.c | 2 ++ test/openssl/test_pkcs7.rb | 5 +++++ 2 files changed, 7 insertions(+) diff --git a/ext/openssl/ossl_pkcs7.c b/ext/openssl/ossl_pkcs7.c index dbe53476..8d28f02f 100644 --- a/ext/openssl/ossl_pkcs7.c +++ b/ext/openssl/ossl_pkcs7.c @@ -346,6 +346,8 @@ ossl_pkcs7_initialize(int argc, VALUE *argv, VALUE self) BIO_free(in); if (!p7) ossl_raise(rb_eArgError, "Could not parse the PKCS7"); + if (!p7->d.ptr) + ossl_raise(rb_eArgError, "No content in PKCS7"); RTYPEDDATA_DATA(self) = p7; PKCS7_free(p7_orig); diff --git a/test/openssl/test_pkcs7.rb b/test/openssl/test_pkcs7.rb index ba8b93d0..fa15bdbc 100644 --- a/test/openssl/test_pkcs7.rb +++ b/test/openssl/test_pkcs7.rb @@ -155,6 +155,11 @@ class OpenSSL::TestPKCS7 < OpenSSL::TestCase assert_equal(data, p7.decrypt(@rsa1024)) end + def test_empty_signed_data_ruby_bug_19974 + data = "-----BEGIN PKCS7-----\nMAsGCSqGSIb3DQEHAg==\n-----END PKCS7-----\n" + assert_raise(ArgumentError) { OpenSSL::PKCS7.new(data) } + end + def test_graceful_parsing_failure #[ruby-core:43250] contents = File.read(__FILE__) assert_raise(ArgumentError) { OpenSSL::PKCS7.new(contents) } -- cgit v1.2.3 From 07eceb7f63260427cf8b062ad27da19b6841969e Mon Sep 17 00:00:00 2001 From: Jeremy Evans Date: Sat, 11 Nov 2023 16:36:39 -0800 Subject: 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] Co-authored-by: pkuzco Co-authored-by: Kazuki Yamaguchi --- ext/openssl/ossl_pkcs7.c | 6 +++++- test/openssl/test_pkcs7.rb | 10 ++++++++++ 2 files changed, 15 insertions(+), 1 deletion(-) diff --git a/ext/openssl/ossl_pkcs7.c b/ext/openssl/ossl_pkcs7.c index 8d28f02f..c8f7924e 100644 --- a/ext/openssl/ossl_pkcs7.c +++ b/ext/openssl/ossl_pkcs7.c @@ -165,7 +165,11 @@ ossl_pkcs7_s_read_smime(VALUE klass, VALUE arg) out = NULL; pkcs7 = SMIME_read_PKCS7(in, &out); BIO_free(in); - if(!pkcs7) ossl_raise(ePKCS7Error, NULL); + if (!pkcs7) + ossl_raise(ePKCS7Error, "Could not parse the PKCS7"); + if (!pkcs7->d.ptr) + ossl_raise(ePKCS7Error, "No content in PKCS7"); + data = out ? ossl_membio2str(out) : Qnil; SetPKCS7(ret, pkcs7); ossl_pkcs7_set_data(ret, data); diff --git a/test/openssl/test_pkcs7.rb b/test/openssl/test_pkcs7.rb index fa15bdbc..96f3f1f6 100644 --- a/test/openssl/test_pkcs7.rb +++ b/test/openssl/test_pkcs7.rb @@ -158,6 +158,16 @@ class OpenSSL::TestPKCS7 < OpenSSL::TestCase def test_empty_signed_data_ruby_bug_19974 data = "-----BEGIN PKCS7-----\nMAsGCSqGSIb3DQEHAg==\n-----END PKCS7-----\n" assert_raise(ArgumentError) { OpenSSL::PKCS7.new(data) } + + data = < Date: Tue, 11 Apr 2023 19:43:49 +0200 Subject: Fix modular square root test with LibreSSL >= 3.8 [ This is a backport to the 3.1 branch. ] If x is a modular square root of a (mod p) then so is (p - x). Both answers are valid. In particular, both 2 and 3 are valid square roots of 4 (mod 5). Do not assume that a particular square root is chosen by the algorithm. Indeed, the algorithm in OpenSSL and LibreSSL <= 3.7 returns a non-deterministic answer in many cases. LibreSSL 3.8 and later will always return the smaller of the two possible answers. This breaks the current test case. Instead of checking for a particular square root, check that the square of the claimed square root is the given value. This is always true. Add the simplest test case where the answer is indeed non-deterministic. (cherry picked from commit 93548ae9597ba40d3f8b564f6a948ce55b432e30) --- test/openssl/test_bn.rb | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/test/openssl/test_bn.rb b/test/openssl/test_bn.rb index 77af1409..ea88ff06 100644 --- a/test/openssl/test_bn.rb +++ b/test/openssl/test_bn.rb @@ -175,7 +175,9 @@ class OpenSSL::TestBN < OpenSSL::TestCase end def test_mod_sqrt - assert_equal(3, 4.to_bn.mod_sqrt(5)) + assert_equal(4, 4.to_bn.mod_sqrt(5).mod_sqr(5)) + # One of 189484 or 326277 is returned as a square root of 2 (mod 515761). + assert_equal(2, 2.to_bn.mod_sqrt(515761).mod_sqr(515761)) assert_equal(0, 5.to_bn.mod_sqrt(5)) assert_raise(OpenSSL::BNError) { 3.to_bn.mod_sqrt(5) } end -- cgit v1.2.3