Issue #14024 has been updated by rhenium (Kazuki Yamaguchi).

Status changed from Open to Closed

Since CFB isn't an authenticated encryption mode, OpenSSL::Cipher#auth_data= must not be called. It is definitely a bug that calling it crashes, though.

https://github.com/ruby/openssl/commit/bb10767b0570d44f240632a7399c882764a48649

----------------------------------------
Bug #14024: Segment fault on OpenSSL::Cipher#auth_data= 
https://bugs.ruby-lang.org/issues/14024#change-67301

* Author: darfux (Lee YX)
* Status: Closed
* Priority: Normal
* Assignee: 
* Target version: 
* ruby -v: ruby 2.4.2p198 (2017-09-14 revision 59899) [x86_64-linux]
* Backport: 2.3: UNKNOWN, 2.4: UNKNOWN
----------------------------------------
The doc of *auth_data=* says that "If no associated data shall be used, this method must still be called with a value of '' . "  http://ruby-doc.org/stdlib-2.4.2/libdoc/openssl/rdoc/OpenSSL/Cipher.html#method-i-auth_data-3D
But if I call this method with a non-empty string when there's no associated data, ruby just crash rather than raise an error.

~~~ ruby
require 'openssl'
cipher = OpenSSL::Cipher::AES.new(128, :CFB)
cipher.auth_data="123"
~~~


~~~
ssl.rb:3: [BUG] Segmentation fault at 0x00000000026365d8
ruby 2.4.2p198 (2017-09-14 revision 59899) [x86_64-linux]

-- Control frame information -----------------------------------------------
c:0003 p:---- s:0013 e:000012 CFUNC  :auth_data=
c:0002 p:0043 s:0008 E:002348 EVAL   ssl.rb:3 [FINISH]
c:0001 p:0000 s:0003 E:0021e0 (none) [FINISH]

-- Ruby level backtrace information ----------------------------------------
ssl.rb:3:in `<main>'
ssl.rb:3:in `auth_data='
~~~

I guess this is because the function *ossl_cipher_set_auth_data* doesn't verify the ctx and simply pass a NULL to openssl.

~~~ c
static VALUE
ossl_cipher_set_auth_data(VALUE self, VALUE data)
{
    EVP_CIPHER_CTX *ctx;
    unsigned char *in;
    long in_len, out_len;

    StringValue(data);

    in = (unsigned char *) RSTRING_PTR(data);
    in_len = RSTRING_LEN(data);

    GetCipher(self, ctx);

    // HERE out is NULL
    if (!ossl_cipher_update_long(ctx, NULL, &out_len, in, in_len))
        ossl_raise(eCipherError, "couldn't set additional authenticated data");

    return data;
}
~~~

While the function CRYPTO_cfb128_encrypt of openssl(openssl/crypto/modes/cfb128.c) also doesn't verify the value of **out**. Then the access of **out(0x0)** leads to a segment fault.

~~~
#1  0x00007ffff58b1c99 in CRYPTO_cfb128_encrypt (in=0x6e51c8 "123", out=0x0, len=3, key=0x9da8a0, ivec=0x953948 "", num=0x953978, enc=0, block=0x80b150) at cfb128.c:155
...
#5  0x00007ffff591d90c in EVP_CipherUpdate (ctx=ctx@entry=0x953920, out=out@entry=0x0, outl=outl@entry=0x7fffffffcbb4, in=in@entry=0x6e51c8 "123", inl=inl@entry=3) at evp_enc.c:273
#6  0x00007ffff5ecbf6a in ossl_cipher_update_long (out=<optimized out>, in_len=3, in=0x6e51c8 "123", out_len_ptr=<optimized out>, ctx=<optimized out>) at ossl_cipher.c:349
#7  ossl_cipher_set_auth_data (self=<optimized out>, data=7229880) at ossl_cipher.c:584
~~~

---Files--------------------------------
crash.log (15.1 KB)
auth_data.rb (86 Bytes)


-- 
https://bugs.ruby-lang.org/

Unsubscribe: <mailto:ruby-core-request / ruby-lang.org?subject=unsubscribe>
<http://lists.ruby-lang.org/cgi-bin/mailman/options/ruby-core>