convert to cffi 1.0 precompile system
diff --git a/.gitignore b/.gitignore
index 509eba3..8a870e0 100644
--- a/.gitignore
+++ b/.gitignore
@@ -3,7 +3,7 @@
 build/
 dist/
 htmlcov/
-src/cryptography/_Cryptography_cffi_*
+*.so
 .tox/
 .cache/
 .coverage
diff --git a/CHANGELOG.rst b/CHANGELOG.rst
index 7e0f8a8..eacd934 100644
--- a/CHANGELOG.rst
+++ b/CHANGELOG.rst
@@ -6,6 +6,9 @@
 
 .. note:: This version is not yet released and is under active development.
 
+* Switched to the new `cffi`_ ``set_source`` out-of-line API mode for
+  compilation. This results in significantly faster imports and lowered
+  memory consumption.
 * Support serialization of certificate signing requests using the
   ``public_bytes`` method of
   :class:`~cryptography.x509.CertificateSigningRequest`.
@@ -442,3 +445,4 @@
 * Initial release.
 
 .. _`master`: https://github.com/pyca/cryptography/
+.. _`cffi`: https://cffi.readthedocs.org/en/latest/
diff --git a/MANIFEST.in b/MANIFEST.in
index 8dbd0dc..b05a869 100644
--- a/MANIFEST.in
+++ b/MANIFEST.in
@@ -7,8 +7,7 @@
 include README.rst
 
 recursive-include docs *
-recursive-include src/cryptography/hazmat/primitives/src *.c *.h
-recursive-include src/cryptography/hazmat/bindings/openssl/src *.c *.h
+recursive-include src/_cffi_src *.py *.c *.h
 prune docs/_build
 recursive-include tests *.py
 recursive-exclude vectors *
diff --git a/setup.py b/setup.py
index 77f6dcd..2f950b7 100644
--- a/setup.py
+++ b/setup.py
@@ -45,7 +45,7 @@
     requirements.append("ipaddress")
 
 if platform.python_implementation() != "PyPy":
-    requirements.append("cffi>=0.8")
+    requirements.append("cffi>=1.1.0")
 
 # If you add a new dep here you probably need to add it in the tox.ini as well
 test_requirements = [
@@ -75,52 +75,6 @@
     )
 
 
-def get_ext_modules():
-    from cryptography.hazmat.bindings.commoncrypto.binding import (
-        Binding as CommonCryptoBinding
-    )
-    from cryptography.hazmat.bindings.openssl.binding import (
-        Binding as OpenSSLBinding
-    )
-    from cryptography.hazmat.primitives import constant_time, padding
-
-    ext_modules = [
-        OpenSSLBinding.ffi.verifier.get_extension(),
-        constant_time._ffi.verifier.get_extension(),
-        padding._ffi.verifier.get_extension()
-    ]
-    if cc_is_available():
-        ext_modules.append(CommonCryptoBinding.ffi.verifier.get_extension())
-    return ext_modules
-
-
-class CFFIBuild(build):
-    """
-    This class exists, instead of just providing ``ext_modules=[...]`` directly
-    in ``setup()`` because importing cryptography requires we have several
-    packages installed first.
-
-    By doing the imports here we ensure that packages listed in
-    ``setup_requires`` are already installed.
-    """
-
-    def finalize_options(self):
-        self.distribution.ext_modules = get_ext_modules()
-        build.finalize_options(self)
-
-
-class CFFIInstall(install):
-    """
-    As a consequence of CFFIBuild and it's late addition of ext_modules, we
-    need the equivalent for the ``install`` command to install into platlib
-    install-dir rather than purelib.
-    """
-
-    def finalize_options(self):
-        self.distribution.ext_modules = get_ext_modules()
-        install.finalize_options(self)
-
-
 class PyTest(test):
     def finalize_options(self):
         test.finalize_options(self)
@@ -234,19 +188,26 @@
            for i in range(1, len(argv))):
         return {
             "cmdclass": {
-                "build": DummyCFFIBuild,
-                "install": DummyCFFIInstall,
+                "build": DummyBuild,
+                "install": DummyInstall,
                 "test": DummyPyTest,
             }
         }
     else:
+        cffi_modules = [
+            "src/_cffi_src/build_openssl.py:ffi",
+            "src/_cffi_src/build_constant_time.py:ffi",
+            "src/_cffi_src/build_padding.py:ffi",
+        ]
+        if cc_is_available():
+            cffi_modules.append("src/_cffi_src/build_commoncrypto.py:ffi")
+
         return {
             "setup_requires": requirements,
             "cmdclass": {
-                "build": CFFIBuild,
-                "install": CFFIInstall,
                 "test": PyTest,
-            }
+            },
+            "cffi_modules": cffi_modules
         }
 
 
@@ -255,7 +216,7 @@
                         "free command or option.")
 
 
-class DummyCFFIBuild(build):
+class DummyBuild(build):
     """
     This class makes it very obvious when ``keywords_with_side_effects()`` has
     incorrectly interpreted the command line arguments to ``setup.py build`` as
@@ -266,7 +227,7 @@
         raise RuntimeError(setup_requires_error)
 
 
-class DummyCFFIInstall(install):
+class DummyInstall(install):
     """
     This class makes it very obvious when ``keywords_with_side_effects()`` has
     incorrectly interpreted the command line arguments to ``setup.py install``
@@ -327,7 +288,9 @@
     ],
 
     package_dir={"": "src"},
-    packages=find_packages(where="src", exclude=["tests", "tests.*"]),
+    packages=find_packages(
+        where="src", exclude=["_cffi_src", "_cffi_src.*", "tests", "tests.*"]
+    ),
     include_package_data=True,
 
     install_requires=requirements,
@@ -335,7 +298,7 @@
 
     # for cffi
     zip_safe=False,
-    ext_package="cryptography",
+    ext_package="cryptography.hazmat.bindings",
     entry_points={
         "cryptography.backends": backends,
     },
