Merge pull request #1774 from chelseawinfree/im_confident

Moved OpenSSL engine into standalone c and h files
diff --git a/MANIFEST.in b/MANIFEST.in
index b7e6559..8dbd0dc 100644
--- a/MANIFEST.in
+++ b/MANIFEST.in
@@ -8,6 +8,7 @@
 
 recursive-include docs *
 recursive-include src/cryptography/hazmat/primitives/src *.c *.h
+recursive-include src/cryptography/hazmat/bindings/openssl/src *.c *.h
 prune docs/_build
 recursive-include tests *.py
 recursive-exclude vectors *
diff --git a/src/cryptography/hazmat/bindings/openssl/osrandom_engine.py b/src/cryptography/hazmat/bindings/openssl/osrandom_engine.py
index 1b6c88a..a8479b0 100644
--- a/src/cryptography/hazmat/bindings/openssl/osrandom_engine.py
+++ b/src/cryptography/hazmat/bindings/openssl/osrandom_engine.py
@@ -4,14 +4,12 @@
 
 from __future__ import absolute_import, division, print_function
 
-INCLUDES = """
-#ifdef _WIN32
-#include <Wincrypt.h>
-#else
-#include <fcntl.h>
-#include <unistd.h>
-#endif
-"""
+import os
+
+with open(os.path.join(
+    os.path.dirname(__file__), "src/osrandom_engine.h"
+)) as f:
+    INCLUDES = f.read()
 
 TYPES = """
 static const char *const Cryptography_osrandom_engine_name;
@@ -25,185 +23,9 @@
 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_engine.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) {
-        int flags = fcntl(urandom_fd, F_GETFD);
-        if (flags == -1) {
-            osrandom_finish(e);
-            return 0;
-        } else if (fcntl(urandom_fd, F_SETFD, flags | 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_engine.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)s
-#else
-%(POSIX_CUSTOMIZATIONS)s
-#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,
-};
-
-/* Returns 1 if successfully added, 2 if engine has previously been added,
-   and 0 for error. */
-int Cryptography_add_osrandom_engine(void) {
-    ENGINE *e;
-    e = ENGINE_by_id(Cryptography_osrandom_engine_id);
-    if (e != NULL) {
-        ENGINE_free(e);
-        return 2;
-    } else {
-        ERR_clear_error();
-    }
-
-    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;
-}
-""" % {
-    "WIN32_CUSTOMIZATIONS": WIN32_CUSTOMIZATIONS,
-    "POSIX_CUSTOMIZATIONS": POSIX_CUSTOMIZATIONS,
-}
+with open(os.path.join(
+    os.path.dirname(__file__), "src/osrandom_engine.c"
+)) as f:
+    CUSTOMIZATIONS = f.read()
 
 CONDITIONAL_NAMES = {}
diff --git a/src/cryptography/hazmat/bindings/openssl/src/osrandom_engine.c b/src/cryptography/hazmat/bindings/openssl/src/osrandom_engine.c
new file mode 100644
index 0000000..2789471
--- /dev/null
+++ b/src/cryptography/hazmat/bindings/openssl/src/osrandom_engine.c
@@ -0,0 +1,167 @@
+static const char *Cryptography_osrandom_engine_id = "osrandom";
+static const char *Cryptography_osrandom_engine_name = "osrandom_engine";
+
+#if defined(_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) {
+    if (hCryptProv == 0) {
+        return 0;
+    }
+
+    if (!CryptGenRandom(hCryptProv, (DWORD)size, buffer)) {
+        ERR_put_error(
+            ERR_LIB_RAND, 0, ERR_R_RAND_LIB, "osrandom_engine.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;
+    }
+}
+#else
+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) {
+        int flags = fcntl(urandom_fd, F_GETFD);
+        if (flags == -1) {
+            osrandom_finish(e);
+            return 0;
+        } else if (fcntl(urandom_fd, F_SETFD, flags | 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_engine.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;
+    }
+}
+#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,
+};
+
+/* Returns 1 if successfully added, 2 if engine has previously been added,
+   and 0 for error. */
+int Cryptography_add_osrandom_engine(void) {
+    ENGINE *e;
+    e = ENGINE_by_id(Cryptography_osrandom_engine_id);
+    if (e != NULL) {
+        ENGINE_free(e);
+        return 2;
+    } else {
+        ERR_clear_error();
+    }
+
+    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;
+}
diff --git a/src/cryptography/hazmat/bindings/openssl/src/osrandom_engine.h b/src/cryptography/hazmat/bindings/openssl/src/osrandom_engine.h
new file mode 100644
index 0000000..11a3159
--- /dev/null
+++ b/src/cryptography/hazmat/bindings/openssl/src/osrandom_engine.h
@@ -0,0 +1,6 @@
+#ifdef _WIN32
+#include <Wincrypt.h>
+#else
+#include <fcntl.h>
+#include <unistd.h>
+#endif