aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rwxr-xr-x.travis/install.sh18
-rw-r--r--cryptography/hazmat/backends/openssl/backend.py338
-rw-r--r--cryptography/hazmat/bindings/__init__.py12
-rw-r--r--cryptography/hazmat/bindings/openssl/__init__.py12
-rw-r--r--cryptography/hazmat/bindings/openssl/asn1.py (renamed from cryptography/hazmat/backends/openssl/asn1.py)0
-rw-r--r--cryptography/hazmat/bindings/openssl/bignum.py (renamed from cryptography/hazmat/backends/openssl/bignum.py)0
-rw-r--r--cryptography/hazmat/bindings/openssl/binding.py149
-rw-r--r--cryptography/hazmat/bindings/openssl/bio.py (renamed from cryptography/hazmat/backends/openssl/bio.py)0
-rw-r--r--cryptography/hazmat/bindings/openssl/conf.py (renamed from cryptography/hazmat/backends/openssl/conf.py)0
-rw-r--r--cryptography/hazmat/bindings/openssl/crypto.py (renamed from cryptography/hazmat/backends/openssl/crypto.py)5
-rw-r--r--cryptography/hazmat/bindings/openssl/dh.py (renamed from cryptography/hazmat/backends/openssl/dh.py)0
-rw-r--r--cryptography/hazmat/bindings/openssl/dsa.py (renamed from cryptography/hazmat/backends/openssl/dsa.py)0
-rw-r--r--cryptography/hazmat/bindings/openssl/engine.py (renamed from cryptography/hazmat/backends/openssl/engine.py)0
-rw-r--r--cryptography/hazmat/bindings/openssl/err.py (renamed from cryptography/hazmat/backends/openssl/err.py)0
-rw-r--r--cryptography/hazmat/bindings/openssl/evp.py (renamed from cryptography/hazmat/backends/openssl/evp.py)0
-rw-r--r--cryptography/hazmat/bindings/openssl/hmac.py (renamed from cryptography/hazmat/backends/openssl/hmac.py)0
-rw-r--r--cryptography/hazmat/bindings/openssl/nid.py (renamed from cryptography/hazmat/backends/openssl/nid.py)0
-rw-r--r--cryptography/hazmat/bindings/openssl/objects.py (renamed from cryptography/hazmat/backends/openssl/objects.py)0
-rw-r--r--cryptography/hazmat/bindings/openssl/opensslv.py (renamed from cryptography/hazmat/backends/openssl/opensslv.py)0
-rw-r--r--cryptography/hazmat/bindings/openssl/pem.py (renamed from cryptography/hazmat/backends/openssl/pem.py)0
-rw-r--r--cryptography/hazmat/bindings/openssl/pkcs12.py (renamed from cryptography/hazmat/backends/openssl/pkcs12.py)0
-rw-r--r--cryptography/hazmat/bindings/openssl/pkcs7.py (renamed from cryptography/hazmat/backends/openssl/pkcs7.py)0
-rw-r--r--cryptography/hazmat/bindings/openssl/rand.py (renamed from cryptography/hazmat/backends/openssl/rand.py)0
-rw-r--r--cryptography/hazmat/bindings/openssl/rsa.py (renamed from cryptography/hazmat/backends/openssl/rsa.py)0
-rw-r--r--cryptography/hazmat/bindings/openssl/ssl.py (renamed from cryptography/hazmat/backends/openssl/ssl.py)0
-rw-r--r--cryptography/hazmat/bindings/openssl/x509.py (renamed from cryptography/hazmat/backends/openssl/x509.py)0
-rw-r--r--cryptography/hazmat/bindings/openssl/x509name.py (renamed from cryptography/hazmat/backends/openssl/x509name.py)0
-rw-r--r--cryptography/hazmat/bindings/openssl/x509v3.py (renamed from cryptography/hazmat/backends/openssl/x509v3.py)0
-rw-r--r--cryptography/hazmat/primitives/ciphers/base.py14
-rw-r--r--cryptography/hazmat/primitives/ciphers/modes.py5
-rw-r--r--docs/architecture.rst13
-rw-r--r--docs/hazmat/backends/openssl.rst17
-rw-r--r--docs/hazmat/bindings/index.rst22
-rw-r--r--docs/hazmat/bindings/openssl.rst27
-rw-r--r--docs/index.rst6
-rw-r--r--tests/hazmat/backends/test_openssl.py17
-rw-r--r--tests/hazmat/bindings/test_openssl.py22
-rw-r--r--tests/hazmat/primitives/utils.py9
-rw-r--r--tox.ini2
39 files changed, 410 insertions, 278 deletions
diff --git a/.travis/install.sh b/.travis/install.sh
index 4aa39799..fdd71907 100755
--- a/.travis/install.sh
+++ b/.travis/install.sh
@@ -5,8 +5,24 @@ set -x
if [[ "${OPENSSL}" == "0.9.8" ]]; then
sudo add-apt-repository "deb http://archive.ubuntu.com/ubuntu/ lucid main"
- sudo apt-get -y update
+fi
+
+if [[ "${TOX_ENV}" == "pypy" ]]; then
+ sudo add-apt-repository -y ppa:pypy/ppa
+fi
+
+sudo apt-get -y update
+
+if [[ "${OPENSSL}" == "0.9.8" ]]; then
sudo apt-get install -y --force-yes libssl-dev/lucid
fi
+if [[ "${TOX_ENV}" == "pypy" ]]; then
+ sudo apt-get install -y pypy
+
+ # This is required because we need to get rid of the Travis installed PyPy
+ # or it'll take precedence over the PPA installed one.
+ sudo rm -rf /usr/local/pypy/bin
+fi
+
pip install tox coveralls
diff --git a/cryptography/hazmat/backends/openssl/backend.py b/cryptography/hazmat/backends/openssl/backend.py
index 6231aadb..49066466 100644
--- a/cryptography/hazmat/backends/openssl/backend.py
+++ b/cryptography/hazmat/backends/openssl/backend.py
@@ -14,9 +14,6 @@
from __future__ import absolute_import, division, print_function
import itertools
-import sys
-
-import cffi
from cryptography import utils
from cryptography.exceptions import UnsupportedAlgorithm, InvalidTag
@@ -30,24 +27,7 @@ from cryptography.hazmat.primitives.ciphers.algorithms import (
from cryptography.hazmat.primitives.ciphers.modes import (
CBC, CTR, ECB, OFB, CFB, GCM,
)
-
-_OSX_PRE_INCLUDE = """
-#ifdef __APPLE__
-#include <AvailabilityMacros.h>
-#define __ORIG_DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER \
- DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER
-#undef DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER
-#define DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER
-#endif
-"""
-
-_OSX_POST_INCLUDE = """
-#ifdef __APPLE__
-#undef DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER
-#define DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER \
- __ORIG_DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER
-#endif
-"""
+from cryptography.hazmat.bindings.openssl.binding import Binding
@utils.register_interface(CipherBackend)
@@ -55,135 +35,34 @@ _OSX_POST_INCLUDE = """
@utils.register_interface(HMACBackend)
class Backend(object):
"""
- OpenSSL API wrapper.
-
- Modules listed in the ``_modules`` listed should have the following
- attributes:
-
- * ``INCLUDES``: A string containg C includes.
- * ``TYPES``: A string containing C declarations for types.
- * ``FUNCTIONS``: A string containing C declarations for functions.
- * ``MACROS``: A string containing C declarations for any macros.
- * ``CUSTOMIZATIONS``: A string containing arbitrary top-level C code, this
- can be used to do things like test for a define and provide an
- alternate implementation based on that.
- * ``CONDITIONAL_NAMES``: A dict mapping strings of condition names from the
- library to a list of names which will not be present without the
- condition.
+ OpenSSL API binding interfaces.
"""
- _module_prefix = "cryptography.hazmat.backends.openssl."
- _modules = [
- "asn1",
- "bignum",
- "bio",
- "conf",
- "crypto",
- "dh",
- "dsa",
- "engine",
- "err",
- "evp",
- "hmac",
- "nid",
- "objects",
- "opensslv",
- "pem",
- "pkcs7",
- "pkcs12",
- "rand",
- "rsa",
- "ssl",
- "x509",
- "x509name",
- "x509v3",
- ]
-
- ffi = None
- lib = None
def __init__(self):
- self._ensure_ffi_initialized()
+ self._binding = Binding()
+ self._ffi = self._binding.ffi
+ self._lib = self._binding.lib
+
+ self._lib.OpenSSL_add_all_algorithms()
+ self._lib.SSL_load_error_strings()
self._cipher_registry = {}
self._register_default_ciphers()
- @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 = []
- customizations = []
- for name in cls._modules:
- module_name = cls._module_prefix + name
- __import__(module_name)
- module = sys.modules[module_name]
-
- 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:
- ffi.cdef(func)
- for macro in macros:
- 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
- # to re-declare a function if it has the same signature. That is:
- # int foo(int);
- # int foo(int);
- # is legal, but the following will fail to compile:
- # int foo(int);
- # int foo(short);
-
- lib = ffi.verify(
- source="\n".join(
- [_OSX_PRE_INCLUDE] +
- includes +
- [_OSX_POST_INCLUDE] +
- functions +
- customizations
- ),
- libraries=["crypto", "ssl"],
- )
-
- for name in cls._modules:
- module_name = cls._module_prefix + name
- module = sys.modules[module_name]
- for condition, names in module.CONDITIONAL_NAMES.items():
- if not getattr(lib, condition):
- for name in names:
- delattr(lib, name)
-
- cls.ffi = ffi
- cls.lib = lib
- cls.lib.OpenSSL_add_all_algorithms()
- cls.lib.SSL_load_error_strings()
-
def openssl_version_text(self):
"""
Friendly string name of linked OpenSSL.
Example: OpenSSL 1.0.1e 11 Feb 2013
"""
- return self.ffi.string(self.lib.OPENSSL_VERSION_TEXT).decode("ascii")
+ return self._ffi.string(self._lib.OPENSSL_VERSION_TEXT).decode("ascii")
def create_hmac_ctx(self, key, algorithm):
return _HMACContext(self, key, algorithm)
def hash_supported(self, algorithm):
- digest = self.lib.EVP_get_digestbyname(algorithm.name.encode("ascii"))
- return digest != self.ffi.NULL
+ digest = self._lib.EVP_get_digestbyname(algorithm.name.encode("ascii"))
+ return digest != self._ffi.NULL
def hmac_supported(self, algorithm):
return self.hash_supported(algorithm)
@@ -197,7 +76,7 @@ class Backend(object):
except KeyError:
return False
evp_cipher = adapter(self, cipher, mode)
- return self.ffi.NULL != evp_cipher
+ return self._ffi.NULL != evp_cipher
def register_cipher_adapter(self, cipher_cls, mode_cls, adapter):
if (cipher_cls, mode_cls) in self._cipher_registry:
@@ -251,25 +130,25 @@ class Backend(object):
return _CipherContext(self, cipher, mode, _CipherContext._DECRYPT)
def _handle_error(self, mode):
- code = self.lib.ERR_get_error()
+ code = self._lib.ERR_get_error()
if not code and isinstance(mode, GCM):
raise InvalidTag
assert code != 0
- lib = self.lib.ERR_GET_LIB(code)
- func = self.lib.ERR_GET_FUNC(code)
- reason = self.lib.ERR_GET_REASON(code)
+ lib = self._lib.ERR_GET_LIB(code)
+ func = self._lib.ERR_GET_FUNC(code)
+ reason = self._lib.ERR_GET_REASON(code)
return self._handle_error_code(lib, func, reason)
def _handle_error_code(self, lib, func, reason):
- if lib == self.lib.ERR_LIB_EVP:
- if func == self.lib.EVP_F_EVP_ENCRYPTFINAL_EX:
- if reason == self.lib.EVP_R_DATA_NOT_MULTIPLE_OF_BLOCK_LENGTH:
+ if lib == self._lib.ERR_LIB_EVP:
+ if func == self._lib.EVP_F_EVP_ENCRYPTFINAL_EX:
+ if reason == self._lib.EVP_R_DATA_NOT_MULTIPLE_OF_BLOCK_LENGTH:
raise ValueError(
"The length of the provided data is not a multiple of "
"the block length"
)
- elif func == self.lib.EVP_F_EVP_DECRYPTFINAL_EX:
- if reason == self.lib.EVP_R_DATA_NOT_MULTIPLE_OF_BLOCK_LENGTH:
+ elif func == self._lib.EVP_F_EVP_DECRYPTFINAL_EX:
+ if reason == self._lib.EVP_R_DATA_NOT_MULTIPLE_OF_BLOCK_LENGTH:
raise ValueError(
"The length of the provided data is not a multiple of "
"the block length"
@@ -286,7 +165,7 @@ class GetCipherByName(object):
def __call__(self, backend, cipher, mode):
cipher_name = self._fmt.format(cipher=cipher, mode=mode).lower()
- return backend.lib.EVP_get_cipherbyname(cipher_name.encode("ascii"))
+ return backend._lib.EVP_get_cipherbyname(cipher_name.encode("ascii"))
@utils.register_interface(interfaces.CipherContext)
@@ -308,8 +187,10 @@ class _CipherContext(object):
else:
self._block_size = 1
- ctx = self._backend.lib.EVP_CIPHER_CTX_new()
- ctx = self._backend.ffi.gc(ctx, self._backend.lib.EVP_CIPHER_CTX_free)
+ ctx = self._backend._lib.EVP_CIPHER_CTX_new()
+ ctx = self._backend._ffi.gc(
+ ctx, self._backend._lib.EVP_CIPHER_CTX_free
+ )
registry = self._backend._cipher_registry
try:
@@ -322,7 +203,7 @@ class _CipherContext(object):
)
evp_cipher = adapter(self._backend, cipher, mode)
- if evp_cipher == self._backend.ffi.NULL:
+ if evp_cipher == self._backend._ffi.NULL:
raise UnsupportedAlgorithm(
"cipher {0} in {1} mode is not supported "
"by this backend".format(
@@ -334,86 +215,84 @@ class _CipherContext(object):
elif isinstance(mode, interfaces.ModeWithNonce):
iv_nonce = mode.nonce
else:
- iv_nonce = self._backend.ffi.NULL
+ iv_nonce = self._backend._ffi.NULL
# begin init with cipher and operation type
- res = self._backend.lib.EVP_CipherInit_ex(ctx, evp_cipher,
- self._backend.ffi.NULL,
- self._backend.ffi.NULL,
- self._backend.ffi.NULL,
- operation)
+ res = self._backend._lib.EVP_CipherInit_ex(ctx, evp_cipher,
+ self._backend._ffi.NULL,
+ self._backend._ffi.NULL,
+ self._backend._ffi.NULL,
+ operation)
assert res != 0
# set the key length to handle variable key ciphers
- res = self._backend.lib.EVP_CIPHER_CTX_set_key_length(
+ res = self._backend._lib.EVP_CIPHER_CTX_set_key_length(
ctx, len(cipher.key)
)
assert res != 0
if isinstance(mode, GCM):
- res = self._backend.lib.EVP_CIPHER_CTX_ctrl(
- ctx, self._backend.lib.EVP_CTRL_GCM_SET_IVLEN,
- len(iv_nonce), self._backend.ffi.NULL
+ res = self._backend._lib.EVP_CIPHER_CTX_ctrl(
+ ctx, self._backend._lib.EVP_CTRL_GCM_SET_IVLEN,
+ len(iv_nonce), self._backend._ffi.NULL
)
assert res != 0
if operation == self._DECRYPT:
- if not mode.tag or len(mode.tag) < 4:
- raise ValueError("Authentication tag must be provided and "
- "be 4 bytes or longer when decrypting")
- res = self._backend.lib.EVP_CIPHER_CTX_ctrl(
- ctx, self._backend.lib.EVP_CTRL_GCM_SET_TAG,
+ res = self._backend._lib.EVP_CIPHER_CTX_ctrl(
+ ctx, self._backend._lib.EVP_CTRL_GCM_SET_TAG,
len(mode.tag), mode.tag
)
assert res != 0
- else:
- if mode.tag:
- raise ValueError("Authentication tag must be None when "
- "encrypting")
# pass key/iv
- res = self._backend.lib.EVP_CipherInit_ex(ctx, self._backend.ffi.NULL,
- self._backend.ffi.NULL,
- cipher.key,
- iv_nonce,
- operation)
+ res = self._backend._lib.EVP_CipherInit_ex(
+ ctx,
+ self._backend._ffi.NULL,
+ self._backend._ffi.NULL,
+ cipher.key,
+ iv_nonce,
+ operation
+ )
assert res != 0
# We purposely disable padding here as it's handled higher up in the
# API.
- self._backend.lib.EVP_CIPHER_CTX_set_padding(ctx, 0)
+ self._backend._lib.EVP_CIPHER_CTX_set_padding(ctx, 0)
self._ctx = ctx
def update(self, data):
- buf = self._backend.ffi.new("unsigned char[]",
- len(data) + self._block_size - 1)
- outlen = self._backend.ffi.new("int *")
- res = self._backend.lib.EVP_CipherUpdate(self._ctx, buf, outlen, data,
- len(data))
+ buf = self._backend._ffi.new("unsigned char[]",
+ len(data) + self._block_size - 1)
+ outlen = self._backend._ffi.new("int *")
+ res = self._backend._lib.EVP_CipherUpdate(self._ctx, buf, outlen, data,
+ len(data))
assert res != 0
- return self._backend.ffi.buffer(buf)[:outlen[0]]
+ return self._backend._ffi.buffer(buf)[:outlen[0]]
def finalize(self):
- buf = self._backend.ffi.new("unsigned char[]", self._block_size)
- outlen = self._backend.ffi.new("int *")
- res = self._backend.lib.EVP_CipherFinal_ex(self._ctx, buf, outlen)
+ buf = self._backend._ffi.new("unsigned char[]", self._block_size)
+ outlen = self._backend._ffi.new("int *")
+ res = self._backend._lib.EVP_CipherFinal_ex(self._ctx, buf, outlen)
if res == 0:
self._backend._handle_error(self._mode)
if (isinstance(self._mode, GCM) and
self._operation == self._ENCRYPT):
block_byte_size = self._block_size // 8
- tag_buf = self._backend.ffi.new("unsigned char[]", block_byte_size)
- res = self._backend.lib.EVP_CIPHER_CTX_ctrl(
- self._ctx, self._backend.lib.EVP_CTRL_GCM_GET_TAG,
+ tag_buf = self._backend._ffi.new(
+ "unsigned char[]", block_byte_size
+ )
+ res = self._backend._lib.EVP_CIPHER_CTX_ctrl(
+ self._ctx, self._backend._lib.EVP_CTRL_GCM_GET_TAG,
block_byte_size, tag_buf
)
assert res != 0
- self._tag = self._backend.ffi.buffer(tag_buf)[:]
+ self._tag = self._backend._ffi.buffer(tag_buf)[:]
- res = self._backend.lib.EVP_CIPHER_CTX_cleanup(self._ctx)
+ res = self._backend._lib.EVP_CIPHER_CTX_cleanup(self._ctx)
assert res == 1
- return self._backend.ffi.buffer(buf)[:outlen[0]]
+ return self._backend._ffi.buffer(buf)[:outlen[0]]
def authenticate_additional_data(self, data):
- outlen = self._backend.ffi.new("int *")
- res = self._backend.lib.EVP_CipherUpdate(
- self._ctx, self._backend.ffi.NULL, outlen, data, len(data)
+ outlen = self._backend._ffi.new("int *")
+ res = self._backend._lib.EVP_CipherUpdate(
+ self._ctx, self._backend._ffi.NULL, outlen, data, len(data)
)
assert res != 0
@@ -430,43 +309,44 @@ class _HashContext(object):
self._backend = backend
if ctx is None:
- ctx = self._backend.lib.EVP_MD_CTX_create()
- ctx = self._backend.ffi.gc(ctx,
- self._backend.lib.EVP_MD_CTX_destroy)
- evp_md = self._backend.lib.EVP_get_digestbyname(
+ ctx = self._backend._lib.EVP_MD_CTX_create()
+ ctx = self._backend._ffi.gc(ctx,
+ self._backend._lib.EVP_MD_CTX_destroy)
+ evp_md = self._backend._lib.EVP_get_digestbyname(
algorithm.name.encode("ascii"))
- if evp_md == self._backend.ffi.NULL:
+ if evp_md == self._backend._ffi.NULL:
raise UnsupportedAlgorithm(
"{0} is not a supported hash on this backend".format(
algorithm.name)
)
- res = self._backend.lib.EVP_DigestInit_ex(ctx, evp_md,
- self._backend.ffi.NULL)
+ res = self._backend._lib.EVP_DigestInit_ex(ctx, evp_md,
+ self._backend._ffi.NULL)
assert res != 0
self._ctx = ctx
def copy(self):
- copied_ctx = self._backend.lib.EVP_MD_CTX_create()
- copied_ctx = self._backend.ffi.gc(copied_ctx,
- self._backend.lib.EVP_MD_CTX_destroy)
- res = self._backend.lib.EVP_MD_CTX_copy_ex(copied_ctx, self._ctx)
+ copied_ctx = self._backend._lib.EVP_MD_CTX_create()
+ copied_ctx = self._backend._ffi.gc(
+ copied_ctx, self._backend._lib.EVP_MD_CTX_destroy
+ )
+ res = self._backend._lib.EVP_MD_CTX_copy_ex(copied_ctx, self._ctx)
assert res != 0
return _HashContext(self._backend, self.algorithm, ctx=copied_ctx)
def update(self, data):
- res = self._backend.lib.EVP_DigestUpdate(self._ctx, data, len(data))
+ res = self._backend._lib.EVP_DigestUpdate(self._ctx, data, len(data))
assert res != 0
def finalize(self):
- buf = self._backend.ffi.new("unsigned char[]",
- self.algorithm.digest_size)
- res = self._backend.lib.EVP_DigestFinal_ex(self._ctx, buf,
- self._backend.ffi.NULL)
+ buf = self._backend._ffi.new("unsigned char[]",
+ self.algorithm.digest_size)
+ res = self._backend._lib.EVP_DigestFinal_ex(self._ctx, buf,
+ self._backend._ffi.NULL)
assert res != 0
- res = self._backend.lib.EVP_MD_CTX_cleanup(self._ctx)
+ res = self._backend._lib.EVP_MD_CTX_cleanup(self._ctx)
assert res == 1
- return self._backend.ffi.buffer(buf)[:]
+ return self._backend._ffi.buffer(buf)[:]
@utils.register_interface(interfaces.HashContext)
@@ -476,18 +356,20 @@ class _HMACContext(object):
self._backend = backend
if ctx is None:
- ctx = self._backend.ffi.new("HMAC_CTX *")
- self._backend.lib.HMAC_CTX_init(ctx)
- ctx = self._backend.ffi.gc(ctx, self._backend.lib.HMAC_CTX_cleanup)
- evp_md = self._backend.lib.EVP_get_digestbyname(
+ ctx = self._backend._ffi.new("HMAC_CTX *")
+ self._backend._lib.HMAC_CTX_init(ctx)
+ ctx = self._backend._ffi.gc(
+ ctx, self._backend._lib.HMAC_CTX_cleanup
+ )
+ evp_md = self._backend._lib.EVP_get_digestbyname(
algorithm.name.encode('ascii'))
- if evp_md == self._backend.ffi.NULL:
+ if evp_md == self._backend._ffi.NULL:
raise UnsupportedAlgorithm(
"{0} is not a supported hash on this backend".format(
algorithm.name)
)
- res = self._backend.lib.Cryptography_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
@@ -495,12 +377,12 @@ class _HMACContext(object):
self._key = key
def copy(self):
- copied_ctx = self._backend.ffi.new("HMAC_CTX *")
- self._backend.lib.HMAC_CTX_init(copied_ctx)
- copied_ctx = self._backend.ffi.gc(
- copied_ctx, self._backend.lib.HMAC_CTX_cleanup
+ copied_ctx = self._backend._ffi.new("HMAC_CTX *")
+ 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.Cryptography_HMAC_CTX_copy(
+ res = self._backend._lib.Cryptography_HMAC_CTX_copy(
copied_ctx, self._ctx
)
assert res != 0
@@ -509,20 +391,22 @@ class _HMACContext(object):
)
def update(self, data):
- res = self._backend.lib.Cryptography_HMAC_Update(
+ res = self._backend._lib.Cryptography_HMAC_Update(
self._ctx, data, len(data)
)
assert res != 0
def finalize(self):
- buf = self._backend.ffi.new("unsigned char[]",
- self.algorithm.digest_size)
- buflen = self._backend.ffi.new("unsigned int *",
- self.algorithm.digest_size)
- res = self._backend.lib.Cryptography_HMAC_Final(self._ctx, buf, buflen)
+ buf = self._backend._ffi.new("unsigned char[]",
+ self.algorithm.digest_size)
+ buflen = self._backend._ffi.new("unsigned int *",
+ self.algorithm.digest_size)
+ res = self._backend._lib.Cryptography_HMAC_Final(
+ self._ctx, buf, buflen
+ )
assert res != 0
- self._backend.lib.HMAC_CTX_cleanup(self._ctx)
- return self._backend.ffi.buffer(buf)[:]
+ self._backend._lib.HMAC_CTX_cleanup(self._ctx)
+ return self._backend._ffi.buffer(buf)[:]
backend = Backend()
diff --git a/cryptography/hazmat/bindings/__init__.py b/cryptography/hazmat/bindings/__init__.py
new file mode 100644
index 00000000..55c925c6
--- /dev/null
+++ b/cryptography/hazmat/bindings/__init__.py
@@ -0,0 +1,12 @@
+# 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.
diff --git a/cryptography/hazmat/bindings/openssl/__init__.py b/cryptography/hazmat/bindings/openssl/__init__.py
new file mode 100644
index 00000000..55c925c6
--- /dev/null
+++ b/cryptography/hazmat/bindings/openssl/__init__.py
@@ -0,0 +1,12 @@
+# 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.
diff --git a/cryptography/hazmat/backends/openssl/asn1.py b/cryptography/hazmat/bindings/openssl/asn1.py
index aeaf316e..aeaf316e 100644
--- a/cryptography/hazmat/backends/openssl/asn1.py
+++ b/cryptography/hazmat/bindings/openssl/asn1.py
diff --git a/cryptography/hazmat/backends/openssl/bignum.py b/cryptography/hazmat/bindings/openssl/bignum.py
index 59efd171..59efd171 100644
--- a/cryptography/hazmat/backends/openssl/bignum.py
+++ b/cryptography/hazmat/bindings/openssl/bignum.py
diff --git a/cryptography/hazmat/bindings/openssl/binding.py b/cryptography/hazmat/bindings/openssl/binding.py
new file mode 100644
index 00000000..8b5e3449
--- /dev/null
+++ b/cryptography/hazmat/bindings/openssl/binding.py
@@ -0,0 +1,149 @@
+# 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.
+
+from __future__ import absolute_import, division, print_function
+
+import sys
+
+import cffi
+
+_OSX_PRE_INCLUDE = """
+#ifdef __APPLE__
+#include <AvailabilityMacros.h>
+#define __ORIG_DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER \
+ DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER
+#undef DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER
+#define DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER
+#endif
+"""
+
+_OSX_POST_INCLUDE = """
+#ifdef __APPLE__
+#undef DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER
+#define DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER \
+ __ORIG_DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER
+#endif
+"""
+
+
+class Binding(object):
+ """
+ OpenSSL API wrapper.
+
+ Modules listed in the ``_modules`` listed should have the following
+ attributes:
+
+ * ``INCLUDES``: A string containg C includes.
+ * ``TYPES``: A string containing C declarations for types.
+ * ``FUNCTIONS``: A string containing C declarations for functions.
+ * ``MACROS``: A string containing C declarations for any macros.
+ * ``CUSTOMIZATIONS``: A string containing arbitrary top-level C code, this
+ can be used to do things like test for a define and provide an
+ alternate implementation based on that.
+ * ``CONDITIONAL_NAMES``: A dict mapping strings of condition names from the
+ library to a list of names which will not be present without the
+ condition.
+ """
+ _module_prefix = "cryptography.hazmat.bindings.openssl."
+ _modules = [
+ "asn1",
+ "bignum",
+ "bio",
+ "conf",
+ "crypto",
+ "dh",
+ "dsa",
+ "engine",
+ "err",
+ "evp",
+ "hmac",
+ "nid",
+ "objects",
+ "opensslv",
+ "pem",
+ "pkcs7",
+ "pkcs12",
+ "rand",
+ "rsa",
+ "ssl",
+ "x509",
+ "x509name",
+ "x509v3",
+ ]
+
+ ffi = None
+ lib = None
+
+ def __init__(self):
+ self._ensure_ffi_initialized()
+
+ @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 = []
+ customizations = []
+ for name in cls._modules:
+ module_name = cls._module_prefix + name
+ __import__(module_name)
+ module = sys.modules[module_name]
+
+ 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:
+ ffi.cdef(func)
+ for macro in macros:
+ 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
+ # to re-declare a function if it has the same signature. That is:
+ # int foo(int);
+ # int foo(int);
+ # is legal, but the following will fail to compile:
+ # int foo(int);
+ # int foo(short);
+
+ lib = ffi.verify(
+ source="\n".join(
+ [_OSX_PRE_INCLUDE] +
+ includes +
+ [_OSX_POST_INCLUDE] +
+ functions +
+ customizations
+ ),
+ libraries=["crypto", "ssl"],
+ )
+
+ for name in cls._modules:
+ module_name = cls._module_prefix + name
+ module = sys.modules[module_name]
+ for condition, names in module.CONDITIONAL_NAMES.items():
+ if not getattr(lib, condition):
+ for name in names:
+ delattr(lib, name)
+
+ cls.ffi = ffi
+ cls.lib = lib
diff --git a/cryptography/hazmat/backends/openssl/bio.py b/cryptography/hazmat/bindings/openssl/bio.py
index 279ad223..279ad223 100644
--- a/cryptography/hazmat/backends/openssl/bio.py
+++ b/cryptography/hazmat/bindings/openssl/bio.py
diff --git a/cryptography/hazmat/backends/openssl/conf.py b/cryptography/hazmat/bindings/openssl/conf.py
index 6d818cf1..6d818cf1 100644
--- a/cryptography/hazmat/backends/openssl/conf.py
+++ b/cryptography/hazmat/bindings/openssl/conf.py
diff --git a/cryptography/hazmat/backends/openssl/crypto.py b/cryptography/hazmat/bindings/openssl/crypto.py
index 835be14b..189867bd 100644
--- a/cryptography/hazmat/backends/openssl/crypto.py
+++ b/cryptography/hazmat/bindings/openssl/crypto.py
@@ -36,6 +36,11 @@ int CRYPTO_mem_ctrl(int);
int CRYPTO_is_mem_check_on(void);
void CRYPTO_mem_leaks(struct bio_st *);
void CRYPTO_cleanup_all_ex_data(void);
+int CRYPTO_num_locks(void);
+void CRYPTO_set_locking_callback(void(*)(int, int, const char *, int));
+void CRYPTO_set_id_callback(unsigned long (*)(void));
+unsigned long (*CRYPTO_get_id_callback(void))(void);
+void (*CRYPTO_get_locking_callback(void))(int, int, const char *, int);
void OPENSSL_free(void *);
"""
diff --git a/cryptography/hazmat/backends/openssl/dh.py b/cryptography/hazmat/bindings/openssl/dh.py
index 3c12fbc6..3c12fbc6 100644
--- a/cryptography/hazmat/backends/openssl/dh.py
+++ b/cryptography/hazmat/bindings/openssl/dh.py
diff --git a/cryptography/hazmat/backends/openssl/dsa.py b/cryptography/hazmat/bindings/openssl/dsa.py
index 3b77d7ae..3b77d7ae 100644
--- a/cryptography/hazmat/backends/openssl/dsa.py
+++ b/cryptography/hazmat/bindings/openssl/dsa.py
diff --git a/cryptography/hazmat/backends/openssl/engine.py b/cryptography/hazmat/bindings/openssl/engine.py
index 390bfde1..390bfde1 100644
--- a/cryptography/hazmat/backends/openssl/engine.py
+++ b/cryptography/hazmat/bindings/openssl/engine.py
diff --git a/cryptography/hazmat/backends/openssl/err.py b/cryptography/hazmat/bindings/openssl/err.py
index 6b2a77b1..6b2a77b1 100644
--- a/cryptography/hazmat/backends/openssl/err.py
+++ b/cryptography/hazmat/bindings/openssl/err.py
diff --git a/cryptography/hazmat/backends/openssl/evp.py b/cryptography/hazmat/bindings/openssl/evp.py
index c426e52e..c426e52e 100644
--- a/cryptography/hazmat/backends/openssl/evp.py
+++ b/cryptography/hazmat/bindings/openssl/evp.py
diff --git a/cryptography/hazmat/backends/openssl/hmac.py b/cryptography/hazmat/bindings/openssl/hmac.py
index 5f9e0945..5f9e0945 100644
--- a/cryptography/hazmat/backends/openssl/hmac.py
+++ b/cryptography/hazmat/bindings/openssl/hmac.py
diff --git a/cryptography/hazmat/backends/openssl/nid.py b/cryptography/hazmat/bindings/openssl/nid.py
index 40aed19f..40aed19f 100644
--- a/cryptography/hazmat/backends/openssl/nid.py
+++ b/cryptography/hazmat/bindings/openssl/nid.py
diff --git a/cryptography/hazmat/backends/openssl/objects.py b/cryptography/hazmat/bindings/openssl/objects.py
index 0abc42d6..0abc42d6 100644
--- a/cryptography/hazmat/backends/openssl/objects.py
+++ b/cryptography/hazmat/bindings/openssl/objects.py
diff --git a/cryptography/hazmat/backends/openssl/opensslv.py b/cryptography/hazmat/bindings/openssl/opensslv.py
index 397f4ca2..397f4ca2 100644
--- a/cryptography/hazmat/backends/openssl/opensslv.py
+++ b/cryptography/hazmat/bindings/openssl/opensslv.py
diff --git a/cryptography/hazmat/backends/openssl/pem.py b/cryptography/hazmat/bindings/openssl/pem.py
index ee5552c5..ee5552c5 100644
--- a/cryptography/hazmat/backends/openssl/pem.py
+++ b/cryptography/hazmat/bindings/openssl/pem.py
diff --git a/cryptography/hazmat/backends/openssl/pkcs12.py b/cryptography/hazmat/bindings/openssl/pkcs12.py
index bd01e756..bd01e756 100644
--- a/cryptography/hazmat/backends/openssl/pkcs12.py
+++ b/cryptography/hazmat/bindings/openssl/pkcs12.py
diff --git a/cryptography/hazmat/backends/openssl/pkcs7.py b/cryptography/hazmat/bindings/openssl/pkcs7.py
index 43f9540b..43f9540b 100644
--- a/cryptography/hazmat/backends/openssl/pkcs7.py
+++ b/cryptography/hazmat/bindings/openssl/pkcs7.py
diff --git a/cryptography/hazmat/backends/openssl/rand.py b/cryptography/hazmat/bindings/openssl/rand.py
index 0e645fbc..0e645fbc 100644
--- a/cryptography/hazmat/backends/openssl/rand.py
+++ b/cryptography/hazmat/bindings/openssl/rand.py
diff --git a/cryptography/hazmat/backends/openssl/rsa.py b/cryptography/hazmat/bindings/openssl/rsa.py
index a44ca4a6..a44ca4a6 100644
--- a/cryptography/hazmat/backends/openssl/rsa.py
+++ b/cryptography/hazmat/bindings/openssl/rsa.py
diff --git a/cryptography/hazmat/backends/openssl/ssl.py b/cryptography/hazmat/bindings/openssl/ssl.py
index d0d5ae2d..d0d5ae2d 100644
--- a/cryptography/hazmat/backends/openssl/ssl.py
+++ b/cryptography/hazmat/bindings/openssl/ssl.py
diff --git a/cryptography/hazmat/backends/openssl/x509.py b/cryptography/hazmat/bindings/openssl/x509.py
index 840254a2..840254a2 100644
--- a/cryptography/hazmat/backends/openssl/x509.py
+++ b/cryptography/hazmat/bindings/openssl/x509.py
diff --git a/cryptography/hazmat/backends/openssl/x509name.py b/cryptography/hazmat/bindings/openssl/x509name.py
index bf627d61..bf627d61 100644
--- a/cryptography/hazmat/backends/openssl/x509name.py
+++ b/cryptography/hazmat/bindings/openssl/x509name.py
diff --git a/cryptography/hazmat/backends/openssl/x509v3.py b/cryptography/hazmat/bindings/openssl/x509v3.py
index 6d2d2361..6d2d2361 100644
--- a/cryptography/hazmat/backends/openssl/x509v3.py
+++ b/cryptography/hazmat/bindings/openssl/x509v3.py
diff --git a/cryptography/hazmat/primitives/ciphers/base.py b/cryptography/hazmat/primitives/ciphers/base.py
index a5603ab5..d366e4cf 100644
--- a/cryptography/hazmat/primitives/ciphers/base.py
+++ b/cryptography/hazmat/primitives/ciphers/base.py
@@ -33,16 +33,26 @@ class Cipher(object):
self._backend = backend
def encryptor(self):
+ if isinstance(self.mode, interfaces.ModeWithAuthenticationTag):
+ if self.mode.tag is not None:
+ raise ValueError(
+ "Authentication tag must be None when encrypting"
+ )
ctx = self._backend.create_symmetric_encryption_ctx(
self.algorithm, self.mode
)
- return self._wrap_ctx(ctx, True)
+ return self._wrap_ctx(ctx, encrypt=True)
def decryptor(self):
+ if isinstance(self.mode, interfaces.ModeWithAuthenticationTag):
+ if self.mode.tag is None:
+ raise ValueError(
+ "Authentication tag must be provided when decrypting"
+ )
ctx = self._backend.create_symmetric_decryption_ctx(
self.algorithm, self.mode
)
- return self._wrap_ctx(ctx, False)
+ return self._wrap_ctx(ctx, encrypt=False)
def _wrap_ctx(self, ctx, encrypt):
if isinstance(self.mode, interfaces.ModeWithAuthenticationTag):
diff --git a/cryptography/hazmat/primitives/ciphers/modes.py b/cryptography/hazmat/primitives/ciphers/modes.py
index 31af5d6e..739f23dd 100644
--- a/cryptography/hazmat/primitives/ciphers/modes.py
+++ b/cryptography/hazmat/primitives/ciphers/modes.py
@@ -95,6 +95,11 @@ class GCM(object):
# len(initialization_vector) must in [1, 2 ** 64), but it's impossible
# to actually construct a bytes object that large, so we don't check
# for it
+ if tag is not None and len(tag) < 4:
+ raise ValueError(
+ "Authentication tag must be 4 bytes or longer"
+ )
+
self.initialization_vector = initialization_vector
self.tag = tag
diff --git a/docs/architecture.rst b/docs/architecture.rst
deleted file mode 100644
index bacde1bb..00000000
--- a/docs/architecture.rst
+++ /dev/null
@@ -1,13 +0,0 @@
-Architecture
-============
-
-``cryptography`` has three different layers:
-
-* ``cryptography``: This package contains higher level recipes, for example
- "encrypt and then MAC". This is implemented on top of
- ``cryptography.hazmat.primitives``.
-* ``cryptography.hazmat.primitives``: This packages contains low level
- algorithms, things like ``AES`` or ``SHA1``. This is implemented on top of
- ``cryptography.hazmat.backends``.
-* ``cryptography.hazmat.backends``: This package contains bindings to low level
- cryptographic libraries. Our initial target is OpenSSL.
diff --git a/docs/hazmat/backends/openssl.rst b/docs/hazmat/backends/openssl.rst
index 99b327d9..404573a3 100644
--- a/docs/hazmat/backends/openssl.rst
+++ b/docs/hazmat/backends/openssl.rst
@@ -3,23 +3,11 @@
OpenSSL Backend
===============
-These are `CFFI`_ bindings to the `OpenSSL`_ C library.
+The `OpenSSL`_ C library.
.. data:: cryptography.hazmat.backends.openssl.backend
- This is the exposed API for the OpenSSL bindings. It has two public
- attributes:
-
- .. attribute:: ffi
-
- This is a :class:`cffi.FFI` instance. It can be used to allocate and
- otherwise manipulate OpenSSL structures.
-
- .. attribute:: lib
-
- This is a ``cffi`` library. It can be used to call OpenSSL functions,
- and access constants.
-
+ This is the exposed API for the OpenSSL backend. It has no public attributes.
Using your own OpenSSL on Linux
-------------------------------
@@ -48,5 +36,4 @@ You'll also need to generate your own ``openssl.ld`` file. For example::
You should replace the version string on the first line as appropriate for your
build.
-.. _`CFFI`: https://cffi.readthedocs.org/
.. _`OpenSSL`: https://www.openssl.org/
diff --git a/docs/hazmat/bindings/index.rst b/docs/hazmat/bindings/index.rst
new file mode 100644
index 00000000..809eddfc
--- /dev/null
+++ b/docs/hazmat/bindings/index.rst
@@ -0,0 +1,22 @@
+.. hazmat::
+
+Bindings
+========
+
+.. currentmodule:: cryptography.hazmat.bindings
+
+``cryptography`` aims to provide low-level CFFI based bindings to multiple
+native C libraries. These provide no automatic initialisation of the library
+and may not provide complete wrappers for its API.
+
+Using these functions directly is likely to require you to be careful in
+managing memory allocation, locking and other resources.
+
+
+Individual Bindings
+-------------------
+
+.. toctree::
+ :maxdepth: 1
+
+ openssl
diff --git a/docs/hazmat/bindings/openssl.rst b/docs/hazmat/bindings/openssl.rst
new file mode 100644
index 00000000..373fe472
--- /dev/null
+++ b/docs/hazmat/bindings/openssl.rst
@@ -0,0 +1,27 @@
+.. hazmat::
+
+OpenSSL Binding
+===============
+
+.. currentmodule:: cryptography.hazmat.bindings.openssl.binding
+
+These are `CFFI`_ bindings to the `OpenSSL`_ C library.
+
+.. class:: cryptography.hazmat.bindings.openssl.binding.Binding()
+
+ This is the exposed API for the OpenSSL bindings. It has two public
+ attributes:
+
+ .. attribute:: ffi
+
+ This is a :class:`cffi.FFI` instance. It can be used to allocate and
+ otherwise manipulate OpenSSL structures.
+
+ .. attribute:: lib
+
+ This is a ``cffi`` library. It can be used to call OpenSSL functions,
+ and access constants.
+
+
+.. _`CFFI`: https://cffi.readthedocs.org/
+.. _`OpenSSL`: https://www.openssl.org/
diff --git a/docs/index.rst b/docs/index.rst
index 70558bda..5eb3de7d 100644
--- a/docs/index.rst
+++ b/docs/index.rst
@@ -43,7 +43,9 @@ The other level is low-level cryptographic primitives. These are often
dangerous and can be used incorrectly. They require making decisions and having
an in-depth knowledge of the cryptographic concepts at work. Because of the
potential danger in working at this level, this is referred to as the
-"hazardous materials" or "hazmat" layer.
+"hazardous materials" or "hazmat" layer. These live in the
+``cryptography.hazmat`` package, and their documentation will always contain an
+admonition at the top.
We recommend using the recipes layer whenever possible, and falling back to the
hazmat layer only when necessary.
@@ -54,7 +56,6 @@ The recipes layer
.. toctree::
:maxdepth: 2
- architecture
exceptions
glossary
@@ -66,6 +67,7 @@ The hazardous materials layer
hazmat/primitives/index
hazmat/backends/index
+ hazmat/bindings/index
The ``cryptography`` open source project
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
diff --git a/tests/hazmat/backends/test_openssl.py b/tests/hazmat/backends/test_openssl.py
index 23f9bff1..ad399594 100644
--- a/tests/hazmat/backends/test_openssl.py
+++ b/tests/hazmat/backends/test_openssl.py
@@ -61,18 +61,13 @@ class TestOpenSSL(object):
with pytest.raises(ValueError):
backend.register_cipher_adapter(AES, CBC, None)
- def test_instances_share_ffi(self):
- b = Backend()
- assert b.ffi is backend.ffi
- assert b.lib is backend.lib
-
@pytest.mark.parametrize("mode", [DummyMode(), None])
def test_nonexistent_cipher(self, mode):
b = Backend()
b.register_cipher_adapter(
DummyCipher,
type(mode),
- lambda backend, cipher, mode: backend.ffi.NULL
+ lambda backend, cipher, mode: backend._ffi.NULL
)
cipher = Cipher(
DummyCipher(), mode, backend=b,
@@ -85,18 +80,18 @@ class TestOpenSSL(object):
backend._handle_error_code(0, 0, 0)
with pytest.raises(SystemError):
- backend._handle_error_code(backend.lib.ERR_LIB_EVP, 0, 0)
+ backend._handle_error_code(backend._lib.ERR_LIB_EVP, 0, 0)
with pytest.raises(SystemError):
backend._handle_error_code(
- backend.lib.ERR_LIB_EVP,
- backend.lib.EVP_F_EVP_ENCRYPTFINAL_EX,
+ backend._lib.ERR_LIB_EVP,
+ backend._lib.EVP_F_EVP_ENCRYPTFINAL_EX,
0
)
with pytest.raises(SystemError):
backend._handle_error_code(
- backend.lib.ERR_LIB_EVP,
- backend.lib.EVP_F_EVP_DECRYPTFINAL_EX,
+ backend._lib.ERR_LIB_EVP,
+ backend._lib.EVP_F_EVP_DECRYPTFINAL_EX,
0
)
diff --git a/tests/hazmat/bindings/test_openssl.py b/tests/hazmat/bindings/test_openssl.py
new file mode 100644
index 00000000..31f736ab
--- /dev/null
+++ b/tests/hazmat/bindings/test_openssl.py
@@ -0,0 +1,22 @@
+# 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.
+
+from cryptography.hazmat.bindings.openssl.binding import Binding
+
+
+class TestOpenSSL(object):
+ def test_binding_loads(self):
+ binding = Binding()
+ assert binding
+ assert binding.lib
+ assert binding.ffi
diff --git a/tests/hazmat/primitives/utils.py b/tests/hazmat/primitives/utils.py
index cdcf84cb..6ecc70ff 100644
--- a/tests/hazmat/primitives/utils.py
+++ b/tests/hazmat/primitives/utils.py
@@ -264,13 +264,10 @@ def aead_tag_exception_test(backend, cipher_factory, mode_factory):
)
with pytest.raises(ValueError):
cipher.decryptor()
- cipher = Cipher(
- cipher_factory(binascii.unhexlify(b"0" * 32)),
- mode_factory(binascii.unhexlify(b"0" * 24), b"000"),
- backend
- )
+
with pytest.raises(ValueError):
- cipher.decryptor()
+ mode_factory(binascii.unhexlify(b"0" * 24), b"000")
+
cipher = Cipher(
cipher_factory(binascii.unhexlify(b"0" * 32)),
mode_factory(binascii.unhexlify(b"0" * 24), b"0" * 16),
diff --git a/tox.ini b/tox.ini
index 61143112..93f5b421 100644
--- a/tox.ini
+++ b/tox.ini
@@ -24,7 +24,7 @@ commands =
# Temporarily disable coverage on pypy because of performance problems with
# coverage.py on pypy.
[testenv:pypy]
-commands = py.test --capture=no
+commands = py.test --capture=no --strict
[testenv:pep8]
deps = flake8