[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