diff --git a/src/_cffi_src/__init__.py b/src/_cffi_src/__init__.py
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/src/_cffi_src/__init__.py
diff --git a/src/_cffi_src/build_commoncrypto.py b/src/_cffi_src/build_commoncrypto.py
new file mode 100644
index 0000000..1c2692a
--- /dev/null
+++ b/src/_cffi_src/build_commoncrypto.py
@@ -0,0 +1,29 @@
+# This file is dual licensed under the terms of the Apache License, Version
+# 2.0, and the BSD License. See the LICENSE file in the root of this repository
+# for complete details.
+
+from __future__ import absolute_import, division, print_function
+
+from _cffi_src.utils import build_ffi_for_binding
+
+
+ffi = build_ffi_for_binding(
+    module_name="_commoncrypto",
+    module_prefix="_cffi_src.commoncrypto.",
+    modules=[
+        "cf",
+        "common_digest",
+        "common_hmac",
+        "common_key_derivation",
+        "common_cryptor",
+        "common_symmetric_key_wrap",
+        "secimport",
+        "secitem",
+        "seckey",
+        "seckeychain",
+        "sectransform",
+    ],
+    extra_link_args=[
+        "-framework", "Security", "-framework", "CoreFoundation"
+    ],
+)
diff --git a/src/_cffi_src/build_constant_time.py b/src/_cffi_src/build_constant_time.py
new file mode 100644
index 0000000..eae0f21
--- /dev/null
+++ b/src/_cffi_src/build_constant_time.py
@@ -0,0 +1,26 @@
+# This file is dual licensed under the terms of the Apache License, Version
+# 2.0, and the BSD License. See the LICENSE file in the root of this repository
+# for complete details.
+
+from __future__ import absolute_import, division, print_function
+
+import os
+
+from _cffi_src.utils import build_ffi
+
+
+with open(os.path.join(
+    os.path.dirname(__file__), "hazmat_src/constant_time.h"
+)) as f:
+    types = f.read()
+
+with open(os.path.join(
+    os.path.dirname(__file__), "hazmat_src/constant_time.c"
+)) as f:
+    functions = f.read()
+
+ffi = build_ffi(
+    module_name="_constant_time",
+    cdef_source=types,
+    verify_source=functions
+)
diff --git a/src/_cffi_src/build_openssl.py b/src/_cffi_src/build_openssl.py
new file mode 100644
index 0000000..4c30fe4
--- /dev/null
+++ b/src/_cffi_src/build_openssl.py
@@ -0,0 +1,98 @@
+# This file is dual licensed under the terms of the Apache License, Version
+# 2.0, and the BSD License. See the LICENSE file in the root of this repository
+# for complete details.
+
+from __future__ import absolute_import, division, print_function
+
+import os
+import sys
+
+from _cffi_src.utils import (
+    build_ffi_for_binding
+)
+
+
+def _get_openssl_libraries(platform):
+    # OpenSSL goes by a different library name on different operating systems.
+    if platform != "win32":
+        # In some circumstances, the order in which these libs are
+        # specified on the linker command-line is significant;
+        # libssl must come before libcrypto
+        # (http://marc.info/?l=openssl-users&m=135361825921871)
+        return ["ssl", "crypto"]
+    else:
+        link_type = os.environ.get("PYCA_WINDOWS_LINK_TYPE", "static")
+        return _get_openssl_windows_libraries(link_type)
+
+
+def _get_openssl_windows_libraries(link_type):
+    if link_type == "dynamic":
+        return ["libeay32", "ssleay32", "advapi32"]
+    elif link_type == "static" or link_type == "":
+        return ["libeay32mt", "ssleay32mt", "advapi32",
+                "crypt32", "gdi32", "user32", "ws2_32"]
+    else:
+        raise ValueError(
+            "PYCA_WINDOWS_LINK_TYPE must be 'static' or 'dynamic'"
+        )
+
+
+_OSX_PRE_INCLUDE = """
+#ifdef __APPLE__
+#include <AvailabilityMacros.h>
+#define __ORIG_DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER \
+    DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER
+#undef DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER
+#define DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER
+#endif
+"""
+
+_OSX_POST_INCLUDE = """
+#ifdef __APPLE__
+#undef DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER
+#define DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER \
+    __ORIG_DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER
+#endif
+"""
+
+
+ffi = build_ffi_for_binding(
+    module_name="_openssl",
+    module_prefix="_cffi_src.openssl.",
+    modules=[
+        "aes",
+        "asn1",
+        "bignum",
+        "bio",
+        "cmac",
+        "cms",
+        "conf",
+        "crypto",
+        "dh",
+        "dsa",
+        "ec",
+        "ecdh",
+        "ecdsa",
+        "engine",
+        "err",
+        "evp",
+        "hmac",
+        "nid",
+        "objects",
+        "opensslv",
+        "osrandom_engine",
+        "pem",
+        "pkcs7",
+        "pkcs12",
+        "rand",
+        "rsa",
+        "ssl",
+        "x509",
+        "x509name",
+        "x509v3",
+        "x509_vfy"
+    ],
+    pre_include=_OSX_PRE_INCLUDE,
+    post_include=_OSX_POST_INCLUDE,
+    libraries=_get_openssl_libraries(sys.platform)
+)
diff --git a/src/_cffi_src/build_padding.py b/src/_cffi_src/build_padding.py
new file mode 100644
index 0000000..3eeac2e
--- /dev/null
+++ b/src/_cffi_src/build_padding.py
@@ -0,0 +1,26 @@
+# This file is dual licensed under the terms of the Apache License, Version
+# 2.0, and the BSD License. See the LICENSE file in the root of this repository
+# for complete details.
+
+from __future__ import absolute_import, division, print_function
+
+import os
+
+from _cffi_src.utils import build_ffi
+
+
+with open(os.path.join(
+    os.path.dirname(__file__), "hazmat_src/padding.h"
+)) as f:
+    types = f.read()
+
+with open(os.path.join(
+    os.path.dirname(__file__), "hazmat_src/padding.c"
+)) as f:
+    functions = f.read()
+
+ffi = build_ffi(
+    module_name="_padding",
+    cdef_source=types,
+    verify_source=functions
+)
diff --git a/src/_cffi_src/commoncrypto/__init__.py b/src/_cffi_src/commoncrypto/__init__.py
new file mode 100644
index 0000000..4b54088
--- /dev/null
+++ b/src/_cffi_src/commoncrypto/__init__.py
@@ -0,0 +1,5 @@
+# This file is dual licensed under the terms of the Apache License, Version
+# 2.0, and the BSD License. See the LICENSE file in the root of this repository
+# for complete details.
+
+from __future__ import absolute_import, division, print_function
diff --git a/src/cryptography/hazmat/bindings/commoncrypto/cf.py b/src/_cffi_src/commoncrypto/cf.py
similarity index 100%
rename from src/cryptography/hazmat/bindings/commoncrypto/cf.py
rename to src/_cffi_src/commoncrypto/cf.py
diff --git a/src/cryptography/hazmat/bindings/commoncrypto/common_cryptor.py b/src/_cffi_src/commoncrypto/common_cryptor.py
similarity index 100%
rename from src/cryptography/hazmat/bindings/commoncrypto/common_cryptor.py
rename to src/_cffi_src/commoncrypto/common_cryptor.py
diff --git a/src/cryptography/hazmat/bindings/commoncrypto/common_digest.py b/src/_cffi_src/commoncrypto/common_digest.py
similarity index 100%
rename from src/cryptography/hazmat/bindings/commoncrypto/common_digest.py
rename to src/_cffi_src/commoncrypto/common_digest.py
diff --git a/src/cryptography/hazmat/bindings/commoncrypto/common_hmac.py b/src/_cffi_src/commoncrypto/common_hmac.py
similarity index 100%
rename from src/cryptography/hazmat/bindings/commoncrypto/common_hmac.py
rename to src/_cffi_src/commoncrypto/common_hmac.py
diff --git a/src/cryptography/hazmat/bindings/commoncrypto/common_key_derivation.py b/src/_cffi_src/commoncrypto/common_key_derivation.py
similarity index 100%
rename from src/cryptography/hazmat/bindings/commoncrypto/common_key_derivation.py
rename to src/_cffi_src/commoncrypto/common_key_derivation.py
diff --git a/src/cryptography/hazmat/bindings/commoncrypto/common_symmetric_key_wrap.py b/src/_cffi_src/commoncrypto/common_symmetric_key_wrap.py
similarity index 100%
rename from src/cryptography/hazmat/bindings/commoncrypto/common_symmetric_key_wrap.py
rename to src/_cffi_src/commoncrypto/common_symmetric_key_wrap.py
diff --git a/src/cryptography/hazmat/bindings/commoncrypto/secimport.py b/src/_cffi_src/commoncrypto/secimport.py
similarity index 100%
rename from src/cryptography/hazmat/bindings/commoncrypto/secimport.py
rename to src/_cffi_src/commoncrypto/secimport.py
diff --git a/src/cryptography/hazmat/bindings/commoncrypto/secitem.py b/src/_cffi_src/commoncrypto/secitem.py
similarity index 100%
rename from src/cryptography/hazmat/bindings/commoncrypto/secitem.py
rename to src/_cffi_src/commoncrypto/secitem.py
diff --git a/src/cryptography/hazmat/bindings/commoncrypto/seckey.py b/src/_cffi_src/commoncrypto/seckey.py
similarity index 100%
rename from src/cryptography/hazmat/bindings/commoncrypto/seckey.py
rename to src/_cffi_src/commoncrypto/seckey.py
diff --git a/src/cryptography/hazmat/bindings/commoncrypto/seckeychain.py b/src/_cffi_src/commoncrypto/seckeychain.py
similarity index 100%
rename from src/cryptography/hazmat/bindings/commoncrypto/seckeychain.py
rename to src/_cffi_src/commoncrypto/seckeychain.py
diff --git a/src/cryptography/hazmat/bindings/commoncrypto/sectransform.py b/src/_cffi_src/commoncrypto/sectransform.py
similarity index 100%
rename from src/cryptography/hazmat/bindings/commoncrypto/sectransform.py
rename to src/_cffi_src/commoncrypto/sectransform.py
diff --git a/src/cryptography/hazmat/primitives/src/constant_time.c b/src/_cffi_src/hazmat_src/constant_time.c
similarity index 100%
rename from src/cryptography/hazmat/primitives/src/constant_time.c
rename to src/_cffi_src/hazmat_src/constant_time.c
diff --git a/src/cryptography/hazmat/primitives/src/constant_time.h b/src/_cffi_src/hazmat_src/constant_time.h
similarity index 100%
rename from src/cryptography/hazmat/primitives/src/constant_time.h
rename to src/_cffi_src/hazmat_src/constant_time.h
diff --git a/src/cryptography/hazmat/primitives/src/padding.c b/src/_cffi_src/hazmat_src/padding.c
similarity index 100%
rename from src/cryptography/hazmat/primitives/src/padding.c
rename to src/_cffi_src/hazmat_src/padding.c
diff --git a/src/cryptography/hazmat/primitives/src/padding.h b/src/_cffi_src/hazmat_src/padding.h
similarity index 100%
rename from src/cryptography/hazmat/primitives/src/padding.h
rename to src/_cffi_src/hazmat_src/padding.h
diff --git a/src/_cffi_src/openssl/__init__.py b/src/_cffi_src/openssl/__init__.py
new file mode 100644
index 0000000..4b54088
--- /dev/null
+++ b/src/_cffi_src/openssl/__init__.py
@@ -0,0 +1,5 @@
+# This file is dual licensed under the terms of the Apache License, Version
+# 2.0, and the BSD License. See the LICENSE file in the root of this repository
+# for complete details.
+
+from __future__ import absolute_import, division, print_function
diff --git a/src/cryptography/hazmat/bindings/openssl/aes.py b/src/_cffi_src/openssl/aes.py
similarity index 100%
rename from src/cryptography/hazmat/bindings/openssl/aes.py
rename to src/_cffi_src/openssl/aes.py
diff --git a/src/cryptography/hazmat/bindings/openssl/asn1.py b/src/_cffi_src/openssl/asn1.py
similarity index 100%
rename from src/cryptography/hazmat/bindings/openssl/asn1.py
rename to src/_cffi_src/openssl/asn1.py
diff --git a/src/cryptography/hazmat/bindings/openssl/bignum.py b/src/_cffi_src/openssl/bignum.py
similarity index 100%
rename from src/cryptography/hazmat/bindings/openssl/bignum.py
rename to src/_cffi_src/openssl/bignum.py
diff --git a/src/cryptography/hazmat/bindings/openssl/bio.py b/src/_cffi_src/openssl/bio.py
similarity index 100%
rename from src/cryptography/hazmat/bindings/openssl/bio.py
rename to src/_cffi_src/openssl/bio.py
diff --git a/src/cryptography/hazmat/bindings/openssl/cmac.py b/src/_cffi_src/openssl/cmac.py
similarity index 100%
rename from src/cryptography/hazmat/bindings/openssl/cmac.py
rename to src/_cffi_src/openssl/cmac.py
diff --git a/src/cryptography/hazmat/bindings/openssl/cms.py b/src/_cffi_src/openssl/cms.py
similarity index 100%
rename from src/cryptography/hazmat/bindings/openssl/cms.py
rename to src/_cffi_src/openssl/cms.py
diff --git a/src/cryptography/hazmat/bindings/openssl/conf.py b/src/_cffi_src/openssl/conf.py
similarity index 100%
rename from src/cryptography/hazmat/bindings/openssl/conf.py
rename to src/_cffi_src/openssl/conf.py
diff --git a/src/cryptography/hazmat/bindings/openssl/crypto.py b/src/_cffi_src/openssl/crypto.py
similarity index 100%
rename from src/cryptography/hazmat/bindings/openssl/crypto.py
rename to src/_cffi_src/openssl/crypto.py
diff --git a/src/cryptography/hazmat/bindings/openssl/dh.py b/src/_cffi_src/openssl/dh.py
similarity index 100%
rename from src/cryptography/hazmat/bindings/openssl/dh.py
rename to src/_cffi_src/openssl/dh.py
diff --git a/src/cryptography/hazmat/bindings/openssl/dsa.py b/src/_cffi_src/openssl/dsa.py
similarity index 100%
rename from src/cryptography/hazmat/bindings/openssl/dsa.py
rename to src/_cffi_src/openssl/dsa.py
diff --git a/src/cryptography/hazmat/bindings/openssl/ec.py b/src/_cffi_src/openssl/ec.py
similarity index 100%
rename from src/cryptography/hazmat/bindings/openssl/ec.py
rename to src/_cffi_src/openssl/ec.py
diff --git a/src/cryptography/hazmat/bindings/openssl/ecdh.py b/src/_cffi_src/openssl/ecdh.py
similarity index 100%
rename from src/cryptography/hazmat/bindings/openssl/ecdh.py
rename to src/_cffi_src/openssl/ecdh.py
diff --git a/src/cryptography/hazmat/bindings/openssl/ecdsa.py b/src/_cffi_src/openssl/ecdsa.py
similarity index 100%
rename from src/cryptography/hazmat/bindings/openssl/ecdsa.py
rename to src/_cffi_src/openssl/ecdsa.py
diff --git a/src/cryptography/hazmat/bindings/openssl/engine.py b/src/_cffi_src/openssl/engine.py
similarity index 100%
rename from src/cryptography/hazmat/bindings/openssl/engine.py
rename to src/_cffi_src/openssl/engine.py
diff --git a/src/cryptography/hazmat/bindings/openssl/err.py b/src/_cffi_src/openssl/err.py
similarity index 100%
rename from src/cryptography/hazmat/bindings/openssl/err.py
rename to src/_cffi_src/openssl/err.py
diff --git a/src/cryptography/hazmat/bindings/openssl/evp.py b/src/_cffi_src/openssl/evp.py
similarity index 100%
rename from src/cryptography/hazmat/bindings/openssl/evp.py
rename to src/_cffi_src/openssl/evp.py
diff --git a/src/cryptography/hazmat/bindings/openssl/hmac.py b/src/_cffi_src/openssl/hmac.py
similarity index 100%
rename from src/cryptography/hazmat/bindings/openssl/hmac.py
rename to src/_cffi_src/openssl/hmac.py
diff --git a/src/cryptography/hazmat/bindings/openssl/nid.py b/src/_cffi_src/openssl/nid.py
similarity index 100%
rename from src/cryptography/hazmat/bindings/openssl/nid.py
rename to src/_cffi_src/openssl/nid.py
diff --git a/src/cryptography/hazmat/bindings/openssl/objects.py b/src/_cffi_src/openssl/objects.py
similarity index 100%
rename from src/cryptography/hazmat/bindings/openssl/objects.py
rename to src/_cffi_src/openssl/objects.py
diff --git a/src/cryptography/hazmat/bindings/openssl/opensslv.py b/src/_cffi_src/openssl/opensslv.py
similarity index 100%
rename from src/cryptography/hazmat/bindings/openssl/opensslv.py
rename to src/_cffi_src/openssl/opensslv.py
diff --git a/src/cryptography/hazmat/bindings/openssl/osrandom_engine.py b/src/_cffi_src/openssl/osrandom_engine.py
similarity index 100%
rename from src/cryptography/hazmat/bindings/openssl/osrandom_engine.py
rename to src/_cffi_src/openssl/osrandom_engine.py
diff --git a/src/cryptography/hazmat/bindings/openssl/pem.py b/src/_cffi_src/openssl/pem.py
similarity index 100%
rename from src/cryptography/hazmat/bindings/openssl/pem.py
rename to src/_cffi_src/openssl/pem.py
diff --git a/src/cryptography/hazmat/bindings/openssl/pkcs12.py b/src/_cffi_src/openssl/pkcs12.py
similarity index 100%
rename from src/cryptography/hazmat/bindings/openssl/pkcs12.py
rename to src/_cffi_src/openssl/pkcs12.py
diff --git a/src/cryptography/hazmat/bindings/openssl/pkcs7.py b/src/_cffi_src/openssl/pkcs7.py
similarity index 100%
rename from src/cryptography/hazmat/bindings/openssl/pkcs7.py
rename to src/_cffi_src/openssl/pkcs7.py
diff --git a/src/cryptography/hazmat/bindings/openssl/rand.py b/src/_cffi_src/openssl/rand.py
similarity index 100%
rename from src/cryptography/hazmat/bindings/openssl/rand.py
rename to src/_cffi_src/openssl/rand.py
diff --git a/src/cryptography/hazmat/bindings/openssl/rsa.py b/src/_cffi_src/openssl/rsa.py
similarity index 100%
rename from src/cryptography/hazmat/bindings/openssl/rsa.py
rename to src/_cffi_src/openssl/rsa.py
diff --git a/src/cryptography/hazmat/bindings/openssl/src/osrandom_engine.c b/src/_cffi_src/openssl/src/osrandom_engine.c
similarity index 100%
rename from src/cryptography/hazmat/bindings/openssl/src/osrandom_engine.c
rename to src/_cffi_src/openssl/src/osrandom_engine.c
diff --git a/src/cryptography/hazmat/bindings/openssl/src/osrandom_engine.h b/src/_cffi_src/openssl/src/osrandom_engine.h
similarity index 100%
rename from src/cryptography/hazmat/bindings/openssl/src/osrandom_engine.h
rename to src/_cffi_src/openssl/src/osrandom_engine.h
diff --git a/src/cryptography/hazmat/bindings/openssl/ssl.py b/src/_cffi_src/openssl/ssl.py
similarity index 100%
rename from src/cryptography/hazmat/bindings/openssl/ssl.py
rename to src/_cffi_src/openssl/ssl.py
diff --git a/src/cryptography/hazmat/bindings/openssl/x509.py b/src/_cffi_src/openssl/x509.py
similarity index 100%
rename from src/cryptography/hazmat/bindings/openssl/x509.py
rename to src/_cffi_src/openssl/x509.py
diff --git a/src/cryptography/hazmat/bindings/openssl/x509_vfy.py b/src/_cffi_src/openssl/x509_vfy.py
similarity index 100%
rename from src/cryptography/hazmat/bindings/openssl/x509_vfy.py
rename to src/_cffi_src/openssl/x509_vfy.py
diff --git a/src/cryptography/hazmat/bindings/openssl/x509name.py b/src/_cffi_src/openssl/x509name.py
similarity index 100%
rename from src/cryptography/hazmat/bindings/openssl/x509name.py
rename to src/_cffi_src/openssl/x509name.py
diff --git a/src/cryptography/hazmat/bindings/openssl/x509v3.py b/src/_cffi_src/openssl/x509v3.py
similarity index 100%
rename from src/cryptography/hazmat/bindings/openssl/x509v3.py
rename to src/_cffi_src/openssl/x509v3.py
diff --git a/src/_cffi_src/utils.py b/src/_cffi_src/utils.py
new file mode 100644
index 0000000..b1ad74d
--- /dev/null
+++ b/src/_cffi_src/utils.py
@@ -0,0 +1,82 @@
+# This file is dual licensed under the terms of the Apache License, Version
+# 2.0, and the BSD License. See the LICENSE file in the root of this repository
+# for complete details.
+
+from __future__ import absolute_import, division, print_function
+
+import sys
+
+from cffi import FFI
+
+
+def build_ffi_for_binding(module_name, module_prefix, modules, pre_include="",
+                          post_include="", libraries=[], extra_compile_args=[],
+                          extra_link_args=[]):
+    """
+    Modules listed in ``modules`` should have the following attributes:
+
+    * ``INCLUDES``: A string containing C includes.
+    * ``TYPES``: A string containing C declarations for types.
+    * ``FUNCTIONS``: A string containing C declarations for functions.
+    * ``MACROS``: A string containing C declarations for any macros.
+    * ``CUSTOMIZATIONS``: A string containing arbitrary top-level C code, this
+        can be used to do things like test for a define and provide an
+        alternate implementation based on that.
+    * ``CONDITIONAL_NAMES``: A dict mapping strings of condition names from the
+        library to a list of names which will not be present without the
+        condition.
+    """
+    types = []
+    includes = []
+    functions = []
+    macros = []
+    customizations = []
+    for name in modules:
+        __import__(module_prefix + name)
+        module = sys.modules[module_prefix + name]
+
+        types.append(module.TYPES)
+        macros.append(module.MACROS)
+        functions.append(module.FUNCTIONS)
+        includes.append(module.INCLUDES)
+        customizations.append(module.CUSTOMIZATIONS)
+
+    # We include functions here so that if we got any of their definitions
+    # wrong, the underlying C compiler will explode. In C you are allowed
+    # to re-declare a function if it has the same signature. That is:
+    #   int foo(int);
+    #   int foo(int);
+    # is legal, but the following will fail to compile:
+    #   int foo(int);
+    #   int foo(short);
+    verify_source = "\n".join(
+        [pre_include] +
+        includes +
+        [post_include] +
+        functions +
+        customizations
+    )
+    ffi = build_ffi(
+        module_name,
+        cdef_source="\n".join(types + functions + macros),
+        verify_source=verify_source,
+        libraries=libraries,
+        extra_compile_args=extra_compile_args,
+        extra_link_args=extra_link_args,
+    )
+
+    return ffi
+
+
+def build_ffi(module_name, cdef_source, verify_source, libraries=[],
+              extra_compile_args=[], extra_link_args=[]):
+    ffi = FFI()
+    ffi.cdef(cdef_source)
+    ffi.set_source(
+        module_name,
+        verify_source,
+        libraries=libraries,
+        extra_compile_args=extra_compile_args,
+        extra_link_args=extra_link_args,
+    )
+    return ffi
diff --git a/src/cryptography/hazmat/bindings/commoncrypto/binding.py b/src/cryptography/hazmat/bindings/commoncrypto/binding.py
index 54c7603..1695c04 100644
--- a/src/cryptography/hazmat/bindings/commoncrypto/binding.py
+++ b/src/cryptography/hazmat/bindings/commoncrypto/binding.py
@@ -4,54 +4,15 @@
 
 from __future__ import absolute_import, division, print_function
 
