create & use _evp_md_from_algorithm and _evp_md_non_null_from_algorithm (#4542)

* create & use _evp_md_from_algorithm and _evp_md_non_null_from_algorithm

* remove unused import
diff --git a/src/cryptography/hazmat/backends/openssl/backend.py b/src/cryptography/hazmat/backends/openssl/backend.py
index bd414fd..19734a5 100644
--- a/src/cryptography/hazmat/backends/openssl/backend.py
+++ b/src/cryptography/hazmat/backends/openssl/backend.py
@@ -181,7 +181,7 @@
     def create_hmac_ctx(self, key, algorithm):
         return _HMACContext(self, key, algorithm)
 
-    def _build_openssl_digest_name(self, algorithm):
+    def _evp_md_from_algorithm(self, algorithm):
         if algorithm.name == "blake2b" or algorithm.name == "blake2s":
             alg = "{0}{1}".format(
                 algorithm.name, algorithm.digest_size * 8
@@ -189,12 +189,17 @@
         else:
             alg = algorithm.name.encode("ascii")
 
-        return alg
+        evp_md = self._lib.EVP_get_digestbyname(alg)
+        return evp_md
+
+    def _evp_md_non_null_from_algorithm(self, algorithm):
+        evp_md = self._evp_md_from_algorithm(algorithm)
+        self.openssl_assert(evp_md != self._ffi.NULL)
+        return evp_md
 
     def hash_supported(self, algorithm):
-        name = self._build_openssl_digest_name(algorithm)
-        digest = self._lib.EVP_get_digestbyname(name)
-        return digest != self._ffi.NULL
+        evp_md = self._evp_md_from_algorithm(algorithm)
+        return evp_md != self._ffi.NULL
 
     def hmac_supported(self, algorithm):
         return self.hash_supported(algorithm)
@@ -286,9 +291,7 @@
     def derive_pbkdf2_hmac(self, algorithm, length, salt, iterations,
                            key_material):
         buf = self._ffi.new("unsigned char[]", length)
-        evp_md = self._lib.EVP_get_digestbyname(
-            algorithm.name.encode("ascii"))
-        self.openssl_assert(evp_md != self._ffi.NULL)
+        evp_md = self._evp_md_non_null_from_algorithm(algorithm)
         res = self._lib.PKCS5_PBKDF2_HMAC(
             key_material,
             len(key_material),
@@ -685,10 +688,7 @@
             )
 
         # Resolve the signature algorithm.
-        evp_md = self._lib.EVP_get_digestbyname(
-            algorithm.name.encode('ascii')
-        )
-        self.openssl_assert(evp_md != self._ffi.NULL)
+        evp_md = self._evp_md_non_null_from_algorithm(algorithm)
 
         # Create an empty request.
         x509_req = self._lib.X509_REQ_new()
@@ -767,10 +767,7 @@
             )
 
         # Resolve the signature algorithm.
-        evp_md = self._lib.EVP_get_digestbyname(
-            algorithm.name.encode('ascii')
-        )
-        self.openssl_assert(evp_md != self._ffi.NULL)
+        evp_md = self._evp_md_non_null_from_algorithm(algorithm)
 
         # Create an empty certificate.
         x509_cert = self._lib.X509_new()
@@ -875,10 +872,7 @@
                 "MD5 is not a supported hash algorithm for EC/DSA CRLs"
             )
 
-        evp_md = self._lib.EVP_get_digestbyname(
-            algorithm.name.encode('ascii')
-        )
-        self.openssl_assert(evp_md != self._ffi.NULL)
+        evp_md = self._evp_md_non_null_from_algorithm(algorithm)
 
         # Create an empty CRL.
         x509_crl = self._lib.X509_CRL_new()
@@ -1452,9 +1446,7 @@
         self.openssl_assert(ocsp_req != self._ffi.NULL)
         ocsp_req = self._ffi.gc(ocsp_req, self._lib.OCSP_REQUEST_free)
         cert, issuer, algorithm = builder._request
-        evp_md = self._lib.EVP_get_digestbyname(
-            algorithm.name.encode("ascii"))
-        self.openssl_assert(evp_md != self._ffi.NULL)
+        evp_md = self._evp_md_non_null_from_algorithm(algorithm)
         certid = self._lib.OCSP_cert_to_id(
             evp_md, cert._x509, issuer._x509
         )
