mirror of
git://git.yoctoproject.org/poky.git
synced 2025-07-19 21:09:03 +02:00
ruby: Security fix for CVE-2016-7798
affectes ruby < 2.3.1 (From OE-Core rev: 6af2319008dc16c61092f71ff227c285aac51288) Signed-off-by: Thiruvadi Rajaraman <trajaraman@mvista.com> Signed-off-by: Armin Kuster <akuster@mvista.com> Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
This commit is contained in:
parent
fe8a56109b
commit
cab5a620ac
164
meta/recipes-devtools/ruby/ruby/CVE-2016-7798.patch
Normal file
164
meta/recipes-devtools/ruby/ruby/CVE-2016-7798.patch
Normal file
|
@ -0,0 +1,164 @@
|
|||
cipher: don't set dummy encryption key in Cipher#initialize
|
||||
Remove the encryption key initialization from Cipher#initialize. This
|
||||
is effectively a revert of r32723 ("Avoid possible SEGV from AES
|
||||
encryption/decryption", 2011-07-28).
|
||||
|
||||
r32723, which added the key initialization, was a workaround for
|
||||
Ruby Bug #2768. For some certain ciphers, calling EVP_CipherUpdate()
|
||||
before setting an encryption key caused segfault. It was not a problem
|
||||
until OpenSSL implemented GCM mode - the encryption key could be
|
||||
overridden by repeated calls of EVP_CipherInit_ex(). But, it is not the
|
||||
case for AES-GCM ciphers. Setting a key, an IV, a key, in this order
|
||||
causes the IV to be reset to an all-zero IV.
|
||||
|
||||
The problem of Bug #2768 persists on the current versions of OpenSSL.
|
||||
So, make Cipher#update raise an exception if a key is not yet set by the
|
||||
user. Since encrypting or decrypting without key does not make any
|
||||
sense, this should not break existing applications.
|
||||
|
||||
Users can still call Cipher#key= and Cipher#iv= multiple times with
|
||||
their own responsibility.
|
||||
|
||||
Reference: https://bugs.ruby-lang.org/issues/2768
|
||||
Reference: https://bugs.ruby-lang.org/issues/8221
|
||||
|
||||
Upstream-Status: Backport
|
||||
CVE: CVE-2016-7798
|
||||
|
||||
Signed-off-by: Thiruvadi Rajaraman <trajaraman@mvista.com>
|
||||
|
||||
Index: ruby-2.2.2/ext/openssl/ossl_cipher.c
|
||||
===================================================================
|
||||
--- ruby-2.2.2.orig/ext/openssl/ossl_cipher.c
|
||||
+++ ruby-2.2.2/ext/openssl/ossl_cipher.c
|
||||
@@ -35,6 +35,7 @@
|
||||
*/
|
||||
VALUE cCipher;
|
||||
VALUE eCipherError;
|
||||
+static ID id_key_set;
|
||||
|
||||
static VALUE ossl_cipher_alloc(VALUE klass);
|
||||
static void ossl_cipher_free(void *ptr);
|
||||
@@ -119,7 +120,6 @@ ossl_cipher_initialize(VALUE self, VALUE
|
||||
EVP_CIPHER_CTX *ctx;
|
||||
const EVP_CIPHER *cipher;
|
||||
char *name;
|
||||
- unsigned char key[EVP_MAX_KEY_LENGTH];
|
||||
|
||||
name = StringValuePtr(str);
|
||||
GetCipherInit(self, ctx);
|
||||
@@ -131,14 +131,7 @@ ossl_cipher_initialize(VALUE self, VALUE
|
||||
if (!(cipher = EVP_get_cipherbyname(name))) {
|
||||
ossl_raise(rb_eRuntimeError, "unsupported cipher algorithm (%s)", name);
|
||||
}
|
||||
- /*
|
||||
- * The EVP which has EVP_CIPH_RAND_KEY flag (such as DES3) allows
|
||||
- * uninitialized key, but other EVPs (such as AES) does not allow it.
|
||||
- * Calling EVP_CipherUpdate() without initializing key causes SEGV so we
|
||||
- * set the data filled with "\0" as the key by default.
|
||||
- */
|
||||
- memset(key, 0, EVP_MAX_KEY_LENGTH);
|
||||
- if (EVP_CipherInit_ex(ctx, cipher, NULL, key, NULL, -1) != 1)
|
||||
+ if (EVP_CipherInit_ex(ctx, cipher, NULL, NULL, NULL, -1) != 1)
|
||||
ossl_raise(eCipherError, NULL);
|
||||
|
||||
return self;
|
||||
@@ -256,6 +249,8 @@ ossl_cipher_init(int argc, VALUE *argv,
|
||||
if (EVP_CipherInit_ex(ctx, NULL, NULL, p_key, p_iv, mode) != 1) {
|
||||
ossl_raise(eCipherError, NULL);
|
||||
}
|
||||
+ if (p_key)
|
||||
+ rb_ivar_set(self, id_key_set, Qtrue);
|
||||
|
||||
return self;
|
||||
}
|
||||
@@ -343,6 +338,8 @@ ossl_cipher_pkcs5_keyivgen(int argc, VAL
|
||||
OPENSSL_cleanse(key, sizeof key);
|
||||
OPENSSL_cleanse(iv, sizeof iv);
|
||||
|
||||
+ rb_ivar_set(self, id_key_set, Qtrue);
|
||||
+
|
||||
return Qnil;
|
||||
}
|
||||
|
||||
@@ -396,6 +393,9 @@ ossl_cipher_update(int argc, VALUE *argv
|
||||
|
||||
rb_scan_args(argc, argv, "11", &data, &str);
|
||||
|
||||
+ if (!RTEST(rb_attr_get(self, id_key_set)))
|
||||
+ ossl_raise(eCipherError, "key not set");
|
||||
+
|
||||
StringValue(data);
|
||||
in = (unsigned char *)RSTRING_PTR(data);
|
||||
if ((in_len = RSTRING_LEN(data)) == 0)
|
||||
@@ -495,6 +495,8 @@ ossl_cipher_set_key(VALUE self, VALUE ke
|
||||
if (EVP_CipherInit_ex(ctx, NULL, NULL, (unsigned char *)RSTRING_PTR(key), NULL, -1) != 1)
|
||||
ossl_raise(eCipherError, NULL);
|
||||
|
||||
+ rb_ivar_set(self, id_key_set, Qtrue);
|
||||
+
|
||||
return key;
|
||||
}
|
||||
|
||||
@@ -1013,5 +1015,7 @@ Init_ossl_cipher(void)
|
||||
rb_define_method(cCipher, "iv_len", ossl_cipher_iv_length, 0);
|
||||
rb_define_method(cCipher, "block_size", ossl_cipher_block_size, 0);
|
||||
rb_define_method(cCipher, "padding=", ossl_cipher_set_padding, 1);
|
||||
+
|
||||
+ id_key_set = rb_intern_const("key_set");
|
||||
}
|
||||
|
||||
Index: ruby-2.2.2/test/openssl/test_cipher.rb
|
||||
===================================================================
|
||||
--- ruby-2.2.2.orig/test/openssl/test_cipher.rb
|
||||
+++ ruby-2.2.2/test/openssl/test_cipher.rb
|
||||
@@ -80,6 +80,7 @@ class OpenSSL::TestCipher < Test::Unit::
|
||||
|
||||
def test_empty_data
|
||||
@c1.encrypt
|
||||
+ @c1.random_key
|
||||
assert_raise(ArgumentError){ @c1.update("") }
|
||||
end
|
||||
|
||||
@@ -127,13 +128,10 @@ class OpenSSL::TestCipher < Test::Unit::
|
||||
assert_equal(pt, c2.update(ct) + c2.final)
|
||||
}
|
||||
end
|
||||
-
|
||||
- def test_AES_crush
|
||||
- 500.times do
|
||||
- assert_nothing_raised("[Bug #2768]") do
|
||||
- # it caused OpenSSL SEGV by uninitialized key
|
||||
- OpenSSL::Cipher::AES128.new("ECB").update "." * 17
|
||||
- end
|
||||
+ def test_update_raise_if_key_not_set
|
||||
+ assert_raise(OpenSSL::Cipher::CipherError) do
|
||||
+ # it caused OpenSSL SEGV by uninitialized key [Bug #2768]
|
||||
+ OpenSSL::Cipher::AES128.new("ECB").update "." * 17
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -236,6 +234,23 @@ class OpenSSL::TestCipher < Test::Unit::
|
||||
end
|
||||
|
||||
end
|
||||
+ def test_aes_gcm_key_iv_order_issue
|
||||
+ pt = "[ruby/openssl#49]"
|
||||
+ cipher = OpenSSL::Cipher.new("aes-128-gcm").encrypt
|
||||
+ cipher.key = "x" * 16
|
||||
+ cipher.iv = "a" * 12
|
||||
+ ct1 = cipher.update(pt) << cipher.final
|
||||
+ tag1 = cipher.auth_tag
|
||||
+
|
||||
+ cipher = OpenSSL::Cipher.new("aes-128-gcm").encrypt
|
||||
+ cipher.iv = "a" * 12
|
||||
+ cipher.key = "x" * 16
|
||||
+ ct2 = cipher.update(pt) << cipher.final
|
||||
+ tag2 = cipher.auth_tag
|
||||
+
|
||||
+ assert_equal ct1, ct2
|
||||
+ assert_equal tag1, tag2
|
||||
+ end if has_cipher?("aes-128-gcm")
|
||||
|
||||
private
|
||||
|
|
@ -3,7 +3,9 @@ require ruby.inc
|
|||
SRC_URI[md5sum] = "bd8e349d4fb2c75d90817649674f94be"
|
||||
SRC_URI[sha256sum] = "30c4b31697a4ca4ea0c8db8ad30cf45e6690a0f09687e5d483c933c03ca335e3"
|
||||
|
||||
SRC_URI += "file://prevent-gc.patch"
|
||||
SRC_URI += "file://prevent-gc.patch \
|
||||
file://CVE-2016-7798.patch \
|
||||
"
|
||||
|
||||
# it's unknown to configure script, but then passed to extconf.rb
|
||||
# maybe it's not really needed as we're hardcoding the result with
|
||||
|
|
Loading…
Reference in New Issue
Block a user