summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJean-Paul Calderone <exarkun@twistedmatrix.com>2012-04-03 15:25:07 -0400
committerJean-Paul Calderone <exarkun@twistedmatrix.com>2012-04-03 15:25:07 -0400
commitffe420a7cd03197b0c3012dab2a1a90a71d26eb0 (patch)
treeef53cd05f3fa8b045e891ddb99e9127cbd82fc68
parent0beed1c968ea4511cbe8515effed7acd2a715b48 (diff)
parent5f2cd26054adff5a1fbf9ba5d56766b972f46670 (diff)
downloadpyopenssl-ffe420a7cd03197b0c3012dab2a1a90a71d26eb0.tar.gz
Release the GIL around RSA and DSA key generation.
-rw-r--r--ChangeLog5
-rw-r--r--OpenSSL/crypto/pkey.c21
-rw-r--r--leakcheck/thread-key-gen.py38
3 files changed, 59 insertions, 5 deletions
diff --git a/ChangeLog b/ChangeLog
index 27c7556..4e67443 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,8 @@
+2012-04-03 Jean-Paul Calderone <exarkun@twistedmatrix.com>
+
+ * OpenSSL/crypto/pkey.c: Release the GIL around RSA and DSA key
+ generation, based on code from INADA Naoki.
+
2012-02-13 Jean-Paul Calderone <exarkun@twistedmatrix.com>
* OpenSSL/ssl/ssl.c: Add session cache related constants for use
diff --git a/OpenSSL/crypto/pkey.c b/OpenSSL/crypto/pkey.c
index b9472ec..f23ec70 100644
--- a/OpenSSL/crypto/pkey.c
+++ b/OpenSSL/crypto/pkey.c
@@ -52,19 +52,30 @@ crypto_PKey_generate_key(crypto_PKeyObj *self, PyObject *args)
PyErr_SetString(PyExc_ValueError, "Invalid number of bits");
return NULL;
}
- if ((rsa = RSA_generate_key(bits, 0x10001, NULL, NULL)) == NULL)
+ Py_BEGIN_ALLOW_THREADS;
+ rsa = RSA_generate_key(bits, 0x10001, NULL, NULL);
+ Py_END_ALLOW_THREADS;
+ if (rsa == NULL) {
FAIL();
- if (!EVP_PKEY_assign_RSA(self->pkey, rsa))
+ }
+ if (!EVP_PKEY_assign_RSA(self->pkey, rsa)) {
FAIL();
+ }
break;
case crypto_TYPE_DSA:
- if ((dsa = DSA_generate_parameters(bits, NULL, 0, NULL, NULL, NULL, NULL)) == NULL)
+ Py_BEGIN_ALLOW_THREADS;
+ dsa = DSA_generate_parameters(bits, NULL, 0, NULL, NULL, NULL, NULL);
+ Py_END_ALLOW_THREADS;
+ if (dsa == NULL) {
FAIL();
- if (!DSA_generate_key(dsa))
+ }
+ if (!DSA_generate_key(dsa)) {
FAIL();
- if (!EVP_PKEY_assign_DSA(self->pkey, dsa))
+ }
+ if (!EVP_PKEY_assign_DSA(self->pkey, dsa)) {
FAIL();
+ }
break;
default:
diff --git a/leakcheck/thread-key-gen.py b/leakcheck/thread-key-gen.py
new file mode 100644
index 0000000..62e1a58
--- /dev/null
+++ b/leakcheck/thread-key-gen.py
@@ -0,0 +1,38 @@
+# Copyright (C) Jean-Paul Calderone
+# See LICENSE for details.
+#
+# Stress tester for thread-related bugs in RSA and DSA key generation. 0.12 and
+# older held the GIL during these operations. Subsequent versions release it
+# during them.
+
+from threading import Thread
+
+from OpenSSL.crypto import TYPE_RSA, TYPE_DSA, PKey
+
+def generate_rsa():
+ keys = []
+ for i in range(100):
+ key = PKey()
+ key.generate_key(TYPE_RSA, 1024)
+ keys.append(key)
+
+def generate_dsa():
+ keys = []
+ for i in range(100):
+ key = PKey()
+ key.generate_key(TYPE_DSA, 512)
+ keys.append(key)
+
+
+def main():
+ threads = []
+ for i in range(3):
+ t = Thread(target=generate_rsa, args=())
+ threads.append(t)
+ t = Thread(target=generate_dsa, args=())
+ threads.append(t)
+
+ for t in threads:
+ t.start()
+
+main()