-import threading
-
-from cryptography.hazmat.bindings.utils import (
-    build_ffi_for_binding, load_library_for_binding,
-)
+from cryptography.hazmat.bindings._commoncrypto import ffi, lib
 
 
 class Binding(object):
     """
     CommonCrypto API wrapper.
     """
-    _module_prefix = "cryptography.hazmat.bindings.commoncrypto."
-    _modules = [
-        "cf",
-        "common_digest",
-        "common_hmac",
-        "common_key_derivation",
-        "common_cryptor",
-        "common_symmetric_key_wrap",
-        "secimport",
-        "secitem",
-        "seckey",
-        "seckeychain",
-        "sectransform",
-    ]
-
-    ffi = build_ffi_for_binding(
-        module_prefix=_module_prefix,
-        modules=_modules,
-        extra_link_args=[
-            "-framework", "Security", "-framework", "CoreFoundation"
-        ],
-    )
-    lib = None
-    _init_lock = threading.Lock()
+    lib = lib
+    ffi = ffi
 
     def __init__(self):
-        self._ensure_ffi_initialized()
-
-    @classmethod
-    def _ensure_ffi_initialized(cls):
-        if cls.lib is not None:
-            return
-
-        with cls._init_lock:
-            if cls.lib is None:
-                cls.lib = load_library_for_binding(
-                    cls.ffi,
-                    module_prefix=cls._module_prefix,
-                    modules=cls._modules,
-                )
+        pass
diff --git a/src/cryptography/hazmat/bindings/openssl/binding.py b/src/cryptography/hazmat/bindings/openssl/binding.py
index 5ccee97..e0a8397 100644
--- a/src/cryptography/hazmat/bindings/openssl/binding.py
+++ b/src/cryptography/hazmat/bindings/openssl/binding.py
@@ -4,128 +4,34 @@
 
 from __future__ import absolute_import, division, print_function
 
