Merge pull request #807 from Ayrx/add-backend-check-to-rsa

Added backend check to rsa primitives
diff --git a/cryptography/hazmat/primitives/ciphers/base.py b/cryptography/hazmat/primitives/ciphers/base.py
index d366e4c..2c804ca 100644
--- a/cryptography/hazmat/primitives/ciphers/base.py
+++ b/cryptography/hazmat/primitives/ciphers/base.py
@@ -16,12 +16,18 @@
 from cryptography import utils
 from cryptography.exceptions import (
     AlreadyFinalized, NotYetFinalized, AlreadyUpdated,
-)
+    UnsupportedInterface)
+
+from cryptography.hazmat.backends.interfaces import CipherBackend
 from cryptography.hazmat.primitives import interfaces
 
 
 class Cipher(object):
     def __init__(self, algorithm, mode, backend):
+        if not isinstance(backend, CipherBackend):
+            raise UnsupportedInterface(
+                "Backend object does not implement CipherBackend")
+
         if not isinstance(algorithm, interfaces.CipherAlgorithm):
             raise TypeError("Expected interface of interfaces.CipherAlgorithm")
 
diff --git a/cryptography/hazmat/primitives/hashes.py b/cryptography/hazmat/primitives/hashes.py
index bee188b..409f564 100644
--- a/cryptography/hazmat/primitives/hashes.py
+++ b/cryptography/hazmat/primitives/hashes.py
@@ -16,13 +16,18 @@
 import six
 
 from cryptography import utils
-from cryptography.exceptions import AlreadyFinalized
+from cryptography.exceptions import AlreadyFinalized, UnsupportedInterface
+from cryptography.hazmat.backends.interfaces import HashBackend
 from cryptography.hazmat.primitives import interfaces
 
 
 @utils.register_interface(interfaces.HashContext)
 class Hash(object):
     def __init__(self, algorithm, backend, ctx=None):
+        if not isinstance(backend, HashBackend):
+            raise UnsupportedInterface(
+                "Backend object does not implement HashBackend")
+
         if not isinstance(algorithm, interfaces.HashAlgorithm):
             raise TypeError("Expected instance of interfaces.HashAlgorithm.")
         self.algorithm = algorithm
diff --git a/cryptography/hazmat/primitives/hmac.py b/cryptography/hazmat/primitives/hmac.py
index 76d658a..18cf7f0 100644
--- a/cryptography/hazmat/primitives/hmac.py
+++ b/cryptography/hazmat/primitives/hmac.py
@@ -16,13 +16,21 @@
 import six
 
 from cryptography import utils
-from cryptography.exceptions import AlreadyFinalized, InvalidSignature
+from cryptography.exceptions import (
+    AlreadyFinalized, InvalidSignature, UnsupportedInterface
+)
+
+from cryptography.hazmat.backends.interfaces import HMACBackend
 from cryptography.hazmat.primitives import constant_time, interfaces
 
 
 @utils.register_interface(interfaces.HashContext)
 class HMAC(object):
     def __init__(self, key, algorithm, backend, ctx=None):
+        if not isinstance(backend, HMACBackend):
+            raise UnsupportedInterface(
+                "Backend object does not implement HMACBackend")
+
         if not isinstance(algorithm, interfaces.HashAlgorithm):
             raise TypeError("Expected instance of interfaces.HashAlgorithm.")
         self.algorithm = algorithm
diff --git a/docs/hazmat/primitives/cryptographic-hashes.rst b/docs/hazmat/primitives/cryptographic-hashes.rst
index 627ca7b..b7eee2f 100644
--- a/docs/hazmat/primitives/cryptographic-hashes.rst
+++ b/docs/hazmat/primitives/cryptographic-hashes.rst
@@ -45,6 +45,10 @@
         :class:`~cryptography.hazmat.backends.interfaces.HashBackend`
         provider.
 
+    :raises cryptography.exceptions.UnsupportedInterface: This is raised if the
+        provided ``backend`` does not implement
+        :class:`~cryptography.hazmat.backends.interfaces.HashBackend`
+
     .. method:: update(data)
 
         :param bytes data: The bytes to be hashed.
diff --git a/docs/hazmat/primitives/hmac.rst b/docs/hazmat/primitives/hmac.rst
index 6ca9e16..ce4e880 100644
--- a/docs/hazmat/primitives/hmac.rst
+++ b/docs/hazmat/primitives/hmac.rst
@@ -56,6 +56,10 @@
         :class:`~cryptography.hazmat.backends.interfaces.HMACBackend`
         provider.
 
+    :raises cryptography.exceptions.UnsupportedInterface: This is raised if the
+        provided ``backend`` does not implement
+        :class:`~cryptography.hazmat.backends.interfaces.HMACBackend`
+
     .. method:: update(msg)
 
         :param bytes msg: The bytes to hash and authenticate.
