diff options
-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 |