aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorThiruvadi Rajaraman <trajaraman@mvista.com>2017-11-04 10:30:06 -0700
committerRichard Purdie <richard.purdie@linuxfoundation.org>2017-11-21 14:42:57 +0000
commit6af2319008dc16c61092f71ff227c285aac51288 (patch)
treeeabae7c5e96b48609835bad198486773587aeb7c
parent3cd67ae472cf163a592aac6ca783e451068fca0c (diff)
downloadopenembedded-core-6af2319008dc16c61092f71ff227c285aac51288.tar.gz
openembedded-core-6af2319008dc16c61092f71ff227c285aac51288.tar.bz2
openembedded-core-6af2319008dc16c61092f71ff227c285aac51288.zip
ruby: Security fix for CVE-2016-7798
affectes ruby < 2.3.1 Signed-off-by: Thiruvadi Rajaraman <trajaraman@mvista.com> Signed-off-by: Armin Kuster <akuster@mvista.com>
-rw-r--r--meta/recipes-devtools/ruby/ruby/CVE-2016-7798.patch164
-rw-r--r--meta/recipes-devtools/ruby/ruby_2.2.5.bb4
2 files changed, 167 insertions, 1 deletions
diff --git a/meta/recipes-devtools/ruby/ruby/CVE-2016-7798.patch b/meta/recipes-devtools/ruby/ruby/CVE-2016-7798.patch
new file mode 100644
index 0000000000..2b8772ba41
--- /dev/null
+++ b/meta/recipes-devtools/ruby/ruby/CVE-2016-7798.patch
@@ -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
+
diff --git a/meta/recipes-devtools/ruby/ruby_2.2.5.bb b/meta/recipes-devtools/ruby/ruby_2.2.5.bb
index 66ba1d4b84..35882d18e6 100644
--- a/meta/recipes-devtools/ruby/ruby_2.2.5.bb
+++ b/meta/recipes-devtools/ruby/ruby_2.2.5.bb
@@ -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