Skip to content

Instantly share code, notes, and snippets.

@public
Last active January 1, 2016 10:39
Show Gist options
  • Save public/8132604 to your computer and use it in GitHub Desktop.
Save public/8132604 to your computer and use it in GitHub Desktop.
Implement the OpenSSL locking callback in Python. It seems to work but is ~4x slower on PyPy and ~8x slower in CPython than using the C implementation from Modules/_ssl.py.
import thread
import threading
import itertools
import cryptography.hazmat.backends
b = cryptography.hazmat.backends.default_backend()
# UNCOMMENT THIS TO POSSIBLY STOP CRASHES
#import _ssl
# OR
# ENABLE THIS BLOCK TO HANDLE THE LOCKING IN PYTHON
"""
You need this patch to crypto.py for this
index 8d88c16..293e361 100644
--- a/cryptography/hazmat/backends/openssl/crypto.py
+++ b/cryptography/hazmat/backends/openssl/crypto.py
@@ -24,6 +24,8 @@ int CRYPTO_mem_ctrl(int);
int CRYPTO_is_mem_check_on();
void CRYPTO_mem_leaks(struct bio_st *);
void CRYPTO_cleanup_all_ex_data();
+void CRYPTO_set_locking_callback(void (*func)(int, int, const char *, int));
+int CRYPTO_num_locks();
void OPENSSL_free(void *);
\"\"\"
"""
if 1:
import thread
_ssl_locks_count = b.lib.CRYPTO_num_locks()
_ssl_locks = [thread.allocate_lock()
for n in range(_ssl_locks_count)]
CRYPTO_LOCK = 1
def ssl_lock(mode, n, file, line):
global _ssl_locks
assert _ssl_locks
assert n >= 0
assert n < _ssl_locks_count
lock = _ssl_locks[n]
if mode & CRYPTO_LOCK:
lock.acquire(1)
else:
lock.release()
ssl_lock_cb = b.ffi.callback(
"void(int mode, int n, const char *file, int line)",
ssl_lock
)
b.lib.CRYPTO_set_locking_callback(ssl_lock_cb)
def randloop():
s = b.ffi.new("char[]", 16)
sb = b.ffi.buffer(s)
sb[:] = b"\0" * 16
for i in itertools.count():
b.lib.RAND_seed(s, 16)
if i % 10000 == 0:
print thread.get_ident(), i
if i > 300000:
break
threads = []
print "Starting..."
for x in range(3):
t = threading.Thread(target=randloop)
t.daemon = True
t.start()
threads.append(t)
print "Waiting..."
while threads:
for t in threads:
t.join(0.1)
if not t.isAlive():
threads.remove(t)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment