diff options
22 files changed, 285 insertions, 122 deletions
diff --git a/.travis/install.sh b/.travis/install.sh index fdd71907..4aa39799 100755 --- a/.travis/install.sh +++ b/.travis/install.sh @@ -5,24 +5,8 @@ set -x if [[ "${OPENSSL}" == "0.9.8" ]]; then sudo add-apt-repository "deb http://archive.ubuntu.com/ubuntu/ lucid main" -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 -y update 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 46212bff..54a9dbe6 100644 --- a/cryptography/__about__.py +++ b/cryptography/__about__.py @@ -26,7 +26,7 @@ __version__ = "0.1.dev1" __author__ = ("Alex Gaynor, Hynek Schlawack, Donald Stufft, " "Laurens Van Houtven, Jean-Paul Calderone, Christian Heimes, " - "and individual contributors.") + "Paul Kehrer, and individual contributors.") __email__ = "cryptography-dev@python.org" __license__ = "Apache License, Version 2.0" diff --git a/cryptography/hazmat/bindings/openssl/binding.py b/cryptography/hazmat/bindings/openssl/binding.py index 8b5e3449..2a1e1184 100644 --- a/cryptography/hazmat/bindings/openssl/binding.py +++ b/cryptography/hazmat/bindings/openssl/binding.py @@ -13,9 +13,9 @@ from __future__ import absolute_import, division, print_function -import sys - -import cffi +from cryptography.hazmat.bindings.utils import ( + build_ffi, binding_available +) _OSX_PRE_INCLUDE = """ #ifdef __APPLE__ @@ -39,20 +39,6 @@ _OSX_POST_INCLUDE = """ 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 = [ @@ -92,58 +78,10 @@ class Binding(object): 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) + cls.ffi, cls.lib = build_ffi(cls._module_prefix, cls._modules, + _OSX_PRE_INCLUDE, _OSX_POST_INCLUDE, + ["crypto", "ssl"]) - # 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 + @classmethod + def is_available(cls): + return binding_available(cls._ensure_ffi_initialized) diff --git a/cryptography/hazmat/bindings/utils.py b/cryptography/hazmat/bindings/utils.py new file mode 100644 index 00000000..9141c155 --- /dev/null +++ b/cryptography/hazmat/bindings/utils.py @@ -0,0 +1,96 @@ +# 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 + + +def build_ffi(module_prefix, modules, pre_include, post_include, libraries): + """ + Modules listed in ``modules`` should have the following attributes: + + * ``INCLUDES``: A string containing 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. + """ + ffi = cffi.FFI() + includes = [] + functions = [] + macros = [] + customizations = [] + for name in modules: + module_name = 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( + [pre_include] + + includes + + [post_include] + + functions + + customizations + ), + libraries=libraries + ) + + for name in modules: + module_name = 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) + + return ffi, lib + + +def binding_available(initializer): + try: + initializer() + return True + except cffi.VerificationError: + return False diff --git a/cryptography/hazmat/primitives/ciphers/base.py b/cryptography/hazmat/primitives/ciphers/base.py index 1da0802c..d366e4cf 100644 --- a/cryptography/hazmat/primitives/ciphers/base.py +++ b/cryptography/hazmat/primitives/ciphers/base.py @@ -25,6 +25,9 @@ class Cipher(object): if not isinstance(algorithm, interfaces.CipherAlgorithm): raise TypeError("Expected interface of interfaces.CipherAlgorithm") + if mode is not None: + mode.validate_for_algorithm(algorithm) + self.algorithm = algorithm self.mode = mode self._backend = backend diff --git a/cryptography/hazmat/primitives/ciphers/modes.py b/cryptography/hazmat/primitives/ciphers/modes.py index ab8501c6..739f23dd 100644 --- a/cryptography/hazmat/primitives/ciphers/modes.py +++ b/cryptography/hazmat/primitives/ciphers/modes.py @@ -25,11 +25,20 @@ class CBC(object): def __init__(self, initialization_vector): self.initialization_vector = initialization_vector + def validate_for_algorithm(self, algorithm): + if len(self.initialization_vector) * 8 != algorithm.block_size: + raise ValueError("Invalid iv size ({0}) for {1}".format( + len(self.initialization_vector), self.name + )) + @utils.register_interface(interfaces.Mode) class ECB(object): name = "ECB" + def validate_for_algorithm(self, algorithm): + pass + @utils.register_interface(interfaces.Mode) @utils.register_interface(interfaces.ModeWithInitializationVector) @@ -39,6 +48,12 @@ class OFB(object): def __init__(self, initialization_vector): self.initialization_vector = initialization_vector + def validate_for_algorithm(self, algorithm): + if len(self.initialization_vector) * 8 != algorithm.block_size: + raise ValueError("Invalid iv size ({0}) for {1}".format( + len(self.initialization_vector), self.name + )) + @utils.register_interface(interfaces.Mode) @utils.register_interface(interfaces.ModeWithInitializationVector) @@ -48,6 +63,12 @@ class CFB(object): def __init__(self, initialization_vector): self.initialization_vector = initialization_vector + def validate_for_algorithm(self, algorithm): + if len(self.initialization_vector) * 8 != algorithm.block_size: + raise ValueError("Invalid iv size ({0}) for {1}".format( + len(self.initialization_vector), self.name + )) + @utils.register_interface(interfaces.Mode) @utils.register_interface(interfaces.ModeWithNonce) @@ -57,6 +78,12 @@ class CTR(object): def __init__(self, nonce): self.nonce = nonce + def validate_for_algorithm(self, algorithm): + if len(self.nonce) * 8 != algorithm.block_size: + raise ValueError("Invalid nonce size ({0}) for {1}".format( + len(self.nonce), self.name + )) + @utils.register_interface(interfaces.Mode) @utils.register_interface(interfaces.ModeWithInitializationVector) @@ -65,6 +92,9 @@ class GCM(object): name = "GCM" def __init__(self, initialization_vector, tag=None): + # 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" @@ -72,3 +102,6 @@ class GCM(object): self.initialization_vector = initialization_vector self.tag = tag + + def validate_for_algorithm(self, algorithm): + pass diff --git a/cryptography/hazmat/primitives/interfaces.py b/cryptography/hazmat/primitives/interfaces.py index e87c9ca9..7a6bf3e2 100644 --- a/cryptography/hazmat/primitives/interfaces.py +++ b/cryptography/hazmat/primitives/interfaces.py @@ -47,6 +47,13 @@ class Mode(six.with_metaclass(abc.ABCMeta)): A string naming this mode (e.g. "ECB", "CBC"). """ + @abc.abstractmethod + def validate_for_algorithm(self, algorithm): + """ + Checks that all the necessary invariants of this (mode, algorithm) + combination are met. + """ + class ModeWithInitializationVector(six.with_metaclass(abc.ABCMeta)): @abc.abstractproperty diff --git a/docs/glossary.rst b/docs/glossary.rst index 63e0a6ce..4421fca3 100644 --- a/docs/glossary.rst +++ b/docs/glossary.rst @@ -2,6 +2,7 @@ Glossary ======== .. glossary:: + :sorted: plaintext User-readable data you care about. @@ -35,7 +36,7 @@ Glossary symmetric or asymmetric. Authentication is necessary for effective encryption. - Ciphertext indistinguishability + ciphertext indistinguishability This is a property of encryption systems whereby two encrypted messages aren't distinguishable without knowing the encryption key. This is considered a basic, necessary property for a working encryption system. diff --git a/docs/hazmat/bindings/index.rst b/docs/hazmat/bindings/index.rst index 809eddfc..e2a17591 100644 --- a/docs/hazmat/bindings/index.rst +++ b/docs/hazmat/bindings/index.rst @@ -6,7 +6,7 @@ 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 +native C libraries. These provide no automatic initialization 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 diff --git a/docs/hazmat/primitives/hmac.rst b/docs/hazmat/primitives/hmac.rst index b8f94fd2..dc5c54f8 100644 --- a/docs/hazmat/primitives/hmac.rst +++ b/docs/hazmat/primitives/hmac.rst @@ -74,8 +74,11 @@ message. .. method:: verify(signature) - Finalize the current context and securely compare digest to ``signature``. + Finalize the current context and securely compare digest to + ``signature``. - :param bytes signature: The bytes of the HMAC signature recieved. + :param bytes signature: The bytes to compare the current digest + against. :raises cryptography.exceptions.AlreadyFinalized: See :meth:`finalize` - :raises cryptography.exceptions.InvalidSignature: If signature does not match digest + :raises cryptography.exceptions.InvalidSignature: If signature does not + match digest diff --git a/docs/hazmat/primitives/interfaces.rst b/docs/hazmat/primitives/interfaces.rst index 361b723e..edb24cd9 100644 --- a/docs/hazmat/primitives/interfaces.rst +++ b/docs/hazmat/primitives/interfaces.rst @@ -67,6 +67,18 @@ Interfaces used by the symmetric cipher modes described in The name may be used by a backend to influence the operation of a cipher in conjunction with the algorithm's name. + .. method:: validate_for_algorithm(algorithm) + + :param CipherAlgorithm algorithm: + + Checks that the combination of this mode with the provided algorithm + meets any necessary invariants. This should raise an exception if they + are not met. + + For example, the :class:`~cryptography.hazmat.primitives.modes.CBC` + mode uses this method to check that the provided initialization + vector's length matches the block size of the algorithm. + .. class:: ModeWithInitializationVector @@ -10,12 +10,16 @@ # implied. # See the License for the specific language governing permissions and # limitations under the License. +import os + from setuptools import setup, find_packages +base_dir = os.path.dirname(__file__) + about = {} -with open("cryptography/__about__.py") as fp: - exec(fp.read(), about) +with open(os.path.join(base_dir, "cryptography", "__about__.py")) as f: + exec(f.read(), about) CFFI_DEPENDENCY = "cffi>=0.6" @@ -30,11 +34,16 @@ setup_requires = [ CFFI_DEPENDENCY, ] +with open(os.path.join(base_dir, "README.rst")) as f: + long_description = f.read() + + setup( name=about["__title__"], version=about["__version__"], description=about["__summary__"], + long_description=long_description, license=about["__license__"], url=about["__uri__"], diff --git a/tests/hazmat/backends/test_openssl.py b/tests/hazmat/backends/test_openssl.py index 22cfbe71..ad399594 100644 --- a/tests/hazmat/backends/test_openssl.py +++ b/tests/hazmat/backends/test_openssl.py @@ -27,6 +27,9 @@ from cryptography.hazmat.primitives.ciphers.modes import CBC class DummyMode(object): name = "dummy-mode" + def validate_for_algorithm(self, algorithm): + pass + @utils.register_interface(interfaces.CipherAlgorithm) class DummyCipher(object): diff --git a/tests/hazmat/bindings/test_bindings.py b/tests/hazmat/bindings/test_bindings.py new file mode 100644 index 00000000..7af1d581 --- /dev/null +++ b/tests/hazmat/bindings/test_bindings.py @@ -0,0 +1,32 @@ +# 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 cffi + +from cryptography.hazmat.bindings.utils import binding_available +from cryptography.hazmat.bindings.openssl.binding import Binding + + +def dummy_initializer(): + ffi = cffi.FFI() + ffi.verify(source="#include <fake_header.h>") + + +def test_binding_available(): + assert binding_available(Binding._ensure_ffi_initialized) is True + + +def test_binding_unavailable(): + assert binding_available(dummy_initializer) is False diff --git a/tests/hazmat/bindings/test_openssl.py b/tests/hazmat/bindings/test_openssl.py index 31f736ab..d1e85058 100644 --- a/tests/hazmat/bindings/test_openssl.py +++ b/tests/hazmat/bindings/test_openssl.py @@ -20,3 +20,6 @@ class TestOpenSSL(object): assert binding assert binding.lib assert binding.ffi + + def test_is_available(self): + assert Binding.is_available() is True diff --git a/tests/hazmat/primitives/test_block.py b/tests/hazmat/primitives/test_block.py index 30cf1d60..f758ffaa 100644 --- a/tests/hazmat/primitives/test_block.py +++ b/tests/hazmat/primitives/test_block.py @@ -35,6 +35,9 @@ from .utils import ( class DummyMode(object): name = "dummy-mode" + def validate_for_algorithm(self, algorithm): + pass + @utils.register_interface(interfaces.CipherAlgorithm) class DummyCipher(object): @@ -152,3 +155,37 @@ class TestAEADCipherContext(object): algorithms.AES, modes.GCM, ) + + +class TestModeValidation(object): + def test_cbc(self, backend): + with pytest.raises(ValueError): + Cipher( + algorithms.AES(b"\x00" * 16), + modes.CBC(b"abc"), + backend, + ) + + def test_ofb(self, backend): + with pytest.raises(ValueError): + Cipher( + algorithms.AES(b"\x00" * 16), + modes.OFB(b"abc"), + backend, + ) + + def test_cfb(self, backend): + with pytest.raises(ValueError): + Cipher( + algorithms.AES(b"\x00" * 16), + modes.CFB(b"abc"), + backend, + ) + + def test_ctr(self, backend): + with pytest.raises(ValueError): + Cipher( + algorithms.AES(b"\x00" * 16), + modes.CTR(b"abc"), + backend, + ) diff --git a/tests/hazmat/primitives/test_hash_vectors.py b/tests/hazmat/primitives/test_hash_vectors.py index 13ffc3fd..ca97fc11 100644 --- a/tests/hazmat/primitives/test_hash_vectors.py +++ b/tests/hazmat/primitives/test_hash_vectors.py @@ -24,7 +24,7 @@ from ...utils import load_hash_vectors @pytest.mark.supported( - only_if=lambda backend: backend.hash_supported(hashes.SHA1), + only_if=lambda backend: backend.hash_supported(hashes.SHA1()), skip_message="Does not support SHA1", ) @pytest.mark.hash @@ -41,7 +41,7 @@ class TestSHA1(object): @pytest.mark.supported( - only_if=lambda backend: backend.hash_supported(hashes.SHA224), + only_if=lambda backend: backend.hash_supported(hashes.SHA224()), skip_message="Does not support SHA224", ) @pytest.mark.hash @@ -58,7 +58,7 @@ class TestSHA224(object): @pytest.mark.supported( - only_if=lambda backend: backend.hash_supported(hashes.SHA256), + only_if=lambda backend: backend.hash_supported(hashes.SHA256()), skip_message="Does not support SHA256", ) @pytest.mark.hash @@ -75,7 +75,7 @@ class TestSHA256(object): @pytest.mark.supported( - only_if=lambda backend: backend.hash_supported(hashes.SHA384), + only_if=lambda backend: backend.hash_supported(hashes.SHA384()), skip_message="Does not support SHA384", ) @pytest.mark.hash @@ -92,7 +92,7 @@ class TestSHA384(object): @pytest.mark.supported( - only_if=lambda backend: backend.hash_supported(hashes.SHA512), + only_if=lambda backend: backend.hash_supported(hashes.SHA512()), skip_message="Does not support SHA512", ) @pytest.mark.hash @@ -109,7 +109,7 @@ class TestSHA512(object): @pytest.mark.supported( - only_if=lambda backend: backend.hash_supported(hashes.RIPEMD160), + only_if=lambda backend: backend.hash_supported(hashes.RIPEMD160()), skip_message="Does not support RIPEMD160", ) @pytest.mark.hash @@ -130,7 +130,7 @@ class TestRIPEMD160(object): @pytest.mark.supported( - only_if=lambda backend: backend.hash_supported(hashes.Whirlpool), + only_if=lambda backend: backend.hash_supported(hashes.Whirlpool()), skip_message="Does not support Whirlpool", ) @pytest.mark.hash @@ -153,7 +153,7 @@ class TestWhirlpool(object): @pytest.mark.supported( - only_if=lambda backend: backend.hash_supported(hashes.MD5), + only_if=lambda backend: backend.hash_supported(hashes.MD5()), skip_message="Does not support MD5", ) @pytest.mark.hash diff --git a/tests/hazmat/primitives/test_hashes.py b/tests/hazmat/primitives/test_hashes.py index c907ef61..9ca2feee 100644 --- a/tests/hazmat/primitives/test_hashes.py +++ b/tests/hazmat/primitives/test_hashes.py @@ -70,7 +70,7 @@ class TestHashContext(object): @pytest.mark.supported( - only_if=lambda backend: backend.hash_supported(hashes.SHA1), + only_if=lambda backend: backend.hash_supported(hashes.SHA1()), skip_message="Does not support SHA1", ) @pytest.mark.hash @@ -83,7 +83,7 @@ class TestSHA1(object): @pytest.mark.supported( - only_if=lambda backend: backend.hash_supported(hashes.SHA224), + only_if=lambda backend: backend.hash_supported(hashes.SHA224()), skip_message="Does not support SHA224", ) @pytest.mark.hash @@ -96,7 +96,7 @@ class TestSHA224(object): @pytest.mark.supported( - only_if=lambda backend: backend.hash_supported(hashes.SHA256), + only_if=lambda backend: backend.hash_supported(hashes.SHA256()), skip_message="Does not support SHA256", ) @pytest.mark.hash @@ -109,7 +109,7 @@ class TestSHA256(object): @pytest.mark.supported( - only_if=lambda backend: backend.hash_supported(hashes.SHA384), + only_if=lambda backend: backend.hash_supported(hashes.SHA384()), skip_message="Does not support SHA384", ) @pytest.mark.hash @@ -122,7 +122,7 @@ class TestSHA384(object): @pytest.mark.supported( - only_if=lambda backend: backend.hash_supported(hashes.SHA512), + only_if=lambda backend: backend.hash_supported(hashes.SHA512()), skip_message="Does not support SHA512", ) @pytest.mark.hash @@ -135,7 +135,7 @@ class TestSHA512(object): @pytest.mark.supported( - only_if=lambda backend: backend.hash_supported(hashes.RIPEMD160), + only_if=lambda backend: backend.hash_supported(hashes.RIPEMD160()), skip_message="Does not support RIPEMD160", ) @pytest.mark.hash @@ -148,7 +148,7 @@ class TestRIPEMD160(object): @pytest.mark.supported( - only_if=lambda backend: backend.hash_supported(hashes.Whirlpool), + only_if=lambda backend: backend.hash_supported(hashes.Whirlpool()), skip_message="Does not support Whirlpool", ) @pytest.mark.hash @@ -161,7 +161,7 @@ class TestWhirlpool(object): @pytest.mark.supported( - only_if=lambda backend: backend.hash_supported(hashes.MD5), + only_if=lambda backend: backend.hash_supported(hashes.MD5()), skip_message="Does not support MD5", ) @pytest.mark.hash diff --git a/tests/hazmat/primitives/test_hmac.py b/tests/hazmat/primitives/test_hmac.py index 04913af6..dd9cdaab 100644 --- a/tests/hazmat/primitives/test_hmac.py +++ b/tests/hazmat/primitives/test_hmac.py @@ -34,7 +34,7 @@ class UnsupportedDummyHash(object): @pytest.mark.supported( - only_if=lambda backend: backend.hmac_supported(hashes.MD5), + only_if=lambda backend: backend.hmac_supported(hashes.MD5()), skip_message="Does not support MD5", ) @pytest.mark.hmac diff --git a/tests/hazmat/primitives/test_hmac_vectors.py b/tests/hazmat/primitives/test_hmac_vectors.py index c5644459..0792080b 100644 --- a/tests/hazmat/primitives/test_hmac_vectors.py +++ b/tests/hazmat/primitives/test_hmac_vectors.py @@ -22,7 +22,7 @@ from ...utils import load_hash_vectors @pytest.mark.supported( - only_if=lambda backend: backend.hmac_supported(hashes.MD5), + only_if=lambda backend: backend.hmac_supported(hashes.MD5()), skip_message="Does not support MD5", ) @pytest.mark.hmac @@ -38,7 +38,7 @@ class TestHMAC_MD5(object): @pytest.mark.supported( - only_if=lambda backend: backend.hmac_supported(hashes.SHA1), + only_if=lambda backend: backend.hmac_supported(hashes.SHA1()), skip_message="Does not support SHA1", ) @pytest.mark.hmac @@ -54,7 +54,7 @@ class TestHMAC_SHA1(object): @pytest.mark.supported( - only_if=lambda backend: backend.hmac_supported(hashes.SHA224), + only_if=lambda backend: backend.hmac_supported(hashes.SHA224()), skip_message="Does not support SHA224", ) @pytest.mark.hmac @@ -70,7 +70,7 @@ class TestHMAC_SHA224(object): @pytest.mark.supported( - only_if=lambda backend: backend.hmac_supported(hashes.SHA256), + only_if=lambda backend: backend.hmac_supported(hashes.SHA256()), skip_message="Does not support SHA256", ) @pytest.mark.hmac @@ -86,7 +86,7 @@ class TestHMAC_SHA256(object): @pytest.mark.supported( - only_if=lambda backend: backend.hmac_supported(hashes.SHA384), + only_if=lambda backend: backend.hmac_supported(hashes.SHA384()), skip_message="Does not support SHA384", ) @pytest.mark.hmac @@ -102,7 +102,7 @@ class TestHMAC_SHA384(object): @pytest.mark.supported( - only_if=lambda backend: backend.hmac_supported(hashes.SHA512), + only_if=lambda backend: backend.hmac_supported(hashes.SHA512()), skip_message="Does not support SHA512", ) @pytest.mark.hmac @@ -118,7 +118,7 @@ class TestHMAC_SHA512(object): @pytest.mark.supported( - only_if=lambda backend: backend.hmac_supported(hashes.RIPEMD160), + only_if=lambda backend: backend.hmac_supported(hashes.RIPEMD160()), skip_message="Does not support RIPEMD160", ) @pytest.mark.hmac diff --git a/tests/test_utils.py b/tests/test_utils.py index c640367e..e3e53d63 100644 --- a/tests/test_utils.py +++ b/tests/test_utils.py @@ -50,7 +50,7 @@ def test_check_backend_support_skip(): funcargs={"backend": True}) with pytest.raises(pytest.skip.Exception) as exc_info: check_backend_support(item) - assert exc_info.value.args[0] == "Nope" + assert exc_info.value.args[0] == "Nope (True)" def test_check_backend_support_no_skip(): diff --git a/tests/utils.py b/tests/utils.py index beb2ca5d..693a0c8f 100644 --- a/tests/utils.py +++ b/tests/utils.py @@ -28,7 +28,9 @@ def check_backend_support(item): supported = item.keywords.get("supported") if supported and "backend" in item.funcargs: if not supported.kwargs["only_if"](item.funcargs["backend"]): - pytest.skip(supported.kwargs["skip_message"]) + pytest.skip("{0} ({1})".format( + supported.kwargs["skip_message"], item.funcargs["backend"] + )) elif supported: raise ValueError("This mark is only available on methods that take a " "backend") |