| Brad Bishop | 6e60e8b | 2018-02-01 10:27:11 -0500 | [diff] [blame] | 1 | From 8dbe0dc3eea5c689d4f76b37b93fe216cf1f00d4 Mon Sep 17 00:00:00 2001 | 
|  | 2 | From: Legrandin <helderijs@gmail.com> | 
|  | 3 | Date: Sun, 22 Dec 2013 22:24:46 +0100 | 
|  | 4 | Subject: [PATCH] Throw exception when IV is used with ECB or CTR | 
|  | 5 |  | 
|  | 6 | The IV parameter is currently ignored when initializing | 
|  | 7 | a cipher in ECB or CTR mode. | 
|  | 8 |  | 
|  | 9 | For CTR mode, it is confusing: it takes some time to see | 
|  | 10 | that a different parameter is needed (the counter). | 
|  | 11 |  | 
|  | 12 | For ECB mode, it is outright dangerous. | 
|  | 13 |  | 
|  | 14 | This patch forces an exception to be raised. | 
|  | 15 |  | 
|  | 16 | Upstream-Status: Backport | 
|  | 17 | [https://github.com/dlitz/pycrypto/commit/8dbe0dc3eea5c689d4f76b37b93fe216cf1f00d4] | 
|  | 18 |  | 
|  | 19 | CVE: CVE-2013-7459 | 
|  | 20 |  | 
|  | 21 | Signed-off-by: Yi Zhao <yi.zhao@windriver.com> | 
|  | 22 | --- | 
|  | 23 | lib/Crypto/SelfTest/Cipher/common.py | 31 +++++++++++++++++++++++-------- | 
|  | 24 | src/block_template.c                 | 11 +++++++++++ | 
|  | 25 | 2 files changed, 34 insertions(+), 8 deletions(-) | 
|  | 26 |  | 
|  | 27 | diff --git a/lib/Crypto/SelfTest/Cipher/common.py b/lib/Crypto/SelfTest/Cipher/common.py | 
|  | 28 | index 8bebed9..91ec743 100644 | 
|  | 29 | --- a/lib/Crypto/SelfTest/Cipher/common.py | 
|  | 30 | +++ b/lib/Crypto/SelfTest/Cipher/common.py | 
|  | 31 | @@ -239,19 +239,34 @@ class RoundtripTest(unittest.TestCase): | 
|  | 32 | return """%s .decrypt() output of .encrypt() should not be garbled""" % (self.module_name,) | 
|  | 33 |  | 
|  | 34 | def runTest(self): | 
|  | 35 | -        for mode in (self.module.MODE_ECB, self.module.MODE_CBC, self.module.MODE_CFB, self.module.MODE_OFB, self.module.MODE_OPENPGP): | 
|  | 36 | + | 
|  | 37 | +        ## ECB mode | 
|  | 38 | +        mode = self.module.MODE_ECB | 
|  | 39 | +        encryption_cipher = self.module.new(a2b_hex(self.key), mode) | 
|  | 40 | +        ciphertext = encryption_cipher.encrypt(self.plaintext) | 
|  | 41 | +        decryption_cipher = self.module.new(a2b_hex(self.key), mode) | 
|  | 42 | +        decrypted_plaintext = decryption_cipher.decrypt(ciphertext) | 
|  | 43 | +        self.assertEqual(self.plaintext, decrypted_plaintext) | 
|  | 44 | + | 
|  | 45 | +        ## OPENPGP mode | 
|  | 46 | +        mode = self.module.MODE_OPENPGP | 
|  | 47 | +        encryption_cipher = self.module.new(a2b_hex(self.key), mode, self.iv) | 
|  | 48 | +        eiv_ciphertext = encryption_cipher.encrypt(self.plaintext) | 
|  | 49 | +        eiv = eiv_ciphertext[:self.module.block_size+2] | 
|  | 50 | +        ciphertext = eiv_ciphertext[self.module.block_size+2:] | 
|  | 51 | +        decryption_cipher = self.module.new(a2b_hex(self.key), mode, eiv) | 
|  | 52 | +        decrypted_plaintext = decryption_cipher.decrypt(ciphertext) | 
|  | 53 | +        self.assertEqual(self.plaintext, decrypted_plaintext) | 
|  | 54 | + | 
|  | 55 | +        ## All other non-AEAD modes (but CTR) | 
|  | 56 | +        for mode in (self.module.MODE_CBC, self.module.MODE_CFB, self.module.MODE_OFB): | 
|  | 57 | encryption_cipher = self.module.new(a2b_hex(self.key), mode, self.iv) | 
|  | 58 | ciphertext = encryption_cipher.encrypt(self.plaintext) | 
|  | 59 | - | 
|  | 60 | -            if mode != self.module.MODE_OPENPGP: | 
|  | 61 | -                decryption_cipher = self.module.new(a2b_hex(self.key), mode, self.iv) | 
|  | 62 | -            else: | 
|  | 63 | -                eiv = ciphertext[:self.module.block_size+2] | 
|  | 64 | -                ciphertext = ciphertext[self.module.block_size+2:] | 
|  | 65 | -                decryption_cipher = self.module.new(a2b_hex(self.key), mode, eiv) | 
|  | 66 | +            decryption_cipher = self.module.new(a2b_hex(self.key), mode, self.iv) | 
|  | 67 | decrypted_plaintext = decryption_cipher.decrypt(ciphertext) | 
|  | 68 | self.assertEqual(self.plaintext, decrypted_plaintext) | 
|  | 69 |  | 
|  | 70 | + | 
|  | 71 | class PGPTest(unittest.TestCase): | 
|  | 72 | def __init__(self, module, params): | 
|  | 73 | unittest.TestCase.__init__(self) | 
|  | 74 | diff --git a/src/block_template.c b/src/block_template.c | 
|  | 75 | index c36b316..8746948 100644 | 
|  | 76 | --- a/src/block_template.c | 
|  | 77 | +++ b/src/block_template.c | 
|  | 78 | @@ -170,6 +170,17 @@ ALGnew(PyObject *self, PyObject *args, PyObject *kwdict) | 
|  | 79 | "Key cannot be the null string"); | 
|  | 80 | return NULL; | 
|  | 81 | } | 
|  | 82 | +	if (IVlen != 0 && mode == MODE_ECB) | 
|  | 83 | +	{ | 
|  | 84 | +		PyErr_Format(PyExc_ValueError, "ECB mode does not use IV"); | 
|  | 85 | +		return NULL; | 
|  | 86 | +	} | 
|  | 87 | +	if (IVlen != 0 && mode == MODE_CTR) | 
|  | 88 | +	{ | 
|  | 89 | +		PyErr_Format(PyExc_ValueError, | 
|  | 90 | +			"CTR mode needs counter parameter, not IV"); | 
|  | 91 | +		return NULL; | 
|  | 92 | +	} | 
|  | 93 | if (IVlen != BLOCK_SIZE && mode != MODE_ECB && mode != MODE_CTR) | 
|  | 94 | { | 
|  | 95 | PyErr_Format(PyExc_ValueError, | 
|  | 96 | -- | 
|  | 97 | 2.7.4 | 
|  | 98 |  |