-
Notifications
You must be signed in to change notification settings - Fork 171
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Possible bug: order of setting key vs. IV affects encryption with AES GCM #49
Comments
👍 |
Thank you for detailed analysis. From aes*_gcm_init_key() in crypto/evp/e_aes.c that is called through EVP_CipherInit_ex():
So Cipher#iv= does not preserve the IV in The pre-initialization in Cipher#initialize was added as the fix for https://bugs.ruby-lang.org/issues/2768. I still get the SEGV with The possible workaround is to remove the initialization and make Cipher#update check that a key is set by the user. |
Don't set an initial key in Cipher#initialize, and instead, make Cipher#update raise an exception if an encryption key not provided by user. We currently set the all-zero key as a workaround for [Bug #2768]. Calling EVP_CipherUpdate() with no key set can cause the process to crash for some certain ciphers. This has worked well for most others which don't have the issue, but not for aes-*-gcm ciphers. aes-*-gcm ciphers don't seem to expect the key to be set more than once - setting a key, an IV, a key in this order causes the IV to be discarded. An user can still call Cipher#key= multiple times, and this won't be rescued. Reference: https://bugs.ruby-lang.org/issues/2768 Reference: https://bugs.ruby-lang.org/issues/8221 Reference: ruby#49
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 Reference: #49
Fixed by 8108e0a. Thanks again. |
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 Reference: ruby/openssl#49 Closes: #842432 [CVE-2016-7798] Backportted for Debian by Christian Hofstaedtler <zeha@debian.org> Signed-off-by: Christian Hofstaedtler <zeha@debian.org> Signed-off-by: Antonio Terceiro <terceiro@debian.org>
Hello, I think I may have found a possible bug in the ruby openssl code for encryption.
If initialization vector is set before setting the encryption key when using one of the
AES-*-GCM
algorithms, the encryption does not take the IV into account at all and two different IVs (with the same key) produce the same encrypted ciphertext. If IV is set after the key, everything behaves perfectly OK. This issue does not affect other algorithms, only the AES-GCM ones.For more context about how I came to this conclusion, please see this stack overflow question and this pull request in the
encryptor
gem.Let me first show a simple test in ruby, to prove this issue:
When you run this test file, you'll get these results:
The critical lines are lines 5 and 6. They show that when the IV is set before the encryption key, the IV is not taken into account. Lines 1-4 show that it this behavior is not present in the CBC encryption mode.
I tried to do further tests and they suggest that this behavior is caused by the pre-initialization of the encryption key in
ossl_cipher.c
. In the following test, I tried to closely mimic the C calls that ruby-openssl makes when doing a very simple encryption task:The test tries to encrypt the same data as in the ruby test above, with IV set before / after the key and with or without the pre-initialization of the key. Compiling and running the test reveals the following:
The test shows that when the key pre-initialization (i.e. setting the key to all zeroes when configuring the cipher) is skipped, the IV, even if set before the encryption key, is correctly taken into account. On the other hand, when the pre-initialization takes place, the IV must be set after the key for the data to be encrypted correctly. I have not experienced any seg-faults when not preinitializing the key (a warning about this is present in the comment above the preinitialization code). I compiled and tested the code above against master branch of openssl as well as
openssl-1.0.1f
with the same results.Overall, this behavior seems to me like a bug. Nowhere in the ruby-openssl documentation I have found any mention about the order of setting IV vs key being relevant for the encryption process. I believe this should perhaps be more explicitly documented, because accidental setting IVs before keys with GCM algorithms would lead to a severe weakening of the whole encryption, without the user being warned in any way.
What do you think? Let me know if you need further info and thanks!
The text was updated successfully, but these errors were encountered: