Blob Blame History Raw
From 85855cf6fdc076dee6cd884c8b46d491458c431e Mon Sep 17 00:00:00 2001
From: "Miss Islington (bot)"
 <31488909+miss-islington@users.noreply.github.com>
Date: Thu, 17 Oct 2019 20:48:42 -0700
Subject: [PATCH 01/43] bpo-33604: Raise TypeError on missing hmac arg.
 (GH-16805)

Also updates the documentation to clarify the situation surrounding
the digestmod parameter that is required despite its position in the
argument list as of 3.8.0 as well as removing old python2 era
references to "binary strings".

We indavertently had this raise ValueError in 3.8.0 for the missing
arg.  This is not considered an API change as no reasonable code would
be catching this missing argument error in order to handle it.
(cherry picked from commit f33c57d5c780da1500619f548585792bb5b750ee)

Co-authored-by: Gregory P. Smith <greg@krypto.org>
---
 Doc/library/hmac.rst                          |  8 +--
 Lib/hmac.py                                   | 53 ++++++++++---------
 Lib/test/test_hmac.py                         |  7 ++-
 .../2019-10-15-09-47-40.bpo-33604.J12cWT.rst  |  3 ++
 4 files changed, 43 insertions(+), 28 deletions(-)
 create mode 100644 Misc/NEWS.d/next/Library/2019-10-15-09-47-40.bpo-33604.J12cWT.rst

diff --git a/Doc/library/hmac.rst b/Doc/library/hmac.rst
index dc994b07c3..57ac8bb161 100644
--- a/Doc/library/hmac.rst
+++ b/Doc/library/hmac.rst
@@ -14,12 +14,13 @@
 This module implements the HMAC algorithm as described by :rfc:`2104`.
 
 
-.. function:: new(key, msg=None, digestmod=None)
+.. function:: new(key, msg=None, digestmod='')
 
    Return a new hmac object.  *key* is a bytes or bytearray object giving the
    secret key.  If *msg* is present, the method call ``update(msg)`` is made.
    *digestmod* is the digest name, digest constructor or module for the HMAC
-   object to use. It supports any name suitable to :func:`hashlib.new`.
+   object to use.  It may be any name suitable to :func:`hashlib.new`.
+   Despite its argument position, it is required.
 
    .. versionchanged:: 3.4
       Parameter *key* can be a bytes or bytearray object.
@@ -28,6 +29,8 @@ This module implements the HMAC algorithm as described by :rfc:`2104`.
 
    .. deprecated-removed:: 3.4 3.8
       MD5 as implicit default digest for *digestmod* is deprecated.
+      The digestmod parameter is now required.  Pass it as a keyword
+      argument to avoid awkwardness when you do not have an initial msg.
 
 
 .. function:: digest(key, msg, digest)
@@ -127,7 +130,6 @@ This module also provides the following helper function:
       a timing attack could theoretically reveal information about the
       types and lengths of *a* and *b*—but not their values.
 
-
    .. versionadded:: 3.3
 
 
diff --git a/Lib/hmac.py b/Lib/hmac.py
index 890eaba08e..b769876e6f 100644
--- a/Lib/hmac.py
+++ b/Lib/hmac.py
@@ -1,4 +1,4 @@
-"""HMAC (Keyed-Hashing for Message Authentication) Python module.
+"""HMAC (Keyed-Hashing for Message Authentication) module.
 
 Implements the HMAC algorithm as described by RFC 2104.
 """
@@ -30,23 +30,25 @@ class HMAC:
     """
     blocksize = 64  # 512-bit HMAC; can be changed in subclasses.
 
-    def __init__(self, key, msg = None, digestmod = None):
+    def __init__(self, key, msg=None, digestmod=''):
         """Create a new HMAC object.
 
-        key:       key for the keyed hash object.
-        msg:       Initial input for the hash, if provided.
-        digestmod: Required.  A module supporting PEP 247.  *OR*
-                   A hashlib constructor returning a new hash object.  *OR*
-                   A hash name suitable for hashlib.new().
+        key: bytes or buffer, key for the keyed hash object.
+        msg: bytes or buffer, Initial input for the hash or None.
+        digestmod: A hash name suitable for hashlib.new(). *OR*
+                   A hashlib constructor returning a new hash object. *OR*
+                   A module supporting PEP 247.
 
-        Note: key and msg must be a bytes or bytearray objects.
+                   Required as of 3.8, despite its position after the optional
+                   msg argument.  Passing it as a keyword argument is
+                   recommended, though not required for legacy API reasons.
         """
 
         if not isinstance(key, (bytes, bytearray)):
             raise TypeError("key: expected bytes or bytearray, but got %r" % type(key).__name__)
 
-        if digestmod is None:
-            raise ValueError('`digestmod` is required.')
+        if not digestmod:
+            raise TypeError("Missing required parameter 'digestmod'.")
 
         if callable(digestmod):
             self.digest_cons = digestmod
@@ -90,8 +92,7 @@ class HMAC:
         return "hmac-" + self.inner.name
 
     def update(self, msg):
-        """Update this hashing object with the string msg.
-        """
+        """Feed data from msg into this hashing object."""
         self.inner.update(msg)
 
     def copy(self):
@@ -119,7 +120,7 @@ class HMAC:
     def digest(self):
         """Return the hash value of this hashing object.
 
-        This returns a string containing 8-bit data.  The object is
+        This returns the hmac value as bytes.  The object is
         not altered in any way by this function; you can continue
         updating the object after calling this function.
         """
@@ -132,30 +133,34 @@ class HMAC:
         h = self._current()
         return h.hexdigest()
 
-def new(key, msg = None, digestmod = None):
+def new(key, msg=None, digestmod=''):
     """Create a new hashing object and return it.
 
-    key: The starting key for the hash.
-    msg: if available, will immediately be hashed into the object's starting
-    state.
+    key: bytes or buffer, The starting key for the hash.
+    msg: bytes or buffer, Initial input for the hash, or None.
+    digestmod: A hash name suitable for hashlib.new(). *OR*
+               A hashlib constructor returning a new hash object. *OR*
+               A module supporting PEP 247.
+
+               Required as of 3.8, despite its position after the optional
+               msg argument.  Passing it as a keyword argument is
+               recommended, though not required for legacy API reasons.
 
-    You can now feed arbitrary strings into the object using its update()
+    You can now feed arbitrary bytes into the object using its update()
     method, and can ask for the hash value at any time by calling its digest()
-    method.
+    or hexdigest() methods.
     """
     return HMAC(key, msg, digestmod)
 
 
 def digest(key, msg, digest):
-    """Fast inline implementation of HMAC
+    """Fast inline implementation of HMAC.
 
-    key:    key for the keyed hash object.
-    msg:    input message
+    key: bytes or buffer, The key for the keyed hash object.
+    msg: bytes or buffer, Input message.
     digest: A hash name suitable for hashlib.new() for best performance. *OR*
             A hashlib constructor returning a new hash object. *OR*
             A module supporting PEP 247.
-
-    Note: key and msg must be a bytes or bytearray objects.
     """
     if (_hashopenssl is not None and
             isinstance(digest, str) and digest in _openssl_md_meths):
diff --git a/Lib/test/test_hmac.py b/Lib/test/test_hmac.py
index 1bbf201727..ea00367c80 100644
--- a/Lib/test/test_hmac.py
+++ b/Lib/test/test_hmac.py
@@ -312,10 +312,15 @@ class TestVectorsTestCase(unittest.TestCase):
                 self.fail('Expected warning about small block_size')
 
     def test_with_digestmod_no_default(self):
-        with self.assertRaises(ValueError):
+        """The digestmod parameter is required as of Python 3.8."""
+        with self.assertRaisesRegex(TypeError, r'required.*digestmod'):
             key = b"\x0b" * 16
             data = b"Hi There"
             hmac.HMAC(key, data, digestmod=None)
+        with self.assertRaisesRegex(TypeError, r'required.*digestmod'):
+            hmac.new(key, data)
+        with self.assertRaisesRegex(TypeError, r'required.*digestmod'):
+            hmac.HMAC(key, msg=data, digestmod='')
 
 
 class ConstructorTestCase(unittest.TestCase):
diff --git a/Misc/NEWS.d/next/Library/2019-10-15-09-47-40.bpo-33604.J12cWT.rst b/Misc/NEWS.d/next/Library/2019-10-15-09-47-40.bpo-33604.J12cWT.rst
new file mode 100644
index 0000000000..fbd73003cf
--- /dev/null
+++ b/Misc/NEWS.d/next/Library/2019-10-15-09-47-40.bpo-33604.J12cWT.rst
@@ -0,0 +1,3 @@
+Fixed `hmac.new` and `hmac.HMAC` to raise TypeError instead of ValueError
+when the digestmod parameter, now required in 3.8, is omitted.  Also
+clarified the hmac module documentation and docstrings.
-- 
2.25.4


From f01bee1d24524c80d446f702e8b8ff054a583064 Mon Sep 17 00:00:00 2001
From: "Miss Islington (bot)"
 <31488909+miss-islington@users.noreply.github.com>
Date: Thu, 5 Dec 2019 08:51:30 -0800
Subject: [PATCH 02/43] [3.8] bpo-38270: Fix indentation of test_hmac
 assertions (GH-17446) (GH-17450)

Since https://github.com/python/cpython/commit/c64a1a61e6fc542cada40eb069a239317e1af36e two assertions were indented and thus ignored when running test_hmac.

This PR fixes it. As the change is quite trivial I didn't add a NEWS entry.


https://bugs.python.org/issue38270
(cherry picked from commit 894331838b256412c95d54051ec46a1cb96f52e7)


Co-authored-by: stratakis <cstratak@redhat.com>


https://bugs.python.org/issue38270



Automerge-Triggered-By: @tiran
---
 Lib/test/test_hmac.py | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/Lib/test/test_hmac.py b/Lib/test/test_hmac.py
index ea00367c80..23c108f6e3 100644
--- a/Lib/test/test_hmac.py
+++ b/Lib/test/test_hmac.py
@@ -367,7 +367,7 @@ class ConstructorTestCase(unittest.TestCase):
                           digestmod="sha256")
         except Exception:
             self.fail("Constructor call with bytearray arguments raised exception.")
-            self.assertEqual(h.hexdigest(), self.expected)
+        self.assertEqual(h.hexdigest(), self.expected)
 
     @requires_hashdigest('sha256')
     def test_with_memoryview_msg(self):
@@ -375,7 +375,7 @@ class ConstructorTestCase(unittest.TestCase):
             h = hmac.HMAC(b"key", memoryview(b"hash this!"), digestmod="sha256")
         except Exception:
             self.fail("Constructor call with memoryview msg raised exception.")
-            self.assertEqual(h.hexdigest(), self.expected)
+        self.assertEqual(h.hexdigest(), self.expected)
 
     @requires_hashdigest('sha256')
     def test_withmodule(self):
-- 
2.25.4


From 480c5e0c1fd8ed871f54b124528b35e570839a09 Mon Sep 17 00:00:00 2001
From: Petr Viktorin <pviktori@redhat.com>
Date: Thu, 25 Jul 2019 16:19:52 +0200
Subject: [PATCH 03/43] Expose OpenSSL FIPS_mode() as hashlib.get_fips_mode()

---
 Lib/hashlib.py                  |  5 +++++
 Modules/_hashopenssl.c          | 37 +++++++++++++++++++++++++++++++++
 Modules/clinic/_hashopenssl.c.h | 25 +++++++++++++++++++++-
 3 files changed, 66 insertions(+), 1 deletion(-)

diff --git a/Lib/hashlib.py b/Lib/hashlib.py
index 56873b7278..63ae8368ab 100644
--- a/Lib/hashlib.py
+++ b/Lib/hashlib.py
@@ -243,6 +243,11 @@ try:
 except ImportError:
     pass
 
+try:
+    from _hashlib import get_fips_mode
+except ImportError:
+    pass
+
 
 for __func_name in __always_supported:
     # try them all, some may not work due to the OpenSSL
diff --git a/Modules/_hashopenssl.c b/Modules/_hashopenssl.c
index 1513e4e35e..43a69c73d1 100644
--- a/Modules/_hashopenssl.c
+++ b/Modules/_hashopenssl.c
@@ -26,6 +26,9 @@
 #include <openssl/objects.h>
 #include "openssl/err.h"
 
+/* Expose FIPS_mode */
+#include <openssl/crypto.h>
+
 #if (OPENSSL_VERSION_NUMBER < 0x10100000L) || defined(LIBRESSL_VERSION_NUMBER)
 /* OpenSSL < 1.1.0 */
 #define EVP_MD_CTX_new EVP_MD_CTX_create
@@ -1068,12 +1071,46 @@ generate_hash_name_list(void)
     return state.set;
 }
 
+/*[clinic input]
+_hashlib.get_fips_mode
+
+Determine the OpenSSL FIPS mode of operation.
+
+Effectively any non-zero return value indicates FIPS mode;
+values other than 1 may have additional significance.
+
+See OpenSSL documentation for the FIPS_mode() function for details.
+[clinic start generated code]*/
+
+static PyObject *
+_hashlib_get_fips_mode_impl(PyObject *module)
+/*[clinic end generated code: output=ad8a7793310d3f98 input=f42a2135df2a5e11]*/
+
+{
+    int result = FIPS_mode();
+    if (result == 0) {
+        // "If the library was built without support of the FIPS Object Module,
+        // then the function will return 0 with an error code of
+        // CRYPTO_R_FIPS_MODE_NOT_SUPPORTED (0x0f06d065)."
+        // But 0 is also a valid result value.
+
+        unsigned long errcode = ERR_peek_last_error();
+        if (errcode) {
+            _setException(PyExc_ValueError);
+            return NULL;
+        }
+    }
+    return PyLong_FromLong(result);
+}
+
+
 /* List of functions exported by this module */
 
 static struct PyMethodDef EVP_functions[] = {
     EVP_NEW_METHODDEF
     PBKDF2_HMAC_METHODDEF
     _HASHLIB_SCRYPT_METHODDEF
+    _HASHLIB_GET_FIPS_MODE_METHODDEF
     _HASHLIB_HMAC_DIGEST_METHODDEF
     _HASHLIB_OPENSSL_MD5_METHODDEF
     _HASHLIB_OPENSSL_SHA1_METHODDEF
diff --git a/Modules/clinic/_hashopenssl.c.h b/Modules/clinic/_hashopenssl.c.h
index 9aaea47e83..30fd8a9796 100644
--- a/Modules/clinic/_hashopenssl.c.h
+++ b/Modules/clinic/_hashopenssl.c.h
@@ -620,7 +620,30 @@ exit:
     return return_value;
 }
 
+PyDoc_STRVAR(_hashlib_get_fips_mode__doc__,
+"get_fips_mode($module, /)\n"
+"--\n"
+"\n"
+"Determine the OpenSSL FIPS mode of operation.\n"
+"\n"
+"Effectively any non-zero return value indicates FIPS mode;\n"
+"values other than 1 may have additional significance.\n"
+"\n"
+"See OpenSSL documentation for the FIPS_mode() function for details.");
+
+#define _HASHLIB_GET_FIPS_MODE_METHODDEF    \
+    {"get_fips_mode", (PyCFunction)_hashlib_get_fips_mode, METH_NOARGS, _hashlib_get_fips_mode__doc__},
+
+static PyObject *
+_hashlib_get_fips_mode_impl(PyObject *module);
+
+static PyObject *
+_hashlib_get_fips_mode(PyObject *module, PyObject *Py_UNUSED(ignored))
+{
+    return _hashlib_get_fips_mode_impl(module);
+}
+
 #ifndef _HASHLIB_SCRYPT_METHODDEF
     #define _HASHLIB_SCRYPT_METHODDEF
 #endif /* !defined(_HASHLIB_SCRYPT_METHODDEF) */
-/*[clinic end generated code: output=38c2637f67e9bb79 input=a9049054013a1b77]*/
+/*[clinic end generated code: output=5467006d93e7479e input=a9049054013a1b77]*/
-- 
2.25.4


From ad854d7f0fb26aea7dff9b1da50de9e81fb3ba5c Mon Sep 17 00:00:00 2001
From: Charalampos Stratakis <cstratak@redhat.com>
Date: Thu, 25 Jul 2019 17:04:06 +0200
Subject: [PATCH 04/43] Use python's fall backs for the crypto it implements
 only if we are not in FIPS mode

---
 Lib/hashlib.py           | 207 +++++++++++++++------------------------
 Lib/test/test_hashlib.py |   1 +
 2 files changed, 81 insertions(+), 127 deletions(-)

diff --git a/Lib/hashlib.py b/Lib/hashlib.py
index 63ae8368ab..1bcfdf9f7f 100644
--- a/Lib/hashlib.py
+++ b/Lib/hashlib.py
@@ -68,7 +68,6 @@ __all__ = __always_supported + ('new', 'algorithms_guaranteed',
                                 'algorithms_available', 'pbkdf2_hmac')
 
 
-__builtin_constructor_cache = {}
 
 __block_openssl_constructor = {
     'sha3_224', 'sha3_256', 'sha3_384', 'sha3_512',
@@ -76,54 +75,64 @@ __block_openssl_constructor = {
     'blake2b', 'blake2s',
 }
 
-def __get_builtin_constructor(name):
-    cache = __builtin_constructor_cache
-    constructor = cache.get(name)
-    if constructor is not None:
-        return constructor
-    try:
-        if name in {'SHA1', 'sha1'}:
-            import _sha1
-            cache['SHA1'] = cache['sha1'] = _sha1.sha1
-        elif name in {'MD5', 'md5'}:
-            import _md5
-            cache['MD5'] = cache['md5'] = _md5.md5
-        elif name in {'SHA256', 'sha256', 'SHA224', 'sha224'}:
-            import _sha256
-            cache['SHA224'] = cache['sha224'] = _sha256.sha224
-            cache['SHA256'] = cache['sha256'] = _sha256.sha256
-        elif name in {'SHA512', 'sha512', 'SHA384', 'sha384'}:
-            import _sha512
-            cache['SHA384'] = cache['sha384'] = _sha512.sha384
-            cache['SHA512'] = cache['sha512'] = _sha512.sha512
-        elif name in {'blake2b', 'blake2s'}:
-            import _blake2
-            cache['blake2b'] = _blake2.blake2b
-            cache['blake2s'] = _blake2.blake2s
-        elif name in {'sha3_224', 'sha3_256', 'sha3_384', 'sha3_512'}:
-            import _sha3
-            cache['sha3_224'] = _sha3.sha3_224
-            cache['sha3_256'] = _sha3.sha3_256
-            cache['sha3_384'] = _sha3.sha3_384
-            cache['sha3_512'] = _sha3.sha3_512
-        elif name in {'shake_128', 'shake_256'}:
-            import _sha3
-            cache['shake_128'] = _sha3.shake_128
-            cache['shake_256'] = _sha3.shake_256
-    except ImportError:
-        pass  # no extension module, this hash is unsupported.
-
-    constructor = cache.get(name)
-    if constructor is not None:
-        return constructor
-
-    raise ValueError('unsupported hash type ' + name)
+try:
+    from _hashlib import get_fips_mode
+except ImportError:
+    def get_fips_mode():
+        return 0
+
+if not get_fips_mode():
+    __builtin_constructor_cache = {}
+
+    def __get_builtin_constructor(name):
+        cache = __builtin_constructor_cache
+        constructor = cache.get(name)
+        if constructor is not None:
+            return constructor
+        try:
+            if name in {'SHA1', 'sha1'}:
+                import _sha1
+                cache['SHA1'] = cache['sha1'] = _sha1.sha1
+            elif name in {'MD5', 'md5'}:
+                import _md5
+                cache['MD5'] = cache['md5'] = _md5.md5
+            elif name in {'SHA256', 'sha256', 'SHA224', 'sha224'}:
+                import _sha256
+                cache['SHA224'] = cache['sha224'] = _sha256.sha224
+                cache['SHA256'] = cache['sha256'] = _sha256.sha256
+            elif name in {'SHA512', 'sha512', 'SHA384', 'sha384'}:
+                import _sha512
+                cache['SHA384'] = cache['sha384'] = _sha512.sha384
+                cache['SHA512'] = cache['sha512'] = _sha512.sha512
+            elif name in {'blake2b', 'blake2s'}:
+                import _blake2
+                cache['blake2b'] = _blake2.blake2b
+                cache['blake2s'] = _blake2.blake2s
+            elif name in {'sha3_224', 'sha3_256', 'sha3_384', 'sha3_512'}:
+                import _sha3
+                cache['sha3_224'] = _sha3.sha3_224
+                cache['sha3_256'] = _sha3.sha3_256
+                cache['sha3_384'] = _sha3.sha3_384
+                cache['sha3_512'] = _sha3.sha3_512
+            elif name in {'shake_128', 'shake_256'}:
+                import _sha3
+                cache['shake_128'] = _sha3.shake_128
+                cache['shake_256'] = _sha3.shake_256
+        except ImportError:
+            pass  # no extension module, this hash is unsupported.
+
+        constructor = cache.get(name)
+        if constructor is not None:
+            return constructor
+
+        raise ValueError('unsupported hash type ' + name)
 
 
 def __get_openssl_constructor(name):
-    if name in __block_openssl_constructor:
-        # Prefer our blake2 and sha3 implementation.
-        return __get_builtin_constructor(name)
+    if not get_fips_mode():
+        if name in __block_openssl_constructor:
+            # Prefer our blake2 and sha3 implementation.
+            return __get_builtin_constructor(name)
     try:
         f = getattr(_hashlib, 'openssl_' + name)
         # Allow the C module to raise ValueError.  The function will be
@@ -132,27 +141,31 @@ def __get_openssl_constructor(name):
         # Use the C function directly (very fast)
         return f
     except (AttributeError, ValueError):
+        if get_fips_mode():
+            raise
         return __get_builtin_constructor(name)
 
 
-def __py_new(name, data=b'', **kwargs):
-    """new(name, data=b'', **kwargs) - Return a new hashing object using the
-    named algorithm; optionally initialized with data (which must be
-    a bytes-like object).
-    """
-    return __get_builtin_constructor(name)(data, **kwargs)
+if not get_fips_mode():
+    def __py_new(name, data=b'', **kwargs):
+        """new(name, data=b'', **kwargs) - Return a new hashing object using the
+        named algorithm; optionally initialized with data (which must be
+        a bytes-like object).
+        """
+        return __get_builtin_constructor(name)(data, **kwargs)
 
 
 def __hash_new(name, data=b'', **kwargs):
     """new(name, data=b'') - Return a new hashing object using the named algorithm;
     optionally initialized with data (which must be a bytes-like object).
     """
-    if name in __block_openssl_constructor:
-        # Prefer our blake2 and sha3 implementation
-        # OpenSSL 1.1.0 comes with a limited implementation of blake2b/s.
-        # It does neither support keyed blake2 nor advanced features like
-        # salt, personal, tree hashing or SSE.
-        return __get_builtin_constructor(name)(data, **kwargs)
+    if not get_fips_mode():
+        if name in __block_openssl_constructor:
+            # Prefer our blake2 and sha3 implementation
+            # OpenSSL 1.1.0 comes with a limited implementation of blake2b/s.
+            # It does neither support keyed blake2 nor advanced features like
+            # salt, personal, tree hashing or SSE.
+            return __get_builtin_constructor(name)(data, **kwargs)
     try:
         return _hashlib.new(name, data)
     except ValueError:
@@ -160,6 +173,8 @@ def __hash_new(name, data=b'', **kwargs):
         # hash, try using our builtin implementations.
         # This allows for SHA224/256 and SHA384/512 support even though
         # the OpenSSL library prior to 0.9.8 doesn't provide them.
+        if get_fips_mode():
+            raise
         return __get_builtin_constructor(name)(data)
 
 
@@ -170,72 +185,13 @@ try:
     algorithms_available = algorithms_available.union(
             _hashlib.openssl_md_meth_names)
 except ImportError:
+    if get_fips_mode():
+        raise
     new = __py_new
     __get_hash = __get_builtin_constructor
 
-try:
-    # OpenSSL's PKCS5_PBKDF2_HMAC requires OpenSSL 1.0+ with HMAC and SHA
-    from _hashlib import pbkdf2_hmac
-except ImportError:
-    _trans_5C = bytes((x ^ 0x5C) for x in range(256))
-    _trans_36 = bytes((x ^ 0x36) for x in range(256))
-
-    def pbkdf2_hmac(hash_name, password, salt, iterations, dklen=None):
-        """Password based key derivation function 2 (PKCS #5 v2.0)
-
-        This Python implementations based on the hmac module about as fast
-        as OpenSSL's PKCS5_PBKDF2_HMAC for short passwords and much faster
-        for long passwords.
-        """
-        if not isinstance(hash_name, str):
-            raise TypeError(hash_name)
-
-        if not isinstance(password, (bytes, bytearray)):
-            password = bytes(memoryview(password))
-        if not isinstance(salt, (bytes, bytearray)):
-            salt = bytes(memoryview(salt))
-
-        # Fast inline HMAC implementation
-        inner = new(hash_name)
-        outer = new(hash_name)
-        blocksize = getattr(inner, 'block_size', 64)
-        if len(password) > blocksize:
-            password = new(hash_name, password).digest()
-        password = password + b'\x00' * (blocksize - len(password))
-        inner.update(password.translate(_trans_36))
-        outer.update(password.translate(_trans_5C))
-
-        def prf(msg, inner=inner, outer=outer):
-            # PBKDF2_HMAC uses the password as key. We can re-use the same
-            # digest objects and just update copies to skip initialization.
-            icpy = inner.copy()
-            ocpy = outer.copy()
-            icpy.update(msg)
-            ocpy.update(icpy.digest())
-            return ocpy.digest()
-
-        if iterations < 1:
-            raise ValueError(iterations)
-        if dklen is None:
-            dklen = outer.digest_size
-        if dklen < 1:
-            raise ValueError(dklen)
-
-        dkey = b''
-        loop = 1
-        from_bytes = int.from_bytes
-        while len(dkey) < dklen:
-            prev = prf(salt + loop.to_bytes(4, 'big'))
-            # endianness doesn't matter here as long to / from use the same
-            rkey = int.from_bytes(prev, 'big')
-            for i in range(iterations - 1):
-                prev = prf(prev)
-                # rkey = rkey ^ prev
-                rkey ^= from_bytes(prev, 'big')
-            loop += 1
-            dkey += rkey.to_bytes(inner.digest_size, 'big')
-
-        return dkey[:dklen]
+# OpenSSL's PKCS5_PBKDF2_HMAC requires OpenSSL 1.0+ with HMAC and SHA
+from _hashlib import pbkdf2_hmac
 
 try:
     # OpenSSL's scrypt requires OpenSSL 1.1+
@@ -243,11 +199,6 @@ try:
 except ImportError:
     pass
 
-try:
-    from _hashlib import get_fips_mode
-except ImportError:
-    pass
-
 
 for __func_name in __always_supported:
     # try them all, some may not work due to the OpenSSL
@@ -261,4 +212,6 @@ for __func_name in __always_supported:
 
 # Cleanup locals()
 del __always_supported, __func_name, __get_hash
-del __py_new, __hash_new, __get_openssl_constructor
+del __hash_new, __get_openssl_constructor
+if not get_fips_mode():
+    del __py_new
diff --git a/Lib/test/test_hashlib.py b/Lib/test/test_hashlib.py
index 8b53d23ef5..e9abcbb929 100644
--- a/Lib/test/test_hashlib.py
+++ b/Lib/test/test_hashlib.py
@@ -945,6 +945,7 @@ class KDFTests(unittest.TestCase):
             iterations=1, dklen=None)
         self.assertEqual(out, self.pbkdf2_results['sha1'][0][0])
 
+    @unittest.skip("The python implementation of pbkdf2_hmac has been removed")
     def test_pbkdf2_hmac_py(self):
         self._test_pbkdf2_hmac(py_hashlib.pbkdf2_hmac)
 
-- 
2.25.4


From 351fa613d2e194a7fe5c1f63bc89cbaa340deca5 Mon Sep 17 00:00:00 2001
From: Petr Viktorin <pviktori@redhat.com>
Date: Thu, 25 Jul 2019 17:19:06 +0200
Subject: [PATCH 05/43] Disable Python's hash implementations in FIPS mode,
 forcing OpenSSL

---
 Include/_hashopenssl.h         | 66 ++++++++++++++++++++++++++++++++++
 Modules/_blake2/blake2b_impl.c |  5 +++
 Modules/_blake2/blake2module.c |  3 ++
 Modules/_blake2/blake2s_impl.c |  5 +++
 Modules/_hashopenssl.c         | 37 +------------------
 Modules/_sha3/sha3module.c     |  5 +++
 setup.py                       | 48 +++++++++++++------------
 7 files changed, 110 insertions(+), 59 deletions(-)
 create mode 100644 Include/_hashopenssl.h

diff --git a/Include/_hashopenssl.h b/Include/_hashopenssl.h
new file mode 100644
index 0000000000..a726c0d3fb
--- /dev/null
+++ b/Include/_hashopenssl.h
@@ -0,0 +1,66 @@
+#ifndef Py_HASHOPENSSL_H
+#define Py_HASHOPENSSL_H
+
+#include "Python.h"
+#include <openssl/crypto.h>
+#include <openssl/err.h>
+
+/* LCOV_EXCL_START */
+static PyObject *
+_setException(PyObject *exc)
+{
+    unsigned long errcode;
+    const char *lib, *func, *reason;
+
+    errcode = ERR_peek_last_error();
+    if (!errcode) {
+        PyErr_SetString(exc, "unknown reasons");
+        return NULL;
+    }
+    ERR_clear_error();
+
+    lib = ERR_lib_error_string(errcode);
+    func = ERR_func_error_string(errcode);
+    reason = ERR_reason_error_string(errcode);
+
+    if (lib && func) {
+        PyErr_Format(exc, "[%s: %s] %s", lib, func, reason);
+    }
+    else if (lib) {
+        PyErr_Format(exc, "[%s] %s", lib, reason);
+    }
+    else {
+        PyErr_SetString(exc, reason);
+    }
+    return NULL;
+}
+/* LCOV_EXCL_STOP */
+
+
+__attribute__((__unused__))
+static int
+_Py_hashlib_fips_error(char *name) {
+    int result = FIPS_mode();
+    if (result == 0) {
+        // "If the library was built without support of the FIPS Object Module,
+        // then the function will return 0 with an error code of
+        // CRYPTO_R_FIPS_MODE_NOT_SUPPORTED (0x0f06d065)."
+        // But 0 is also a valid result value.
+
+        unsigned long errcode = ERR_peek_last_error();
+        if (errcode) {
+            _setException(PyExc_ValueError);
+            return 1;
+        }
+        return 0;
+    }
+    PyErr_Format(PyExc_ValueError, "%s is not available in FIPS mode",
+                 name);
+    return 1;
+}
+
+#define FAIL_RETURN_IN_FIPS_MODE(name) do { \
+    if (_Py_hashlib_fips_error(name)) return NULL; \
+} while (0)
+
+#endif  // !Py_HASHOPENSSL_H
diff --git a/Modules/_blake2/blake2b_impl.c b/Modules/_blake2/blake2b_impl.c
index edab31ea22..1daf5c38e2 100644
--- a/Modules/_blake2/blake2b_impl.c
+++ b/Modules/_blake2/blake2b_impl.c
@@ -14,6 +14,7 @@
  */
 
 #include "Python.h"
+#include "_hashopenssl.h"
 #include "pystrhex.h"
 #include "pythread.h"
 
@@ -96,6 +97,8 @@ py_blake2b_new_impl(PyTypeObject *type, PyObject *data, int digest_size,
     BLAKE2bObject *self = NULL;
     Py_buffer buf;
 
+    FAIL_RETURN_IN_FIPS_MODE("_blake2");
+
     self = new_BLAKE2bObject(type);
     if (self == NULL) {
         goto error;
@@ -274,6 +277,8 @@ _blake2_blake2b_update(BLAKE2bObject *self, PyObject *data)
 {
     Py_buffer buf;
 
+    FAIL_RETURN_IN_FIPS_MODE("_blake2");
+
     GET_BUFFER_VIEW_OR_ERROUT(data, &buf);
 
     if (self->lock == NULL && buf.len >= HASHLIB_GIL_MINSIZE)
diff --git a/Modules/_blake2/blake2module.c b/Modules/_blake2/blake2module.c
index e2a3d420d4..817b716568 100644
--- a/Modules/_blake2/blake2module.c
+++ b/Modules/_blake2/blake2module.c
@@ -9,6 +9,7 @@
  */
 
 #include "Python.h"
+#include "_hashopenssl.h"
 
 #include "impl/blake2.h"
 
@@ -57,6 +58,8 @@ PyInit__blake2(void)
     PyObject *m;
     PyObject *d;
 
+    FAIL_RETURN_IN_FIPS_MODE("blake2");
+
     m = PyModule_Create(&blake2_module);
     if (m == NULL)
         return NULL;
diff --git a/Modules/_blake2/blake2s_impl.c b/Modules/_blake2/blake2s_impl.c
index ef2f7e1980..389711abf1 100644
--- a/Modules/_blake2/blake2s_impl.c
+++ b/Modules/_blake2/blake2s_impl.c
@@ -14,6 +14,7 @@
  */
 
 #include "Python.h"
+#include "_hashopenssl.h"
 #include "pystrhex.h"
 #include "pythread.h"
 
@@ -96,6 +97,8 @@ py_blake2s_new_impl(PyTypeObject *type, PyObject *data, int digest_size,
     BLAKE2sObject *self = NULL;
     Py_buffer buf;
 
+    FAIL_RETURN_IN_FIPS_MODE("_blake2");
+
     self = new_BLAKE2sObject(type);
     if (self == NULL) {
         goto error;
@@ -274,6 +277,8 @@ _blake2_blake2s_update(BLAKE2sObject *self, PyObject *data)
 {
     Py_buffer buf;
 
+    FAIL_RETURN_IN_FIPS_MODE("_blake2");
+
     GET_BUFFER_VIEW_OR_ERROUT(data, &buf);
 
     if (self->lock == NULL && buf.len >= HASHLIB_GIL_MINSIZE)
diff --git a/Modules/_hashopenssl.c b/Modules/_hashopenssl.c
index 43a69c73d1..661ceaa198 100644
--- a/Modules/_hashopenssl.c
+++ b/Modules/_hashopenssl.c
@@ -17,6 +17,7 @@
 #include "structmember.h"
 #include "hashlib.h"
 #include "pystrhex.h"
+#include "_hashopenssl.h"
 
 
 /* EVP is the preferred interface to hashing in OpenSSL */
@@ -24,10 +25,6 @@
 #include <openssl/hmac.h>
 /* We use the object interface to discover what hashes OpenSSL supports. */
 #include <openssl/objects.h>
-#include "openssl/err.h"
-
-/* Expose FIPS_mode */
-#include <openssl/crypto.h>
 
 #if (OPENSSL_VERSION_NUMBER < 0x10100000L) || defined(LIBRESSL_VERSION_NUMBER)
 /* OpenSSL < 1.1.0 */
@@ -65,38 +62,6 @@ class _hashlib.HASH "EVPobject *" "&EVPtype"
 [clinic start generated code]*/
 /*[clinic end generated code: output=da39a3ee5e6b4b0d input=a881a5092eecad28]*/
 
-
-/* LCOV_EXCL_START */
-static PyObject *
-_setException(PyObject *exc)
-{
-    unsigned long errcode;
-    const char *lib, *func, *reason;
-
-    errcode = ERR_peek_last_error();
-    if (!errcode) {
-        PyErr_SetString(exc, "unknown reasons");
-        return NULL;
-    }
-    ERR_clear_error();
-
-    lib = ERR_lib_error_string(errcode);
-    func = ERR_func_error_string(errcode);
-    reason = ERR_reason_error_string(errcode);
-
-    if (lib && func) {
-        PyErr_Format(exc, "[%s: %s] %s", lib, func, reason);
-    }
-    else if (lib) {
-        PyErr_Format(exc, "[%s] %s", lib, reason);
-    }
-    else {
-        PyErr_SetString(exc, reason);
-    }
-    return NULL;
-}
-/* LCOV_EXCL_STOP */
-
 static PyObject*
 py_digest_name(const EVP_MD *md)
 {
diff --git a/Modules/_sha3/sha3module.c b/Modules/_sha3/sha3module.c
index c1fb6185e2..34d09b45d9 100644
--- a/Modules/_sha3/sha3module.c
+++ b/Modules/_sha3/sha3module.c
@@ -18,6 +18,7 @@
 #include "Python.h"
 #include "pystrhex.h"
 #include "../hashlib.h"
+#include "_hashopenssl.h"
 
 /* **************************************************************************
  *                          SHA-3 (Keccak) and SHAKE
@@ -160,6 +161,7 @@ static PyTypeObject SHAKE256type;
 static SHA3object *
 newSHA3object(PyTypeObject *type)
 {
+    FAIL_RETURN_IN_FIPS_MODE("_sha3");
     SHA3object *newobj;
     newobj = (SHA3object *)PyObject_New(SHA3object, type);
     if (newobj == NULL) {
@@ -173,6 +175,7 @@ newSHA3object(PyTypeObject *type)
 static PyObject *
 py_sha3_new(PyTypeObject *type, PyObject *args, PyObject *kwargs)
 {
+    FAIL_RETURN_IN_FIPS_MODE("_sha3");
     SHA3object *self = NULL;
     Py_buffer buf = {NULL, NULL};
     HashReturn res;
@@ -704,6 +707,8 @@ PyInit__sha3(void)
 {
     PyObject *m = NULL;
 
+    FAIL_RETURN_IN_FIPS_MODE("_sha3");
+
     if ((m = PyModule_Create(&_SHA3module)) == NULL) {
         return NULL;
     }
diff --git a/setup.py b/setup.py
index 20d7f35652..0066006772 100644
--- a/setup.py
+++ b/setup.py
@@ -1688,7 +1688,6 @@ class PyBuildExt(build_ext):
     def detect_modules(self):
         self.configure_compiler()
         self.init_inc_lib_dirs()
-
         self.detect_simple_extensions()
         if TEST_EXTENSIONS:
             self.detect_test_extensions()
@@ -2187,7 +2186,7 @@ class PyBuildExt(build_ext):
                            sources=sources,
                            depends=depends))
 
-    def detect_openssl_hashlib(self):
+    def detect_openssl_args(self):
         # Detect SSL support for the socket module (via _ssl)
         config_vars = sysconfig.get_config_vars()
 
@@ -2208,7 +2207,7 @@ class PyBuildExt(build_ext):
         if not openssl_libs:
             # libssl and libcrypto not found
             self.missing.extend(['_ssl', '_hashlib'])
-            return None, None
+            raise ValueError('Cannot build for RHEL without OpenSSL')
 
         # Find OpenSSL includes
         ssl_incs = find_file(
@@ -2216,7 +2215,7 @@ class PyBuildExt(build_ext):
         )
         if ssl_incs is None:
             self.missing.extend(['_ssl', '_hashlib'])
-            return None, None
+            raise ValueError('Cannot build for RHEL without OpenSSL')
 
         # OpenSSL 1.0.2 uses Kerberos for KRB5 ciphers
         krb5_h = find_file(
@@ -2226,12 +2225,23 @@ class PyBuildExt(build_ext):
         if krb5_h:
             ssl_incs.extend(krb5_h)
 
+
+        ssl_args = {
+            'include_dirs': openssl_includes,
+            'library_dirs': openssl_libdirs,
+            'libraries': ['ssl', 'crypto'],
+        }
+
+        return ssl_args
+
+    def detect_openssl_hashlib(self):
+
+        config_vars = sysconfig.get_config_vars()
+
         if config_vars.get("HAVE_X509_VERIFY_PARAM_SET1_HOST"):
             self.add(Extension(
                 '_ssl', ['_ssl.c'],
-                include_dirs=openssl_includes,
-                library_dirs=openssl_libdirs,
-                libraries=openssl_libs,
+                **self.detect_openssl_args(),
                 depends=['socketmodule.h', '_ssl/debughelpers.c'])
             )
         else:
@@ -2239,22 +2249,12 @@ class PyBuildExt(build_ext):
 
         self.add(Extension('_hashlib', ['_hashopenssl.c'],
                            depends=['hashlib.h'],
-                           include_dirs=openssl_includes,
-                           library_dirs=openssl_libdirs,
-                           libraries=openssl_libs))
+                           **self.detect_openssl_args()) )
 
     def detect_hash_builtins(self):
-        # We always compile these even when OpenSSL is available (issue #14693).
-        # It's harmless and the object code is tiny (40-50 KiB per module,
-        # only loaded when actually used).
-        self.add(Extension('_sha256', ['sha256module.c'],
-                           depends=['hashlib.h']))
-        self.add(Extension('_sha512', ['sha512module.c'],
-                           depends=['hashlib.h']))
-        self.add(Extension('_md5', ['md5module.c'],
-                           depends=['hashlib.h']))
-        self.add(Extension('_sha1', ['sha1module.c'],
-                           depends=['hashlib.h']))
+        # RHEL: Always force OpenSSL for md5, sha1, sha256, sha512;
+        # don't build Python's implementations.
+        # sha3 and blake2 have extra functionality, so do build those:
 
         blake2_deps = glob(os.path.join(self.srcdir,
                                         'Modules/_blake2/impl/*'))
@@ -2264,14 +2264,16 @@ class PyBuildExt(build_ext):
                            ['_blake2/blake2module.c',
                             '_blake2/blake2b_impl.c',
                             '_blake2/blake2s_impl.c'],
-                           depends=blake2_deps))
+                            **self.detect_openssl_args(),
+                            depends=blake2_deps))
 
         sha3_deps = glob(os.path.join(self.srcdir,
                                       'Modules/_sha3/kcp/*'))
         sha3_deps.append('hashlib.h')
         self.add(Extension('_sha3',
                            ['_sha3/sha3module.c'],
-                           depends=sha3_deps))
+                           **self.detect_openssl_args(),
+                           depends=sha3_deps + ['hashlib.h']))
 
     def detect_nis(self):
         if MS_WINDOWS or CYGWIN or HOST_PLATFORM == 'qnx6':
-- 
2.25.4


From 502fab3354771128a7b18a4e117cf09327803a6c Mon Sep 17 00:00:00 2001
From: Charalampos Stratakis <cstratak@redhat.com>
Date: Thu, 12 Dec 2019 16:58:31 +0100
Subject: [PATCH 06/43] Expose all hashes available to OpenSSL

---
 Modules/_hashopenssl.c          | 150 ++++++++++++++++
 Modules/clinic/_hashopenssl.c.h | 298 +++++++++++++++++++++++++++++++-
 2 files changed, 447 insertions(+), 1 deletion(-)

diff --git a/Modules/_hashopenssl.c b/Modules/_hashopenssl.c
index 661ceaa198..625e2d2e8f 100644
--- a/Modules/_hashopenssl.c
+++ b/Modules/_hashopenssl.c
@@ -190,6 +190,12 @@ py_digest_by_name(const char *name)
         else if (!strcmp(name, "blake2b512")) {
             digest = EVP_blake2b512();
         }
+        else if (!strcmp(name, "blake2s")) {
+            digest = EVP_blake2s256();
+        }
+        else if (!strcmp(name, "blake2b")) {
+            digest = EVP_blake2b512();
+        }
 #endif
     }
 
@@ -708,6 +714,142 @@ _hashlib_openssl_sha512_impl(PyObject *module, PyObject *data_obj)
     return EVP_fast_new(module, data_obj, EVP_sha512());
 }
 
+/*[clinic input]
+_hashlib.openssl_blake2b
+
+    string as data_obj: object(py_default="b''") = NULL
+
+Returns a blake2b hash object; optionally initialized with a string
+
+[clinic start generated code]*/
+
+static PyObject *
+_hashlib_openssl_blake2b_impl(PyObject *module, PyObject *data_obj)
+/*[clinic end generated code: output=0d65acd1d9bb5e3f input=d9e6f84fa97e630d]*/
+
+{
+    return EVP_fast_new(module, data_obj, EVP_blake2b512());
+}
+
+/*[clinic input]
+_hashlib.openssl_blake2s
+
+    string as data_obj: object(py_default="b''") = NULL
+
+Returns a blake2s hash object; optionally initialized with a string
+
+[clinic start generated code]*/
+
+static PyObject *
+_hashlib_openssl_blake2s_impl(PyObject *module, PyObject *data_obj)
+/*[clinic end generated code: output=0f1330138041ec22 input=f1aec29465fc49c6]*/
+
+{
+    return EVP_fast_new(module, data_obj, EVP_blake2s256());
+}
+
+/*[clinic input]
+_hashlib.openssl_sha3_224
+
+    string as data_obj: object(py_default="b''") = NULL
+
+Returns a sha3_224 hash object; optionally initialized with a string
+
+[clinic start generated code]*/
+
+static PyObject *
+_hashlib_openssl_sha3_224_impl(PyObject *module, PyObject *data_obj)
+/*[clinic end generated code: output=e3817bed6ecafc20 input=adc74bf14410af70]*/
+
+{
+    return EVP_fast_new(module, data_obj, EVP_sha3_224());
+}
+
+/*[clinic input]
+_hashlib.openssl_sha3_256
+
+    string as data_obj: object(py_default="b''") = NULL
+
+Returns a sha3_256 hash object; optionally initialized with a string
+
+[clinic start generated code]*/
+
+static PyObject *
+_hashlib_openssl_sha3_256_impl(PyObject *module, PyObject *data_obj)
+/*[clinic end generated code: output=9c15fac1ce09cd62 input=2922c3e78ab8bd2d]*/
+
+{
+    return EVP_fast_new(module, data_obj, EVP_sha3_256());
+}
+
+/*[clinic input]
+_hashlib.openssl_sha3_384
+
+    string as data_obj: object(py_default="b''") = NULL
+
+Returns a sha3_384 hash object; optionally initialized with a string
+
+[clinic start generated code]*/
+
+static PyObject *
+_hashlib_openssl_sha3_384_impl(PyObject *module, PyObject *data_obj)
+/*[clinic end generated code: output=0923a782b9b81a40 input=742b499c372c8316]*/
+
+{
+    return EVP_fast_new(module, data_obj, EVP_sha3_384());
+}
+
+/*[clinic input]
+_hashlib.openssl_sha3_512
+
+    string as data_obj: object(py_default="b''") = NULL
+
+Returns a sha3-512 hash object; optionally initialized with a string
+
+[clinic start generated code]*/
+
+static PyObject *
+_hashlib_openssl_sha3_512_impl(PyObject *module, PyObject *data_obj)
+/*[clinic end generated code: output=34bbe194704dbce4 input=46383f88e59a0385]*/
+
+{
+    return EVP_fast_new(module, data_obj, EVP_sha3_512());
+}
+
+/*[clinic input]
+_hashlib.openssl_shake_128
+
+    string as data_obj: object(py_default="b''") = NULL
+
+Returns a shake_128 hash object; optionally initialized with a string
+
+[clinic start generated code]*/
+
+static PyObject *
+_hashlib_openssl_shake_128_impl(PyObject *module, PyObject *data_obj)
+/*[clinic end generated code: output=a6ea5917ce65ef10 input=f256751eb810fdaa]*/
+
+{
+    return EVP_fast_new(module, data_obj, EVP_shake128());
+}
+
+/*[clinic input]
+_hashlib.openssl_shake_256
+
+    string as data_obj: object(py_default="b''") = NULL
+
+Returns a shake_256 hash object; optionally initialized with a string
+
+[clinic start generated code]*/
+
+static PyObject *
+_hashlib_openssl_shake_256_impl(PyObject *module, PyObject *data_obj)
+/*[clinic end generated code: output=c91aaa96b000e186 input=d1331313db34116c]*/
+
+{
+    return EVP_fast_new(module, data_obj, EVP_shake256());
+}
+
 
 /*[clinic input]
 _hashlib.pbkdf2_hmac as pbkdf2_hmac
@@ -1083,6 +1225,14 @@ static struct PyMethodDef EVP_functions[] = {
     _HASHLIB_OPENSSL_SHA256_METHODDEF
     _HASHLIB_OPENSSL_SHA384_METHODDEF
     _HASHLIB_OPENSSL_SHA512_METHODDEF
+    _HASHLIB_OPENSSL_BLAKE2B_METHODDEF
+    _HASHLIB_OPENSSL_BLAKE2S_METHODDEF
+    _HASHLIB_OPENSSL_SHA3_224_METHODDEF
+    _HASHLIB_OPENSSL_SHA3_256_METHODDEF
+    _HASHLIB_OPENSSL_SHA3_384_METHODDEF
+    _HASHLIB_OPENSSL_SHA3_512_METHODDEF
+    _HASHLIB_OPENSSL_SHAKE_128_METHODDEF
+    _HASHLIB_OPENSSL_SHAKE_256_METHODDEF
     {NULL,      NULL}            /* Sentinel */
 };
 
diff --git a/Modules/clinic/_hashopenssl.c.h b/Modules/clinic/_hashopenssl.c.h
index 30fd8a9796..e96a752e27 100644
--- a/Modules/clinic/_hashopenssl.c.h
+++ b/Modules/clinic/_hashopenssl.c.h
@@ -331,6 +331,302 @@ exit:
     return return_value;
 }
 
+PyDoc_STRVAR(_hashlib_openssl_blake2b__doc__,
+"openssl_blake2b($module, /, string=b\'\')\n"
+"--\n"
+"\n"
+"Returns a blake2b hash object; optionally initialized with a string");
+
+#define _HASHLIB_OPENSSL_BLAKE2B_METHODDEF    \
+    {"openssl_blake2b", (PyCFunction)(void(*)(void))_hashlib_openssl_blake2b, METH_FASTCALL|METH_KEYWORDS, _hashlib_openssl_blake2b__doc__},
+
+static PyObject *
+_hashlib_openssl_blake2b_impl(PyObject *module, PyObject *data_obj);
+
+static PyObject *
+_hashlib_openssl_blake2b(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames)
+{
+    PyObject *return_value = NULL;
+    static const char * const _keywords[] = {"string", NULL};
+    static _PyArg_Parser _parser = {NULL, _keywords, "openssl_blake2b", 0};
+    PyObject *argsbuf[1];
+    Py_ssize_t noptargs = nargs + (kwnames ? PyTuple_GET_SIZE(kwnames) : 0) - 0;
+    PyObject *data_obj = NULL;
+
+    args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 0, 1, 0, argsbuf);
+    if (!args) {
+        goto exit;
+    }
+    if (!noptargs) {
+        goto skip_optional_pos;
+    }
+    data_obj = args[0];
+skip_optional_pos:
+    return_value = _hashlib_openssl_blake2b_impl(module, data_obj);
+
+exit:
+    return return_value;
+}
+
+PyDoc_STRVAR(_hashlib_openssl_blake2s__doc__,
+"openssl_blake2s($module, /, string=b\'\')\n"
+"--\n"
+"\n"
+"Returns a blake2s hash object; optionally initialized with a string");
+
+#define _HASHLIB_OPENSSL_BLAKE2S_METHODDEF    \
+    {"openssl_blake2s", (PyCFunction)(void(*)(void))_hashlib_openssl_blake2s, METH_FASTCALL|METH_KEYWORDS, _hashlib_openssl_blake2s__doc__},
+
+static PyObject *
+_hashlib_openssl_blake2s_impl(PyObject *module, PyObject *data_obj);
+
+static PyObject *
+_hashlib_openssl_blake2s(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames)
+{
+    PyObject *return_value = NULL;
+    static const char * const _keywords[] = {"string", NULL};
+    static _PyArg_Parser _parser = {NULL, _keywords, "openssl_blake2s", 0};
+    PyObject *argsbuf[1];
+    Py_ssize_t noptargs = nargs + (kwnames ? PyTuple_GET_SIZE(kwnames) : 0) - 0;
+    PyObject *data_obj = NULL;
+
+    args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 0, 1, 0, argsbuf);
+    if (!args) {
+        goto exit;
+    }
+    if (!noptargs) {
+        goto skip_optional_pos;
+    }
+    data_obj = args[0];
+skip_optional_pos:
+    return_value = _hashlib_openssl_blake2s_impl(module, data_obj);
+
+exit:
+    return return_value;
+}
+
+PyDoc_STRVAR(_hashlib_openssl_sha3_224__doc__,
+"openssl_sha3_224($module, /, string=b\'\')\n"
+"--\n"
+"\n"
+"Returns a sha3_224 hash object; optionally initialized with a string");
+
+#define _HASHLIB_OPENSSL_SHA3_224_METHODDEF    \
+    {"openssl_sha3_224", (PyCFunction)(void(*)(void))_hashlib_openssl_sha3_224, METH_FASTCALL|METH_KEYWORDS, _hashlib_openssl_sha3_224__doc__},
+
+static PyObject *
+_hashlib_openssl_sha3_224_impl(PyObject *module, PyObject *data_obj);
+
+static PyObject *
+_hashlib_openssl_sha3_224(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames)
+{
+    PyObject *return_value = NULL;
+    static const char * const _keywords[] = {"string", NULL};
+    static _PyArg_Parser _parser = {NULL, _keywords, "openssl_sha3_224", 0};
+    PyObject *argsbuf[1];
+    Py_ssize_t noptargs = nargs + (kwnames ? PyTuple_GET_SIZE(kwnames) : 0) - 0;
+    PyObject *data_obj = NULL;
+
+    args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 0, 1, 0, argsbuf);
+    if (!args) {
+        goto exit;
+    }
+    if (!noptargs) {
+        goto skip_optional_pos;
+    }
+    data_obj = args[0];
+skip_optional_pos:
+    return_value = _hashlib_openssl_sha3_224_impl(module, data_obj);
+
+exit:
+    return return_value;
+}
+
+PyDoc_STRVAR(_hashlib_openssl_sha3_256__doc__,
+"openssl_sha3_256($module, /, string=b\'\')\n"
+"--\n"
+"\n"
+"Returns a sha3_256 hash object; optionally initialized with a string");
+
+#define _HASHLIB_OPENSSL_SHA3_256_METHODDEF    \
+    {"openssl_sha3_256", (PyCFunction)(void(*)(void))_hashlib_openssl_sha3_256, METH_FASTCALL|METH_KEYWORDS, _hashlib_openssl_sha3_256__doc__},
+
+static PyObject *
+_hashlib_openssl_sha3_256_impl(PyObject *module, PyObject *data_obj);
+
+static PyObject *
+_hashlib_openssl_sha3_256(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames)
+{
+    PyObject *return_value = NULL;
+    static const char * const _keywords[] = {"string", NULL};
+    static _PyArg_Parser _parser = {NULL, _keywords, "openssl_sha3_256", 0};
+    PyObject *argsbuf[1];
+    Py_ssize_t noptargs = nargs + (kwnames ? PyTuple_GET_SIZE(kwnames) : 0) - 0;
+    PyObject *data_obj = NULL;
+
+    args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 0, 1, 0, argsbuf);
+    if (!args) {
+        goto exit;
+    }
+    if (!noptargs) {
+        goto skip_optional_pos;
+    }
+    data_obj = args[0];
+skip_optional_pos:
+    return_value = _hashlib_openssl_sha3_256_impl(module, data_obj);
+
+exit:
+    return return_value;
+}
+
+PyDoc_STRVAR(_hashlib_openssl_sha3_384__doc__,
+"openssl_sha3_384($module, /, string=b\'\')\n"
+"--\n"
+"\n"
+"Returns a sha3_384 hash object; optionally initialized with a string");
+
+#define _HASHLIB_OPENSSL_SHA3_384_METHODDEF    \
+    {"openssl_sha3_384", (PyCFunction)(void(*)(void))_hashlib_openssl_sha3_384, METH_FASTCALL|METH_KEYWORDS, _hashlib_openssl_sha3_384__doc__},
+
+static PyObject *
+_hashlib_openssl_sha3_384_impl(PyObject *module, PyObject *data_obj);
+
+static PyObject *
+_hashlib_openssl_sha3_384(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames)
+{
+    PyObject *return_value = NULL;
+    static const char * const _keywords[] = {"string", NULL};
+    static _PyArg_Parser _parser = {NULL, _keywords, "openssl_sha3_384", 0};
+    PyObject *argsbuf[1];
+    Py_ssize_t noptargs = nargs + (kwnames ? PyTuple_GET_SIZE(kwnames) : 0) - 0;
+    PyObject *data_obj = NULL;
+
+    args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 0, 1, 0, argsbuf);
+    if (!args) {
+        goto exit;
+    }
+    if (!noptargs) {
+        goto skip_optional_pos;
+    }
+    data_obj = args[0];
+skip_optional_pos:
+    return_value = _hashlib_openssl_sha3_384_impl(module, data_obj);
+
+exit:
+    return return_value;
+}
+
+PyDoc_STRVAR(_hashlib_openssl_sha3_512__doc__,
+"openssl_sha3_512($module, /, string=b\'\')\n"
+"--\n"
+"\n"
+"Returns a sha3-512 hash object; optionally initialized with a string");
+
+#define _HASHLIB_OPENSSL_SHA3_512_METHODDEF    \
+    {"openssl_sha3_512", (PyCFunction)(void(*)(void))_hashlib_openssl_sha3_512, METH_FASTCALL|METH_KEYWORDS, _hashlib_openssl_sha3_512__doc__},
+
+static PyObject *
+_hashlib_openssl_sha3_512_impl(PyObject *module, PyObject *data_obj);
+
+static PyObject *
+_hashlib_openssl_sha3_512(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames)
+{
+    PyObject *return_value = NULL;
+    static const char * const _keywords[] = {"string", NULL};
+    static _PyArg_Parser _parser = {NULL, _keywords, "openssl_sha3_512", 0};
+    PyObject *argsbuf[1];
+    Py_ssize_t noptargs = nargs + (kwnames ? PyTuple_GET_SIZE(kwnames) : 0) - 0;
+    PyObject *data_obj = NULL;
+
+    args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 0, 1, 0, argsbuf);
+    if (!args) {
+        goto exit;
+    }
+    if (!noptargs) {
+        goto skip_optional_pos;
+    }
+    data_obj = args[0];
+skip_optional_pos:
+    return_value = _hashlib_openssl_sha3_512_impl(module, data_obj);
+
+exit:
+    return return_value;
+}
+
+PyDoc_STRVAR(_hashlib_openssl_shake_128__doc__,
+"openssl_shake_128($module, /, string=b\'\')\n"
+"--\n"
+"\n"
+"Returns a shake_128 hash object; optionally initialized with a string");
+
+#define _HASHLIB_OPENSSL_SHAKE_128_METHODDEF    \
+    {"openssl_shake_128", (PyCFunction)(void(*)(void))_hashlib_openssl_shake_128, METH_FASTCALL|METH_KEYWORDS, _hashlib_openssl_shake_128__doc__},
+
+static PyObject *
+_hashlib_openssl_shake_128_impl(PyObject *module, PyObject *data_obj);
+
+static PyObject *
+_hashlib_openssl_shake_128(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames)
+{
+    PyObject *return_value = NULL;
+    static const char * const _keywords[] = {"string", NULL};
+    static _PyArg_Parser _parser = {NULL, _keywords, "openssl_shake_128", 0};
+    PyObject *argsbuf[1];
+    Py_ssize_t noptargs = nargs + (kwnames ? PyTuple_GET_SIZE(kwnames) : 0) - 0;
+    PyObject *data_obj = NULL;
+
+    args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 0, 1, 0, argsbuf);
+    if (!args) {
+        goto exit;
+    }
+    if (!noptargs) {
+        goto skip_optional_pos;
+    }
+    data_obj = args[0];
+skip_optional_pos:
+    return_value = _hashlib_openssl_shake_128_impl(module, data_obj);
+
+exit:
+    return return_value;
+}
+
+PyDoc_STRVAR(_hashlib_openssl_shake_256__doc__,
+"openssl_shake_256($module, /, string=b\'\')\n"
+"--\n"
+"\n"
+"Returns a shake_256 hash object; optionally initialized with a string");
+
+#define _HASHLIB_OPENSSL_SHAKE_256_METHODDEF    \
+    {"openssl_shake_256", (PyCFunction)(void(*)(void))_hashlib_openssl_shake_256, METH_FASTCALL|METH_KEYWORDS, _hashlib_openssl_shake_256__doc__},
+
+static PyObject *
+_hashlib_openssl_shake_256_impl(PyObject *module, PyObject *data_obj);
+
+static PyObject *
+_hashlib_openssl_shake_256(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames)
+{
+    PyObject *return_value = NULL;
+    static const char * const _keywords[] = {"string", NULL};
+    static _PyArg_Parser _parser = {NULL, _keywords, "openssl_shake_256", 0};
+    PyObject *argsbuf[1];
+    Py_ssize_t noptargs = nargs + (kwnames ? PyTuple_GET_SIZE(kwnames) : 0) - 0;
+    PyObject *data_obj = NULL;
+
+    args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 0, 1, 0, argsbuf);
+    if (!args) {
+        goto exit;
+    }
+    if (!noptargs) {
+        goto skip_optional_pos;
+    }
+    data_obj = args[0];
+skip_optional_pos:
+    return_value = _hashlib_openssl_shake_256_impl(module, data_obj);
+
+exit:
+    return return_value;
+}
+
 PyDoc_STRVAR(pbkdf2_hmac__doc__,
 "pbkdf2_hmac($module, /, hash_name, password, salt, iterations,\n"
 "            dklen=None)\n"
@@ -646,4 +942,4 @@ _hashlib_get_fips_mode(PyObject *module, PyObject *Py_UNUSED(ignored))
 #ifndef _HASHLIB_SCRYPT_METHODDEF
     #define _HASHLIB_SCRYPT_METHODDEF
 #endif /* !defined(_HASHLIB_SCRYPT_METHODDEF) */
-/*[clinic end generated code: output=5467006d93e7479e input=a9049054013a1b77]*/
+/*[clinic end generated code: output=be8e21a10dff71e7 input=a9049054013a1b77]*/
-- 
2.25.4


From bc9f365705cf600dc26cd16585a25bcde6b43ff1 Mon Sep 17 00:00:00 2001
From: Petr Viktorin <pviktori@redhat.com>
Date: Thu, 25 Jul 2019 18:13:45 +0200
Subject: [PATCH 07/43] Fix tests

---
 Lib/test/test_hashlib.py | 58 +++++++++++++++++++++++++++++++---------
 1 file changed, 45 insertions(+), 13 deletions(-)

diff --git a/Lib/test/test_hashlib.py b/Lib/test/test_hashlib.py
index e9abcbb929..2a55fd4309 100644
--- a/Lib/test/test_hashlib.py
+++ b/Lib/test/test_hashlib.py
@@ -190,7 +190,9 @@ class HashLibTestCase(unittest.TestCase):
         a = array.array("b", range(10))
         for cons in self.hash_constructors:
             c = cons(a)
-            if c.name in self.shakes:
+            if (c.name in self.shakes
+                and not cons.__name__.startswith('openssl_')
+            ):
                 c.hexdigest(16)
             else:
                 c.hexdigest()
@@ -240,7 +242,9 @@ class HashLibTestCase(unittest.TestCase):
     def test_hexdigest(self):
         for cons in self.hash_constructors:
             h = cons()
-            if h.name in self.shakes:
+            if (h.name in self.shakes
+                and not cons.__name__.startswith('openssl_')
+            ):
                 self.assertIsInstance(h.digest(16), bytes)
                 self.assertEqual(hexstr(h.digest(16)), h.hexdigest(16))
             else:
@@ -254,6 +258,8 @@ class HashLibTestCase(unittest.TestCase):
             h = cons()
             if h.name not in self.shakes:
                 continue
+            if cons.__name__.startswith('openssl_'):
+                continue
             for digest in h.digest, h.hexdigest:
                 self.assertRaises(ValueError, digest, -10)
                 for length in large_sizes:
@@ -282,7 +288,9 @@ class HashLibTestCase(unittest.TestCase):
             m1.update(bees)
             m1.update(cees)
             m1.update(dees)
-            if m1.name in self.shakes:
+            if (m1.name in self.shakes
+                and not cons.__name__.startswith('openssl_')
+            ):
                 args = (16,)
             else:
                 args = ()
@@ -309,15 +317,36 @@ class HashLibTestCase(unittest.TestCase):
         # 2 is for hashlib.name(...) and hashlib.new(name, ...)
         self.assertGreaterEqual(len(constructors), 2)
         for hash_object_constructor in constructors:
+            if (
+                kwargs
+                and hash_object_constructor.__name__.startswith('openssl_')
+            ):
+                return
             m = hash_object_constructor(data, **kwargs)
-            computed = m.hexdigest() if not shake else m.hexdigest(length)
+            if shake:
+                if hash_object_constructor.__name__.startswith('openssl_'):
+                    if length > m.digest_size:
+                        # OpenSSL doesn't give long digests
+                        return
+                    computed = m.hexdigest()[:length*2]
+                    hexdigest = hexdigest[:length*2]
+                else:
+                    computed = m.hexdigest(length)
+            else:
+                computed = m.hexdigest()
             self.assertEqual(
                     computed, hexdigest,
                     "Hash algorithm %s constructed using %s returned hexdigest"
                     " %r for %d byte input data that should have hashed to %r."
                     % (name, hash_object_constructor,
                        computed, len(data), hexdigest))
-            computed = m.digest() if not shake else m.digest(length)
+            if shake:
+                if hash_object_constructor.__name__.startswith('openssl_'):
+                    computed = m.digest()[:length]
+                else:
+                    computed = m.digest(length)
+            else:
+                computed = m.digest()
             digest = bytes.fromhex(hexdigest)
             self.assertEqual(computed, digest)
             if not shake:
@@ -357,12 +386,14 @@ class HashLibTestCase(unittest.TestCase):
         for hash_object_constructor in constructors:
             m = hash_object_constructor()
             self.assertEqual(m.block_size, block_size)
-            self.assertEqual(m.digest_size, digest_size)
+            if not hash_object_constructor.__name__.startswith('openssl_'):
+                self.assertEqual(m.digest_size, digest_size)
             if digest_length:
-                self.assertEqual(len(m.digest(digest_length)),
-                                 digest_length)
-                self.assertEqual(len(m.hexdigest(digest_length)),
-                                 2*digest_length)
+                if not hash_object_constructor.__name__.startswith('openssl_'):
+                    self.assertEqual(len(m.digest(digest_length)),
+                                    digest_length)
+                    self.assertEqual(len(m.hexdigest(digest_length)),
+                                    2*digest_length)
             else:
                 self.assertEqual(len(m.digest()), digest_size)
                 self.assertEqual(len(m.hexdigest()), 2*digest_size)
@@ -395,9 +426,10 @@ class HashLibTestCase(unittest.TestCase):
                 # _hashopenssl's variant does not have extra SHA3 attributes
                 continue
             self.assertEqual(capacity + rate, 1600)
-            self.assertEqual(m._capacity_bits, capacity)
-            self.assertEqual(m._rate_bits, rate)
-            self.assertEqual(m._suffix, suffix)
+            if not hash_object_constructor.__name__.startswith('openssl_'):
+                self.assertEqual(m._capacity_bits, capacity)
+                self.assertEqual(m._rate_bits, rate)
+                self.assertEqual(m._suffix, suffix)
 
     @requires_sha3
     def test_extra_sha3(self):
-- 
2.25.4


From de23605b73ef563766405f678822ec3b6e3645ea Mon Sep 17 00:00:00 2001
From: Petr Viktorin <pviktori@redhat.com>
Date: Fri, 26 Jul 2019 11:27:57 +0200
Subject: [PATCH 08/43] Change FIPS exceptions from _blake2, _sha3 module init
 to ImportError

---
 Include/_hashopenssl.h         | 11 +++++------
 Modules/_blake2/blake2b_impl.c |  4 ++--
 Modules/_blake2/blake2module.c |  2 +-
 Modules/_blake2/blake2s_impl.c |  4 ++--
 Modules/_sha3/sha3module.c     |  6 +++---
 5 files changed, 13 insertions(+), 14 deletions(-)

diff --git a/Include/_hashopenssl.h b/Include/_hashopenssl.h
index a726c0d3fb..47ed003042 100644
--- a/Include/_hashopenssl.h
+++ b/Include/_hashopenssl.h
@@ -39,7 +39,7 @@ _setException(PyObject *exc)
 
 __attribute__((__unused__))
 static int
-_Py_hashlib_fips_error(char *name) {
+_Py_hashlib_fips_error(PyObject *exc, char *name) {
     int result = FIPS_mode();
     if (result == 0) {
         // "If the library was built without support of the FIPS Object Module,
@@ -49,18 +49,17 @@ _Py_hashlib_fips_error(char *name) {
 
         unsigned long errcode = ERR_peek_last_error();
         if (errcode) {
-            _setException(PyExc_ValueError);
+            _setException(exc);
             return 1;
         }
         return 0;
     }
-    PyErr_Format(PyExc_ValueError, "%s is not available in FIPS mode",
-                 name);
+    PyErr_Format(exc, "%s is not available in FIPS mode", name);
     return 1;
 }
 
-#define FAIL_RETURN_IN_FIPS_MODE(name) do { \
-    if (_Py_hashlib_fips_error(name)) return NULL; \
+#define FAIL_RETURN_IN_FIPS_MODE(exc, name) do { \
+    if (_Py_hashlib_fips_error(exc, name)) return NULL; \
 } while (0)
 
 #endif  // !Py_HASHOPENSSL_H
diff --git a/Modules/_blake2/blake2b_impl.c b/Modules/_blake2/blake2b_impl.c
index 1daf5c38e2..97ce89d33c 100644
--- a/Modules/_blake2/blake2b_impl.c
+++ b/Modules/_blake2/blake2b_impl.c
@@ -97,7 +97,7 @@ py_blake2b_new_impl(PyTypeObject *type, PyObject *data, int digest_size,
     BLAKE2bObject *self = NULL;
     Py_buffer buf;
 
-    FAIL_RETURN_IN_FIPS_MODE("_blake2");
+    FAIL_RETURN_IN_FIPS_MODE(PyExc_ValueError, "_blake2");
 
     self = new_BLAKE2bObject(type);
     if (self == NULL) {
@@ -277,7 +277,7 @@ _blake2_blake2b_update(BLAKE2bObject *self, PyObject *data)
 {
     Py_buffer buf;
 
-    FAIL_RETURN_IN_FIPS_MODE("_blake2");
+    FAIL_RETURN_IN_FIPS_MODE(PyExc_ValueError, "_blake2");
 
     GET_BUFFER_VIEW_OR_ERROUT(data, &buf);
 
diff --git a/Modules/_blake2/blake2module.c b/Modules/_blake2/blake2module.c
index 817b716568..a9c7cbc7eb 100644
--- a/Modules/_blake2/blake2module.c
+++ b/Modules/_blake2/blake2module.c
@@ -58,7 +58,7 @@ PyInit__blake2(void)
     PyObject *m;
     PyObject *d;
 
-    FAIL_RETURN_IN_FIPS_MODE("blake2");
+    FAIL_RETURN_IN_FIPS_MODE(PyExc_ImportError, "blake2");
 
     m = PyModule_Create(&blake2_module);
     if (m == NULL)
diff --git a/Modules/_blake2/blake2s_impl.c b/Modules/_blake2/blake2s_impl.c
index 389711abf1..c4447b4fe8 100644
--- a/Modules/_blake2/blake2s_impl.c
+++ b/Modules/_blake2/blake2s_impl.c
@@ -97,7 +97,7 @@ py_blake2s_new_impl(PyTypeObject *type, PyObject *data, int digest_size,
     BLAKE2sObject *self = NULL;
     Py_buffer buf;
 
-    FAIL_RETURN_IN_FIPS_MODE("_blake2");
+    FAIL_RETURN_IN_FIPS_MODE(PyExc_ValueError, "_blake2");
 
     self = new_BLAKE2sObject(type);
     if (self == NULL) {
@@ -277,7 +277,7 @@ _blake2_blake2s_update(BLAKE2sObject *self, PyObject *data)
 {
     Py_buffer buf;
 
-    FAIL_RETURN_IN_FIPS_MODE("_blake2");
+    FAIL_RETURN_IN_FIPS_MODE(PyExc_ValueError, "_blake2");
 
     GET_BUFFER_VIEW_OR_ERROUT(data, &buf);
 
diff --git a/Modules/_sha3/sha3module.c b/Modules/_sha3/sha3module.c
index 34d09b45d9..3079e1e3a4 100644
--- a/Modules/_sha3/sha3module.c
+++ b/Modules/_sha3/sha3module.c
@@ -161,7 +161,7 @@ static PyTypeObject SHAKE256type;
 static SHA3object *
 newSHA3object(PyTypeObject *type)
 {
-    FAIL_RETURN_IN_FIPS_MODE("_sha3");
+    FAIL_RETURN_IN_FIPS_MODE(PyExc_ValueError, "_sha3");
     SHA3object *newobj;
     newobj = (SHA3object *)PyObject_New(SHA3object, type);
     if (newobj == NULL) {
@@ -175,7 +175,7 @@ newSHA3object(PyTypeObject *type)
 static PyObject *
 py_sha3_new(PyTypeObject *type, PyObject *args, PyObject *kwargs)
 {
-    FAIL_RETURN_IN_FIPS_MODE("_sha3");
+    FAIL_RETURN_IN_FIPS_MODE(PyExc_ValueError, "_sha3");
     SHA3object *self = NULL;
     Py_buffer buf = {NULL, NULL};
     HashReturn res;
@@ -707,7 +707,7 @@ PyInit__sha3(void)
 {
     PyObject *m = NULL;
 
-    FAIL_RETURN_IN_FIPS_MODE("_sha3");
+    FAIL_RETURN_IN_FIPS_MODE(PyExc_ImportError, "_sha3");
 
     if ((m = PyModule_Create(&_SHA3module)) == NULL) {
         return NULL;
-- 
2.25.4


From 104d4b32cb6b28f48f6e03a0b9ec51126a833b72 Mon Sep 17 00:00:00 2001
From: Petr Viktorin <pviktori@redhat.com>
Date: Fri, 26 Jul 2019 11:24:09 +0200
Subject: [PATCH 09/43] Make hashlib importable under FIPS mode

---
 Lib/hashlib.py | 8 +++++---
 1 file changed, 5 insertions(+), 3 deletions(-)

diff --git a/Lib/hashlib.py b/Lib/hashlib.py
index 1bcfdf9f7f..898e6dca56 100644
--- a/Lib/hashlib.py
+++ b/Lib/hashlib.py
@@ -137,12 +137,14 @@ def __get_openssl_constructor(name):
         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.
-        f()
+        if not get_fips_mode():
+            # N.B. In "FIPS mode", there is no fallback.
+            # If this test fails, we want to export the broken hash
+            # constructor anyway.
+            f()
         # Use the C function directly (very fast)
         return f
     except (AttributeError, ValueError):
-        if get_fips_mode():
-            raise
         return __get_builtin_constructor(name)
 
 
-- 
2.25.4


From 168538a496916c0b92c11c433fd0f9545c33f535 Mon Sep 17 00:00:00 2001
From: Petr Viktorin <pviktori@redhat.com>
Date: Fri, 26 Jul 2019 15:41:10 +0200
Subject: [PATCH 10/43] Implement hmac.new using new built-in module,
 _hmacopenssl

---
 Lib/hmac.py                     |  32 ++-
 Modules/_hmacopenssl.c          | 396 ++++++++++++++++++++++++++++++++
 Modules/clinic/_hmacopenssl.c.h | 133 +++++++++++
 setup.py                        |   4 +
 4 files changed, 564 insertions(+), 1 deletion(-)
 create mode 100644 Modules/_hmacopenssl.c
 create mode 100644 Modules/clinic/_hmacopenssl.c.h

diff --git a/Lib/hmac.py b/Lib/hmac.py
index b769876e6f..daabc8c142 100644
--- a/Lib/hmac.py
+++ b/Lib/hmac.py
@@ -13,6 +13,8 @@ except ImportError:
 else:
     _openssl_md_meths = frozenset(_hashopenssl.openssl_md_meth_names)
 import hashlib as _hashlib
+import _hashlib as _hashlibopenssl
+import _hmacopenssl
 
 trans_5C = bytes((x ^ 0x5C) for x in range(256))
 trans_36 = bytes((x ^ 0x36) for x in range(256))
@@ -43,6 +45,11 @@ class HMAC:
                    msg argument.  Passing it as a keyword argument is
                    recommended, though not required for legacy API reasons.
         """
+        if _hashlib.get_fips_mode():
+            raise ValueError(
+                'hmac.HMAC is not available in FIPS mode. '
+                + 'Use hmac.new().'
+            )
 
         if not isinstance(key, (bytes, bytearray)):
             raise TypeError("key: expected bytes or bytearray, but got %r" % type(key).__name__)
@@ -93,6 +100,8 @@ class HMAC:
 
     def update(self, msg):
         """Feed data from msg into this hashing object."""
+        if _hashlib.get_fips_mode():
+            raise ValueError('hmac.HMAC is not available in FIPS mode')
         self.inner.update(msg)
 
     def copy(self):
@@ -133,6 +142,18 @@ class HMAC:
         h = self._current()
         return h.hexdigest()
 
+def _get_openssl_name(digestmod):
+    if isinstance(digestmod, str):
+        return digestmod.lower()
+    elif callable(digestmod):
+        digestmod = digestmod(b'')
+
+    if not isinstance(digestmod, _hashlibopenssl.HASH):
+        raise TypeError(
+            'Only OpenSSL hashlib hashes are accepted in FIPS mode.')
+
+    return digestmod.name.lower().replace('_', '-')
+
 def new(key, msg=None, digestmod=''):
     """Create a new hashing object and return it.
 
@@ -150,7 +171,16 @@ def new(key, msg=None, digestmod=''):
     method, and can ask for the hash value at any time by calling its digest()
     or hexdigest() methods.
     """
-    return HMAC(key, msg, digestmod)
+    if _hashlib.get_fips_mode():
+        if digestmod is None:
+            digestmod = 'md5'
+        name = _get_openssl_name(digestmod)
+        result = _hmacopenssl.new(key, digestmod=name)
+        if msg:
+            result.update(msg)
+        return result
+    else:
+        return HMAC(key, msg, digestmod)
 
 
 def digest(key, msg, digest):
diff --git a/Modules/_hmacopenssl.c b/Modules/_hmacopenssl.c
new file mode 100644
index 0000000000..ca95d725f0
--- /dev/null
+++ b/Modules/_hmacopenssl.c
@@ -0,0 +1,396 @@
+/* Module that wraps all OpenSSL MHAC algorithm */
+
+/* Copyright (C) 2019 Red Hat, Inc. Red Hat, Inc. and/or its affiliates
+ *
+ * Based on _hashopenssl.c, which is:
+ * Copyright (C) 2005-2010   Gregory P. Smith (greg@krypto.org)
+ * Licensed to PSF under a Contributor Agreement.
+ *
+ * Derived from a skeleton of shamodule.c containing work performed by:
+ *
+ * Andrew Kuchling (amk@amk.ca)
+ * Greg Stein (gstein@lyra.org)
+ *
+ */
+
+#define PY_SSIZE_T_CLEAN
+
+#include "Python.h"
+#include "structmember.h"
+#include "hashlib.h"
+#include "pystrhex.h"
+#include "_hashopenssl.h"
+
+
+#include <openssl/hmac.h>
+
+static PyTypeObject HmacType;
+
+typedef struct {
+    PyObject_HEAD
+    PyObject *name;  /* name of the hash algorithm */
+    HMAC_CTX *ctx;   /* OpenSSL hmac context */
+    PyThread_type_lock lock;  /* HMAC context lock */
+} HmacObject;
+
+#include "clinic/_hmacopenssl.c.h"
+/*[clinic input]
+module _hmacopenssl
+class _hmacopenssl.HMAC "HmacObject *" "&HmacType"
+[clinic start generated code]*/
+/*[clinic end generated code: output=da39a3ee5e6b4b0d input=c98d3f2af591c085]*/
+
+
+/*[clinic input]
+_hmacopenssl.new
+
+    key: Py_buffer
+    *
+    digestmod: str
+
+Return a new hmac object.
+[clinic start generated code]*/
+
+static PyObject *
+_hmacopenssl_new_impl(PyObject *module, Py_buffer *key,
+                      const char *digestmod)
+/*[clinic end generated code: output=46f1cb4e02921922 input=be8c0c2e4fad508c]*/
+{
+    if (digestmod == NULL) {
+        PyErr_SetString(PyExc_ValueError, "digestmod must be specified");
+        return NULL;
+    }
+
+    /* name mut be lowercase */
+    for (int i=0; digestmod[i]; i++) {
+        if (
+            ((digestmod[i] < 'a') || (digestmod[i] > 'z'))
+            && ((digestmod[i] < '0') || (digestmod[i] > '9'))
+            && digestmod[i] != '-'
+        ) {
+            PyErr_SetString(PyExc_ValueError, "digestmod must be lowercase");
+            return NULL;
+        }
+    }
+
+    const EVP_MD *digest = EVP_get_digestbyname(digestmod);
+    if (!digest) {
+        PyErr_SetString(PyExc_ValueError, "unknown hash function");
+        return NULL;
+    }
+
+    PyObject *name = NULL;
+    HMAC_CTX *ctx = NULL;
+    HmacObject *retval = NULL;
+
+    name = PyUnicode_FromFormat("hmac-%s", digestmod);
+    if (name == NULL) {
+        goto error;
+    }
+
+    ctx = HMAC_CTX_new();
+    if (ctx == NULL) {
+        _setException(PyExc_ValueError);
+        goto error;
+    }
+
+    int r = HMAC_Init_ex(
+        ctx,
+        (const char*)key->buf,
+        key->len,
+        digest,
+        NULL /*impl*/);
+    if (r == 0) {
+        _setException(PyExc_ValueError);
+        goto error;
+    }
+
+    retval = (HmacObject *)PyObject_New(HmacObject, &HmacType);
+    if (retval == NULL) {
+        goto error;
+    }
+
+    retval->name = name;
+    retval->ctx = ctx;
+    retval->lock = NULL;
+
+    return (PyObject*)retval;
+
+error:
+    if (ctx) HMAC_CTX_free(ctx);
+    if (name) Py_DECREF(name);
+    if (retval) PyObject_Del(name);
+    return NULL;
+}
+
+/*[clinic input]
+_hmacopenssl.HMAC.copy
+
+Return a copy (“clone”) of the HMAC object.
+[clinic start generated code]*/
+
+static PyObject *
+_hmacopenssl_HMAC_copy_impl(HmacObject *self)
+/*[clinic end generated code: output=fe5ee41faf30dcf0 input=f5ed20feec42d8d0]*/
+{
+    HmacObject *retval = (HmacObject *)PyObject_New(HmacObject, &HmacType);
+    if (retval == NULL) {
+        return NULL;
+    }
+
+    Py_INCREF(self->name);
+    retval->name = self->name;
+
+    int r = HMAC_CTX_copy(retval->ctx, self->ctx);
+    if (r == 0) {
+        PyObject_Del(retval);
+        return _setException(PyExc_ValueError);
+    }
+
+    return (PyObject*)retval;
+}
+
+static void
+_hmac_dealloc(HmacObject *self)
+{
+    if (self->lock != NULL) {
+        PyThread_free_lock(self->lock);
+    }
+    HMAC_CTX_free(self->ctx);
+    Py_XDECREF(self->name);
+    PyObject_Del(self);
+}
+
+static PyObject *
+_hmac_repr(HmacObject *self)
+{
+    return PyUnicode_FromFormat("<%U HMAC object @ %p>", self->name, self);
+}
+
+/*[clinic input]
+_hmacopenssl.HMAC.update
+
+    msg: Py_buffer
+
+Update the HMAC object with msg.
+[clinic start generated code]*/
+
+static PyObject *
+_hmacopenssl_HMAC_update_impl(HmacObject *self, Py_buffer *msg)
+/*[clinic end generated code: output=0efeee663a98cee5 input=0683d64f35808cb9]*/
+{
+    if (self->lock == NULL && msg->len >= HASHLIB_GIL_MINSIZE) {
+        self->lock = PyThread_allocate_lock();
+        /* fail? lock = NULL and we fail over to non-threaded code. */
+    }
+
+    int r;
+
+    if (self->lock != NULL) {
+        Py_BEGIN_ALLOW_THREADS
+        PyThread_acquire_lock(self->lock, 1);
+        r = HMAC_Update(self->ctx, (const unsigned char*)msg->buf, msg->len);
+        PyThread_release_lock(self->lock);
+        Py_END_ALLOW_THREADS
+    } else {
+        r = HMAC_Update(self->ctx, (const unsigned char*)msg->buf, msg->len);
+    }
+
+    if (r == 0) {
+        _setException(PyExc_ValueError);
+        return NULL;
+    }
+    Py_RETURN_NONE;
+}
+
+static unsigned int
+_digest_size(HmacObject *self)
+{
+    const EVP_MD *md = HMAC_CTX_get_md(self->ctx);
+    if (md == NULL) {
+        _setException(PyExc_ValueError);
+        return 0;
+    }
+    return EVP_MD_size(md);
+}
+
+static int
+_digest(HmacObject *self, unsigned char *buf, unsigned int len)
+{
+    HMAC_CTX *temp_ctx = HMAC_CTX_new();
+    if (temp_ctx == NULL) {
+        PyErr_NoMemory();
+        return 0;
+    }
+    int r = HMAC_CTX_copy(temp_ctx, self->ctx);
+    if (r == 0) {
+        _setException(PyExc_ValueError);
+        return 0;
+    }
+    r = HMAC_Final(temp_ctx, buf, &len);
+    HMAC_CTX_free(temp_ctx);
+    if (r == 0) {
+        _setException(PyExc_ValueError);
+        return 0;
+    }
+    return 1;
+}
+
+/*[clinic input]
+_hmacopenssl.HMAC.digest
+
+Return the digest of the bytes passed to the update() method so far.
+[clinic start generated code]*/
+
+static PyObject *
+_hmacopenssl_HMAC_digest_impl(HmacObject *self)
+/*[clinic end generated code: output=3aa6dbfc46ec4957 input=bf769a10b1d9edd9]*/
+{
+    unsigned int digest_size = _digest_size(self);
+    if (digest_size == 0) {
+        return _setException(PyExc_ValueError);
+    }
+    unsigned char buf[digest_size]; /* FIXME: C99 feature */
+    int r = _digest(self, buf, digest_size);
+    if (r == 0) {
+        return NULL;
+    }
+    return PyBytes_FromStringAndSize((const char *)buf, digest_size);
+}
+
+/*[clinic input]
+_hmacopenssl.HMAC.hexdigest
+
+Return hexadecimal digest of the bytes passed to the update() method so far.
+
+This may be used to exchange the value safely in email or other non-binary
+environments.
+[clinic start generated code]*/
+
+static PyObject *
+_hmacopenssl_HMAC_hexdigest_impl(HmacObject *self)
+/*[clinic end generated code: output=630f6fa89f9f1e48 input=b8e60ec8b811c4cd]*/
+{
+    unsigned int digest_size = _digest_size(self);
+    if (digest_size == 0) {
+        return _setException(PyExc_ValueError);
+    }
+    unsigned char buf[digest_size]; /* FIXME: C99 feature */
+    int r = _digest(self, buf, digest_size);
+    if (r == 0) {
+        return NULL;
+    }
+    return _Py_strhex((const char *)buf, digest_size);
+}
+
+
+
+static PyObject *
+_hmacopenssl_get_digest_size(HmacObject *self, void *closure)
+{
+    unsigned int digest_size = _digest_size(self);
+    if (digest_size == 0) {
+        return _setException(PyExc_ValueError);
+    }
+    return PyLong_FromLong(digest_size);
+}
+
+static PyObject *
+_hmacopenssl_get_block_size(HmacObject *self, void *closure)
+{
+    const EVP_MD *md = HMAC_CTX_get_md(self->ctx);
+    if (md == NULL) {
+        return _setException(PyExc_ValueError);
+    }
+    return PyLong_FromLong(EVP_MD_size(md));
+}
+
+static PyMethodDef Hmac_methods[] = {
+    _HMACOPENSSL_HMAC_UPDATE_METHODDEF
+    _HMACOPENSSL_HMAC_DIGEST_METHODDEF
+    _HMACOPENSSL_HMAC_HEXDIGEST_METHODDEF
+    _HMACOPENSSL_HMAC_COPY_METHODDEF
+    {NULL, NULL}  /* sentinel */
+};
+
+static PyGetSetDef Hmac_getset[] = {
+    {"digest_size", (getter)_hmacopenssl_get_digest_size, NULL, NULL, NULL},
+    {"block_size", (getter)_hmacopenssl_get_block_size, NULL, NULL, NULL},
+    {NULL}  /* Sentinel */
+};
+
+static PyMemberDef Hmac_members[] = {
+    {"name", T_OBJECT, offsetof(HmacObject, name), READONLY, PyDoc_STR("HMAC name")},
+};
+
+PyDoc_STRVAR(hmactype_doc,
+"The object used to calculate HMAC of a message.\n\
+\n\
+Methods:\n\
+\n\
+update() -- updates the current digest with an additional string\n\
+digest() -- return the current digest value\n\
+hexdigest() -- return the current digest as a string of hexadecimal digits\n\
+copy() -- return a copy of the current hash object\n\
+\n\
+Attributes:\n\
+\n\
+name -- the name, including the hash algorithm used by this object\n\
+digest_size -- number of bytes in digest() output\n");
+
+static PyTypeObject HmacType = {
+    PyVarObject_HEAD_INIT(NULL, 0)
+    "_hmacopenssl.HMAC",    /*tp_name*/
+    sizeof(HmacObject),  /*tp_basicsize*/
+    .tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE,
+    .tp_doc = hmactype_doc,
+    .tp_repr = (reprfunc)_hmac_repr,
+    .tp_dealloc = (destructor)_hmac_dealloc,
+    .tp_methods = Hmac_methods,
+    .tp_getset = Hmac_getset,
+    .tp_members = Hmac_members,
+};
+
+static struct PyMethodDef hmacopenssl_functions[] = {
+    _HMACOPENSSL_NEW_METHODDEF
+    {NULL,      NULL}            /* Sentinel */
+};
+
+
+
+/* Initialize this module. */
+
+
+static struct PyModuleDef _hmacopenssl_module = {
+    PyModuleDef_HEAD_INIT,
+    "_hmacopenssl",
+    NULL,
+    -1,
+    hmacopenssl_functions,
+    NULL,
+    NULL,
+    NULL,
+    NULL
+};
+
+PyMODINIT_FUNC
+PyInit__hmacopenssl(void)
+{
+    /* TODO build EVP_functions openssl_* entries dynamically based
+     * on what hashes are supported rather than listing many
+     * but having some be unsupported.  Only init appropriate
+     * constants. */
+
+    Py_TYPE(&HmacType) = &PyType_Type;
+    if (PyType_Ready(&HmacType) < 0)
+        return NULL;
+
+    PyObject *m = PyModule_Create(&_hmacopenssl_module);
+    if (m == NULL)
+        return NULL;
+
+    Py_INCREF((PyObject *)&HmacType);
+    PyModule_AddObject(m, "HMAC", (PyObject *)&HmacType);
+
+    return m;
+}
diff --git a/Modules/clinic/_hmacopenssl.c.h b/Modules/clinic/_hmacopenssl.c.h
new file mode 100644
index 0000000000..b472a6eddd
--- /dev/null
+++ b/Modules/clinic/_hmacopenssl.c.h
@@ -0,0 +1,133 @@
+/*[clinic input]
+preserve
+[clinic start generated code]*/
+
+PyDoc_STRVAR(_hmacopenssl_new__doc__,
+"new($module, /, key, *, digestmod)\n"
+"--\n"
+"\n"
+"Return a new hmac object.");
+
+#define _HMACOPENSSL_NEW_METHODDEF    \
+    {"new", (PyCFunction)_hmacopenssl_new, METH_FASTCALL, _hmacopenssl_new__doc__},
+
+static PyObject *
+_hmacopenssl_new_impl(PyObject *module, Py_buffer *key,
+                      const char *digestmod);
+
+static PyObject *
+_hmacopenssl_new(PyObject *module, PyObject **args, Py_ssize_t nargs, PyObject *kwnames)
+{
+    PyObject *return_value = NULL;
+    static const char * const _keywords[] = {"key", "digestmod", NULL};
+    static _PyArg_Parser _parser = {"y*$s:new", _keywords, 0};
+    Py_buffer key = {NULL, NULL};
+    const char *digestmod;
+
+    if (!_PyArg_ParseStack(args, nargs, kwnames, &_parser,
+        &key, &digestmod)) {
+        goto exit;
+    }
+    return_value = _hmacopenssl_new_impl(module, &key, digestmod);
+
+exit:
+    /* Cleanup for key */
+    if (key.obj) {
+       PyBuffer_Release(&key);
+    }
+
+    return return_value;
+}
+
+PyDoc_STRVAR(_hmacopenssl_HMAC_copy__doc__,
+"copy($self, /)\n"
+"--\n"
+"\n"
+"Return a copy (“clone”) of the HMAC object.");
+
+#define _HMACOPENSSL_HMAC_COPY_METHODDEF    \
+    {"copy", (PyCFunction)_hmacopenssl_HMAC_copy, METH_NOARGS, _hmacopenssl_HMAC_copy__doc__},
+
+static PyObject *
+_hmacopenssl_HMAC_copy_impl(HmacObject *self);
+
+static PyObject *
+_hmacopenssl_HMAC_copy(HmacObject *self, PyObject *Py_UNUSED(ignored))
+{
+    return _hmacopenssl_HMAC_copy_impl(self);
+}
+
+PyDoc_STRVAR(_hmacopenssl_HMAC_update__doc__,
+"update($self, /, msg)\n"
+"--\n"
+"\n"
+"Update the HMAC object with msg.");
+
+#define _HMACOPENSSL_HMAC_UPDATE_METHODDEF    \
+    {"update", (PyCFunction)_hmacopenssl_HMAC_update, METH_FASTCALL, _hmacopenssl_HMAC_update__doc__},
+
+static PyObject *
+_hmacopenssl_HMAC_update_impl(HmacObject *self, Py_buffer *msg);
+
+static PyObject *
+_hmacopenssl_HMAC_update(HmacObject *self, PyObject **args, Py_ssize_t nargs, PyObject *kwnames)
+{
+    PyObject *return_value = NULL;
+    static const char * const _keywords[] = {"msg", NULL};
+    static _PyArg_Parser _parser = {"y*:update", _keywords, 0};
+    Py_buffer msg = {NULL, NULL};
+
+    if (!_PyArg_ParseStack(args, nargs, kwnames, &_parser,
+        &msg)) {
+        goto exit;
+    }
+    return_value = _hmacopenssl_HMAC_update_impl(self, &msg);
+
+exit:
+    /* Cleanup for msg */
+    if (msg.obj) {
+       PyBuffer_Release(&msg);
+    }
+
+    return return_value;
+}
+
+PyDoc_STRVAR(_hmacopenssl_HMAC_digest__doc__,
+"digest($self, /)\n"
+"--\n"
+"\n"
+"Return the digest of the bytes passed to the update() method so far.");
+
+#define _HMACOPENSSL_HMAC_DIGEST_METHODDEF    \
+    {"digest", (PyCFunction)_hmacopenssl_HMAC_digest, METH_NOARGS, _hmacopenssl_HMAC_digest__doc__},
+
+static PyObject *
+_hmacopenssl_HMAC_digest_impl(HmacObject *self);
+
+static PyObject *
+_hmacopenssl_HMAC_digest(HmacObject *self, PyObject *Py_UNUSED(ignored))
+{
+    return _hmacopenssl_HMAC_digest_impl(self);
+}
+
+PyDoc_STRVAR(_hmacopenssl_HMAC_hexdigest__doc__,
+"hexdigest($self, /)\n"
+"--\n"
+"\n"
+"Return hexadecimal digest of the bytes passed to the update() method so far.\n"
+"\n"
+"This may be used to exchange the value safely in email or other non-binary\n"
+"environments.");
+
+#define _HMACOPENSSL_HMAC_HEXDIGEST_METHODDEF    \
+    {"hexdigest", (PyCFunction)_hmacopenssl_HMAC_hexdigest, METH_NOARGS, _hmacopenssl_HMAC_hexdigest__doc__},
+
+static PyObject *
+_hmacopenssl_HMAC_hexdigest_impl(HmacObject *self);
+
+static PyObject *
+_hmacopenssl_HMAC_hexdigest(HmacObject *self, PyObject *Py_UNUSED(ignored))
+{
+    return _hmacopenssl_HMAC_hexdigest_impl(self);
+}
+/*[clinic end generated code: output=10b6e8cac6d7a2c9 input=a9049054013a1b77]*/
diff --git a/setup.py b/setup.py
index 0066006772..6b376040ff 100644
--- a/setup.py
+++ b/setup.py
@@ -2251,6 +2251,10 @@ class PyBuildExt(build_ext):
                            depends=['hashlib.h'],
                            **self.detect_openssl_args()) )
 
+        self.add(Extension('_hmacopenssl', ['_hmacopenssl.c'],
+                                depends = ['hashlib.h'],
+                                **self.detect_openssl_args()) )
+
     def detect_hash_builtins(self):
         # RHEL: Always force OpenSSL for md5, sha1, sha256, sha512;
         # don't build Python's implementations.
-- 
2.25.4


From a5091b7016e4d86abaa733cd0dd7c0d066c4c33a Mon Sep 17 00:00:00 2001
From: Marcel Plch <mplch@redhat.com>
Date: Mon, 29 Jul 2019 12:45:11 +0200
Subject: [PATCH 11/43] FIPS review

* Port _hmacopenssl to multiphase init.
* Make _hmacopenssl.HMAC.copy create same type as self.
* hmac.py cosmetic nitpick
---
 Lib/hmac.py            |   2 +-
 Modules/_hmacopenssl.c | 112 +++++++++++++++++++++++++----------------
 2 files changed, 70 insertions(+), 44 deletions(-)

diff --git a/Lib/hmac.py b/Lib/hmac.py
index daabc8c142..2ec24da573 100644
--- a/Lib/hmac.py
+++ b/Lib/hmac.py
@@ -48,7 +48,7 @@ class HMAC:
         if _hashlib.get_fips_mode():
             raise ValueError(
                 'hmac.HMAC is not available in FIPS mode. '
-                + 'Use hmac.new().'
+                'Use hmac.new().'
             )
 
         if not isinstance(key, (bytes, bytearray)):
diff --git a/Modules/_hmacopenssl.c b/Modules/_hmacopenssl.c
index ca95d725f0..216ed04f23 100644
--- a/Modules/_hmacopenssl.c
+++ b/Modules/_hmacopenssl.c
@@ -24,7 +24,10 @@
 
 #include <openssl/hmac.h>
 
-static PyTypeObject HmacType;
+typedef struct hmacopenssl_state {
+    PyTypeObject *HmacType;
+} hmacopenssl_state;
+
 
 typedef struct {
     PyObject_HEAD
@@ -36,9 +39,9 @@ typedef struct {
 #include "clinic/_hmacopenssl.c.h"
 /*[clinic input]
 module _hmacopenssl
-class _hmacopenssl.HMAC "HmacObject *" "&HmacType"
+class _hmacopenssl.HMAC "HmacObject *" "PyModule_GetState(module)->HmacType"
 [clinic start generated code]*/
-/*[clinic end generated code: output=da39a3ee5e6b4b0d input=c98d3f2af591c085]*/
+/*[clinic end generated code: output=da39a3ee5e6b4b0d input=204b7f45847f57b4]*/
 
 
 /*[clinic input]
@@ -56,11 +59,18 @@ _hmacopenssl_new_impl(PyObject *module, Py_buffer *key,
                       const char *digestmod)
 /*[clinic end generated code: output=46f1cb4e02921922 input=be8c0c2e4fad508c]*/
 {
+    hmacopenssl_state *state;
+
     if (digestmod == NULL) {
         PyErr_SetString(PyExc_ValueError, "digestmod must be specified");
         return NULL;
     }
 
+    state = PyModule_GetState(module);
+    if (state == NULL) {
+        return NULL;
+    }
+
     /* name mut be lowercase */
     for (int i=0; digestmod[i]; i++) {
         if (
@@ -105,7 +115,7 @@ _hmacopenssl_new_impl(PyObject *module, Py_buffer *key,
         goto error;
     }
 
-    retval = (HmacObject *)PyObject_New(HmacObject, &HmacType);
+    retval = (HmacObject *)PyObject_New(HmacObject, state->HmacType);
     if (retval == NULL) {
         goto error;
     }
@@ -133,7 +143,9 @@ static PyObject *
 _hmacopenssl_HMAC_copy_impl(HmacObject *self)
 /*[clinic end generated code: output=fe5ee41faf30dcf0 input=f5ed20feec42d8d0]*/
 {
-    HmacObject *retval = (HmacObject *)PyObject_New(HmacObject, &HmacType);
+    HmacObject *retval;
+
+    retval = (HmacObject *)PyObject_New(HmacObject, (PyTypeObject *)PyObject_Type((PyObject *)self));
     if (retval == NULL) {
         return NULL;
     }
@@ -147,7 +159,7 @@ _hmacopenssl_HMAC_copy_impl(HmacObject *self)
         return _setException(PyExc_ValueError);
     }
 
-    return (PyObject*)retval;
+    return (PyObject *)retval;
 }
 
 static void
@@ -338,19 +350,24 @@ Attributes:\n\
 name -- the name, including the hash algorithm used by this object\n\
 digest_size -- number of bytes in digest() output\n");
 
-static PyTypeObject HmacType = {
-    PyVarObject_HEAD_INIT(NULL, 0)
-    "_hmacopenssl.HMAC",    /*tp_name*/
-    sizeof(HmacObject),  /*tp_basicsize*/
-    .tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE,
-    .tp_doc = hmactype_doc,
-    .tp_repr = (reprfunc)_hmac_repr,
-    .tp_dealloc = (destructor)_hmac_dealloc,
-    .tp_methods = Hmac_methods,
-    .tp_getset = Hmac_getset,
-    .tp_members = Hmac_members,
+static PyType_Slot HmacType_slots[] = {
+    {Py_tp_doc, hmactype_doc},
+    {Py_tp_repr, (reprfunc)_hmac_repr},
+    {Py_tp_dealloc,(destructor)_hmac_dealloc},
+    {Py_tp_methods, Hmac_methods},
+    {Py_tp_getset, Hmac_getset},
+    {Py_tp_members, Hmac_members},
+    {0, NULL}
+};
+
+PyType_Spec HmacType_spec = {
+    "_hmacopenssl.HMAC",    /* name */
+    sizeof(HmacObject),     /* basicsize */
+    .flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE,     
+    .slots = HmacType_slots,
 };
 
+
 static struct PyMethodDef hmacopenssl_functions[] = {
     _HMACOPENSSL_NEW_METHODDEF
     {NULL,      NULL}            /* Sentinel */
@@ -360,37 +377,46 @@ static struct PyMethodDef hmacopenssl_functions[] = {
 
 /* Initialize this module. */
 
-
-static struct PyModuleDef _hmacopenssl_module = {
-    PyModuleDef_HEAD_INIT,
-    "_hmacopenssl",
-    NULL,
-    -1,
-    hmacopenssl_functions,
-    NULL,
-    NULL,
-    NULL,
-    NULL
-};
-
-PyMODINIT_FUNC
-PyInit__hmacopenssl(void)
-{
+static int
+hmacopenssl_exec(PyObject *m) {
     /* TODO build EVP_functions openssl_* entries dynamically based
      * on what hashes are supported rather than listing many
-     * but having some be unsupported.  Only init appropriate
+     * and having some unsupported.  Only init appropriate
      * constants. */
+    PyObject *temp;
 
-    Py_TYPE(&HmacType) = &PyType_Type;
-    if (PyType_Ready(&HmacType) < 0)
-        return NULL;
+    temp = PyType_FromSpec(&HmacType_spec);
+    if (temp == NULL) {
+        goto fail;
+    }
 
-    PyObject *m = PyModule_Create(&_hmacopenssl_module);
-    if (m == NULL)
-        return NULL;
+    if (PyModule_AddObject(m, "HMAC", temp) == -1) {
+        goto fail;
+    }
+
+    return 0;
 
-    Py_INCREF((PyObject *)&HmacType);
-    PyModule_AddObject(m, "HMAC", (PyObject *)&HmacType);
+fail:
+    Py_XDECREF(temp);
+    return -1;
+}
 
-    return m;
+static PyModuleDef_Slot hmacopenssl_slots[] = {
+    {Py_mod_exec, hmacopenssl_exec},
+    {0, NULL},
+};
+
+static struct PyModuleDef _hmacopenssl_def = {
+    PyModuleDef_HEAD_INIT,  /* m_base */ 
+    .m_name = "_hmacopenssl",
+    .m_methods = hmacopenssl_functions,
+    .m_slots = hmacopenssl_slots,
+    .m_size = sizeof(hmacopenssl_state)
+};
+
+
+PyMODINIT_FUNC
+PyInit__hmacopenssl(void)
+{
+    return PyModuleDef_Init(&_hmacopenssl_def);
 }
-- 
2.25.4


From c482ed4a74e06d17a612d3a286772b62e5a8001a Mon Sep 17 00:00:00 2001
From: Marcel Plch <mplch@redhat.com>
Date: Mon, 29 Jul 2019 13:05:04 +0200
Subject: [PATCH 12/43] revert cosmetic nitpick and remove trailing whitespace

---
 Lib/hmac.py            | 2 +-
 Modules/_hmacopenssl.c | 4 ++--
 2 files changed, 3 insertions(+), 3 deletions(-)

diff --git a/Lib/hmac.py b/Lib/hmac.py
index 2ec24da573..daabc8c142 100644
--- a/Lib/hmac.py
+++ b/Lib/hmac.py
@@ -48,7 +48,7 @@ class HMAC:
         if _hashlib.get_fips_mode():
             raise ValueError(
                 'hmac.HMAC is not available in FIPS mode. '
-                'Use hmac.new().'
+                + 'Use hmac.new().'
             )
 
         if not isinstance(key, (bytes, bytearray)):
diff --git a/Modules/_hmacopenssl.c b/Modules/_hmacopenssl.c
index 216ed04f23..221714ca43 100644
--- a/Modules/_hmacopenssl.c
+++ b/Modules/_hmacopenssl.c
@@ -363,7 +363,7 @@ static PyType_Slot HmacType_slots[] = {
 PyType_Spec HmacType_spec = {
     "_hmacopenssl.HMAC",    /* name */
     sizeof(HmacObject),     /* basicsize */
-    .flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE,     
+    .flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE,
     .slots = HmacType_slots,
 };
 
@@ -407,7 +407,7 @@ static PyModuleDef_Slot hmacopenssl_slots[] = {
 };
 
 static struct PyModuleDef _hmacopenssl_def = {
-    PyModuleDef_HEAD_INIT,  /* m_base */ 
+    PyModuleDef_HEAD_INIT,  /* m_base */
     .m_name = "_hmacopenssl",
     .m_methods = hmacopenssl_functions,
     .m_slots = hmacopenssl_slots,
-- 
2.25.4


From fceba59a20d8f22f618777874a63162f520bed69 Mon Sep 17 00:00:00 2001
From: Charalampos Stratakis <cstratak@redhat.com>
Date: Wed, 31 Jul 2019 15:43:43 +0200
Subject: [PATCH 13/43] Add initial tests for various hashes under FIPS mode

---
 Lib/test/test_fips.py | 64 +++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 64 insertions(+)
 create mode 100644 Lib/test/test_fips.py

diff --git a/Lib/test/test_fips.py b/Lib/test/test_fips.py
new file mode 100644
index 0000000000..bee911ef40
--- /dev/null
+++ b/Lib/test/test_fips.py
@@ -0,0 +1,64 @@
+import unittest
+import hmac, _hmacopenssl
+import hashlib, _hashlib
+
+
+
+class HashlibFipsTests(unittest.TestCase):
+
+    @unittest.skipUnless(hashlib.get_fips_mode(), "Test only when FIPS is enabled")
+    def test_fips_imports(self):
+        """blake2s and blake2b should fail to import in FIPS mode
+        """
+        with self.assertRaises(ValueError, msg='blake2s not available in FIPS'):
+            m = hashlib.blake2s()
+        with self.assertRaises(ValueError, msg='blake2b not available in FIPS'):
+            m = hashlib.blake2b()
+
+    def compare_hashes(self, python_hash, openssl_hash):
+        """
+        Compare between the python implementation and the openssl one that the digests
+        are the same
+        """
+        if python_hash.name.startswith('shake_128'):
+            m = python_hash.hexdigest(16)
+        elif python_hash.name.startswith('shake_256'):
+            m = python_hash.hexdigest(32)
+        else:
+            m = python_hash.hexdigest()
+        h = openssl_hash.hexdigest()
+
+        self.assertEqual(m, h)
+
+    @unittest.skipIf(hashlib.get_fips_mode(), "blake2 hashes are not available under FIPS")
+    def test_blake2_hashes(self):
+        self.compare_hashes(hashlib.blake2b(b'abc'), _hashlib.openssl_blake2b(b'abc'))
+        self.compare_hashes(hashlib.blake2s(b'abc'), _hashlib.openssl_blake2s(b'abc'))
+
+    def test_sha3_hashes(self):
+        self.compare_hashes(hashlib.sha3_224(b'abc'), _hashlib.openssl_sha3_224(b'abc'))
+        self.compare_hashes(hashlib.sha3_256(b'abc'), _hashlib.openssl_sha3_256(b'abc'))
+        self.compare_hashes(hashlib.sha3_384(b'abc'), _hashlib.openssl_sha3_384(b'abc'))
+        self.compare_hashes(hashlib.sha3_512(b'abc'), _hashlib.openssl_sha3_512(b'abc'))
+
+    @unittest.skipIf(hashlib.get_fips_mode(), "shake hashes are not available under FIPS")
+    def test_shake_hashes(self):
+        self.compare_hashes(hashlib.shake_128(b'abc'), _hashlib.openssl_shake_128(b'abc'))
+        self.compare_hashes(hashlib.shake_256(b'abc'), _hashlib.openssl_shake_256(b'abc'))
+
+    def test_sha(self):
+        self.compare_hashes(hashlib.sha1(b'abc'), _hashlib.openssl_sha1(b'abc'))
+        self.compare_hashes(hashlib.sha224(b'abc'), _hashlib.openssl_sha224(b'abc'))
+        self.compare_hashes(hashlib.sha256(b'abc'), _hashlib.openssl_sha256(b'abc'))
+        self.compare_hashes(hashlib.sha384(b'abc'), _hashlib.openssl_sha384(b'abc'))
+        self.compare_hashes(hashlib.sha512(b'abc'), _hashlib.openssl_sha512(b'abc'))
+
+    def test_hmac_digests(self):
+        self.compare_hashes(_hmacopenssl.new(b'My hovercraft is full of eels', digestmod='sha384'),
+                            hmac.new(b'My hovercraft is full of eels', digestmod='sha384'))
+
+
+
+
+if __name__ == "__main__":
+    unittest.main()
-- 
2.25.4


From 556b34545c0f7d72470faeb186371ffc9c2c997c Mon Sep 17 00:00:00 2001
From: Marcel Plch <mplch@redhat.com>
Date: Thu, 1 Aug 2019 16:39:37 +0200
Subject: [PATCH 14/43] Initialize HMAC type.

---
 Modules/_hmacopenssl.c | 12 ++++++++----
 1 file changed, 8 insertions(+), 4 deletions(-)

diff --git a/Modules/_hmacopenssl.c b/Modules/_hmacopenssl.c
index 221714ca43..239445a083 100644
--- a/Modules/_hmacopenssl.c
+++ b/Modules/_hmacopenssl.c
@@ -22,12 +22,12 @@
 #include "_hashopenssl.h"
 
 
-#include <openssl/hmac.h>
 
 typedef struct hmacopenssl_state {
     PyTypeObject *HmacType;
 } hmacopenssl_state;
 
+#include <openssl/hmac.h>
 
 typedef struct {
     PyObject_HEAD
@@ -39,7 +39,7 @@ typedef struct {
 #include "clinic/_hmacopenssl.c.h"
 /*[clinic input]
 module _hmacopenssl
-class _hmacopenssl.HMAC "HmacObject *" "PyModule_GetState(module)->HmacType"
+class _hmacopenssl.HMAC "HmacObject *" "((hmacopenssl_state *)PyModule_GetState(module))->HmacType"
 [clinic start generated code]*/
 /*[clinic end generated code: output=da39a3ee5e6b4b0d input=204b7f45847f57b4]*/
 
@@ -71,7 +71,7 @@ _hmacopenssl_new_impl(PyObject *module, Py_buffer *key,
         return NULL;
     }
 
-    /* name mut be lowercase */
+    /* name must be lowercase */
     for (int i=0; digestmod[i]; i++) {
         if (
             ((digestmod[i] < 'a') || (digestmod[i] > 'z'))
@@ -383,7 +383,8 @@ hmacopenssl_exec(PyObject *m) {
      * on what hashes are supported rather than listing many
      * and having some unsupported.  Only init appropriate
      * constants. */
-    PyObject *temp;
+    PyObject *temp = NULL;
+    hmacopenssl_state *state;
 
     temp = PyType_FromSpec(&HmacType_spec);
     if (temp == NULL) {
@@ -394,6 +395,9 @@ hmacopenssl_exec(PyObject *m) {
         goto fail;
     }
 
+    state = PyModule_GetState(m);
+    state->HmacType = (PyTypeObject *)temp;
+
     return 0;
 
 fail:
-- 
2.25.4


From 425d95325f304b0c2a04511a9f8e62208a5bace2 Mon Sep 17 00:00:00 2001
From: Petr Viktorin <pviktori@redhat.com>
Date: Thu, 1 Aug 2019 17:57:05 +0200
Subject: [PATCH 15/43] Use a stronger hash in multiprocessing handshake

Adapted from patch by David Malcolm,
https://bugs.python.org/issue17258
---
 Lib/multiprocessing/connection.py | 8 ++++++--
 1 file changed, 6 insertions(+), 2 deletions(-)

diff --git a/Lib/multiprocessing/connection.py b/Lib/multiprocessing/connection.py
index c9f995e5fa..64180b245e 100644
--- a/Lib/multiprocessing/connection.py
+++ b/Lib/multiprocessing/connection.py
@@ -42,6 +42,10 @@ BUFSIZE = 8192
 # A very generous timeout when it comes to local connections...
 CONNECTION_TIMEOUT = 20.
 
+# The hmac module implicitly defaults to using MD5.
+# Support using a stronger algorithm for the challenge/response code:
+HMAC_DIGEST_NAME='sha256'
+
 _mmap_counter = itertools.count()
 
 default_family = 'AF_INET'
@@ -735,7 +739,7 @@ def deliver_challenge(connection, authkey):
             "Authkey must be bytes, not {0!s}".format(type(authkey)))
     message = os.urandom(MESSAGE_LENGTH)
     connection.send_bytes(CHALLENGE + message)
-    digest = hmac.new(authkey, message, 'md5').digest()
+    digest = hmac.new(authkey, message, HMAC_DIGEST_NAME).digest()
     response = connection.recv_bytes(256)        # reject large message
     if response == digest:
         connection.send_bytes(WELCOME)
@@ -751,7 +755,7 @@ def answer_challenge(connection, authkey):
     message = connection.recv_bytes(256)         # reject large message
     assert message[:len(CHALLENGE)] == CHALLENGE, 'message = %r' % message
     message = message[len(CHALLENGE):]
-    digest = hmac.new(authkey, message, 'md5').digest()
+    digest = hmac.new(authkey, message, HMAC_DIGEST_NAME).digest()
     connection.send_bytes(digest)
     response = connection.recv_bytes(256)        # reject large message
     if response != WELCOME:
-- 
2.25.4


From 5369e3fd06c84a648d056226616c6e796e014b20 Mon Sep 17 00:00:00 2001
From: Marcel Plch <mplch@redhat.com>
Date: Fri, 2 Aug 2019 17:36:01 +0200
Subject: [PATCH 16/43] Fix refcounting

---
 Modules/_hmacopenssl.c | 35 ++++++++++++++++++++++++++++++++++-
 1 file changed, 34 insertions(+), 1 deletion(-)

diff --git a/Modules/_hmacopenssl.c b/Modules/_hmacopenssl.c
index 239445a083..9c2882833d 100644
--- a/Modules/_hmacopenssl.c
+++ b/Modules/_hmacopenssl.c
@@ -373,6 +373,34 @@ static struct PyMethodDef hmacopenssl_functions[] = {
     {NULL,      NULL}            /* Sentinel */
 };
 
+static int
+hmacopenssl_traverse(PyObject *self, visitproc visit, void *arg)
+{
+    hmacopenssl_state *state;
+
+    state = PyModule_GetState(self);
+
+    if (state) {
+        Py_VISIT(state->HmacType);
+    }
+
+    return 0;
+}
+
+static int
+hmacopenssl_clear(PyObject *self)
+{
+    hmacopenssl_state *state;
+
+    state = PyModule_GetState(self);
+
+    if (state) {
+        Py_CLEAR(state->HmacType);
+    }
+
+    return 0;
+}
+
 
 
 /* Initialize this module. */
@@ -396,7 +424,10 @@ hmacopenssl_exec(PyObject *m) {
     }
 
     state = PyModule_GetState(m);
+
     state->HmacType = (PyTypeObject *)temp;
+    Py_INCREF(temp);
+
 
     return 0;
 
@@ -415,7 +446,9 @@ static struct PyModuleDef _hmacopenssl_def = {
     .m_name = "_hmacopenssl",
     .m_methods = hmacopenssl_functions,
     .m_slots = hmacopenssl_slots,
-    .m_size = sizeof(hmacopenssl_state)
+    .m_size = sizeof(hmacopenssl_state),
+    .m_traverse = hmacopenssl_traverse,
+    .m_clear = hmacopenssl_clear
 };
 
 
-- 
2.25.4


From 11bc3a8ba5179defa0c6e86e27bdf25ab43809d4 Mon Sep 17 00:00:00 2001
From: Petr Viktorin <pviktori@redhat.com>
Date: Mon, 5 Aug 2019 13:37:05 +0200
Subject: [PATCH 17/43] hmac: Don't default to md5 in FIPS mode

---
 Lib/hmac.py | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/Lib/hmac.py b/Lib/hmac.py
index daabc8c142..0302364642 100644
--- a/Lib/hmac.py
+++ b/Lib/hmac.py
@@ -173,7 +173,7 @@ def new(key, msg=None, digestmod=''):
     """
     if _hashlib.get_fips_mode():
         if digestmod is None:
-            digestmod = 'md5'
+            raise ValueError("'digestmod' argument is mandatory in FIPS mode")
         name = _get_openssl_name(digestmod)
         result = _hmacopenssl.new(key, digestmod=name)
         if msg:
-- 
2.25.4


From 074d6c62025226c381eb0191eddb86322be9d4f1 Mon Sep 17 00:00:00 2001
From: Petr Viktorin <pviktori@redhat.com>
Date: Mon, 5 Aug 2019 14:20:58 +0200
Subject: [PATCH 18/43] Make _hmacopenssl.HMAC subclassable; subclass it as
 hmac.HMAC under FIPS

This removes the _hmacopenssl.new function.
---
 Lib/hmac.py                     | 26 +++++++-----
 Lib/test/test_fips.py           |  2 +-
 Modules/_hmacopenssl.c          | 75 ++++++++++++++++-----------------
 Modules/clinic/_hmacopenssl.c.h | 39 +----------------
 4 files changed, 55 insertions(+), 87 deletions(-)

diff --git a/Lib/hmac.py b/Lib/hmac.py
index 0302364642..e4222be7dc 100644
--- a/Lib/hmac.py
+++ b/Lib/hmac.py
@@ -143,6 +143,8 @@ class HMAC:
         return h.hexdigest()
 
 def _get_openssl_name(digestmod):
+    if digestmod is None:
+        raise ValueError("'digestmod' argument is mandatory in FIPS mode")
     if isinstance(digestmod, str):
         return digestmod.lower()
     elif callable(digestmod):
@@ -154,6 +156,19 @@ def _get_openssl_name(digestmod):
 
     return digestmod.name.lower().replace('_', '-')
 
+class HMAC_openssl(_hmacopenssl.HMAC):
+    def __new__(cls, key, msg = None, digestmod = None):
+        name = _get_openssl_name(digestmod)
+        result = _hmacopenssl.HMAC.__new__(cls, key, digestmod=name)
+        if msg:
+            result.update(msg)
+        return result
+
+
+if _hashlib.get_fips_mode():
+    HMAC = HMAC_openssl
+
+
 def new(key, msg=None, digestmod=''):
     """Create a new hashing object and return it.
 
@@ -171,16 +186,7 @@ def new(key, msg=None, digestmod=''):
     method, and can ask for the hash value at any time by calling its digest()
     or hexdigest() methods.
     """
-    if _hashlib.get_fips_mode():
-        if digestmod is None:
-            raise ValueError("'digestmod' argument is mandatory in FIPS mode")
-        name = _get_openssl_name(digestmod)
-        result = _hmacopenssl.new(key, digestmod=name)
-        if msg:
-            result.update(msg)
-        return result
-    else:
-        return HMAC(key, msg, digestmod)
+    return HMAC(key, msg, digestmod)
 
 
 def digest(key, msg, digest):
diff --git a/Lib/test/test_fips.py b/Lib/test/test_fips.py
index bee911ef40..34812e6098 100644
--- a/Lib/test/test_fips.py
+++ b/Lib/test/test_fips.py
@@ -54,7 +54,7 @@ class HashlibFipsTests(unittest.TestCase):
         self.compare_hashes(hashlib.sha512(b'abc'), _hashlib.openssl_sha512(b'abc'))
 
     def test_hmac_digests(self):
-        self.compare_hashes(_hmacopenssl.new(b'My hovercraft is full of eels', digestmod='sha384'),
+        self.compare_hashes(_hmacopenssl.HMAC(b'My hovercraft is full of eels', digestmod='sha384'),
                             hmac.new(b'My hovercraft is full of eels', digestmod='sha384'))
 
 
diff --git a/Modules/_hmacopenssl.c b/Modules/_hmacopenssl.c
index 9c2882833d..7d3d9739f3 100644
--- a/Modules/_hmacopenssl.c
+++ b/Modules/_hmacopenssl.c
@@ -41,33 +41,25 @@ typedef struct {
 module _hmacopenssl
 class _hmacopenssl.HMAC "HmacObject *" "((hmacopenssl_state *)PyModule_GetState(module))->HmacType"
 [clinic start generated code]*/
-/*[clinic end generated code: output=da39a3ee5e6b4b0d input=204b7f45847f57b4]*/
+/*[clinic end generated code: output=da39a3ee5e6b4b0d input=9fe07a087adc2cf9]*/
 
 
-/*[clinic input]
-_hmacopenssl.new
-
-    key: Py_buffer
-    *
-    digestmod: str
-
-Return a new hmac object.
-[clinic start generated code]*/
-
 static PyObject *
-_hmacopenssl_new_impl(PyObject *module, Py_buffer *key,
-                      const char *digestmod)
-/*[clinic end generated code: output=46f1cb4e02921922 input=be8c0c2e4fad508c]*/
+Hmac_new(PyTypeObject *subtype, PyObject *args, PyObject *kwds)
 {
-    hmacopenssl_state *state;
-
-    if (digestmod == NULL) {
-        PyErr_SetString(PyExc_ValueError, "digestmod must be specified");
+    static char *kwarg_names[] = {"key", "digestmod", NULL};
+    Py_buffer key = {NULL, NULL};
+    char *digestmod = NULL;
+
+    int ret = PyArg_ParseTupleAndKeywords(
+        args, kwds, "y*|$s:_hmacopenssl.HMAC", kwarg_names,
+        &key, &digestmod);
+    if (ret == 0) {
         return NULL;
     }
 
-    state = PyModule_GetState(module);
-    if (state == NULL) {
+    if (digestmod == NULL) {
+        PyErr_SetString(PyExc_ValueError, "digestmod must be specified");
         return NULL;
     }
 
@@ -106,8 +98,8 @@ _hmacopenssl_new_impl(PyObject *module, Py_buffer *key,
 
     int r = HMAC_Init_ex(
         ctx,
-        (const char*)key->buf,
-        key->len,
+        (const char*)key.buf,
+        key.len,
         digest,
         NULL /*impl*/);
     if (r == 0) {
@@ -115,7 +107,10 @@ _hmacopenssl_new_impl(PyObject *module, Py_buffer *key,
         goto error;
     }
 
-    retval = (HmacObject *)PyObject_New(HmacObject, state->HmacType);
+    PyBuffer_Release(&key);
+    key.buf = NULL;
+
+    retval = (HmacObject *)subtype->tp_alloc(subtype, 0);
     if (retval == NULL) {
         goto error;
     }
@@ -130,6 +125,7 @@ error:
     if (ctx) HMAC_CTX_free(ctx);
     if (name) Py_DECREF(name);
     if (retval) PyObject_Del(name);
+    if (key.buf) PyBuffer_Release(&key);
     return NULL;
 }
 
@@ -145,19 +141,27 @@ _hmacopenssl_HMAC_copy_impl(HmacObject *self)
 {
     HmacObject *retval;
 
-    retval = (HmacObject *)PyObject_New(HmacObject, (PyTypeObject *)PyObject_Type((PyObject *)self));
+    HMAC_CTX *ctx = HMAC_CTX_new();
+    if (ctx == NULL) {
+        return _setException(PyExc_ValueError);
+    }
+
+    int r = HMAC_CTX_copy(ctx, self->ctx);
+    if (r == 0) {
+        HMAC_CTX_free(ctx);
+        return _setException(PyExc_ValueError);
+    }
+
+    retval = (HmacObject *)Py_TYPE(self)->tp_alloc(Py_TYPE(self), 0);
     if (retval == NULL) {
+        HMAC_CTX_free(ctx);
         return NULL;
     }
-
+    retval->ctx = ctx;
     Py_INCREF(self->name);
     retval->name = self->name;
 
-    int r = HMAC_CTX_copy(retval->ctx, self->ctx);
-    if (r == 0) {
-        PyObject_Del(retval);
-        return _setException(PyExc_ValueError);
-    }
+    retval->lock = NULL;
 
     return (PyObject *)retval;
 }
@@ -169,8 +173,8 @@ _hmac_dealloc(HmacObject *self)
         PyThread_free_lock(self->lock);
     }
     HMAC_CTX_free(self->ctx);
-    Py_XDECREF(self->name);
-    PyObject_Del(self);
+    Py_CLEAR(self->name);
+    Py_TYPE(self)->tp_free(self);
 }
 
 static PyObject *
@@ -357,6 +361,7 @@ static PyType_Slot HmacType_slots[] = {
     {Py_tp_methods, Hmac_methods},
     {Py_tp_getset, Hmac_getset},
     {Py_tp_members, Hmac_members},
+    {Py_tp_new, Hmac_new},
     {0, NULL}
 };
 
@@ -368,11 +373,6 @@ PyType_Spec HmacType_spec = {
 };
 
 
-static struct PyMethodDef hmacopenssl_functions[] = {
-    _HMACOPENSSL_NEW_METHODDEF
-    {NULL,      NULL}            /* Sentinel */
-};
-
 static int
 hmacopenssl_traverse(PyObject *self, visitproc visit, void *arg)
 {
@@ -444,7 +444,6 @@ static PyModuleDef_Slot hmacopenssl_slots[] = {
 static struct PyModuleDef _hmacopenssl_def = {
     PyModuleDef_HEAD_INIT,  /* m_base */
     .m_name = "_hmacopenssl",
-    .m_methods = hmacopenssl_functions,
     .m_slots = hmacopenssl_slots,
     .m_size = sizeof(hmacopenssl_state),
     .m_traverse = hmacopenssl_traverse,
diff --git a/Modules/clinic/_hmacopenssl.c.h b/Modules/clinic/_hmacopenssl.c.h
index b472a6eddd..861acc11bf 100644
--- a/Modules/clinic/_hmacopenssl.c.h
+++ b/Modules/clinic/_hmacopenssl.c.h
@@ -2,43 +2,6 @@
 preserve
 [clinic start generated code]*/
 
-PyDoc_STRVAR(_hmacopenssl_new__doc__,
-"new($module, /, key, *, digestmod)\n"
-"--\n"
-"\n"
-"Return a new hmac object.");
-
-#define _HMACOPENSSL_NEW_METHODDEF    \
-    {"new", (PyCFunction)_hmacopenssl_new, METH_FASTCALL, _hmacopenssl_new__doc__},
-
-static PyObject *
-_hmacopenssl_new_impl(PyObject *module, Py_buffer *key,
-                      const char *digestmod);
-
-static PyObject *
-_hmacopenssl_new(PyObject *module, PyObject **args, Py_ssize_t nargs, PyObject *kwnames)
-{
-    PyObject *return_value = NULL;
-    static const char * const _keywords[] = {"key", "digestmod", NULL};
-    static _PyArg_Parser _parser = {"y*$s:new", _keywords, 0};
-    Py_buffer key = {NULL, NULL};
-    const char *digestmod;
-
-    if (!_PyArg_ParseStack(args, nargs, kwnames, &_parser,
-        &key, &digestmod)) {
-        goto exit;
-    }
-    return_value = _hmacopenssl_new_impl(module, &key, digestmod);
-
-exit:
-    /* Cleanup for key */
-    if (key.obj) {
-       PyBuffer_Release(&key);
-    }
-
-    return return_value;
-}
-
 PyDoc_STRVAR(_hmacopenssl_HMAC_copy__doc__,
 "copy($self, /)\n"
 "--\n"
@@ -130,4 +93,4 @@ _hmacopenssl_HMAC_hexdigest(HmacObject *self, PyObject *Py_UNUSED(ignored))
 {
     return _hmacopenssl_HMAC_hexdigest_impl(self);
 }
-/*[clinic end generated code: output=10b6e8cac6d7a2c9 input=a9049054013a1b77]*/
+/*[clinic end generated code: output=d93ad460795d49b5 input=a9049054013a1b77]*/
-- 
2.25.4


From 0cc9eab738876807a9116ee6fee57ac5757c1eb6 Mon Sep 17 00:00:00 2001
From: Petr Viktorin <pviktori@redhat.com>
Date: Mon, 5 Aug 2019 16:10:36 +0200
Subject: [PATCH 19/43] Fix _hmacopenssl.HMAC.block_size

---
 Modules/_hmacopenssl.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/Modules/_hmacopenssl.c b/Modules/_hmacopenssl.c
index 7d3d9739f3..a24c8ba022 100644
--- a/Modules/_hmacopenssl.c
+++ b/Modules/_hmacopenssl.c
@@ -318,7 +318,7 @@ _hmacopenssl_get_block_size(HmacObject *self, void *closure)
     if (md == NULL) {
         return _setException(PyExc_ValueError);
     }
-    return PyLong_FromLong(EVP_MD_size(md));
+    return PyLong_FromLong(EVP_MD_block_size(md));
 }
 
 static PyMethodDef Hmac_methods[] = {
-- 
2.25.4


From 79442a65e763d1942a14f52f8ceb83d51d39ca2b Mon Sep 17 00:00:00 2001
From: Petr Viktorin <pviktori@redhat.com>
Date: Mon, 5 Aug 2019 15:02:08 +0200
Subject: [PATCH 20/43] distutils upload: Skip md5 checksum in FIPS mode

---
 Lib/distutils/command/upload.py    | 12 +++++++++++-
 Lib/distutils/tests/test_upload.py | 13 +++++++++++--
 2 files changed, 22 insertions(+), 3 deletions(-)

diff --git a/Lib/distutils/command/upload.py b/Lib/distutils/command/upload.py
index 11afa24b77..79a6315a43 100644
--- a/Lib/distutils/command/upload.py
+++ b/Lib/distutils/command/upload.py
@@ -102,7 +102,6 @@ class upload(PyPIRCCommand):
             'content': (os.path.basename(filename),content),
             'filetype': command,
             'pyversion': pyversion,
-            'md5_digest': hashlib.md5(content).hexdigest(),
 
             # additional meta-data
             'metadata_version': '1.0',
@@ -122,6 +121,17 @@ class upload(PyPIRCCommand):
             'obsoletes': meta.get_obsoletes(),
             }
 
+        try:
+            digest = hashlib.md5(content).hexdigest()
+        except ValueError as e:
+            msg = 'calculating md5 checksum failed: %s' % e
+            self.announce(msg, log.ERROR)
+            if not hashlib.get_fips_mode():
+                # this really shouldn't fail
+                raise
+        else:
+            data['md5_digest'] = digest
+
         data['comment'] = ''
 
         if self.sign:
diff --git a/Lib/distutils/tests/test_upload.py b/Lib/distutils/tests/test_upload.py
index c17d8e7d54..b4b64e9773 100644
--- a/Lib/distutils/tests/test_upload.py
+++ b/Lib/distutils/tests/test_upload.py
@@ -3,6 +3,7 @@ import os
 import unittest
 import unittest.mock as mock
 from urllib.request import HTTPError
+import hashlib
 
 from test.support import run_unittest
 
@@ -130,7 +131,11 @@ class uploadTestCase(BasePyPIRCCommandTestCase):
 
         # what did we send ?
         headers = dict(self.last_open.req.headers)
-        self.assertEqual(headers['Content-length'], '2162')
+        if hashlib.get_fips_mode():
+            # md5 hash is omitted
+            self.assertEqual(headers['Content-length'], '2020')
+        else:
+            self.assertEqual(headers['Content-length'], '2162')
         content_type = headers['Content-type']
         self.assertTrue(content_type.startswith('multipart/form-data'))
         self.assertEqual(self.last_open.req.get_method(), 'POST')
@@ -166,7 +171,11 @@ class uploadTestCase(BasePyPIRCCommandTestCase):
         cmd.run()
 
         headers = dict(self.last_open.req.headers)
-        self.assertEqual(headers['Content-length'], '2172')
+        if hashlib.get_fips_mode():
+            # md5 hash is omitted
+            self.assertEqual(headers['Content-length'], '2030')
+        else:
+            self.assertEqual(headers['Content-length'], '2172')
         self.assertIn(b'long description\r', self.last_open.req.data)
 
     def test_upload_fails(self):
-- 
2.25.4


From b37078729378cb7c0b93ab15da0b1e4343a0b976 Mon Sep 17 00:00:00 2001
From: Petr Viktorin <pviktori@redhat.com>
Date: Mon, 5 Aug 2019 15:32:25 +0200
Subject: [PATCH 21/43] Fix HMAC tests on FIPS mode

---
 Lib/hmac.py           |  3 +++
 Lib/test/test_hmac.py | 26 ++++++++++++++++++++++++++
 2 files changed, 29 insertions(+)

diff --git a/Lib/hmac.py b/Lib/hmac.py
index e4222be7dc..394c81037b 100644
--- a/Lib/hmac.py
+++ b/Lib/hmac.py
@@ -158,6 +158,9 @@ def _get_openssl_name(digestmod):
 
 class HMAC_openssl(_hmacopenssl.HMAC):
     def __new__(cls, key, msg = None, digestmod = None):
+        if not isinstance(key, (bytes, bytearray)):
+            raise TypeError("key: expected bytes or bytearray, but got %r" % type(key).__name__)
+
         name = _get_openssl_name(digestmod)
         result = _hmacopenssl.HMAC.__new__(cls, key, digestmod=name)
         if msg:
diff --git a/Lib/test/test_hmac.py b/Lib/test/test_hmac.py
index 23c108f6e3..0a859817f6 100644
--- a/Lib/test/test_hmac.py
+++ b/Lib/test/test_hmac.py
@@ -288,6 +288,7 @@ class TestVectorsTestCase(unittest.TestCase):
     def test_sha512_rfc4231(self):
         self._rfc4231_test_cases(hashlib.sha512, 'sha512', 64, 128)
 
+    @unittest.skipIf(hashlib.get_fips_mode(), 'MockCrazyHash unacceptable in FIPS mode.')
     @requires_hashdigest('sha256')
     def test_legacy_block_size_warnings(self):
         class MockCrazyHash(object):
@@ -337,6 +338,14 @@ class ConstructorTestCase(unittest.TestCase):
         except Exception:
             self.fail("Standard constructor call raised exception.")
 
+    def test_normal_digestmod(self):
+        # Standard constructor call.
+        failed = 0
+        try:
+            h = hmac.HMAC(b"key", digestmod='sha1')
+        except Exception:
+            self.fail("Standard constructor call raised exception.")
+
     @requires_hashdigest('sha256')
     def test_with_str_key(self):
         # Pass a key of type str, which is an error, because it expects a key
@@ -404,6 +413,7 @@ class SanityTestCase(unittest.TestCase):
 
 class CopyTestCase(unittest.TestCase):
 
+    @unittest.skipIf(hashlib.get_fips_mode(), "Internal attributes unavailable in FIPS mode")
     @requires_hashdigest('sha256')
     def test_attributes(self):
         # Testing if attributes are of same type.
@@ -416,6 +426,7 @@ class CopyTestCase(unittest.TestCase):
         self.assertEqual(type(h1.outer), type(h2.outer),
             "Types of outer don't match.")
 
+    @unittest.skipIf(hashlib.get_fips_mode(), "Internal attributes unavailable in FIPS mode")
     @requires_hashdigest('sha256')
     def test_realcopy(self):
         # Testing if the copy method created a real copy.
@@ -428,6 +439,21 @@ class CopyTestCase(unittest.TestCase):
         self.assertTrue(id(h1.outer) != id(h2.outer),
             "No real copy of the attribute 'outer'.")
 
+    def test_realcopy(self):
+        # Testing if the copy method created a real copy.
+        h1 = hmac.HMAC(b"key", digestmod="sha1")
+        h2 = h1.copy()
+        # Using id() in case somebody has overridden __eq__/__ne__.
+        self.assertTrue(id(h1) != id(h2), "No real copy of the HMAC instance.")
+        old_digest = h1.digest()
+        assert h1.digest() == h2.digest()
+        h1.update(b'hi')
+        assert h1.digest() != h2.digest()
+        assert h2.digest() == old_digest
+        new_digest = h1.digest()
+        h2.update(b'hi')
+        assert h1.digest() == h2.digest() == new_digest
+
     @requires_hashdigest('sha256')
     def test_equality(self):
         # Testing if the copy has the same digests.
-- 
2.25.4


From 9481cec81e30e0dfaa988ade89c50bea91762856 Mon Sep 17 00:00:00 2001
From: Petr Viktorin <pviktori@redhat.com>
Date: Mon, 5 Aug 2019 16:37:12 +0200
Subject: [PATCH 22/43] test_tools: Skip md5sum tests in FIPS mode

---
 Lib/test/test_tools/test_md5sum.py | 4 ++++
 1 file changed, 4 insertions(+)

diff --git a/Lib/test/test_tools/test_md5sum.py b/Lib/test/test_tools/test_md5sum.py
index fb565b7377..7028a4dc21 100644
--- a/Lib/test/test_tools/test_md5sum.py
+++ b/Lib/test/test_tools/test_md5sum.py
@@ -4,11 +4,15 @@ import os
 import unittest
 from test import support
 from test.support.script_helper import assert_python_ok, assert_python_failure
+import hashlib
 
 from test.test_tools import scriptsdir, skip_if_missing
 
 skip_if_missing()
 
+if hashlib.get_fips_mode():
+    raise unittest.SkipTest("md5sum won't work at all in FIPS mode")
+
 class MD5SumTests(unittest.TestCase):
     @classmethod
     def setUpClass(cls):
-- 
2.25.4


From a12dec28f06338b7529da9bfeda2a8fe835395d2 Mon Sep 17 00:00:00 2001
From: Petr Viktorin <pviktori@redhat.com>
Date: Mon, 5 Aug 2019 18:23:57 +0200
Subject: [PATCH 23/43] Make hashlib tests pass in FIPS mode

---
 Lib/test/test_hashlib.py | 67 ++++++++++++++++++++++++++++------------
 1 file changed, 48 insertions(+), 19 deletions(-)

diff --git a/Lib/test/test_hashlib.py b/Lib/test/test_hashlib.py
index 2a55fd4309..9ae5efc451 100644
--- a/Lib/test/test_hashlib.py
+++ b/Lib/test/test_hashlib.py
@@ -28,6 +28,11 @@ COMPILED_WITH_PYDEBUG = hasattr(sys, 'gettotalrefcount')
 c_hashlib = import_fresh_module('hashlib', fresh=['_hashlib'])
 py_hashlib = import_fresh_module('hashlib', blocked=['_hashlib'])
 
+if hashlib.get_fips_mode():
+    FIPS_DISABLED = {'md5', 'MD5', 'blake2b', 'blake2s'}
+else:
+    FIPS_DISABLED = set()
+
 try:
     from _hashlib import HASH
 except ImportError:
@@ -88,6 +93,11 @@ class HashLibTestCase(unittest.TestCase):
     # Issue #14693: fallback modules are always compiled under POSIX
     _warn_on_extension_import = os.name == 'posix' or COMPILED_WITH_PYDEBUG
 
+    if hashlib.get_fips_mode():
+        shakes = set()
+        supported_hash_names = tuple(
+            n for n in supported_hash_names if n not in FIPS_DISABLED)
+
     def _conditional_import_module(self, module_name):
         """Import a module and return a reference to it or None on failure."""
         try:
@@ -95,8 +105,20 @@ class HashLibTestCase(unittest.TestCase):
         except ModuleNotFoundError as error:
             if self._warn_on_extension_import:
                 warnings.warn('Did a C extension fail to compile? %s' % error)
+        except ImportError as error:
+            if not hashlib.get_fips_mode():
+                raise
         return None
 
+    def _has_shake_extras(self, hasher):
+        """Return true if the hasher should have "shake" API (digest length)"""
+        if hasher.name not in self.shakes:
+            return False
+        _hashlib = self._conditional_import_module('_hashlib')
+        if _hashlib and isinstance(hasher, _hashlib.HASH):
+            return False
+        return True
+
     def __init__(self, *args, **kwargs):
         algorithms = set()
         for algorithm in self.supported_hash_names:
@@ -190,15 +212,13 @@ class HashLibTestCase(unittest.TestCase):
         a = array.array("b", range(10))
         for cons in self.hash_constructors:
             c = cons(a)
-            if (c.name in self.shakes
-                and not cons.__name__.startswith('openssl_')
-            ):
+            if self._has_shake_extras(c):
                 c.hexdigest(16)
             else:
                 c.hexdigest()
 
     def test_algorithms_guaranteed(self):
-        self.assertEqual(hashlib.algorithms_guaranteed,
+        self.assertEqual(hashlib.algorithms_guaranteed - FIPS_DISABLED,
             set(_algo for _algo in self.supported_hash_names
                   if _algo.islower()))
 
@@ -213,6 +233,12 @@ class HashLibTestCase(unittest.TestCase):
     def test_new_upper_to_lower(self):
         self.assertEqual(hashlib.new("SHA256").name, "sha256")
 
+    @unittest.skipUnless(hashlib.get_fips_mode(), "Builtin constructor only unavailable in FIPS mode")
+    def test_get_builtin_constructor_fips(self):
+        with self.assertRaises(AttributeError):
+            hashlib.__get_builtin_constructor
+
+    @unittest.skipIf(hashlib.get_fips_mode(), "No builtin constructors in FIPS mode")
     def test_get_builtin_constructor(self):
         get_builtin_constructor = getattr(hashlib,
                                           '__get_builtin_constructor')
@@ -242,9 +268,7 @@ class HashLibTestCase(unittest.TestCase):
     def test_hexdigest(self):
         for cons in self.hash_constructors:
             h = cons()
-            if (h.name in self.shakes
-                and not cons.__name__.startswith('openssl_')
-            ):
+            if self._has_shake_extras(h):
                 self.assertIsInstance(h.digest(16), bytes)
                 self.assertEqual(hexstr(h.digest(16)), h.hexdigest(16))
             else:
@@ -256,9 +280,7 @@ class HashLibTestCase(unittest.TestCase):
         large_sizes = (2**29, 2**32-10, 2**32+10, 2**61, 2**64-10, 2**64+10)
         for cons in self.hash_constructors:
             h = cons()
-            if h.name not in self.shakes:
-                continue
-            if cons.__name__.startswith('openssl_'):
+            if not self._has_shake_extras(h):
                 continue
             for digest in h.digest, h.hexdigest:
                 self.assertRaises(ValueError, digest, -10)
@@ -288,9 +310,7 @@ class HashLibTestCase(unittest.TestCase):
             m1.update(bees)
             m1.update(cees)
             m1.update(dees)
-            if (m1.name in self.shakes
-                and not cons.__name__.startswith('openssl_')
-            ):
+            if self._has_shake_extras(m1):
                 args = (16,)
             else:
                 args = ()
@@ -359,7 +379,8 @@ class HashLibTestCase(unittest.TestCase):
             self.assertRaises(TypeError, hash_object_constructor, 'spam')
 
     def test_no_unicode(self):
-        self.check_no_unicode('md5')
+        if not hashlib.get_fips_mode():
+            self.check_no_unicode('md5')
         self.check_no_unicode('sha1')
         self.check_no_unicode('sha224')
         self.check_no_unicode('sha256')
@@ -402,7 +423,8 @@ class HashLibTestCase(unittest.TestCase):
             self.assertIn(name.split("_")[0], repr(m))
 
     def test_blocksize_name(self):
-        self.check_blocksize_name('md5', 64, 16)
+        if not hashlib.get_fips_mode():
+            self.check_blocksize_name('md5', 64, 16)
         self.check_blocksize_name('sha1', 64, 20)
         self.check_blocksize_name('sha224', 64, 28)
         self.check_blocksize_name('sha256', 64, 32)
@@ -445,22 +467,27 @@ class HashLibTestCase(unittest.TestCase):
         self.check_blocksize_name('blake2b', 128, 64)
         self.check_blocksize_name('blake2s', 64, 32)
 
+    @unittest.skipIf(hashlib.get_fips_mode(), "md5 unacceptable in FIPS mode")
     def test_case_md5_0(self):
         self.check('md5', b'', 'd41d8cd98f00b204e9800998ecf8427e')
 
+    @unittest.skipIf(hashlib.get_fips_mode(), "md5 unacceptable in FIPS mode")
     def test_case_md5_1(self):
         self.check('md5', b'abc', '900150983cd24fb0d6963f7d28e17f72')
 
+    @unittest.skipIf(hashlib.get_fips_mode(), "md5 unacceptable in FIPS mode")
     def test_case_md5_2(self):
         self.check('md5',
                    b'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789',
                    'd174ab98d277d9f5a5611c2c9f419d9f')
 
+    @unittest.skipIf(hashlib.get_fips_mode(), "md5 unacceptable in FIPS mode")
     @unittest.skipIf(sys.maxsize < _4G + 5, 'test cannot run on 32-bit systems')
     @bigmemtest(size=_4G + 5, memuse=1, dry_run=False)
     def test_case_md5_huge(self, size):
         self.check('md5', b'A'*size, 'c9af2dff37468ce5dfee8f2cfc0a9c6d')
 
+    @unittest.skipIf(hashlib.get_fips_mode(), "md5 unacceptable in FIPS mode")
     @unittest.skipIf(sys.maxsize < _4G - 1, 'test cannot run on 32-bit systems')
     @bigmemtest(size=_4G - 1, memuse=1, dry_run=False)
     def test_case_md5_uintmax(self, size):
@@ -842,14 +869,16 @@ class HashLibTestCase(unittest.TestCase):
             m = cons(b'x' * gil_minsize)
             m.update(b'1')
 
-        m = hashlib.md5()
+        m = hashlib.sha1()
         m.update(b'1')
         m.update(b'#' * gil_minsize)
         m.update(b'1')
-        self.assertEqual(m.hexdigest(), 'cb1e1a2cbc80be75e19935d621fb9b21')
+        self.assertEqual(m.hexdigest(),
+                         'c45f7445ca0ea087d7a1758fbea07935f267c46a')
 
-        m = hashlib.md5(b'x' * gil_minsize)
-        self.assertEqual(m.hexdigest(), 'cfb767f225d58469c5de3632a8803958')
+        m = hashlib.sha1(b'x' * gil_minsize)
+        self.assertEqual(m.hexdigest(),
+                         '63fda1efde982ba1ffe9d53035bff5c9ce4758fb')
 
     @support.reap_threads
     def test_threaded_hashing(self):
-- 
2.25.4


From 35ebfc357302e14372529a63334ca60cbec49b3e Mon Sep 17 00:00:00 2001
From: Lumir Balhar <lbalhar@redhat.com>
Date: Wed, 14 Aug 2019 14:43:07 +0200
Subject: [PATCH 24/43] distutils upload: only add md5 if available, but
 *always* use sha256

---
 Lib/distutils/command/upload.py    |  3 ++-
 Lib/distutils/tests/test_upload.py | 14 ++++++++------
 2 files changed, 10 insertions(+), 7 deletions(-)

diff --git a/Lib/distutils/command/upload.py b/Lib/distutils/command/upload.py
index 79a6315a43..553617a8d8 100644
--- a/Lib/distutils/command/upload.py
+++ b/Lib/distutils/command/upload.py
@@ -102,6 +102,7 @@ class upload(PyPIRCCommand):
             'content': (os.path.basename(filename),content),
             'filetype': command,
             'pyversion': pyversion,
+            'sha256_digest': hashlib.sha256(content).hexdigest(),
 
             # additional meta-data
             'metadata_version': '1.0',
@@ -125,7 +126,7 @@ class upload(PyPIRCCommand):
             digest = hashlib.md5(content).hexdigest()
         except ValueError as e:
             msg = 'calculating md5 checksum failed: %s' % e
-            self.announce(msg, log.ERROR)
+            self.announce(msg, log.INFO)
             if not hashlib.get_fips_mode():
                 # this really shouldn't fail
                 raise
diff --git a/Lib/distutils/tests/test_upload.py b/Lib/distutils/tests/test_upload.py
index b4b64e9773..f720a7905d 100644
--- a/Lib/distutils/tests/test_upload.py
+++ b/Lib/distutils/tests/test_upload.py
@@ -132,10 +132,11 @@ class uploadTestCase(BasePyPIRCCommandTestCase):
         # what did we send ?
         headers = dict(self.last_open.req.headers)
         if hashlib.get_fips_mode():
-            # md5 hash is omitted
-            self.assertEqual(headers['Content-length'], '2020')
+            # only sha256 hash is used
+            self.assertEqual(headers['Content-length'], '2197')
         else:
-            self.assertEqual(headers['Content-length'], '2162')
+            # both sha256 and md5 hashes are used
+            self.assertEqual(headers['Content-length'], '2339')
         content_type = headers['Content-type']
         self.assertTrue(content_type.startswith('multipart/form-data'))
         self.assertEqual(self.last_open.req.get_method(), 'POST')
@@ -172,10 +173,11 @@ class uploadTestCase(BasePyPIRCCommandTestCase):
 
         headers = dict(self.last_open.req.headers)
         if hashlib.get_fips_mode():
-            # md5 hash is omitted
-            self.assertEqual(headers['Content-length'], '2030')
+            # only sha256 hash is used
+            self.assertEqual(headers['Content-length'], '2207')
         else:
-            self.assertEqual(headers['Content-length'], '2172')
+            # both sha256 and md5 hashes are used
+            self.assertEqual(headers['Content-length'], '2349')
         self.assertIn(b'long description\r', self.last_open.req.data)
 
     def test_upload_fails(self):
-- 
2.25.4


From 36204b47f4f48d4be8e4772f4ab8fc39ca98934b Mon Sep 17 00:00:00 2001
From: Christian Heimes <christian@python.org>
Date: Fri, 13 Sep 2019 02:30:00 +0200
Subject: [PATCH 25/43] bpo-9216: Add usedforsecurity to hashlib constructors
 (GH-16044)

The usedforsecurity keyword only argument added to the hash constructors is useful for FIPS builds and similar restrictive environment with non-technical requirements that legacy algorithms be forbidden by their implementations without being explicitly annotated as not being used for any security related purposes.  Linux distros with FIPS support benefit from this being standard rather than making up their own way(s) to do it.

Contributed and Signed-off-by: Christian Heimes christian@python.org
---
 Doc/library/hashlib.rst                       |  17 +-
 Lib/test/test_hashlib.py                      |   9 +
 Lib/uuid.py                                   |   7 +-
 .../2019-09-12-14-54-45.bpo-9216.W7QMpC.rst   |   2 +
 Modules/_blake2/blake2b_impl.c                |   5 +-
 Modules/_blake2/blake2s_impl.c                |   5 +-
 Modules/_blake2/clinic/blake2b_impl.c.h       |  27 +-
 Modules/_blake2/clinic/blake2s_impl.c.h       |  27 +-
 Modules/_hashopenssl.c                        | 151 ++++---
 Modules/_sha3/clinic/sha3module.c.h           |  48 ++-
 Modules/_sha3/sha3module.c                    |  41 +-
 Modules/clinic/_hashopenssl.c.h               | 407 ++++++++++++++----
 Modules/clinic/md5module.c.h                  |  28 +-
 Modules/clinic/sha1module.c.h                 |  28 +-
 Modules/clinic/sha256module.c.h               |  54 ++-
 Modules/clinic/sha512module.c.h               |  54 ++-
 Modules/md5module.c                           |   6 +-
 Modules/sha1module.c                          |   6 +-
 Modules/sha256module.c                        |  12 +-
 Modules/sha512module.c                        |  12 +-
 20 files changed, 709 insertions(+), 237 deletions(-)
 create mode 100644 Misc/NEWS.d/next/Library/2019-09-12-14-54-45.bpo-9216.W7QMpC.rst

diff --git a/Doc/library/hashlib.rst b/Doc/library/hashlib.rst
index a16c7cd4d7..6eb3a7bb4c 100644
--- a/Doc/library/hashlib.rst
+++ b/Doc/library/hashlib.rst
@@ -67,7 +67,7 @@ Constructors for hash algorithms that are always present in this module are
 :func:`sha1`, :func:`sha224`, :func:`sha256`, :func:`sha384`,
 :func:`sha512`, :func:`blake2b`, and :func:`blake2s`.
 :func:`md5` is normally available as well, though it
-may be missing if you are using a rare "FIPS compliant" build of Python.
+may be missing or blocked if you are using a rare "FIPS compliant" build of Python.
 Additional algorithms may also be available depending upon the OpenSSL
 library that Python uses on your platform. On most platforms the
 :func:`sha3_224`, :func:`sha3_256`, :func:`sha3_384`, :func:`sha3_512`,
@@ -80,6 +80,13 @@ library that Python uses on your platform. On most platforms the
 .. versionadded:: 3.6
    :func:`blake2b` and :func:`blake2s` were added.
 
+.. versionchanged:: 3.9
+   All hashlib constructors take a keyword-only argument *usedforsecurity*
+   with default value *True*. A false value allows the use of insecure and
+   blocked hashing algorithms in restricted environments. *False* indicates
+   that the hashing algorithm is not used in a security context, e.g. as a
+   non-cryptographic one-way compression function.
+
 For example, to obtain the digest of the byte string ``b'Nobody inspects the
 spammish repetition'``::
 
@@ -99,7 +106,7 @@ More condensed:
    >>> hashlib.sha224(b"Nobody inspects the spammish repetition").hexdigest()
    'a4337bc45a8fc544c03f52dc550cd6e1e87021bc896588bd79e901e2'
 
-.. function:: new(name[, data])
+.. function:: new(name[, data], *, usedforsecurity=True)
 
    Is a generic constructor that takes the string *name* of the desired
    algorithm as its first parameter.  It also exists to allow access to the
@@ -308,11 +315,13 @@ New hash objects are created by calling constructor functions:
 
 .. function:: blake2b(data=b'', *, digest_size=64, key=b'', salt=b'', \
                 person=b'', fanout=1, depth=1, leaf_size=0, node_offset=0,  \
-                node_depth=0, inner_size=0, last_node=False)
+                node_depth=0, inner_size=0, last_node=False, \
+                usedforsecurity=True)
 
 .. function:: blake2s(data=b'', *, digest_size=32, key=b'', salt=b'', \
                 person=b'', fanout=1, depth=1, leaf_size=0, node_offset=0,  \
-                node_depth=0, inner_size=0, last_node=False)
+                node_depth=0, inner_size=0, last_node=False, \
+                usedforsecurity=True)
 
 
 These functions return the corresponding hash objects for calculating
diff --git a/Lib/test/test_hashlib.py b/Lib/test/test_hashlib.py
index 9ae5efc451..08bb91f27b 100644
--- a/Lib/test/test_hashlib.py
+++ b/Lib/test/test_hashlib.py
@@ -226,6 +226,15 @@ class HashLibTestCase(unittest.TestCase):
         self.assertTrue(set(hashlib.algorithms_guaranteed).
                             issubset(hashlib.algorithms_available))
 
+    def test_usedforsecurity(self):
+        for cons in self.hash_constructors:
+            cons(usedforsecurity=True)
+            cons(usedforsecurity=False)
+            cons(b'', usedforsecurity=True)
+            cons(b'', usedforsecurity=False)
+        hashlib.new("sha256", usedforsecurity=True)
+        hashlib.new("sha256", usedforsecurity=False)
+
     def test_unknown_hash(self):
         self.assertRaises(ValueError, hashlib.new, 'spam spam spam spam spam')
         self.assertRaises(TypeError, hashlib.new, 1)
diff --git a/Lib/uuid.py b/Lib/uuid.py
index 188e16ba14..5f3bc9e8de 100644
--- a/Lib/uuid.py
+++ b/Lib/uuid.py
@@ -772,8 +772,11 @@ def uuid1(node=None, clock_seq=None):
 def uuid3(namespace, name):
     """Generate a UUID from the MD5 hash of a namespace UUID and a name."""
     from hashlib import md5
-    hash = md5(namespace.bytes + bytes(name, "utf-8")).digest()
-    return UUID(bytes=hash[:16], version=3)
+    digest = md5(
+        namespace.bytes + bytes(name, "utf-8"),
+        usedforsecurity=False
+    ).digest()
+    return UUID(bytes=digest[:16], version=3)
 
 def uuid4():
     """Generate a random UUID."""
diff --git a/Misc/NEWS.d/next/Library/2019-09-12-14-54-45.bpo-9216.W7QMpC.rst b/Misc/NEWS.d/next/Library/2019-09-12-14-54-45.bpo-9216.W7QMpC.rst
new file mode 100644
index 0000000000..a97ca4b8b4
--- /dev/null
+++ b/Misc/NEWS.d/next/Library/2019-09-12-14-54-45.bpo-9216.W7QMpC.rst
@@ -0,0 +1,2 @@
+hashlib constructors now support usedforsecurity flag to signal that a
+hashing algorithm is not used in a security context.
diff --git a/Modules/_blake2/blake2b_impl.c b/Modules/_blake2/blake2b_impl.c
index 97ce89d33c..16df232793 100644
--- a/Modules/_blake2/blake2b_impl.c
+++ b/Modules/_blake2/blake2b_impl.c
@@ -82,6 +82,7 @@ _blake2.blake2b.__new__ as py_blake2b_new
     node_depth: int = 0
     inner_size: int = 0
     last_node: bool = False
+    usedforsecurity: bool = True
 
 Return a new BLAKE2b hash object.
 [clinic start generated code]*/
@@ -91,8 +92,8 @@ py_blake2b_new_impl(PyTypeObject *type, PyObject *data, int digest_size,
                     Py_buffer *key, Py_buffer *salt, Py_buffer *person,
                     int fanout, int depth, unsigned long leaf_size,
                     unsigned long long node_offset, int node_depth,
-                    int inner_size, int last_node)
-/*[clinic end generated code: output=65e732c66c2297a0 input=82be35a4e6a9daa2]*/
+                    int inner_size, int last_node, int usedforsecurity)
+/*[clinic end generated code: output=32bfd8f043c6896f input=b947312abff46977]*/
 {
     BLAKE2bObject *self = NULL;
     Py_buffer buf;
diff --git a/Modules/_blake2/blake2s_impl.c b/Modules/_blake2/blake2s_impl.c
index c4447b4fe8..66a7ee567d 100644
--- a/Modules/_blake2/blake2s_impl.c
+++ b/Modules/_blake2/blake2s_impl.c
@@ -82,6 +82,7 @@ _blake2.blake2s.__new__ as py_blake2s_new
     node_depth: int = 0
     inner_size: int = 0
     last_node: bool = False
+    usedforsecurity: bool = True
 
 Return a new BLAKE2s hash object.
 [clinic start generated code]*/
@@ -91,8 +92,8 @@ py_blake2s_new_impl(PyTypeObject *type, PyObject *data, int digest_size,
                     Py_buffer *key, Py_buffer *salt, Py_buffer *person,
                     int fanout, int depth, unsigned long leaf_size,
                     unsigned long long node_offset, int node_depth,
-                    int inner_size, int last_node)
-/*[clinic end generated code: output=b95806be0514dcf7 input=641c0509debf714d]*/
+                    int inner_size, int last_node, int usedforsecurity)
+/*[clinic end generated code: output=556181f73905c686 input=4dda87723f23abb0]*/
 {
     BLAKE2sObject *self = NULL;
     Py_buffer buf;
diff --git a/Modules/_blake2/clinic/blake2b_impl.c.h b/Modules/_blake2/clinic/blake2b_impl.c.h
index cd329c07c9..07258c31c9 100644
--- a/Modules/_blake2/clinic/blake2b_impl.c.h
+++ b/Modules/_blake2/clinic/blake2b_impl.c.h
@@ -5,7 +5,8 @@ preserve
 PyDoc_STRVAR(py_blake2b_new__doc__,
 "blake2b(data=b\'\', /, *, digest_size=_blake2.blake2b.MAX_DIGEST_SIZE,\n"
 "        key=b\'\', salt=b\'\', person=b\'\', fanout=1, depth=1, leaf_size=0,\n"
-"        node_offset=0, node_depth=0, inner_size=0, last_node=False)\n"
+"        node_offset=0, node_depth=0, inner_size=0, last_node=False,\n"
+"        usedforsecurity=True)\n"
 "--\n"
 "\n"
 "Return a new BLAKE2b hash object.");
@@ -15,15 +16,15 @@ py_blake2b_new_impl(PyTypeObject *type, PyObject *data, int digest_size,
                     Py_buffer *key, Py_buffer *salt, Py_buffer *person,
                     int fanout, int depth, unsigned long leaf_size,
                     unsigned long long node_offset, int node_depth,
-                    int inner_size, int last_node);
+                    int inner_size, int last_node, int usedforsecurity);
 
 static PyObject *
 py_blake2b_new(PyTypeObject *type, PyObject *args, PyObject *kwargs)
 {
     PyObject *return_value = NULL;
-    static const char * const _keywords[] = {"", "digest_size", "key", "salt", "person", "fanout", "depth", "leaf_size", "node_offset", "node_depth", "inner_size", "last_node", NULL};
+    static const char * const _keywords[] = {"", "digest_size", "key", "salt", "person", "fanout", "depth", "leaf_size", "node_offset", "node_depth", "inner_size", "last_node", "usedforsecurity", NULL};
     static _PyArg_Parser _parser = {NULL, _keywords, "blake2b", 0};
-    PyObject *argsbuf[12];
+    PyObject *argsbuf[13];
     PyObject * const *fastargs;
     Py_ssize_t nargs = PyTuple_GET_SIZE(args);
     Py_ssize_t noptargs = nargs + (kwargs ? PyDict_GET_SIZE(kwargs) : 0) - 0;
@@ -39,6 +40,7 @@ py_blake2b_new(PyTypeObject *type, PyObject *args, PyObject *kwargs)
     int node_depth = 0;
     int inner_size = 0;
     int last_node = 0;
+    int usedforsecurity = 1;
 
     fastargs = _PyArg_UnpackKeywords(_PyTuple_CAST(args)->ob_item, nargs, kwargs, NULL, &_parser, 0, 1, 0, argsbuf);
     if (!fastargs) {
@@ -175,12 +177,21 @@ skip_optional_posonly:
             goto skip_optional_kwonly;
         }
     }
-    last_node = PyObject_IsTrue(fastargs[11]);
-    if (last_node < 0) {
+    if (fastargs[11]) {
+        last_node = PyObject_IsTrue(fastargs[11]);
+        if (last_node < 0) {
+            goto exit;
+        }
+        if (!--noptargs) {
+            goto skip_optional_kwonly;
+        }
+    }
+    usedforsecurity = PyObject_IsTrue(fastargs[12]);
+    if (usedforsecurity < 0) {
         goto exit;
     }
 skip_optional_kwonly:
-    return_value = py_blake2b_new_impl(type, data, digest_size, &key, &salt, &person, fanout, depth, leaf_size, node_offset, node_depth, inner_size, last_node);
+    return_value = py_blake2b_new_impl(type, data, digest_size, &key, &salt, &person, fanout, depth, leaf_size, node_offset, node_depth, inner_size, last_node, usedforsecurity);
 
 exit:
     /* Cleanup for key */
@@ -261,4 +272,4 @@ _blake2_blake2b_hexdigest(BLAKE2bObject *self, PyObject *Py_UNUSED(ignored))
 {
     return _blake2_blake2b_hexdigest_impl(self);
 }
-/*[clinic end generated code: output=cbb625d7f60c288c input=a9049054013a1b77]*/
+/*[clinic end generated code: output=2d6d0fe9aa42a42a input=a9049054013a1b77]*/
diff --git a/Modules/_blake2/clinic/blake2s_impl.c.h b/Modules/_blake2/clinic/blake2s_impl.c.h
index 560bd68160..71c5706fb6 100644
--- a/Modules/_blake2/clinic/blake2s_impl.c.h
+++ b/Modules/_blake2/clinic/blake2s_impl.c.h
@@ -5,7 +5,8 @@ preserve
 PyDoc_STRVAR(py_blake2s_new__doc__,
 "blake2s(data=b\'\', /, *, digest_size=_blake2.blake2s.MAX_DIGEST_SIZE,\n"
 "        key=b\'\', salt=b\'\', person=b\'\', fanout=1, depth=1, leaf_size=0,\n"
-"        node_offset=0, node_depth=0, inner_size=0, last_node=False)\n"
+"        node_offset=0, node_depth=0, inner_size=0, last_node=False,\n"
+"        usedforsecurity=True)\n"
 "--\n"
 "\n"
 "Return a new BLAKE2s hash object.");
@@ -15,15 +16,15 @@ py_blake2s_new_impl(PyTypeObject *type, PyObject *data, int digest_size,
                     Py_buffer *key, Py_buffer *salt, Py_buffer *person,
                     int fanout, int depth, unsigned long leaf_size,
                     unsigned long long node_offset, int node_depth,
-                    int inner_size, int last_node);
+                    int inner_size, int last_node, int usedforsecurity);
 
 static PyObject *
 py_blake2s_new(PyTypeObject *type, PyObject *args, PyObject *kwargs)
 {
     PyObject *return_value = NULL;
-    static const char * const _keywords[] = {"", "digest_size", "key", "salt", "person", "fanout", "depth", "leaf_size", "node_offset", "node_depth", "inner_size", "last_node", NULL};
+    static const char * const _keywords[] = {"", "digest_size", "key", "salt", "person", "fanout", "depth", "leaf_size", "node_offset", "node_depth", "inner_size", "last_node", "usedforsecurity", NULL};
     static _PyArg_Parser _parser = {NULL, _keywords, "blake2s", 0};
-    PyObject *argsbuf[12];
+    PyObject *argsbuf[13];
     PyObject * const *fastargs;
     Py_ssize_t nargs = PyTuple_GET_SIZE(args);
     Py_ssize_t noptargs = nargs + (kwargs ? PyDict_GET_SIZE(kwargs) : 0) - 0;
@@ -39,6 +40,7 @@ py_blake2s_new(PyTypeObject *type, PyObject *args, PyObject *kwargs)
     int node_depth = 0;
     int inner_size = 0;
     int last_node = 0;
+    int usedforsecurity = 1;
 
     fastargs = _PyArg_UnpackKeywords(_PyTuple_CAST(args)->ob_item, nargs, kwargs, NULL, &_parser, 0, 1, 0, argsbuf);
     if (!fastargs) {
@@ -175,12 +177,21 @@ skip_optional_posonly:
             goto skip_optional_kwonly;
         }
     }
-    last_node = PyObject_IsTrue(fastargs[11]);
-    if (last_node < 0) {
+    if (fastargs[11]) {
+        last_node = PyObject_IsTrue(fastargs[11]);
+        if (last_node < 0) {
+            goto exit;
+        }
+        if (!--noptargs) {
+            goto skip_optional_kwonly;
+        }
+    }
+    usedforsecurity = PyObject_IsTrue(fastargs[12]);
+    if (usedforsecurity < 0) {
         goto exit;
     }
 skip_optional_kwonly:
-    return_value = py_blake2s_new_impl(type, data, digest_size, &key, &salt, &person, fanout, depth, leaf_size, node_offset, node_depth, inner_size, last_node);
+    return_value = py_blake2s_new_impl(type, data, digest_size, &key, &salt, &person, fanout, depth, leaf_size, node_offset, node_depth, inner_size, last_node, usedforsecurity);
 
 exit:
     /* Cleanup for key */
@@ -261,4 +272,4 @@ _blake2_blake2s_hexdigest(BLAKE2sObject *self, PyObject *Py_UNUSED(ignored))
 {
     return _blake2_blake2s_hexdigest_impl(self);
 }
-/*[clinic end generated code: output=39af5a74c8805b36 input=a9049054013a1b77]*/
+/*[clinic end generated code: output=c80d8d06ce40a192 input=a9049054013a1b77]*/
diff --git a/Modules/_hashopenssl.c b/Modules/_hashopenssl.c
index 625e2d2e8f..8d0c7de2b2 100644
--- a/Modules/_hashopenssl.c
+++ b/Modules/_hashopenssl.c
@@ -517,7 +517,7 @@ static PyTypeObject EVPtype = {
 \
 static PyObject *
 EVPnew(const EVP_MD *digest,
-       const unsigned char *cp, Py_ssize_t len)
+       const unsigned char *cp, Py_ssize_t len, int usedforsecurity)
 {
     int result = 0;
     EVPobject *self;
@@ -530,6 +530,12 @@ EVPnew(const EVP_MD *digest,
     if ((self = newEVPobject()) == NULL)
         return NULL;
 
+    if (!usedforsecurity) {
+#ifdef EVP_MD_CTX_FLAG_NON_FIPS_ALLOW
+        EVP_MD_CTX_set_flags(self->ctx, EVP_MD_CTX_FLAG_NON_FIPS_ALLOW);
+#endif
+    }
+
     if (!EVP_DigestInit_ex(self->ctx, digest, NULL)) {
         _setException(PyExc_ValueError);
         Py_DECREF(self);
@@ -561,6 +567,8 @@ _hashlib.new as EVP_new
 
     name as name_obj: object
     string as data_obj: object(c_default="NULL") = b''
+    *
+    usedforsecurity: bool = True
 
 Return a new hash object using the named algorithm.
 
@@ -571,8 +579,9 @@ The MD5 and SHA1 algorithms are always supported.
 [clinic start generated code]*/
 
 static PyObject *
-EVP_new_impl(PyObject *module, PyObject *name_obj, PyObject *data_obj)
-/*[clinic end generated code: output=9e7cf664e04b0226 input=7eb79bf30058bd02]*/
+EVP_new_impl(PyObject *module, PyObject *name_obj, PyObject *data_obj,
+             int usedforsecurity)
+/*[clinic end generated code: output=ddd5053f92dffe90 input=c24554d0337be1b0]*/
 {
     Py_buffer view = { 0 };
     PyObject *ret_obj;
@@ -589,7 +598,9 @@ EVP_new_impl(PyObject *module, PyObject *name_obj, PyObject *data_obj)
 
     digest = py_digest_by_name(name);
 
-    ret_obj = EVPnew(digest, (unsigned char*)view.buf, view.len);
+    ret_obj = EVPnew(digest,
+                    (unsigned char*)view.buf, view.len,
+                    usedforsecurity);
 
     if (data_obj)
         PyBuffer_Release(&view);
@@ -597,7 +608,8 @@ EVP_new_impl(PyObject *module, PyObject *name_obj, PyObject *data_obj)
 }
 
 static PyObject*
-EVP_fast_new(PyObject *module, PyObject *data_obj, const EVP_MD *digest)
+EVP_fast_new(PyObject *module, PyObject *data_obj, const EVP_MD *digest,
+             int usedforsecurity)
 {
     Py_buffer view = { 0 };
     PyObject *ret_obj;
@@ -605,7 +617,8 @@ EVP_fast_new(PyObject *module, PyObject *data_obj, const EVP_MD *digest)
     if (data_obj)
         GET_BUFFER_VIEW_OR_ERROUT(data_obj, &view);
 
-    ret_obj = EVPnew(digest, (unsigned char*)view.buf, view.len);
+    ret_obj = EVPnew(digest, (unsigned char*)view.buf, view.len,
+                     usedforsecurity);
 
     if (data_obj)
         PyBuffer_Release(&view);
@@ -617,16 +630,19 @@ EVP_fast_new(PyObject *module, PyObject *data_obj, const EVP_MD *digest)
 _hashlib.openssl_md5
 
     string as data_obj: object(py_default="b''") = NULL
+    *
+    usedforsecurity: bool = True
 
 Returns a md5 hash object; optionally initialized with a string
 
 [clinic start generated code]*/
 
 static PyObject *
-_hashlib_openssl_md5_impl(PyObject *module, PyObject *data_obj)
-/*[clinic end generated code: output=6caae75b73e22c3f input=52010d3869e1b1a7]*/
+_hashlib_openssl_md5_impl(PyObject *module, PyObject *data_obj,
+                          int usedforsecurity)
+/*[clinic end generated code: output=87b0186440a44f8c input=990e36d5e689b16e]*/
 {
-    return EVP_fast_new(module, data_obj, EVP_md5());
+    return EVP_fast_new(module, data_obj, EVP_md5(), usedforsecurity);
 }
 
 
@@ -634,16 +650,19 @@ _hashlib_openssl_md5_impl(PyObject *module, PyObject *data_obj)
 _hashlib.openssl_sha1
 
     string as data_obj: object(py_default="b''") = NULL
+    *
+    usedforsecurity: bool = True
 
 Returns a sha1 hash object; optionally initialized with a string
 
 [clinic start generated code]*/
 
 static PyObject *
-_hashlib_openssl_sha1_impl(PyObject *module, PyObject *data_obj)
-/*[clinic end generated code: output=07606d8f75153e61 input=16807d30e4aa8ae9]*/
+_hashlib_openssl_sha1_impl(PyObject *module, PyObject *data_obj,
+                           int usedforsecurity)
+/*[clinic end generated code: output=6813024cf690670d input=948f2f4b6deabc10]*/
 {
-    return EVP_fast_new(module, data_obj, EVP_sha1());
+    return EVP_fast_new(module, data_obj, EVP_sha1(), usedforsecurity);
 }
 
 
@@ -651,16 +670,19 @@ _hashlib_openssl_sha1_impl(PyObject *module, PyObject *data_obj)
 _hashlib.openssl_sha224
 
     string as data_obj: object(py_default="b''") = NULL
+    *
+    usedforsecurity: bool = True
 
 Returns a sha224 hash object; optionally initialized with a string
 
 [clinic start generated code]*/
 
 static PyObject *
-_hashlib_openssl_sha224_impl(PyObject *module, PyObject *data_obj)
-/*[clinic end generated code: output=55e848761bcef0c9 input=5dbc2f1d84eb459b]*/
+_hashlib_openssl_sha224_impl(PyObject *module, PyObject *data_obj,
+                             int usedforsecurity)
+/*[clinic end generated code: output=a2dfe7cc4eb14ebb input=f9272821fadca505]*/
 {
-    return EVP_fast_new(module, data_obj, EVP_sha224());
+    return EVP_fast_new(module, data_obj, EVP_sha224(), usedforsecurity);
 }
 
 
@@ -668,16 +690,19 @@ _hashlib_openssl_sha224_impl(PyObject *module, PyObject *data_obj)
 _hashlib.openssl_sha256
 
     string as data_obj: object(py_default="b''") = NULL
+    *
+    usedforsecurity: bool = True
 
 Returns a sha256 hash object; optionally initialized with a string
 
 [clinic start generated code]*/
 
 static PyObject *
-_hashlib_openssl_sha256_impl(PyObject *module, PyObject *data_obj)
-/*[clinic end generated code: output=05851d7cce34ac65 input=a68a5d21cda5a80f]*/
+_hashlib_openssl_sha256_impl(PyObject *module, PyObject *data_obj,
+                             int usedforsecurity)
+/*[clinic end generated code: output=1f874a34870f0a68 input=549fad9d2930d4c5]*/
 {
-    return EVP_fast_new(module, data_obj, EVP_sha256());
+    return EVP_fast_new(module, data_obj, EVP_sha256(), usedforsecurity);
 }
 
 
@@ -685,16 +710,19 @@ _hashlib_openssl_sha256_impl(PyObject *module, PyObject *data_obj)
 _hashlib.openssl_sha384
 
     string as data_obj: object(py_default="b''") = NULL
+    *
+    usedforsecurity: bool = True
 
 Returns a sha384 hash object; optionally initialized with a string
 
 [clinic start generated code]*/
 
 static PyObject *
-_hashlib_openssl_sha384_impl(PyObject *module, PyObject *data_obj)
-/*[clinic end generated code: output=5101a4704a932c2f input=6bdfa006622b64ea]*/
+_hashlib_openssl_sha384_impl(PyObject *module, PyObject *data_obj,
+                             int usedforsecurity)
+/*[clinic end generated code: output=58529eff9ca457b2 input=48601a6e3bf14ad7]*/
 {
-    return EVP_fast_new(module, data_obj, EVP_sha384());
+    return EVP_fast_new(module, data_obj, EVP_sha384(), usedforsecurity);
 }
 
 
@@ -702,152 +730,179 @@ _hashlib_openssl_sha384_impl(PyObject *module, PyObject *data_obj)
 _hashlib.openssl_sha512
 
     string as data_obj: object(py_default="b''") = NULL
+    *
+    usedforsecurity: bool = True
 
 Returns a sha512 hash object; optionally initialized with a string
 
 [clinic start generated code]*/
 
 static PyObject *
-_hashlib_openssl_sha512_impl(PyObject *module, PyObject *data_obj)
-/*[clinic end generated code: output=20c8e63ee560a5cb input=ece50182ad4b76a6]*/
+_hashlib_openssl_sha512_impl(PyObject *module, PyObject *data_obj,
+                             int usedforsecurity)
+/*[clinic end generated code: output=2c744c9e4a40d5f6 input=c5c46a2a817aa98f]*/
 {
-    return EVP_fast_new(module, data_obj, EVP_sha512());
+    return EVP_fast_new(module, data_obj, EVP_sha512(), usedforsecurity);
 }
 
 /*[clinic input]
 _hashlib.openssl_blake2b
 
     string as data_obj: object(py_default="b''") = NULL
+    *
+    usedforsecurity: bool = True
 
 Returns a blake2b hash object; optionally initialized with a string
 
 [clinic start generated code]*/
 
 static PyObject *
-_hashlib_openssl_blake2b_impl(PyObject *module, PyObject *data_obj)
-/*[clinic end generated code: output=0d65acd1d9bb5e3f input=d9e6f84fa97e630d]*/
+_hashlib_openssl_blake2b_impl(PyObject *module, PyObject *data_obj,
+                              int usedforsecurity)
+/*[clinic end generated code: output=7a838b1643cde13e input=37247f187d9c4f4a]*/
 
 {
-    return EVP_fast_new(module, data_obj, EVP_blake2b512());
+    return EVP_fast_new(module, data_obj, EVP_blake2b512(), usedforsecurity);
 }
 
 /*[clinic input]
 _hashlib.openssl_blake2s
 
     string as data_obj: object(py_default="b''") = NULL
+    *
+    usedforsecurity: bool = True
 
 Returns a blake2s hash object; optionally initialized with a string
 
 [clinic start generated code]*/
 
 static PyObject *
-_hashlib_openssl_blake2s_impl(PyObject *module, PyObject *data_obj)
-/*[clinic end generated code: output=0f1330138041ec22 input=f1aec29465fc49c6]*/
+_hashlib_openssl_blake2s_impl(PyObject *module, PyObject *data_obj,
+                              int usedforsecurity)
+/*[clinic end generated code: output=4eda6b40757471da input=36e42912f87ff123]*/
 
 {
-    return EVP_fast_new(module, data_obj, EVP_blake2s256());
+    return EVP_fast_new(module, data_obj, EVP_blake2s256(), usedforsecurity);
 }
 
 /*[clinic input]
 _hashlib.openssl_sha3_224
 
     string as data_obj: object(py_default="b''") = NULL
+    *
+    usedforsecurity: bool = True
 
 Returns a sha3_224 hash object; optionally initialized with a string
 
 [clinic start generated code]*/
 
 static PyObject *
-_hashlib_openssl_sha3_224_impl(PyObject *module, PyObject *data_obj)
-/*[clinic end generated code: output=e3817bed6ecafc20 input=adc74bf14410af70]*/
+_hashlib_openssl_sha3_224_impl(PyObject *module, PyObject *data_obj,
+                               int usedforsecurity)
+/*[clinic end generated code: output=144641c1d144b974 input=450128ca92633287]*/
 
 {
-    return EVP_fast_new(module, data_obj, EVP_sha3_224());
+    return EVP_fast_new(module, data_obj, EVP_sha3_224(), usedforsecurity);
 }
 
 /*[clinic input]
 _hashlib.openssl_sha3_256
 
     string as data_obj: object(py_default="b''") = NULL
+    *
+    usedforsecurity: bool = True
 
 Returns a sha3_256 hash object; optionally initialized with a string
 
 [clinic start generated code]*/
 
 static PyObject *
-_hashlib_openssl_sha3_256_impl(PyObject *module, PyObject *data_obj)
-/*[clinic end generated code: output=9c15fac1ce09cd62 input=2922c3e78ab8bd2d]*/
+_hashlib_openssl_sha3_256_impl(PyObject *module, PyObject *data_obj,
+                               int usedforsecurity)
+/*[clinic end generated code: output=c61f1ab772d06668 input=dda801b8285bc25f]*/
 
 {
-    return EVP_fast_new(module, data_obj, EVP_sha3_256());
+    return EVP_fast_new(module, data_obj, EVP_sha3_256(), usedforsecurity);
 }
 
 /*[clinic input]
 _hashlib.openssl_sha3_384
 
     string as data_obj: object(py_default="b''") = NULL
+    *
+    usedforsecurity: bool = True
 
 Returns a sha3_384 hash object; optionally initialized with a string
 
 [clinic start generated code]*/
 
 static PyObject *
-_hashlib_openssl_sha3_384_impl(PyObject *module, PyObject *data_obj)
-/*[clinic end generated code: output=0923a782b9b81a40 input=742b499c372c8316]*/
+_hashlib_openssl_sha3_384_impl(PyObject *module, PyObject *data_obj,
+                               int usedforsecurity)
+/*[clinic end generated code: output=f68e4846858cf0ee input=3e2c46d271c64ec8]*/
 
 {
-    return EVP_fast_new(module, data_obj, EVP_sha3_384());
+    return EVP_fast_new(module, data_obj, EVP_sha3_384(), usedforsecurity);
 }
 
 /*[clinic input]
 _hashlib.openssl_sha3_512
 
     string as data_obj: object(py_default="b''") = NULL
+    *
+    usedforsecurity: bool = True
 
 Returns a sha3-512 hash object; optionally initialized with a string
 
 [clinic start generated code]*/
 
 static PyObject *
-_hashlib_openssl_sha3_512_impl(PyObject *module, PyObject *data_obj)
-/*[clinic end generated code: output=34bbe194704dbce4 input=46383f88e59a0385]*/
+_hashlib_openssl_sha3_512_impl(PyObject *module, PyObject *data_obj,
+                               int usedforsecurity)
+/*[clinic end generated code: output=2eede478c159354a input=64e2cc0c094d56f4]*/
 
 {
-    return EVP_fast_new(module, data_obj, EVP_sha3_512());
+    return EVP_fast_new(module, data_obj, EVP_sha3_512(), usedforsecurity);
 }
 
 /*[clinic input]
 _hashlib.openssl_shake_128
 
     string as data_obj: object(py_default="b''") = NULL
+    *
+    usedforsecurity: bool = True
 
 Returns a shake_128 hash object; optionally initialized with a string
 
 [clinic start generated code]*/
 
 static PyObject *
-_hashlib_openssl_shake_128_impl(PyObject *module, PyObject *data_obj)
-/*[clinic end generated code: output=a6ea5917ce65ef10 input=f256751eb810fdaa]*/
+_hashlib_openssl_shake_128_impl(PyObject *module, PyObject *data_obj,
+                                int usedforsecurity)
+/*[clinic end generated code: output=bc49cdd8ada1fa97 input=395c17aac1eb4d2e]*/
 
 {
-    return EVP_fast_new(module, data_obj, EVP_shake128());
+    return EVP_fast_new(module, data_obj, EVP_shake128(), usedforsecurity);
 }
 
 /*[clinic input]
 _hashlib.openssl_shake_256
 
     string as data_obj: object(py_default="b''") = NULL
+    *
+    usedforsecurity: bool = True
 
 Returns a shake_256 hash object; optionally initialized with a string
 
 [clinic start generated code]*/
 
 static PyObject *
-_hashlib_openssl_shake_256_impl(PyObject *module, PyObject *data_obj)
-/*[clinic end generated code: output=c91aaa96b000e186 input=d1331313db34116c]*/
+_hashlib_openssl_shake_256_impl(PyObject *module, PyObject *data_obj,
+                                int usedforsecurity)
+/*[clinic end generated code: output=358d213be8852df7 input=4fcf0b80fb663690]*/
 
 {
-    return EVP_fast_new(module, data_obj, EVP_shake256());
+    return EVP_fast_new(module, data_obj, EVP_shake256(), usedforsecurity);
 }
 
 
diff --git a/Modules/_sha3/clinic/sha3module.c.h b/Modules/_sha3/clinic/sha3module.c.h
index 554442df0e..1c79c26939 100644
--- a/Modules/_sha3/clinic/sha3module.c.h
+++ b/Modules/_sha3/clinic/sha3module.c.h
@@ -2,6 +2,52 @@
 preserve
 [clinic start generated code]*/
 
+PyDoc_STRVAR(py_sha3_new__doc__,
+"sha3_224(data=b\'\', /, *, usedforsecurity=True)\n"
+"--\n"
+"\n"
+"Return a new BLAKE2b hash object.");
+
+static PyObject *
+py_sha3_new_impl(PyTypeObject *type, PyObject *data, int usedforsecurity);
+
+static PyObject *
+py_sha3_new(PyTypeObject *type, PyObject *args, PyObject *kwargs)
+{
+    PyObject *return_value = NULL;
+    static const char * const _keywords[] = {"", "usedforsecurity", NULL};
+    static _PyArg_Parser _parser = {NULL, _keywords, "sha3_224", 0};
+    PyObject *argsbuf[2];
+    PyObject * const *fastargs;
+    Py_ssize_t nargs = PyTuple_GET_SIZE(args);
+    Py_ssize_t noptargs = nargs + (kwargs ? PyDict_GET_SIZE(kwargs) : 0) - 0;
+    PyObject *data = NULL;
+    int usedforsecurity = 1;
+
+    fastargs = _PyArg_UnpackKeywords(_PyTuple_CAST(args)->ob_item, nargs, kwargs, NULL, &_parser, 0, 1, 0, argsbuf);
+    if (!fastargs) {
+        goto exit;
+    }
+    if (nargs < 1) {
+        goto skip_optional_posonly;
+    }
+    noptargs--;
+    data = fastargs[0];
+skip_optional_posonly:
+    if (!noptargs) {
+        goto skip_optional_kwonly;
+    }
+    usedforsecurity = PyObject_IsTrue(fastargs[1]);
+    if (usedforsecurity < 0) {
+        goto exit;
+    }
+skip_optional_kwonly:
+    return_value = py_sha3_new_impl(type, data, usedforsecurity);
+
+exit:
+    return return_value;
+}
+
 PyDoc_STRVAR(_sha3_sha3_224_copy__doc__,
 "copy($self, /)\n"
 "--\n"
@@ -118,4 +164,4 @@ _sha3_shake_128_hexdigest(SHA3object *self, PyObject *arg)
 exit:
     return return_value;
 }
-/*[clinic end generated code: output=5b3e99b9a96471e8 input=a9049054013a1b77]*/
+/*[clinic end generated code: output=c8a97b34e80def62 input=a9049054013a1b77]*/
diff --git a/Modules/_sha3/sha3module.c b/Modules/_sha3/sha3module.c
index 3079e1e3a4..fc8b1b262a 100644
--- a/Modules/_sha3/sha3module.c
+++ b/Modules/_sha3/sha3module.c
@@ -171,22 +171,25 @@ newSHA3object(PyTypeObject *type)
     return newobj;
 }
 
+/*[clinic input]
+@classmethod
+_sha3.sha3_224.__new__ as py_sha3_new
+    data: object(c_default="NULL") = b''
+    /
+    *
+    usedforsecurity: bool = True
+
+Return a new BLAKE2b hash object.
+[clinic start generated code]*/
 
 static PyObject *
-py_sha3_new(PyTypeObject *type, PyObject *args, PyObject *kwargs)
+py_sha3_new_impl(PyTypeObject *type, PyObject *data, int usedforsecurity)
+/*[clinic end generated code: output=90409addc5d5e8b0 input=bcfcdf2e4368347a]*/
 {
     FAIL_RETURN_IN_FIPS_MODE(PyExc_ValueError, "_sha3");
     SHA3object *self = NULL;
     Py_buffer buf = {NULL, NULL};
     HashReturn res;
-    PyObject *data = NULL;
-
-    if (!_PyArg_NoKeywords(_PyType_Name(type), kwargs)) {
-        return NULL;
-    }
-    if (!PyArg_UnpackTuple(args, _PyType_Name(type), 0, 1, &data)) {
-        return NULL;
-    }
 
     self = newSHA3object(type);
     if (self == NULL) {
@@ -532,22 +535,22 @@ static PyGetSetDef SHA3_getseters[] = {
     }
 
 PyDoc_STRVAR(sha3_224__doc__,
-"sha3_224([data]) -> SHA3 object\n\
+"sha3_224([data], *, usedforsecurity=True) -> SHA3 object\n\
 \n\
 Return a new SHA3 hash object with a hashbit length of 28 bytes.");
 
 PyDoc_STRVAR(sha3_256__doc__,
-"sha3_256([data]) -> SHA3 object\n\
+"sha3_256([data], *, usedforsecurity=True) -> SHA3 object\n\
 \n\
 Return a new SHA3 hash object with a hashbit length of 32 bytes.");
 
 PyDoc_STRVAR(sha3_384__doc__,
-"sha3_384([data]) -> SHA3 object\n\
+"sha3_384([data], *, usedforsecurity=True) -> SHA3 object\n\
 \n\
 Return a new SHA3 hash object with a hashbit length of 48 bytes.");
 
 PyDoc_STRVAR(sha3_512__doc__,
-"sha3_512([data]) -> SHA3 object\n\
+"sha3_512([data], *, usedforsecurity=True) -> SHA3 object\n\
 \n\
 Return a new SHA3 hash object with a hashbit length of 64 bytes.");
 
@@ -558,22 +561,22 @@ SHA3_TYPE(SHA3_512type, "_sha3.sha3_512", sha3_512__doc__, SHA3_methods);
 
 #ifdef PY_WITH_KECCAK
 PyDoc_STRVAR(keccak_224__doc__,
-"keccak_224([data]) -> Keccak object\n\
+"keccak_224([data], *, usedforsecurity=True) -> Keccak object\n\
 \n\
 Return a new Keccak hash object with a hashbit length of 28 bytes.");
 
 PyDoc_STRVAR(keccak_256__doc__,
-"keccak_256([data]) -> Keccak object\n\
+"keccak_256([data], *, usedforsecurity=True) -> Keccak object\n\
 \n\
 Return a new Keccak hash object with a hashbit length of 32 bytes.");
 
 PyDoc_STRVAR(keccak_384__doc__,
-"keccak_384([data]) -> Keccak object\n\
+"keccak_384([data], *, usedforsecurity=True) -> Keccak object\n\
 \n\
 Return a new Keccak hash object with a hashbit length of 48 bytes.");
 
 PyDoc_STRVAR(keccak_512__doc__,
-"keccak_512([data]) -> Keccak object\n\
+"keccak_512([data], *, usedforsecurity=True) -> Keccak object\n\
 \n\
 Return a new Keccak hash object with a hashbit length of 64 bytes.");
 
@@ -675,12 +678,12 @@ static PyMethodDef SHAKE_methods[] = {
 };
 
 PyDoc_STRVAR(shake_128__doc__,
-"shake_128([data]) -> SHAKE object\n\
+"shake_128([data], *, usedforsecurity=True) -> SHAKE object\n\
 \n\
 Return a new SHAKE hash object.");
 
 PyDoc_STRVAR(shake_256__doc__,
-"shake_256([data]) -> SHAKE object\n\
+"shake_256([data], *, usedforsecurity=True) -> SHAKE object\n\
 \n\
 Return a new SHAKE hash object.");
 
diff --git a/Modules/clinic/_hashopenssl.c.h b/Modules/clinic/_hashopenssl.c.h
index e96a752e27..967884727b 100644
--- a/Modules/clinic/_hashopenssl.c.h
+++ b/Modules/clinic/_hashopenssl.c.h
@@ -66,7 +66,7 @@ PyDoc_STRVAR(EVP_update__doc__,
     {"update", (PyCFunction)EVP_update, METH_O, EVP_update__doc__},
 
 PyDoc_STRVAR(EVP_new__doc__,
-"new($module, /, name, string=b\'\')\n"
+"new($module, /, name, string=b\'\', *, usedforsecurity=True)\n"
 "--\n"
 "\n"
 "Return a new hash object using the named algorithm.\n"
@@ -80,18 +80,20 @@ PyDoc_STRVAR(EVP_new__doc__,
     {"new", (PyCFunction)(void(*)(void))EVP_new, METH_FASTCALL|METH_KEYWORDS, EVP_new__doc__},
 
 static PyObject *
-EVP_new_impl(PyObject *module, PyObject *name_obj, PyObject *data_obj);
+EVP_new_impl(PyObject *module, PyObject *name_obj, PyObject *data_obj,
+             int usedforsecurity);
 
 static PyObject *
 EVP_new(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames)
 {
     PyObject *return_value = NULL;
-    static const char * const _keywords[] = {"name", "string", NULL};
+    static const char * const _keywords[] = {"name", "string", "usedforsecurity", NULL};
     static _PyArg_Parser _parser = {NULL, _keywords, "new", 0};
-    PyObject *argsbuf[2];
+    PyObject *argsbuf[3];
     Py_ssize_t noptargs = nargs + (kwnames ? PyTuple_GET_SIZE(kwnames) : 0) - 1;
     PyObject *name_obj;
     PyObject *data_obj = NULL;
+    int usedforsecurity = 1;
 
     args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 1, 2, 0, argsbuf);
     if (!args) {
@@ -101,16 +103,29 @@ EVP_new(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwn
     if (!noptargs) {
         goto skip_optional_pos;
     }
-    data_obj = args[1];
+    if (args[1]) {
+        data_obj = args[1];
+        if (!--noptargs) {
+            goto skip_optional_pos;
+        }
+    }
 skip_optional_pos:
-    return_value = EVP_new_impl(module, name_obj, data_obj);
+    if (!noptargs) {
+        goto skip_optional_kwonly;
+    }
+    usedforsecurity = PyObject_IsTrue(args[2]);
+    if (usedforsecurity < 0) {
+        goto exit;
+    }
+skip_optional_kwonly:
+    return_value = EVP_new_impl(module, name_obj, data_obj, usedforsecurity);
 
 exit:
     return return_value;
 }
 
 PyDoc_STRVAR(_hashlib_openssl_md5__doc__,
-"openssl_md5($module, /, string=b\'\')\n"
+"openssl_md5($module, /, string=b\'\', *, usedforsecurity=True)\n"
 "--\n"
 "\n"
 "Returns a md5 hash object; optionally initialized with a string");
@@ -119,17 +134,19 @@ PyDoc_STRVAR(_hashlib_openssl_md5__doc__,
     {"openssl_md5", (PyCFunction)(void(*)(void))_hashlib_openssl_md5, METH_FASTCALL|METH_KEYWORDS, _hashlib_openssl_md5__doc__},
 
 static PyObject *
-_hashlib_openssl_md5_impl(PyObject *module, PyObject *data_obj);
+_hashlib_openssl_md5_impl(PyObject *module, PyObject *data_obj,
+                          int usedforsecurity);
 
 static PyObject *
 _hashlib_openssl_md5(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames)
 {
     PyObject *return_value = NULL;
-    static const char * const _keywords[] = {"string", NULL};
+    static const char * const _keywords[] = {"string", "usedforsecurity", NULL};
     static _PyArg_Parser _parser = {NULL, _keywords, "openssl_md5", 0};
-    PyObject *argsbuf[1];
+    PyObject *argsbuf[2];
     Py_ssize_t noptargs = nargs + (kwnames ? PyTuple_GET_SIZE(kwnames) : 0) - 0;
     PyObject *data_obj = NULL;
+    int usedforsecurity = 1;
 
     args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 0, 1, 0, argsbuf);
     if (!args) {
@@ -138,16 +155,29 @@ _hashlib_openssl_md5(PyObject *module, PyObject *const *args, Py_ssize_t nargs,
     if (!noptargs) {
         goto skip_optional_pos;
     }
-    data_obj = args[0];
+    if (args[0]) {
+        data_obj = args[0];
+        if (!--noptargs) {
+            goto skip_optional_pos;
+        }
+    }
 skip_optional_pos:
-    return_value = _hashlib_openssl_md5_impl(module, data_obj);
+    if (!noptargs) {
+        goto skip_optional_kwonly;
+    }
+    usedforsecurity = PyObject_IsTrue(args[1]);
+    if (usedforsecurity < 0) {
+        goto exit;
+    }
+skip_optional_kwonly:
+    return_value = _hashlib_openssl_md5_impl(module, data_obj, usedforsecurity);
 
 exit:
     return return_value;
 }
 
 PyDoc_STRVAR(_hashlib_openssl_sha1__doc__,
-"openssl_sha1($module, /, string=b\'\')\n"
+"openssl_sha1($module, /, string=b\'\', *, usedforsecurity=True)\n"
 "--\n"
 "\n"
 "Returns a sha1 hash object; optionally initialized with a string");
@@ -156,17 +186,19 @@ PyDoc_STRVAR(_hashlib_openssl_sha1__doc__,
     {"openssl_sha1", (PyCFunction)(void(*)(void))_hashlib_openssl_sha1, METH_FASTCALL|METH_KEYWORDS, _hashlib_openssl_sha1__doc__},
 
 static PyObject *
-_hashlib_openssl_sha1_impl(PyObject *module, PyObject *data_obj);
+_hashlib_openssl_sha1_impl(PyObject *module, PyObject *data_obj,
+                           int usedforsecurity);
 
 static PyObject *
 _hashlib_openssl_sha1(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames)
 {
     PyObject *return_value = NULL;
-    static const char * const _keywords[] = {"string", NULL};
+    static const char * const _keywords[] = {"string", "usedforsecurity", NULL};
     static _PyArg_Parser _parser = {NULL, _keywords, "openssl_sha1", 0};
-    PyObject *argsbuf[1];
+    PyObject *argsbuf[2];
     Py_ssize_t noptargs = nargs + (kwnames ? PyTuple_GET_SIZE(kwnames) : 0) - 0;
     PyObject *data_obj = NULL;
+    int usedforsecurity = 1;
 
     args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 0, 1, 0, argsbuf);
     if (!args) {
@@ -175,16 +207,29 @@ _hashlib_openssl_sha1(PyObject *module, PyObject *const *args, Py_ssize_t nargs,
     if (!noptargs) {
         goto skip_optional_pos;
     }
-    data_obj = args[0];
+    if (args[0]) {
+        data_obj = args[0];
+        if (!--noptargs) {
+            goto skip_optional_pos;
+        }
+    }
 skip_optional_pos:
-    return_value = _hashlib_openssl_sha1_impl(module, data_obj);
+    if (!noptargs) {
+        goto skip_optional_kwonly;
+    }
+    usedforsecurity = PyObject_IsTrue(args[1]);
+    if (usedforsecurity < 0) {
+        goto exit;
+    }
+skip_optional_kwonly:
+    return_value = _hashlib_openssl_sha1_impl(module, data_obj, usedforsecurity);
 
 exit:
     return return_value;
 }
 
 PyDoc_STRVAR(_hashlib_openssl_sha224__doc__,
-"openssl_sha224($module, /, string=b\'\')\n"
+"openssl_sha224($module, /, string=b\'\', *, usedforsecurity=True)\n"
 "--\n"
 "\n"
 "Returns a sha224 hash object; optionally initialized with a string");
@@ -193,17 +238,19 @@ PyDoc_STRVAR(_hashlib_openssl_sha224__doc__,
     {"openssl_sha224", (PyCFunction)(void(*)(void))_hashlib_openssl_sha224, METH_FASTCALL|METH_KEYWORDS, _hashlib_openssl_sha224__doc__},
 
 static PyObject *
-_hashlib_openssl_sha224_impl(PyObject *module, PyObject *data_obj);
+_hashlib_openssl_sha224_impl(PyObject *module, PyObject *data_obj,
+                             int usedforsecurity);
 
 static PyObject *
 _hashlib_openssl_sha224(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames)
 {
     PyObject *return_value = NULL;
-    static const char * const _keywords[] = {"string", NULL};
+    static const char * const _keywords[] = {"string", "usedforsecurity", NULL};
     static _PyArg_Parser _parser = {NULL, _keywords, "openssl_sha224", 0};
-    PyObject *argsbuf[1];
+    PyObject *argsbuf[2];
     Py_ssize_t noptargs = nargs + (kwnames ? PyTuple_GET_SIZE(kwnames) : 0) - 0;
     PyObject *data_obj = NULL;
+    int usedforsecurity = 1;
 
     args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 0, 1, 0, argsbuf);
     if (!args) {
@@ -212,16 +259,29 @@ _hashlib_openssl_sha224(PyObject *module, PyObject *const *args, Py_ssize_t narg
     if (!noptargs) {
         goto skip_optional_pos;
     }
-    data_obj = args[0];
+    if (args[0]) {
+        data_obj = args[0];
+        if (!--noptargs) {
+            goto skip_optional_pos;
+        }
+    }
 skip_optional_pos:
-    return_value = _hashlib_openssl_sha224_impl(module, data_obj);
+    if (!noptargs) {
+        goto skip_optional_kwonly;
+    }
+    usedforsecurity = PyObject_IsTrue(args[1]);
+    if (usedforsecurity < 0) {
+        goto exit;
+    }
+skip_optional_kwonly:
+    return_value = _hashlib_openssl_sha224_impl(module, data_obj, usedforsecurity);
 
 exit:
     return return_value;
 }
 
 PyDoc_STRVAR(_hashlib_openssl_sha256__doc__,
-"openssl_sha256($module, /, string=b\'\')\n"
+"openssl_sha256($module, /, string=b\'\', *, usedforsecurity=True)\n"
 "--\n"
 "\n"
 "Returns a sha256 hash object; optionally initialized with a string");
@@ -230,17 +290,19 @@ PyDoc_STRVAR(_hashlib_openssl_sha256__doc__,
     {"openssl_sha256", (PyCFunction)(void(*)(void))_hashlib_openssl_sha256, METH_FASTCALL|METH_KEYWORDS, _hashlib_openssl_sha256__doc__},
 
 static PyObject *
-_hashlib_openssl_sha256_impl(PyObject *module, PyObject *data_obj);
+_hashlib_openssl_sha256_impl(PyObject *module, PyObject *data_obj,
+                             int usedforsecurity);
 
 static PyObject *
 _hashlib_openssl_sha256(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames)
 {
     PyObject *return_value = NULL;
-    static const char * const _keywords[] = {"string", NULL};
+    static const char * const _keywords[] = {"string", "usedforsecurity", NULL};
     static _PyArg_Parser _parser = {NULL, _keywords, "openssl_sha256", 0};
-    PyObject *argsbuf[1];
+    PyObject *argsbuf[2];
     Py_ssize_t noptargs = nargs + (kwnames ? PyTuple_GET_SIZE(kwnames) : 0) - 0;
     PyObject *data_obj = NULL;
+    int usedforsecurity = 1;
 
     args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 0, 1, 0, argsbuf);
     if (!args) {
@@ -249,16 +311,29 @@ _hashlib_openssl_sha256(PyObject *module, PyObject *const *args, Py_ssize_t narg
     if (!noptargs) {
         goto skip_optional_pos;
     }
-    data_obj = args[0];
+    if (args[0]) {
+        data_obj = args[0];
+        if (!--noptargs) {
+            goto skip_optional_pos;
+        }
+    }
 skip_optional_pos:
-    return_value = _hashlib_openssl_sha256_impl(module, data_obj);
+    if (!noptargs) {
+        goto skip_optional_kwonly;
+    }
+    usedforsecurity = PyObject_IsTrue(args[1]);
+    if (usedforsecurity < 0) {
+        goto exit;
+    }
+skip_optional_kwonly:
+    return_value = _hashlib_openssl_sha256_impl(module, data_obj, usedforsecurity);
 
 exit:
     return return_value;
 }
 
 PyDoc_STRVAR(_hashlib_openssl_sha384__doc__,
-"openssl_sha384($module, /, string=b\'\')\n"
+"openssl_sha384($module, /, string=b\'\', *, usedforsecurity=True)\n"
 "--\n"
 "\n"
 "Returns a sha384 hash object; optionally initialized with a string");
@@ -267,17 +342,19 @@ PyDoc_STRVAR(_hashlib_openssl_sha384__doc__,
     {"openssl_sha384", (PyCFunction)(void(*)(void))_hashlib_openssl_sha384, METH_FASTCALL|METH_KEYWORDS, _hashlib_openssl_sha384__doc__},
 
 static PyObject *
-_hashlib_openssl_sha384_impl(PyObject *module, PyObject *data_obj);
+_hashlib_openssl_sha384_impl(PyObject *module, PyObject *data_obj,
+                             int usedforsecurity);
 
 static PyObject *
 _hashlib_openssl_sha384(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames)
 {
     PyObject *return_value = NULL;
-    static const char * const _keywords[] = {"string", NULL};
+    static const char * const _keywords[] = {"string", "usedforsecurity", NULL};
     static _PyArg_Parser _parser = {NULL, _keywords, "openssl_sha384", 0};
-    PyObject *argsbuf[1];
+    PyObject *argsbuf[2];
     Py_ssize_t noptargs = nargs + (kwnames ? PyTuple_GET_SIZE(kwnames) : 0) - 0;
     PyObject *data_obj = NULL;
+    int usedforsecurity = 1;
 
     args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 0, 1, 0, argsbuf);
     if (!args) {
@@ -286,16 +363,29 @@ _hashlib_openssl_sha384(PyObject *module, PyObject *const *args, Py_ssize_t narg
     if (!noptargs) {
         goto skip_optional_pos;
     }
-    data_obj = args[0];
+    if (args[0]) {
+        data_obj = args[0];
+        if (!--noptargs) {
+            goto skip_optional_pos;
+        }
+    }
 skip_optional_pos:
-    return_value = _hashlib_openssl_sha384_impl(module, data_obj);
+    if (!noptargs) {
+        goto skip_optional_kwonly;
+    }
+    usedforsecurity = PyObject_IsTrue(args[1]);
+    if (usedforsecurity < 0) {
+        goto exit;
+    }
+skip_optional_kwonly:
+    return_value = _hashlib_openssl_sha384_impl(module, data_obj, usedforsecurity);
 
 exit:
     return return_value;
 }
 
 PyDoc_STRVAR(_hashlib_openssl_sha512__doc__,
-"openssl_sha512($module, /, string=b\'\')\n"
+"openssl_sha512($module, /, string=b\'\', *, usedforsecurity=True)\n"
 "--\n"
 "\n"
 "Returns a sha512 hash object; optionally initialized with a string");
@@ -304,17 +394,19 @@ PyDoc_STRVAR(_hashlib_openssl_sha512__doc__,
     {"openssl_sha512", (PyCFunction)(void(*)(void))_hashlib_openssl_sha512, METH_FASTCALL|METH_KEYWORDS, _hashlib_openssl_sha512__doc__},
 
 static PyObject *
-_hashlib_openssl_sha512_impl(PyObject *module, PyObject *data_obj);
+_hashlib_openssl_sha512_impl(PyObject *module, PyObject *data_obj,
+                             int usedforsecurity);
 
 static PyObject *
 _hashlib_openssl_sha512(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames)
 {
     PyObject *return_value = NULL;
-    static const char * const _keywords[] = {"string", NULL};
+    static const char * const _keywords[] = {"string", "usedforsecurity", NULL};
     static _PyArg_Parser _parser = {NULL, _keywords, "openssl_sha512", 0};
-    PyObject *argsbuf[1];
+    PyObject *argsbuf[2];
     Py_ssize_t noptargs = nargs + (kwnames ? PyTuple_GET_SIZE(kwnames) : 0) - 0;
     PyObject *data_obj = NULL;
+    int usedforsecurity = 1;
 
     args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 0, 1, 0, argsbuf);
     if (!args) {
@@ -323,16 +415,29 @@ _hashlib_openssl_sha512(PyObject *module, PyObject *const *args, Py_ssize_t narg
     if (!noptargs) {
         goto skip_optional_pos;
     }
-    data_obj = args[0];
+    if (args[0]) {
+        data_obj = args[0];
+        if (!--noptargs) {
+            goto skip_optional_pos;
+        }
+    }
 skip_optional_pos:
-    return_value = _hashlib_openssl_sha512_impl(module, data_obj);
+    if (!noptargs) {
+        goto skip_optional_kwonly;
+    }
+    usedforsecurity = PyObject_IsTrue(args[1]);
+    if (usedforsecurity < 0) {
+        goto exit;
+    }
+skip_optional_kwonly:
+    return_value = _hashlib_openssl_sha512_impl(module, data_obj, usedforsecurity);
 
 exit:
     return return_value;
 }
 
 PyDoc_STRVAR(_hashlib_openssl_blake2b__doc__,
-"openssl_blake2b($module, /, string=b\'\')\n"
+"openssl_blake2b($module, /, string=b\'\', *, usedforsecurity=True)\n"
 "--\n"
 "\n"
 "Returns a blake2b hash object; optionally initialized with a string");
@@ -341,17 +446,19 @@ PyDoc_STRVAR(_hashlib_openssl_blake2b__doc__,
     {"openssl_blake2b", (PyCFunction)(void(*)(void))_hashlib_openssl_blake2b, METH_FASTCALL|METH_KEYWORDS, _hashlib_openssl_blake2b__doc__},
 
 static PyObject *
-_hashlib_openssl_blake2b_impl(PyObject *module, PyObject *data_obj);
+_hashlib_openssl_blake2b_impl(PyObject *module, PyObject *data_obj,
+                              int usedforsecurity);
 
 static PyObject *
 _hashlib_openssl_blake2b(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames)
 {
     PyObject *return_value = NULL;
-    static const char * const _keywords[] = {"string", NULL};
+    static const char * const _keywords[] = {"string", "usedforsecurity", NULL};
     static _PyArg_Parser _parser = {NULL, _keywords, "openssl_blake2b", 0};
-    PyObject *argsbuf[1];
+    PyObject *argsbuf[2];
     Py_ssize_t noptargs = nargs + (kwnames ? PyTuple_GET_SIZE(kwnames) : 0) - 0;
     PyObject *data_obj = NULL;
+    int usedforsecurity = 1;
 
     args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 0, 1, 0, argsbuf);
     if (!args) {
@@ -360,16 +467,29 @@ _hashlib_openssl_blake2b(PyObject *module, PyObject *const *args, Py_ssize_t nar
     if (!noptargs) {
         goto skip_optional_pos;
     }
-    data_obj = args[0];
+    if (args[0]) {
+        data_obj = args[0];
+        if (!--noptargs) {
+            goto skip_optional_pos;
+        }
+    }
 skip_optional_pos:
-    return_value = _hashlib_openssl_blake2b_impl(module, data_obj);
+    if (!noptargs) {
+        goto skip_optional_kwonly;
+    }
+    usedforsecurity = PyObject_IsTrue(args[1]);
+    if (usedforsecurity < 0) {
+        goto exit;
+    }
+skip_optional_kwonly:
+    return_value = _hashlib_openssl_blake2b_impl(module, data_obj, usedforsecurity);
 
 exit:
     return return_value;
 }
 
 PyDoc_STRVAR(_hashlib_openssl_blake2s__doc__,
-"openssl_blake2s($module, /, string=b\'\')\n"
+"openssl_blake2s($module, /, string=b\'\', *, usedforsecurity=True)\n"
 "--\n"
 "\n"
 "Returns a blake2s hash object; optionally initialized with a string");
@@ -378,17 +498,19 @@ PyDoc_STRVAR(_hashlib_openssl_blake2s__doc__,
     {"openssl_blake2s", (PyCFunction)(void(*)(void))_hashlib_openssl_blake2s, METH_FASTCALL|METH_KEYWORDS, _hashlib_openssl_blake2s__doc__},
 
 static PyObject *
-_hashlib_openssl_blake2s_impl(PyObject *module, PyObject *data_obj);
+_hashlib_openssl_blake2s_impl(PyObject *module, PyObject *data_obj,
+                              int usedforsecurity);
 
 static PyObject *
 _hashlib_openssl_blake2s(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames)
 {
     PyObject *return_value = NULL;
-    static const char * const _keywords[] = {"string", NULL};
+    static const char * const _keywords[] = {"string", "usedforsecurity", NULL};
     static _PyArg_Parser _parser = {NULL, _keywords, "openssl_blake2s", 0};
-    PyObject *argsbuf[1];
+    PyObject *argsbuf[2];
     Py_ssize_t noptargs = nargs + (kwnames ? PyTuple_GET_SIZE(kwnames) : 0) - 0;
     PyObject *data_obj = NULL;
+    int usedforsecurity = 1;
 
     args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 0, 1, 0, argsbuf);
     if (!args) {
@@ -397,16 +519,29 @@ _hashlib_openssl_blake2s(PyObject *module, PyObject *const *args, Py_ssize_t nar
     if (!noptargs) {
         goto skip_optional_pos;
     }
-    data_obj = args[0];
+    if (args[0]) {
+        data_obj = args[0];
+        if (!--noptargs) {
+            goto skip_optional_pos;
+        }
+    }
 skip_optional_pos:
-    return_value = _hashlib_openssl_blake2s_impl(module, data_obj);
+    if (!noptargs) {
+        goto skip_optional_kwonly;
+    }
+    usedforsecurity = PyObject_IsTrue(args[1]);
+    if (usedforsecurity < 0) {
+        goto exit;
+    }
+skip_optional_kwonly:
+    return_value = _hashlib_openssl_blake2s_impl(module, data_obj, usedforsecurity);
 
 exit:
     return return_value;
 }
 
 PyDoc_STRVAR(_hashlib_openssl_sha3_224__doc__,
-"openssl_sha3_224($module, /, string=b\'\')\n"
+"openssl_sha3_224($module, /, string=b\'\', *, usedforsecurity=True)\n"
 "--\n"
 "\n"
 "Returns a sha3_224 hash object; optionally initialized with a string");
@@ -415,17 +550,19 @@ PyDoc_STRVAR(_hashlib_openssl_sha3_224__doc__,
     {"openssl_sha3_224", (PyCFunction)(void(*)(void))_hashlib_openssl_sha3_224, METH_FASTCALL|METH_KEYWORDS, _hashlib_openssl_sha3_224__doc__},
 
 static PyObject *
-_hashlib_openssl_sha3_224_impl(PyObject *module, PyObject *data_obj);
+_hashlib_openssl_sha3_224_impl(PyObject *module, PyObject *data_obj,
+                               int usedforsecurity);
 
 static PyObject *
 _hashlib_openssl_sha3_224(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames)
 {
     PyObject *return_value = NULL;
-    static const char * const _keywords[] = {"string", NULL};
+    static const char * const _keywords[] = {"string", "usedforsecurity", NULL};
     static _PyArg_Parser _parser = {NULL, _keywords, "openssl_sha3_224", 0};
-    PyObject *argsbuf[1];
+    PyObject *argsbuf[2];
     Py_ssize_t noptargs = nargs + (kwnames ? PyTuple_GET_SIZE(kwnames) : 0) - 0;
     PyObject *data_obj = NULL;
+    int usedforsecurity = 1;
 
     args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 0, 1, 0, argsbuf);
     if (!args) {
@@ -434,16 +571,29 @@ _hashlib_openssl_sha3_224(PyObject *module, PyObject *const *args, Py_ssize_t na
     if (!noptargs) {
         goto skip_optional_pos;
     }
-    data_obj = args[0];
+    if (args[0]) {
+        data_obj = args[0];
+        if (!--noptargs) {
+            goto skip_optional_pos;
+        }
+    }
 skip_optional_pos:
-    return_value = _hashlib_openssl_sha3_224_impl(module, data_obj);
+    if (!noptargs) {
+        goto skip_optional_kwonly;
+    }
+    usedforsecurity = PyObject_IsTrue(args[1]);
+    if (usedforsecurity < 0) {
+        goto exit;
+    }
+skip_optional_kwonly:
+    return_value = _hashlib_openssl_sha3_224_impl(module, data_obj, usedforsecurity);
 
 exit:
     return return_value;
 }
 
 PyDoc_STRVAR(_hashlib_openssl_sha3_256__doc__,
-"openssl_sha3_256($module, /, string=b\'\')\n"
+"openssl_sha3_256($module, /, string=b\'\', *, usedforsecurity=True)\n"
 "--\n"
 "\n"
 "Returns a sha3_256 hash object; optionally initialized with a string");
@@ -452,17 +602,19 @@ PyDoc_STRVAR(_hashlib_openssl_sha3_256__doc__,
     {"openssl_sha3_256", (PyCFunction)(void(*)(void))_hashlib_openssl_sha3_256, METH_FASTCALL|METH_KEYWORDS, _hashlib_openssl_sha3_256__doc__},
 
 static PyObject *
-_hashlib_openssl_sha3_256_impl(PyObject *module, PyObject *data_obj);
+_hashlib_openssl_sha3_256_impl(PyObject *module, PyObject *data_obj,
+                               int usedforsecurity);
 
 static PyObject *
 _hashlib_openssl_sha3_256(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames)
 {
     PyObject *return_value = NULL;
-    static const char * const _keywords[] = {"string", NULL};
+    static const char * const _keywords[] = {"string", "usedforsecurity", NULL};
     static _PyArg_Parser _parser = {NULL, _keywords, "openssl_sha3_256", 0};
-    PyObject *argsbuf[1];
+    PyObject *argsbuf[2];
     Py_ssize_t noptargs = nargs + (kwnames ? PyTuple_GET_SIZE(kwnames) : 0) - 0;
     PyObject *data_obj = NULL;
+    int usedforsecurity = 1;
 
     args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 0, 1, 0, argsbuf);
     if (!args) {
@@ -471,16 +623,29 @@ _hashlib_openssl_sha3_256(PyObject *module, PyObject *const *args, Py_ssize_t na
     if (!noptargs) {
         goto skip_optional_pos;
     }
-    data_obj = args[0];
+    if (args[0]) {
+        data_obj = args[0];
+        if (!--noptargs) {
+            goto skip_optional_pos;
+        }
+    }
 skip_optional_pos:
-    return_value = _hashlib_openssl_sha3_256_impl(module, data_obj);
+    if (!noptargs) {
+        goto skip_optional_kwonly;
+    }
+    usedforsecurity = PyObject_IsTrue(args[1]);
+    if (usedforsecurity < 0) {
+        goto exit;
+    }
+skip_optional_kwonly:
+    return_value = _hashlib_openssl_sha3_256_impl(module, data_obj, usedforsecurity);
 
 exit:
     return return_value;
 }
 
 PyDoc_STRVAR(_hashlib_openssl_sha3_384__doc__,
-"openssl_sha3_384($module, /, string=b\'\')\n"
+"openssl_sha3_384($module, /, string=b\'\', *, usedforsecurity=True)\n"
 "--\n"
 "\n"
 "Returns a sha3_384 hash object; optionally initialized with a string");
@@ -489,17 +654,19 @@ PyDoc_STRVAR(_hashlib_openssl_sha3_384__doc__,
     {"openssl_sha3_384", (PyCFunction)(void(*)(void))_hashlib_openssl_sha3_384, METH_FASTCALL|METH_KEYWORDS, _hashlib_openssl_sha3_384__doc__},
 
 static PyObject *
-_hashlib_openssl_sha3_384_impl(PyObject *module, PyObject *data_obj);
+_hashlib_openssl_sha3_384_impl(PyObject *module, PyObject *data_obj,
+                               int usedforsecurity);
 
 static PyObject *
 _hashlib_openssl_sha3_384(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames)
 {
     PyObject *return_value = NULL;
-    static const char * const _keywords[] = {"string", NULL};
+    static const char * const _keywords[] = {"string", "usedforsecurity", NULL};
     static _PyArg_Parser _parser = {NULL, _keywords, "openssl_sha3_384", 0};
-    PyObject *argsbuf[1];
+    PyObject *argsbuf[2];
     Py_ssize_t noptargs = nargs + (kwnames ? PyTuple_GET_SIZE(kwnames) : 0) - 0;
     PyObject *data_obj = NULL;
+    int usedforsecurity = 1;
 
     args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 0, 1, 0, argsbuf);
     if (!args) {
@@ -508,16 +675,29 @@ _hashlib_openssl_sha3_384(PyObject *module, PyObject *const *args, Py_ssize_t na
     if (!noptargs) {
         goto skip_optional_pos;
     }
-    data_obj = args[0];
+    if (args[0]) {
+        data_obj = args[0];
+        if (!--noptargs) {
+            goto skip_optional_pos;
+        }
+    }
 skip_optional_pos:
-    return_value = _hashlib_openssl_sha3_384_impl(module, data_obj);
+    if (!noptargs) {
+        goto skip_optional_kwonly;
+    }
+    usedforsecurity = PyObject_IsTrue(args[1]);
+    if (usedforsecurity < 0) {
+        goto exit;
+    }
+skip_optional_kwonly:
+    return_value = _hashlib_openssl_sha3_384_impl(module, data_obj, usedforsecurity);
 
 exit:
     return return_value;
 }
 
 PyDoc_STRVAR(_hashlib_openssl_sha3_512__doc__,
-"openssl_sha3_512($module, /, string=b\'\')\n"
+"openssl_sha3_512($module, /, string=b\'\', *, usedforsecurity=True)\n"
 "--\n"
 "\n"
 "Returns a sha3-512 hash object; optionally initialized with a string");
@@ -526,17 +706,19 @@ PyDoc_STRVAR(_hashlib_openssl_sha3_512__doc__,
     {"openssl_sha3_512", (PyCFunction)(void(*)(void))_hashlib_openssl_sha3_512, METH_FASTCALL|METH_KEYWORDS, _hashlib_openssl_sha3_512__doc__},
 
 static PyObject *
-_hashlib_openssl_sha3_512_impl(PyObject *module, PyObject *data_obj);
+_hashlib_openssl_sha3_512_impl(PyObject *module, PyObject *data_obj,
+                               int usedforsecurity);
 
 static PyObject *
 _hashlib_openssl_sha3_512(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames)
 {
     PyObject *return_value = NULL;
-    static const char * const _keywords[] = {"string", NULL};
+    static const char * const _keywords[] = {"string", "usedforsecurity", NULL};
     static _PyArg_Parser _parser = {NULL, _keywords, "openssl_sha3_512", 0};
-    PyObject *argsbuf[1];
+    PyObject *argsbuf[2];
     Py_ssize_t noptargs = nargs + (kwnames ? PyTuple_GET_SIZE(kwnames) : 0) - 0;
     PyObject *data_obj = NULL;
+    int usedforsecurity = 1;
 
     args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 0, 1, 0, argsbuf);
     if (!args) {
@@ -545,16 +727,29 @@ _hashlib_openssl_sha3_512(PyObject *module, PyObject *const *args, Py_ssize_t na
     if (!noptargs) {
         goto skip_optional_pos;
     }
-    data_obj = args[0];
+    if (args[0]) {
+        data_obj = args[0];
+        if (!--noptargs) {
+            goto skip_optional_pos;
+        }
+    }
 skip_optional_pos:
-    return_value = _hashlib_openssl_sha3_512_impl(module, data_obj);
+    if (!noptargs) {
+        goto skip_optional_kwonly;
+    }
+    usedforsecurity = PyObject_IsTrue(args[1]);
+    if (usedforsecurity < 0) {
+        goto exit;
+    }
+skip_optional_kwonly:
+    return_value = _hashlib_openssl_sha3_512_impl(module, data_obj, usedforsecurity);
 
 exit:
     return return_value;
 }
 
 PyDoc_STRVAR(_hashlib_openssl_shake_128__doc__,
-"openssl_shake_128($module, /, string=b\'\')\n"
+"openssl_shake_128($module, /, string=b\'\', *, usedforsecurity=True)\n"
 "--\n"
 "\n"
 "Returns a shake_128 hash object; optionally initialized with a string");
@@ -563,17 +758,19 @@ PyDoc_STRVAR(_hashlib_openssl_shake_128__doc__,
     {"openssl_shake_128", (PyCFunction)(void(*)(void))_hashlib_openssl_shake_128, METH_FASTCALL|METH_KEYWORDS, _hashlib_openssl_shake_128__doc__},
 
 static PyObject *
-_hashlib_openssl_shake_128_impl(PyObject *module, PyObject *data_obj);
+_hashlib_openssl_shake_128_impl(PyObject *module, PyObject *data_obj,
+                                int usedforsecurity);
 
 static PyObject *
 _hashlib_openssl_shake_128(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames)
 {
     PyObject *return_value = NULL;
-    static const char * const _keywords[] = {"string", NULL};
+    static const char * const _keywords[] = {"string", "usedforsecurity", NULL};
     static _PyArg_Parser _parser = {NULL, _keywords, "openssl_shake_128", 0};
-    PyObject *argsbuf[1];
+    PyObject *argsbuf[2];
     Py_ssize_t noptargs = nargs + (kwnames ? PyTuple_GET_SIZE(kwnames) : 0) - 0;
     PyObject *data_obj = NULL;
+    int usedforsecurity = 1;
 
     args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 0, 1, 0, argsbuf);
     if (!args) {
@@ -582,16 +779,29 @@ _hashlib_openssl_shake_128(PyObject *module, PyObject *const *args, Py_ssize_t n
     if (!noptargs) {
         goto skip_optional_pos;
     }
-    data_obj = args[0];
+    if (args[0]) {
+        data_obj = args[0];
+        if (!--noptargs) {
+            goto skip_optional_pos;
+        }
+    }
 skip_optional_pos:
-    return_value = _hashlib_openssl_shake_128_impl(module, data_obj);
+    if (!noptargs) {
+        goto skip_optional_kwonly;
+    }
+    usedforsecurity = PyObject_IsTrue(args[1]);
+    if (usedforsecurity < 0) {
+        goto exit;
+    }
+skip_optional_kwonly:
+    return_value = _hashlib_openssl_shake_128_impl(module, data_obj, usedforsecurity);
 
 exit:
     return return_value;
 }
 
 PyDoc_STRVAR(_hashlib_openssl_shake_256__doc__,
-"openssl_shake_256($module, /, string=b\'\')\n"
+"openssl_shake_256($module, /, string=b\'\', *, usedforsecurity=True)\n"
 "--\n"
 "\n"
 "Returns a shake_256 hash object; optionally initialized with a string");
@@ -600,17 +810,19 @@ PyDoc_STRVAR(_hashlib_openssl_shake_256__doc__,
     {"openssl_shake_256", (PyCFunction)(void(*)(void))_hashlib_openssl_shake_256, METH_FASTCALL|METH_KEYWORDS, _hashlib_openssl_shake_256__doc__},
 
 static PyObject *
-_hashlib_openssl_shake_256_impl(PyObject *module, PyObject *data_obj);
+_hashlib_openssl_shake_256_impl(PyObject *module, PyObject *data_obj,
+                                int usedforsecurity);
 
 static PyObject *
 _hashlib_openssl_shake_256(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames)
 {
     PyObject *return_value = NULL;
-    static const char * const _keywords[] = {"string", NULL};
+    static const char * const _keywords[] = {"string", "usedforsecurity", NULL};
     static _PyArg_Parser _parser = {NULL, _keywords, "openssl_shake_256", 0};
-    PyObject *argsbuf[1];
+    PyObject *argsbuf[2];
     Py_ssize_t noptargs = nargs + (kwnames ? PyTuple_GET_SIZE(kwnames) : 0) - 0;
     PyObject *data_obj = NULL;
+    int usedforsecurity = 1;
 
     args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 0, 1, 0, argsbuf);
     if (!args) {
@@ -619,9 +831,22 @@ _hashlib_openssl_shake_256(PyObject *module, PyObject *const *args, Py_ssize_t n
     if (!noptargs) {
         goto skip_optional_pos;
     }
-    data_obj = args[0];
+    if (args[0]) {
+        data_obj = args[0];
+        if (!--noptargs) {
+            goto skip_optional_pos;
+        }
+    }
 skip_optional_pos:
-    return_value = _hashlib_openssl_shake_256_impl(module, data_obj);
+    if (!noptargs) {
+        goto skip_optional_kwonly;
+    }
+    usedforsecurity = PyObject_IsTrue(args[1]);
+    if (usedforsecurity < 0) {
+        goto exit;
+    }
+skip_optional_kwonly:
+    return_value = _hashlib_openssl_shake_256_impl(module, data_obj, usedforsecurity);
 
 exit:
     return return_value;
@@ -942,4 +1167,4 @@ _hashlib_get_fips_mode(PyObject *module, PyObject *Py_UNUSED(ignored))
 #ifndef _HASHLIB_SCRYPT_METHODDEF
     #define _HASHLIB_SCRYPT_METHODDEF
 #endif /* !defined(_HASHLIB_SCRYPT_METHODDEF) */
-/*[clinic end generated code: output=be8e21a10dff71e7 input=a9049054013a1b77]*/
+/*[clinic end generated code: output=3db4f18f12892fa4 input=a9049054013a1b77]*/
diff --git a/Modules/clinic/md5module.c.h b/Modules/clinic/md5module.c.h
index 12484cc0e3..c109f9efec 100644
--- a/Modules/clinic/md5module.c.h
+++ b/Modules/clinic/md5module.c.h
@@ -66,7 +66,7 @@ PyDoc_STRVAR(MD5Type_update__doc__,
     {"update", (PyCFunction)MD5Type_update, METH_O, MD5Type_update__doc__},
 
 PyDoc_STRVAR(_md5_md5__doc__,
-"md5($module, /, string=b\'\')\n"
+"md5($module, /, string=b\'\', *, usedforsecurity=True)\n"
 "--\n"
 "\n"
 "Return a new MD5 hash object; optionally initialized with a string.");
@@ -75,17 +75,18 @@ PyDoc_STRVAR(_md5_md5__doc__,
     {"md5", (PyCFunction)(void(*)(void))_md5_md5, METH_FASTCALL|METH_KEYWORDS, _md5_md5__doc__},
 
 static PyObject *
-_md5_md5_impl(PyObject *module, PyObject *string);
+_md5_md5_impl(PyObject *module, PyObject *string, int usedforsecurity);
 
 static PyObject *
 _md5_md5(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames)
 {
     PyObject *return_value = NULL;
-    static const char * const _keywords[] = {"string", NULL};
+    static const char * const _keywords[] = {"string", "usedforsecurity", NULL};
     static _PyArg_Parser _parser = {NULL, _keywords, "md5", 0};
-    PyObject *argsbuf[1];
+    PyObject *argsbuf[2];
     Py_ssize_t noptargs = nargs + (kwnames ? PyTuple_GET_SIZE(kwnames) : 0) - 0;
     PyObject *string = NULL;
+    int usedforsecurity = 1;
 
     args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 0, 1, 0, argsbuf);
     if (!args) {
@@ -94,11 +95,24 @@ _md5_md5(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kw
     if (!noptargs) {
         goto skip_optional_pos;
     }
-    string = args[0];
+    if (args[0]) {
+        string = args[0];
+        if (!--noptargs) {
+            goto skip_optional_pos;
+        }
+    }
 skip_optional_pos:
-    return_value = _md5_md5_impl(module, string);
+    if (!noptargs) {
+        goto skip_optional_kwonly;
+    }
+    usedforsecurity = PyObject_IsTrue(args[1]);
+    if (usedforsecurity < 0) {
+        goto exit;
+    }
+skip_optional_kwonly:
+    return_value = _md5_md5_impl(module, string, usedforsecurity);
 
 exit:
     return return_value;
 }
-/*[clinic end generated code: output=53133f08cf9095fc input=a9049054013a1b77]*/
+/*[clinic end generated code: output=dbe3abc60086f3ef input=a9049054013a1b77]*/
diff --git a/Modules/clinic/sha1module.c.h b/Modules/clinic/sha1module.c.h
index 001c6af737..fc37b1ab88 100644
--- a/Modules/clinic/sha1module.c.h
+++ b/Modules/clinic/sha1module.c.h
@@ -66,7 +66,7 @@ PyDoc_STRVAR(SHA1Type_update__doc__,
     {"update", (PyCFunction)SHA1Type_update, METH_O, SHA1Type_update__doc__},
 
 PyDoc_STRVAR(_sha1_sha1__doc__,
-"sha1($module, /, string=b\'\')\n"
+"sha1($module, /, string=b\'\', *, usedforsecurity=True)\n"
 "--\n"
 "\n"
 "Return a new SHA1 hash object; optionally initialized with a string.");
@@ -75,17 +75,18 @@ PyDoc_STRVAR(_sha1_sha1__doc__,
     {"sha1", (PyCFunction)(void(*)(void))_sha1_sha1, METH_FASTCALL|METH_KEYWORDS, _sha1_sha1__doc__},
 
 static PyObject *
-_sha1_sha1_impl(PyObject *module, PyObject *string);
+_sha1_sha1_impl(PyObject *module, PyObject *string, int usedforsecurity);
 
 static PyObject *
 _sha1_sha1(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames)
 {
     PyObject *return_value = NULL;
-    static const char * const _keywords[] = {"string", NULL};
+    static const char * const _keywords[] = {"string", "usedforsecurity", NULL};
     static _PyArg_Parser _parser = {NULL, _keywords, "sha1", 0};
-    PyObject *argsbuf[1];
+    PyObject *argsbuf[2];
     Py_ssize_t noptargs = nargs + (kwnames ? PyTuple_GET_SIZE(kwnames) : 0) - 0;
     PyObject *string = NULL;
+    int usedforsecurity = 1;
 
     args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 0, 1, 0, argsbuf);
     if (!args) {
@@ -94,11 +95,24 @@ _sha1_sha1(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *
     if (!noptargs) {
         goto skip_optional_pos;
     }
-    string = args[0];
+    if (args[0]) {
+        string = args[0];
+        if (!--noptargs) {
+            goto skip_optional_pos;
+        }
+    }
 skip_optional_pos:
-    return_value = _sha1_sha1_impl(module, string);
+    if (!noptargs) {
+        goto skip_optional_kwonly;
+    }
+    usedforsecurity = PyObject_IsTrue(args[1]);
+    if (usedforsecurity < 0) {
+        goto exit;
+    }
+skip_optional_kwonly:
+    return_value = _sha1_sha1_impl(module, string, usedforsecurity);
 
 exit:
     return return_value;
 }
-/*[clinic end generated code: output=1ae7e73ec84a27d5 input=a9049054013a1b77]*/
+/*[clinic end generated code: output=3ddd637ae17e14b3 input=a9049054013a1b77]*/
diff --git a/Modules/clinic/sha256module.c.h b/Modules/clinic/sha256module.c.h
index 658abb15cf..2a788ea984 100644
--- a/Modules/clinic/sha256module.c.h
+++ b/Modules/clinic/sha256module.c.h
@@ -66,7 +66,7 @@ PyDoc_STRVAR(SHA256Type_update__doc__,
     {"update", (PyCFunction)SHA256Type_update, METH_O, SHA256Type_update__doc__},
 
 PyDoc_STRVAR(_sha256_sha256__doc__,
-"sha256($module, /, string=b\'\')\n"
+"sha256($module, /, string=b\'\', *, usedforsecurity=True)\n"
 "--\n"
 "\n"
 "Return a new SHA-256 hash object; optionally initialized with a string.");
@@ -75,17 +75,18 @@ PyDoc_STRVAR(_sha256_sha256__doc__,
     {"sha256", (PyCFunction)(void(*)(void))_sha256_sha256, METH_FASTCALL|METH_KEYWORDS, _sha256_sha256__doc__},
 
 static PyObject *
-_sha256_sha256_impl(PyObject *module, PyObject *string);
+_sha256_sha256_impl(PyObject *module, PyObject *string, int usedforsecurity);
 
 static PyObject *
 _sha256_sha256(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames)
 {
     PyObject *return_value = NULL;
-    static const char * const _keywords[] = {"string", NULL};
+    static const char * const _keywords[] = {"string", "usedforsecurity", NULL};
     static _PyArg_Parser _parser = {NULL, _keywords, "sha256", 0};
-    PyObject *argsbuf[1];
+    PyObject *argsbuf[2];
     Py_ssize_t noptargs = nargs + (kwnames ? PyTuple_GET_SIZE(kwnames) : 0) - 0;
     PyObject *string = NULL;
+    int usedforsecurity = 1;
 
     args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 0, 1, 0, argsbuf);
     if (!args) {
@@ -94,16 +95,29 @@ _sha256_sha256(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObje
     if (!noptargs) {
         goto skip_optional_pos;
     }
-    string = args[0];
+    if (args[0]) {
+        string = args[0];
+        if (!--noptargs) {
+            goto skip_optional_pos;
+        }
+    }
 skip_optional_pos:
-    return_value = _sha256_sha256_impl(module, string);
+    if (!noptargs) {
+        goto skip_optional_kwonly;
+    }
+    usedforsecurity = PyObject_IsTrue(args[1]);
+    if (usedforsecurity < 0) {
+        goto exit;
+    }
+skip_optional_kwonly:
+    return_value = _sha256_sha256_impl(module, string, usedforsecurity);
 
 exit:
     return return_value;
 }
 
 PyDoc_STRVAR(_sha256_sha224__doc__,
-"sha224($module, /, string=b\'\')\n"
+"sha224($module, /, string=b\'\', *, usedforsecurity=True)\n"
 "--\n"
 "\n"
 "Return a new SHA-224 hash object; optionally initialized with a string.");
@@ -112,17 +126,18 @@ PyDoc_STRVAR(_sha256_sha224__doc__,
     {"sha224", (PyCFunction)(void(*)(void))_sha256_sha224, METH_FASTCALL|METH_KEYWORDS, _sha256_sha224__doc__},
 
 static PyObject *
-_sha256_sha224_impl(PyObject *module, PyObject *string);
+_sha256_sha224_impl(PyObject *module, PyObject *string, int usedforsecurity);
 
 static PyObject *
 _sha256_sha224(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames)
 {
     PyObject *return_value = NULL;
-    static const char * const _keywords[] = {"string", NULL};
+    static const char * const _keywords[] = {"string", "usedforsecurity", NULL};
     static _PyArg_Parser _parser = {NULL, _keywords, "sha224", 0};
-    PyObject *argsbuf[1];
+    PyObject *argsbuf[2];
     Py_ssize_t noptargs = nargs + (kwnames ? PyTuple_GET_SIZE(kwnames) : 0) - 0;
     PyObject *string = NULL;
+    int usedforsecurity = 1;
 
     args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 0, 1, 0, argsbuf);
     if (!args) {
@@ -131,11 +146,24 @@ _sha256_sha224(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObje
     if (!noptargs) {
         goto skip_optional_pos;
     }
-    string = args[0];
+    if (args[0]) {
+        string = args[0];
+        if (!--noptargs) {
+            goto skip_optional_pos;
+        }
+    }
 skip_optional_pos:
-    return_value = _sha256_sha224_impl(module, string);
+    if (!noptargs) {
+        goto skip_optional_kwonly;
+    }
+    usedforsecurity = PyObject_IsTrue(args[1]);
+    if (usedforsecurity < 0) {
+        goto exit;
+    }
+skip_optional_kwonly:
+    return_value = _sha256_sha224_impl(module, string, usedforsecurity);
 
 exit:
     return return_value;
 }
-/*[clinic end generated code: output=c54d0956ec88409d input=a9049054013a1b77]*/
+/*[clinic end generated code: output=c8cca8adbe72ec9a input=a9049054013a1b77]*/
diff --git a/Modules/clinic/sha512module.c.h b/Modules/clinic/sha512module.c.h
index 459a9341cf..b8185b62bb 100644
--- a/Modules/clinic/sha512module.c.h
+++ b/Modules/clinic/sha512module.c.h
@@ -66,7 +66,7 @@ PyDoc_STRVAR(SHA512Type_update__doc__,
     {"update", (PyCFunction)SHA512Type_update, METH_O, SHA512Type_update__doc__},
 
 PyDoc_STRVAR(_sha512_sha512__doc__,
-"sha512($module, /, string=b\'\')\n"
+"sha512($module, /, string=b\'\', *, usedforsecurity=True)\n"
 "--\n"
 "\n"
 "Return a new SHA-512 hash object; optionally initialized with a string.");
@@ -75,17 +75,18 @@ PyDoc_STRVAR(_sha512_sha512__doc__,
     {"sha512", (PyCFunction)(void(*)(void))_sha512_sha512, METH_FASTCALL|METH_KEYWORDS, _sha512_sha512__doc__},
 
 static PyObject *
-_sha512_sha512_impl(PyObject *module, PyObject *string);
+_sha512_sha512_impl(PyObject *module, PyObject *string, int usedforsecurity);
 
 static PyObject *
 _sha512_sha512(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames)
 {
     PyObject *return_value = NULL;
-    static const char * const _keywords[] = {"string", NULL};
+    static const char * const _keywords[] = {"string", "usedforsecurity", NULL};
     static _PyArg_Parser _parser = {NULL, _keywords, "sha512", 0};
-    PyObject *argsbuf[1];
+    PyObject *argsbuf[2];
     Py_ssize_t noptargs = nargs + (kwnames ? PyTuple_GET_SIZE(kwnames) : 0) - 0;
     PyObject *string = NULL;
+    int usedforsecurity = 1;
 
     args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 0, 1, 0, argsbuf);
     if (!args) {
@@ -94,16 +95,29 @@ _sha512_sha512(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObje
     if (!noptargs) {
         goto skip_optional_pos;
     }
-    string = args[0];
+    if (args[0]) {
+        string = args[0];
+        if (!--noptargs) {
+            goto skip_optional_pos;
+        }
+    }
 skip_optional_pos:
-    return_value = _sha512_sha512_impl(module, string);
+    if (!noptargs) {
+        goto skip_optional_kwonly;
+    }
+    usedforsecurity = PyObject_IsTrue(args[1]);
+    if (usedforsecurity < 0) {
+        goto exit;
+    }
+skip_optional_kwonly:
+    return_value = _sha512_sha512_impl(module, string, usedforsecurity);
 
 exit:
     return return_value;
 }
 
 PyDoc_STRVAR(_sha512_sha384__doc__,
-"sha384($module, /, string=b\'\')\n"
+"sha384($module, /, string=b\'\', *, usedforsecurity=True)\n"
 "--\n"
 "\n"
 "Return a new SHA-384 hash object; optionally initialized with a string.");
@@ -112,17 +126,18 @@ PyDoc_STRVAR(_sha512_sha384__doc__,
     {"sha384", (PyCFunction)(void(*)(void))_sha512_sha384, METH_FASTCALL|METH_KEYWORDS, _sha512_sha384__doc__},
 
 static PyObject *
-_sha512_sha384_impl(PyObject *module, PyObject *string);
+_sha512_sha384_impl(PyObject *module, PyObject *string, int usedforsecurity);
 
 static PyObject *
 _sha512_sha384(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames)
 {
     PyObject *return_value = NULL;
-    static const char * const _keywords[] = {"string", NULL};
+    static const char * const _keywords[] = {"string", "usedforsecurity", NULL};
     static _PyArg_Parser _parser = {NULL, _keywords, "sha384", 0};
-    PyObject *argsbuf[1];
+    PyObject *argsbuf[2];
     Py_ssize_t noptargs = nargs + (kwnames ? PyTuple_GET_SIZE(kwnames) : 0) - 0;
     PyObject *string = NULL;
+    int usedforsecurity = 1;
 
     args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 0, 1, 0, argsbuf);
     if (!args) {
@@ -131,11 +146,24 @@ _sha512_sha384(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObje
     if (!noptargs) {
         goto skip_optional_pos;
     }
-    string = args[0];
+    if (args[0]) {
+        string = args[0];
+        if (!--noptargs) {
+            goto skip_optional_pos;
+        }
+    }
 skip_optional_pos:
-    return_value = _sha512_sha384_impl(module, string);
+    if (!noptargs) {
+        goto skip_optional_kwonly;
+    }
+    usedforsecurity = PyObject_IsTrue(args[1]);
+    if (usedforsecurity < 0) {
+        goto exit;
+    }
+skip_optional_kwonly:
+    return_value = _sha512_sha384_impl(module, string, usedforsecurity);
 
 exit:
     return return_value;
 }
-/*[clinic end generated code: output=580df4b667084a7e input=a9049054013a1b77]*/
+/*[clinic end generated code: output=bbfa72d8703c82b5 input=a9049054013a1b77]*/
diff --git a/Modules/md5module.c b/Modules/md5module.c
index b9a351a8c1..f2c2d32cbe 100644
--- a/Modules/md5module.c
+++ b/Modules/md5module.c
@@ -503,13 +503,15 @@ static PyTypeObject MD5type = {
 _md5.md5
 
     string: object(c_default="NULL") = b''
+    *
+    usedforsecurity: bool = True
 
 Return a new MD5 hash object; optionally initialized with a string.
 [clinic start generated code]*/
 
 static PyObject *
-_md5_md5_impl(PyObject *module, PyObject *string)
-/*[clinic end generated code: output=2cfd0f8c091b97e6 input=d12ef8f72d684f7b]*/
+_md5_md5_impl(PyObject *module, PyObject *string, int usedforsecurity)
+/*[clinic end generated code: output=587071f76254a4ac input=7a144a1905636985]*/
 {
     MD5object *new;
     Py_buffer buf;
diff --git a/Modules/sha1module.c b/Modules/sha1module.c
index ce2ad267e7..4d191c3c48 100644
--- a/Modules/sha1module.c
+++ b/Modules/sha1module.c
@@ -480,13 +480,15 @@ static PyTypeObject SHA1type = {
 _sha1.sha1
 
     string: object(c_default="NULL") = b''
+    *
+    usedforsecurity: bool = True
 
 Return a new SHA1 hash object; optionally initialized with a string.
 [clinic start generated code]*/
 
 static PyObject *
-_sha1_sha1_impl(PyObject *module, PyObject *string)
-/*[clinic end generated code: output=e5982830d1dece51 input=27ea54281d995ec2]*/
+_sha1_sha1_impl(PyObject *module, PyObject *string, int usedforsecurity)
+/*[clinic end generated code: output=6f8b3af05126e18e input=bd54b68e2bf36a8a]*/
 {
     SHA1object *new;
     Py_buffer buf;
diff --git a/Modules/sha256module.c b/Modules/sha256module.c
index b8d6c4cf80..245f4c0454 100644
--- a/Modules/sha256module.c
+++ b/Modules/sha256module.c
@@ -601,13 +601,15 @@ static PyTypeObject SHA256type = {
 _sha256.sha256
 
     string: object(c_default="NULL") = b''
+    *
+    usedforsecurity: bool = True
 
 Return a new SHA-256 hash object; optionally initialized with a string.
 [clinic start generated code]*/
 
 static PyObject *
-_sha256_sha256_impl(PyObject *module, PyObject *string)
-/*[clinic end generated code: output=fa644436dcea5c31 input=09cce3fb855056b2]*/
+_sha256_sha256_impl(PyObject *module, PyObject *string, int usedforsecurity)
+/*[clinic end generated code: output=a1de327e8e1185cf input=9be86301aeb14ea5]*/
 {
     SHAobject *new;
     Py_buffer buf;
@@ -641,13 +643,15 @@ _sha256_sha256_impl(PyObject *module, PyObject *string)
 _sha256.sha224
 
     string: object(c_default="NULL") = b''
+    *
+    usedforsecurity: bool = True
 
 Return a new SHA-224 hash object; optionally initialized with a string.
 [clinic start generated code]*/
 
 static PyObject *
-_sha256_sha224_impl(PyObject *module, PyObject *string)
-/*[clinic end generated code: output=21e3ba22c3404f93 input=27a04ba24c353a73]*/
+_sha256_sha224_impl(PyObject *module, PyObject *string, int usedforsecurity)
+/*[clinic end generated code: output=08be6b36569bc69c input=9fcfb46e460860ac]*/
 {
     SHAobject *new;
     Py_buffer buf;
diff --git a/Modules/sha512module.c b/Modules/sha512module.c
index 98b97917f4..df4f9d2d74 100644
--- a/Modules/sha512module.c
+++ b/Modules/sha512module.c
@@ -666,13 +666,15 @@ static PyTypeObject SHA512type = {
 _sha512.sha512
 
     string: object(c_default="NULL") = b''
+    *
+    usedforsecurity: bool = True
 
 Return a new SHA-512 hash object; optionally initialized with a string.
 [clinic start generated code]*/
 
 static PyObject *
-_sha512_sha512_impl(PyObject *module, PyObject *string)
-/*[clinic end generated code: output=8b865a2df73bd387 input=e69bad9ae9b6a308]*/
+_sha512_sha512_impl(PyObject *module, PyObject *string, int usedforsecurity)
+/*[clinic end generated code: output=a8d9e5f9e6a0831c input=23b4daebc2ebb9c9]*/
 {
     SHAobject *new;
     Py_buffer buf;
@@ -706,13 +708,15 @@ _sha512_sha512_impl(PyObject *module, PyObject *string)
 _sha512.sha384
 
     string: object(c_default="NULL") = b''
+    *
+    usedforsecurity: bool = True
 
 Return a new SHA-384 hash object; optionally initialized with a string.
 [clinic start generated code]*/
 
 static PyObject *
-_sha512_sha384_impl(PyObject *module, PyObject *string)
-/*[clinic end generated code: output=ae4b2e26decf81e8 input=c9327788d4ea4545]*/
+_sha512_sha384_impl(PyObject *module, PyObject *string, int usedforsecurity)
+/*[clinic end generated code: output=da7d594a08027ac3 input=59ef72f039a6b431]*/
 {
     SHAobject *new;
     Py_buffer buf;
-- 
2.25.4


From aed5f603fda874d823ca04b562c8289bfa42d8f3 Mon Sep 17 00:00:00 2001
From: Petr Viktorin <pviktori@redhat.com>
Date: Mon, 26 Aug 2019 19:09:39 +0200
Subject: [PATCH 26/43] Test the usedforsecurity flag

---
 Lib/test/test_hashlib.py | 88 ++++++++++++++++++++++++----------------
 1 file changed, 54 insertions(+), 34 deletions(-)

diff --git a/Lib/test/test_hashlib.py b/Lib/test/test_hashlib.py
index 08bb91f27b..1368e91708 100644
--- a/Lib/test/test_hashlib.py
+++ b/Lib/test/test_hashlib.py
@@ -21,6 +21,7 @@ from test import support
 from test.support import _4G, bigmemtest, import_fresh_module
 from test.support import requires_hashdigest
 from http.client import HTTPException
+from functools import partial
 
 # Were we compiled --with-pydebug or with #define Py_DEBUG?
 COMPILED_WITH_PYDEBUG = hasattr(sys, 'gettotalrefcount')
@@ -29,8 +30,10 @@ c_hashlib = import_fresh_module('hashlib', fresh=['_hashlib'])
 py_hashlib = import_fresh_module('hashlib', blocked=['_hashlib'])
 
 if hashlib.get_fips_mode():
-    FIPS_DISABLED = {'md5', 'MD5', 'blake2b', 'blake2s'}
+    FIPS_UNAVAILABLE = {'blake2b', 'blake2s'}
+    FIPS_DISABLED = {'md5', 'MD5', *FIPS_UNAVAILABLE}
 else:
+    FIPS_UNAVAILABLE = set()
     FIPS_DISABLED = set()
 
 try:
@@ -80,6 +83,15 @@ def read_vectors(hash_name):
             yield parts
 
 
+def _is_openssl_constructor(constructor):
+    if getattr(constructor, '__name__', '').startswith('openssl_'):
+        return True
+    if isinstance(constructor, partial):
+        if constructor.func.__name__.startswith('openssl_'):
+            return True
+    return False
+
+
 class HashLibTestCase(unittest.TestCase):
     supported_hash_names = ( 'md5', 'MD5', 'sha1', 'SHA1',
                              'sha224', 'SHA224', 'sha256', 'SHA256',
@@ -95,8 +107,6 @@ class HashLibTestCase(unittest.TestCase):
 
     if hashlib.get_fips_mode():
         shakes = set()
-        supported_hash_names = tuple(
-            n for n in supported_hash_names if n not in FIPS_DISABLED)
 
     def _conditional_import_module(self, module_name):
         """Import a module and return a reference to it or None on failure."""
@@ -122,7 +132,8 @@ class HashLibTestCase(unittest.TestCase):
     def __init__(self, *args, **kwargs):
         algorithms = set()
         for algorithm in self.supported_hash_names:
-            algorithms.add(algorithm.lower())
+            if algorithm not in FIPS_UNAVAILABLE:
+                algorithms.add(algorithm.lower())
 
         _blake2 = self._conditional_import_module('_blake2')
         if _blake2:
@@ -132,15 +143,21 @@ class HashLibTestCase(unittest.TestCase):
         for algorithm in algorithms:
             self.constructors_to_test[algorithm] = set()
 
+        def _add_constructor(algorithm, constructor):
+            constructors.add(partial(constructor, usedforsecurity=False))
+            if algorithm not in FIPS_DISABLED:
+                constructors.add(constructor)
+                constructors.add(partial(constructor, usedforsecurity=True))
+
         # For each algorithm, test the direct constructor and the use
         # of hashlib.new given the algorithm name.
         for algorithm, constructors in self.constructors_to_test.items():
-            constructors.add(getattr(hashlib, algorithm))
+            _add_constructor(algorithm, getattr(hashlib, algorithm))
             def _test_algorithm_via_hashlib_new(data=None, _alg=algorithm, **kwargs):
                 if data is None:
                     return hashlib.new(_alg, **kwargs)
                 return hashlib.new(_alg, data, **kwargs)
-            constructors.add(_test_algorithm_via_hashlib_new)
+            _add_constructor(algorithm, _test_algorithm_via_hashlib_new)
 
         _hashlib = self._conditional_import_module('_hashlib')
         self._hashlib = _hashlib
@@ -152,13 +169,7 @@ class HashLibTestCase(unittest.TestCase):
             for algorithm, constructors in self.constructors_to_test.items():
                 constructor = getattr(_hashlib, 'openssl_'+algorithm, None)
                 if constructor:
-                    try:
-                        constructor()
-                    except ValueError:
-                        # default constructor blocked by crypto policy
-                        pass
-                    else:
-                        constructors.add(constructor)
+                    _add_constructor(algorithm, constructor)
 
         def add_builtin_constructor(name):
             constructor = getattr(hashlib, "__get_builtin_constructor")(name)
@@ -218,7 +229,7 @@ class HashLibTestCase(unittest.TestCase):
                 c.hexdigest()
 
     def test_algorithms_guaranteed(self):
-        self.assertEqual(hashlib.algorithms_guaranteed - FIPS_DISABLED,
+        self.assertEqual(hashlib.algorithms_guaranteed,
             set(_algo for _algo in self.supported_hash_names
                   if _algo.islower()))
 
@@ -305,7 +316,9 @@ class HashLibTestCase(unittest.TestCase):
                 self.assertIn(h.name, self.supported_hash_names)
             else:
                 self.assertNotIn(h.name, self.supported_hash_names)
-            self.assertEqual(h.name, hashlib.new(h.name).name)
+            if h.name not in FIPS_DISABLED:
+                self.assertEqual(h.name, hashlib.new(h.name).name)
+            self.assertEqual(h.name, hashlib.new(h.name, usedforsecurity=False).name)
 
     def test_large_update(self):
         aas = b'a' * 128
@@ -347,13 +360,15 @@ class HashLibTestCase(unittest.TestCase):
         self.assertGreaterEqual(len(constructors), 2)
         for hash_object_constructor in constructors:
             if (
-                kwargs
-                and hash_object_constructor.__name__.startswith('openssl_')
+                (kwargs.keys() - {'usedforsecurity'})
+                and _is_openssl_constructor(hash_object_constructor)
             ):
+                # Don't check openssl constructors with
+                # any extra keys (except usedforsecurity)
                 return
             m = hash_object_constructor(data, **kwargs)
             if shake:
-                if hash_object_constructor.__name__.startswith('openssl_'):
+                if _is_openssl_constructor(hash_object_constructor):
                     if length > m.digest_size:
                         # OpenSSL doesn't give long digests
                         return
@@ -370,7 +385,7 @@ class HashLibTestCase(unittest.TestCase):
                     % (name, hash_object_constructor,
                        computed, len(data), hexdigest))
             if shake:
-                if hash_object_constructor.__name__.startswith('openssl_'):
+                if _is_openssl_constructor(hash_object_constructor):
                     computed = m.digest()[:length]
                 else:
                     computed = m.digest(length)
@@ -388,8 +403,7 @@ class HashLibTestCase(unittest.TestCase):
             self.assertRaises(TypeError, hash_object_constructor, 'spam')
 
     def test_no_unicode(self):
-        if not hashlib.get_fips_mode():
-            self.check_no_unicode('md5')
+        self.check_no_unicode('md5')
         self.check_no_unicode('sha1')
         self.check_no_unicode('sha224')
         self.check_no_unicode('sha256')
@@ -416,10 +430,10 @@ class HashLibTestCase(unittest.TestCase):
         for hash_object_constructor in constructors:
             m = hash_object_constructor()
             self.assertEqual(m.block_size, block_size)
-            if not hash_object_constructor.__name__.startswith('openssl_'):
+            if not _is_openssl_constructor(hash_object_constructor):
                 self.assertEqual(m.digest_size, digest_size)
             if digest_length:
-                if not hash_object_constructor.__name__.startswith('openssl_'):
+                if not _is_openssl_constructor(hash_object_constructor):
                     self.assertEqual(len(m.digest(digest_length)),
                                     digest_length)
                     self.assertEqual(len(m.hexdigest(digest_length)),
@@ -457,7 +471,7 @@ class HashLibTestCase(unittest.TestCase):
                 # _hashopenssl's variant does not have extra SHA3 attributes
                 continue
             self.assertEqual(capacity + rate, 1600)
-            if not hash_object_constructor.__name__.startswith('openssl_'):
+            if not _is_openssl_constructor(hash_object_constructor):
                 self.assertEqual(m._capacity_bits, capacity)
                 self.assertEqual(m._rate_bits, rate)
                 self.assertEqual(m._suffix, suffix)
@@ -476,31 +490,27 @@ class HashLibTestCase(unittest.TestCase):
         self.check_blocksize_name('blake2b', 128, 64)
         self.check_blocksize_name('blake2s', 64, 32)
 
-    @unittest.skipIf(hashlib.get_fips_mode(), "md5 unacceptable in FIPS mode")
     def test_case_md5_0(self):
-        self.check('md5', b'', 'd41d8cd98f00b204e9800998ecf8427e')
+        self.check('md5', b'', 'd41d8cd98f00b204e9800998ecf8427e', usedforsecurity=False)
 
-    @unittest.skipIf(hashlib.get_fips_mode(), "md5 unacceptable in FIPS mode")
     def test_case_md5_1(self):
-        self.check('md5', b'abc', '900150983cd24fb0d6963f7d28e17f72')
+        self.check('md5', b'abc', '900150983cd24fb0d6963f7d28e17f72', usedforsecurity=False)
 
-    @unittest.skipIf(hashlib.get_fips_mode(), "md5 unacceptable in FIPS mode")
     def test_case_md5_2(self):
         self.check('md5',
                    b'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789',
-                   'd174ab98d277d9f5a5611c2c9f419d9f')
+                   'd174ab98d277d9f5a5611c2c9f419d9f',
+                   usedforsecurity=False)
 
-    @unittest.skipIf(hashlib.get_fips_mode(), "md5 unacceptable in FIPS mode")
     @unittest.skipIf(sys.maxsize < _4G + 5, 'test cannot run on 32-bit systems')
     @bigmemtest(size=_4G + 5, memuse=1, dry_run=False)
     def test_case_md5_huge(self, size):
-        self.check('md5', b'A'*size, 'c9af2dff37468ce5dfee8f2cfc0a9c6d')
+        self.check('md5', b'A'*size, 'c9af2dff37468ce5dfee8f2cfc0a9c6d', usedforsecurity=False)
 
-    @unittest.skipIf(hashlib.get_fips_mode(), "md5 unacceptable in FIPS mode")
     @unittest.skipIf(sys.maxsize < _4G - 1, 'test cannot run on 32-bit systems')
     @bigmemtest(size=_4G - 1, memuse=1, dry_run=False)
     def test_case_md5_uintmax(self, size):
-        self.check('md5', b'A'*size, '28138d306ff1b8281f1a9067e1a1a2b3')
+        self.check('md5', b'A'*size, '28138d306ff1b8281f1a9067e1a1a2b3', usedforsecurity=False)
 
     # use the three examples from Federal Information Processing Standards
     # Publication 180-1, Secure Hash Standard,  1995 April 17
@@ -925,6 +935,16 @@ class HashLibTestCase(unittest.TestCase):
 
         self.assertEqual(expected_hash, hasher.hexdigest())
 
+    @unittest.skipUnless(hashlib.get_fips_mode(), 'Needs FIPS mode.')
+    def test_usedforsecurity_repeat(self):
+        """Make sure usedforsecurity flag isn't copied to other contexts"""
+        for i in range(3):
+            for cons in hashlib.md5, partial(hashlib.new, 'md5'):
+                self.assertRaises(ValueError, cons)
+                self.assertRaises(ValueError, partial(cons, usedforsecurity=True))
+                self.assertEqual(cons(usedforsecurity=False).hexdigest(),
+                                'd41d8cd98f00b204e9800998ecf8427e')
+
 
 class KDFTests(unittest.TestCase):
 
-- 
2.25.4


From fa3ce5149806b1ef588b75681147636d55c5c604 Mon Sep 17 00:00:00 2001
From: Petr Viktorin <pviktori@redhat.com>
Date: Thu, 29 Aug 2019 10:25:28 +0200
Subject: [PATCH 27/43] Skip error checking in _hashlib.get_fips_mode

Fixes: https://bugzilla.redhat.com/show_bug.cgi?id=1745499
---
 Modules/_hashopenssl.c | 30 ++++++++++++++++--------------
 1 file changed, 16 insertions(+), 14 deletions(-)

diff --git a/Modules/_hashopenssl.c b/Modules/_hashopenssl.c
index 8d0c7de2b2..ed92514e78 100644
--- a/Modules/_hashopenssl.c
+++ b/Modules/_hashopenssl.c
@@ -1249,20 +1249,22 @@ _hashlib_get_fips_mode_impl(PyObject *module)
 /*[clinic end generated code: output=ad8a7793310d3f98 input=f42a2135df2a5e11]*/
 
 {
-    int result = FIPS_mode();
-    if (result == 0) {
-        // "If the library was built without support of the FIPS Object Module,
-        // then the function will return 0 with an error code of
-        // CRYPTO_R_FIPS_MODE_NOT_SUPPORTED (0x0f06d065)."
-        // But 0 is also a valid result value.
-
-        unsigned long errcode = ERR_peek_last_error();
-        if (errcode) {
-            _setException(PyExc_ValueError);
-            return NULL;
-        }
-    }
-    return PyLong_FromLong(result);
+    // XXX: This function skips error checking.
+    // This is only appropriate for RHEL.
+
+    // From the OpenSSL docs:
+    // "If the library was built without support of the FIPS Object Module,
+    // then the function will return 0 with an error code of
+    // CRYPTO_R_FIPS_MODE_NOT_SUPPORTED (0x0f06d065)."
+    // In RHEL:
+    // * we do build with FIPS, so the function always succeeds
+    // * even if it didn't, people seem used to errors being left on the
+    //   OpenSSL error stack.
+
+    // For more info, see:
+    //  https://bugzilla.redhat.com/show_bug.cgi?id=1745499
+
+    return PyLong_FromLong(FIPS_mode());
 }
 
 
-- 
2.25.4


From 282056eda492073e9e03904e8a513547fe2b9836 Mon Sep 17 00:00:00 2001
From: Petr Viktorin <pviktori@redhat.com>
Date: Thu, 10 Oct 2019 13:04:50 +0200
Subject: [PATCH 28/43] Skip error checking in _Py_hashlib_fips_error

https://bugzilla.redhat.com/show_bug.cgi?id=1760106
---
 Include/_hashopenssl.h | 12 +++---------
 1 file changed, 3 insertions(+), 9 deletions(-)

diff --git a/Include/_hashopenssl.h b/Include/_hashopenssl.h
index 47ed003042..d4cbdef984 100644
--- a/Include/_hashopenssl.h
+++ b/Include/_hashopenssl.h
@@ -42,16 +42,10 @@ static int
 _Py_hashlib_fips_error(PyObject *exc, char *name) {
     int result = FIPS_mode();
     if (result == 0) {
-        // "If the library was built without support of the FIPS Object Module,
-        // then the function will return 0 with an error code of
-        // CRYPTO_R_FIPS_MODE_NOT_SUPPORTED (0x0f06d065)."
-        // But 0 is also a valid result value.
+        // XXX: This function skips error checking.
+        // This is only appropriate for RHEL.
+        // See _hashlib.get_fips_mode for details.
 
-        unsigned long errcode = ERR_peek_last_error();
-        if (errcode) {
-            _setException(exc);
-            return 1;
-        }
         return 0;
     }
     PyErr_Format(exc, "%s is not available in FIPS mode", name);
-- 
2.25.4


From 6c5a3b45f7754e7d19084794f573189ba38a00fa Mon Sep 17 00:00:00 2001
From: Petr Viktorin <pviktori@redhat.com>
Date: Mon, 5 Aug 2019 19:12:38 +0200
Subject: [PATCH 29/43] Fixups

- Adjust error message of the original hmac.HMAC class
- Don't duplicate a test name
---
 Lib/hmac.py           | 2 +-
 Lib/test/test_hmac.py | 2 +-
 2 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/Lib/hmac.py b/Lib/hmac.py
index 394c81037b..b2bff7d975 100644
--- a/Lib/hmac.py
+++ b/Lib/hmac.py
@@ -47,7 +47,7 @@ class HMAC:
         """
         if _hashlib.get_fips_mode():
             raise ValueError(
-                'hmac.HMAC is not available in FIPS mode. '
+                'This class is not available in FIPS mode. '
                 + 'Use hmac.new().'
             )
 
diff --git a/Lib/test/test_hmac.py b/Lib/test/test_hmac.py
index 0a859817f6..0b481ec9c0 100644
--- a/Lib/test/test_hmac.py
+++ b/Lib/test/test_hmac.py
@@ -439,7 +439,7 @@ class CopyTestCase(unittest.TestCase):
         self.assertTrue(id(h1.outer) != id(h2.outer),
             "No real copy of the attribute 'outer'.")
 
-    def test_realcopy(self):
+    def test_realcopy_by_digest(self):
         # Testing if the copy method created a real copy.
         h1 = hmac.HMAC(b"key", digestmod="sha1")
         h2 = h1.copy()
-- 
2.25.4


From 63426a2f6c7904800094db9fd3476a5d4711ad25 Mon Sep 17 00:00:00 2001
From: Petr Viktorin <pviktori@redhat.com>
Date: Mon, 26 Aug 2019 19:39:48 +0200
Subject: [PATCH 30/43] Don't re-export get_fips_mode from hashlib

Fixes: https://bugzilla.redhat.com/show_bug.cgi?id=1745685
---
 Lib/distutils/command/upload.py    |  3 ++-
 Lib/distutils/tests/test_upload.py |  5 +++--
 Lib/hashlib.py                     | 21 +++++++++++----------
 Lib/hmac.py                        |  6 +++---
 Lib/test/test_fips.py              |  6 +++---
 Lib/test/test_hashlib.py           | 16 +++++++++-------
 Lib/test/test_hmac.py              |  7 ++++---
 Lib/test/test_smtplib.py           |  4 +++-
 Lib/test/test_tools/test_md5sum.py |  4 ++--
 Lib/test/test_urllib2_localnet.py  |  1 +
 10 files changed, 41 insertions(+), 32 deletions(-)

diff --git a/Lib/distutils/command/upload.py b/Lib/distutils/command/upload.py
index 553617a8d8..8653caefc9 100644
--- a/Lib/distutils/command/upload.py
+++ b/Lib/distutils/command/upload.py
@@ -127,7 +127,8 @@ class upload(PyPIRCCommand):
         except ValueError as e:
             msg = 'calculating md5 checksum failed: %s' % e
             self.announce(msg, log.INFO)
-            if not hashlib.get_fips_mode():
+            from _hashlib import get_fips_mode
+            if not get_fips_mode():
                 # this really shouldn't fail
                 raise
         else:
diff --git a/Lib/distutils/tests/test_upload.py b/Lib/distutils/tests/test_upload.py
index f720a7905d..a198b21357 100644
--- a/Lib/distutils/tests/test_upload.py
+++ b/Lib/distutils/tests/test_upload.py
@@ -4,6 +4,7 @@ import unittest
 import unittest.mock as mock
 from urllib.request import HTTPError
 import hashlib
+from _hashlib import get_fips_mode
 
 from test.support import run_unittest
 
@@ -131,7 +132,7 @@ class uploadTestCase(BasePyPIRCCommandTestCase):
 
         # what did we send ?
         headers = dict(self.last_open.req.headers)
-        if hashlib.get_fips_mode():
+        if get_fips_mode():
             # only sha256 hash is used
             self.assertEqual(headers['Content-length'], '2197')
         else:
@@ -172,7 +173,7 @@ class uploadTestCase(BasePyPIRCCommandTestCase):
         cmd.run()
 
         headers = dict(self.last_open.req.headers)
-        if hashlib.get_fips_mode():
+        if get_fips_mode():
             # only sha256 hash is used
             self.assertEqual(headers['Content-length'], '2207')
         else:
diff --git a/Lib/hashlib.py b/Lib/hashlib.py
index 898e6dca56..2fc214e7ef 100644
--- a/Lib/hashlib.py
+++ b/Lib/hashlib.py
@@ -76,12 +76,12 @@ __block_openssl_constructor = {
 }
 
 try:
-    from _hashlib import get_fips_mode
+    from _hashlib import get_fips_mode as _hashlib_get_fips_mode
 except ImportError:
-    def get_fips_mode():
+    def _hashlib_get_fips_mode():
         return 0
 
-if not get_fips_mode():
+if not _hashlib_get_fips_mode():
     __builtin_constructor_cache = {}
 
     def __get_builtin_constructor(name):
@@ -129,7 +129,7 @@ if not get_fips_mode():
 
 
 def __get_openssl_constructor(name):
-    if not get_fips_mode():
+    if not _hashlib_get_fips_mode():
         if name in __block_openssl_constructor:
             # Prefer our blake2 and sha3 implementation.
             return __get_builtin_constructor(name)
@@ -137,7 +137,7 @@ def __get_openssl_constructor(name):
         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.
-        if not get_fips_mode():
+        if not _hashlib.get_fips_mode():
             # N.B. In "FIPS mode", there is no fallback.
             # If this test fails, we want to export the broken hash
             # constructor anyway.
@@ -148,7 +148,7 @@ def __get_openssl_constructor(name):
         return __get_builtin_constructor(name)
 
 
-if not get_fips_mode():
+if not _hashlib_get_fips_mode():
     def __py_new(name, data=b'', **kwargs):
         """new(name, data=b'', **kwargs) - Return a new hashing object using the
         named algorithm; optionally initialized with data (which must be
@@ -161,7 +161,7 @@ def __hash_new(name, data=b'', **kwargs):
     """new(name, data=b'') - Return a new hashing object using the named algorithm;
     optionally initialized with data (which must be a bytes-like object).
     """
-    if not get_fips_mode():
+    if not _hashlib.get_fips_mode():
         if name in __block_openssl_constructor:
             # Prefer our blake2 and sha3 implementation
             # OpenSSL 1.1.0 comes with a limited implementation of blake2b/s.
@@ -175,7 +175,7 @@ def __hash_new(name, data=b'', **kwargs):
         # hash, try using our builtin implementations.
         # This allows for SHA224/256 and SHA384/512 support even though
         # the OpenSSL library prior to 0.9.8 doesn't provide them.
-        if get_fips_mode():
+        if _hashlib.get_fips_mode():
             raise
         return __get_builtin_constructor(name)(data)
 
@@ -187,7 +187,7 @@ try:
     algorithms_available = algorithms_available.union(
             _hashlib.openssl_md_meth_names)
 except ImportError:
-    if get_fips_mode():
+    if _hashlib_get_fips_mode():
         raise
     new = __py_new
     __get_hash = __get_builtin_constructor
@@ -215,5 +215,6 @@ for __func_name in __always_supported:
 # Cleanup locals()
 del __always_supported, __func_name, __get_hash
 del __hash_new, __get_openssl_constructor
-if not get_fips_mode():
+if not _hashlib.get_fips_mode():
     del __py_new
+del _hashlib_get_fips_mode
diff --git a/Lib/hmac.py b/Lib/hmac.py
index b2bff7d975..5055027bbb 100644
--- a/Lib/hmac.py
+++ b/Lib/hmac.py
@@ -45,7 +45,7 @@ class HMAC:
                    msg argument.  Passing it as a keyword argument is
                    recommended, though not required for legacy API reasons.
         """
-        if _hashlib.get_fips_mode():
+        if _hashlibopenssl.get_fips_mode():
             raise ValueError(
                 'This class is not available in FIPS mode. '
                 + 'Use hmac.new().'
@@ -100,7 +100,7 @@ class HMAC:
 
     def update(self, msg):
         """Feed data from msg into this hashing object."""
-        if _hashlib.get_fips_mode():
+        if _hashlibopenssl.get_fips_mode():
             raise ValueError('hmac.HMAC is not available in FIPS mode')
         self.inner.update(msg)
 
@@ -168,7 +168,7 @@ class HMAC_openssl(_hmacopenssl.HMAC):
         return result
 
 
-if _hashlib.get_fips_mode():
+if _hashlibopenssl.get_fips_mode():
     HMAC = HMAC_openssl
 
 
diff --git a/Lib/test/test_fips.py b/Lib/test/test_fips.py
index 34812e6098..86e61e29c0 100644
--- a/Lib/test/test_fips.py
+++ b/Lib/test/test_fips.py
@@ -6,7 +6,7 @@ import hashlib, _hashlib
 
 class HashlibFipsTests(unittest.TestCase):
 
-    @unittest.skipUnless(hashlib.get_fips_mode(), "Test only when FIPS is enabled")
+    @unittest.skipUnless(_hashlib.get_fips_mode(), "Test only when FIPS is enabled")
     def test_fips_imports(self):
         """blake2s and blake2b should fail to import in FIPS mode
         """
@@ -30,7 +30,7 @@ class HashlibFipsTests(unittest.TestCase):
 
         self.assertEqual(m, h)
 
-    @unittest.skipIf(hashlib.get_fips_mode(), "blake2 hashes are not available under FIPS")
+    @unittest.skipIf(_hashlib.get_fips_mode(), "blake2 hashes are not available under FIPS")
     def test_blake2_hashes(self):
         self.compare_hashes(hashlib.blake2b(b'abc'), _hashlib.openssl_blake2b(b'abc'))
         self.compare_hashes(hashlib.blake2s(b'abc'), _hashlib.openssl_blake2s(b'abc'))
@@ -41,7 +41,7 @@ class HashlibFipsTests(unittest.TestCase):
         self.compare_hashes(hashlib.sha3_384(b'abc'), _hashlib.openssl_sha3_384(b'abc'))
         self.compare_hashes(hashlib.sha3_512(b'abc'), _hashlib.openssl_sha3_512(b'abc'))
 
-    @unittest.skipIf(hashlib.get_fips_mode(), "shake hashes are not available under FIPS")
+    @unittest.skipIf(_hashlib.get_fips_mode(), "shake hashes are not available under FIPS")
     def test_shake_hashes(self):
         self.compare_hashes(hashlib.shake_128(b'abc'), _hashlib.openssl_shake_128(b'abc'))
         self.compare_hashes(hashlib.shake_256(b'abc'), _hashlib.openssl_shake_256(b'abc'))
diff --git a/Lib/test/test_hashlib.py b/Lib/test/test_hashlib.py
index 1368e91708..a4b78406a5 100644
--- a/Lib/test/test_hashlib.py
+++ b/Lib/test/test_hashlib.py
@@ -29,7 +29,9 @@ COMPILED_WITH_PYDEBUG = hasattr(sys, 'gettotalrefcount')
 c_hashlib = import_fresh_module('hashlib', fresh=['_hashlib'])
 py_hashlib = import_fresh_module('hashlib', blocked=['_hashlib'])
 
-if hashlib.get_fips_mode():
+from _hashlib import get_fips_mode as _get_fips_mode
+
+if _get_fips_mode():
     FIPS_UNAVAILABLE = {'blake2b', 'blake2s'}
     FIPS_DISABLED = {'md5', 'MD5', *FIPS_UNAVAILABLE}
 else:
@@ -105,7 +107,7 @@ class HashLibTestCase(unittest.TestCase):
     # Issue #14693: fallback modules are always compiled under POSIX
     _warn_on_extension_import = os.name == 'posix' or COMPILED_WITH_PYDEBUG
 
-    if hashlib.get_fips_mode():
+    if _get_fips_mode():
         shakes = set()
 
     def _conditional_import_module(self, module_name):
@@ -116,7 +118,7 @@ class HashLibTestCase(unittest.TestCase):
             if self._warn_on_extension_import:
                 warnings.warn('Did a C extension fail to compile? %s' % error)
         except ImportError as error:
-            if not hashlib.get_fips_mode():
+            if not _get_fips_mode():
                 raise
         return None
 
@@ -253,12 +255,12 @@ class HashLibTestCase(unittest.TestCase):
     def test_new_upper_to_lower(self):
         self.assertEqual(hashlib.new("SHA256").name, "sha256")
 
-    @unittest.skipUnless(hashlib.get_fips_mode(), "Builtin constructor only unavailable in FIPS mode")
+    @unittest.skipUnless(_get_fips_mode(), "Builtin constructor only unavailable in FIPS mode")
     def test_get_builtin_constructor_fips(self):
         with self.assertRaises(AttributeError):
             hashlib.__get_builtin_constructor
 
-    @unittest.skipIf(hashlib.get_fips_mode(), "No builtin constructors in FIPS mode")
+    @unittest.skipIf(_get_fips_mode(), "No builtin constructors in FIPS mode")
     def test_get_builtin_constructor(self):
         get_builtin_constructor = getattr(hashlib,
                                           '__get_builtin_constructor')
@@ -446,7 +448,7 @@ class HashLibTestCase(unittest.TestCase):
             self.assertIn(name.split("_")[0], repr(m))
 
     def test_blocksize_name(self):
-        if not hashlib.get_fips_mode():
+        if not _get_fips_mode():
             self.check_blocksize_name('md5', 64, 16)
         self.check_blocksize_name('sha1', 64, 20)
         self.check_blocksize_name('sha224', 64, 28)
@@ -935,7 +937,7 @@ class HashLibTestCase(unittest.TestCase):
 
         self.assertEqual(expected_hash, hasher.hexdigest())
 
-    @unittest.skipUnless(hashlib.get_fips_mode(), 'Needs FIPS mode.')
+    @unittest.skipUnless(_get_fips_mode(), 'Needs FIPS mode.')
     def test_usedforsecurity_repeat(self):
         """Make sure usedforsecurity flag isn't copied to other contexts"""
         for i in range(3):
diff --git a/Lib/test/test_hmac.py b/Lib/test/test_hmac.py
index 0b481ec9c0..cc77928fa3 100644
--- a/Lib/test/test_hmac.py
+++ b/Lib/test/test_hmac.py
@@ -5,6 +5,7 @@ import hashlib
 import unittest
 import unittest.mock
 import warnings
+from _hashlib import get_fips_mode
 
 from test.support import requires_hashdigest
 
@@ -288,7 +289,7 @@ class TestVectorsTestCase(unittest.TestCase):
     def test_sha512_rfc4231(self):
         self._rfc4231_test_cases(hashlib.sha512, 'sha512', 64, 128)
 
-    @unittest.skipIf(hashlib.get_fips_mode(), 'MockCrazyHash unacceptable in FIPS mode.')
+    @unittest.skipIf(get_fips_mode(), 'MockCrazyHash unacceptable in FIPS mode.')
     @requires_hashdigest('sha256')
     def test_legacy_block_size_warnings(self):
         class MockCrazyHash(object):
@@ -413,7 +414,7 @@ class SanityTestCase(unittest.TestCase):
 
 class CopyTestCase(unittest.TestCase):
 
-    @unittest.skipIf(hashlib.get_fips_mode(), "Internal attributes unavailable in FIPS mode")
+    @unittest.skipIf(get_fips_mode(), "Internal attributes unavailable in FIPS mode")
     @requires_hashdigest('sha256')
     def test_attributes(self):
         # Testing if attributes are of same type.
@@ -426,7 +427,7 @@ class CopyTestCase(unittest.TestCase):
         self.assertEqual(type(h1.outer), type(h2.outer),
             "Types of outer don't match.")
 
-    @unittest.skipIf(hashlib.get_fips_mode(), "Internal attributes unavailable in FIPS mode")
+    @unittest.skipIf(get_fips_mode(), "Internal attributes unavailable in FIPS mode")
     @requires_hashdigest('sha256')
     def test_realcopy(self):
         # Testing if the copy method created a real copy.
diff --git a/Lib/test/test_smtplib.py b/Lib/test/test_smtplib.py
index d0c9862ede..9a44c0dc7a 100644
--- a/Lib/test/test_smtplib.py
+++ b/Lib/test/test_smtplib.py
@@ -17,6 +17,8 @@ import select
 import errno
 import textwrap
 import threading
+import hashlib
+from _hashlib import get_fips_mode
 
 import unittest
 from test import support, mock_socket
@@ -1021,7 +1023,7 @@ class SMTPSimTests(unittest.TestCase):
 
     def testAUTH_multiple(self):
         # Test that multiple authentication methods are tried.
-        self.serv.add_feature("AUTH BOGUS PLAIN LOGIN CRAM-MD5")
+        self.serv.add_feature("AUTH BOGUS PLAIN LOGIN")
         smtp = smtplib.SMTP(HOST, self.port, local_hostname='localhost', timeout=15)
         resp = smtp.login(sim_auth[0], sim_auth[1])
         self.assertEqual(resp, (235, b'Authentication Succeeded'))
diff --git a/Lib/test/test_tools/test_md5sum.py b/Lib/test/test_tools/test_md5sum.py
index 7028a4dc21..3ba1ca0f14 100644
--- a/Lib/test/test_tools/test_md5sum.py
+++ b/Lib/test/test_tools/test_md5sum.py
@@ -4,13 +4,13 @@ import os
 import unittest
 from test import support
 from test.support.script_helper import assert_python_ok, assert_python_failure
-import hashlib
+import _hashlib
 
 from test.test_tools import scriptsdir, skip_if_missing
 
 skip_if_missing()
 
-if hashlib.get_fips_mode():
+if _hashlib.get_fips_mode():
     raise unittest.SkipTest("md5sum won't work at all in FIPS mode")
 
 class MD5SumTests(unittest.TestCase):
diff --git a/Lib/test/test_urllib2_localnet.py b/Lib/test/test_urllib2_localnet.py
index 1cb358f8dd..6f5cb7fcd1 100644
--- a/Lib/test/test_urllib2_localnet.py
+++ b/Lib/test/test_urllib2_localnet.py
@@ -7,6 +7,7 @@ import http.server
 import threading
 import unittest
 import hashlib
+from _hashlib import get_fips_mode
 
 from test import support
 
-- 
2.25.4


From c57685eb479fb51300fcffd4ae78877c2f10774a Mon Sep 17 00:00:00 2001
From: Charalampos Stratakis <cstratak@redhat.com>
Date: Thu, 2 Apr 2020 16:50:37 +0200
Subject: [PATCH 31/43] Do not raise a ValueError if digestmod is missing in
 FIPS

Python 3.8 already requires the digestmod argument and raises
a TypeError if it's missing, so we remove our downstream check
for it.
---
 Lib/hmac.py | 2 --
 1 file changed, 2 deletions(-)

diff --git a/Lib/hmac.py b/Lib/hmac.py
index 5055027bbb..ee1ad76d22 100644
--- a/Lib/hmac.py
+++ b/Lib/hmac.py
@@ -143,8 +143,6 @@ class HMAC:
         return h.hexdigest()
 
 def _get_openssl_name(digestmod):
-    if digestmod is None:
-        raise ValueError("'digestmod' argument is mandatory in FIPS mode")
     if isinstance(digestmod, str):
         return digestmod.lower()
     elif callable(digestmod):
-- 
2.25.4


From 2f1eee259ad8ee0ff12ed1762a49e494c6989ac7 Mon Sep 17 00:00:00 2001
From: Charalampos Stratakis <cstratak@redhat.com>
Date: Thu, 2 Apr 2020 16:55:36 +0200
Subject: [PATCH 32/43] Regenerate the clinic files

---
 Modules/_hmacopenssl.c          |  4 ++--
 Modules/clinic/_hmacopenssl.c.h | 22 +++++++++++++++-------
 2 files changed, 17 insertions(+), 9 deletions(-)

diff --git a/Modules/_hmacopenssl.c b/Modules/_hmacopenssl.c
index a24c8ba022..9577cadf93 100644
--- a/Modules/_hmacopenssl.c
+++ b/Modules/_hmacopenssl.c
@@ -132,12 +132,12 @@ error:
 /*[clinic input]
 _hmacopenssl.HMAC.copy
 
-Return a copy (“clone”) of the HMAC object.
+Return a copy ("clone") of the HMAC object.
 [clinic start generated code]*/
 
 static PyObject *
 _hmacopenssl_HMAC_copy_impl(HmacObject *self)
-/*[clinic end generated code: output=fe5ee41faf30dcf0 input=f5ed20feec42d8d0]*/
+/*[clinic end generated code: output=fe5ee41faf30dcf0 input=06e7dbc1af7f4a13]*/
 {
     HmacObject *retval;
 
diff --git a/Modules/clinic/_hmacopenssl.c.h b/Modules/clinic/_hmacopenssl.c.h
index 861acc11bf..527be832bf 100644
--- a/Modules/clinic/_hmacopenssl.c.h
+++ b/Modules/clinic/_hmacopenssl.c.h
@@ -6,7 +6,7 @@ PyDoc_STRVAR(_hmacopenssl_HMAC_copy__doc__,
 "copy($self, /)\n"
 "--\n"
 "\n"
-"Return a copy (“clone”) of the HMAC object.");
+"Return a copy (\"clone\") of the HMAC object.");
 
 #define _HMACOPENSSL_HMAC_COPY_METHODDEF    \
     {"copy", (PyCFunction)_hmacopenssl_HMAC_copy, METH_NOARGS, _hmacopenssl_HMAC_copy__doc__},
@@ -27,21 +27,29 @@ PyDoc_STRVAR(_hmacopenssl_HMAC_update__doc__,
 "Update the HMAC object with msg.");
 
 #define _HMACOPENSSL_HMAC_UPDATE_METHODDEF    \
-    {"update", (PyCFunction)_hmacopenssl_HMAC_update, METH_FASTCALL, _hmacopenssl_HMAC_update__doc__},
+    {"update", (PyCFunction)(void(*)(void))_hmacopenssl_HMAC_update, METH_FASTCALL|METH_KEYWORDS, _hmacopenssl_HMAC_update__doc__},
 
 static PyObject *
 _hmacopenssl_HMAC_update_impl(HmacObject *self, Py_buffer *msg);
 
 static PyObject *
-_hmacopenssl_HMAC_update(HmacObject *self, PyObject **args, Py_ssize_t nargs, PyObject *kwnames)
+_hmacopenssl_HMAC_update(HmacObject *self, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames)
 {
     PyObject *return_value = NULL;
     static const char * const _keywords[] = {"msg", NULL};
-    static _PyArg_Parser _parser = {"y*:update", _keywords, 0};
+    static _PyArg_Parser _parser = {NULL, _keywords, "update", 0};
+    PyObject *argsbuf[1];
     Py_buffer msg = {NULL, NULL};
 
-    if (!_PyArg_ParseStack(args, nargs, kwnames, &_parser,
-        &msg)) {
+    args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 1, 1, 0, argsbuf);
+    if (!args) {
+        goto exit;
+    }
+    if (PyObject_GetBuffer(args[0], &msg, PyBUF_SIMPLE) != 0) {
+        goto exit;
+    }
+    if (!PyBuffer_IsContiguous(&msg, 'C')) {
+        _PyArg_BadArgument("update", "argument 'msg'", "contiguous buffer", args[0]);
         goto exit;
     }
     return_value = _hmacopenssl_HMAC_update_impl(self, &msg);
@@ -93,4 +101,4 @@ _hmacopenssl_HMAC_hexdigest(HmacObject *self, PyObject *Py_UNUSED(ignored))
 {
     return _hmacopenssl_HMAC_hexdigest_impl(self);
 }
-/*[clinic end generated code: output=d93ad460795d49b5 input=a9049054013a1b77]*/
+/*[clinic end generated code: output=9b75c31e1116bf6f input=a9049054013a1b77]*/
-- 
2.25.4


From a11ba02aae78de5242751aef09048a9d13b773a7 Mon Sep 17 00:00:00 2001
From: Petr Viktorin <pviktori@redhat.com>
Date: Tue, 7 Apr 2020 15:16:45 +0200
Subject: [PATCH 33/43] Pass kwargs (like usedforsecurity) through __hash_new

---
 Lib/hashlib.py | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/Lib/hashlib.py b/Lib/hashlib.py
index 2fc214e7ef..785858ff8e 100644
--- a/Lib/hashlib.py
+++ b/Lib/hashlib.py
@@ -169,7 +169,7 @@ def __hash_new(name, data=b'', **kwargs):
             # salt, personal, tree hashing or SSE.
             return __get_builtin_constructor(name)(data, **kwargs)
     try:
-        return _hashlib.new(name, data)
+        return _hashlib.new(name, data, **kwargs)
     except ValueError:
         # If the _hashlib module (OpenSSL) doesn't support the named
         # hash, try using our builtin implementations.
@@ -177,7 +177,7 @@ def __hash_new(name, data=b'', **kwargs):
         # the OpenSSL library prior to 0.9.8 doesn't provide them.
         if _hashlib.get_fips_mode():
             raise
-        return __get_builtin_constructor(name)(data)
+        return __get_builtin_constructor(name)(data, **kwargs)
 
 
 try:
-- 
2.25.4


From a06019a22fcb8098745a267e3eb8b0f63c250618 Mon Sep 17 00:00:00 2001
From: Petr Viktorin <pviktori@redhat.com>
Date: Tue, 7 Apr 2020 15:18:48 +0200
Subject: [PATCH 34/43] Adjust new upstream test for failing hashes with
 usedforsecurity

---
 Lib/test/test_hashlib.py | 16 ++++++++++++----
 1 file changed, 12 insertions(+), 4 deletions(-)

diff --git a/Lib/test/test_hashlib.py b/Lib/test/test_hashlib.py
index a4b78406a5..a858bf4c59 100644
--- a/Lib/test/test_hashlib.py
+++ b/Lib/test/test_hashlib.py
@@ -239,15 +239,23 @@ class HashLibTestCase(unittest.TestCase):
         self.assertTrue(set(hashlib.algorithms_guaranteed).
                             issubset(hashlib.algorithms_available))
 
-    def test_usedforsecurity(self):
+    def test_usedforsecurity_false(self):
         for cons in self.hash_constructors:
-            cons(usedforsecurity=True)
             cons(usedforsecurity=False)
-            cons(b'', usedforsecurity=True)
             cons(b'', usedforsecurity=False)
-        hashlib.new("sha256", usedforsecurity=True)
         hashlib.new("sha256", usedforsecurity=False)
 
+    def test_usedforsecurity_true(self):
+        if _get_fips_mode():
+            with self.assertRaises(ValueError):
+                hashlib.new("md5", usedforsecurity=True)
+        else:
+            for cons in self.hash_constructors:
+                cons(usedforsecurity=True)
+                cons(b'', usedforsecurity=True)
+
+        hashlib.new("sha256", usedforsecurity=True)
+
     def test_unknown_hash(self):
         self.assertRaises(ValueError, hashlib.new, 'spam spam spam spam spam')
         self.assertRaises(TypeError, hashlib.new, 1)
-- 
2.25.4


From 96d8c633152ac5650deb1532207f816bf43c483b Mon Sep 17 00:00:00 2001
From: Charalampos Stratakis <cstratak@redhat.com>
Date: Fri, 24 Apr 2020 19:57:16 +0200
Subject: [PATCH 35/43] Skip the test_with_digestmod_no_default under FIPS

Also add a new test for testing the error values of
the digestmod parameter misuse under FIPS mode.
---
 Lib/test/test_hmac.py | 13 +++++++++++++
 1 file changed, 13 insertions(+)

diff --git a/Lib/test/test_hmac.py b/Lib/test/test_hmac.py
index cc77928fa3..fd068e0229 100644
--- a/Lib/test/test_hmac.py
+++ b/Lib/test/test_hmac.py
@@ -313,6 +313,7 @@ class TestVectorsTestCase(unittest.TestCase):
                 hmac.HMAC(b'a', b'b', digestmod=MockCrazyHash)
                 self.fail('Expected warning about small block_size')
 
+    @unittest.skipIf(get_fips_mode(), "digestmod misuse raises different errors under FIPS mode")
     def test_with_digestmod_no_default(self):
         """The digestmod parameter is required as of Python 3.8."""
         with self.assertRaisesRegex(TypeError, r'required.*digestmod'):
@@ -324,6 +325,18 @@ class TestVectorsTestCase(unittest.TestCase):
         with self.assertRaisesRegex(TypeError, r'required.*digestmod'):
             hmac.HMAC(key, msg=data, digestmod='')
 
+    @unittest.skipIf(not get_fips_mode(), "test is run only under FIPS mode")
+    def test_with_digestmod_no_default_under_fips(self):
+        """Test the error values of digestmod misuse under FIPS mode."""
+        with self.assertRaises(TypeError):
+            key = b"\x0b" * 16
+            data = b"Hi There"
+            hmac.HMAC(key, data, digestmod=None)
+        with self.assertRaises(ValueError):
+            hmac.new(key, data)
+        with self.assertRaises(ValueError):
+            hmac.HMAC(key, msg=data, digestmod='')
+
 
 class ConstructorTestCase(unittest.TestCase):
 
-- 
2.25.4


From 82cacfa19d45b1a6a3255ab277bbeaf8da390097 Mon Sep 17 00:00:00 2001
From: Charalampos Stratakis <cstratak@redhat.com>
Date: Fri, 24 Apr 2020 20:00:59 +0200
Subject: [PATCH 36/43] Fix test_crypt under FIPS mode

The crypt methods list changes under FIPS mode
and crypt.METHOD_CRYPT is not always available.
---
 Lib/test/test_crypt.py | 2 --
 1 file changed, 2 deletions(-)

diff --git a/Lib/test/test_crypt.py b/Lib/test/test_crypt.py
index d29e005fda..9568ff4adf 100644
--- a/Lib/test/test_crypt.py
+++ b/Lib/test/test_crypt.py
@@ -52,8 +52,6 @@ class CryptTestCase(unittest.TestCase):
         self.assertTrue(len(crypt.methods) >= 1)
         if sys.platform.startswith('openbsd'):
             self.assertEqual(crypt.methods, [crypt.METHOD_BLOWFISH])
-        else:
-            self.assertEqual(crypt.methods[-1], crypt.METHOD_CRYPT)
 
     @unittest.skipUnless(
         crypt
-- 
2.25.4


From 6df7fbee955b906534c2284f9ca08a8c359d623e Mon Sep 17 00:00:00 2001
From: Charalampos Stratakis <cstratak@redhat.com>
Date: Fri, 24 Apr 2020 20:14:52 +0200
Subject: [PATCH 37/43] Port the _hashopenssl module to openssl api 1.0.2

---
 Include/_hashopenssl.h |  1 +
 Modules/_hmacopenssl.c | 21 ++++++++++-----------
 2 files changed, 11 insertions(+), 11 deletions(-)

diff --git a/Include/_hashopenssl.h b/Include/_hashopenssl.h
index d4cbdef984..4d23f6d584 100644
--- a/Include/_hashopenssl.h
+++ b/Include/_hashopenssl.h
@@ -2,6 +2,7 @@
 #define Py_HASHOPENSSL_H
 
 #include "Python.h"
+#include <openssl/ssl.h>
 #include <openssl/crypto.h>
 #include <openssl/err.h>
 
diff --git a/Modules/_hmacopenssl.c b/Modules/_hmacopenssl.c
index 9577cadf93..7e60fa9bb7 100644
--- a/Modules/_hmacopenssl.c
+++ b/Modules/_hmacopenssl.c
@@ -82,7 +82,7 @@ Hmac_new(PyTypeObject *subtype, PyObject *args, PyObject *kwds)
     }
 
     PyObject *name = NULL;
-    HMAC_CTX *ctx = NULL;
+    HMAC_CTX *ctx = PyMem_RawCalloc(1, sizeof(HMAC_CTX));
     HmacObject *retval = NULL;
 
     name = PyUnicode_FromFormat("hmac-%s", digestmod);
@@ -90,7 +90,6 @@ Hmac_new(PyTypeObject *subtype, PyObject *args, PyObject *kwds)
         goto error;
     }
 
-    ctx = HMAC_CTX_new();
     if (ctx == NULL) {
         _setException(PyExc_ValueError);
         goto error;
@@ -122,7 +121,7 @@ Hmac_new(PyTypeObject *subtype, PyObject *args, PyObject *kwds)
     return (PyObject*)retval;
 
 error:
-    if (ctx) HMAC_CTX_free(ctx);
+    if (ctx) PyMem_RawFree(ctx);
     if (name) Py_DECREF(name);
     if (retval) PyObject_Del(name);
     if (key.buf) PyBuffer_Release(&key);
@@ -141,20 +140,20 @@ _hmacopenssl_HMAC_copy_impl(HmacObject *self)
 {
     HmacObject *retval;
 
-    HMAC_CTX *ctx = HMAC_CTX_new();
+    HMAC_CTX *ctx = PyMem_RawCalloc(1, sizeof(HMAC_CTX));
     if (ctx == NULL) {
         return _setException(PyExc_ValueError);
     }
 
     int r = HMAC_CTX_copy(ctx, self->ctx);
     if (r == 0) {
-        HMAC_CTX_free(ctx);
+        PyMem_RawFree(ctx);
         return _setException(PyExc_ValueError);
     }
 
     retval = (HmacObject *)Py_TYPE(self)->tp_alloc(Py_TYPE(self), 0);
     if (retval == NULL) {
-        HMAC_CTX_free(ctx);
+        PyMem_RawFree(ctx);
         return NULL;
     }
     retval->ctx = ctx;
@@ -172,7 +171,7 @@ _hmac_dealloc(HmacObject *self)
     if (self->lock != NULL) {
         PyThread_free_lock(self->lock);
     }
-    HMAC_CTX_free(self->ctx);
+    PyMem_RawFree(self->ctx);
     Py_CLEAR(self->name);
     Py_TYPE(self)->tp_free(self);
 }
@@ -222,7 +221,7 @@ _hmacopenssl_HMAC_update_impl(HmacObject *self, Py_buffer *msg)
 static unsigned int
 _digest_size(HmacObject *self)
 {
-    const EVP_MD *md = HMAC_CTX_get_md(self->ctx);
+    const EVP_MD *md = self->ctx->md;
     if (md == NULL) {
         _setException(PyExc_ValueError);
         return 0;
@@ -233,7 +232,7 @@ _digest_size(HmacObject *self)
 static int
 _digest(HmacObject *self, unsigned char *buf, unsigned int len)
 {
-    HMAC_CTX *temp_ctx = HMAC_CTX_new();
+    HMAC_CTX *temp_ctx = PyMem_RawCalloc(1, sizeof(HMAC_CTX));
     if (temp_ctx == NULL) {
         PyErr_NoMemory();
         return 0;
@@ -244,7 +243,7 @@ _digest(HmacObject *self, unsigned char *buf, unsigned int len)
         return 0;
     }
     r = HMAC_Final(temp_ctx, buf, &len);
-    HMAC_CTX_free(temp_ctx);
+    PyMem_RawFree(temp_ctx);
     if (r == 0) {
         _setException(PyExc_ValueError);
         return 0;
@@ -314,7 +313,7 @@ _hmacopenssl_get_digest_size(HmacObject *self, void *closure)
 static PyObject *
 _hmacopenssl_get_block_size(HmacObject *self, void *closure)
 {
-    const EVP_MD *md = HMAC_CTX_get_md(self->ctx);
+    const EVP_MD *md = self->ctx->md;
     if (md == NULL) {
         return _setException(PyExc_ValueError);
     }
-- 
2.25.4


From de130ba751965e19ac0e9ff4aa4ae2cc02f6cda2 Mon Sep 17 00:00:00 2001
From: Charalampos Stratakis <cstratak@redhat.com>
Date: Fri, 24 Apr 2020 20:17:33 +0200
Subject: [PATCH 38/43] blake2, sha3 and shake are not available through
 openssl in RHEL7

---
 Modules/_blake2/blake2module.c  |   2 -
 Modules/_hashopenssl.c          | 168 -------------
 Modules/_sha3/sha3module.c      |   2 -
 Modules/clinic/_hashopenssl.c.h | 418 +-------------------------------
 4 files changed, 1 insertion(+), 589 deletions(-)

diff --git a/Modules/_blake2/blake2module.c b/Modules/_blake2/blake2module.c
index a9c7cbc7eb..278467731b 100644
--- a/Modules/_blake2/blake2module.c
+++ b/Modules/_blake2/blake2module.c
@@ -58,8 +58,6 @@ PyInit__blake2(void)
     PyObject *m;
     PyObject *d;
 
-    FAIL_RETURN_IN_FIPS_MODE(PyExc_ImportError, "blake2");
-
     m = PyModule_Create(&blake2_module);
     if (m == NULL)
         return NULL;
diff --git a/Modules/_hashopenssl.c b/Modules/_hashopenssl.c
index ed92514e78..9583b65b62 100644
--- a/Modules/_hashopenssl.c
+++ b/Modules/_hashopenssl.c
@@ -745,166 +745,6 @@ _hashlib_openssl_sha512_impl(PyObject *module, PyObject *data_obj,
     return EVP_fast_new(module, data_obj, EVP_sha512(), usedforsecurity);
 }
 
-/*[clinic input]
-_hashlib.openssl_blake2b
-
-    string as data_obj: object(py_default="b''") = NULL
-    *
-    usedforsecurity: bool = True
-
-Returns a blake2b hash object; optionally initialized with a string
-
-[clinic start generated code]*/
-
-static PyObject *
-_hashlib_openssl_blake2b_impl(PyObject *module, PyObject *data_obj,
-                              int usedforsecurity)
-/*[clinic end generated code: output=7a838b1643cde13e input=37247f187d9c4f4a]*/
-
-{
-    return EVP_fast_new(module, data_obj, EVP_blake2b512(), usedforsecurity);
-}
-
-/*[clinic input]
-_hashlib.openssl_blake2s
-
-    string as data_obj: object(py_default="b''") = NULL
-    *
-    usedforsecurity: bool = True
-
-Returns a blake2s hash object; optionally initialized with a string
-
-[clinic start generated code]*/
-
-static PyObject *
-_hashlib_openssl_blake2s_impl(PyObject *module, PyObject *data_obj,
-                              int usedforsecurity)
-/*[clinic end generated code: output=4eda6b40757471da input=36e42912f87ff123]*/
-
-{
-    return EVP_fast_new(module, data_obj, EVP_blake2s256(), usedforsecurity);
-}
-
-/*[clinic input]
-_hashlib.openssl_sha3_224
-
-    string as data_obj: object(py_default="b''") = NULL
-    *
-    usedforsecurity: bool = True
-
-Returns a sha3_224 hash object; optionally initialized with a string
-
-[clinic start generated code]*/
-
-static PyObject *
-_hashlib_openssl_sha3_224_impl(PyObject *module, PyObject *data_obj,
-                               int usedforsecurity)
-/*[clinic end generated code: output=144641c1d144b974 input=450128ca92633287]*/
-
-{
-    return EVP_fast_new(module, data_obj, EVP_sha3_224(), usedforsecurity);
-}
-
-/*[clinic input]
-_hashlib.openssl_sha3_256
-
-    string as data_obj: object(py_default="b''") = NULL
-    *
-    usedforsecurity: bool = True
-
-Returns a sha3_256 hash object; optionally initialized with a string
-
-[clinic start generated code]*/
-
-static PyObject *
-_hashlib_openssl_sha3_256_impl(PyObject *module, PyObject *data_obj,
-                               int usedforsecurity)
-/*[clinic end generated code: output=c61f1ab772d06668 input=dda801b8285bc25f]*/
-
-{
-    return EVP_fast_new(module, data_obj, EVP_sha3_256(), usedforsecurity);
-}
-
-/*[clinic input]
-_hashlib.openssl_sha3_384
-
-    string as data_obj: object(py_default="b''") = NULL
-    *
-    usedforsecurity: bool = True
-
-Returns a sha3_384 hash object; optionally initialized with a string
-
-[clinic start generated code]*/
-
-static PyObject *
-_hashlib_openssl_sha3_384_impl(PyObject *module, PyObject *data_obj,
-                               int usedforsecurity)
-/*[clinic end generated code: output=f68e4846858cf0ee input=3e2c46d271c64ec8]*/
-
-{
-    return EVP_fast_new(module, data_obj, EVP_sha3_384(), usedforsecurity);
-}
-
-/*[clinic input]
-_hashlib.openssl_sha3_512
-
-    string as data_obj: object(py_default="b''") = NULL
-    *
-    usedforsecurity: bool = True
-
-Returns a sha3-512 hash object; optionally initialized with a string
-
-[clinic start generated code]*/
-
-static PyObject *
-_hashlib_openssl_sha3_512_impl(PyObject *module, PyObject *data_obj,
-                               int usedforsecurity)
-/*[clinic end generated code: output=2eede478c159354a input=64e2cc0c094d56f4]*/
-
-{
-    return EVP_fast_new(module, data_obj, EVP_sha3_512(), usedforsecurity);
-}
-
-/*[clinic input]
-_hashlib.openssl_shake_128
-
-    string as data_obj: object(py_default="b''") = NULL
-    *
-    usedforsecurity: bool = True
-
-Returns a shake_128 hash object; optionally initialized with a string
-
-[clinic start generated code]*/
-
-static PyObject *
-_hashlib_openssl_shake_128_impl(PyObject *module, PyObject *data_obj,
-                                int usedforsecurity)
-/*[clinic end generated code: output=bc49cdd8ada1fa97 input=395c17aac1eb4d2e]*/
-
-{
-    return EVP_fast_new(module, data_obj, EVP_shake128(), usedforsecurity);
-}
-
-/*[clinic input]
-_hashlib.openssl_shake_256
-
-    string as data_obj: object(py_default="b''") = NULL
-    *
-    usedforsecurity: bool = True
-
-Returns a shake_256 hash object; optionally initialized with a string
-
-[clinic start generated code]*/
-
-static PyObject *
-_hashlib_openssl_shake_256_impl(PyObject *module, PyObject *data_obj,
-                                int usedforsecurity)
-/*[clinic end generated code: output=358d213be8852df7 input=4fcf0b80fb663690]*/
-
-{
-    return EVP_fast_new(module, data_obj, EVP_shake256(), usedforsecurity);
-}
-
 
 /*[clinic input]
 _hashlib.pbkdf2_hmac as pbkdf2_hmac
@@ -1282,14 +1122,6 @@ static struct PyMethodDef EVP_functions[] = {
     _HASHLIB_OPENSSL_SHA256_METHODDEF
     _HASHLIB_OPENSSL_SHA384_METHODDEF
     _HASHLIB_OPENSSL_SHA512_METHODDEF
-    _HASHLIB_OPENSSL_BLAKE2B_METHODDEF
-    _HASHLIB_OPENSSL_BLAKE2S_METHODDEF
-    _HASHLIB_OPENSSL_SHA3_224_METHODDEF
-    _HASHLIB_OPENSSL_SHA3_256_METHODDEF
-    _HASHLIB_OPENSSL_SHA3_384_METHODDEF
-    _HASHLIB_OPENSSL_SHA3_512_METHODDEF
-    _HASHLIB_OPENSSL_SHAKE_128_METHODDEF
-    _HASHLIB_OPENSSL_SHAKE_256_METHODDEF
     {NULL,      NULL}            /* Sentinel */
 };
 
diff --git a/Modules/_sha3/sha3module.c b/Modules/_sha3/sha3module.c
index fc8b1b262a..4be98e4cb0 100644
--- a/Modules/_sha3/sha3module.c
+++ b/Modules/_sha3/sha3module.c
@@ -710,8 +710,6 @@ PyInit__sha3(void)
 {
     PyObject *m = NULL;
 
-    FAIL_RETURN_IN_FIPS_MODE(PyExc_ImportError, "_sha3");
-
     if ((m = PyModule_Create(&_SHA3module)) == NULL) {
         return NULL;
     }
diff --git a/Modules/clinic/_hashopenssl.c.h b/Modules/clinic/_hashopenssl.c.h
index 967884727b..7c31809c60 100644
--- a/Modules/clinic/_hashopenssl.c.h
+++ b/Modules/clinic/_hashopenssl.c.h
@@ -436,422 +436,6 @@ exit:
     return return_value;
 }
 
-PyDoc_STRVAR(_hashlib_openssl_blake2b__doc__,
-"openssl_blake2b($module, /, string=b\'\', *, usedforsecurity=True)\n"
-"--\n"
-"\n"
-"Returns a blake2b hash object; optionally initialized with a string");
-
-#define _HASHLIB_OPENSSL_BLAKE2B_METHODDEF    \
-    {"openssl_blake2b", (PyCFunction)(void(*)(void))_hashlib_openssl_blake2b, METH_FASTCALL|METH_KEYWORDS, _hashlib_openssl_blake2b__doc__},
-
-static PyObject *
-_hashlib_openssl_blake2b_impl(PyObject *module, PyObject *data_obj,
-                              int usedforsecurity);
-
-static PyObject *
-_hashlib_openssl_blake2b(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames)
-{
-    PyObject *return_value = NULL;
-    static const char * const _keywords[] = {"string", "usedforsecurity", NULL};
-    static _PyArg_Parser _parser = {NULL, _keywords, "openssl_blake2b", 0};
-    PyObject *argsbuf[2];
-    Py_ssize_t noptargs = nargs + (kwnames ? PyTuple_GET_SIZE(kwnames) : 0) - 0;
-    PyObject *data_obj = NULL;
-    int usedforsecurity = 1;
-
-    args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 0, 1, 0, argsbuf);
-    if (!args) {
-        goto exit;
-    }
-    if (!noptargs) {
-        goto skip_optional_pos;
-    }
-    if (args[0]) {
-        data_obj = args[0];
-        if (!--noptargs) {
-            goto skip_optional_pos;
-        }
-    }
-skip_optional_pos:
-    if (!noptargs) {
-        goto skip_optional_kwonly;
-    }
-    usedforsecurity = PyObject_IsTrue(args[1]);
-    if (usedforsecurity < 0) {
-        goto exit;
-    }
-skip_optional_kwonly:
-    return_value = _hashlib_openssl_blake2b_impl(module, data_obj, usedforsecurity);
-
-exit:
-    return return_value;
-}
-
-PyDoc_STRVAR(_hashlib_openssl_blake2s__doc__,
-"openssl_blake2s($module, /, string=b\'\', *, usedforsecurity=True)\n"
-"--\n"
-"\n"
-"Returns a blake2s hash object; optionally initialized with a string");
-
-#define _HASHLIB_OPENSSL_BLAKE2S_METHODDEF    \
-    {"openssl_blake2s", (PyCFunction)(void(*)(void))_hashlib_openssl_blake2s, METH_FASTCALL|METH_KEYWORDS, _hashlib_openssl_blake2s__doc__},
-
-static PyObject *
-_hashlib_openssl_blake2s_impl(PyObject *module, PyObject *data_obj,
-                              int usedforsecurity);
-
-static PyObject *
-_hashlib_openssl_blake2s(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames)
-{
-    PyObject *return_value = NULL;
-    static const char * const _keywords[] = {"string", "usedforsecurity", NULL};
-    static _PyArg_Parser _parser = {NULL, _keywords, "openssl_blake2s", 0};
-    PyObject *argsbuf[2];
-    Py_ssize_t noptargs = nargs + (kwnames ? PyTuple_GET_SIZE(kwnames) : 0) - 0;
-    PyObject *data_obj = NULL;
-    int usedforsecurity = 1;
-
-    args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 0, 1, 0, argsbuf);
-    if (!args) {
-        goto exit;
-    }
-    if (!noptargs) {
-        goto skip_optional_pos;
-    }
-    if (args[0]) {
-        data_obj = args[0];
-        if (!--noptargs) {
-            goto skip_optional_pos;
-        }
-    }
-skip_optional_pos:
-    if (!noptargs) {
-        goto skip_optional_kwonly;
-    }
-    usedforsecurity = PyObject_IsTrue(args[1]);
-    if (usedforsecurity < 0) {
-        goto exit;
-    }
-skip_optional_kwonly:
-    return_value = _hashlib_openssl_blake2s_impl(module, data_obj, usedforsecurity);
-
-exit:
-    return return_value;
-}
-
-PyDoc_STRVAR(_hashlib_openssl_sha3_224__doc__,
-"openssl_sha3_224($module, /, string=b\'\', *, usedforsecurity=True)\n"
-"--\n"
-"\n"
-"Returns a sha3_224 hash object; optionally initialized with a string");
-
-#define _HASHLIB_OPENSSL_SHA3_224_METHODDEF    \
-    {"openssl_sha3_224", (PyCFunction)(void(*)(void))_hashlib_openssl_sha3_224, METH_FASTCALL|METH_KEYWORDS, _hashlib_openssl_sha3_224__doc__},
-
-static PyObject *
-_hashlib_openssl_sha3_224_impl(PyObject *module, PyObject *data_obj,
-                               int usedforsecurity);
-
-static PyObject *
-_hashlib_openssl_sha3_224(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames)
-{
-    PyObject *return_value = NULL;
-    static const char * const _keywords[] = {"string", "usedforsecurity", NULL};
-    static _PyArg_Parser _parser = {NULL, _keywords, "openssl_sha3_224", 0};
-    PyObject *argsbuf[2];
-    Py_ssize_t noptargs = nargs + (kwnames ? PyTuple_GET_SIZE(kwnames) : 0) - 0;
-    PyObject *data_obj = NULL;
-    int usedforsecurity = 1;
-
-    args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 0, 1, 0, argsbuf);
-    if (!args) {
-        goto exit;
-    }
-    if (!noptargs) {
-        goto skip_optional_pos;
-    }
-    if (args[0]) {
-        data_obj = args[0];
-        if (!--noptargs) {
-            goto skip_optional_pos;
-        }
-    }
-skip_optional_pos:
-    if (!noptargs) {
-        goto skip_optional_kwonly;
-    }
-    usedforsecurity = PyObject_IsTrue(args[1]);
-    if (usedforsecurity < 0) {
-        goto exit;
-    }
-skip_optional_kwonly:
-    return_value = _hashlib_openssl_sha3_224_impl(module, data_obj, usedforsecurity);
-
-exit:
-    return return_value;
-}
-
-PyDoc_STRVAR(_hashlib_openssl_sha3_256__doc__,
-"openssl_sha3_256($module, /, string=b\'\', *, usedforsecurity=True)\n"
-"--\n"
-"\n"
-"Returns a sha3_256 hash object; optionally initialized with a string");
-
-#define _HASHLIB_OPENSSL_SHA3_256_METHODDEF    \
-    {"openssl_sha3_256", (PyCFunction)(void(*)(void))_hashlib_openssl_sha3_256, METH_FASTCALL|METH_KEYWORDS, _hashlib_openssl_sha3_256__doc__},
-
-static PyObject *
-_hashlib_openssl_sha3_256_impl(PyObject *module, PyObject *data_obj,
-                               int usedforsecurity);
-
-static PyObject *
-_hashlib_openssl_sha3_256(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames)
-{
-    PyObject *return_value = NULL;
-    static const char * const _keywords[] = {"string", "usedforsecurity", NULL};
-    static _PyArg_Parser _parser = {NULL, _keywords, "openssl_sha3_256", 0};
-    PyObject *argsbuf[2];
-    Py_ssize_t noptargs = nargs + (kwnames ? PyTuple_GET_SIZE(kwnames) : 0) - 0;
-    PyObject *data_obj = NULL;
-    int usedforsecurity = 1;
-
-    args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 0, 1, 0, argsbuf);
-    if (!args) {
-        goto exit;
-    }
-    if (!noptargs) {
-        goto skip_optional_pos;
-    }
-    if (args[0]) {
-        data_obj = args[0];
-        if (!--noptargs) {
-            goto skip_optional_pos;
-        }
-    }
-skip_optional_pos:
-    if (!noptargs) {
-        goto skip_optional_kwonly;
-    }
-    usedforsecurity = PyObject_IsTrue(args[1]);
-    if (usedforsecurity < 0) {
-        goto exit;
-    }
-skip_optional_kwonly:
-    return_value = _hashlib_openssl_sha3_256_impl(module, data_obj, usedforsecurity);
-
-exit:
-    return return_value;
-}
-
-PyDoc_STRVAR(_hashlib_openssl_sha3_384__doc__,
-"openssl_sha3_384($module, /, string=b\'\', *, usedforsecurity=True)\n"
-"--\n"
-"\n"
-"Returns a sha3_384 hash object; optionally initialized with a string");
-
-#define _HASHLIB_OPENSSL_SHA3_384_METHODDEF    \
-    {"openssl_sha3_384", (PyCFunction)(void(*)(void))_hashlib_openssl_sha3_384, METH_FASTCALL|METH_KEYWORDS, _hashlib_openssl_sha3_384__doc__},
-
-static PyObject *
-_hashlib_openssl_sha3_384_impl(PyObject *module, PyObject *data_obj,
-                               int usedforsecurity);
-
-static PyObject *
-_hashlib_openssl_sha3_384(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames)
-{
-    PyObject *return_value = NULL;
-    static const char * const _keywords[] = {"string", "usedforsecurity", NULL};
-    static _PyArg_Parser _parser = {NULL, _keywords, "openssl_sha3_384", 0};
-    PyObject *argsbuf[2];
-    Py_ssize_t noptargs = nargs + (kwnames ? PyTuple_GET_SIZE(kwnames) : 0) - 0;
-    PyObject *data_obj = NULL;
-    int usedforsecurity = 1;
-
-    args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 0, 1, 0, argsbuf);
-    if (!args) {
-        goto exit;
-    }
-    if (!noptargs) {
-        goto skip_optional_pos;
-    }
-    if (args[0]) {
-        data_obj = args[0];
-        if (!--noptargs) {
-            goto skip_optional_pos;
-        }
-    }
-skip_optional_pos:
-    if (!noptargs) {
-        goto skip_optional_kwonly;
-    }
-    usedforsecurity = PyObject_IsTrue(args[1]);
-    if (usedforsecurity < 0) {
-        goto exit;
-    }
-skip_optional_kwonly:
-    return_value = _hashlib_openssl_sha3_384_impl(module, data_obj, usedforsecurity);
-
-exit:
-    return return_value;
-}
-
-PyDoc_STRVAR(_hashlib_openssl_sha3_512__doc__,
-"openssl_sha3_512($module, /, string=b\'\', *, usedforsecurity=True)\n"
-"--\n"
-"\n"
-"Returns a sha3-512 hash object; optionally initialized with a string");
-
-#define _HASHLIB_OPENSSL_SHA3_512_METHODDEF    \
-    {"openssl_sha3_512", (PyCFunction)(void(*)(void))_hashlib_openssl_sha3_512, METH_FASTCALL|METH_KEYWORDS, _hashlib_openssl_sha3_512__doc__},
-
-static PyObject *
-_hashlib_openssl_sha3_512_impl(PyObject *module, PyObject *data_obj,
-                               int usedforsecurity);
-
-static PyObject *
-_hashlib_openssl_sha3_512(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames)
-{
-    PyObject *return_value = NULL;
-    static const char * const _keywords[] = {"string", "usedforsecurity", NULL};
-    static _PyArg_Parser _parser = {NULL, _keywords, "openssl_sha3_512", 0};
-    PyObject *argsbuf[2];
-    Py_ssize_t noptargs = nargs + (kwnames ? PyTuple_GET_SIZE(kwnames) : 0) - 0;
-    PyObject *data_obj = NULL;
-    int usedforsecurity = 1;
-
-    args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 0, 1, 0, argsbuf);
-    if (!args) {
-        goto exit;
-    }
-    if (!noptargs) {
-        goto skip_optional_pos;
-    }
-    if (args[0]) {
-        data_obj = args[0];
-        if (!--noptargs) {
-            goto skip_optional_pos;
-        }
-    }
-skip_optional_pos:
-    if (!noptargs) {
-        goto skip_optional_kwonly;
-    }
-    usedforsecurity = PyObject_IsTrue(args[1]);
-    if (usedforsecurity < 0) {
-        goto exit;
-    }
-skip_optional_kwonly:
-    return_value = _hashlib_openssl_sha3_512_impl(module, data_obj, usedforsecurity);
-
-exit:
-    return return_value;
-}
-
-PyDoc_STRVAR(_hashlib_openssl_shake_128__doc__,
-"openssl_shake_128($module, /, string=b\'\', *, usedforsecurity=True)\n"
-"--\n"
-"\n"
-"Returns a shake_128 hash object; optionally initialized with a string");
-
-#define _HASHLIB_OPENSSL_SHAKE_128_METHODDEF    \
-    {"openssl_shake_128", (PyCFunction)(void(*)(void))_hashlib_openssl_shake_128, METH_FASTCALL|METH_KEYWORDS, _hashlib_openssl_shake_128__doc__},
-
-static PyObject *
-_hashlib_openssl_shake_128_impl(PyObject *module, PyObject *data_obj,
-                                int usedforsecurity);
-
-static PyObject *
-_hashlib_openssl_shake_128(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames)
-{
-    PyObject *return_value = NULL;
-    static const char * const _keywords[] = {"string", "usedforsecurity", NULL};
-    static _PyArg_Parser _parser = {NULL, _keywords, "openssl_shake_128", 0};
-    PyObject *argsbuf[2];
-    Py_ssize_t noptargs = nargs + (kwnames ? PyTuple_GET_SIZE(kwnames) : 0) - 0;
-    PyObject *data_obj = NULL;
-    int usedforsecurity = 1;
-
-    args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 0, 1, 0, argsbuf);
-    if (!args) {
-        goto exit;
-    }
-    if (!noptargs) {
-        goto skip_optional_pos;
-    }
-    if (args[0]) {
-        data_obj = args[0];
-        if (!--noptargs) {
-            goto skip_optional_pos;
-        }
-    }
-skip_optional_pos:
-    if (!noptargs) {
-        goto skip_optional_kwonly;
-    }
-    usedforsecurity = PyObject_IsTrue(args[1]);
-    if (usedforsecurity < 0) {
-        goto exit;
-    }
-skip_optional_kwonly:
-    return_value = _hashlib_openssl_shake_128_impl(module, data_obj, usedforsecurity);
-
-exit:
-    return return_value;
-}
-
-PyDoc_STRVAR(_hashlib_openssl_shake_256__doc__,
-"openssl_shake_256($module, /, string=b\'\', *, usedforsecurity=True)\n"
-"--\n"
-"\n"
-"Returns a shake_256 hash object; optionally initialized with a string");
-
-#define _HASHLIB_OPENSSL_SHAKE_256_METHODDEF    \
-    {"openssl_shake_256", (PyCFunction)(void(*)(void))_hashlib_openssl_shake_256, METH_FASTCALL|METH_KEYWORDS, _hashlib_openssl_shake_256__doc__},
-
-static PyObject *
-_hashlib_openssl_shake_256_impl(PyObject *module, PyObject *data_obj,
-                                int usedforsecurity);
-
-static PyObject *
-_hashlib_openssl_shake_256(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames)
-{
-    PyObject *return_value = NULL;
-    static const char * const _keywords[] = {"string", "usedforsecurity", NULL};
-    static _PyArg_Parser _parser = {NULL, _keywords, "openssl_shake_256", 0};
-    PyObject *argsbuf[2];
-    Py_ssize_t noptargs = nargs + (kwnames ? PyTuple_GET_SIZE(kwnames) : 0) - 0;
-    PyObject *data_obj = NULL;
-    int usedforsecurity = 1;
-
-    args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 0, 1, 0, argsbuf);
-    if (!args) {
-        goto exit;
-    }
-    if (!noptargs) {
-        goto skip_optional_pos;
-    }
-    if (args[0]) {
-        data_obj = args[0];
-        if (!--noptargs) {
-            goto skip_optional_pos;
-        }
-    }
-skip_optional_pos:
-    if (!noptargs) {
-        goto skip_optional_kwonly;
-    }
-    usedforsecurity = PyObject_IsTrue(args[1]);
-    if (usedforsecurity < 0) {
-        goto exit;
-    }
-skip_optional_kwonly:
-    return_value = _hashlib_openssl_shake_256_impl(module, data_obj, usedforsecurity);
-
-exit:
-    return return_value;
-}
-
 PyDoc_STRVAR(pbkdf2_hmac__doc__,
 "pbkdf2_hmac($module, /, hash_name, password, salt, iterations,\n"
 "            dklen=None)\n"
@@ -1167,4 +751,4 @@ _hashlib_get_fips_mode(PyObject *module, PyObject *Py_UNUSED(ignored))
 #ifndef _HASHLIB_SCRYPT_METHODDEF
     #define _HASHLIB_SCRYPT_METHODDEF
 #endif /* !defined(_HASHLIB_SCRYPT_METHODDEF) */
-/*[clinic end generated code: output=3db4f18f12892fa4 input=a9049054013a1b77]*/
+/*[clinic end generated code: output=646d49f01d125759 input=a9049054013a1b77]*/
-- 
2.25.4


From 4b8ecb575a742220d21db10a2c09b0e1ac750f82 Mon Sep 17 00:00:00 2001
From: Charalampos Stratakis <cstratak@redhat.com>
Date: Fri, 24 Apr 2020 20:18:44 +0200
Subject: [PATCH 39/43] Remove unavailable algorithms testing from test_fips

---
 Lib/test/test_fips.py | 25 -------------------------
 1 file changed, 25 deletions(-)

diff --git a/Lib/test/test_fips.py b/Lib/test/test_fips.py
index 86e61e29c0..73b219be6a 100644
--- a/Lib/test/test_fips.py
+++ b/Lib/test/test_fips.py
@@ -6,15 +6,6 @@ import hashlib, _hashlib
 
 class HashlibFipsTests(unittest.TestCase):
 
-    @unittest.skipUnless(_hashlib.get_fips_mode(), "Test only when FIPS is enabled")
-    def test_fips_imports(self):
-        """blake2s and blake2b should fail to import in FIPS mode
-        """
-        with self.assertRaises(ValueError, msg='blake2s not available in FIPS'):
-            m = hashlib.blake2s()
-        with self.assertRaises(ValueError, msg='blake2b not available in FIPS'):
-            m = hashlib.blake2b()
-
     def compare_hashes(self, python_hash, openssl_hash):
         """
         Compare between the python implementation and the openssl one that the digests
@@ -30,22 +21,6 @@ class HashlibFipsTests(unittest.TestCase):
 
         self.assertEqual(m, h)
 
-    @unittest.skipIf(_hashlib.get_fips_mode(), "blake2 hashes are not available under FIPS")
-    def test_blake2_hashes(self):
-        self.compare_hashes(hashlib.blake2b(b'abc'), _hashlib.openssl_blake2b(b'abc'))
-        self.compare_hashes(hashlib.blake2s(b'abc'), _hashlib.openssl_blake2s(b'abc'))
-
-    def test_sha3_hashes(self):
-        self.compare_hashes(hashlib.sha3_224(b'abc'), _hashlib.openssl_sha3_224(b'abc'))
-        self.compare_hashes(hashlib.sha3_256(b'abc'), _hashlib.openssl_sha3_256(b'abc'))
-        self.compare_hashes(hashlib.sha3_384(b'abc'), _hashlib.openssl_sha3_384(b'abc'))
-        self.compare_hashes(hashlib.sha3_512(b'abc'), _hashlib.openssl_sha3_512(b'abc'))
-
-    @unittest.skipIf(_hashlib.get_fips_mode(), "shake hashes are not available under FIPS")
-    def test_shake_hashes(self):
-        self.compare_hashes(hashlib.shake_128(b'abc'), _hashlib.openssl_shake_128(b'abc'))
-        self.compare_hashes(hashlib.shake_256(b'abc'), _hashlib.openssl_shake_256(b'abc'))
-
     def test_sha(self):
         self.compare_hashes(hashlib.sha1(b'abc'), _hashlib.openssl_sha1(b'abc'))
         self.compare_hashes(hashlib.sha224(b'abc'), _hashlib.openssl_sha224(b'abc'))
-- 
2.25.4


From 24570434ab6b9381c8255d70758a87408b183583 Mon Sep 17 00:00:00 2001
From: Charalampos Stratakis <cstratak@redhat.com>
Date: Fri, 24 Apr 2020 20:20:03 +0200
Subject: [PATCH 40/43] Fix the hashlib test under FIPS mode in RHEL7

---
 Lib/hashlib.py           |  96 +++++++++---------
 Lib/test/test_hashlib.py | 213 ++++++++++++++++++++++-----------------
 2 files changed, 167 insertions(+), 142 deletions(-)

diff --git a/Lib/hashlib.py b/Lib/hashlib.py
index 785858ff8e..1d214c1767 100644
--- a/Lib/hashlib.py
+++ b/Lib/hashlib.py
@@ -53,6 +53,12 @@ More condensed:
 
 """
 
+try:
+    from _hashlib import get_fips_mode as _hashlib_get_fips_mode
+except ImportError:
+    def _hashlib_get_fips_mode():
+        return 0
+
 # This tuple and __get_builtin_constructor() must be modified if a new
 # always available algorithm is added.
 __always_supported = ('md5', 'sha1', 'sha224', 'sha256', 'sha384', 'sha512',
@@ -69,27 +75,19 @@ __all__ = __always_supported + ('new', 'algorithms_guaranteed',
 
 
 
-__block_openssl_constructor = {
-    'sha3_224', 'sha3_256', 'sha3_384', 'sha3_512',
-    'shake_128', 'shake_256',
-    'blake2b', 'blake2s',
-}
+__block_openssl_constructor = {'sha3_224', 'sha3_256', 'sha3_384', 'sha3_512',
+                               'shake_128', 'shake_256',
+                               'blake2b', 'blake2s'}
 
-try:
-    from _hashlib import get_fips_mode as _hashlib_get_fips_mode
-except ImportError:
-    def _hashlib_get_fips_mode():
-        return 0
+__builtin_constructor_cache = {}
 
-if not _hashlib_get_fips_mode():
-    __builtin_constructor_cache = {}
-
-    def __get_builtin_constructor(name):
-        cache = __builtin_constructor_cache
-        constructor = cache.get(name)
-        if constructor is not None:
-            return constructor
-        try:
+def __get_builtin_constructor(name):
+    cache = __builtin_constructor_cache
+    constructor = cache.get(name)
+    if constructor is not None:
+        return constructor
+    try:
+        if not _hashlib_get_fips_mode():
             if name in {'SHA1', 'sha1'}:
                 import _sha1
                 cache['SHA1'] = cache['sha1'] = _sha1.sha1
@@ -104,35 +102,34 @@ if not _hashlib_get_fips_mode():
                 import _sha512
                 cache['SHA384'] = cache['sha384'] = _sha512.sha384
                 cache['SHA512'] = cache['sha512'] = _sha512.sha512
-            elif name in {'blake2b', 'blake2s'}:
-                import _blake2
-                cache['blake2b'] = _blake2.blake2b
-                cache['blake2s'] = _blake2.blake2s
-            elif name in {'sha3_224', 'sha3_256', 'sha3_384', 'sha3_512'}:
-                import _sha3
-                cache['sha3_224'] = _sha3.sha3_224
-                cache['sha3_256'] = _sha3.sha3_256
-                cache['sha3_384'] = _sha3.sha3_384
-                cache['sha3_512'] = _sha3.sha3_512
-            elif name in {'shake_128', 'shake_256'}:
-                import _sha3
-                cache['shake_128'] = _sha3.shake_128
-                cache['shake_256'] = _sha3.shake_256
-        except ImportError:
-            pass  # no extension module, this hash is unsupported.
-
-        constructor = cache.get(name)
-        if constructor is not None:
-            return constructor
-
-        raise ValueError('unsupported hash type ' + name)
+        if name in {'blake2b', 'blake2s'}:
+            import _blake2
+            cache['blake2b'] = _blake2.blake2b
+            cache['blake2s'] = _blake2.blake2s
+        elif name in {'sha3_224', 'sha3_256', 'sha3_384', 'sha3_512'}:
+            import _sha3
+            cache['sha3_224'] = _sha3.sha3_224
+            cache['sha3_256'] = _sha3.sha3_256
+            cache['sha3_384'] = _sha3.sha3_384
+            cache['sha3_512'] = _sha3.sha3_512
+        elif name in {'shake_128', 'shake_256'}:
+            import _sha3
+            cache['shake_128'] = _sha3.shake_128
+            cache['shake_256'] = _sha3.shake_256
+    except ImportError:
+        pass  # no extension module, this hash is unsupported.
+
+    constructor = cache.get(name)
+    if constructor is not None:
+        return constructor
+
+    raise ValueError('unsupported hash type ' + name)
 
 
 def __get_openssl_constructor(name):
-    if not _hashlib_get_fips_mode():
-        if name in __block_openssl_constructor:
-            # Prefer our blake2 and sha3 implementation.
-            return __get_builtin_constructor(name)
+    if name in __block_openssl_constructor:
+        # Prefer our blake2 and sha3 implementation.
+        return __get_builtin_constructor(name)
     try:
         f = getattr(_hashlib, 'openssl_' + name)
         # Allow the C module to raise ValueError.  The function will be
@@ -145,7 +142,7 @@ def __get_openssl_constructor(name):
         # Use the C function directly (very fast)
         return f
     except (AttributeError, ValueError):
-        return __get_builtin_constructor(name)
+         __get_builtin_constructor(name)
 
 
 if not _hashlib_get_fips_mode():
@@ -187,8 +184,6 @@ try:
     algorithms_available = algorithms_available.union(
             _hashlib.openssl_md_meth_names)
 except ImportError:
-    if _hashlib_get_fips_mode():
-        raise
     new = __py_new
     __get_hash = __get_builtin_constructor
 
@@ -208,8 +203,9 @@ for __func_name in __always_supported:
     try:
         globals()[__func_name] = __get_hash(__func_name)
     except ValueError:
-        import logging
-        logging.exception('code for hash %s was not found.', __func_name)
+        if not _hashlib_get_fips_mode():
+            import logging
+            logging.exception('code for hash %s was not found.', __func_name)
 
 
 # Cleanup locals()
diff --git a/Lib/test/test_hashlib.py b/Lib/test/test_hashlib.py
index a858bf4c59..ccc572dabf 100644
--- a/Lib/test/test_hashlib.py
+++ b/Lib/test/test_hashlib.py
@@ -1,4 +1,4 @@
-# Test hashlib module
+#e Test hashlib module
 #
 # $Id$
 #
@@ -32,7 +32,7 @@ py_hashlib = import_fresh_module('hashlib', blocked=['_hashlib'])
 from _hashlib import get_fips_mode as _get_fips_mode
 
 if _get_fips_mode():
-    FIPS_UNAVAILABLE = {'blake2b', 'blake2s'}
+    FIPS_UNAVAILABLE = {'blake2b', 'blake2s', 'sha3_224', 'sha3_256', 'sha3_384', 'sha3_512', 'shake_128', 'shake_256'}
     FIPS_DISABLED = {'md5', 'MD5', *FIPS_UNAVAILABLE}
 else:
     FIPS_UNAVAILABLE = set()
@@ -48,14 +48,14 @@ try:
 except ImportError:
     _blake2 = None
 
-requires_blake2 = unittest.skipUnless(_blake2, 'requires _blake2')
+requires_blake2 = unittest.skipUnless(_blake2 and not _get_fips_mode(), 'requires _blake2')
 
 try:
     import _sha3
 except ImportError:
     _sha3 = None
 
-requires_sha3 = unittest.skipUnless(_sha3, 'requires _sha3')
+requires_sha3 = unittest.skipUnless(_sha3 and not _get_fips_mode(), 'requires _sha3')
 
 
 def hexstr(s):
@@ -173,6 +173,7 @@ class HashLibTestCase(unittest.TestCase):
                 if constructor:
                     _add_constructor(algorithm, constructor)
 
+
         def add_builtin_constructor(name):
             constructor = getattr(hashlib, "__get_builtin_constructor")(name)
             self.constructors_to_test[name].add(constructor)
@@ -191,18 +192,20 @@ class HashLibTestCase(unittest.TestCase):
         if _sha512:
             add_builtin_constructor('sha384')
             add_builtin_constructor('sha512')
-        if _blake2:
-            add_builtin_constructor('blake2s')
-            add_builtin_constructor('blake2b')
-
-        _sha3 = self._conditional_import_module('_sha3')
-        if _sha3:
-            add_builtin_constructor('sha3_224')
-            add_builtin_constructor('sha3_256')
-            add_builtin_constructor('sha3_384')
-            add_builtin_constructor('sha3_512')
-            add_builtin_constructor('shake_128')
-            add_builtin_constructor('shake_256')
+
+        if not _get_fips_mode():
+            if _blake2:
+                add_builtin_constructor('blake2s')
+                add_builtin_constructor('blake2b')
+
+            _sha3 = self._conditional_import_module('_sha3')
+            if _sha3:
+                add_builtin_constructor('sha3_224')
+                add_builtin_constructor('sha3_256')
+                add_builtin_constructor('sha3_384')
+                add_builtin_constructor('sha3_512')
+                add_builtin_constructor('shake_128')
+                add_builtin_constructor('shake_256')
 
         super(HashLibTestCase, self).__init__(*args, **kwargs)
 
@@ -223,12 +226,15 @@ class HashLibTestCase(unittest.TestCase):
 
     def test_hash_array(self):
         a = array.array("b", range(10))
-        for cons in self.hash_constructors:
-            c = cons(a)
-            if self._has_shake_extras(c):
-                c.hexdigest(16)
-            else:
-                c.hexdigest()
+        try:
+            for cons in self.hash_constructors:
+                c = cons(a)
+                if self._has_shake_extras(c):
+                    c.hexdigest(16)
+                else:
+                    c.hexdigest()
+        except ValueError:
+            pass # Some algorithms aren't supported
 
     def test_algorithms_guaranteed(self):
         self.assertEqual(hashlib.algorithms_guaranteed,
@@ -240,9 +246,12 @@ class HashLibTestCase(unittest.TestCase):
                             issubset(hashlib.algorithms_available))
 
     def test_usedforsecurity_false(self):
-        for cons in self.hash_constructors:
-            cons(usedforsecurity=False)
-            cons(b'', usedforsecurity=False)
+        try:
+            for cons in self.hash_constructors:
+                cons(usedforsecurity=False)
+                cons(b'', usedforsecurity=False)
+        except ValueError:
+            pass # Some algorithms aren't supported
         hashlib.new("sha256", usedforsecurity=False)
 
     def test_usedforsecurity_true(self):
@@ -296,39 +305,48 @@ class HashLibTestCase(unittest.TestCase):
         self.assertEqual(sorted(builtin_constructor_cache), ['MD5', 'md5'])
 
     def test_hexdigest(self):
-        for cons in self.hash_constructors:
-            h = cons()
-            if self._has_shake_extras(h):
-                self.assertIsInstance(h.digest(16), bytes)
-                self.assertEqual(hexstr(h.digest(16)), h.hexdigest(16))
-            else:
-                self.assertIsInstance(h.digest(), bytes)
-                self.assertEqual(hexstr(h.digest()), h.hexdigest())
+        try:
+            for cons in self.hash_constructors:
+                h = cons()
+                if self._has_shake_extras(h):
+                    self.assertIsInstance(h.digest(16), bytes)
+                    self.assertEqual(hexstr(h.digest(16)), h.hexdigest(16))
+                else:
+                    self.assertIsInstance(h.digest(), bytes)
+                    self.assertEqual(hexstr(h.digest()), h.hexdigest())
+        except ValueError:
+            pass # Some algorithms aren't supported
 
     def test_digest_length_overflow(self):
-        # See issue #34922
-        large_sizes = (2**29, 2**32-10, 2**32+10, 2**61, 2**64-10, 2**64+10)
-        for cons in self.hash_constructors:
-            h = cons()
-            if not self._has_shake_extras(h):
-                continue
-            for digest in h.digest, h.hexdigest:
-                self.assertRaises(ValueError, digest, -10)
-                for length in large_sizes:
-                    with self.assertRaises((ValueError, OverflowError)):
-                        digest(length)
+        try:
+            # See issue #34922
+            large_sizes = (2**29, 2**32-10, 2**32+10, 2**61, 2**64-10, 2**64+10)
+            for cons in self.hash_constructors:
+                h = cons()
+                if not self._has_shake_extras(h):
+                    continue
+                for digest in h.digest, h.hexdigest:
+                    self.assertRaises(ValueError, digest, -10)
+                    for length in large_sizes:
+                        with self.assertRaises((ValueError, OverflowError)):
+                            digest(length)
+        except ValueError:
+            pass # Some algorithms aren't supported
 
     def test_name_attribute(self):
-        for cons in self.hash_constructors:
-            h = cons()
-            self.assertIsInstance(h.name, str)
-            if h.name in self.supported_hash_names:
-                self.assertIn(h.name, self.supported_hash_names)
-            else:
-                self.assertNotIn(h.name, self.supported_hash_names)
-            if h.name not in FIPS_DISABLED:
-                self.assertEqual(h.name, hashlib.new(h.name).name)
-            self.assertEqual(h.name, hashlib.new(h.name, usedforsecurity=False).name)
+        try:
+            for cons in self.hash_constructors:
+                h = cons()
+                self.assertIsInstance(h.name, str)
+                if h.name in self.supported_hash_names:
+                    self.assertIn(h.name, self.supported_hash_names)
+                else:
+                    self.assertNotIn(h.name, self.supported_hash_names)
+                if h.name not in FIPS_DISABLED:
+                    self.assertEqual(h.name, hashlib.new(h.name).name)
+                self.assertEqual(h.name, hashlib.new(h.name, usedforsecurity=False).name)
+        except ValueError:
+            pass # Some algorithms aren't supported
 
     def test_large_update(self):
         aas = b'a' * 128
@@ -336,31 +354,34 @@ class HashLibTestCase(unittest.TestCase):
         cees = b'c' * 126
         dees = b'd' * 2048 #  HASHLIB_GIL_MINSIZE
 
-        for cons in self.hash_constructors:
-            m1 = cons()
-            m1.update(aas)
-            m1.update(bees)
-            m1.update(cees)
-            m1.update(dees)
-            if self._has_shake_extras(m1):
-                args = (16,)
-            else:
-                args = ()
+        try:
+            for cons in self.hash_constructors:
+                m1 = cons()
+                m1.update(aas)
+                m1.update(bees)
+                m1.update(cees)
+                m1.update(dees)
+                if self._has_shake_extras(m1):
+                    args = (16,)
+                else:
+                    args = ()
 
-            m2 = cons()
-            m2.update(aas + bees + cees + dees)
-            self.assertEqual(m1.digest(*args), m2.digest(*args))
+                m2 = cons()
+                m2.update(aas + bees + cees + dees)
+                self.assertEqual(m1.digest(*args), m2.digest(*args))
 
-            m3 = cons(aas + bees + cees + dees)
-            self.assertEqual(m1.digest(*args), m3.digest(*args))
+                m3 = cons(aas + bees + cees + dees)
+                self.assertEqual(m1.digest(*args), m3.digest(*args))
 
-            # verify copy() doesn't touch original
-            m4 = cons(aas + bees + cees)
-            m4_digest = m4.digest(*args)
-            m4_copy = m4.copy()
-            m4_copy.update(dees)
-            self.assertEqual(m1.digest(*args), m4_copy.digest(*args))
-            self.assertEqual(m4.digest(*args), m4_digest)
+                # verify copy() doesn't touch original
+                m4 = cons(aas + bees + cees)
+                m4_digest = m4.digest(*args)
+                m4_copy = m4.copy()
+                m4_copy.update(dees)
+                self.assertEqual(m1.digest(*args), m4_copy.digest(*args))
+                self.assertEqual(m4.digest(*args), m4_digest)
+        except ValueError:
+            pass # Some algorithms aren't supported
 
     def check(self, name, data, hexdigest, shake=False, **kwargs):
         length = len(hexdigest)//2
@@ -496,6 +517,7 @@ class HashLibTestCase(unittest.TestCase):
         self.check_sha3('shake_256', 512, 1088, b'\x1f')
 
     @requires_blake2
+    @unittest.skipIf(_get_fips_mode(), "No builtin constructors in FIPS mode")
     def test_blocksize_name_blake2(self):
         self.check_blocksize_name('blake2b', 128, 64)
         self.check_blocksize_name('blake2s', 64, 32)
@@ -731,6 +753,7 @@ class HashLibTestCase(unittest.TestCase):
         return outer.hexdigest()
 
     @requires_blake2
+    @unittest.skipIf(_get_fips_mode(), "No builtin constructors in FIPS mode")
     def test_blake2b(self):
         self.check_blake2(hashlib.blake2b, 16, 16, 64, 64, (1<<64)-1)
         b2b_md_len = [20, 32, 48, 64]
@@ -770,12 +793,14 @@ class HashLibTestCase(unittest.TestCase):
           last_node=True)
 
     @requires_blake2
+    @unittest.skipIf(_get_fips_mode(), "No builtin constructors in FIPS mode")
     def test_blake2b_vectors(self):
         for msg, key, md in read_vectors('blake2b'):
             key = bytes.fromhex(key)
             self.check('blake2b', msg, md, key=key)
 
     @requires_blake2
+    @unittest.skipIf(_get_fips_mode(), "No builtin constructors in FIPS mode")
     def test_blake2s(self):
         self.check_blake2(hashlib.blake2s, 8, 8, 32, 32, (1<<48)-1)
         b2s_md_len = [16, 20, 28, 32]
@@ -813,6 +838,7 @@ class HashLibTestCase(unittest.TestCase):
           last_node=True)
 
     @requires_blake2
+    @unittest.skipIf(_get_fips_mode(), "No builtin constructors in FIPS mode")
     def test_blake2s_vectors(self):
         for msg, key, md in read_vectors('blake2s'):
             key = bytes.fromhex(key)
@@ -889,25 +915,28 @@ class HashLibTestCase(unittest.TestCase):
         # for multithreaded operation (which is hardwired to 2048).
         gil_minsize = 2048
 
-        for cons in self.hash_constructors:
-            m = cons()
+        try:
+            for cons in self.hash_constructors:
+                m = cons()
+                m.update(b'1')
+                m.update(b'#' * gil_minsize)
+                m.update(b'1')
+
+                m = cons(b'x' * gil_minsize)
+                m.update(b'1')
+
+            m = hashlib.sha1()
             m.update(b'1')
             m.update(b'#' * gil_minsize)
             m.update(b'1')
-
-            m = cons(b'x' * gil_minsize)
-            m.update(b'1')
-
-        m = hashlib.sha1()
-        m.update(b'1')
-        m.update(b'#' * gil_minsize)
-        m.update(b'1')
-        self.assertEqual(m.hexdigest(),
-                         'c45f7445ca0ea087d7a1758fbea07935f267c46a')
-
-        m = hashlib.sha1(b'x' * gil_minsize)
-        self.assertEqual(m.hexdigest(),
-                         '63fda1efde982ba1ffe9d53035bff5c9ce4758fb')
+            self.assertEqual(m.hexdigest(),
+                             'c45f7445ca0ea087d7a1758fbea07935f267c46a')
+
+            m = hashlib.sha1(b'x' * gil_minsize)
+            self.assertEqual(m.hexdigest(),
+                             '63fda1efde982ba1ffe9d53035bff5c9ce4758fb')
+        except ValueError:
+            pass # Some algorithms aren't supported
 
     @support.reap_threads
     def test_threaded_hashing(self):
-- 
2.25.4


From 2aec945f3288aad6af5d8b517e97cf2fd6ae81de Mon Sep 17 00:00:00 2001
From: Charalampos Stratakis <cstratak@redhat.com>
Date: Fri, 24 Apr 2020 23:32:23 +0200
Subject: [PATCH 41/43] test_ssl fixes for FIPS mode in RHEL7

---
 Lib/test/test_ssl.py | 47 +++++++++++++++++++++++++++++---------------
 1 file changed, 31 insertions(+), 16 deletions(-)

diff --git a/Lib/test/test_ssl.py b/Lib/test/test_ssl.py
index 419506f4d3..085a67c496 100644
--- a/Lib/test/test_ssl.py
+++ b/Lib/test/test_ssl.py
@@ -20,6 +20,7 @@ import weakref
 import platform
 import sysconfig
 import functools
+from _hashlib import get_fips_mode
 try:
     import ctypes
 except ImportError:
@@ -30,6 +31,11 @@ ssl = support.import_module("ssl")
 from ssl import TLSVersion, _TLSContentType, _TLSMessageType
 
 PROTOCOLS = sorted(ssl._PROTOCOL_NAMES)
+if get_fips_mode():
+    for protocol in PROTOCOLS:
+        if "SSLv3" in str(protocol):
+            PROTOCOLS.remove(protocol)
+
 HOST = support.HOST
 IS_LIBRESSL = ssl.OPENSSL_VERSION.startswith('LibreSSL')
 IS_OPENSSL_1_1_0 = not IS_LIBRESSL and ssl.OPENSSL_VERSION_INFO >= (1, 1, 0)
@@ -3217,36 +3223,41 @@ class ThreadedTests(unittest.TestCase):
         if support.verbose:
             sys.stdout.write("\n")
         if has_tls_version('SSLv2'):
-            try:
-                try_protocol_combo(ssl.PROTOCOL_TLS, ssl.PROTOCOL_SSLv2, True)
-            except OSError as x:
-                # this fails on some older versions of OpenSSL (0.9.7l, for instance)
-                if support.verbose:
-                    sys.stdout.write(
-                        " SSL2 client to SSL23 server test unexpectedly failed:\n %s\n"
-                        % str(x))
+            if not get_fips_mode():
+                try:
+                    try_protocol_combo(ssl.PROTOCOL_TLS, ssl.PROTOCOL_SSLv2, True)
+                except OSError as x:
+                    # this fails on some older versions of OpenSSL (0.9.7l, for instance)
+                    if support.verbose:
+                        sys.stdout.write(
+                            " SSL2 client to SSL23 server test unexpectedly failed:\n %s\n"
+                            % str(x))
         if has_tls_version('SSLv3'):
-            try_protocol_combo(ssl.PROTOCOL_TLS, ssl.PROTOCOL_SSLv3, False)
+            if not get_fips_mode():
+                try_protocol_combo(ssl.PROTOCOL_TLS, ssl.PROTOCOL_SSLv3, False)
         try_protocol_combo(ssl.PROTOCOL_TLS, ssl.PROTOCOL_TLS, True)
         if has_tls_version('TLSv1'):
             try_protocol_combo(ssl.PROTOCOL_TLS, ssl.PROTOCOL_TLSv1, 'TLSv1')
 
         if has_tls_version('SSLv3'):
-            try_protocol_combo(ssl.PROTOCOL_TLS, ssl.PROTOCOL_SSLv3, False, ssl.CERT_OPTIONAL)
+            if not get_fips_mode():
+                try_protocol_combo(ssl.PROTOCOL_TLS, ssl.PROTOCOL_SSLv3, False, ssl.CERT_OPTIONAL)
         try_protocol_combo(ssl.PROTOCOL_TLS, ssl.PROTOCOL_TLS, True, ssl.CERT_OPTIONAL)
         if has_tls_version('TLSv1'):
             try_protocol_combo(ssl.PROTOCOL_TLS, ssl.PROTOCOL_TLSv1, 'TLSv1', ssl.CERT_OPTIONAL)
 
         if has_tls_version('SSLv3'):
-            try_protocol_combo(ssl.PROTOCOL_TLS, ssl.PROTOCOL_SSLv3, False, ssl.CERT_REQUIRED)
+            if not get_fips_mode():
+                try_protocol_combo(ssl.PROTOCOL_TLS, ssl.PROTOCOL_SSLv3, False, ssl.CERT_REQUIRED)
         try_protocol_combo(ssl.PROTOCOL_TLS, ssl.PROTOCOL_TLS, True, ssl.CERT_REQUIRED)
         if has_tls_version('TLSv1'):
             try_protocol_combo(ssl.PROTOCOL_TLS, ssl.PROTOCOL_TLSv1, 'TLSv1', ssl.CERT_REQUIRED)
 
         # Server with specific SSL options
         if has_tls_version('SSLv3'):
-            try_protocol_combo(ssl.PROTOCOL_TLS, ssl.PROTOCOL_SSLv3, False,
-                           server_options=ssl.OP_NO_SSLv3)
+            if not get_fips_mode():
+                try_protocol_combo(ssl.PROTOCOL_TLS, ssl.PROTOCOL_SSLv3, False,
+                               server_options=ssl.OP_NO_SSLv3)
         # Will choose TLSv1
         try_protocol_combo(ssl.PROTOCOL_TLS, ssl.PROTOCOL_TLS, True,
                            server_options=ssl.OP_NO_SSLv2 | ssl.OP_NO_SSLv3)
@@ -3254,6 +3265,7 @@ class ThreadedTests(unittest.TestCase):
             try_protocol_combo(ssl.PROTOCOL_TLS, ssl.PROTOCOL_TLSv1, False,
                                server_options=ssl.OP_NO_TLSv1)
 
+    @unittest.skipIf(get_fips_mode(), "SSLv3 is disabled on runtime on FIPS mode")
     @requires_tls_version('SSLv3')
     def test_protocol_sslv3(self):
         """Connecting to an SSLv3 server with various client options"""
@@ -3283,7 +3295,8 @@ class ThreadedTests(unittest.TestCase):
         if has_tls_version('SSLv2'):
             try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_SSLv2, False)
         if has_tls_version('SSLv3'):
-            try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_SSLv3, False)
+            if not get_fips_mode():
+                try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_SSLv3, False)
         try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_TLS, False,
                            client_options=ssl.OP_NO_TLSv1)
 
@@ -3297,7 +3310,8 @@ class ThreadedTests(unittest.TestCase):
         if has_tls_version('SSLv2'):
             try_protocol_combo(ssl.PROTOCOL_TLSv1_1, ssl.PROTOCOL_SSLv2, False)
         if has_tls_version('SSLv3'):
-            try_protocol_combo(ssl.PROTOCOL_TLSv1_1, ssl.PROTOCOL_SSLv3, False)
+            if not get_fips_mode():
+                try_protocol_combo(ssl.PROTOCOL_TLSv1_1, ssl.PROTOCOL_SSLv3, False)
         try_protocol_combo(ssl.PROTOCOL_TLSv1_1, ssl.PROTOCOL_TLS, False,
                            client_options=ssl.OP_NO_TLSv1_1)
 
@@ -3317,7 +3331,8 @@ class ThreadedTests(unittest.TestCase):
         if has_tls_version('SSLv2'):
             try_protocol_combo(ssl.PROTOCOL_TLSv1_2, ssl.PROTOCOL_SSLv2, False)
         if has_tls_version('SSLv3'):
-            try_protocol_combo(ssl.PROTOCOL_TLSv1_2, ssl.PROTOCOL_SSLv3, False)
+            if not get_fips_mode():
+                try_protocol_combo(ssl.PROTOCOL_TLSv1_2, ssl.PROTOCOL_SSLv3, False)
         try_protocol_combo(ssl.PROTOCOL_TLSv1_2, ssl.PROTOCOL_TLS, False,
                            client_options=ssl.OP_NO_TLSv1_2)
 
-- 
2.25.4


From b04db8f08ea04dd7bbaa2bb5747f34b1434b2cfa Mon Sep 17 00:00:00 2001
From: Marcel Plch <mplch@redhat.com>
Date: Fri, 24 Apr 2020 22:44:43 +0200
Subject: [PATCH 42/43] Fix imports in hashlib under FIPS mode

---
 Lib/hashlib.py | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/Lib/hashlib.py b/Lib/hashlib.py
index 1d214c1767..5b54ba7360 100644
--- a/Lib/hashlib.py
+++ b/Lib/hashlib.py
@@ -81,7 +81,7 @@ __block_openssl_constructor = {'sha3_224', 'sha3_256', 'sha3_384', 'sha3_512',
 
 __builtin_constructor_cache = {}
 
-def __get_builtin_constructor(name):
+def __get_builtin_constructor(name, *, _hashlib_get_fips_mode=_hashlib_get_fips_mode):
     cache = __builtin_constructor_cache
     constructor = cache.get(name)
     if constructor is not None:
-- 
2.25.4


From a7d877821c59ef9752804767705cbb3705645c9d Mon Sep 17 00:00:00 2001
From: Charalampos Stratakis <cstratak@redhat.com>
Date: Tue, 31 Mar 2020 18:00:42 +0200
Subject: [PATCH 43/43] Add a sentinel value on the Hmac_members table of the
 hmac module

---
 Modules/_hmacopenssl.c | 1 +
 1 file changed, 1 insertion(+)

diff --git a/Modules/_hmacopenssl.c b/Modules/_hmacopenssl.c
index 7e60fa9bb7..ed07a18215 100644
--- a/Modules/_hmacopenssl.c
+++ b/Modules/_hmacopenssl.c
@@ -336,6 +336,7 @@ static PyGetSetDef Hmac_getset[] = {
 
 static PyMemberDef Hmac_members[] = {
     {"name", T_OBJECT, offsetof(HmacObject, name), READONLY, PyDoc_STR("HMAC name")},
+    {NULL} /* Sentinel */
 };
 
 PyDoc_STRVAR(hmactype_doc,
-- 
2.25.4