make signature and verification contexts error better re: prehashed (#3658)

* make signature and verification contexts error better re: prehashed

* code review feedback
diff --git a/docs/hazmat/primitives/asymmetric/interfaces.rst b/docs/hazmat/primitives/asymmetric/interfaces.rst
index c4f176c..a5dbc67 100644
--- a/docs/hazmat/primitives/asymmetric/interfaces.rst
+++ b/docs/hazmat/primitives/asymmetric/interfaces.rst
@@ -9,6 +9,12 @@
 
     .. versionadded:: 0.2
 
+    .. note::
+
+        :class:`~cryptography.hazmat.primitives.asymmetric.utils.Prehashed`
+        is not supported by this context. You must use the ``sign`` method
+        on the private key object.
+
     .. method:: update(data)
 
         :param bytes data: The data you want to sign.
@@ -22,6 +28,12 @@
 
     .. versionadded:: 0.2
 
+    .. note::
+
+        :class:`~cryptography.hazmat.primitives.asymmetric.utils.Prehashed`
+        is not supported by this context. You must use the ``verify`` method
+        on the public key object.
+
     .. method:: update(data)
 
         :param bytes data: The data you wish to verify using the signature.
diff --git a/src/cryptography/hazmat/backends/openssl/dsa.py b/src/cryptography/hazmat/backends/openssl/dsa.py
index e2ed3df..c222325 100644
--- a/src/cryptography/hazmat/backends/openssl/dsa.py
+++ b/src/cryptography/hazmat/backends/openssl/dsa.py
@@ -7,7 +7,7 @@
 from cryptography import utils
 from cryptography.exceptions import InvalidSignature
 from cryptography.hazmat.backends.openssl.utils import (
-    _calculate_digest_and_algorithm
+    _calculate_digest_and_algorithm, _check_not_prehashed
 )
 from cryptography.hazmat.primitives import hashes, serialization
 from cryptography.hazmat.primitives.asymmetric import (
@@ -121,6 +121,7 @@
     key_size = utils.read_only_property("_key_size")
 
     def signer(self, signature_algorithm):
+        _check_not_prehashed(signature_algorithm)
         return _DSASignatureContext(self._backend, self, signature_algorithm)
 
     def private_numbers(self):
@@ -210,6 +211,7 @@
         if not isinstance(signature, bytes):
             raise TypeError("signature must be bytes.")
 
+        _check_not_prehashed(signature_algorithm)
         return _DSAVerificationContext(
             self._backend, self, signature, signature_algorithm
         )
diff --git a/src/cryptography/hazmat/backends/openssl/ec.py b/src/cryptography/hazmat/backends/openssl/ec.py
index 3a81f91..b70735d 100644
--- a/src/cryptography/hazmat/backends/openssl/ec.py
+++ b/src/cryptography/hazmat/backends/openssl/ec.py
@@ -9,7 +9,7 @@
     InvalidSignature, UnsupportedAlgorithm, _Reasons
 )
 from cryptography.hazmat.backends.openssl.utils import (
-    _calculate_digest_and_algorithm
+    _calculate_digest_and_algorithm, _check_not_prehashed
 )
 from cryptography.hazmat.primitives import hashes, serialization
 from cryptography.hazmat.primitives.asymmetric import (
@@ -141,6 +141,7 @@
 
     def signer(self, signature_algorithm):
         _check_signature_algorithm(signature_algorithm)
+        _check_not_prehashed(signature_algorithm.algorithm)
         return _ECDSASignatureContext(
             self._backend, self, signature_algorithm.algorithm
         )
@@ -244,6 +245,7 @@
             raise TypeError("signature must be bytes.")
 
         _check_signature_algorithm(signature_algorithm)
+        _check_not_prehashed(signature_algorithm.algorithm)
         return _ECDSAVerificationContext(
             self._backend, self, signature, signature_algorithm.algorithm
         )
diff --git a/src/cryptography/hazmat/backends/openssl/rsa.py b/src/cryptography/hazmat/backends/openssl/rsa.py
index 0a37572..fdde458 100644
--- a/src/cryptography/hazmat/backends/openssl/rsa.py
+++ b/src/cryptography/hazmat/backends/openssl/rsa.py
@@ -11,7 +11,7 @@
     InvalidSignature, UnsupportedAlgorithm, _Reasons
 )
 from cryptography.hazmat.backends.openssl.utils import (
-    _calculate_digest_and_algorithm
+    _calculate_digest_and_algorithm, _check_not_prehashed
 )
 from cryptography.hazmat.primitives import hashes
 from cryptography.hazmat.primitives.asymmetric import (
@@ -378,6 +378,7 @@
     key_size = utils.read_only_property("_key_size")
 
     def signer(self, padding, algorithm):
+        _check_not_prehashed(algorithm)
         return _RSASignatureContext(self._backend, self, padding, algorithm)
 
     def decrypt(self, ciphertext, padding):
@@ -474,6 +475,7 @@
         if not isinstance(signature, bytes):
             raise TypeError("signature must be bytes.")
 
+        _check_not_prehashed(algorithm)
         return _RSAVerificationContext(
             self._backend, self, signature, padding, algorithm
         )
diff --git a/src/cryptography/hazmat/backends/openssl/utils.py b/src/cryptography/hazmat/backends/openssl/utils.py
index e8b4a30..f71a62a 100644
--- a/src/cryptography/hazmat/backends/openssl/utils.py
+++ b/src/cryptography/hazmat/backends/openssl/utils.py
@@ -23,3 +23,11 @@
         )
 
     return (data, algorithm)
+
+
+def _check_not_prehashed(signature_algorithm):
+    if isinstance(signature_algorithm, Prehashed):
+        raise TypeError(
+            "Prehashed is only supported in the sign and verify methods. "
+            "It cannot be used with signer or verifier."
+        )
diff --git a/tests/hazmat/primitives/test_dsa.py b/tests/hazmat/primitives/test_dsa.py
index 8160ad9..6ea0577 100644
--- a/tests/hazmat/primitives/test_dsa.py
+++ b/tests/hazmat/primitives/test_dsa.py
@@ -638,6 +638,18 @@
         with pytest.raises(ValueError):
             public_key.verify(b"\x00" * 128, digest, prehashed_alg)
 
+    def test_prehashed_unsupported_in_signer_ctx(self, backend):
+        private_key = DSA_KEY_1024.private_key(backend)
+        with pytest.raises(TypeError):
+            private_key.signer(Prehashed(hashes.SHA1()))
+
+    def test_prehashed_unsupported_in_verifier_ctx(self, backend):
+        public_key = DSA_KEY_1024.private_key(backend).public_key()
+        with pytest.raises(TypeError):
+            public_key.verifier(
+                b"0" * 64, Prehashed(hashes.SHA1())
+            )
+
 
 @pytest.mark.requires_backend_interface(interface=DSABackend)
 class TestDSASignature(object):
diff --git a/tests/hazmat/primitives/test_ec.py b/tests/hazmat/primitives/test_ec.py
index d5db52a..d917704 100644
--- a/tests/hazmat/primitives/test_ec.py
+++ b/tests/hazmat/primitives/test_ec.py
@@ -629,6 +629,22 @@
                 b"\x00" * 32, data, ec.ECDSA(Prehashed(hashes.SHA256()))
             )
 
