aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorAlex Gaynor <alex.gaynor@gmail.com>2016-01-08 07:35:43 -0500
committerAlex Gaynor <alex.gaynor@gmail.com>2016-01-08 07:35:43 -0500
commitcaf9cf64b4beeee00491c125a2d067026355196b (patch)
tree1b79f73cb68f8928496afa4d8a525dcaaa3551c5 /src
parentb3913acb3612e5c941924b15d3de47a2280d4011 (diff)
parent90ad38fae043268e3bfe2844f1996707bfd0caf8 (diff)
downloadcryptography-caf9cf64b4beeee00491c125a2d067026355196b.tar.gz
cryptography-caf9cf64b4beeee00491c125a2d067026355196b.tar.bz2
cryptography-caf9cf64b4beeee00491c125a2d067026355196b.zip
Merge pull request #2646 from reaperhulk/static-callbacks
Static callbacks
Diffstat (limited to 'src')
-rw-r--r--src/_cffi_src/build_openssl.py1
-rw-r--r--src/_cffi_src/openssl/callbacks.py50
-rw-r--r--src/cryptography/hazmat/backends/openssl/backend.py22
-rw-r--r--src/cryptography/hazmat/bindings/openssl/binding.py34
4 files changed, 94 insertions, 13 deletions
diff --git a/src/_cffi_src/build_openssl.py b/src/_cffi_src/build_openssl.py
index c47b3082..ebbe8865 100644
--- a/src/_cffi_src/build_openssl.py
+++ b/src/_cffi_src/build_openssl.py
@@ -90,6 +90,7 @@ ffi = build_ffi_for_binding(
"x509v3",
"x509_vfy",
"pkcs7",
+ "callbacks",
],
pre_include=_OSX_PRE_INCLUDE,
post_include=_OSX_POST_INCLUDE,
diff --git a/src/_cffi_src/openssl/callbacks.py b/src/_cffi_src/openssl/callbacks.py
new file mode 100644
index 00000000..3e4ef572
--- /dev/null
+++ b/src/_cffi_src/openssl/callbacks.py
@@ -0,0 +1,50 @@
+# 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 cffi
+
+INCLUDES = """
+#include <openssl/ssl.h>
+#include <openssl/x509.h>
+#include <openssl/x509_vfy.h>
+"""
+
+TYPES = """
+static const long Cryptography_STATIC_CALLBACKS;
+
+/* crypto.h
+ * CRYPTO_set_locking_callback
+ * void (*cb)(int mode, int type, const char *file, int line)
+ */
+extern "Python" void Cryptography_locking_cb(int, int, const char *, int);
+
+/* pem.h
+ * int pem_password_cb(char *buf, int size, int rwflag, void *userdata);
+ */
+extern "Python" int Cryptography_pem_password_cb(char *, int, int, void *);
+
+/* rand.h
+ * int (*bytes)(unsigned char *buf, int num);
+ * int (*status)(void);
+ */
+extern "Python" int Cryptography_rand_bytes(unsigned char *, int);
+extern "Python" int Cryptography_rand_status(void);
+"""
+
+FUNCTIONS = """
+"""
+
+MACROS = """
+"""
+
+CUSTOMIZATIONS = """
+static const long Cryptography_STATIC_CALLBACKS = 1;
+"""
+
+if cffi.__version_info__ < (1, 4, 0):
+ # backwards compatibility for old cffi version on PyPy
+ TYPES = "static const long Cryptography_STATIC_CALLBACKS;"
+ CUSTOMIZATIONS = "static const long Cryptography_STATIC_CALLBACKS = 0;"
diff --git a/src/cryptography/hazmat/backends/openssl/backend.py b/src/cryptography/hazmat/backends/openssl/backend.py
index c3e1db66..c21d5427 100644
--- a/src/cryptography/hazmat/backends/openssl/backend.py
+++ b/src/cryptography/hazmat/backends/openssl/backend.py
@@ -648,7 +648,21 @@ class _PasswordUserdata(object):
self.exception = None
+@binding.ffi_callback("int (char *, int, int, void *)",
+ name="Cryptography_pem_password_cb")
def _pem_password_cb(buf, size, writing, userdata_handle):
+ """
+ A pem_password_cb function pointer that copied the password to
+ OpenSSL as required and returns the number of bytes copied.
+
+ typedef int pem_password_cb(char *buf, int size,
+ int rwflag, void *userdata);
+
+ Useful for decrypting PKCS8 files and so on.
+
+ The userdata pointer must point to a cffi handle of a
+ _PasswordUserdata instance.
+ """
ud = _ffi.from_handle(userdata_handle)
ud.called += 1
@@ -1143,13 +1157,7 @@ class Backend(object):
# globally. The backend is passed in as userdata argument.
userdata = _PasswordUserdata(password=password)
-
- pem_password_cb = self._ffi.callback(
- "int (char *, int, int, void *)",
- _pem_password_cb,
- )
-
- return pem_password_cb, userdata
+ return _pem_password_cb, userdata
def _mgf1_hash_supported(self, algorithm):
if self._lib.Cryptography_HAS_MGF1_MD:
diff --git a/src/cryptography/hazmat/bindings/openssl/binding.py b/src/cryptography/hazmat/bindings/openssl/binding.py
index 8e419439..1cfe8162 100644
--- a/src/cryptography/hazmat/bindings/openssl/binding.py
+++ b/src/cryptography/hazmat/bindings/openssl/binding.py
@@ -14,7 +14,6 @@ from cryptography.exceptions import InternalError
from cryptography.hazmat.bindings._openssl import ffi, lib
from cryptography.hazmat.bindings.openssl._conditional import CONDITIONAL_NAMES
-
_OpenSSLError = collections.namedtuple("_OpenSSLError",
["code", "lib", "func", "reason"])
@@ -45,7 +44,28 @@ def _openssl_assert(lib, ok):
)
-@ffi.callback("int (*)(unsigned char *, int)", error=-1)
+def ffi_callback(signature, name, **kwargs):
+ """Callback dispatcher
+
+ The ffi_callback() dispatcher keeps callbacks compatible between dynamic
+ and static callbacks.
+ """
+ def wrapper(func):
+ if lib.Cryptography_STATIC_CALLBACKS:
+ # def_extern() returns a decorator that sets the internal
+ # function pointer and returns the original function unmodified.
+ ffi.def_extern(name=name, **kwargs)(func)
+ callback = getattr(lib, name)
+ else:
+ # callback() wraps the function in a cdata function.
+ callback = ffi.callback(signature, **kwargs)(func)
+ return callback
+ return wrapper
+
+
+@ffi_callback("int (*)(unsigned char *, int)",
+ name="Cryptography_rand_bytes",
+ error=-1)
def _osrandom_rand_bytes(buf, size):
signed = ffi.cast("char *", buf)
result = os.urandom(size)
@@ -53,7 +73,7 @@ def _osrandom_rand_bytes(buf, size):
return 1
-@ffi.callback("int (*)(void)")
+@ffi_callback("int (*)(void)", name="Cryptography_rand_status")
def _osrandom_rand_status():
return 1
@@ -88,7 +108,8 @@ class Binding(object):
_osrandom_engine_name = ffi.new("const char[]", b"osrandom_engine")
_osrandom_method = ffi.new(
"RAND_METHOD *",
- dict(bytes=_osrandom_rand_bytes, pseudorand=_osrandom_rand_bytes,
+ dict(bytes=_osrandom_rand_bytes,
+ pseudorand=_osrandom_rand_bytes,
status=_osrandom_rand_status)
)
@@ -140,10 +161,11 @@ class Binding(object):
cls._ensure_ffi_initialized()
if not cls._lock_cb_handle:
- cls._lock_cb_handle = cls.ffi.callback(
+ wrapper = ffi_callback(
"void(int, int, const char *, int)",
- cls._lock_cb
+ name="Cryptography_locking_cb",
)
+ cls._lock_cb_handle = wrapper(cls._lock_cb)
# Use Python's implementation if available, importing _ssl triggers
# the setup for this.