Skip to content

Commit

Permalink
Merge branch 'maint-3.2'
Browse files Browse the repository at this point in the history
* maint-3.2:
  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)
  • Loading branch information
rhenium committed May 2, 2024
2 parents abacf2f + a8ef534 commit 386a735
Show file tree
Hide file tree
Showing 5 changed files with 64 additions and 10 deletions.
18 changes: 15 additions & 3 deletions ext/openssl/ossl_cipher.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand All @@ -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;
Expand Down
8 changes: 7 additions & 1 deletion ext/openssl/ossl_pkcs7.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down Expand Up @@ -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);
Expand Down
17 changes: 11 additions & 6 deletions lib/openssl/buffering.rb
Original file line number Diff line number Diff line change
Expand Up @@ -349,13 +349,18 @@ def do_write(s)
@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
Expand Down
16 changes: 16 additions & 0 deletions test/openssl/test_cipher.rb
Original file line number Diff line number Diff line change
Expand Up @@ -331,6 +331,22 @@ def test_aes_gcm_key_iv_order_issue
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
Expand Down
15 changes: 15 additions & 0 deletions test/openssl/test_pkcs7.rb
Original file line number Diff line number Diff line change
Expand Up @@ -155,6 +155,21 @@ def test_enveloped
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) }
Expand Down

0 comments on commit 386a735

Please sign in to comment.