diff options
author | Dwayne Litzenberger <dlitz@dlitz.net> | 2013-07-14 10:55:06 -0700 |
---|---|---|
committer | Dwayne Litzenberger <dlitz@dlitz.net> | 2013-07-14 18:32:04 -0700 |
commit | b6ad2b47d9b7f3799c29097b4324dff2540fe77d (patch) | |
tree | add26f4b539dadecb45f21e265f04c827db195db /lib | |
parent | 0ee73a1b571f540cfca8d656853f2bc3df2e3767 (diff) | |
download | pycrypto-b6ad2b47d9b7f3799c29097b4324dff2540fe77d.tar.gz |
Counter: Deprecate disable_shortcut; Remove __PCT_CTR_SHORTCUT__ entirely
The `disable_shortcut` option served as a workaround in case
`__PCT_CTR_SHORTCUT__` leaked through a wrapper object, but I don't
think anyone actually used it, and it was a bad idea to expose it as
part of the public API.
Now that we do strong type checking inside block_template.c, there
shoujld be no need to ever use this option. It's now a no-op, retained
for backward compatibility only. It will be removed in some future
version of PyCrypto.
Diffstat (limited to 'lib')
-rw-r--r-- | lib/Crypto/SelfTest/Cipher/common.py | 43 | ||||
-rw-r--r-- | lib/Crypto/SelfTest/Util/test_Counter.py | 20 | ||||
-rw-r--r-- | lib/Crypto/Util/Counter.py | 20 | ||||
-rw-r--r-- | lib/Crypto/pct_warnings.py | 3 |
4 files changed, 56 insertions, 30 deletions
diff --git a/lib/Crypto/SelfTest/Cipher/common.py b/lib/Crypto/SelfTest/Cipher/common.py index 26fabed..4d6edf0 100644 --- a/lib/Crypto/SelfTest/Cipher/common.py +++ b/lib/Crypto/SelfTest/Cipher/common.py @@ -24,6 +24,8 @@ """Self-testing for PyCrypto hash modules""" +from __future__ import nested_scopes + __revision__ = "$Id$" import sys @@ -195,18 +197,43 @@ class CTRWraparoundTest(unittest.TestCase): self.module_name = params.get('module_name', None) def shortDescription(self): - return """Regression test: %s with MODE_CTR should raise OverflowError on wraparound when shortcut used""" % (self.module_name,) + return """Regression test: %s with MODE_CTR raising OverflowError on wraparound""" % (self.module_name,) def runTest(self): from Crypto.Util import Counter - for disable_shortcut in (0, 1): # (False, True) Test CTR-mode shortcut and PyObject_CallObject code paths - for little_endian in (0, 1): # (False, True) Test both endiannesses - ctr = Counter.new(8*self.module.block_size, initial_value=2L**(8*self.module.block_size)-1, little_endian=little_endian, disable_shortcut=disable_shortcut) - cipher = self.module.new(a2b_hex(self.key), self.module.MODE_CTR, counter=ctr) - block = b("\x00") * self.module.block_size - cipher.encrypt(block) - self.assertRaises(OverflowError, cipher.encrypt, block) + def pythonCounter(): + state = [0] + def ctr(): + # First block succeeds; Second and subsequent blocks raise OverflowError + if state[0] == 0: + state[0] = 1 + return b("\xff") * self.module.block_size + else: + raise OverflowError + return ctr + + for little_endian in (0, 1): # (False, True) Test both endiannesses + block = b("\x00") * self.module.block_size + + # Test PyObject_CallObject code path: if the counter raises OverflowError + cipher = self.module.new(a2b_hex(self.key), self.module.MODE_CTR, counter=pythonCounter()) + cipher.encrypt(block) + self.assertRaises(OverflowError, cipher.encrypt, block) + self.assertRaises(OverflowError, cipher.encrypt, block) + + # Test PyObject_CallObject code path: counter object should raise OverflowError + ctr = Counter.new(8*self.module.block_size, initial_value=2L**(8*self.module.block_size)-1, little_endian=little_endian) + ctr() + self.assertRaises(OverflowError, ctr) + self.assertRaises(OverflowError, ctr) + + # Test the CTR-mode shortcut + ctr = Counter.new(8*self.module.block_size, initial_value=2L**(8*self.module.block_size)-1, little_endian=little_endian) + cipher = self.module.new(a2b_hex(self.key), self.module.MODE_CTR, counter=ctr) + cipher.encrypt(block) + self.assertRaises(OverflowError, cipher.encrypt, block) + self.assertRaises(OverflowError, cipher.encrypt, block) class CFBSegmentSizeTest(unittest.TestCase): diff --git a/lib/Crypto/SelfTest/Util/test_Counter.py b/lib/Crypto/SelfTest/Util/test_Counter.py index 33c9bd7..7dbfc97 100644 --- a/lib/Crypto/SelfTest/Util/test_Counter.py +++ b/lib/Crypto/SelfTest/Util/test_Counter.py @@ -39,34 +39,24 @@ class CounterTests(unittest.TestCase): from Crypto.Util import Counter def test_BE_shortcut(self): - """Big endian, shortcut enabled""" + """Big endian""" c = Counter.new(128) - self.assertEqual(c.__PCT_CTR_SHORTCUT__,True) # assert_ c = Counter.new(128, little_endian=False) - self.assertEqual(c.__PCT_CTR_SHORTCUT__,True) # assert_ - c = Counter.new(128, disable_shortcut=False) - self.assertEqual(c.__PCT_CTR_SHORTCUT__,True) # assert_ - c = Counter.new(128, little_endian=False, disable_shortcut=False) - self.assertEqual(c.__PCT_CTR_SHORTCUT__,True) # assert_ def test_LE_shortcut(self): - """Little endian, shortcut enabled""" + """Little endian""" c = Counter.new(128, little_endian=True) - self.assertEqual(c.__PCT_CTR_SHORTCUT__,True) # assert_ - c = Counter.new(128, little_endian=True, disable_shortcut=False) - self.assertEqual(c.__PCT_CTR_SHORTCUT__,True) # assert_ def test_BE_no_shortcut(self): - """Big endian, shortcut disabled""" + """Big endian, with disable_shortcut""" + # Just testing API backward-compatibility. disable_shortcut is now a no-op. c = Counter.new(128, disable_shortcut=True) - self.assertRaises(AttributeError, getattr, c, '__PCT_CTR_SHORTCUT__') c = Counter.new(128, little_endian=False, disable_shortcut=True) - self.assertRaises(AttributeError, getattr, c, '__PCT_CTR_SHORTCUT__') def test_LE_no_shortcut(self): """Little endian, shortcut disabled""" + # Just testing API backward-compatibility. disable_shortcut is now a no-op. c = Counter.new(128, little_endian=True, disable_shortcut=True) - self.assertRaises(AttributeError, getattr, c, '__PCT_CTR_SHORTCUT__') def test_BE_defaults(self): """128-bit, Big endian, defaults""" diff --git a/lib/Crypto/Util/Counter.py b/lib/Crypto/Util/Counter.py index 60e281c..2068fb3 100644 --- a/lib/Crypto/Util/Counter.py +++ b/lib/Crypto/Util/Counter.py @@ -57,11 +57,15 @@ if sys.version_info[0] == 2 and sys.version_info[1] == 1: from Crypto.Util.py21compat import * from Crypto.Util.py3compat import * +from Crypto.pct_warnings import DisableShortcut_DeprecationWarning from Crypto.Util import _counter import struct +import warnings + # Factory function -def new(nbits, prefix=b(""), suffix=b(""), initial_value=1, overflow=0, little_endian=False, allow_wraparound=False, disable_shortcut=False): +_deprecated = "deprecated" +def new(nbits, prefix=b(""), suffix=b(""), initial_value=1, overflow=0, little_endian=False, allow_wraparound=False, disable_shortcut=_deprecated): """Create a stateful counter block function suitable for CTR encryption modes. Each call to the function returns the next counter block. @@ -89,10 +93,9 @@ def new(nbits, prefix=b(""), suffix=b(""), initial_value=1, overflow=0, little_e If True, the function will raise an *OverflowError* exception as soon as the counter wraps around. If False (default), the counter will simply restart from zero. - disable_shortcut : boolean - If True, do not make ciphers from `Crypto.Cipher` bypass the Python - layer when invoking the counter block function. - If False (default), bypass the Python layer. + disable_shortcut : deprecated + This option is a no-op for backward compatibility. It will be removed + in a future version. Don't use it. :Returns: The counter block function. """ @@ -109,10 +112,13 @@ def new(nbits, prefix=b(""), suffix=b(""), initial_value=1, overflow=0, little_e initval = _encode(initial_value, nbytes, little_endian) + if disable_shortcut is not _deprecated: # exact object comparison + warnings.warn("disable_shortcut has no effect and is deprecated", DisableShortcut_DeprecationWarning) + if little_endian: - return _counter._newLE(bstr(prefix), bstr(suffix), initval, allow_wraparound=allow_wraparound, disable_shortcut=disable_shortcut) + return _counter._newLE(bstr(prefix), bstr(suffix), initval, allow_wraparound=allow_wraparound) else: - return _counter._newBE(bstr(prefix), bstr(suffix), initval, allow_wraparound=allow_wraparound, disable_shortcut=disable_shortcut) + return _counter._newBE(bstr(prefix), bstr(suffix), initval, allow_wraparound=allow_wraparound) def _encode(n, nbytes, little_endian=False): retval = [] diff --git a/lib/Crypto/pct_warnings.py b/lib/Crypto/pct_warnings.py index 9b4361e..d6adc5b 100644 --- a/lib/Crypto/pct_warnings.py +++ b/lib/Crypto/pct_warnings.py @@ -49,6 +49,9 @@ class ClockRewindWarning(CryptoRuntimeWarning): class GetRandomNumber_DeprecationWarning(CryptoDeprecationWarning): """Issued when Crypto.Util.number.getRandomNumber is invoked.""" +class DisableShortcut_DeprecationWarning(CryptoDeprecationWarning): + """Issued when Counter.new(disable_shortcut=...) is invoked.""" + class PowmInsecureWarning(CryptoRuntimeWarning): """Warning for when _fastmath is built without mpz_powm_sec""" |