Merge branch 'master' into urandom-engine

* master:
  PKCS #1 RSA test vector loader
  Removed pointless anchor
  Docs need virtualenv as well
  Everything about bash is the worst
  Some reST markup nonsense
  Fix for OS X
  More clearly describe the behavior of constant_time.bytes_eq
  Run the doc tests under OS X
  Made OpenSSL's derive_pbkdf2_hmac raise the right exception
  Document which backends implement which itnerfaces. Fixes #538
  pep8
  Fixed a typo in the docs
  Make the default backend be a multi-backend

Conflicts:
	tests/hazmat/backends/test_openssl.py
diff --git a/cryptography/hazmat/backends/openssl/backend.py b/cryptography/hazmat/backends/openssl/backend.py
index 74faee5..f4b5c3a 100644
--- a/cryptography/hazmat/backends/openssl/backend.py
+++ b/cryptography/hazmat/backends/openssl/backend.py
@@ -58,6 +58,61 @@
 
         self._cipher_registry = {}
         self._register_default_ciphers()
+        self.activate_osrandom_engine()
+
+    def deactivate_osrandom_engine(self):
+        # obtains a new structural reference
+        e = self._lib.ENGINE_get_default_RAND()
+        if e != self._ffi.NULL:
+            # this obtains the name of the engine but does not obtain a
+            # structural or functional reference
+            name = self._lib.ENGINE_get_name(e)
+            assert name != self._ffi.NULL
+            if name == self._lib.Cryptography_osrandom_engine_name:
+                # removes the engine provided from the list of available RAND
+                # engines.
+                self._lib.ENGINE_unregister_RAND(e)
+                # this resets the RNG to use the new engine
+                self._lib.RAND_cleanup()
+            # decrement the structural reference from get_default_RAND
+            res = self._lib.ENGINE_finish(e)
+            assert res == 1
+
+    def activate_osrandom_engine(self):
+        # obtains a new structural reference
+        current_rand = self._lib.ENGINE_get_default_RAND()
+        if current_rand != self._ffi.NULL:
+            # this obtains the name of the engine but does not obtain a
+            # structural or functional reference
+            name = self._lib.ENGINE_get_name(current_rand)
+            assert name != self._ffi.NULL
+            if name != self._lib.Cryptography_osrandom_engine_name:
+                self._activate_osrandom_engine()
+            # decrement the structural reference from get_default_RAND
+            res = self._lib.ENGINE_finish(current_rand)
+            assert res == 1
+        else:
+            self._activate_osrandom_engine()
+
+    def _activate_osrandom_engine(self):
+        # Fetches an engine by id and returns it. This creates a structural
+        # reference.
+        e = self._lib.ENGINE_by_id(self._lib.Cryptography_osrandom_engine_id)
+        assert e != self._ffi.NULL
+        # Initialize the engine for use. This adds a functional reference.
+        res = self._lib.ENGINE_init(e)
+        assert res == 1
+        # Set the engine as the default RAND provider.
+        res = self._lib.ENGINE_set_default_RAND(e)
+        assert res == 1
+        # decrement the structural ref incremented by ENGINE_by_id
+        res = self._lib.ENGINE_free(e)
+        assert res == 1
+        # decrement the functional ref incremented by ENGINE_init
+        res = self._lib.ENGINE_finish(e)
+        assert res == 1
+        # Reset the RNG to use the new engine
+        self._lib.RAND_cleanup()
 
     def openssl_version_text(self):
         """
diff --git a/cryptography/hazmat/bindings/openssl/binding.py b/cryptography/hazmat/bindings/openssl/binding.py
index cde3bdb..84bfacb 100644
--- a/cryptography/hazmat/bindings/openssl/binding.py
+++ b/cryptography/hazmat/bindings/openssl/binding.py
@@ -60,6 +60,7 @@
         "nid",
         "objects",
         "opensslv",
+        "osrandom_engine",
         "pem",
         "pkcs7",
         "pkcs12",
@@ -90,11 +91,13 @@
         if sys.platform != "win32":
             libraries = ["crypto", "ssl"]
         else:  # pragma: no cover
-            libraries = ["libeay32", "ssleay32"]
+            libraries = ["libeay32", "ssleay32", "advapi32"]
 
         cls.ffi, cls.lib = build_ffi(cls._module_prefix, cls._modules,
                                      _OSX_PRE_INCLUDE, _OSX_POST_INCLUDE,
                                      libraries)
+        res = cls.lib.Cryptography_add_osrandom_engine()
+        assert res == 1
 
     @classmethod
     def is_available(cls):
diff --git a/cryptography/hazmat/bindings/openssl/osrandom_engine.py b/cryptography/hazmat/bindings/openssl/osrandom_engine.py
new file mode 100644
index 0000000..5c5661b
--- /dev/null
+++ b/cryptography/hazmat/bindings/openssl/osrandom_engine.py
@@ -0,0 +1,194 @@
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#    http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+# implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+INCLUDES = """
+#ifdef _WIN32
+#include <Wincrypt.h>
+#else
+#include <fcntl.h>
+#include <unistd.h>
+#endif
+"""
+
+TYPES = """
+static const char *const Cryptography_osrandom_engine_name;
+static const char *const Cryptography_osrandom_engine_id;
+"""
+
+FUNCTIONS = """
+int Cryptography_add_osrandom_engine(void);
+"""
+
+MACROS = """
+"""
+
+WIN32_CUSTOMIZATIONS = """
+static HCRYPTPROV hCryptProv = 0;
+
+static int osrandom_init(ENGINE *e) {
+    if (hCryptProv > 0) {
+        return 1;
+    }
+    if (CryptAcquireContext(&hCryptProv, NULL, NULL,
+                            PROV_RSA_FULL, CRYPT_VERIFYCONTEXT)) {
+        return 1;
+    } else {
+        return 0;
+    }
+}
+
+static int osrandom_rand_bytes(unsigned char *buffer, int size) {
+    if (hCryptProv == 0) {
+        return 0;
+    }
+
+    if (!CryptGenRandom(hCryptProv, (DWORD)size, buffer)) {
+        ERR_put_error(ERR_LIB_RAND, 0, ERR_R_RAND_LIB, "osrandom.py", 0);
+        return 0;
+    }
+    return 1;
+}
+
+static int osrandom_finish(ENGINE *e) {
+    if (CryptReleaseContext(hCryptProv, 0)) {
+        hCryptProv = 0;
+        return 1;
+    } else {
+        return 0;
+    }
+}
+
+static int osrandom_rand_status(void) {
+    if (hCryptProv == 0) {
+        return 0;
+    } else {
+        return 1;
+    }
+}
+"""
+
+POSIX_CUSTOMIZATIONS = """
+static int urandom_fd = -1;
+
+static int osrandom_finish(ENGINE *e);
+
+static int osrandom_init(ENGINE *e) {
+    if (urandom_fd > -1) {
+        return 1;
+    }
+    urandom_fd = open("/dev/urandom", O_RDONLY);
+    if (urandom_fd > -1) {
+        if (fcntl(urandom_fd, F_SETFD, FD_CLOEXEC) == -1) {
+            osrandom_finish(e);
+            return 0;
+        }
+        return 1;
+    } else {
+        return 0;
+    }
+}
+
+static int osrandom_rand_bytes(unsigned char *buffer, int size) {
+    ssize_t n;
+    while (size > 0) {
+        do {
+            n = read(urandom_fd, buffer, (size_t)size);
+        } while (n < 0 && errno == EINTR);
+        if (n <= 0) {
+            ERR_put_error(ERR_LIB_RAND, 0, ERR_R_RAND_LIB, "osrandom.py", 0);
+            return 0;
+        }
+        buffer += n;
+        size -= n;
+    }
+    return 1;
+}
+
+static int osrandom_finish(ENGINE *e) {
+    int n;
+    do {
+        n = close(urandom_fd);
+    } while (n < 0 && errno == EINTR);
+    urandom_fd = -1;
+    if (n < 0) {
+        return 0;
+    } else {
+        return 1;
+    }
+}
+
+static int osrandom_rand_status(void) {
+    if (urandom_fd == -1) {
+        return 0;
+    } else {
+        return 1;
+    }
+}
+"""
+
+CUSTOMIZATIONS = """
+static const char *Cryptography_osrandom_engine_id = "osrandom";
+static const char *Cryptography_osrandom_engine_name = "osrandom_engine";
+
+#if defined(_WIN32)
+""" + WIN32_CUSTOMIZATIONS + """
+#else
+""" + POSIX_CUSTOMIZATIONS + """
+#endif
+
+/* This replicates the behavior of the OpenSSL FIPS RNG, which returns a
+-1 in the event that there is an error when calling RAND_pseudo_bytes.  */
+static int osrandom_pseudo_rand_bytes(unsigned char *buffer, int size) {
+    int res = osrandom_rand_bytes(buffer, size);
+    if (res == 0) {
+        return -1;
+    } else {
+        return res;
+    }
+}
+
+static RAND_METHOD osrandom_rand = {
+    NULL,
+    osrandom_rand_bytes,
+    NULL,
+    NULL,
+    osrandom_pseudo_rand_bytes,
+    osrandom_rand_status,
+};
+
+int Cryptography_add_osrandom_engine(void) {
+    ENGINE *e = ENGINE_new();
+    if (e == NULL) {
+        return 0;
+    }
+    if(!ENGINE_set_id(e, Cryptography_osrandom_engine_id) ||
+            !ENGINE_set_name(e, Cryptography_osrandom_engine_name) ||
+            !ENGINE_set_RAND(e, &osrandom_rand) ||
+            !ENGINE_set_init_function(e, osrandom_init) ||
+            !ENGINE_set_finish_function(e, osrandom_finish)) {
+        ENGINE_free(e);
+        return 0;
+    }
+    if (!ENGINE_add(e)) {
+        ENGINE_free(e);
+        return 0;
+    }
+    if (!ENGINE_free(e)) {
+        return 0;
+    }
+
+    return 1;
+}
+"""
+
+CONDITIONAL_NAMES = {}
diff --git a/docs/hazmat/backends/openssl.rst b/docs/hazmat/backends/openssl.rst
index 4db3972..f7d6b71 100644
--- a/docs/hazmat/backends/openssl.rst
+++ b/docs/hazmat/backends/openssl.rst
@@ -16,10 +16,61 @@
     * :class:`~cryptography.hazmat.backends.interfaces.HMACBackend`
     * :class:`~cryptography.hazmat.backends.interfaces.PBKDF2HMACBackend`
 
-    It has one additional public attribute.
+    It also exposes the following:
 
     .. attribute:: name
 
         The string name of this backend: ``"openssl"``
 
+    .. method:: activate_osrandom_engine()
+
+        Activates the OS random engine. This will effectively disable OpenSSL's
+        default CSPRNG.
+
+    .. method:: deactivate_osrandom_engine()
+
+        Deactivates the OS random engine if it is default. This will restore
+        the default OpenSSL CSPRNG. If the OS random engine is not the default
+        engine (e.g. if another engine is set as default) nothing will be
+        changed.
+
+OS Random Engine
+----------------
+
+OpenSSL uses a user-space CSPRNG that is seeded from system random (
+``/dev/urandom`` or ``CryptGenRandom``). This CSPRNG is not reseeded
+automatically when a process calls ``fork()``. This can result in situations
+where two different processes can return similar or identical keys and
+compromise the security of the system.
+
+The approach this project has chosen to mitigate this vulnerability is to
+include an engine that replaces the OpenSSL default CSPRNG with one that sources
+its entropy from ``/dev/urandom`` on UNIX-like operating systems and uses
+``CryptGenRandom`` on Windows. This method of pulling from the system pool
+allows us to avoid potential issues with `initializing the RNG`_ as well as
+protecting us from the ``fork()`` weakness.
+
+This engine is **active** by default when importing the OpenSSL backend. When
+active this engine will be used to generate all the random data OpenSSL
+requests.
+
+When importing only the binding it is added to the engine list but
+**not activated**.
+
+
+OS Random Sources
+-----------------
+
+On OS X and FreeBSD ``/dev/urandom`` is an alias for ``/dev/random`` and
+utilizes the `Yarrow`_ algorithm.
+
+On Windows ``CryptGenRandom`` is backed by `Fortuna`_.
+
+Linux uses its own PRNG design. ``/dev/urandom`` is a non-blocking source seeded
+from the same pool as ``/dev/random``.
+
+
 .. _`OpenSSL`: https://www.openssl.org/
+.. _`initializing the RNG`: http://en.wikipedia.org/wiki/OpenSSL#Vulnerability_in_the_Debian_implementation
+.. _`Yarrow`: http://en.wikipedia.org/wiki/Yarrow_algorithm
+.. _`Fortuna`: http://en.wikipedia.org/wiki/Fortuna_(PRNG)
diff --git a/docs/spelling_wordlist.txt b/docs/spelling_wordlist.txt
index cf421ea..acb50ff 100644
--- a/docs/spelling_wordlist.txt
+++ b/docs/spelling_wordlist.txt
@@ -28,3 +28,4 @@
 Docstrings
 Fernet
 Schneier
+Unregisters
diff --git a/tests/hazmat/backends/test_openssl.py b/tests/hazmat/backends/test_openssl.py
index ea04c13..1fd513d 100644
--- a/tests/hazmat/backends/test_openssl.py
+++ b/tests/hazmat/backends/test_openssl.py
@@ -11,6 +11,10 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
+import sys
+
+import cffi
+
 import pytest
 
 from cryptography import utils
@@ -22,6 +26,101 @@
 from cryptography.hazmat.primitives.ciphers.modes import CBC
 
 
+if sys.platform != "win32":
+    libraries = ["crypto", "ssl"]
+else:  # pragma: no cover
+    libraries = ["libeay32", "ssleay32", "advapi32"]
+
+ffi = cffi.FFI()
+
+ffi.cdef("""
+static const char *const Cryptography_faux_engine_name;
+static const char *const Cryptography_faux_engine_id;
+int Cryptography_add_faux_engine(void);
+""")
+dummy_engine = ffi.verify(
+    source="""
+        #include <openssl/engine.h>
+        #include <string.h>
+        static const char *const Cryptography_faux_engine_name="faux_engine";
+        static const char *const Cryptography_faux_engine_id="faux";
+        static int faux_bytes(unsigned char *buffer, int size) {
+            memset(buffer, 1, size);
+            return 1;
+        }
+        static int faux_status(void) { return 1; }
+        static int faux_init(ENGINE *e) { return 1; }
+        static int faux_finish(ENGINE *e) { return 1; }
+        static RAND_METHOD faux_rand = {
+            NULL,
+            faux_bytes,
+            NULL,
+            NULL,
+            faux_bytes,
+            faux_status,
+        };
+
+        int Cryptography_add_faux_engine(void) {
+            ENGINE *e = ENGINE_new();
+            if (e == NULL) {
+                return 0;
+            }
+            if(!ENGINE_set_id(e, Cryptography_faux_engine_id) ||
+                    !ENGINE_set_name(e, Cryptography_faux_engine_name) ||
+                    !ENGINE_set_RAND(e, &faux_rand) ||
+                    !ENGINE_set_init_function(e, faux_init) ||
+                    !ENGINE_set_finish_function(e, faux_finish)) {
+                return 0;
+            }
+            if (!ENGINE_add(e)) {
+                ENGINE_free(e);
+                return 0;
+            }
+            if (!ENGINE_free(e)) {
+                return 0;
+            }
+
+            return 1;
+        }
+    """,
+    libraries=libraries
+)
+
+
+def activate_dummy_engine():
+    current_rand = backend._lib.ENGINE_get_default_RAND()
+    assert current_rand != backend._ffi.NULL
+    name = backend._lib.ENGINE_get_name(current_rand)
+    assert name != backend._ffi.NULL
+    assert name != dummy_engine.Cryptography_faux_engine_name
+    res = backend._lib.ENGINE_finish(current_rand)
+    assert res == 1
+    e = backend._lib.ENGINE_by_id(dummy_engine.Cryptography_faux_engine_id)
+    assert e != backend._ffi.NULL
+    res = backend._lib.ENGINE_init(e)
+    assert res == 1
+    res = backend._lib.ENGINE_set_default_RAND(e)
+    assert res == 1
+    res = backend._lib.ENGINE_finish(e)
+    assert res == 1
+    res = backend._lib.ENGINE_free(e)
+    assert res == 1
+    # this resets the RNG to use the new engine
+    backend._lib.RAND_cleanup()
+
+
+def deactivate_dummy_engine():
+    e = backend._lib.ENGINE_get_default_RAND()
+    if e != backend._ffi.NULL:
+        name = backend._lib.ENGINE_get_name(e)
+        assert name != backend._ffi.NULL
+        if name == dummy_engine.Cryptography_faux_engine_name:
+            backend._lib.ENGINE_unregister_RAND(e)
+            backend._lib.RAND_cleanup()
+        res = backend._lib.ENGINE_finish(e)
+        assert res == 1
+
+
 @utils.register_interface(interfaces.Mode)
 class DummyMode(object):
     name = "dummy-mode"
@@ -152,3 +251,107 @@
             pytest.skip("Requires an older OpenSSL")
         with pytest.raises(UnsupportedAlgorithm):
             backend.derive_pbkdf2_hmac(hashes.SHA256(), 10, b"", 1000, b"")
+
+    # This test is not in the next class because to check if it's really
+    # default we don't want to run the setup_method before it
+    def test_osrandom_engine_is_default(self):
+        e = backend._lib.ENGINE_get_default_RAND()
+        name = backend._lib.ENGINE_get_name(e)
+        assert name == backend._lib.Cryptography_osrandom_engine_name
+        res = backend._lib.ENGINE_free(e)
+        assert res == 1
+
+
+class TestOpenSSLRandomEngine(object):
+    @classmethod
+    def setup_class(cls):
+        # add the faux engine to the list of available engines
+        res = dummy_engine.Cryptography_add_faux_engine()
+        assert res == 1
+
+    def teardown_method(self, method):
+        # we need to reset state to being default. backend is a shared global
+        # for all these tests.
+        deactivate_dummy_engine()
+        backend.activate_osrandom_engine()
+        current_default = backend._lib.ENGINE_get_default_RAND()
+        name = backend._lib.ENGINE_get_name(current_default)
+        assert name == backend._lib.Cryptography_osrandom_engine_name
+
+    def test_osrandom_sanity_check(self):
+        # This test serves as a check against catastrophic failure.
+        buf = backend._ffi.new("char[]", 500)
+        res = backend._lib.RAND_bytes(buf, 500)
+        assert res == 1
+        assert backend._ffi.buffer(buf)[:] != "\x00" * 500
+
+    def test_activate_osrandom_already_default(self):
+        e = backend._lib.ENGINE_get_default_RAND()
+        name = backend._lib.ENGINE_get_name(e)
+        assert name == backend._lib.Cryptography_osrandom_engine_name
+        res = backend._lib.ENGINE_free(e)
+        assert res == 1
+        backend.activate_osrandom_engine()
+        e = backend._lib.ENGINE_get_default_RAND()
+        name = backend._lib.ENGINE_get_name(e)
+        assert name == backend._lib.Cryptography_osrandom_engine_name
+        res = backend._lib.ENGINE_free(e)
+        assert res == 1
+
+    def test_deactivate_osrandom_engine_nothing_registered(self):
+        backend.deactivate_osrandom_engine()
+        e = backend._lib.ENGINE_get_default_RAND()
+        assert e == backend._ffi.NULL
+        backend.deactivate_osrandom_engine()
+        e = backend._lib.ENGINE_get_default_RAND()
+        assert e == backend._ffi.NULL
+
+    def test_deactivate_osrandom_engine(self):
+        e = backend._lib.ENGINE_get_default_RAND()
+        assert e != backend._ffi.NULL
+        name = backend._lib.ENGINE_get_name(e)
+        assert name == backend._lib.Cryptography_osrandom_engine_name
+        res = backend._lib.ENGINE_free(e)
+        assert res == 1
+        backend.deactivate_osrandom_engine()
+        e = backend._lib.ENGINE_get_default_RAND()
+        assert e == backend._ffi.NULL
+
+    def test_activate_osrandom_no_default(self):
+        backend.deactivate_osrandom_engine()
+        e = backend._lib.ENGINE_get_default_RAND()
+        assert e == backend._ffi.NULL
+        backend.activate_osrandom_engine()
+        e = backend._lib.ENGINE_get_default_RAND()
+        name = backend._lib.ENGINE_get_name(e)
+        assert name == backend._lib.Cryptography_osrandom_engine_name
+        res = backend._lib.ENGINE_free(e)
+        assert res == 1
+
+    def test_deactivate_osrandom_other_engine_default(self):
+        activate_dummy_engine()
+        default = backend._lib.ENGINE_get_default_RAND()
+        default_name = backend._lib.ENGINE_get_name(default)
+        assert default_name == dummy_engine.Cryptography_faux_engine_name
+        res = backend._lib.ENGINE_finish(default)
+        assert res == 1
+        backend.deactivate_osrandom_engine()
+        current_default = backend._lib.ENGINE_get_default_RAND()
+        name = backend._lib.ENGINE_get_name(current_default)
+        assert name == dummy_engine.Cryptography_faux_engine_name
+        res = backend._lib.ENGINE_finish(current_default)
+        assert res == 1
+
+    def test_activate_osrandom_other_engine_default(self):
+        activate_dummy_engine()
+        default = backend._lib.ENGINE_get_default_RAND()
+        default_name = backend._lib.ENGINE_get_name(default)
+        assert default_name == dummy_engine.Cryptography_faux_engine_name
+        res = backend._lib.ENGINE_finish(default)
+        assert res == 1
+        backend.activate_osrandom_engine()
+        current_default = backend._lib.ENGINE_get_default_RAND()
+        name = backend._lib.ENGINE_get_name(current_default)
+        assert name == backend._lib.Cryptography_osrandom_engine_name
+        res = backend._lib.ENGINE_finish(current_default)
+        assert res == 1