@@ -1474,10 +1466,9 @@
         basic = self._lib.OCSP_BASICRESP_new()
         self.openssl_assert(basic != self._ffi.NULL)
         basic = self._ffi.gc(basic, self._lib.OCSP_BASICRESP_free)
-        evp_md = self._lib.EVP_get_digestbyname(
-            builder._response._algorithm.name.encode("ascii")
+        evp_md = self._evp_md_non_null_from_algorithm(
+            builder._response._algorithm
         )
-        self.openssl_assert(evp_md != self._ffi.NULL)
         certid = self._lib.OCSP_cert_to_id(
             evp_md, builder._response._cert._x509,
             builder._response._issuer._x509
@@ -1516,8 +1507,7 @@
         )
         self.openssl_assert(res != self._ffi.NULL)
         # okay, now sign the basic structure
-        evp_md = self._lib.EVP_get_digestbyname(algorithm.name.encode("ascii"))
-        self.openssl_assert(evp_md != self._ffi.NULL)
+        evp_md = self._evp_md_non_null_from_algorithm(algorithm)
         responder_cert, responder_encoding = builder._responder_id
         flags = self._lib.OCSP_NOCERTS
         if responder_encoding is ocsp.OCSPResponderEncoding.HASH:
diff --git a/src/cryptography/hazmat/backends/openssl/hashes.py b/src/cryptography/hazmat/backends/openssl/hashes.py
index 92ea53b..c39f57d 100644
--- a/src/cryptography/hazmat/backends/openssl/hashes.py
+++ b/src/cryptography/hazmat/backends/openssl/hashes.py
@@ -22,12 +22,11 @@
             ctx = self._backend._ffi.gc(
                 ctx, self._backend._lib.Cryptography_EVP_MD_CTX_free
             )
-            name = self._backend._build_openssl_digest_name(algorithm)
-            evp_md = self._backend._lib.EVP_get_digestbyname(name)
+            evp_md = self._backend._evp_md_from_algorithm(algorithm)
             if evp_md == self._backend._ffi.NULL:
                 raise UnsupportedAlgorithm(
                     "{0} is not a supported hash on this backend.".format(
-                        name),
+                        algorithm.name),
                     _Reasons.UNSUPPORTED_HASH
                 )
             res = self._backend._lib.EVP_DigestInit_ex(ctx, evp_md,
diff --git a/src/cryptography/hazmat/backends/openssl/hmac.py b/src/cryptography/hazmat/backends/openssl/hmac.py
index 3577f47..99c43f2 100644
--- a/src/cryptography/hazmat/backends/openssl/hmac.py
+++ b/src/cryptography/hazmat/backends/openssl/hmac.py
@@ -25,11 +25,11 @@
             ctx = self._backend._ffi.gc(
                 ctx, self._backend._lib.Cryptography_HMAC_CTX_free
             )
-            name = self._backend._build_openssl_digest_name(algorithm)
-            evp_md = self._backend._lib.EVP_get_digestbyname(name)
+            evp_md = self._backend._evp_md_from_algorithm(algorithm)
             if evp_md == self._backend._ffi.NULL:
                 raise UnsupportedAlgorithm(
-                    "{0} is not a supported hash on this backend".format(name),
+                    "{0} is not a supported hash on this backend".format(
+                        algorithm.name),
                     _Reasons.UNSUPPORTED_HASH
                 )
             res = self._backend._lib.HMAC_Init_ex(
diff --git a/src/cryptography/hazmat/backends/openssl/rsa.py b/src/cryptography/hazmat/backends/openssl/rsa.py
index 9a7bfaa..00f5e37 100644
--- a/src/cryptography/hazmat/backends/openssl/rsa.py
+++ b/src/cryptography/hazmat/backends/openssl/rsa.py
@@ -92,14 +92,11 @@
         isinstance(padding, OAEP) and
         backend._lib.Cryptography_HAS_RSA_OAEP_MD
     ):
-        mgf1_md = backend._lib.EVP_get_digestbyname(
-            padding._mgf._algorithm.name.encode("ascii"))
-        backend.openssl_assert(mgf1_md != backend._ffi.NULL)
+        mgf1_md = backend._evp_md_non_null_from_algorithm(
+            padding._mgf._algorithm)
         res = backend._lib.EVP_PKEY_CTX_set_rsa_mgf1_md(pkey_ctx, mgf1_md)
         backend.openssl_assert(res > 0)
-        oaep_md = backend._lib.EVP_get_digestbyname(
-            padding._algorithm.name.encode("ascii"))
-        backend.openssl_assert(oaep_md != backend._ffi.NULL)
+        oaep_md = backend._evp_md_non_null_from_algorithm(padding._algorithm)
         res = backend._lib.EVP_PKEY_CTX_set_rsa_oaep_md(pkey_ctx, oaep_md)
         backend.openssl_assert(res > 0)
 
@@ -189,15 +186,21 @@
 
 def _rsa_sig_setup(backend, padding, algorithm, key, data, init_func):
     padding_enum = _rsa_sig_determine_padding(backend, key, padding, algorithm)
-    evp_md = backend._lib.EVP_get_digestbyname(algorithm.name.encode("ascii"))
-    backend.openssl_assert(evp_md != backend._ffi.NULL)
+    evp_md = backend._evp_md_non_null_from_algorithm(algorithm)
     pkey_ctx = backend._lib.EVP_PKEY_CTX_new(key._evp_pkey, backend._ffi.NULL)
     backend.openssl_assert(pkey_ctx != backend._ffi.NULL)
     pkey_ctx = backend._ffi.gc(pkey_ctx, backend._lib.EVP_PKEY_CTX_free)
     res = init_func(pkey_ctx)
     backend.openssl_assert(res == 1)
     res = backend._lib.EVP_PKEY_CTX_set_signature_md(pkey_ctx, evp_md)
-    backend.openssl_assert(res > 0)
+    if res == 0:
+        backend._consume_errors()
+        raise UnsupportedAlgorithm(
+            "{0} is not supported by this backend for RSA signing.".format(
+                algorithm.name
+            ),
+            _Reasons.UNSUPPORTED_HASH
+        )
     res = backend._lib.EVP_PKEY_CTX_set_rsa_padding(pkey_ctx, padding_enum)
     backend.openssl_assert(res > 0)
     if isinstance(padding, PSS):
@@ -206,10 +209,8 @@
         )
         backend.openssl_assert(res > 0)
 
