diff options
author | Legrandin <helderijs@gmail.com> | 2013-12-22 22:24:46 +0100 |
---|---|---|
committer | Dwayne Litzenberger <dlitz@dlitz.net> | 2014-02-21 23:43:06 -0800 |
commit | 8dbe0dc3eea5c689d4f76b37b93fe216cf1f00d4 (patch) | |
tree | 26838a55707ebba81f6fedce36bb64ae1bd4959e | |
parent | 860523d288793d0ebc4867ea0d5234712562bc32 (diff) | |
download | pycrypto-8dbe0dc3eea5c689d4f76b37b93fe216cf1f00d4.tar.gz |
Throw exception when IV is used with ECB or CTR
The IV parameter is currently ignored when initializing
a cipher in ECB or CTR mode.
For CTR mode, it is confusing: it takes some time to see
that a different parameter is needed (the counter).
For ECB mode, it is outright dangerous.
This patch forces an exception to be raised.
-rw-r--r-- | lib/Crypto/SelfTest/Cipher/common.py | 31 | ||||
-rw-r--r-- | src/block_template.c | 11 |
2 files changed, 34 insertions, 8 deletions
diff --git a/lib/Crypto/SelfTest/Cipher/common.py b/lib/Crypto/SelfTest/Cipher/common.py index 420b6ff..a5f8a88 100644 --- a/lib/Crypto/SelfTest/Cipher/common.py +++ b/lib/Crypto/SelfTest/Cipher/common.py @@ -605,19 +605,34 @@ class RoundtripTest(unittest.TestCase): return """%s .decrypt() output of .encrypt() should not be garbled""" % (self.module_name,) def runTest(self): - for mode in (self.module.MODE_ECB, self.module.MODE_CBC, self.module.MODE_CFB, self.module.MODE_OFB, self.module.MODE_OPENPGP): + + ## ECB mode + mode = self.module.MODE_ECB + encryption_cipher = self.module.new(a2b_hex(self.key), mode) + ciphertext = encryption_cipher.encrypt(self.plaintext) + decryption_cipher = self.module.new(a2b_hex(self.key), mode) + decrypted_plaintext = decryption_cipher.decrypt(ciphertext) + self.assertEqual(self.plaintext, decrypted_plaintext) + + ## OPENPGP mode + mode = self.module.MODE_OPENPGP + encryption_cipher = self.module.new(a2b_hex(self.key), mode, self.iv) + eiv_ciphertext = encryption_cipher.encrypt(self.plaintext) + eiv = eiv_ciphertext[:self.module.block_size+2] + ciphertext = eiv_ciphertext[self.module.block_size+2:] + decryption_cipher = self.module.new(a2b_hex(self.key), mode, eiv) + decrypted_plaintext = decryption_cipher.decrypt(ciphertext) + self.assertEqual(self.plaintext, decrypted_plaintext) + + ## All other non-AEAD modes (but CTR) + for mode in (self.module.MODE_CBC, self.module.MODE_CFB, self.module.MODE_OFB): encryption_cipher = self.module.new(a2b_hex(self.key), mode, self.iv) ciphertext = encryption_cipher.encrypt(self.plaintext) - - if mode != self.module.MODE_OPENPGP: - decryption_cipher = self.module.new(a2b_hex(self.key), mode, self.iv) - else: - eiv = ciphertext[:self.module.block_size+2] - ciphertext = ciphertext[self.module.block_size+2:] - decryption_cipher = self.module.new(a2b_hex(self.key), mode, eiv) + decryption_cipher = self.module.new(a2b_hex(self.key), mode, self.iv) decrypted_plaintext = decryption_cipher.decrypt(ciphertext) self.assertEqual(self.plaintext, decrypted_plaintext) + class PGPTest(unittest.TestCase): def __init__(self, module, params): unittest.TestCase.__init__(self) diff --git a/src/block_template.c b/src/block_template.c index f940e0e..d555ceb 100644 --- a/src/block_template.c +++ b/src/block_template.c @@ -158,6 +158,17 @@ ALGnew(PyObject *self, PyObject *args, PyObject *kwdict) "Key cannot be the null string"); return NULL; } + if (IVlen != 0 && mode == MODE_ECB) + { + PyErr_Format(PyExc_ValueError, "ECB mode does not use IV"); + return NULL; + } + if (IVlen != 0 && mode == MODE_CTR) + { + PyErr_Format(PyExc_ValueError, + "CTR mode needs counter parameter, not IV"); + return NULL; + } if (IVlen != BLOCK_SIZE && mode != MODE_ECB && mode != MODE_CTR) { PyErr_Format(PyExc_ValueError, |