-import os
-import sys
 import threading
 
-from cryptography.hazmat.bindings.utils import (
-    build_ffi_for_binding, load_library_for_binding,
-)
-
-
-_OSX_PRE_INCLUDE = """
-#ifdef __APPLE__
-#include <AvailabilityMacros.h>
-#define __ORIG_DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER \
-    DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER
-#undef DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER
-#define DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER
-#endif
-"""
-
-_OSX_POST_INCLUDE = """
-#ifdef __APPLE__
-#undef DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER
-#define DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER \
-    __ORIG_DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER
-#endif
-"""
-
-
-def _get_libraries(platform):
-    # OpenSSL goes by a different library name on different operating systems.
-    if platform != "win32":
-        # In some circumstances, the order in which these libs are
-        # specified on the linker command-line is significant;
-        # libssl must come before libcrypto
-        # (http://marc.info/?l=openssl-users&m=135361825921871)
-        return ["ssl", "crypto"]
-    else:
-        link_type = os.environ.get("PYCA_WINDOWS_LINK_TYPE", "static")
-        return _get_windows_libraries(link_type)
-
-
-def _get_windows_libraries(link_type):
-    if link_type == "dynamic":
-        return ["libeay32", "ssleay32", "advapi32"]
-    elif link_type == "static" or link_type == "":
-        return ["libeay32mt", "ssleay32mt", "advapi32",
-                "crypt32", "gdi32", "user32", "ws2_32"]
-    else:
-        raise ValueError(
-            "PYCA_WINDOWS_LINK_TYPE must be 'static' or 'dynamic'"
-        )
+from cryptography.hazmat.bindings._openssl import ffi, lib
 
 
 class Binding(object):
     """
     OpenSSL API wrapper.
     """