-        mgf1_md = backend._lib.EVP_get_digestbyname(
-            padding._mgf._algorithm.name.encode("ascii")
-        )
-        backend.openssl_assert(mgf1_md != backend._ffi.NULL)
+        mgf1_md = backend._evp_md_non_null_from_algorithm(
+            padding._mgf._algorithm)
         res = backend._lib.EVP_PKEY_CTX_set_rsa_mgf1_md(pkey_ctx, mgf1_md)
         backend.openssl_assert(res > 0)
 
diff --git a/tests/hazmat/primitives/test_rsa.py b/tests/hazmat/primitives/test_rsa.py
index 4d56bcd..ffe6259 100644
--- a/tests/hazmat/primitives/test_rsa.py
+++ b/tests/hazmat/primitives/test_rsa.py
@@ -635,6 +635,24 @@
         public_key.verify(signature, message, pss, hashes.SHA1())
 
     @pytest.mark.supported(
+        only_if=lambda backend: backend.hash_supported(
+            hashes.BLAKE2s(digest_size=32)),
+        skip_message="Does not support BLAKE2s",
+    )
+    @pytest.mark.supported(
+        only_if=lambda backend: backend.rsa_padding_supported(
+            padding.PSS(mgf=padding.MGF1(hashes.SHA1()), salt_length=0)
+        ),
+        skip_message="Does not support PSS."
+    )
+    def test_unsupported_hash(self, backend):
+        private_key = RSA_KEY_512.private_key(backend)
+        message = b"one little message"
+        pss = padding.PSS(mgf=padding.MGF1(hashes.SHA256()), salt_length=0)
+        with raises_unsupported_algorithm(_Reasons.UNSUPPORTED_HASH):
+            private_key.sign(message, pss, hashes.BLAKE2s(32))
+
+    @pytest.mark.supported(
         only_if=lambda backend: backend.rsa_padding_supported(
             padding.PSS(mgf=padding.MGF1(hashes.SHA1()), salt_length=0)
         ),