diff options
author | Alex Gaynor <alex.gaynor@gmail.com> | 2014-01-02 10:55:36 -0800 |
---|---|---|
committer | Alex Gaynor <alex.gaynor@gmail.com> | 2014-01-02 10:55:36 -0800 |
commit | 5bae063ff2601db15d84920f18bae194bcd3d373 (patch) | |
tree | b6c39a3f84b434ae26245fcda6abe6c1e4165156 | |
parent | 09aa74635f54ace5480a6d502b0da92651f516b6 (diff) | |
parent | a6d5d6ec53da5bea0193047c5e535a05442f2dfd (diff) | |
download | cryptography-5bae063ff2601db15d84920f18bae194bcd3d373.tar.gz cryptography-5bae063ff2601db15d84920f18bae194bcd3d373.tar.bz2 cryptography-5bae063ff2601db15d84920f18bae194bcd3d373.zip |
Merge branch 'master' into fernet
Conflicts:
docs/index.rst
-rwxr-xr-x | .travis/install.sh | 18 | ||||
-rw-r--r-- | cryptography/__about__.py | 2 | ||||
-rw-r--r-- | cryptography/hazmat/backends/openssl/backend.py | 338 | ||||
-rw-r--r-- | cryptography/hazmat/bindings/__init__.py | 12 | ||||
-rw-r--r-- | cryptography/hazmat/bindings/openssl/__init__.py | 12 | ||||
-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.py | 149 | ||||
-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.py | 14 | ||||
-rw-r--r-- | cryptography/hazmat/primitives/ciphers/modes.py | 5 | ||||
-rw-r--r-- | docs/architecture.rst | 13 | ||||
-rw-r--r-- | docs/conf.py | 2 | ||||
-rw-r--r-- | docs/hazmat/backends/openssl.rst | 34 | ||||
-rw-r--r-- | docs/hazmat/bindings/index.rst | 22 | ||||
-rw-r--r-- | docs/hazmat/bindings/openssl.rst | 27 | ||||
-rw-r--r-- | docs/index.rst | 6 | ||||
-rw-r--r-- | tests/hazmat/backends/test_openssl.py | 17 | ||||
-rw-r--r-- | tests/hazmat/bindings/test_openssl.py | 22 | ||||
-rw-r--r-- | tests/hazmat/primitives/utils.py | 9 | ||||
-rw-r--r-- | tox.ini | 2 |
41 files changed, 434 insertions, 275 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/__about__.py b/cryptography/__about__.py index cd207fcc..46212bff 100644 --- a/cryptography/__about__.py +++ b/cryptography/__about__.py @@ -30,4 +30,4 @@ __author__ = ("Alex Gaynor, Hynek Schlawack, Donald Stufft, " __email__ = "cryptography-dev@python.org" __license__ = "Apache License, Version 2.0" -__copyright__ = "Copyright 2013 %s" % __author__ +__copyright__ = "Copyright 2013-2014 %s" % __author__ 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 b8615cb9..1da0802c 100644 --- a/cryptography/hazmat/primitives/ciphers/base.py +++ b/cryptography/hazmat/primitives/ciphers/base.py @@ -30,16 +30,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 e1c70185..ab8501c6 100644 --- a/cryptography/hazmat/primitives/ciphers/modes.py +++ b/cryptography/hazmat/primitives/ciphers/modes.py @@ -65,5 +65,10 @@ class GCM(object): name = "GCM" def __init__(self, initialization_vector, tag=None): + 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/conf.py b/docs/conf.py index 5092e4d3..5dbcdab8 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -54,7 +54,7 @@ master_doc = 'index' # General information about the project. project = 'Cryptography' -copyright = '2013, Individual Contributors' +copyright = '2013-2014, Individual Contributors' # The version info for the project you're documenting, acts as replacement for # |version| and |release|, also used in various other places throughout the diff --git a/docs/hazmat/backends/openssl.rst b/docs/hazmat/backends/openssl.rst index 5e51c75e..404573a3 100644 --- a/docs/hazmat/backends/openssl.rst +++ b/docs/hazmat/backends/openssl.rst @@ -3,23 +3,37 @@ 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: + This is the exposed API for the OpenSSL backend. It has no public attributes. - .. attribute:: ffi +Using your own OpenSSL on Linux +------------------------------- - This is a :class:`cffi.FFI` instance. It can be used to allocate and - otherwise manipulate OpenSSL structures. +Python links to OpenSSL for its own purposes and this can sometimes cause +problems when you wish to use a different version of OpenSSL with cryptography. +If you want to use cryptography with your own build of OpenSSL you will need to +make sure that the build is configured correctly so that your version of +OpenSSL doesn't conflict with Python's. - .. attribute:: lib +The options you need to add allow the linker to identify every symbol correctly +even when multiple versions of the library are linked into the same program. If +you are using your distribution's source packages these will probably be +patched in for you already, otherwise you'll need to use options something like +this when configuring OpenSSL:: - This is a ``cffi`` library. It can be used to call OpenSSL functions, - and access constants. + ./config -Wl,--version-script=openssl.ld -Wl,-Bsymbolic-functions -fPIC shared +You'll also need to generate your own ``openssl.ld`` file. For example:: + + OPENSSL_1.0.1F_CUSTOM { + global: + *; + }; + +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 72711174..9682337c 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. @@ -55,7 +57,6 @@ The recipes layer :maxdepth: 2 fernet - architecture exceptions glossary @@ -67,6 +68,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 543a05fe..22cfbe71 100644 --- a/tests/hazmat/backends/test_openssl.py +++ b/tests/hazmat/backends/test_openssl.py @@ -58,18 +58,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, @@ -82,18 +77,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), @@ -25,7 +25,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 |