VYPR
High severity7.5NVD Advisory· Published Jan 30, 2017· Updated May 13, 2026

CVE-2016-7798

CVE-2016-7798

Description

The openssl gem for Ruby uses the same initialization vector (IV) in GCM Mode (aes-*-gcm) when the IV is set before the key, which makes it easier for context-dependent attackers to bypass the encryption protection mechanism.

Affected packages

Versions sourced from the GitHub Security Advisory.

PackageAffected versionsPatched versions
opensslRubyGems
< 2.0.02.0.0

Patches

1
8108e0a6db13

cipher: don't set dummy encryption key in Cipher#initialize

https://github.com/ruby/opensslKazuki YamaguchiSep 20, 2016via ghsa
2 files changed · +36 18
  • ext/openssl/ossl_cipher.c+13 12 modified
    @@ -36,7 +36,7 @@
      */
     VALUE cCipher;
     VALUE eCipherError;
    -static ID id_auth_tag_len;
    +static ID id_auth_tag_len, id_key_set;
     
     static VALUE ossl_cipher_alloc(VALUE klass);
     static void ossl_cipher_free(void *ptr);
    @@ -118,7 +118,6 @@ ossl_cipher_initialize(VALUE self, VALUE str)
         EVP_CIPHER_CTX *ctx;
         const EVP_CIPHER *cipher;
         char *name;
    -    unsigned char dummy_key[EVP_MAX_KEY_LENGTH] = { 0 };
     
         name = StringValueCStr(str);
         GetCipherInit(self, ctx);
    @@ -129,16 +128,7 @@ ossl_cipher_initialize(VALUE self, VALUE str)
         if (!(cipher = EVP_get_cipherbyname(name))) {
     	ossl_raise(rb_eRuntimeError, "unsupported cipher algorithm (%"PRIsVALUE")", str);
         }
    -    /*
    -     * EVP_CipherInit_ex() allows to specify NULL to key and IV, however some
    -     * ciphers don't handle well (OpenSSL's bug). [Bug #2768]
    -     *
    -     * 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.
    -     */
    -    if (EVP_CipherInit_ex(ctx, cipher, NULL, dummy_key, NULL, -1) != 1)
    +    if (EVP_CipherInit_ex(ctx, cipher, NULL, NULL, NULL, -1) != 1)
     	ossl_raise(eCipherError, NULL);
     
         return self;
    @@ -251,6 +241,9 @@ ossl_cipher_init(int argc, VALUE *argv, VALUE self, int mode)
     	ossl_raise(eCipherError, NULL);
         }
     
    +    if (p_key)
    +	rb_ivar_set(self, id_key_set, Qtrue);
    +
         return self;
     }
     
    @@ -337,6 +330,8 @@ ossl_cipher_pkcs5_keyivgen(int argc, VALUE *argv, VALUE self)
         OPENSSL_cleanse(key, sizeof key);
         OPENSSL_cleanse(iv, sizeof iv);
     
    +    rb_ivar_set(self, id_key_set, Qtrue);
    +
         return Qnil;
     }
     
    @@ -387,6 +382,9 @@ ossl_cipher_update(int argc, VALUE *argv, VALUE self)
     
         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)
    @@ -488,6 +486,8 @@ ossl_cipher_set_key(VALUE self, VALUE key)
         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;
     }
     
    @@ -1082,4 +1082,5 @@ Init_ossl_cipher(void)
         rb_define_method(cCipher, "padding=", ossl_cipher_set_padding, 1);
     
         id_auth_tag_len = rb_intern_const("auth_tag_len");
    +    id_key_set = rb_intern_const("key_set");
     }
    
  • test/test_cipher.rb+23 6 modified
    @@ -90,6 +90,7 @@ def test_key_iv_set
     
       def test_empty_data
         @c1.encrypt
    +    @c1.random_key
         assert_raise(ArgumentError){ @c1.update("") }
       end
     
    @@ -136,12 +137,10 @@ def test_AES
         }
       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
     
    @@ -317,6 +316,24 @@ def test_aes_ocb_tag_len
         }
       end if has_cipher?("aes-128-ocb")
     
    +  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
     
       def new_encryptor(algo)
    

Vulnerability mechanics

Generated by null/stub on May 9, 2026. Inputs: CWE entries + fix-commit diffs from this CVE's patches. Citations validated against bundle.

References

12

News mentions

0

No linked articles in our index yet.