+    def test_prehashed_unsupported_in_signer_ctx(self, backend):
+        _skip_curve_unsupported(backend, ec.SECP256R1())
+        private_key = ec.generate_private_key(ec.SECP256R1(), backend)
+        with pytest.raises(TypeError):
+            private_key.signer(ec.ECDSA(Prehashed(hashes.SHA1())))
+
+    def test_prehashed_unsupported_in_verifier_ctx(self, backend):
+        _skip_curve_unsupported(backend, ec.SECP256R1())
+        private_key = ec.generate_private_key(ec.SECP256R1(), backend)
+        public_key = private_key.public_key()
+        with pytest.raises(TypeError):
+            public_key.verifier(
+                b"0" * 64,
+                ec.ECDSA(Prehashed(hashes.SHA1()))
+            )
+
 
 class TestECNumbersEquality(object):
     def test_public_numbers_eq(self):
diff --git a/tests/hazmat/primitives/test_rsa.py b/tests/hazmat/primitives/test_rsa.py
index cbb9be6..7ce2746 100644
--- a/tests/hazmat/primitives/test_rsa.py
+++ b/tests/hazmat/primitives/test_rsa.py
@@ -531,6 +531,35 @@
         with pytest.raises(ValueError):
             private_key.sign(digest, pss, prehashed_alg)
 
+    @pytest.mark.supported(
+        only_if=lambda backend: backend.rsa_padding_supported(
+            padding.PKCS1v15()
+        ),
+        skip_message="Does not support PKCS1v1.5."
+    )
+    def test_prehashed_unsupported_in_signer_ctx(self, backend):
+        private_key = RSA_KEY_512.private_key(backend)
+        with pytest.raises(TypeError):
+            private_key.signer(
+                padding.PKCS1v15(),
+                asym_utils.Prehashed(hashes.SHA1())
+            )
+
+    @pytest.mark.supported(
+        only_if=lambda backend: backend.rsa_padding_supported(
+            padding.PKCS1v15()
+        ),
+        skip_message="Does not support PKCS1v1.5."
+    )
+    def test_prehashed_unsupported_in_verifier_ctx(self, backend):
+        public_key = RSA_KEY_512.private_key(backend).public_key()
+        with pytest.raises(TypeError):
+            public_key.verifier(
+                b"0" * 64,
+                padding.PKCS1v15(),
+                asym_utils.Prehashed(hashes.SHA1())
+            )
+
 
 @pytest.mark.requires_backend_interface(interface=RSABackend)
 class TestRSAVerification(object):