-    _module_prefix = "cryptography.hazmat.bindings.openssl."
-    _modules = [
-        "aes",
-        "asn1",
-        "bignum",
-        "bio",
-        "cmac",
-        "cms",
-        "conf",
-        "crypto",
-        "dh",
-        "dsa",
-        "ec",
-        "ecdh",
-        "ecdsa",
-        "engine",
-        "err",
-        "evp",
-        "hmac",
-        "nid",
-        "objects",
-        "opensslv",
-        "osrandom_engine",
-        "pem",
-        "pkcs7",
-        "pkcs12",
-        "rand",
-        "rsa",
-        "ssl",
-        "x509",
-        "x509name",
-        "x509v3",
-        "x509_vfy"
-    ]
-
+    lib = lib
+    ffi = ffi
+    _lib_loaded = False
     _locks = None
     _lock_cb_handle = None
     _init_lock = threading.Lock()
     _lock_init_lock = threading.Lock()
 
-    ffi = build_ffi_for_binding(
-        module_prefix=_module_prefix,
-        modules=_modules,
-        pre_include=_OSX_PRE_INCLUDE,
-        post_include=_OSX_POST_INCLUDE,
-        libraries=_get_libraries(sys.platform)
-    )
-    lib = None
-
     def __init__(self):
         self._ensure_ffi_initialized()
 
     @classmethod
     def _ensure_ffi_initialized(cls):
