Merge branch 'master' into urandom-engine

* master: (58 commits)
  Moar backtick.
  Add to changelog.
  move some dashes around :)
  experiment to disable duplicate cc test runs on osx and speed up travis
  Remove register_cipher_adapter from the interface and the documentation.
  expand tox backend example
  On OS X at build time compile the CC bindings
  remove an extraneous linefeed
  reformat bindings and remove GCM for the moment
  add cipher bindings for CommonCrypto
  doc updates
  hmac support for commoncrypto
  added versionadded
  changelog to note addition of commoncrypto backend with hash support
  fix docs
  doc updates
  update docs for name attribute
  fix copy mistake in docs
  increase indent and note the value of the attribute in the docs
  move HashMethods to top level
  ...
diff --git a/cryptography/hazmat/backends/openssl/backend.py b/cryptography/hazmat/backends/openssl/backend.py
index ee82ba7..88afe99 100644
--- a/cryptography/hazmat/backends/openssl/backend.py
+++ b/cryptography/hazmat/backends/openssl/backend.py
@@ -53,6 +53,47 @@
 
         self._cipher_registry = {}
         self._register_default_ciphers()
+        self.register_osrandom_engine()
+
+    def unregister_osrandom_engine(self):
+        e = self._lib.ENGINE_get_default_RAND()
+        if e != self._ffi.NULL:
+            name = self._lib.ENGINE_get_name(e)
+            assert name != self._ffi.NULL
+            if name == self._lib.Cryptography_osrandom_engine_name:
+                self._lib.ENGINE_unregister_RAND(e)
+                # this resets the RNG to use the new engine
+                self._lib.RAND_cleanup()
+            res = self._lib.ENGINE_finish(e)
+            assert res == 1
+
+    def register_osrandom_engine(self):
+        current_rand = self._lib.ENGINE_get_default_RAND()
+        if current_rand != self._ffi.NULL:
+            name = self._lib.ENGINE_get_name(current_rand)
+            assert name != self._ffi.NULL
+            if name != self._lib.Cryptography_osrandom_engine_name:
+                self._register_osrandom_engine()
+            res = self._lib.ENGINE_finish(current_rand)
+            assert res == 1
+        else:
+            self._register_osrandom_engine()
+
+    def _register_osrandom_engine(self):
+        e = self._lib.ENGINE_by_id(self._lib.Cryptography_osrandom_engine_id)
+        assert e != self._ffi.NULL
+        res = self._lib.ENGINE_init(e)
+        assert res == 1
+        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
+        # this resets 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 88299d1..261bbb8 100644
--- a/cryptography/hazmat/bindings/openssl/binding.py
+++ b/cryptography/hazmat/bindings/openssl/binding.py
@@ -56,6 +56,7 @@
         "nid",
         "objects",
         "opensslv",
+        "osrand_engine",
         "pem",
         "pkcs7",
         "pkcs12",
@@ -81,6 +82,8 @@
         cls.ffi, cls.lib = build_ffi(cls._module_prefix, cls._modules,
                                      _OSX_PRE_INCLUDE, _OSX_POST_INCLUDE,
                                      ["crypto", "ssl"])
+        res = cls.lib.Cryptography_add_osrandom_engine()
+        assert res == 1
 
     @classmethod
     def is_available(cls):
diff --git a/cryptography/hazmat/bindings/openssl/osrand_engine.py b/cryptography/hazmat/bindings/openssl/osrand_engine.py
new file mode 100644
index 0000000..bca2d79
--- /dev/null
+++ b/cryptography/hazmat/bindings/openssl/osrand_engine.py
@@ -0,0 +1,179 @@
+# 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 = """
+"""
+
+CUSTOMIZATIONS = """
+static const char *Cryptography_osrandom_engine_id= "osrandom";
+static const char *Cryptography_osrandom_engine_name = "osrandom_engine";
+
+#ifndef _WIN32
+static int urandom_fd = -1;
+
+static int osrandom_rand_bytes(unsigned char *buffer, int size) {
+    ssize_t n;
+    while (0 < size) {
+        do {
+            n = read(urandom_fd, buffer, (size_t)size);
+        } while (n < 0 && errno == EINTR);
+        if (n <= 0) {
+            return 0;
+        }
+        buffer += n;
+        size -= n;
+    }
+    return 1;
+}
+
+static int osrandom_rand_status(void) {
+    if (urandom_fd == -1) {
+        return 0;
+    } else {
+        return 1;
+    }
+}
+
+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) {
+            return 0;
+        }
+        return 1;
+    } else {
+        return 0;
+    }
+}
+
+static int osrandom_finish(ENGINE *e) {
+    int n;
+    do {
+        n = close(urandom_fd);
+    } while (n < 0 && errno == EINTR);
+    if (n < 0) {
+        urandom_fd = -1;
+        return 0;
+    } else {
+        urandom_fd = -1;
+        return 1;
+    }
+}
+#endif
+
+#ifdef _WIN32
+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) {
+    size_t chunk;
+
+    if (hCryptProv == 0) {
+        return 0;
+    }
+
+    while (size > 0) {
+        chunk = size;
+        if (!CryptGenRandom(hCryptProv, (DWORD)chunk, buffer)) {
+            return 0;
+        }
+        buffer += chunk;
+        size -= chunk;
+    }
+    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;
+    }
+}
+#endif /* MS_WINDOWS */
+
+static RAND_METHOD osrandom_rand = {
+    NULL,
+    osrandom_rand_bytes,
+    NULL,
+    NULL,
+    osrandom_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)) {
+        return 0;
+    }
+    if (!ENGINE_add(e)) {
+        ENGINE_free(e);
+        return 0;
+    }
+    if (!ENGINE_free(e)) {
+        return 0;
+    }
+
+    return 1;
+}
+"""
+
+CONDITIONAL_NAMES = {}
diff --git a/tests/hazmat/backends/test_openssl.py b/tests/hazmat/backends/test_openssl.py
index 2a32992..51eb408 100644
--- a/tests/hazmat/backends/test_openssl.py
+++ b/tests/hazmat/backends/test_openssl.py
@@ -11,6 +11,8 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
+import cffi
+
 import pytest
 
 from cryptography import utils
@@ -23,6 +25,96 @@
 from cryptography.hazmat.primitives.ciphers.modes import CBC
 
 
+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=["crypto", "ssl"],
+)
+
+
+def register_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_id
+    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 unregister_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"
@@ -113,3 +205,100 @@
             b"error:0607F08A:digital envelope routines:EVP_EncryptFinal_ex:"
             b"data not multiple of block length"
         )
+
+    # 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.
+        unregister_dummy_engine()
+        backend.register_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_register_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.register_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_unregister_osrandom_engine_nothing_registered(self):
+        backend.unregister_osrandom_engine()
+        e = backend._lib.ENGINE_get_default_RAND()
+        assert e == backend._ffi.NULL
+        backend.unregister_osrandom_engine()
+        e = backend._lib.ENGINE_get_default_RAND()
+        assert e == backend._ffi.NULL
+
+    def test_unregister_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.unregister_osrandom_engine()
+        e = backend._lib.ENGINE_get_default_RAND()
+        assert e == backend._ffi.NULL
+
+    def test_register_osrandom_no_default(self):
+        backend.unregister_osrandom_engine()
+        e = backend._lib.ENGINE_get_default_RAND()
+        assert e == backend._ffi.NULL
+        backend.register_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_unregister_osrandom_other_engine_default(self):
+        register_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.unregister_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_register_osrandom_other_engine_default(self):
+        register_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.register_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