[前][次][番号順一覧][スレッド一覧]

ruby-changes:47152

From: usa <ko1@a...>
Date: Wed, 5 Jul 2017 16:06:51 +0900 (JST)
Subject: [ruby-changes:47152] usa:r59267 (ruby_2_3): * ext/openssl/ossl_cipher.c: remove the encryption key initialization

usa	2017-07-05 16:06:45 +0900 (Wed, 05 Jul 2017)

  New Revision: 59267

  https://svn.ruby-lang.org/cgi-bin/viewvc.cgi?view=revision&revision=59267

  Log:
    * ext/openssl/ossl_cipher.c: 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).
      the patch is derived from https://github.com/ruby/openssl/commit/8108e0a6db133f3375608303fdd2083eb5115062,
      written by Kazuki Yamaguchi.
      [Backport #8221]

  Modified files:
    branches/ruby_2_3/ChangeLog
    branches/ruby_2_3/ext/openssl/ossl_cipher.c
    branches/ruby_2_3/test/openssl/test_cipher.rb
    branches/ruby_2_3/version.h
Index: ruby_2_3/ChangeLog
===================================================================
--- ruby_2_3/ChangeLog	(revision 59266)
+++ ruby_2_3/ChangeLog	(revision 59267)
@@ -1,3 +1,12 @@ https://github.com/ruby/ruby/blob/trunk/ruby_2_3/ChangeLog#L1
+Wed Jul  5 15:55:35 2017  NAKAMURA Usaku  <usa@r...>
+
+	* ext/openssl/ossl_cipher.c: 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).
+	  the patch is derived from https://github.com/ruby/openssl/commit/8108e0a6db133f3375608303fdd2083eb5115062,
+	  written by Kazuki Yamaguchi.
+	  [Backport #8221]
+
 Sat Jul  1 00:28:22 2017  SHIBATA Hiroshi  <hsbt@r...>
 
 	* ext/psych/yaml: update libyaml to 0.1.7.
Index: ruby_2_3/ext/openssl/ossl_cipher.c
===================================================================
--- ruby_2_3/ext/openssl/ossl_cipher.c	(revision 59266)
+++ ruby_2_3/ext/openssl/ossl_cipher.c	(revision 59267)
@@ -34,6 +34,7 @@ https://github.com/ruby/ruby/blob/trunk/ruby_2_3/ext/openssl/ossl_cipher.c#L34
  */
 VALUE cCipher;
 VALUE eCipherError;
+static ID id_key_set;
 
 static VALUE ossl_cipher_alloc(VALUE klass);
 static void ossl_cipher_free(void *ptr);
@@ -114,7 +115,6 @@ ossl_cipher_initialize(VALUE self, VALUE https://github.com/ruby/ruby/blob/trunk/ruby_2_3/ext/openssl/ossl_cipher.c#L115
     EVP_CIPHER_CTX *ctx;
     const EVP_CIPHER *cipher;
     char *name;
-    unsigned char key[EVP_MAX_KEY_LENGTH];
 
     name = StringValuePtr(str);
     GetCipherInit(self, ctx);
@@ -126,14 +126,7 @@ ossl_cipher_initialize(VALUE self, VALUE https://github.com/ruby/ruby/blob/trunk/ruby_2_3/ext/openssl/ossl_cipher.c#L126
     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;
@@ -252,6 +245,9 @@ ossl_cipher_init(int argc, VALUE *argv, https://github.com/ruby/ruby/blob/trunk/ruby_2_3/ext/openssl/ossl_cipher.c#L245
 	ossl_raise(eCipherError, NULL);
     }
 
+    if (p_key)
+	rb_ivar_set(self, id_key_set, Qtrue);
+
     return self;
 }
 
@@ -338,6 +334,8 @@ ossl_cipher_pkcs5_keyivgen(int argc, VAL https://github.com/ruby/ruby/blob/trunk/ruby_2_3/ext/openssl/ossl_cipher.c#L334
     OPENSSL_cleanse(key, sizeof key);
     OPENSSL_cleanse(iv, sizeof iv);
 
+    rb_ivar_set(self, id_key_set, Qtrue);
+
     return Qnil;
 }
 
@@ -391,6 +389,9 @@ ossl_cipher_update(int argc, VALUE *argv https://github.com/ruby/ruby/blob/trunk/ruby_2_3/ext/openssl/ossl_cipher.c#L389
 
     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)
@@ -490,6 +491,8 @@ ossl_cipher_set_key(VALUE self, VALUE ke https://github.com/ruby/ruby/blob/trunk/ruby_2_3/ext/openssl/ossl_cipher.c#L491
     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;
 }
 
@@ -1008,4 +1011,6 @@ Init_ossl_cipher(void) https://github.com/ruby/ruby/blob/trunk/ruby_2_3/ext/openssl/ossl_cipher.c#L1011
     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_3/version.h
===================================================================
--- ruby_2_3/version.h	(revision 59266)
+++ ruby_2_3/version.h	(revision 59267)
@@ -1,10 +1,10 @@ https://github.com/ruby/ruby/blob/trunk/ruby_2_3/version.h#L1
 #define RUBY_VERSION "2.3.5"
-#define RUBY_RELEASE_DATE "2017-07-01"
-#define RUBY_PATCHLEVEL 339
+#define RUBY_RELEASE_DATE "2017-07-05"
+#define RUBY_PATCHLEVEL 340
 
 #define RUBY_RELEASE_YEAR 2017
 #define RUBY_RELEASE_MONTH 7
-#define RUBY_RELEASE_DAY 1
+#define RUBY_RELEASE_DAY 5
 
 #include "ruby/version.h"
 
Index: ruby_2_3/test/openssl/test_cipher.rb
===================================================================
--- ruby_2_3/test/openssl/test_cipher.rb	(revision 59266)
+++ ruby_2_3/test/openssl/test_cipher.rb	(revision 59267)
@@ -81,6 +81,7 @@ class OpenSSL::TestCipher < Test::Unit:: https://github.com/ruby/ruby/blob/trunk/ruby_2_3/test/openssl/test_cipher.rb#L81
 
   def test_empty_data
     @c1.encrypt
+    @c1.random_key
     assert_raise(ArgumentError){ @c1.update("") }
   end
 
@@ -129,12 +130,10 @@ class OpenSSL::TestCipher < Test::Unit:: https://github.com/ruby/ruby/blob/trunk/ruby_2_3/test/openssl/test_cipher.rb#L130
       }
     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 +235,24 @@ class OpenSSL::TestCipher < Test::Unit:: https://github.com/ruby/ruby/blob/trunk/ruby_2_3/test/openssl/test_cipher.rb#L235
       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")
+
   end
 
   private

--
ML: ruby-changes@q...
Info: http://www.atdot.net/~ko1/quickml/

[前][次][番号順一覧][スレッド一覧]