-        if cls.lib is not None:
+        if cls._lib_loaded:
             return
 
         with cls._init_lock:
-            if cls.lib is None:
-                cls.lib = load_library_for_binding(
-                    cls.ffi,
-                    cls._module_prefix,
-                    cls._modules,
-                )
-
+            if not cls._lib_loaded:
+                cls._lib_loaded = True
                 res = cls.lib.Cryptography_add_osrandom_engine()
                 assert res != 0
 
diff --git a/src/cryptography/hazmat/bindings/utils.py b/src/cryptography/hazmat/bindings/utils.py
deleted file mode 100644
index 52c6f8b..0000000
--- a/src/cryptography/hazmat/bindings/utils.py
+++ /dev/null
@@ -1,146 +0,0 @@
-# This file is dual licensed under the terms of the Apache License, Version
-# 2.0, and the BSD License. See the LICENSE file in the root of this repository
-# for complete details.
-
-from __future__ import absolute_import, division, print_function
-
-import binascii
-import sys
-import threading
-
-from cffi import FFI
-from cffi.verifier import Verifier
-
-
-class LazyLibrary(object):
-    def __init__(self, ffi):
-        self._ffi = ffi
-        self._lib = None
-        self._lock = threading.Lock()
-
-    def __getattr__(self, name):
-        if self._lib is None:
-            with self._lock:
-                if self._lib is None:
-                    self._lib = self._ffi.verifier.load_library()
-
-        return getattr(self._lib, name)
-
-
-def load_library_for_binding(ffi, module_prefix, modules):
-    lib = ffi.verifier.load_library()
-
-    for name in modules:
-        module_name = module_prefix + name
-        module = sys.modules[module_name]
-        for condition, names in module.CONDITIONAL_NAMES.items():
-            if not getattr(lib, condition):
-                for name in names:
-                    delattr(lib, name)
-
-    return lib
-
-
-def build_ffi_for_binding(module_prefix, modules, pre_include="",
-                          post_include="", libraries=[], extra_compile_args=[],
-                          extra_link_args=[]):
-    """
-    Modules listed in ``modules`` should have the following attributes:
-
-    * ``INCLUDES``: A string containing C includes.
-    * ``TYPES``: A string containing C declarations for types.
-    * ``FUNCTIONS``: A string containing C declarations for functions.
-    * ``MACROS``: A string containing C declarations for any macros.
-    * ``CUSTOMIZATIONS``: A string containing arbitrary top-level C code, this
-        can be used to do things like test for a define and provide an
-        alternate implementation based on that.
-    * ``CONDITIONAL_NAMES``: A dict mapping strings of condition names from the
-        library to a list of names which will not be present without the
-        condition.
-    """
-    types = []
-    includes = []
-    functions = []
-    macros = []
-    customizations = []
-    for name in modules:
-        module_name = module_prefix + name
-        __import__(module_name)
-        module = sys.modules[module_name]
-
-        types.append(module.TYPES)
-        macros.append(module.MACROS)
-        functions.append(module.FUNCTIONS)
-        includes.append(module.INCLUDES)
-        customizations.append(module.CUSTOMIZATIONS)
-
-    # We include functions here so that if we got any of their definitions
-    # wrong, the underlying C compiler will explode. In C you are allowed
-    # to re-declare a function if it has the same signature. That is:
-    #   int foo(int);
-    #   int foo(int);
-    # is legal, but the following will fail to compile:
-    #   int foo(int);
-    #   int foo(short);
-    verify_source = "\n".join(
-        [pre_include] +
-        includes +
-        [post_include] +
-        functions +
-        customizations
-    )
-    ffi = build_ffi(
-        cdef_source="\n".join(types + functions + macros),
-        verify_source=verify_source,
-        libraries=libraries,
-        extra_compile_args=extra_compile_args,
-        extra_link_args=extra_link_args,
-    )
-
-    return ffi
-
-
-def build_ffi(cdef_source, verify_source, libraries=[], extra_compile_args=[],
-              extra_link_args=[]):
-    ffi = FFI()
-    ffi.cdef(cdef_source)
-
-    ffi.verifier = Verifier(
-        ffi,
-        verify_source,
-        tmpdir='',
-        modulename=_create_modulename(cdef_source, verify_source, sys.version),
-        libraries=libraries,
-        ext_package="cryptography",
-        extra_compile_args=extra_compile_args,
-        extra_link_args=extra_link_args,
-    )
-
-    ffi.verifier.compile_module = _compile_module
-    ffi.verifier._compile_module = _compile_module
-
-    return ffi
-
-
-def _compile_module(*args, **kwargs):
-    raise RuntimeError(
-        "Attempted implicit compile of a cffi module. All cffi modules should "
-        "be pre-compiled at installation time."
-    )
-
-
-def _create_modulename(cdef_sources, source, sys_version):
-    """
-    cffi creates a modulename internally that incorporates the cffi version.
-    This will cause cryptography's wheels to break when the version of cffi
-    the user has does not match what was used when building the wheel. To
-    resolve this we build our own modulename that uses most of the same code
-    from cffi but elides the version key.
-    """
-    key = '\x00'.join([sys_version[:3], source, cdef_sources])
-    key = key.encode('utf-8')
-    k1 = hex(binascii.crc32(key[0::2]) & 0xffffffff)
-    k1 = k1.lstrip('0x').rstrip('L')
-    k2 = hex(binascii.crc32(key[1::2]) & 0xffffffff)
-    k2 = k2.lstrip('0').rstrip('L')
-    return '_Cryptography_cffi_{0}{1}'.format(k1, k2)
diff --git a/src/cryptography/hazmat/primitives/constant_time.py b/src/cryptography/hazmat/primitives/constant_time.py
index bf85bde..5a682ca 100644
--- a/src/cryptography/hazmat/primitives/constant_time.py
+++ b/src/cryptography/hazmat/primitives/constant_time.py
@@ -5,20 +5,8 @@
 from __future__ import absolute_import, division, print_function
 
 import hmac
