You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
python-crypto/pycrypto-2.6.1-use-os-rando...

1791 lines
61 KiB

--- lib/Crypto/Random/__init__.py
+++ lib/Crypto/Random/__init__.py
@@ -2,8 +2,6 @@
#
# Random/__init__.py : PyCrypto random number generation
#
-# Written in 2008 by Dwayne C. Litzenberger <dlitz@dlitz.net>
-#
# ===================================================================
# The contents of this file are dedicated to the public domain. To
# the extent that dedication to the public domain is not available,
@@ -22,22 +20,38 @@
# SOFTWARE.
# ===================================================================
-__revision__ = "$Id$"
-__all__ = ['new']
+__all__ = ['new', 'get_random_bytes']
+
+from os import urandom
+
+class _UrandomRNG(object):
+
+ def read(self, n):
+ """Return a random byte string of the desired size."""
+ return urandom(n)
+
+ def flush(self):
+ """Method provided for backward compatibility only."""
+ pass
+
+ def reinit(self):
+ """Method provided for backward compatibility only."""
+ pass
+
+ def close(self):
+ """Method provided for backward compatibility only."""
+ pass
-from Crypto.Random import OSRNG
-from Crypto.Random import _UserFriendlyRNG
def new(*args, **kwargs):
"""Return a file-like object that outputs cryptographically random bytes."""
- return _UserFriendlyRNG.new(*args, **kwargs)
+ return _UrandomRNG()
+
def atfork():
- """Call this whenever you call os.fork()"""
- _UserFriendlyRNG.reinit()
+ pass
+
-def get_random_bytes(n):
- """Return the specified number of cryptographically-strong random bytes."""
- return _UserFriendlyRNG.get_random_bytes(n)
+#: Function that returns a random byte string of the desired size.
+get_random_bytes = urandom
-# vim:set ts=4 sw=4 sts=4 expandtab:
--- lib/Crypto/Random/OSRNG/fallback.py
+++ /dev/null
@@ -1,46 +0,0 @@
-#
-# Random/OSRNG/fallback.py : Fallback entropy source for systems with os.urandom
-#
-# Written in 2008 by Dwayne C. Litzenberger <dlitz@dlitz.net>
-#
-# ===================================================================
-# The contents of this file are dedicated to the public domain. To
-# the extent that dedication to the public domain is not available,
-# everyone is granted a worldwide, perpetual, royalty-free,
-# non-exclusive license to exercise all rights associated with the
-# contents of this file for any purpose whatsoever.
-# No rights are reserved.
-#
-# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
-# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
-# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
-# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
-# BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
-# ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
-# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
-# SOFTWARE.
-# ===================================================================
-
-
-__revision__ = "$Id$"
-__all__ = ['PythonOSURandomRNG']
-
-import os
-
-from rng_base import BaseRNG
-
-class PythonOSURandomRNG(BaseRNG):
-
- name = "<os.urandom>"
-
- def __init__(self):
- self._read = os.urandom
- BaseRNG.__init__(self)
-
- def _close(self):
- self._read = None
-
-def new(*args, **kwargs):
- return PythonOSURandomRNG(*args, **kwargs)
-
-# vim:set ts=4 sw=4 sts=4 expandtab:
--- lib/Crypto/Random/OSRNG/__init__.py
+++ /dev/null
@@ -1,40 +0,0 @@
-#
-# Random/OSRNG/__init__.py : Platform-independent OS RNG API
-#
-# Written in 2008 by Dwayne C. Litzenberger <dlitz@dlitz.net>
-#
-# ===================================================================
-# The contents of this file are dedicated to the public domain. To
-# the extent that dedication to the public domain is not available,
-# everyone is granted a worldwide, perpetual, royalty-free,
-# non-exclusive license to exercise all rights associated with the
-# contents of this file for any purpose whatsoever.
-# No rights are reserved.
-#
-# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
-# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
-# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
-# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
-# BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
-# ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
-# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
-# SOFTWARE.
-# ===================================================================
-
-"""Provides a platform-independent interface to the random number generators
-supplied by various operating systems."""
-
-__revision__ = "$Id$"
-
-import os
-
-if os.name == 'posix':
- from Crypto.Random.OSRNG.posix import new
-elif os.name == 'nt':
- from Crypto.Random.OSRNG.nt import new
-elif hasattr(os, 'urandom'):
- from Crypto.Random.OSRNG.fallback import new
-else:
- raise ImportError("Not implemented")
-
-# vim:set ts=4 sw=4 sts=4 expandtab:
--- lib/Crypto/Random/OSRNG/nt.py
+++ /dev/null
@@ -1,74 +0,0 @@
-#
-# Random/OSRNG/nt.py : OS entropy source for MS Windows
-#
-# Written in 2008 by Dwayne C. Litzenberger <dlitz@dlitz.net>
-#
-# ===================================================================
-# The contents of this file are dedicated to the public domain. To
-# the extent that dedication to the public domain is not available,
-# everyone is granted a worldwide, perpetual, royalty-free,
-# non-exclusive license to exercise all rights associated with the
-# contents of this file for any purpose whatsoever.
-# No rights are reserved.
-#
-# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
-# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
-# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
-# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
-# BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
-# ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
-# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
-# SOFTWARE.
-# ===================================================================
-
-
-__revision__ = "$Id$"
-__all__ = ['WindowsRNG']
-
-import winrandom
-from rng_base import BaseRNG
-
-class WindowsRNG(BaseRNG):
-
- name = "<CryptGenRandom>"
-
- def __init__(self):
- self.__winrand = winrandom.new()
- BaseRNG.__init__(self)
-
- def flush(self):
- """Work around weakness in Windows RNG.
-
- The CryptGenRandom mechanism in some versions of Windows allows an
- attacker to learn 128 KiB of past and future output. As a workaround,
- this function reads 128 KiB of 'random' data from Windows and discards
- it.
-
- For more information about the weaknesses in CryptGenRandom, see
- _Cryptanalysis of the Random Number Generator of the Windows Operating
- System_, by Leo Dorrendorf and Zvi Gutterman and Benny Pinkas
- http://eprint.iacr.org/2007/419
- """
- if self.closed:
- raise ValueError("I/O operation on closed file")
- data = self.__winrand.get_bytes(128*1024)
- assert (len(data) == 128*1024)
- BaseRNG.flush(self)
-
- def _close(self):
- self.__winrand = None
-
- def _read(self, N):
- # Unfortunately, research shows that CryptGenRandom doesn't provide
- # forward secrecy and fails the next-bit test unless we apply a
- # workaround, which we do here. See http://eprint.iacr.org/2007/419
- # for information on the vulnerability.
- self.flush()
- data = self.__winrand.get_bytes(N)
- self.flush()
- return data
-
-def new(*args, **kwargs):
- return WindowsRNG(*args, **kwargs)
-
-# vim:set ts=4 sw=4 sts=4 expandtab:
--- lib/Crypto/Random/OSRNG/posix.py
+++ /dev/null
@@ -1,86 +0,0 @@
-#
-# Random/OSRNG/posix.py : OS entropy source for POSIX systems
-#
-# Written in 2008 by Dwayne C. Litzenberger <dlitz@dlitz.net>
-#
-# ===================================================================
-# The contents of this file are dedicated to the public domain. To
-# the extent that dedication to the public domain is not available,
-# everyone is granted a worldwide, perpetual, royalty-free,
-# non-exclusive license to exercise all rights associated with the
-# contents of this file for any purpose whatsoever.
-# No rights are reserved.
-#
-# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
-# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
-# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
-# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
-# BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
-# ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
-# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
-# SOFTWARE.
-# ===================================================================
-
-
-__revision__ = "$Id$"
-__all__ = ['DevURandomRNG']
-
-import errno
-import os
-import stat
-
-from rng_base import BaseRNG
-from Crypto.Util.py3compat import b
-
-class DevURandomRNG(BaseRNG):
-
- def __init__(self, devname=None):
- if devname is None:
- self.name = "/dev/urandom"
- else:
- self.name = devname
-
- # Test that /dev/urandom is a character special device
- f = open(self.name, "rb", 0)
- fmode = os.fstat(f.fileno())[stat.ST_MODE]
- if not stat.S_ISCHR(fmode):
- f.close()
- raise TypeError("%r is not a character special device" % (self.name,))
-
- self.__file = f
-
- BaseRNG.__init__(self)
-
- def _close(self):
- self.__file.close()
-
- def _read(self, N):
- # Starting with Python 3 open with buffering=0 returns a FileIO object.
- # FileIO.read behaves like read(2) and not like fread(3) and thus we
- # have to handle the case that read returns less data as requested here
- # more carefully.
- data = b("")
- while len(data) < N:
- try:
- d = self.__file.read(N - len(data))
- except IOError, e:
- # read(2) has been interrupted by a signal; redo the read
- if e.errno == errno.EINTR:
- continue
- raise
-
- if d is None:
- # __file is in non-blocking mode and no data is available
- return data
- if len(d) == 0:
- # __file is in blocking mode and arrived at EOF
- return data
-
- data += d
- return data
-
-def new(*args, **kwargs):
- return DevURandomRNG(*args, **kwargs)
-
-
-# vim:set ts=4 sw=4 sts=4 expandtab:
--- lib/Crypto/Random/OSRNG/rng_base.py
+++ /dev/null
@@ -1,88 +0,0 @@
-#
-# Random/OSRNG/rng_base.py : Base class for OSRNG
-#
-# Written in 2008 by Dwayne C. Litzenberger <dlitz@dlitz.net>
-#
-# ===================================================================
-# The contents of this file are dedicated to the public domain. To
-# the extent that dedication to the public domain is not available,
-# everyone is granted a worldwide, perpetual, royalty-free,
-# non-exclusive license to exercise all rights associated with the
-# contents of this file for any purpose whatsoever.
-# No rights are reserved.
-#
-# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
-# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
-# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
-# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
-# BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
-# ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
-# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
-# SOFTWARE.
-# ===================================================================
-
-__revision__ = "$Id$"
-
-import sys
-if sys.version_info[0] == 2 and sys.version_info[1] == 1:
- from Crypto.Util.py21compat import *
-
-class BaseRNG(object):
-
- def __init__(self):
- self.closed = False
- self._selftest()
-
- def __del__(self):
- self.close()
-
- def _selftest(self):
- # Test that urandom can return data
- data = self.read(16)
- if len(data) != 16:
- raise AssertionError("read truncated")
-
- # Test that we get different data every time (if we don't, the RNG is
- # probably malfunctioning)
- data2 = self.read(16)
- if data == data2:
- raise AssertionError("OS RNG returned duplicate data")
-
- # PEP 343: Support for the "with" statement
- def __enter__(self):
- pass
- def __exit__(self):
- """PEP 343 support"""
- self.close()
-
- def close(self):
- if not self.closed:
- self._close()
- self.closed = True
-
- def flush(self):
- pass
-
- def read(self, N=-1):
- """Return N bytes from the RNG."""
- if self.closed:
- raise ValueError("I/O operation on closed file")
- if not isinstance(N, (long, int)):
- raise TypeError("an integer is required")
- if N < 0:
- raise ValueError("cannot read to end of infinite stream")
- elif N == 0:
- return ""
- data = self._read(N)
- if len(data) != N:
- raise AssertionError("%s produced truncated output (requested %d, got %d)" % (self.name, N, len(data)))
- return data
-
- def _close(self):
- raise NotImplementedError("child class must implement this")
-
- def _read(self, N):
- raise NotImplementedError("child class must implement this")
-
-
-# vim:set ts=4 sw=4 sts=4 expandtab:
--- lib/Crypto/Random/_UserFriendlyRNG.py
+++ /dev/null
@@ -1,230 +0,0 @@
-# -*- coding: utf-8 -*-
-#
-# Random/_UserFriendlyRNG.py : A user-friendly random number generator
-#
-# Written in 2008 by Dwayne C. Litzenberger <dlitz@dlitz.net>
-#
-# ===================================================================
-# The contents of this file are dedicated to the public domain. To
-# the extent that dedication to the public domain is not available,
-# everyone is granted a worldwide, perpetual, royalty-free,
-# non-exclusive license to exercise all rights associated with the
-# contents of this file for any purpose whatsoever.
-# No rights are reserved.
-#
-# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
-# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
-# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
-# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
-# BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
-# ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
-# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
-# SOFTWARE.
-# ===================================================================
-
-__revision__ = "$Id$"
-
-import sys
-if sys.version_info[0] == 2 and sys.version_info[1] == 1:
- from Crypto.Util.py21compat import *
-
-import os
-import threading
-import struct
-import time
-from math import floor
-
-from Crypto.Random import OSRNG
-from Crypto.Random.Fortuna import FortunaAccumulator
-
-class _EntropySource(object):
- def __init__(self, accumulator, src_num):
- self._fortuna = accumulator
- self._src_num = src_num
- self._pool_num = 0
-
- def feed(self, data):
- self._fortuna.add_random_event(self._src_num, self._pool_num, data)
- self._pool_num = (self._pool_num + 1) & 31
-
-class _EntropyCollector(object):
-
- def __init__(self, accumulator):
- self._osrng = OSRNG.new()
- self._osrng_es = _EntropySource(accumulator, 255)
- self._time_es = _EntropySource(accumulator, 254)
- self._clock_es = _EntropySource(accumulator, 253)
-
- def reinit(self):
- # Add 256 bits to each of the 32 pools, twice. (For a total of 16384
- # bits collected from the operating system.)
- for i in range(2):
- block = self._osrng.read(32*32)
- for p in range(32):
- self._osrng_es.feed(block[p*32:(p+1)*32])
- block = None
- self._osrng.flush()
-
- def collect(self):
- # Collect 64 bits of entropy from the operating system and feed it to Fortuna.
- self._osrng_es.feed(self._osrng.read(8))
-
- # Add the fractional part of time.time()
- t = time.time()
- self._time_es.feed(struct.pack("@I", int(2**30 * (t - floor(t)))))
-
- # Add the fractional part of time.clock()
- t = time.clock()
- self._clock_es.feed(struct.pack("@I", int(2**30 * (t - floor(t)))))
-
-
-class _UserFriendlyRNG(object):
-
- def __init__(self):
- self.closed = False
- self._fa = FortunaAccumulator.FortunaAccumulator()
- self._ec = _EntropyCollector(self._fa)
- self.reinit()
-
- def reinit(self):
- """Initialize the random number generator and seed it with entropy from
- the operating system.
- """
-
- # Save the pid (helps ensure that Crypto.Random.atfork() gets called)
- self._pid = os.getpid()
-
- # Collect entropy from the operating system and feed it to
- # FortunaAccumulator
- self._ec.reinit()
-
- # Override FortunaAccumulator's 100ms minimum re-seed interval. This
- # is necessary to avoid a race condition between this function and
- # self.read(), which that can otherwise cause forked child processes to
- # produce identical output. (e.g. CVE-2013-1445)
- #
- # Note that if this function can be called frequently by an attacker,
- # (and if the bits from OSRNG are insufficiently random) it will weaken
- # Fortuna's ability to resist a state compromise extension attack.
- self._fa._forget_last_reseed()
-
- def close(self):
- self.closed = True
- self._osrng = None
- self._fa = None
-
- def flush(self):
- pass
-
- def read(self, N):
- """Return N bytes from the RNG."""
- if self.closed:
- raise ValueError("I/O operation on closed file")
- if not isinstance(N, (long, int)):
- raise TypeError("an integer is required")
- if N < 0:
- raise ValueError("cannot read to end of infinite stream")
-
- # Collect some entropy and feed it to Fortuna
- self._ec.collect()
-
- # Ask Fortuna to generate some bytes
- retval = self._fa.random_data(N)
-
- # Check that we haven't forked in the meantime. (If we have, we don't
- # want to use the data, because it might have been duplicated in the
- # parent process.
- self._check_pid()
-
- # Return the random data.
- return retval
-
- def _check_pid(self):
- # Lame fork detection to remind developers to invoke Random.atfork()
- # after every call to os.fork(). Note that this check is not reliable,
- # since process IDs can be reused on most operating systems.
- #
- # You need to do Random.atfork() in the child process after every call
- # to os.fork() to avoid reusing PRNG state. If you want to avoid
- # leaking PRNG state to child processes (for example, if you are using
- # os.setuid()) then you should also invoke Random.atfork() in the
- # *parent* process.
- if os.getpid() != self._pid:
- raise AssertionError("PID check failed. RNG must be re-initialized after fork(). Hint: Try Random.atfork()")
-
-
-class _LockingUserFriendlyRNG(_UserFriendlyRNG):
- def __init__(self):
- self._lock = threading.Lock()
- _UserFriendlyRNG.__init__(self)
-
- def close(self):
- self._lock.acquire()
- try:
- return _UserFriendlyRNG.close(self)
- finally:
- self._lock.release()
-
- def reinit(self):
- self._lock.acquire()
- try:
- return _UserFriendlyRNG.reinit(self)
- finally:
- self._lock.release()
-
- def read(self, bytes):
- self._lock.acquire()
- try:
- return _UserFriendlyRNG.read(self, bytes)
- finally:
- self._lock.release()
-
-class RNGFile(object):
- def __init__(self, singleton):
- self.closed = False
- self._singleton = singleton
-
- # PEP 343: Support for the "with" statement
- def __enter__(self):
- """PEP 343 support"""
- def __exit__(self):
- """PEP 343 support"""
- self.close()
-
- def close(self):
- # Don't actually close the singleton, just close this RNGFile instance.
- self.closed = True
- self._singleton = None
-
- def read(self, bytes):
- if self.closed:
- raise ValueError("I/O operation on closed file")
- return self._singleton.read(bytes)
-
- def flush(self):
- if self.closed:
- raise ValueError("I/O operation on closed file")
-
-_singleton_lock = threading.Lock()
-_singleton = None
-def _get_singleton():
- global _singleton
- _singleton_lock.acquire()
- try:
- if _singleton is None:
- _singleton = _LockingUserFriendlyRNG()
- return _singleton
- finally:
- _singleton_lock.release()
-
-def new():
- return RNGFile(_get_singleton())
-
-def reinit():
- _get_singleton().reinit()
-
-def get_random_bytes(n):
- """Return the specified number of cryptographically-strong random bytes."""
- return _get_singleton().read(n)
-
-# vim:set ts=4 sw=4 sts=4 expandtab:
--- lib/Crypto/SelfTest/Random/__init__.py
+++ lib/Crypto/SelfTest/Random/__init__.py
@@ -29,10 +29,8 @@ __revision__ = "$Id$"
def get_tests(config={}):
tests = []
from Crypto.SelfTest.Random import Fortuna; tests += Fortuna.get_tests(config=config)
- from Crypto.SelfTest.Random import OSRNG; tests += OSRNG.get_tests(config=config)
from Crypto.SelfTest.Random import test_random; tests += test_random.get_tests(config=config)
from Crypto.SelfTest.Random import test_rpoolcompat; tests += test_rpoolcompat.get_tests(config=config)
- from Crypto.SelfTest.Random import test__UserFriendlyRNG; tests += test__UserFriendlyRNG.get_tests(config=config)
return tests
if __name__ == '__main__':
--- lib/Crypto/SelfTest/Random/OSRNG/__init__.py
+++ /dev/null
@@ -1,49 +0,0 @@
-# -*- coding: utf-8 -*-
-#
-# SelfTest/Random/OSRNG/__init__.py: Self-test for OSRNG modules
-#
-# Written in 2008 by Dwayne C. Litzenberger <dlitz@dlitz.net>
-#
-# ===================================================================
-# The contents of this file are dedicated to the public domain. To
-# the extent that dedication to the public domain is not available,
-# everyone is granted a worldwide, perpetual, royalty-free,
-# non-exclusive license to exercise all rights associated with the
-# contents of this file for any purpose whatsoever.
-# No rights are reserved.
-#
-# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
-# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
-# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
-# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
-# BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
-# ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
-# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
-# SOFTWARE.
-# ===================================================================
-
-"""Self-test for Crypto.Random.OSRNG package"""
-
-__revision__ = "$Id$"
-
-import os
-
-def get_tests(config={}):
- tests = []
- if os.name == 'nt':
- from Crypto.SelfTest.Random.OSRNG import test_nt; tests += test_nt.get_tests(config=config)
- from Crypto.SelfTest.Random.OSRNG import test_winrandom; tests += test_winrandom.get_tests(config=config)
- elif os.name == 'posix':
- from Crypto.SelfTest.Random.OSRNG import test_posix; tests += test_posix.get_tests(config=config)
- if hasattr(os, 'urandom'):
- from Crypto.SelfTest.Random.OSRNG import test_fallback; tests += test_fallback.get_tests(config=config)
- from Crypto.SelfTest.Random.OSRNG import test_generic; tests += test_generic.get_tests(config=config)
- return tests
-
-if __name__ == '__main__':
- import unittest
- suite = lambda: unittest.TestSuite(get_tests())
- unittest.main(defaultTest='suite')
-
-
-# vim:set ts=4 sw=4 sts=4 expandtab:
--- lib/Crypto/SelfTest/Random/OSRNG/test_fallback.py
+++ /dev/null
@@ -1,48 +0,0 @@
-# -*- coding: utf-8 -*-
-#
-# SelfTest/Util/test_fallback.py: Self-test for the OSRNG.fallback.new() function
-#
-# Written in 2008 by Dwayne C. Litzenberger <dlitz@dlitz.net>
-#
-# ===================================================================
-# The contents of this file are dedicated to the public domain. To
-# the extent that dedication to the public domain is not available,
-# everyone is granted a worldwide, perpetual, royalty-free,
-# non-exclusive license to exercise all rights associated with the
-# contents of this file for any purpose whatsoever.
-# No rights are reserved.
-#
-# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
-# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
-# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
-# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
-# BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
-# ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
-# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
-# SOFTWARE.
-# ===================================================================
-
-"""Self-test suite for Crypto.Random.OSRNG.fallback"""
-
-__revision__ = "$Id$"
-
-import unittest
-
-class SimpleTest(unittest.TestCase):
- def runTest(self):
- """Crypto.Random.OSRNG.fallback.new()"""
- # Import the OSRNG.nt module and try to use it
- import Crypto.Random.OSRNG.fallback
- randobj = Crypto.Random.OSRNG.fallback.new()
- x = randobj.read(16)
- y = randobj.read(16)
- self.assertNotEqual(x, y)
-
-def get_tests(config={}):
- return [SimpleTest()]
-
-if __name__ == '__main__':
- suite = lambda: unittest.TestSuite(get_tests())
- unittest.main(defaultTest='suite')
-
-# vim:set ts=4 sw=4 sts=4 expandtab:
--- lib/Crypto/SelfTest/Random/OSRNG/test_generic.py
+++ /dev/null
@@ -1,48 +0,0 @@
-# -*- coding: utf-8 -*-
-#
-# SelfTest/Util/test_generic.py: Self-test for the OSRNG.new() function
-#
-# Written in 2008 by Dwayne C. Litzenberger <dlitz@dlitz.net>
-#
-# ===================================================================
-# The contents of this file are dedicated to the public domain. To
-# the extent that dedication to the public domain is not available,
-# everyone is granted a worldwide, perpetual, royalty-free,
-# non-exclusive license to exercise all rights associated with the
-# contents of this file for any purpose whatsoever.
-# No rights are reserved.
-#
-# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
-# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
-# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
-# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
-# BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
-# ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
-# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
-# SOFTWARE.
-# ===================================================================
-
-"""Self-test suite for Crypto.Random.OSRNG"""
-
-__revision__ = "$Id$"
-
-import unittest
-
-class SimpleTest(unittest.TestCase):
- def runTest(self):
- """Crypto.Random.OSRNG.new()"""
- # Import the OSRNG module and try to use it
- import Crypto.Random.OSRNG
- randobj = Crypto.Random.OSRNG.new()
- x = randobj.read(16)
- y = randobj.read(16)
- self.assertNotEqual(x, y)
-
-def get_tests(config={}):
- return [SimpleTest()]
-
-if __name__ == '__main__':
- suite = lambda: unittest.TestSuite(get_tests())
- unittest.main(defaultTest='suite')
-
-# vim:set ts=4 sw=4 sts=4 expandtab:
--- lib/Crypto/SelfTest/Random/OSRNG/test_nt.py
+++ /dev/null
@@ -1,48 +0,0 @@
-# -*- coding: utf-8 -*-
-#
-# SelfTest/Util/test_generic.py: Self-test for the OSRNG.nt.new() function
-#
-# Written in 2008 by Dwayne C. Litzenberger <dlitz@dlitz.net>
-#
-# ===================================================================
-# The contents of this file are dedicated to the public domain. To
-# the extent that dedication to the public domain is not available,
-# everyone is granted a worldwide, perpetual, royalty-free,
-# non-exclusive license to exercise all rights associated with the
-# contents of this file for any purpose whatsoever.
-# No rights are reserved.
-#
-# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
-# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
-# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
-# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
-# BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
-# ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
-# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
-# SOFTWARE.
-# ===================================================================
-
-"""Self-test suite for Crypto.Random.OSRNG.nt"""
-
-__revision__ = "$Id$"
-
-import unittest
-
-class SimpleTest(unittest.TestCase):
- def runTest(self):
- """Crypto.Random.OSRNG.nt.new()"""
- # Import the OSRNG.nt module and try to use it
- import Crypto.Random.OSRNG.nt
- randobj = Crypto.Random.OSRNG.nt.new()
- x = randobj.read(16)
- y = randobj.read(16)
- self.assertNotEqual(x, y)
-
-def get_tests(config={}):
- return [SimpleTest()]
-
-if __name__ == '__main__':
- suite = lambda: unittest.TestSuite(get_tests())
- unittest.main(defaultTest='suite')
-
-# vim:set ts=4 sw=4 sts=4 expandtab:
--- lib/Crypto/SelfTest/Random/OSRNG/test_posix.py
+++ /dev/null
@@ -1,48 +0,0 @@
-# -*- coding: utf-8 -*-
-#
-# SelfTest/Util/test_posix.py: Self-test for the OSRNG.posix.new() function
-#
-# Written in 2008 by Dwayne C. Litzenberger <dlitz@dlitz.net>
-#
-# ===================================================================
-# The contents of this file are dedicated to the public domain. To
-# the extent that dedication to the public domain is not available,
-# everyone is granted a worldwide, perpetual, royalty-free,
-# non-exclusive license to exercise all rights associated with the
-# contents of this file for any purpose whatsoever.
-# No rights are reserved.
-#
-# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
-# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
-# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
-# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
-# BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
-# ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
-# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
-# SOFTWARE.
-# ===================================================================
-
-"""Self-test suite for Crypto.Random.OSRNG.posix"""
-
-__revision__ = "$Id$"
-
-import unittest
-
-class SimpleTest(unittest.TestCase):
- def runTest(self):
- """Crypto.Random.OSRNG.posix.new()"""
- # Import the OSRNG.nt module and try to use it
- import Crypto.Random.OSRNG.posix
- randobj = Crypto.Random.OSRNG.posix.new()
- x = randobj.read(16)
- y = randobj.read(16)
- self.assertNotEqual(x, y)
-
-def get_tests(config={}):
- return [SimpleTest()]
-
-if __name__ == '__main__':
- suite = lambda: unittest.TestSuite(get_tests())
- unittest.main(defaultTest='suite')
-
-# vim:set ts=4 sw=4 sts=4 expandtab:
--- lib/Crypto/SelfTest/Random/OSRNG/test_winrandom.py
+++ /dev/null
@@ -1,48 +0,0 @@
-# -*- coding: utf-8 -*-
-#
-# SelfTest/Util/test_winrandom.py: Self-test for the winrandom module
-#
-# Written in 2008 by Dwayne C. Litzenberger <dlitz@dlitz.net>
-#
-# ===================================================================
-# The contents of this file are dedicated to the public domain. To
-# the extent that dedication to the public domain is not available,
-# everyone is granted a worldwide, perpetual, royalty-free,
-# non-exclusive license to exercise all rights associated with the
-# contents of this file for any purpose whatsoever.
-# No rights are reserved.
-#
-# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
-# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
-# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
-# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
-# BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
-# ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
-# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
-# SOFTWARE.
-# ===================================================================
-
-"""Self-test suite for Crypto.Random.OSRNG.winrandom"""
-
-__revision__ = "$Id$"
-
-import unittest
-
-class SimpleTest(unittest.TestCase):
- def runTest(self):
- """Crypto.Random.OSRNG.winrandom"""
- # Import the winrandom module and try to use it
- from Crypto.Random.OSRNG import winrandom
- randobj = winrandom.new()
- x = randobj.get_bytes(16)
- y = randobj.get_bytes(16)
- self.assertNotEqual(x, y)
-
-def get_tests(config={}):
- return [SimpleTest()]
-
-if __name__ == '__main__':
- suite = lambda: unittest.TestSuite(get_tests())
- unittest.main(defaultTest='suite')
-
-# vim:set ts=4 sw=4 sts=4 expandtab:
--- lib/Crypto/SelfTest/Random/test__UserFriendlyRNG.py
+++ /dev/null
@@ -1,171 +0,0 @@
-# -*- coding: utf-8 -*-
-# Self-tests for the user-friendly Crypto.Random interface
-#
-# Written in 2013 by Dwayne C. Litzenberger <dlitz@dlitz.net>
-#
-# ===================================================================
-# The contents of this file are dedicated to the public domain. To
-# the extent that dedication to the public domain is not available,
-# everyone is granted a worldwide, perpetual, royalty-free,
-# non-exclusive license to exercise all rights associated with the
-# contents of this file for any purpose whatsoever.
-# No rights are reserved.
-#
-# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
-# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
-# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
-# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
-# BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
-# ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
-# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
-# SOFTWARE.
-# ===================================================================
-
-"""Self-test suite for generic Crypto.Random stuff """
-
-from __future__ import nested_scopes
-
-__revision__ = "$Id$"
-
-import binascii
-import pprint
-import unittest
-import os
-import time
-import sys
-if sys.version_info[0] == 2 and sys.version_info[1] == 1:
- from Crypto.Util.py21compat import *
-from Crypto.Util.py3compat import *
-
-try:
- import multiprocessing
-except ImportError:
- multiprocessing = None
-
-import Crypto.Random._UserFriendlyRNG
-import Crypto.Random.random
-
-class RNGForkTest(unittest.TestCase):
-
- def _get_reseed_count(self):
- """
- Get `FortunaAccumulator.reseed_count`, the global count of the
- number of times that the PRNG has been reseeded.
- """
- rng_singleton = Crypto.Random._UserFriendlyRNG._get_singleton()
- rng_singleton._lock.acquire()
- try:
- return rng_singleton._fa.reseed_count
- finally:
- rng_singleton._lock.release()
-
- def runTest(self):
- # Regression test for CVE-2013-1445. We had a bug where, under the
- # right conditions, two processes might see the same random sequence.
-
- if sys.platform.startswith('win'): # windows can't fork
- assert not hasattr(os, 'fork') # ... right?
- return
-
- # Wait 150 ms so that we don't trigger the rate-limit prematurely.
- time.sleep(0.15)
-
- reseed_count_before = self._get_reseed_count()
-
- # One or both of these calls together should trigger a reseed right here.
- Crypto.Random._UserFriendlyRNG._get_singleton().reinit()
- Crypto.Random.get_random_bytes(1)
-
- reseed_count_after = self._get_reseed_count()
- self.assertNotEqual(reseed_count_before, reseed_count_after) # sanity check: test should reseed parent before forking
-
- rfiles = []
- for i in range(10):
- rfd, wfd = os.pipe()
- if os.fork() == 0:
- # child
- os.close(rfd)
- f = os.fdopen(wfd, "wb")
-
- Crypto.Random.atfork()
-
- data = Crypto.Random.get_random_bytes(16)
-
- f.write(data)
- f.close()
- os._exit(0)
- # parent
- os.close(wfd)
- rfiles.append(os.fdopen(rfd, "rb"))
-
- results = []
- results_dict = {}
- for f in rfiles:
- data = binascii.hexlify(f.read())
- results.append(data)
- results_dict[data] = 1
- f.close()
-
- if len(results) != len(results_dict.keys()):
- raise AssertionError("RNG output duplicated across fork():\n%s" %
- (pprint.pformat(results)))
-
-
-# For RNGMultiprocessingForkTest
-def _task_main(q):
- a = Crypto.Random.get_random_bytes(16)
- time.sleep(0.1) # wait 100 ms
- b = Crypto.Random.get_random_bytes(16)
- q.put(binascii.b2a_hex(a))
- q.put(binascii.b2a_hex(b))
- q.put(None) # Wait for acknowledgment
-
-
-class RNGMultiprocessingForkTest(unittest.TestCase):
-
- def runTest(self):
- # Another regression test for CVE-2013-1445. This is basically the
- # same as RNGForkTest, but less compatible with old versions of Python,
- # and a little easier to read.
-
- n_procs = 5
- manager = multiprocessing.Manager()
- queues = [manager.Queue(1) for i in range(n_procs)]
-
- # Reseed the pool
- time.sleep(0.15)
- Crypto.Random._UserFriendlyRNG._get_singleton().reinit()
- Crypto.Random.get_random_bytes(1)
-
- # Start the child processes
- pool = multiprocessing.Pool(processes=n_procs, initializer=Crypto.Random.atfork)
- map_result = pool.map_async(_task_main, queues)
-
- # Get the results, ensuring that no pool processes are reused.
- aa = [queues[i].get(30) for i in range(n_procs)]
- bb = [queues[i].get(30) for i in range(n_procs)]
- res = list(zip(aa, bb))
-
- # Shut down the pool
- map_result.get(30)
- pool.close()
- pool.join()
-
- # Check that the results are unique
- if len(set(aa)) != len(aa) or len(set(res)) != len(res):
- raise AssertionError("RNG output duplicated across fork():\n%s" %
- (pprint.pformat(res),))
-
-
-def get_tests(config={}):
- tests = []
- tests += [RNGForkTest()]
- if multiprocessing is not None:
- tests += [RNGMultiprocessingForkTest()]
- return tests
-
-if __name__ == '__main__':
- suite = lambda: unittest.TestSuite(get_tests())
- unittest.main(defaultTest='suite')
-
-# vim:set ts=4 sw=4 sts=4 expandtab:
--- lib/Crypto/SelfTest/Util/__init__.py
+++ lib/Crypto/SelfTest/Util/__init__.py
@@ -30,8 +30,6 @@ import os
def get_tests(config={}):
tests = []
- if os.name == 'nt':
- from Crypto.SelfTest.Util import test_winrandom; tests += test_winrandom.get_tests(config=config)
from Crypto.SelfTest.Util import test_number; tests += test_number.get_tests(config=config)
from Crypto.SelfTest.Util import test_Counter; tests += test_Counter.get_tests(config=config)
return tests
--- lib/Crypto/SelfTest/Util/test_winrandom.py
+++ /dev/null
@@ -1,48 +0,0 @@
-# -*- coding: utf-8 -*-
-#
-# SelfTest/Util/test_winrandom.py: Self-test for the winrandom module
-#
-# Written in 2008 by Dwayne C. Litzenberger <dlitz@dlitz.net>
-#
-# ===================================================================
-# The contents of this file are dedicated to the public domain. To
-# the extent that dedication to the public domain is not available,
-# everyone is granted a worldwide, perpetual, royalty-free,
-# non-exclusive license to exercise all rights associated with the
-# contents of this file for any purpose whatsoever.
-# No rights are reserved.
-#
-# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
-# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
-# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
-# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
-# BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
-# ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
-# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
-# SOFTWARE.
-# ===================================================================
-
-"""Self-test suite for Crypto.Util.winrandom"""
-
-__revision__ = "$Id$"
-
-import unittest
-
-class WinRandomImportTest(unittest.TestCase):
- def runTest(self):
- """winrandom: simple test"""
- # Import the winrandom module and try to use it
- from Crypto.Util import winrandom
- randobj = winrandom.new()
- x = randobj.get_bytes(16)
- y = randobj.get_bytes(16)
- self.assertNotEqual(x, y)
-
-def get_tests(config={}):
- return [WinRandomImportTest()]
-
-if __name__ == '__main__':
- suite = lambda: unittest.TestSuite(get_tests())
- unittest.main(defaultTest='suite')
-
-# vim:set ts=4 sw=4 sts=4 expandtab:
--- lib/Crypto/Util/winrandom.py
+++ /dev/null
@@ -1,28 +0,0 @@
-#
-# Util/winrandom.py : Stub for Crypto.Random.OSRNG.winrandom
-#
-# Written in 2008 by Dwayne C. Litzenberger <dlitz@dlitz.net>
-#
-# ===================================================================
-# The contents of this file are dedicated to the public domain. To
-# the extent that dedication to the public domain is not available,
-# everyone is granted a worldwide, perpetual, royalty-free,
-# non-exclusive license to exercise all rights associated with the
-# contents of this file for any purpose whatsoever.
-# No rights are reserved.
-#
-# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
-# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
-# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
-# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
-# BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
-# ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
-# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
-# SOFTWARE.
-# ===================================================================
-
-__revision__ = "$Id$"
-
-from Crypto.Random.OSRNG.winrandom import *
-
-# vim:set ts=4 sw=4 sts=4 expandtab:
--- setup.py
+++ setup.py
@@ -48,18 +48,6 @@ if sys.version[0:1] == '1':
raise RuntimeError ("The Python Cryptography Toolkit requires "
"Python 2.x or 3.x to build.")
-if sys.platform == 'win32':
- HTONS_LIBS = ['ws2_32']
- plat_ext = [
- Extension("Crypto.Random.OSRNG.winrandom",
- libraries = HTONS_LIBS + ['advapi32'],
- include_dirs=['src/'],
- sources=["src/winrand.c"])
- ]
-else:
- HTONS_LIBS = []
- plat_ext = []
-
# For test development: Set this to 1 to build with gcov support.
# Use "gcov -p -o build/temp.*/src build/temp.*/src/*.gcda" to build the
# .gcov files
@@ -73,18 +61,6 @@ except ImportError:
# Python 2
from distutils.command.build_py import build_py
-# List of pure Python modules that will be excluded from the binary packages.
-# The list consists of (package, module_name) tuples
-if sys.version_info[0] == 2:
- EXCLUDE_PY = []
-else:
- EXCLUDE_PY = [
- # We don't want Py3k to choke on the 2.x compat code
- ('Crypto.Util', 'py21compat'),
- ]
- if sys.platform != "win32": # Avoid nt.py, as 2to3 can't fix it w/o winrandom
- EXCLUDE_PY += [('Crypto.Random.OSRNG','nt')]
-
# Work around the print / print() issue with Python 2.x and 3.x. We only need
# to print at one point of the code, which makes this easy
@@ -264,8 +240,6 @@ class PCTBuildPy(build_py):
retval = []
for item in modules:
pkg, module = item[:2]
- if (pkg, module) in EXCLUDE_PY:
- continue
retval.append(item)
return retval
@@ -330,7 +304,6 @@ kw = {'name':"pycrypto",
'packages' : ["Crypto", "Crypto.Hash", "Crypto.Cipher", "Crypto.Util",
"Crypto.Random",
"Crypto.Random.Fortuna",
- "Crypto.Random.OSRNG",
"Crypto.SelfTest",
"Crypto.SelfTest.Cipher",
"Crypto.SelfTest.Hash",
@@ -338,14 +311,13 @@ kw = {'name':"pycrypto",
"Crypto.SelfTest.PublicKey",
"Crypto.SelfTest.Random",
"Crypto.SelfTest.Random.Fortuna",
- "Crypto.SelfTest.Random.OSRNG",
"Crypto.SelfTest.Util",
"Crypto.SelfTest.Signature",
"Crypto.Protocol",
"Crypto.PublicKey",
"Crypto.Signature"],
'package_dir' : { "Crypto": "lib/Crypto" },
- 'ext_modules': plat_ext + [
+ 'ext_modules': [
# _fastmath (uses GNU mp library)
Extension("Crypto.PublicKey._fastmath",
include_dirs=['src/','/usr/include/'],
@@ -443,11 +415,3 @@ def touch(path):
os.utime(path, (now, now))
except os.error:
PrintErr("Failed to update timestamp of "+path)
-
-# PY3K: Workaround for winrandom.pyd not existing during the first pass.
-# It needs to be there for 2to3 to fix the import in nt.py
-if (sys.platform == 'win32' and sys.version_info[0] == 3 and
- 'build' in sys.argv[1:]):
- PrintErr("\nSecond pass to allow 2to3 to fix nt.py. No cause for alarm.\n")
- touch("./lib/Crypto/Random/OSRNG/nt.py")
- core.setup(**kw)
--- src/winrand.c
+++ /dev/null
@@ -1,472 +0,0 @@
-/* -*- C -*- */
-/*
- * Uses Windows CryptoAPI CryptGenRandom to get random bytes.
- * The "new" method returns an object, whose "get_bytes" method
- * can be called repeatedly to get random bytes, seeded by the
- * OS. See the description in the comment at the end.
- *
- * If you have the Intel Security Driver header files (icsp4ms.h)
- * for their hardware random number generator in the 810 and 820 chipsets,
- * then define HAVE_INTEL_RNG.
- *
- * =======================================================================
- * The contents of this file are dedicated to the public domain. To the
- * extent that dedication to the public domain is not available, everyone
- * is granted a worldwide, perpetual, royalty-free, non-exclusive license
- * to exercise all rights associated with the contents of this file for
- * any purpose whatsoever. No rights are reserved.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
- * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
- * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
- * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
- * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- * SOFTWARE.
- * =======================================================================
- *
- */
-
-/* Author: Mark Moraes */
-
-#include "Python.h"
-#include "pycrypto_compat.h"
-
-#ifdef MS_WIN32
-
-#define _WIN32_WINNT 0x400
-#define WINSOCK
-
-#include <windows.h>
-#include <wincrypt.h>
-
-#ifdef HAVE_INTEL_RNG
-# include "icsp4ms.h"
-#else
-# define PROV_INTEL_SEC 22
-# define INTEL_DEF_PROV "Intel Hardware Cryptographic Service Provider"
-#endif
-
-/* To-Do: store provider name and type for print/repr? */
-
-typedef struct
-{
- PyObject_HEAD
- HCRYPTPROV hcp;
-} WRobject;
-
-/* Please see PEP3123 for a discussion of PyObject_HEAD and changes made in 3.x to make it conform to Standard C.
- * These changes also dictate using Py_TYPE to check type, and PyVarObject_HEAD_INIT(NULL, 0) to initialize
- */
-#ifdef IS_PY3K
-static PyTypeObject WRtype;
-#define is_WRobject(v) (Py_TYPE(v) == &WRtype)
-#else
-staticforward PyTypeObject WRtype;
-#define is_WRobject(v) ((v)->ob_type == &WRtype)
-#define PyLong_FromLong PyInt_FromLong /* for Python 2.x */
-#endif
-
-static void
-WRdealloc(PyObject *ptr)
-{
- WRobject *o = (WRobject *)ptr;
-
- if (! is_WRobject(ptr)) {
- PyErr_Format(PyExc_TypeError,
- "WinRandom trying to dealloc non-WinRandom object");
- return;
- }
- if (! CryptReleaseContext(o->hcp, 0)) {
- PyErr_Format(PyExc_SystemError,
- "CryptReleaseContext failed, error 0x%x",
- (unsigned int) GetLastError());
- return;
- }
- /* Overwrite the contents of the object */
- o->hcp = 0;
- PyObject_Del(ptr);
-}
-
-static char winrandom__doc__[] =
-"new([provider], [provtype]): Returns an object handle to Windows\n\
-CryptoAPI that can be used to access a cryptographically strong\n\
-pseudo-random generator that uses OS-gathered entropy.\n\
-Provider is a string that specifies the Cryptographic Service Provider\n\
-to use, default is the default OS CSP.\n\
-provtype is an integer specifying the provider type to use, default\n\
-is 1 (PROV_RSA_FULL)";
-
-static char WR_get_bytes__doc__[] =
-"get_bytes(nbytes, [userdata]]): Returns nbytes of random data\n\
-from Windows CryptGenRandom.\n\
-userdata is a string with any additional entropic data that the\n\
-user wishes to provide.";
-
-static WRobject *
-winrandom_new(PyObject *self, PyObject *args, PyObject *kwdict)
-{
- HCRYPTPROV hcp = 0;
- WRobject *res;
- char *provname = NULL;
- int provtype = PROV_RSA_FULL;
- static char *kwlist[] = { "provider", "provtype", NULL};
-
- if (!PyArg_ParseTupleAndKeywords(args, kwdict, "|si", kwlist,
- &provname, &provtype)) {
- return NULL;
- }
- if (! CryptAcquireContext(&hcp, NULL, (LPCTSTR) provname,
- (DWORD) provtype,
- CRYPT_VERIFYCONTEXT | CRYPT_SILENT)) {
- PyErr_Format(PyExc_SystemError,
- "CryptAcquireContext for provider \"%s\" type %i failed, error 0x%x",
- provname? provname : "(null)", provtype,
- (unsigned int) GetLastError());
- return NULL;
- }
- res = PyObject_New(WRobject, &WRtype);
- res->hcp = hcp;
- return res;
-}
-
-static PyObject *
-WR_get_bytes(WRobject *self, PyObject *args)
-{
- int n, nbytes, len = 0;
- PyObject *res;
- char *buf, *str = NULL;
-
- if (! is_WRobject(self)) {
- PyErr_Format(PyExc_TypeError,
- "WinRandom trying to get_bytes with non-WinRandom object");
- return NULL;
- }
- if (!PyArg_ParseTuple(args, "i|s#", &n, &str, &len)) {
- return NULL;
- }
- if (n <= 0) {
- PyErr_SetString(PyExc_ValueError, "nbytes must be positive number");
- return NULL;
- }
- /* Just in case char != BYTE, or userdata > desired result */
- nbytes = (((n > len) ? n : len) * sizeof(char)) / sizeof(BYTE) + 1;
- if ((buf = (char *) PyMem_Malloc(nbytes)) == NULL)
- return PyErr_NoMemory();
- if (len > 0)
- memcpy(buf, str, len);
- /*
- * if userdata > desired result, we end up getting
- * more bytes than we really needed to return. No
- * easy way to avoid that: we prefer that
- * CryptGenRandom does the distillation of userdata
- * down to entropy, rather than trying to do it
- * ourselves. Since the extra bytes presumably come
- * from an RC4 stream, they should be relatively
- * cheap.
- */
-
- if (! CryptGenRandom(self->hcp, (DWORD) nbytes, (BYTE *) buf)) {
- PyErr_Format(PyExc_SystemError,
- "CryptGenRandom failed, error 0x%x",
- (unsigned int) GetLastError());
- PyMem_Free(buf);
- return NULL;
- }
-
- res = PyBytes_FromStringAndSize(buf, n);
- PyMem_Free(buf);
- return res;
-}
-
-/* WinRandom object methods */
-
-static PyMethodDef WRmethods[] =
-{
- {"get_bytes", (PyCFunction) WR_get_bytes, METH_VARARGS,
- WR_get_bytes__doc__},
- {NULL, NULL} /* sentinel */
-};
-
-/* winrandom module methods */
-
-static PyMethodDef WR_mod_methods[] = {
- {"new", (PyCFunction) winrandom_new, METH_VARARGS|METH_KEYWORDS,
- winrandom__doc__},
- {NULL, NULL} /* Sentinel */
-};
-
-static PyObject *
-#ifdef IS_PY3K
-WRgetattro(PyObject *s, PyObject *attr)
-#else
-WRgetattr(PyObject *s, char *name)
-#endif
-{
- WRobject *self = (WRobject*)s;
- if (! is_WRobject(self)) {
- PyErr_Format(PyExc_TypeError,
- "WinRandom trying to getattr with non-WinRandom object");
- return NULL;
- }
-#ifdef IS_PY3K
- if (!PyUnicode_Check(attr))
- goto generic;
- if (PyUnicode_CompareWithASCIIString(attr, "hcp") == 0)
-#else
- if (strcmp(name, "hcp") == 0)
-#endif
- return PyLong_FromLong((long) self->hcp);
-#ifdef IS_PY3K
- generic:
- return PyObject_GenericGetAttr(s, attr);
-#else
- return Py_FindMethod(WRmethods, (PyObject *) self, name);
-#endif
-}
-
-static PyTypeObject WRtype =
- {
- #ifdef IS_PY3K
- PyVarObject_HEAD_INIT(NULL, 0) /* deferred type init for compilation on Windows, type will be filled in at runtime */
-#else
- PyObject_HEAD_INIT(NULL)
- 0, /*ob_size*/
-#endif
- "winrandom.WinRandom", /*tp_name*/
- sizeof(WRobject), /*tp_size*/
- 0, /*tp_itemsize*/
- /* methods */
- (destructor) WRdealloc, /*tp_dealloc*/
- 0, /*tp_print*/
-#ifndef IS_PY3K
- WRgetattr, /*tp_getattr*/
-#else
- 0, /*tp_getattr*/
- 0, /*tp_setattr*/
- 0, /*tp_compare*/
- 0, /*tp_repr*/
- 0, /*tp_as_number */
- 0, /*tp_as_sequence */
- 0, /*tp_as_mapping */
- 0, /*tp_hash*/
- 0, /*tp_call*/
- 0, /*tp_str*/
- WRgetattro, /*tp_getattro*/
- 0, /*tp_setattro*/
- 0, /*tp_as_buffer*/
- Py_TPFLAGS_DEFAULT, /*tp_flags*/
- 0, /*tp_doc*/
- 0, /*tp_traverse*/
- 0, /*tp_clear*/
- 0, /*tp_richcompare*/
- 0, /*tp_weaklistoffset*/
- 0, /*tp_iter*/
- 0, /*tp_iternext*/
- WRmethods, /*tp_methods*/
-#endif
-};
-
-#ifdef IS_PY3K
-static struct PyModuleDef moduledef = {
- PyModuleDef_HEAD_INIT,
- "winrandom",
- NULL,
- -1,
- WR_mod_methods,
- NULL,
- NULL,
- NULL,
- NULL
- };
-#endif
-
-#ifdef IS_PY3K
-PyMODINIT_FUNC
-PyInit_winrandom()
-#else
-void
-initwinrandom()
-#endif
-{
- PyObject *m;
-#ifdef IS_PY3K
- /* PyType_Ready automatically fills in ob_type with &PyType_Type if it's not already set */
- if (PyType_Ready(&WRtype) < 0)
- return NULL;
- /* Initialize the module */
- m = PyModule_Create(&moduledef);
- if (m == NULL)
- return NULL;
-#else
- WRtype.ob_type = &PyType_Type;
- m = Py_InitModule("winrandom", WR_mod_methods);
-#endif
-
- /* define Windows CSP Provider Types */
-#ifdef PROV_RSA_FULL
- PyModule_AddIntConstant(m, "PROV_RSA_FULL", PROV_RSA_FULL);
-#endif
-#ifdef PROV_RSA_SIG
- PyModule_AddIntConstant(m, "PROV_RSA_SIG", PROV_RSA_SIG);
-#endif
-#ifdef PROV_DSS
- PyModule_AddIntConstant(m, "PROV_DSS", PROV_DSS);
-#endif
-#ifdef PROV_FORTEZZA
- PyModule_AddIntConstant(m, "PROV_FORTEZZA", PROV_FORTEZZA);
-#endif
-#ifdef PROV_MS_EXCHANGE
- PyModule_AddIntConstant(m, "PROV_MS_EXCHANGE", PROV_MS_EXCHANGE);
-#endif
-#ifdef PROV_SSL
- PyModule_AddIntConstant(m, "PROV_SSL", PROV_SSL);
-#endif
-#ifdef PROV_RSA_SCHANNEL
- PyModule_AddIntConstant(m, "PROV_RSA_SCHANNEL", PROV_RSA_SCHANNEL);
-#endif
-#ifdef PROV_DSS_DH
- PyModule_AddIntConstant(m, "PROV_DSS_DH", PROV_DSS_DH);
-#endif
-#ifdef PROV_EC_ECDSA_SIG
- PyModule_AddIntConstant(m, "PROV_EC_ECDSA_SIG", PROV_EC_ECDSA_SIG);
-#endif
-#ifdef PROV_EC_ECNRA_SIG
- PyModule_AddIntConstant(m, "PROV_EC_ECNRA_SIG", PROV_EC_ECNRA_SIG);
-#endif
-#ifdef PROV_EC_ECDSA_FULL
- PyModule_AddIntConstant(m, "PROV_EC_ECDSA_FULL", PROV_EC_ECDSA_FULL);
-#endif
-#ifdef PROV_EC_ECNRA_FULL
- PyModule_AddIntConstant(m, "PROV_EC_ECNRA_FULL", PROV_EC_ECNRA_FULL);
-#endif
-#ifdef PROV_SPYRUS_LYNKS
- PyModule_AddIntConstant(m, "PROV_SPYRUS_LYNKS", PROV_SPYRUS_LYNKS);
-#endif
-#ifdef PROV_INTEL_SEC
- PyModule_AddIntConstant(m, "PROV_INTEL_SEC", PROV_INTEL_SEC);
-#endif
-
- /* Define Windows CSP Provider Names */
-#ifdef MS_DEF_PROV
- PyModule_AddStringConstant(m, "MS_DEF_PROV", MS_DEF_PROV);
-#endif
-#ifdef MS_ENHANCED_PROV
- PyModule_AddStringConstant(m, "MS_ENHANCED_PROV", MS_ENHANCED_PROV);
-#endif
-#ifdef MS_DEF_RSA_SIG_PROV
- PyModule_AddStringConstant(m, "MS_DEF_RSA_SIG_PROV",
- MS_DEF_RSA_SIG_PROV);
-#endif
-#ifdef MS_DEF_RSA_SCHANNEL_PROV
- PyModule_AddStringConstant(m, "MS_DEF_RSA_SCHANNEL_PROV",
- MS_DEF_RSA_SCHANNEL_PROV);
-#endif
-#ifdef MS_ENHANCED_RSA_SCHANNEL_PROV
- PyModule_AddStringConstant(m, "MS_ENHANCED_RSA_SCHANNEL_PROV",
- MS_ENHANCED_RSA_SCHANNEL_PROV);
-#endif
-#ifdef MS_DEF_DSS_PROV
- PyModule_AddStringConstant(m, "MS_DEF_DSS_PROV", MS_DEF_DSS_PROV);
-#endif
-#ifdef MS_DEF_DSS_DH_PROV
- PyModule_AddStringConstant(m, "MS_DEF_DSS_DH_PROV",
- MS_DEF_DSS_DH_PROV);
-#endif
-#ifdef INTEL_DEF_PROV
- PyModule_AddStringConstant(m, "INTEL_DEF_PROV", INTEL_DEF_PROV);
-#endif
-
- if (PyErr_Occurred())
- Py_FatalError("can't initialize module winrandom");
-
-#ifdef IS_PY3K
- return m;
-#endif
-}
-/*
-
-CryptGenRandom usage is described in
-http://msdn.microsoft.com/library/en-us/security/security/cryptgenrandom.asp
-and many associated pages on Windows Cryptographic Service
-Providers, which say:
-
- With Microsoft CSPs, CryptGenRandom uses the same
- random number generator used by other security
- components. This allows numerous processes to
- contribute to a system-wide seed. CryptoAPI stores
- an intermediate random seed with every user. To form
- the seed for the random number generator, a calling
- application supplies bits it might havefor instance,
- mouse or keyboard timing inputthat are then added to
- both the stored seed and various system data and
- user data such as the process ID and thread ID, the
- system clock, the system time, the system counter,
- memory status, free disk clusters, the hashed user
- environment block. This result is SHA-1 hashed, and
- the output is used to seed an RC4 stream, which is
- then used as the random stream and used to update
- the stored seed.
-
-The only other detailed description I've found of the
-sources of randomness for CryptGenRandom is this excerpt
-from a posting
-http://www.der-keiler.de/Newsgroups/comp.security.ssh/2002-06/0169.html
-
-From: Jon McClelland (dowot69@hotmail.com)
-Date: 06/12/02
-...
-
-Windows, call a function such as CryptGenRandom, which has two of
-the properties of a good random number generator, unpredictability and
-even value distribution. This function, declared in Wincrypt.h, is
-available on just about every Windows platform, including Windows 95
-with Internet Explorer 3.02 or later, Windows 98, Windows Me, Windows
-CE v3, Windows NT 4, Windows 2000, and Windows XP.
-
-CryptGenRandom gets its randomness, also known as entropy, from many
-sources in Windows 2000, including the following:
-The current process ID (GetCurrentProcessID).
-The current thread ID (GetCurrentThreadID).
-The ticks since boot (GetTickCount).
-The current time (GetLocalTime).
-Various high-precision performance counters (QueryPerformanceCounter).
-A Message Digest 4 (MD4) hash of the user's environment block, which
-includes username, computer name, and search path.
-
-High-precision internal CPU counters, such as RDTSC, RDMSR, RDPMC (x86
-only-more information about these counters is at
-developer.intel.com/software/idap/resources/technical_collateral/pentiumii/RDTSCPM1.HTM
-<http://developer.intel.com>).
-
-Low-level system information, such as idle time, kernel time,
-interrupt times, commit limit, page read count, cache read count,
-nonpaged pool allocations, alignment fixup count, operating system
-lookaside information.
-
-Such information is added to a buffer, which is hashed using MD4 and
-used as the key to modify a buffer, using RC4, provided by the user.
-(Refer to the CryptGenRandom documentation in the Platform SDK for
-more information about the user-provided buffer.) Hence, if the user
-provides additional data in the buffer, this is used as an element in
-the witches brew to generate the random data. The result is a
-cryptographically random number generator.
-Also, note that if you plan to sell your software to the United States
-federal government, you'll need to use FIPS 140-1-approved algorithms.
-The default versions of CryptGenRandom in Microsoft Windows CE v3,
-Windows 95, Windows 98, Windows Me, Windows 2000, and Windows XP are
-FIPS-approved. Obviously FIPS-140 compliance is necessary but not
-sufficient to provide a properly secure source of random data.
-
-*/
-/*
-[Update: 2007-11-13]
-CryptGenRandom does not necessarily provide forward secrecy or reverse
-secrecy. See the paper by Leo Dorrendorf and Zvi Gutterman and Benny
-Pinkas, _Cryptanalysis of the Random Number Generator of the Windows
-Operating System_, Cryptology ePrint Archive, Report 2007/419,
-http://eprint.iacr.org/2007/419
-*/
-
-#endif /* MS_WIN32 */