diff --git a/docs/hazmat/primitives/symmetric-encryption.rst b/docs/hazmat/primitives/symmetric-encryption.rst
index 741091b..71a1064 100644
--- a/docs/hazmat/primitives/symmetric-encryption.rst
+++ b/docs/hazmat/primitives/symmetric-encryption.rst
@@ -56,6 +56,10 @@
         :class:`~cryptography.hazmat.backends.interfaces.CipherBackend`
         provider.
 
+    :raises cryptography.exceptions.UnsupportedInterface: This is raised if the
+        provided ``backend`` does not implement
+        :class:`~cryptography.hazmat.backends.interfaces.CipherBackend`
+
     .. method:: encryptor()
 
         :return: An encrypting
diff --git a/tests/hazmat/primitives/test_ciphers.py b/tests/hazmat/primitives/test_ciphers.py
index d9f8353..e1f5dbc 100644
--- a/tests/hazmat/primitives/test_ciphers.py
+++ b/tests/hazmat/primitives/test_ciphers.py
@@ -17,10 +17,15 @@
 
 import pytest
 
+from cryptography.exceptions import UnsupportedInterface
+
+from cryptography.hazmat.primitives import ciphers
 from cryptography.hazmat.primitives.ciphers.algorithms import (
     AES, Camellia, TripleDES, Blowfish, ARC4, CAST5, IDEA
 )
 
+from cryptography.hazmat.primitives.ciphers.modes import ECB
+
 
 class TestAES(object):
     @pytest.mark.parametrize(("key", "keysize"), [
@@ -120,3 +125,10 @@
     def test_invalid_key_size(self):
         with pytest.raises(ValueError):
             IDEA(b"\x00" * 17)
+
+
+def test_invalid_backend():
+    pretend_backend = object()
+
+    with pytest.raises(UnsupportedInterface):
+        ciphers.Cipher(AES(b"AAAAAAAAAAAAAAAA"), ECB, pretend_backend)
diff --git a/tests/hazmat/primitives/test_hashes.py b/tests/hazmat/primitives/test_hashes.py
index fc53d63..d74d1d8 100644
--- a/tests/hazmat/primitives/test_hashes.py
+++ b/tests/hazmat/primitives/test_hashes.py
@@ -20,7 +20,11 @@
 import six
 
 from cryptography import utils
-from cryptography.exceptions import AlreadyFinalized, UnsupportedHash
+from cryptography.exceptions import (
+    AlreadyFinalized, UnsupportedHash, UnsupportedInterface
+)
+
+from cryptography.hazmat.backends.interfaces import HashBackend
 from cryptography.hazmat.primitives import hashes, interfaces
 
 from .utils import generate_base_hash_test
@@ -39,7 +43,11 @@
             m.update(six.u("\u00FC"))
 
     def test_copy_backend_object(self):
-        pretend_backend = pretend.stub()
+        @utils.register_interface(HashBackend)
+        class PretendBackend(object):
+            pass
+
+        pretend_backend = PretendBackend()
         copied_ctx = pretend.stub()
         pretend_ctx = pretend.stub(copy=lambda: copied_ctx)
         h = hashes.Hash(hashes.SHA1(), backend=pretend_backend,
@@ -171,3 +179,10 @@
         digest_size=16,
         block_size=64,
     )
+
+
+def test_invalid_backend():
+    pretend_backend = object()
+
+    with pytest.raises(UnsupportedInterface):
+        hashes.Hash(hashes.SHA1(), pretend_backend)
diff --git a/tests/hazmat/primitives/test_hmac.py b/tests/hazmat/primitives/test_hmac.py
index 88bed52..af177d7 100644
--- a/tests/hazmat/primitives/test_hmac.py
+++ b/tests/hazmat/primitives/test_hmac.py
@@ -21,8 +21,11 @@
 
 from cryptography import utils
 from cryptography.exceptions import (
-    AlreadyFinalized, UnsupportedHash, InvalidSignature
+    AlreadyFinalized, UnsupportedHash, InvalidSignature,
+    UnsupportedInterface
 )
+
+from cryptography.hazmat.backends.interfaces import HMACBackend
 from cryptography.hazmat.primitives import hashes, hmac, interfaces
 
 from .utils import generate_base_hmac_test
@@ -52,8 +55,11 @@
             h.update(six.u("\u00FC"))
 
     def test_copy_backend_object(self):
-        pretend_hmac = pretend.stub()
-        pretend_backend = pretend.stub(hmacs=pretend_hmac)
+        @utils.register_interface(HMACBackend)
+        class PretendBackend(object):
+            pass
+
+        pretend_backend = PretendBackend()
         copied_ctx = pretend.stub()
         pretend_ctx = pretend.stub(copy=lambda: copied_ctx)
         h = hmac.HMAC(b"key", hashes.SHA1(), backend=pretend_backend,
@@ -104,3 +110,10 @@
     def test_unsupported_hash(self, backend):
         with pytest.raises(UnsupportedHash):
             hmac.HMAC(b"key", UnsupportedDummyHash(), backend)
+
+
+def test_invalid_backend():
+    pretend_backend = object()
+
+    with pytest.raises(UnsupportedInterface):
+        hmac.HMAC(b"key", hashes.SHA1(), pretend_backend)