aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPaul Kehrer <paul.l.kehrer@gmail.com>2013-12-29 19:51:17 -0600
committerPaul Kehrer <paul.l.kehrer@gmail.com>2013-12-30 11:17:09 -0600
commit026168cc80c964b237ebd65a20c05679acd48332 (patch)
treee4b0bd76ee6037f11c08cb4b1f7e721b0f2a5297
parentfbd7ffcdcda0269a654ebf373d4ec5f1e6d6d3f4 (diff)
downloadcryptography-026168cc80c964b237ebd65a20c05679acd48332.tar.gz
cryptography-026168cc80c964b237ebd65a20c05679acd48332.tar.bz2
cryptography-026168cc80c964b237ebd65a20c05679acd48332.zip
add urandom engine and set it as default RAND method.
This is a proposed solution to the OpenSSL fork problem.
-rw-r--r--cryptography/hazmat/backends/openssl/backend.py10
-rw-r--r--cryptography/hazmat/backends/openssl/urand_engine.py155
2 files changed, 165 insertions, 0 deletions
diff --git a/cryptography/hazmat/backends/openssl/backend.py b/cryptography/hazmat/backends/openssl/backend.py
index 6231aadb..d6a77640 100644
--- a/cryptography/hazmat/backends/openssl/backend.py
+++ b/cryptography/hazmat/backends/openssl/backend.py
@@ -93,6 +93,7 @@ class Backend(object):
"rand",
"rsa",
"ssl",
+ "urand_engine",
"x509",
"x509name",
"x509v3",
@@ -170,6 +171,15 @@ class Backend(object):
cls.lib.OpenSSL_add_all_algorithms()
cls.lib.SSL_load_error_strings()
+ res = cls.lib.Cryptography_add_urandom_engine()
+ assert res == 1
+ e = cls.lib.ENGINE_by_id("urandom")
+ assert e != cls.ffi.NULL
+ res = cls.lib.ENGINE_init(e)
+ assert res == 1
+ res = cls.lib.ENGINE_set_default_RAND(e)
+ assert res == 1
+
def openssl_version_text(self):
"""
Friendly string name of linked OpenSSL.
diff --git a/cryptography/hazmat/backends/openssl/urand_engine.py b/cryptography/hazmat/backends/openssl/urand_engine.py
new file mode 100644
index 00000000..479bbb2c
--- /dev/null
+++ b/cryptography/hazmat/backends/openssl/urand_engine.py
@@ -0,0 +1,155 @@
+# 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 = """
+"""
+
+FUNCTIONS = """
+int Cryptography_add_urandom_engine(void);
+"""
+
+MACROS = """
+"""
+
+CUSTOMIZATIONS = """
+static const char *urandom_engine_id= "urandom";
+static const char *urandom_engine_name = "urandom engine";
+
+#ifndef _WIN32
+static int urandom_fd;
+
+static int urandom_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;
+ break;
+ }
+ buffer += n;
+ size -= n;
+ }
+ return 1;
+}
+
+static int urandom_rand_status(void) {
+ return 1;
+}
+
+static int urandom_init(ENGINE *e) {
+ urandom_fd = open("/dev/urandom", O_RDONLY);
+ if (urandom_fd > 0) {
+ return 1;
+ } else {
+ printf("crap");
+ return 0;
+ }
+}
+
+static int urandom_finish(ENGINE *e) {
+ int n;
+ do {
+ n = close(urandom_fd);
+ } while (n < 0 && errno == EINTR);
+ if (n < 0) {
+ return 0;
+ } else {
+ return 1;
+ }
+}
+#endif
+
+#ifdef _WIN32
+/* This handle is never explicitly released. Instead, the operating
+ system will release it when the process terminates. */
+static HCRYPTPROV hCryptProv = 0;
+
+static int urandom_init(ENGINE *e) {
+ /* Acquire context */
+ if (CryptAcquireContext(&hCryptProv, NULL, NULL,
+ PROV_RSA_FULL, CRYPT_VERIFYCONTEXT)) {
+ return 1;
+ } else {
+ return 0;
+ }
+}
+
+static int urandom_rand_bytes(unsigned char *buffer, int size) {
+ size_t chunk;
+
+ if (hCryptProv == 0) {
+ return 0;
+ }
+
+ while (size > 0) {
+ chunk = size > INT_MAX ? INT_MAX : size;
+ if (!CryptGenRandom(hCryptProv, (DWORD)chunk, buffer)) {
+ return 0;
+ }
+ buffer += chunk;
+ size -= chunk;
+ }
+ return 1;
+}
+
+static int urandom_finish(ENGINE *e) {
+ return 1;
+}
+
+static int urandom_rand_status(void) {
+ return 1;
+}
+#endif /* MS_WINDOWS */
+
+static RAND_METHOD urandom_rand = {
+ NULL,
+ urandom_rand_bytes,
+ NULL,
+ NULL,
+ urandom_rand_bytes,
+ urandom_rand_status,
+};
+
+int Cryptography_add_urandom_engine(void) {
+ ENGINE *e = ENGINE_new();
+ if(!ENGINE_set_id(e, urandom_engine_id) ||
+ !ENGINE_set_name(e, urandom_engine_name) ||
+ !ENGINE_set_RAND(e, &urandom_rand) ||
+ !ENGINE_set_init_function(e, urandom_init) ||
+ !ENGINE_set_finish_function(e, urandom_finish)) {
+ return 0;
+ }
+ if (!ENGINE_add(e)) {
+ ENGINE_free(e);
+ return 0;
+ }
+ if (!ENGINE_free(e)) {
+ return 0;
+ }
+
+ return 1;
+}
+"""
+
+CONDITIONAL_NAMES = {}