[Buildroot] [PATCH v2] package/python-pycrypto: fix python3.8 compatibility
James Hilliard
james.hilliard1 at gmail.com
Mon Apr 20 18:59:53 UTC 2020
On Mon, Apr 20, 2020 at 8:07 AM Romain Naour <romain.naour at gmail.com> wrote:
>
> Apply the patch from Fedora 31 [1][2] to replace the user-space RNG with a
> thin wrapper to os.urandom. This allow to fixes compatibility with
> Python 3.8 since the code containing time.clock() is removed.
I wonder if it would be better to just replace pycrypto with pycryptodome
which is supposed to be a drop in pycrypto replacement. It should essentially
be a maintained pycrypto compatible version of pycryptodomex.
See here for details:
https://pycryptodome.readthedocs.io/en/latest/src/installation.html#installation
>
> time.clock() was deprecated in Python 3.3 and removed in Python 3.8.
>
> [1] https://src.fedoraproject.org/rpms/python-crypto/c/a5fd7148fb0e9d5526f24feb1bb708bf203480b9?branch=f31
> [2] https://src.fedoraproject.org/rpms/python-crypto/blob/f31/f/pycrypto-2.6.1-use-os-random.patch
>
> Fixes:
> https://gitlab.com/buildroot.org/buildroot/-/jobs/498144209
>
> Signed-off-by: Romain Naour <romain.naour at gmail.com>
> ---
> This patch would allow to use python2 and python3.
> To be backported to Buildroot 2020.02 to fixes the qemu-arm-vexpress-tz defconfig.
> ---
> ...2-pycrypto-2.6.1-use-os-random.patch.patch | 1904 +++++++++++++++++
> 1 file changed, 1904 insertions(+)
> create mode 100644 package/python-pycrypto/0002-pycrypto-2.6.1-use-os-random.patch.patch
>
> diff --git a/package/python-pycrypto/0002-pycrypto-2.6.1-use-os-random.patch.patch b/package/python-pycrypto/0002-pycrypto-2.6.1-use-os-random.patch.patch
> new file mode 100644
> index 0000000000..8e78a60d0f
> --- /dev/null
> +++ b/package/python-pycrypto/0002-pycrypto-2.6.1-use-os-random.patch.patch
> @@ -0,0 +1,1904 @@
> +From 37c2b6be5e331c215574f4fb34bd96c6e8bba2f6 Mon Sep 17 00:00:00 2001
> +From: Romain Naour <romain.naour at gmail.com>
> +Date: Mon, 20 Apr 2020 15:35:52 +0200
> +Subject: [PATCH] pycrypto-2.6.1-use-os-random.patch
> +
> +Apply the patch from Fedora 31 [1][2] to replace the user-space RNG with a
> +thin wrapper to os.urandom. This allow to fixes compatibility with
> +Python 3.8 since the code containing time.clock() is removed.
> +
> +time.clock() was deprecated in Python 3.3 and removed in Python 3.8.
> +
> +[1] https://src.fedoraproject.org/rpms/python-crypto/c/a5fd7148fb0e9d5526f24feb1bb708bf203480b9?branch=f31
> +[2] https://src.fedoraproject.org/rpms/python-crypto/blob/f31/f/pycrypto-2.6.1-use-os-random.patch
> +
> +[Romain: git format, improve commit log]
> +Signed-off-by: Romain Naour <romain.naour at gmail.com>
> +---
> + lib/Crypto/Random/OSRNG/__init__.py | 40 --
> + lib/Crypto/Random/OSRNG/fallback.py | 46 --
> + lib/Crypto/Random/OSRNG/nt.py | 74 ---
> + lib/Crypto/Random/OSRNG/posix.py | 86 ----
> + lib/Crypto/Random/OSRNG/rng_base.py | 88 ----
> + lib/Crypto/Random/_UserFriendlyRNG.py | 230 ---------
> + lib/Crypto/Random/__init__.py | 40 +-
> + lib/Crypto/SelfTest/Random/OSRNG/__init__.py | 49 --
> + .../SelfTest/Random/OSRNG/test_fallback.py | 48 --
> + .../SelfTest/Random/OSRNG/test_generic.py | 48 --
> + lib/Crypto/SelfTest/Random/OSRNG/test_nt.py | 48 --
> + .../SelfTest/Random/OSRNG/test_posix.py | 48 --
> + .../SelfTest/Random/OSRNG/test_winrandom.py | 48 --
> + lib/Crypto/SelfTest/Random/__init__.py | 2 -
> + .../SelfTest/Random/test__UserFriendlyRNG.py | 171 -------
> + lib/Crypto/SelfTest/Util/__init__.py | 2 -
> + lib/Crypto/SelfTest/Util/test_winrandom.py | 48 --
> + lib/Crypto/Util/winrandom.py | 28 --
> + setup.py | 38 +-
> + src/winrand.c | 472 ------------------
> + 20 files changed, 28 insertions(+), 1626 deletions(-)
> + delete mode 100644 lib/Crypto/Random/OSRNG/__init__.py
> + delete mode 100644 lib/Crypto/Random/OSRNG/fallback.py
> + delete mode 100644 lib/Crypto/Random/OSRNG/nt.py
> + delete mode 100644 lib/Crypto/Random/OSRNG/posix.py
> + delete mode 100644 lib/Crypto/Random/OSRNG/rng_base.py
> + delete mode 100644 lib/Crypto/Random/_UserFriendlyRNG.py
> + delete mode 100644 lib/Crypto/SelfTest/Random/OSRNG/__init__.py
> + delete mode 100644 lib/Crypto/SelfTest/Random/OSRNG/test_fallback.py
> + delete mode 100644 lib/Crypto/SelfTest/Random/OSRNG/test_generic.py
> + delete mode 100644 lib/Crypto/SelfTest/Random/OSRNG/test_nt.py
> + delete mode 100644 lib/Crypto/SelfTest/Random/OSRNG/test_posix.py
> + delete mode 100644 lib/Crypto/SelfTest/Random/OSRNG/test_winrandom.py
> + delete mode 100644 lib/Crypto/SelfTest/Random/test__UserFriendlyRNG.py
> + delete mode 100644 lib/Crypto/SelfTest/Util/test_winrandom.py
> + delete mode 100644 lib/Crypto/Util/winrandom.py
> + delete mode 100644 src/winrand.c
> +
> +diff --git a/lib/Crypto/Random/OSRNG/__init__.py b/lib/Crypto/Random/OSRNG/__init__.py
> +deleted file mode 100644
> +index 2fbbecb..0000000
> +--- a/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 at 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:
> +diff --git a/lib/Crypto/Random/OSRNG/fallback.py b/lib/Crypto/Random/OSRNG/fallback.py
> +deleted file mode 100644
> +index 5bb6126..0000000
> +--- a/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 at 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:
> +diff --git a/lib/Crypto/Random/OSRNG/nt.py b/lib/Crypto/Random/OSRNG/nt.py
> +deleted file mode 100644
> +index c1c2f44..0000000
> +--- a/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 at 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:
> +diff --git a/lib/Crypto/Random/OSRNG/posix.py b/lib/Crypto/Random/OSRNG/posix.py
> +deleted file mode 100644
> +index ca6ac05..0000000
> +--- a/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 at 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:
> +diff --git a/lib/Crypto/Random/OSRNG/rng_base.py b/lib/Crypto/Random/OSRNG/rng_base.py
> +deleted file mode 100644
> +index 54c3aa0..0000000
> +--- a/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 at 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:
> +diff --git a/lib/Crypto/Random/_UserFriendlyRNG.py b/lib/Crypto/Random/_UserFriendlyRNG.py
> +deleted file mode 100644
> +index 957e006..0000000
> +--- a/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 at 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:
> +diff --git a/lib/Crypto/Random/__init__.py b/lib/Crypto/Random/__init__.py
> +index 659ffee..a2e241d 100644
> +--- a/lib/Crypto/Random/__init__.py
> ++++ b/lib/Crypto/Random/__init__.py
> +@@ -2,8 +2,6 @@
> + #
> + # Random/__init__.py : PyCrypto random number generation
> + #
> +-# Written in 2008 by Dwayne C. Litzenberger <dlitz at 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:
> +diff --git a/lib/Crypto/SelfTest/Random/OSRNG/__init__.py b/lib/Crypto/SelfTest/Random/OSRNG/__init__.py
> +deleted file mode 100644
> +index 44b3fa1..0000000
> +--- a/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 at 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:
> +diff --git a/lib/Crypto/SelfTest/Random/OSRNG/test_fallback.py b/lib/Crypto/SelfTest/Random/OSRNG/test_fallback.py
> +deleted file mode 100644
> +index 41909b0..0000000
> +--- a/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 at 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:
> +diff --git a/lib/Crypto/SelfTest/Random/OSRNG/test_generic.py b/lib/Crypto/SelfTest/Random/OSRNG/test_generic.py
> +deleted file mode 100644
> +index 2a40974..0000000
> +--- a/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 at 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:
> +diff --git a/lib/Crypto/SelfTest/Random/OSRNG/test_nt.py b/lib/Crypto/SelfTest/Random/OSRNG/test_nt.py
> +deleted file mode 100644
> +index a7a8338..0000000
> +--- a/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 at 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:
> +diff --git a/lib/Crypto/SelfTest/Random/OSRNG/test_posix.py b/lib/Crypto/SelfTest/Random/OSRNG/test_posix.py
> +deleted file mode 100644
> +index 2224afe..0000000
> +--- a/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 at 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:
> +diff --git a/lib/Crypto/SelfTest/Random/OSRNG/test_winrandom.py b/lib/Crypto/SelfTest/Random/OSRNG/test_winrandom.py
> +deleted file mode 100644
> +index 3010eb7..0000000
> +--- a/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 at 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:
> +diff --git a/lib/Crypto/SelfTest/Random/__init__.py b/lib/Crypto/SelfTest/Random/__init__.py
> +index f972bf0..aa8e7de 100644
> +--- a/lib/Crypto/SelfTest/Random/__init__.py
> ++++ b/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__':
> +diff --git a/lib/Crypto/SelfTest/Random/test__UserFriendlyRNG.py b/lib/Crypto/SelfTest/Random/test__UserFriendlyRNG.py
> +deleted file mode 100644
> +index 771a663..0000000
> +--- a/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 at 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:
> +diff --git a/lib/Crypto/SelfTest/Util/__init__.py b/lib/Crypto/SelfTest/Util/__init__.py
> +index abd640a..e9af4b5 100644
> +--- a/lib/Crypto/SelfTest/Util/__init__.py
> ++++ b/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
> +diff --git a/lib/Crypto/SelfTest/Util/test_winrandom.py b/lib/Crypto/SelfTest/Util/test_winrandom.py
> +deleted file mode 100644
> +index 3fc5145..0000000
> +--- a/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 at 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:
> +diff --git a/lib/Crypto/Util/winrandom.py b/lib/Crypto/Util/winrandom.py
> +deleted file mode 100644
> +index 0242815..0000000
> +--- a/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 at 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:
> +diff --git a/setup.py b/setup.py
> +index c546ddb..d3a3b8b 100644
> +--- a/setup.py
> ++++ b/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)
> +diff --git a/src/winrand.c b/src/winrand.c
> +deleted file mode 100644
> +index d505e54..0000000
> +--- a/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 at 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 */
> +--
> +2.25.3
> +
> --
> 2.25.3
>
> _______________________________________________
> buildroot mailing list
> buildroot at busybox.net
> http://lists.busybox.net/mailman/listinfo/buildroot
More information about the buildroot
mailing list