-import os
 
-from cryptography.hazmat.bindings.utils import LazyLibrary, build_ffi
-
-
-with open(os.path.join(os.path.dirname(__file__), "src/constant_time.h")) as f:
-    TYPES = f.read()
-
-with open(os.path.join(os.path.dirname(__file__), "src/constant_time.c")) as f:
-    FUNCTIONS = f.read()
-
-
-_ffi = build_ffi(cdef_source=TYPES, verify_source=FUNCTIONS)
-_lib = LazyLibrary(_ffi)
+from cryptography.hazmat.bindings._constant_time import lib
 
 
 if hasattr(hmac, "compare_digest"):
@@ -33,6 +21,6 @@
         if not isinstance(a, bytes) or not isinstance(b, bytes):
             raise TypeError("a and b must be bytes.")
 
-        return _lib.Cryptography_constant_time_bytes_eq(
+        return lib.Cryptography_constant_time_bytes_eq(
             a, len(a), b, len(b)
         ) == 1
diff --git a/src/cryptography/hazmat/primitives/padding.py b/src/cryptography/hazmat/primitives/padding.py
index 6247f7b..f6491eb 100644
--- a/src/cryptography/hazmat/primitives/padding.py
+++ b/src/cryptography/hazmat/primitives/padding.py
@@ -6,24 +6,11 @@
 
 import abc
 
-import os
-
 import six
 
 from cryptography import utils
 from cryptography.exceptions import AlreadyFinalized
-from cryptography.hazmat.bindings.utils import LazyLibrary, build_ffi
-
-
-with open(os.path.join(os.path.dirname(__file__), "src/padding.h")) as f:
-    TYPES = f.read()
-
-with open(os.path.join(os.path.dirname(__file__), "src/padding.c")) as f:
-    FUNCTIONS = f.read()
-
-
-_ffi = build_ffi(cdef_source=TYPES, verify_source=FUNCTIONS)
-_lib = LazyLibrary(_ffi)
+from cryptography.hazmat.bindings._padding import lib
 
 
 @six.add_metaclass(abc.ABCMeta)
@@ -124,7 +111,7 @@
         if len(self._buffer) != self.block_size // 8:
             raise ValueError("Invalid padding bytes.")
 
-        valid = _lib.Cryptography_check_pkcs7_padding(
+        valid = lib.Cryptography_check_pkcs7_padding(
             self._buffer, self.block_size // 8
         )
 
diff --git a/tests/hazmat/backends/test_openssl.py b/tests/hazmat/backends/test_openssl.py
index 867c5dd..b35e767 100644
--- a/tests/hazmat/backends/test_openssl.py
+++ b/tests/hazmat/backends/test_openssl.py
@@ -482,14 +482,18 @@
             )
 
 
+class DummyLibrary(object):
+    Cryptography_HAS_EC = 0
+
+
 class TestOpenSSLEllipticCurve(object):
     def test_elliptic_curve_supported(self, monkeypatch):
-        monkeypatch.setattr(backend._lib, "Cryptography_HAS_EC", 0)
+        monkeypatch.setattr(backend, "_lib", DummyLibrary())
 
         assert backend.elliptic_curve_supported(None) is False
 
     def test_elliptic_curve_signature_algorithm_supported(self, monkeypatch):
-        monkeypatch.setattr(backend._lib, "Cryptography_HAS_EC", 0)
+        monkeypatch.setattr(backend, "_lib", DummyLibrary())
 
         assert backend.elliptic_curve_signature_algorithm_supported(
             None, None
diff --git a/tests/hazmat/bindings/test_commoncrypto.py b/tests/hazmat/bindings/test_commoncrypto.py
index a86a1fa..b0a2dc4 100644
--- a/tests/hazmat/bindings/test_commoncrypto.py
+++ b/tests/hazmat/bindings/test_commoncrypto.py
@@ -6,22 +6,21 @@
 
 import pytest
 
-from cryptography.hazmat.backends import _available_backends
-from cryptography.hazmat.bindings.commoncrypto.binding import Binding
+
+ccbinding = pytest.importorskip(
+    "cryptography.hazmat.bindings.commoncrypto.binding"
+)
 
 
-@pytest.mark.skipif("commoncrypto" not in
-                    [i.name for i in _available_backends()],
-                    reason="CommonCrypto not available")
 class TestCommonCrypto(object):
     def test_binding_loads(self):
-        binding = Binding()
+        binding = ccbinding.Binding()
         assert binding
         assert binding.lib
         assert binding.ffi
 
     def test_binding_returns_same_lib(self):
-        binding = Binding()
-        binding2 = Binding()
+        binding = ccbinding.Binding()
+        binding2 = ccbinding.Binding()
         assert binding.lib == binding2.lib
         assert binding.ffi == binding2.ffi
diff --git a/tests/hazmat/bindings/test_openssl.py b/tests/hazmat/bindings/test_openssl.py
index 8cc81cd..e6d6fc4 100644
--- a/tests/hazmat/bindings/test_openssl.py
+++ b/tests/hazmat/bindings/test_openssl.py
@@ -6,9 +6,7 @@
 
 import pytest
 
-from cryptography.hazmat.bindings.openssl.binding import (
-    Binding, _get_libraries, _get_windows_libraries
-)
+from cryptography.hazmat.bindings.openssl.binding import Binding
 
 
 class TestOpenSSL(object):
@@ -133,18 +131,3 @@
         expected_options = current_options | b.lib.SSL_OP_ALL
         assert resp == expected_options
         assert b.lib.SSL_get_mode(ssl) == expected_options
-
-    def test_libraries(self, monkeypatch):
-        assert _get_libraries("darwin") == ["ssl", "crypto"]
-        monkeypatch.setenv('PYCA_WINDOWS_LINK_TYPE', 'static')
-        assert "ssleay32mt" in _get_libraries("win32")
-
-    def test_windows_static_dynamic_libraries(self):
-        assert "ssleay32mt" in _get_windows_libraries("static")
-
-        assert "ssleay32mt" in _get_windows_libraries("")
-
-        assert "ssleay32" in _get_windows_libraries("dynamic")
-
-        with pytest.raises(ValueError):
-            _get_windows_libraries("notvalid")
diff --git a/tests/hazmat/bindings/test_utils.py b/tests/hazmat/bindings/test_utils.py
deleted file mode 100644
index 13d5d1c..0000000
--- a/tests/hazmat/bindings/test_utils.py
+++ /dev/null
@@ -1,30 +0,0 @@
-# This file is dual licensed under the terms of the Apache License, Version
-# 2.0, and the BSD License. See the LICENSE file in the root of this repository
-# for complete details.
-
-from __future__ import absolute_import, division, print_function
-
-import binascii
-import os
-
-import pytest
-
-from cryptography.hazmat.bindings import utils
-
-
-def test_create_modulename():
-    cdef_source = "cdef sources go here"
-    source = "source code"
-    name = utils._create_modulename(cdef_source, source, "2.7")
-    assert name == "_Cryptography_cffi_bcba7f4bx4a14b588"
-    name = utils._create_modulename(cdef_source, source, "3.2")
-    assert name == "_Cryptography_cffi_a7462526x4a14b588"
-
-
-def test_implicit_compile_explodes():
-    # This uses a random comment to make sure each test gets its own hash
-    random_comment = binascii.hexlify(os.urandom(24))
-    ffi = utils.build_ffi("/* %s */" % random_comment, "")
-
-    with pytest.raises(RuntimeError):
-        ffi.verifier.load_library()