bpo-37630: Use SHA3 and SHAKE XOF from OpenSSL (GH-16049)



OpenSSL 1.1.1 comes with SHA3 and SHAKE builtin.

Signed-off-by: Christian Heimes <christian@python.org>

Automerge-Triggered-By: @tiran
diff --git a/Lib/hashlib.py b/Lib/hashlib.py
index 56873b7..0f81de0 100644
--- a/Lib/hashlib.py
+++ b/Lib/hashlib.py
@@ -71,8 +71,6 @@
 __builtin_constructor_cache = {}
 
 __block_openssl_constructor = {
-    'sha3_224', 'sha3_256', 'sha3_384', 'sha3_512',
-    'shake_128', 'shake_256',
     'blake2b', 'blake2s',
 }
 
@@ -125,6 +123,8 @@
         # Prefer our blake2 and sha3 implementation.
         return __get_builtin_constructor(name)
     try:
+        # MD5, SHA1, and SHA2 are in all supported OpenSSL versions
+        # SHA3/shake are available in OpenSSL 1.1.1+
         f = getattr(_hashlib, 'openssl_' + name)
         # Allow the C module to raise ValueError.  The function will be
         # defined but the hash not actually available thanks to OpenSSL.
diff --git a/Lib/test/test_hashlib.py b/Lib/test/test_hashlib.py
index f9fe7e3..b901468 100644
--- a/Lib/test/test_hashlib.py
+++ b/Lib/test/test_hashlib.py
@@ -27,9 +27,10 @@
 py_hashlib = import_fresh_module('hashlib', blocked=['_hashlib'])
 
 try:
-    from _hashlib import HASH
+    from _hashlib import HASH, HASHXOF
 except ImportError:
     HASH = None
+    HASHXOF = None
 
 try:
     import _blake2
@@ -254,6 +255,9 @@
             h = cons()
             if h.name not in self.shakes:
                 continue
+            if HASH is not None and isinstance(h, HASH):
+                # _hashopenssl's take a size_t
+                continue
             for digest in h.digest, h.hexdigest:
                 self.assertRaises(ValueError, digest, -10)
                 for length in large_sizes:
@@ -860,6 +864,18 @@
     def test_get_fips_mode(self):
         self.assertIsInstance(c_hashlib.get_fips_mode(), int)
 
+    @unittest.skipUnless(HASH is not None, 'need _hashlib')
+    def test_internal_types(self):
+        # internal types like _hashlib.HASH are not constructable
+        with self.assertRaisesRegex(
+            TypeError, "cannot create 'HASH' instance"
+        ):
+            HASH()
+        with self.assertRaisesRegex(
+            TypeError, "cannot create 'HASHXOF' instance"
+        ):
+            HASHXOF()
+
 
 class KDFTests(unittest.TestCase):