Merge branch 'master' into setup-install-extension

Conflicts:
	cryptography/hazmat/bindings/openssl/binding.py
diff --git a/cryptography/hazmat/bindings/openssl/binding.py b/cryptography/hazmat/bindings/openssl/binding.py
index ccda368..4f6b99a 100644
--- a/cryptography/hazmat/bindings/openssl/binding.py
+++ b/cryptography/hazmat/bindings/openssl/binding.py
@@ -13,9 +13,7 @@
 
 from __future__ import absolute_import, division, print_function
 
-import sys
-
-import cffi
+from cryptography.hazmat.bindings.utils import build_ffi
 
 _OSX_PRE_INCLUDE = """
 #ifdef __APPLE__
@@ -39,20 +37,6 @@
 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,59 +76,6 @@
         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"],
-            ext_package="cryptography",
-        )
-
-        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.ffi, cls.lib = build_ffi(cls._module_prefix, cls._modules,
+                                     _OSX_PRE_INCLUDE, _OSX_POST_INCLUDE,
+                                     ["crypto", "ssl"])
diff --git a/cryptography/hazmat/bindings/utils.py b/cryptography/hazmat/bindings/utils.py
new file mode 100644
index 0000000..9e1d393
--- /dev/null
+++ b/cryptography/hazmat/bindings/utils.py
@@ -0,0 +1,88 @@
+# 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
diff --git a/cryptography/hazmat/primitives/ciphers/base.py b/cryptography/hazmat/primitives/ciphers/base.py
index 1da0802..d366e4c 100644
--- a/cryptography/hazmat/primitives/ciphers/base.py
+++ b/cryptography/hazmat/primitives/ciphers/base.py
@@ -25,6 +25,9 @@
         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 ab8501c..739f23d 100644
--- a/cryptography/hazmat/primitives/ciphers/modes.py
+++ b/cryptography/hazmat/primitives/ciphers/modes.py
@@ -25,11 +25,20 @@
     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 @@
     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 @@
     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 @@
     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 @@
     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 @@
 
         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 e87c9ca..7a6bf3e 100644
--- a/cryptography/hazmat/primitives/interfaces.py
+++ b/cryptography/hazmat/primitives/interfaces.py
@@ -47,6 +47,13 @@
         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/hazmat/primitives/interfaces.rst b/docs/hazmat/primitives/interfaces.rst
index 361b723..edb24cd 100644
--- a/docs/hazmat/primitives/interfaces.rst
+++ b/docs/hazmat/primitives/interfaces.rst
@@ -67,6 +67,18 @@
         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
 
diff --git a/tests/hazmat/backends/test_openssl.py b/tests/hazmat/backends/test_openssl.py
index 22cfbe7..ad39959 100644
--- a/tests/hazmat/backends/test_openssl.py
+++ b/tests/hazmat/backends/test_openssl.py
@@ -27,6 +27,9 @@
 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/primitives/test_block.py b/tests/hazmat/primitives/test_block.py
index 30cf1d6..f758ffa 100644
--- a/tests/hazmat/primitives/test_block.py
+++ b/tests/hazmat/primitives/test_block.py
@@ -35,6 +35,9 @@
 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 @@
         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 13ffc3f..ca97fc1 100644
--- a/tests/hazmat/primitives/test_hash_vectors.py
+++ b/tests/hazmat/primitives/test_hash_vectors.py
@@ -24,7 +24,7 @@
 
 
 @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 @@
 
 
 @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 @@
 
 
 @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 @@
 
 
 @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 @@
 
 
 @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 @@
 
 
 @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 @@
 
 
 @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 @@
 
 
 @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 c907ef6..9ca2fee 100644
--- a/tests/hazmat/primitives/test_hashes.py
+++ b/tests/hazmat/primitives/test_hashes.py
@@ -70,7 +70,7 @@
 
 
 @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 @@
 
 
 @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 @@
 
 
 @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 @@
 
 
 @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 @@
 
 
 @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 @@
 
 
 @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 @@
 
 
 @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 @@
 
 
 @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 04913af..dd9cdaa 100644
--- a/tests/hazmat/primitives/test_hmac.py
+++ b/tests/hazmat/primitives/test_hmac.py
@@ -34,7 +34,7 @@
 
 
 @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 c564445..0792080 100644
--- a/tests/hazmat/primitives/test_hmac_vectors.py
+++ b/tests/hazmat/primitives/test_hmac_vectors.py
@@ -22,7 +22,7 @@
 
 
 @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 @@
 
 
 @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 @@
 
 
 @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 @@
 
 
 @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 @@
 
 
 @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 @@
 
 
 @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 @@
 
 
 @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