diff options
| author | Thiruvadi Rajaraman <trajaraman@mvista.com> | 2017-11-04 10:30:06 -0700 |
|---|---|---|
| committer | Richard Purdie <richard.purdie@linuxfoundation.org> | 2017-11-21 14:43:55 +0000 |
| commit | cab5a620accb47478b477a4a928032a53ed8baf8 (patch) | |
| tree | 612c4165a0171106a5a42bdc89d35e6fb6e64521 /meta/recipes-devtools/ruby | |
| parent | fe8a56109b0c2c4f030994307bd86e406bfb1be3 (diff) | |
| download | poky-cab5a620accb47478b477a4a928032a53ed8baf8.tar.gz | |
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>
Diffstat (limited to 'meta/recipes-devtools/ruby')
| -rw-r--r-- | meta/recipes-devtools/ruby/ruby/CVE-2016-7798.patch | 164 | ||||
| -rw-r--r-- | meta/recipes-devtools/ruby/ruby_2.2.5.bb | 4 |
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 @@ | |||
| 1 | cipher: don't set dummy encryption key in Cipher#initialize | ||
| 2 | Remove the encryption key initialization from Cipher#initialize. This | ||
| 3 | is effectively a revert of r32723 ("Avoid possible SEGV from AES | ||
| 4 | encryption/decryption", 2011-07-28). | ||
| 5 | |||
| 6 | r32723, which added the key initialization, was a workaround for | ||
| 7 | Ruby Bug #2768. For some certain ciphers, calling EVP_CipherUpdate() | ||
| 8 | before setting an encryption key caused segfault. It was not a problem | ||
| 9 | until OpenSSL implemented GCM mode - the encryption key could be | ||
| 10 | overridden by repeated calls of EVP_CipherInit_ex(). But, it is not the | ||
| 11 | case for AES-GCM ciphers. Setting a key, an IV, a key, in this order | ||
| 12 | causes the IV to be reset to an all-zero IV. | ||
| 13 | |||
| 14 | The problem of Bug #2768 persists on the current versions of OpenSSL. | ||
| 15 | So, make Cipher#update raise an exception if a key is not yet set by the | ||
| 16 | user. Since encrypting or decrypting without key does not make any | ||
| 17 | sense, this should not break existing applications. | ||
| 18 | |||
| 19 | Users can still call Cipher#key= and Cipher#iv= multiple times with | ||
| 20 | their own responsibility. | ||
| 21 | |||
| 22 | Reference: https://bugs.ruby-lang.org/issues/2768 | ||
| 23 | Reference: https://bugs.ruby-lang.org/issues/8221 | ||
| 24 | |||
| 25 | Upstream-Status: Backport | ||
| 26 | CVE: CVE-2016-7798 | ||
| 27 | |||
| 28 | Signed-off-by: Thiruvadi Rajaraman <trajaraman@mvista.com> | ||
| 29 | |||
| 30 | Index: ruby-2.2.2/ext/openssl/ossl_cipher.c | ||
| 31 | =================================================================== | ||
| 32 | --- ruby-2.2.2.orig/ext/openssl/ossl_cipher.c | ||
| 33 | +++ ruby-2.2.2/ext/openssl/ossl_cipher.c | ||
| 34 | @@ -35,6 +35,7 @@ | ||
| 35 | */ | ||
| 36 | VALUE cCipher; | ||
| 37 | VALUE eCipherError; | ||
| 38 | +static ID id_key_set; | ||
| 39 | |||
| 40 | static VALUE ossl_cipher_alloc(VALUE klass); | ||
| 41 | static void ossl_cipher_free(void *ptr); | ||
| 42 | @@ -119,7 +120,6 @@ ossl_cipher_initialize(VALUE self, VALUE | ||
| 43 | EVP_CIPHER_CTX *ctx; | ||
| 44 | const EVP_CIPHER *cipher; | ||
| 45 | char *name; | ||
| 46 | - unsigned char key[EVP_MAX_KEY_LENGTH]; | ||
| 47 | |||
| 48 | name = StringValuePtr(str); | ||
| 49 | GetCipherInit(self, ctx); | ||
| 50 | @@ -131,14 +131,7 @@ ossl_cipher_initialize(VALUE self, VALUE | ||
| 51 | if (!(cipher = EVP_get_cipherbyname(name))) { | ||
| 52 | ossl_raise(rb_eRuntimeError, "unsupported cipher algorithm (%s)", name); | ||
| 53 | } | ||
| 54 | - /* | ||
| 55 | - * The EVP which has EVP_CIPH_RAND_KEY flag (such as DES3) allows | ||
| 56 | - * uninitialized key, but other EVPs (such as AES) does not allow it. | ||
| 57 | - * Calling EVP_CipherUpdate() without initializing key causes SEGV so we | ||
| 58 | - * set the data filled with "\0" as the key by default. | ||
| 59 | - */ | ||
| 60 | - memset(key, 0, EVP_MAX_KEY_LENGTH); | ||
| 61 | - if (EVP_CipherInit_ex(ctx, cipher, NULL, key, NULL, -1) != 1) | ||
| 62 | + if (EVP_CipherInit_ex(ctx, cipher, NULL, NULL, NULL, -1) != 1) | ||
| 63 | ossl_raise(eCipherError, NULL); | ||
| 64 | |||
| 65 | return self; | ||
| 66 | @@ -256,6 +249,8 @@ ossl_cipher_init(int argc, VALUE *argv, | ||
| 67 | if (EVP_CipherInit_ex(ctx, NULL, NULL, p_key, p_iv, mode) != 1) { | ||
| 68 | ossl_raise(eCipherError, NULL); | ||
| 69 | } | ||
| 70 | + if (p_key) | ||
| 71 | + rb_ivar_set(self, id_key_set, Qtrue); | ||
| 72 | |||
| 73 | return self; | ||
| 74 | } | ||
| 75 | @@ -343,6 +338,8 @@ ossl_cipher_pkcs5_keyivgen(int argc, VAL | ||
| 76 | OPENSSL_cleanse(key, sizeof key); | ||
| 77 | OPENSSL_cleanse(iv, sizeof iv); | ||
| 78 | |||
| 79 | + rb_ivar_set(self, id_key_set, Qtrue); | ||
| 80 | + | ||
| 81 | return Qnil; | ||
| 82 | } | ||
| 83 | |||
| 84 | @@ -396,6 +393,9 @@ ossl_cipher_update(int argc, VALUE *argv | ||
| 85 | |||
| 86 | rb_scan_args(argc, argv, "11", &data, &str); | ||
| 87 | |||
| 88 | + if (!RTEST(rb_attr_get(self, id_key_set))) | ||
| 89 | + ossl_raise(eCipherError, "key not set"); | ||
| 90 | + | ||
| 91 | StringValue(data); | ||
| 92 | in = (unsigned char *)RSTRING_PTR(data); | ||
| 93 | if ((in_len = RSTRING_LEN(data)) == 0) | ||
| 94 | @@ -495,6 +495,8 @@ ossl_cipher_set_key(VALUE self, VALUE ke | ||
| 95 | if (EVP_CipherInit_ex(ctx, NULL, NULL, (unsigned char *)RSTRING_PTR(key), NULL, -1) != 1) | ||
| 96 | ossl_raise(eCipherError, NULL); | ||
| 97 | |||
| 98 | + rb_ivar_set(self, id_key_set, Qtrue); | ||
| 99 | + | ||
| 100 | return key; | ||
| 101 | } | ||
| 102 | |||
| 103 | @@ -1013,5 +1015,7 @@ Init_ossl_cipher(void) | ||
| 104 | rb_define_method(cCipher, "iv_len", ossl_cipher_iv_length, 0); | ||
| 105 | rb_define_method(cCipher, "block_size", ossl_cipher_block_size, 0); | ||
| 106 | rb_define_method(cCipher, "padding=", ossl_cipher_set_padding, 1); | ||
| 107 | + | ||
| 108 | + id_key_set = rb_intern_const("key_set"); | ||
| 109 | } | ||
| 110 | |||
| 111 | Index: ruby-2.2.2/test/openssl/test_cipher.rb | ||
| 112 | =================================================================== | ||
| 113 | --- ruby-2.2.2.orig/test/openssl/test_cipher.rb | ||
| 114 | +++ ruby-2.2.2/test/openssl/test_cipher.rb | ||
| 115 | @@ -80,6 +80,7 @@ class OpenSSL::TestCipher < Test::Unit:: | ||
| 116 | |||
| 117 | def test_empty_data | ||
| 118 | @c1.encrypt | ||
| 119 | + @c1.random_key | ||
| 120 | assert_raise(ArgumentError){ @c1.update("") } | ||
| 121 | end | ||
| 122 | |||
| 123 | @@ -127,13 +128,10 @@ class OpenSSL::TestCipher < Test::Unit:: | ||
| 124 | assert_equal(pt, c2.update(ct) + c2.final) | ||
| 125 | } | ||
| 126 | end | ||
| 127 | - | ||
| 128 | - def test_AES_crush | ||
| 129 | - 500.times do | ||
| 130 | - assert_nothing_raised("[Bug #2768]") do | ||
| 131 | - # it caused OpenSSL SEGV by uninitialized key | ||
| 132 | - OpenSSL::Cipher::AES128.new("ECB").update "." * 17 | ||
| 133 | - end | ||
| 134 | + def test_update_raise_if_key_not_set | ||
| 135 | + assert_raise(OpenSSL::Cipher::CipherError) do | ||
| 136 | + # it caused OpenSSL SEGV by uninitialized key [Bug #2768] | ||
| 137 | + OpenSSL::Cipher::AES128.new("ECB").update "." * 17 | ||
| 138 | end | ||
| 139 | end | ||
| 140 | end | ||
| 141 | @@ -236,6 +234,23 @@ class OpenSSL::TestCipher < Test::Unit:: | ||
| 142 | end | ||
| 143 | |||
| 144 | end | ||
| 145 | + def test_aes_gcm_key_iv_order_issue | ||
| 146 | + pt = "[ruby/openssl#49]" | ||
| 147 | + cipher = OpenSSL::Cipher.new("aes-128-gcm").encrypt | ||
| 148 | + cipher.key = "x" * 16 | ||
| 149 | + cipher.iv = "a" * 12 | ||
| 150 | + ct1 = cipher.update(pt) << cipher.final | ||
| 151 | + tag1 = cipher.auth_tag | ||
| 152 | + | ||
| 153 | + cipher = OpenSSL::Cipher.new("aes-128-gcm").encrypt | ||
| 154 | + cipher.iv = "a" * 12 | ||
| 155 | + cipher.key = "x" * 16 | ||
| 156 | + ct2 = cipher.update(pt) << cipher.final | ||
| 157 | + tag2 = cipher.auth_tag | ||
| 158 | + | ||
| 159 | + assert_equal ct1, ct2 | ||
| 160 | + assert_equal tag1, tag2 | ||
| 161 | + end if has_cipher?("aes-128-gcm") | ||
| 162 | |||
| 163 | private | ||
| 164 | |||
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 | |||
| 3 | SRC_URI[md5sum] = "bd8e349d4fb2c75d90817649674f94be" | 3 | SRC_URI[md5sum] = "bd8e349d4fb2c75d90817649674f94be" |
| 4 | SRC_URI[sha256sum] = "30c4b31697a4ca4ea0c8db8ad30cf45e6690a0f09687e5d483c933c03ca335e3" | 4 | SRC_URI[sha256sum] = "30c4b31697a4ca4ea0c8db8ad30cf45e6690a0f09687e5d483c933c03ca335e3" |
| 5 | 5 | ||
| 6 | SRC_URI += "file://prevent-gc.patch" | 6 | SRC_URI += "file://prevent-gc.patch \ |
| 7 | file://CVE-2016-7798.patch \ | ||
| 8 | " | ||
| 7 | 9 | ||
| 8 | # it's unknown to configure script, but then passed to extconf.rb | 10 | # it's unknown to configure script, but then passed to extconf.rb |
| 9 | # maybe it's not really needed as we're hardcoding the result with | 11 | # maybe it's not really needed as we're hardcoding the result with |
