aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorKazuki Yamaguchi <k@rhe.jp>2024-05-02 16:07:03 +0900
committerKazuki Yamaguchi <k@rhe.jp>2024-05-02 16:08:04 +0900
commita8ef53494026057038e763af4f33aa9442249498 (patch)
treee43c26187b12dbb584746c26fde610c27af3ead5
parent6b3dd6a372c5eabc88bf35a312937ee3e1a6a105 (diff)
parent3cd3c27c99393af12d40949f2b40e44ac768c338 (diff)
downloadruby-openssl-a8ef53494026057038e763af4f33aa9442249498.tar.gz
Merge branch 'maint-3.1' into maint-3.2
* maint-3.1: Fix modular square root test with LibreSSL >= 3.8 pkcs7: raise PKCS7Error for PKCS7 without content in PKCS7.read_smime pkcs7: raise ArgumentError for PKCS7 with no content in PKCS7.new cipher: fix buffer overflow in Cipher#update ssl: allow failure on test_connect_certificate_verify_failed_exception_message .github/workflows/test.yml: synchronize with master Only CSR version 1 (encoded as 0) is allowed by PKIX standards test_asn1.rb: Remove the assertions of the time string format without second. test/openssl/test_asn1.rb: skip failing tests on LibreSSL 3.6.0 Use EVP_Digest{Sign,Verify} when available Fix performance regression in do_write(s)
-rw-r--r--.github/workflows/test.yml21
-rw-r--r--ext/openssl/ossl_cipher.c18
-rw-r--r--ext/openssl/ossl_pkcs7.c8
-rw-r--r--lib/openssl/buffering.rb17
-rw-r--r--test/openssl/test_asn1.rb8
-rw-r--r--test/openssl/test_cipher.rb16
-rw-r--r--test/openssl/test_pkcs7.rb15
-rw-r--r--test/openssl/test_x509req.rb7
8 files changed, 74 insertions, 36 deletions
diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml
index e8c22369..075bac8e 100644
--- a/.github/workflows/test.yml
+++ b/.github/workflows/test.yml
@@ -51,12 +51,6 @@ jobs:
run: echo "RUBY_OPENSSL_EXTCFLAGS=-Werror" >> $GITHUB_ENV
if: ${{ !matrix.skip-warnings }}
- # Enable provider search path for OpenSSL 3.0 in MSYS2.
- # Remove when Ruby 3.2 build is updated
- - name: enable windows provider search path
- run: echo "OPENSSL_MODULES=$($env:RI_DEVKIT)\$($env:MSYSTEM_PREFIX)\lib\ossl-modules" >> $env:GITHUB_ENV
- if: runner.os == 'Windows' && matrix.ruby == '3.2'
-
- name: compile
run: rake compile
@@ -77,18 +71,21 @@ jobs:
# https://www.openssl.org/source/
- openssl-1.0.2u # EOL
- openssl-1.1.0l # EOL
- - openssl-1.1.1v
- - openssl-3.0.10
- - openssl-3.1.2
+ - 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.7 # EOL
- libressl-3.3.6 # EOL
- libressl-3.4.3 # EOL
- libressl-3.5.3 # EOL
- - libressl-3.6.3
- - libressl-3.7.3
- - libressl-3.8.0 # Development release
+ - libressl-3.6.3 # EOL
+ - libressl-3.7.3 # EOL
+ - libressl-3.8.4
+ - libressl-3.9.1
fips-enabled: [ false ]
include:
- { os: ubuntu-latest, ruby: "3.0", openssl: openssl-3.0.10, fips-enabled: true, append-configure: 'enable-fips', name-extra: 'fips' }
diff --git a/ext/openssl/ossl_cipher.c b/ext/openssl/ossl_cipher.c
index 110610e1..506a0e71 100644
--- a/ext/openssl/ossl_cipher.c
+++ b/ext/openssl/ossl_cipher.c
@@ -386,11 +386,23 @@ ossl_cipher_update(int argc, VALUE *argv, VALUE self)
in = (unsigned char *)RSTRING_PTR(data);
in_len = RSTRING_LEN(data);
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);
@@ -401,7 +413,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/ext/openssl/ossl_pkcs7.c b/ext/openssl/ossl_pkcs7.c
index 78dcbd66..aeeb4bf5 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);
@@ -346,6 +350,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/lib/openssl/buffering.rb b/lib/openssl/buffering.rb
index 9570f14f..4df90746 100644
--- a/lib/openssl/buffering.rb
+++ b/lib/openssl/buffering.rb
@@ -345,13 +345,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
diff --git a/test/openssl/test_asn1.rb b/test/openssl/test_asn1.rb
index 6eb45094..7b1722e5 100644
--- a/test/openssl/test_asn1.rb
+++ b/test/openssl/test_asn1.rb
@@ -406,10 +406,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"))
@@ -428,10 +424,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"))
diff --git a/test/openssl/test_cipher.rb b/test/openssl/test_cipher.rb
index 8faa5706..41885fd5 100644
--- a/test/openssl/test_cipher.rb
+++ b/test/openssl/test_cipher.rb
@@ -331,6 +331,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
diff --git a/test/openssl/test_pkcs7.rb b/test/openssl/test_pkcs7.rb
index ba8b93d0..96f3f1f6 100644
--- a/test/openssl/test_pkcs7.rb
+++ b/test/openssl/test_pkcs7.rb
@@ -155,6 +155,21 @@ 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) }
+
+ data = <<END
+MIME-Version: 1.0
+Content-Disposition: attachment; filename="smime.p7m"
+Content-Type: application/x-pkcs7-mime; smime-type=signed-data; name="smime.p7m"
+Content-Transfer-Encoding: base64
+
+#{data}
+END
+ assert_raise(OpenSSL::PKCS7::PKCS7Error) { OpenSSL::PKCS7.read_smime(data) }
+ end
+
def test_graceful_parsing_failure #[ruby-core:43250]
contents = File.read(__FILE__)
assert_raise(ArgumentError) { OpenSSL::PKCS7.new(contents) }
diff --git a/test/openssl/test_x509req.rb b/test/openssl/test_x509req.rb
index ff17c411..b98754b8 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('SHA256'))
- 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))
rescue OpenSSL::X509::RequestError # RHEL 9 disables SHA1
end