aboutsummaryrefslogtreecommitdiffstats
path: root/cryptography/hazmat/bindings/openssl/backend.py
diff options
context:
space:
mode:
Diffstat (limited to 'cryptography/hazmat/bindings/openssl/backend.py')
-rw-r--r--cryptography/hazmat/bindings/openssl/backend.py71
1 files changed, 47 insertions, 24 deletions
diff --git a/cryptography/hazmat/bindings/openssl/backend.py b/cryptography/hazmat/bindings/openssl/backend.py
index fc73dd39..0c3d22d5 100644
--- a/cryptography/hazmat/bindings/openssl/backend.py
+++ b/cryptography/hazmat/bindings/openssl/backend.py
@@ -18,11 +18,14 @@ import sys
import cffi
+from cryptography.exceptions import UnsupportedAlgorithm
from cryptography.hazmat.primitives import interfaces
-from cryptography.hazmat.primitives.block.ciphers import (
+from cryptography.hazmat.primitives.ciphers.algorithms import (
AES, Blowfish, Camellia, CAST5, TripleDES,
)
-from cryptography.hazmat.primitives.block.modes import CBC, CTR, ECB, OFB, CFB
+from cryptography.hazmat.primitives.ciphers.modes import (
+ CBC, CTR, ECB, OFB, CFB
+)
class Backend(object):
@@ -54,29 +57,45 @@ class Backend(object):
"x509v3",
]
+ ffi = None
+ lib = None
+
def __init__(self):
- self.ffi = cffi.FFI()
+ self._ensure_ffi_initialized()
+
+ self.ciphers = Ciphers(self)
+ self.hashes = Hashes(self)
+ self.hmacs = HMACs(self)
+
+ @classmethod
+ def _ensure_ffi_initialized(cls):
+ if cls.ffi is not None and cls.lib is not None:
+ return
+
+ ffi = cffi.FFI()
includes = []
functions = []
macros = []
- for name in self._modules:
+ customizations = []
+ for name in cls._modules:
module_name = "cryptography.hazmat.bindings.openssl." + name
__import__(module_name)
module = sys.modules[module_name]
- self.ffi.cdef(module.TYPES)
+ ffi.cdef(module.TYPES)
macros.append(module.MACROS)
functions.append(module.FUNCTIONS)
includes.append(module.INCLUDES)
+ customizations.append(module.CUSTOMIZATIONS)
# loop over the functions & macros after declaring all the types
# so we can set interdependent types in different files and still
# have them all defined before we parse the funcs & macros
for func in functions:
- self.ffi.cdef(func)
+ ffi.cdef(func)
for macro in macros:
- self.ffi.cdef(macro)
+ ffi.cdef(macro)
# We include functions here so that if we got any of their definitions
# wrong, the underlying C compiler will explode. In C you are allowed
@@ -86,17 +105,15 @@ class Backend(object):
# is legal, but the following will fail to compile:
# int foo(int);
# int foo(short);
- self.lib = self.ffi.verify(
- source="\n".join(includes + functions),
+ lib = ffi.verify(
+ source="\n".join(includes + functions + customizations),
libraries=["crypto", "ssl"],
)
- self.lib.OpenSSL_add_all_algorithms()
- self.lib.SSL_load_error_strings()
-
- self.ciphers = Ciphers(self)
- self.hashes = Hashes(self)
- self.hmacs = HMACs(self)
+ cls.ffi = ffi
+ cls.lib = lib
+ cls.lib.OpenSSL_add_all_algorithms()
+ cls.lib.SSL_load_error_strings()
def openssl_version_text(self):
"""
@@ -128,10 +145,15 @@ class _CipherContext(object):
ctx = self._backend.ffi.gc(ctx, self._backend.lib.EVP_CIPHER_CTX_free)
registry = self._backend.ciphers._cipher_registry
- evp_cipher = registry[type(cipher), type(mode)](
- self._backend, cipher, mode
- )
- assert evp_cipher != self._backend.ffi.NULL
+ try:
+ adapter = registry[type(cipher), type(mode)]
+ except KeyError:
+ raise UnsupportedAlgorithm
+
+ evp_cipher = adapter(self._backend, cipher, mode)
+ if evp_cipher == self._backend.ffi.NULL:
+ raise UnsupportedAlgorithm
+
if isinstance(mode, interfaces.ModeWithInitializationVector):
iv_nonce = mode.initialization_vector
elif isinstance(mode, interfaces.ModeWithNonce):
@@ -297,19 +319,20 @@ class HMACs(object):
evp_md = self._backend.lib.EVP_get_digestbyname(
hash_cls.name.encode('ascii'))
assert evp_md != self._backend.ffi.NULL
- res = self._backend.lib.HMAC_Init_ex(ctx, key, len(key), evp_md,
- self._backend.ffi.NULL)
+ res = self._backend.lib.Cryptography_HMAC_Init_ex(
+ ctx, key, len(key), evp_md, self._backend.ffi.NULL
+ )
assert res != 0
return ctx
def update_ctx(self, ctx, data):
- res = self._backend.lib.HMAC_Update(ctx, data, len(data))
+ res = self._backend.lib.Cryptography_HMAC_Update(ctx, data, len(data))
assert res != 0
def finalize_ctx(self, ctx, digest_size):
buf = self._backend.ffi.new("unsigned char[]", digest_size)
buflen = self._backend.ffi.new("unsigned int *", digest_size)
- res = self._backend.lib.HMAC_Final(ctx, buf, buflen)
+ res = self._backend.lib.Cryptography_HMAC_Final(ctx, buf, buflen)
assert res != 0
self._backend.lib.HMAC_CTX_cleanup(ctx)
return self._backend.ffi.buffer(buf)[:digest_size]
@@ -319,7 +342,7 @@ class HMACs(object):
self._backend.lib.HMAC_CTX_init(copied_ctx)
copied_ctx = self._backend.ffi.gc(copied_ctx,
self._backend.lib.HMAC_CTX_cleanup)
- res = self._backend.lib.HMAC_CTX_copy(copied_ctx, ctx)
+ res = self._backend.lib.Cryptography_HMAC_CTX_copy(copied_ctx, ctx)
assert res != 0
return copied_ctx