]> git.ipfire.org Git - thirdparty/Python/cpython.git/commitdiff
gh-99108: Implement HACL* HMAC (#130157)
authorBénédikt Tran <10796600+picnixz@users.noreply.github.com>
Fri, 4 Apr 2025 17:04:00 +0000 (19:04 +0200)
committerGitHub <noreply@github.com>
Fri, 4 Apr 2025 17:04:00 +0000 (19:04 +0200)
A new extension module, `_hmac`, now exposes the HACL* HMAC (formally verified) implementation.

The HACL* implementation is used as a fallback implementation when the OpenSSL implementation of HMAC
is not available or disabled. For now, only named hash algorithms are recognized and SIMD support provided
by HACL* for the BLAKE2 hash functions is not yet used.

29 files changed:
Doc/whatsnew/3.14.rst
Lib/hmac.py
Lib/test/support/hashlib_helper.py
Lib/test/test_hmac.py
Makefile.pre.in
Misc/NEWS.d/next/Core_and_Builtins/2025-02-15-14-36-32.gh-issue-99108.u6CfmK.rst [new file with mode: 0644]
Misc/sbom.spdx.json
Modules/Setup
Modules/Setup.stdlib.in
Modules/_hacl/Hacl_HMAC.c [new file with mode: 0644]
Modules/_hacl/Hacl_HMAC.h [new file with mode: 0644]
Modules/_hacl/Hacl_Streaming_HMAC.c [new file with mode: 0644]
Modules/_hacl/Hacl_Streaming_HMAC.h [new file with mode: 0644]
Modules/_hacl/README.md
Modules/_hacl/internal/Hacl_HMAC.h [new file with mode: 0644]
Modules/_hacl/internal/Hacl_Streaming_HMAC.h [new file with mode: 0644]
Modules/_hacl/libintvector-shim.h [new file with mode: 0644]
Modules/_hacl/python_hacl_namespaces.h
Modules/_hacl/refresh.sh
Modules/clinic/hmacmodule.c.h [new file with mode: 0644]
Modules/hmacmodule.c [new file with mode: 0644]
PC/config.c
PCbuild/pythoncore.vcxproj
PCbuild/pythoncore.vcxproj.filters
Python/stdlib_module_names.h
Tools/c-analyzer/cpython/_parser.py
Tools/c-analyzer/cpython/ignored.tsv
configure
configure.ac

index a561d3b3383fc5d720791d4806906e514ccfde61..c475d33472a318841a8dcefb88952f54a3bf1f91 100644 (file)
@@ -455,6 +455,13 @@ Other language changes
   The testbed can also be used to run the test suite of projects other than
   CPython itself. (Contributed by Russell Keith-Magee in :gh:`127592`.)
 
+* Add a built-in implementation for HMAC (:rfc:`2104`) using formally verified
+  code from the `HACL* <https://github.com/hacl-star/hacl-star/>`__ project.
+  This implementation is used as a fallback when the OpenSSL implementation
+  of HMAC is not available.
+  (Contributed by Bénédikt Tran in :gh:`99108`.)
+
+
 .. _whatsnew314-pep765:
 
 PEP 765: Disallow return/break/continue that exit a finally block
@@ -464,6 +471,7 @@ The compiler emits a :exc:`SyntaxWarning` when a :keyword:`return`, :keyword:`br
 :keyword:`continue` statements appears where it exits a :keyword:`finally` block.
 This change is specified in :pep:`765`.
 
+
 New modules
 ===========
 
@@ -705,6 +713,14 @@ graphlib
   (Contributed by Daniel Pope in :gh:`130914`)
 
 
+hmac
+----
+
+* Add a built-in implementation for HMAC (:rfc:`2104`) using formally verified
+  code from the `HACL* <https://github.com/hacl-star/hacl-star/>`__ project.
+  (Contributed by Bénédikt Tran in :gh:`99108`.)
+
+
 http
 ----
 
index 30b6b478734dfc593a4a8b891f6e8890f23c1378..2af11c269470649178bbadecbb00d27844cb1114 100644 (file)
@@ -3,7 +3,6 @@
 Implements the HMAC algorithm as described by RFC 2104.
 """
 
-import warnings as _warnings
 try:
     import _hashlib as _hashopenssl
 except ImportError:
@@ -14,7 +13,10 @@ else:
     compare_digest = _hashopenssl.compare_digest
     _functype = type(_hashopenssl.openssl_sha256)  # builtin type
 
-import hashlib as _hashlib
+try:
+    import _hmac
+except ImportError:
+    _hmac = None
 
 trans_5C = bytes((x ^ 0x5C) for x in range(256))
 trans_36 = bytes((x ^ 0x36) for x in range(256))
@@ -24,11 +26,27 @@ trans_36 = bytes((x ^ 0x36) for x in range(256))
 digest_size = None
 
 
+def _get_digest_constructor(digest_like):
+    if callable(digest_like):
+        return digest_like
+    if isinstance(digest_like, str):
+        def digest_wrapper(d=b''):
+            import hashlib
+            return hashlib.new(digest_like, d)
+    else:
+        def digest_wrapper(d=b''):
+            return digest_like.new(d)
+    return digest_wrapper
+
+
 class HMAC:
     """RFC 2104 HMAC class.  Also complies with RFC 4231.
 
     This supports the API for Cryptographic Hash Functions (PEP 247).
     """
+
+    # Note: self.blocksize is the default blocksize; self.block_size
+    # is effective block size as well as the public API attribute.
     blocksize = 64  # 512-bit HMAC; can be changed in subclasses.
 
     __slots__ = (
@@ -50,32 +68,47 @@ class HMAC:
         """
 
         if not isinstance(key, (bytes, bytearray)):
-            raise TypeError("key: expected bytes or bytearray, but got %r" % type(key).__name__)
+            raise TypeError(f"key: expected bytes or bytearray, "
+                            f"but got {type(key).__name__!r}")
 
         if not digestmod:
             raise TypeError("Missing required argument 'digestmod'.")
 
+        self.__init(key, msg, digestmod)
+
+    def __init(self, key, msg, digestmod):
         if _hashopenssl and isinstance(digestmod, (str, _functype)):
             try:
-                self._init_hmac(key, msg, digestmod)
+                self._init_openssl_hmac(key, msg, digestmod)
+                return
             except _hashopenssl.UnsupportedDigestmodError:
-                self._init_old(key, msg, digestmod)
-        else:
-            self._init_old(key, msg, digestmod)
+                pass
+        if _hmac and isinstance(digestmod, str):
+            try:
+                self._init_builtin_hmac(key, msg, digestmod)
+                return
+            except _hmac.UnknownHashError:
+                pass
+        self._init_old(key, msg, digestmod)
 
-    def _init_hmac(self, key, msg, digestmod):
+    def _init_openssl_hmac(self, key, msg, digestmod):
         self._hmac = _hashopenssl.hmac_new(key, msg, digestmod=digestmod)
         self._inner = self._outer = None  # because the slots are defined
         self.digest_size = self._hmac.digest_size
         self.block_size = self._hmac.block_size
 
+    _init_hmac = _init_openssl_hmac  # for backward compatibility (if any)
+
+    def _init_builtin_hmac(self, key, msg, digestmod):
+        self._hmac = _hmac.new(key, msg, digestmod=digestmod)
+        self._inner = self._outer = None  # because the slots are defined
+        self.digest_size = self._hmac.digest_size
+        self.block_size = self._hmac.block_size
+
     def _init_old(self, key, msg, digestmod):
-        if callable(digestmod):
-            digest_cons = digestmod
-        elif isinstance(digestmod, str):
-            digest_cons = lambda d=b'': _hashlib.new(digestmod, d)
-        else:
-            digest_cons = lambda d=b'': digestmod.new(d)
+        import warnings
+
+        digest_cons = _get_digest_constructor(digestmod)
 
         self._hmac = None
         self._outer = digest_cons()
@@ -85,21 +118,19 @@ class HMAC:
         if hasattr(self._inner, 'block_size'):
             blocksize = self._inner.block_size
             if blocksize < 16:
-                _warnings.warn('block_size of %d seems too small; using our '
-                               'default of %d.' % (blocksize, self.blocksize),
-                               RuntimeWarning, 2)
+                warnings.warn(f"block_size of {blocksize} seems too small; "
+                              f"using our default of {self.blocksize}.",
+                              RuntimeWarning, 2)
                 blocksize = self.blocksize
         else:
-            _warnings.warn('No block_size attribute on given digest object; '
-                           'Assuming %d.' % (self.blocksize),
-                           RuntimeWarning, 2)
+            warnings.warn("No block_size attribute on given digest object; "
+                          f"Assuming {self.blocksize}.",
+                          RuntimeWarning, 2)
             blocksize = self.blocksize
 
         if len(key) > blocksize:
             key = digest_cons(key).digest()
 
-        # self.blocksize is the default blocksize. self.block_size is
-        # effective block size as well as the public API attribute.
         self.block_size = blocksize
 
         key = key.ljust(blocksize, b'\0')
@@ -165,6 +196,7 @@ class HMAC:
         h = self._current()
         return h.hexdigest()
 
+
 def new(key, msg=None, digestmod=''):
     """Create a new hashing object and return it.
 
@@ -194,25 +226,29 @@ def digest(key, msg, digest):
             A hashlib constructor returning a new hash object. *OR*
             A module supporting PEP 247.
     """
-    if _hashopenssl is not None and isinstance(digest, (str, _functype)):
+    if _hashopenssl and isinstance(digest, (str, _functype)):
         try:
             return _hashopenssl.hmac_digest(key, msg, digest)
         except _hashopenssl.UnsupportedDigestmodError:
             pass
 
-    if callable(digest):
-        digest_cons = digest
-    elif isinstance(digest, str):
-        digest_cons = lambda d=b'': _hashlib.new(digest, d)
-    else:
-        digest_cons = lambda d=b'': digest.new(d)
+    if _hmac and isinstance(digest, str):
+        try:
+            return _hmac.compute_digest(key, msg, digest)
+        except (OverflowError, _hmac.UnknownHashError):
+            pass
+
+    return _compute_digest_fallback(key, msg, digest)
+
 
+def _compute_digest_fallback(key, msg, digest):
+    digest_cons = _get_digest_constructor(digest)
     inner = digest_cons()
     outer = digest_cons()
     blocksize = getattr(inner, 'block_size', 64)
     if len(key) > blocksize:
         key = digest_cons(key).digest()
-    key = key + b'\x00' * (blocksize - len(key))
+    key = key.ljust(blocksize, b'\0')
     inner.update(key.translate(trans_36))
     outer.update(key.translate(trans_5C))
     inner.update(msg)
index bed3d696cb384dd02c7cf09f59f1245773868e47..06fac410a5e20fd9333703eba5ba5f5bba35c807 100644 (file)
@@ -8,11 +8,20 @@ try:
 except ImportError:
     _hashlib = None
 
+try:
+    import _hmac
+except ImportError:
+    _hmac = None
+
 
 def requires_hashlib():
     return unittest.skipIf(_hashlib is None, "requires _hashlib")
 
 
+def requires_builtin_hmac():
+    return unittest.skipIf(_hmac is None, "requires _hmac")
+
+
 def _decorate_func_or_class(func_or_class, decorator_func):
     if not isinstance(func_or_class, type):
         return decorator_func(func_or_class)
index 03b9defdce87d7b185b55dae3066ba12e64c616c..42b8a91ae580d2de73fed032cf6024a289536a24 100644 (file)
@@ -4,6 +4,7 @@ import hmac
 import hashlib
 import random
 import test.support.hashlib_helper as hashlib_helper
+import types
 import unittest
 import unittest.mock
 import warnings
@@ -47,7 +48,7 @@ class PyModuleMixin(ModuleMixin):
         cls.hmac = import_fresh_module('hmac', blocked=['_hashlib', '_hmac'])
 
 
-@unittest.skip("no builtin implementation for HMAC for now")
+@hashlib_helper.requires_builtin_hmac()
 class BuiltinModuleMixin(ModuleMixin):
     """Built-in HACL* implementation of HMAC."""
 
@@ -128,6 +129,16 @@ class ThroughOpenSSLAPIMixin(CreatorMixin, DigestMixin):
         return _hashlib.hmac_digest(key, msg, digest=digestmod)
 
 
+class ThroughBuiltinAPIMixin(BuiltinModuleMixin, CreatorMixin, DigestMixin):
+    """Mixin delegating to _hmac.new() and _hmac.compute_digest()."""
+
+    def hmac_new(self, key, msg=None, digestmod=None):
+        return self.hmac.new(key, msg, digestmod=digestmod)
+
+    def hmac_digest(self, key, msg=None, digestmod=None):
+        return self.hmac.compute_digest(key, msg, digest=digestmod)
+
+
 class ObjectCheckerMixin:
     """Mixin for checking HMAC objects (pure Python, OpenSSL or built-in)."""
 
@@ -205,6 +216,10 @@ class AssertersMixin(CreatorMixin, DigestMixin, ObjectCheckerMixin):
                 self.assert_hmac_hexdigest(
                     key, msg, hexdigest, digestmod, digest_size
                 )
+                self.assert_hmac_common_cases(
+                    key, msg, hexdigest, digestmod,
+                    hashname, digest_size, block_size
+                )
                 self.assert_hmac_extra_cases(
                     key, msg, hexdigest, digestmod,
                     hashname, digest_size, block_size
@@ -224,7 +239,7 @@ class AssertersMixin(CreatorMixin, DigestMixin, ObjectCheckerMixin):
 
         This test uses the `hmac_new()` method to create HMAC objects.
         """
-        self._check_hmac_new(
+        self.check_hmac_new(
             key, msg, hexdigest, hashname, digest_size, block_size,
             hmac_new_func=self.hmac_new,
             hmac_new_kwds={'digestmod': digestmod},
@@ -237,15 +252,15 @@ class AssertersMixin(CreatorMixin, DigestMixin, ObjectCheckerMixin):
 
         This test uses the `hmac_new_by_name()` method to create HMAC objects.
         """
-        self._check_hmac_new(
+        self.check_hmac_new(
             key, msg, hexdigest, hashname, digest_size, block_size,
             hmac_new_func=self.hmac_new_by_name,
             hmac_new_kwds={'hashname': hashname},
         )
 
-    def _check_hmac_new(
+    def check_hmac_new(
         self, key, msg, hexdigest, hashname, digest_size, block_size,
-        hmac_new_func, hmac_new_kwds,
+        hmac_new_func, hmac_new_kwds=types.MappingProxyType({}),
     ):
         """Check that HMAC(key, msg) == digest.
 
@@ -272,7 +287,7 @@ class AssertersMixin(CreatorMixin, DigestMixin, ObjectCheckerMixin):
         self, key, msg, hexdigest, digestmod, digest_size,
     ):
         """Check a HMAC digest computed by hmac_digest()."""
-        self._check_hmac_hexdigest(
+        self.check_hmac_hexdigest(
             key, msg, hexdigest, digest_size,
             hmac_digest_func=self.hmac_digest,
             hmac_digest_kwds={'digestmod': digestmod},
@@ -283,40 +298,50 @@ class AssertersMixin(CreatorMixin, DigestMixin, ObjectCheckerMixin):
     ):
         """Check a HMAC digest computed by hmac_digest_by_name()."""
         self.assertIsInstance(hashname, str)
-        self._check_hmac_hexdigest(
+        self.check_hmac_hexdigest(
             key, msg, hexdigest, digest_size,
             hmac_digest_func=self.hmac_digest_by_name,
             hmac_digest_kwds={'hashname': hashname},
         )
 
-    def _check_hmac_hexdigest(
+    def check_hmac_hexdigest(
         self, key, msg, hexdigest, digest_size,
-        hmac_digest_func, hmac_digest_kwds,
+        hmac_digest_func, hmac_digest_kwds=types.MappingProxyType({}),
     ):
+        """Check and return a HMAC digest computed by hmac_digest_func().
+
+        This HMAC digest is computed by:
+
+            hmac_digest_func(key, msg, **hmac_digest_kwds)
+
+        This is typically useful for checking one-shot HMAC functions.
+        """
         d = hmac_digest_func(key, msg, **hmac_digest_kwds)
         self.assertEqual(len(d), digest_size)
         self.assertEqual(d, binascii.unhexlify(hexdigest))
+        return d
 
-    def assert_hmac_extra_cases(
+    def assert_hmac_common_cases(
         self, key, msg, hexdigest, digestmod, hashname, digest_size, block_size
     ):
-        """Extra tests that can be added in subclasses."""
+        """Common tests executed by all subclasses."""
         h1 = self.hmac_new_by_name(key, hashname=hashname)
         h2 = h1.copy()
         h2.update(b"test update should not affect original")
         h1.update(msg)
         self.check_object(h1, hexdigest, hashname, digest_size, block_size)
 
+    def assert_hmac_extra_cases(
+        self, key, msg, hexdigest, digestmod, hashname, digest_size, block_size
+    ):
+        """Extra tests that can be added in subclasses."""
+
 
 class PyAssertersMixin(PyModuleMixin, AssertersMixin):
 
     def assert_hmac_extra_cases(
         self, key, msg, hexdigest, digestmod, hashname, digest_size, block_size
     ):
-        super().assert_hmac_extra_cases(
-            key, msg, hexdigest, digestmod, hashname, digest_size, block_size
-        )
-
         h = self.hmac.HMAC.__new__(self.hmac.HMAC)
         h._init_old(key, msg, digestmod=digestmod)
         self.check_object(h, hexdigest, hashname, digest_size, block_size)
@@ -335,6 +360,10 @@ class OpenSSLAssertersMixin(ThroughOpenSSLAPIMixin, AssertersMixin):
         return self.hmac_digest(key, msg, digestmod=openssl_func)
 
 
+class BuiltinAssertersMixin(ThroughBuiltinAPIMixin, AssertersMixin):
+    pass
+
+
 class HashFunctionsTrait:
     """Trait class for 'hashfunc' in hmac_new() and hmac_digest()."""
 
@@ -719,6 +748,24 @@ class OpenSSLRFCTestCase(OpenSSLAssertersMixin,
     """
 
 
+class BuiltinRFCTestCase(BuiltinAssertersMixin,
+                         WithNamedHashFunctions, RFCTestCaseMixin,
+                         unittest.TestCase):
+    """Built-in HACL* implementation of HMAC.
+
+    The underlying hash functions are also HACL*-based.
+    """
+
+    def assert_hmac_extra_cases(
+        self, key, msg, hexdigest, digestmod, hashname, digest_size, block_size
+    ):
+        # assert one-shot HMAC at the same time
+        with self.subTest(key=key, msg=msg, hashname=hashname):
+            func = getattr(self.hmac, f'compute_{hashname}')
+            self.assertTrue(callable(func))
+            self.check_hmac_hexdigest(key, msg, hexdigest, digest_size, func)
+
+
 # TODO(picnixz): once we have a HACL* HMAC, we should also test the Python
 # implementation of HMAC with a HACL*-based hash function. For now, we only
 # test it partially via the '_sha2' module, but for completeness we could
@@ -726,7 +773,7 @@ class OpenSSLRFCTestCase(OpenSSLAssertersMixin,
 
 
 class DigestModTestCaseMixin(CreatorMixin, DigestMixin):
-    """Tests for the 'digestmod' parameter."""
+    """Tests for the 'digestmod' parameter for hmac_new() and hmac_digest()."""
 
     def assert_raises_missing_digestmod(self):
         """A context manager catching errors when a digestmod is missing."""
@@ -869,11 +916,15 @@ class PyModuleConstructorTestCase(ThroughModuleAPIMixin, PyConstructorBaseMixin,
 class ExtensionConstructorTestCaseMixin(DigestModTestCaseMixin,
                                         ConstructorTestCaseMixin):
 
-    # The underlying C class.
-    obj_type = None
+    @property
+    def obj_type(self):
+        """The underlying (non-instantiable) C class."""
+        raise NotImplementedError
 
-    # The exact exception class raised when a 'digestmod' parameter is invalid.
-    exc_type = None
+    @property
+    def exc_type(self):
+        """The exact exception class raised upon invalid 'digestmod' values."""
+        raise NotImplementedError
 
     def test_internal_types(self):
         # internal C types are immutable and cannot be instantiated
@@ -920,6 +971,24 @@ class OpenSSLConstructorTestCase(ThroughOpenSSLAPIMixin,
                 self.hmac_digest(b'key', b'msg', value)
 
 
+class BuiltinConstructorTestCase(ThroughBuiltinAPIMixin,
+                                 ExtensionConstructorTestCaseMixin,
+                                 unittest.TestCase):
+
+    @property
+    def obj_type(self):
+        return self.hmac.HMAC
+
+    @property
+    def exc_type(self):
+        return self.hmac.UnknownHashError
+
+    def test_hmac_digest_digestmod_parameter(self):
+        for value in [object, 'unknown', 1234, None]:
+            with self.subTest(value=value), self.assert_digestmod_error():
+                self.hmac_digest(b'key', b'msg', value)
+
+
 class SanityTestCaseMixin(CreatorMixin):
     """Sanity checks for HMAC objects and their object interface.
 
@@ -975,6 +1044,20 @@ class OpenSSLSanityTestCase(ThroughOpenSSLAPIMixin, SanityTestCaseMixin,
         self.assertStartsWith(repr(h), f"<{self.digestname} HMAC object @")
 
 
+class BuiltinSanityTestCase(ThroughBuiltinAPIMixin, SanityTestCaseMixin,
+                            unittest.TestCase):
+
+    @classmethod
+    def setUpClass(cls):
+        super().setUpClass()
+        cls.hmac_class = cls.hmac.HMAC
+        cls.digestname = 'sha256'
+
+    def test_repr(self):
+        h = self.hmac_new(b"my secret key", digestmod=self.digestname)
+        self.assertStartsWith(repr(h), f"<{self.digestname} HMAC object @")
+
+
 class UpdateTestCaseMixin:
     """Tests for the update() method (streaming HMAC)."""
 
@@ -1006,7 +1089,7 @@ class PyUpdateTestCase(UpdateTestCaseMixin, unittest.TestCase):
     @classmethod
     def setUpClass(cls):
         super().setUpClass()
-        cls.hmac = import_fresh_module('hmac', blocked=['_hashlib'])
+        cls.hmac = import_fresh_module('hmac', blocked=['_hashlib', '_hmac'])
 
     def HMAC(self, key, msg=None):
         return self.hmac.HMAC(key, msg, digestmod='sha256')
@@ -1016,7 +1099,16 @@ class PyUpdateTestCase(UpdateTestCaseMixin, unittest.TestCase):
 class OpenSSLUpdateTestCase(UpdateTestCaseMixin, unittest.TestCase):
 
     def HMAC(self, key, msg=None):
-        return hmac.new(key, msg, digestmod='sha256')
+        return _hashlib.hmac_new(key, msg, digestmod='sha256')
+
+
+class BuiltinUpdateTestCase(BuiltinModuleMixin,
+                            UpdateTestCaseMixin, unittest.TestCase):
+
+    def HMAC(self, key, msg=None):
+        # Even if Python does not build '_sha2', the HACL* sources
+        # are still built, making it possible to use SHA-2 hashes.
+        return self.hmac.new(key, msg, digestmod='sha256')
 
 
 class CopyBaseTestCase:
@@ -1107,7 +1199,16 @@ class ExtensionCopyTestCase(CopyBaseTestCase):
 class OpenSSLCopyTestCase(ExtensionCopyTestCase, unittest.TestCase):
 
     def init(self, h):
-        h._init_hmac(b"key", b"msg", digestmod="sha256")
+        h._init_openssl_hmac(b"key", b"msg", digestmod="sha256")
+
+
+@hashlib_helper.requires_builtin_hmac()
+class BuiltinCopyTestCase(ExtensionCopyTestCase, unittest.TestCase):
+
+    def init(self, h):
+        # Even if Python does not build '_sha2', the HACL* sources
+        # are still built, making it possible to use SHA-2 hashes.
+        h._init_builtin_hmac(b"key", b"msg", digestmod="sha256")
 
 
 class CompareDigestMixin:
index 3ef0c6320c85db6bc58c1f2736930828c731ab0b..e10c78d640347224034946d3243c81329a5b2848 100644 (file)
@@ -227,8 +227,12 @@ ENSUREPIP=      @ENSUREPIP@
 # Internal static libraries
 LIBMPDEC_A= Modules/_decimal/libmpdec/libmpdec.a
 LIBEXPAT_A= Modules/expat/libexpat.a
+LIBHACL_MD5_A= Modules/_hacl/libHacl_Hash_MD5.a
+LIBHACL_SHA1_A= Modules/_hacl/libHacl_Hash_SHA1.a
 LIBHACL_SHA2_A= Modules/_hacl/libHacl_Hash_SHA2.a
+LIBHACL_SHA3_A= Modules/_hacl/libHacl_Hash_SHA3.a
 LIBHACL_BLAKE2_A= Modules/_hacl/libHacl_Hash_Blake2.a
+LIBHACL_HMAC_A= Modules/_hacl/libHacl_HMAC.a
 LIBHACL_CFLAGS=@LIBHACL_CFLAGS@
 LIBHACL_SIMD128_FLAGS=@LIBHACL_SIMD128_FLAGS@
 LIBHACL_SIMD256_FLAGS=@LIBHACL_SIMD256_FLAGS@
@@ -656,30 +660,65 @@ LIBEXPAT_HEADERS= \
 ##########################################################################
 # hashlib's HACL* library
 
+LIBHACL_MD5_OBJS= \
+               Modules/_hacl/Hacl_Hash_MD5.o
+
+LIBHACL_SHA1_OBJS= \
+               Modules/_hacl/Hacl_Hash_SHA1.o
+
 LIBHACL_SHA2_OBJS= \
-                Modules/_hacl/Hacl_Hash_SHA2.o
+               Modules/_hacl/Hacl_Hash_SHA2.o
+
+LIBHACL_SHA3_OBJS= \
+               Modules/_hacl/Hacl_Hash_SHA3.o
 
 LIBHACL_BLAKE2_OBJS= \
-                Modules/_hacl/Hacl_Hash_Blake2s.o \
-                Modules/_hacl/Hacl_Hash_Blake2b.o \
-                Modules/_hacl/Lib_Memzero0.o \
+               Modules/_hacl/Hacl_Hash_Blake2s.o \
+               Modules/_hacl/Hacl_Hash_Blake2b.o \
+               Modules/_hacl/Lib_Memzero0.o \
                $(LIBHACL_SIMD128_OBJS) \
                $(LIBHACL_SIMD256_OBJS)
 
+LIBHACL_HMAC_OBJS= \
+               Modules/_hacl/Hacl_HMAC.o \
+               Modules/_hacl/Hacl_Streaming_HMAC.o \
+               $(LIBHACL_MD5_OBJS) \
+               $(LIBHACL_SHA1_OBJS) \
+               $(LIBHACL_SHA2_OBJS) \
+               $(LIBHACL_SHA3_OBJS) \
+               $(LIBHACL_BLAKE2_OBJS)
+
 LIBHACL_HEADERS= \
-                Modules/_hacl/include/krml/FStar_UInt128_Verified.h \
-                Modules/_hacl/include/krml/FStar_UInt_8_16_32_64.h \
-                Modules/_hacl/include/krml/fstar_uint128_struct_endianness.h \
-                Modules/_hacl/include/krml/internal/compat.h \
-                Modules/_hacl/include/krml/internal/target.h \
-                Modules/_hacl/include/krml/internal/types.h \
-                Modules/_hacl/include/krml/lowstar_endianness.h \
+               Modules/_hacl/include/krml/FStar_UInt128_Verified.h \
+               Modules/_hacl/include/krml/FStar_UInt_8_16_32_64.h \
+               Modules/_hacl/include/krml/fstar_uint128_struct_endianness.h \
+               Modules/_hacl/include/krml/internal/compat.h \
+               Modules/_hacl/include/krml/internal/target.h \
+               Modules/_hacl/include/krml/internal/types.h \
+               Modules/_hacl/include/krml/lowstar_endianness.h \
                Modules/_hacl/Hacl_Streaming_Types.h \
-                Modules/_hacl/python_hacl_namespaces.h
+               Modules/_hacl/internal/Hacl_Streaming_Types.h \
+               Modules/_hacl/libintvector.h \
+               Modules/_hacl/python_hacl_namespaces.h
+
+LIBHACL_MD5_HEADERS= \
+               Modules/_hacl/Hacl_Hash_MD5.h \
+               Modules/_hacl/internal/Hacl_Hash_MD5.h \
+               $(LIBHACL_HEADERS)
+
+LIBHACL_SHA1_HEADERS= \
+               Modules/_hacl/Hacl_Hash_SHA1.h \
+               Modules/_hacl/internal/Hacl_Hash_SHA1.h \
+               $(LIBHACL_HEADERS)
 
 LIBHACL_SHA2_HEADERS= \
-                Modules/_hacl/Hacl_Hash_SHA2.h \
-                Modules/_hacl/internal/Hacl_Hash_SHA2.h \
+               Modules/_hacl/Hacl_Hash_SHA2.h \
+               Modules/_hacl/internal/Hacl_Hash_SHA2.h \
+               $(LIBHACL_HEADERS)
+
+LIBHACL_SHA3_HEADERS= \
+               Modules/_hacl/Hacl_Hash_SHA3.h \
+               Modules/_hacl/internal/Hacl_Hash_SHA3.h \
                $(LIBHACL_HEADERS)
 
 LIBHACL_BLAKE2_HEADERS= \
@@ -695,6 +734,19 @@ LIBHACL_BLAKE2_HEADERS= \
                Modules/_hacl/internal/Hacl_Streaming_Types.h \
                $(LIBHACL_HEADERS)
 
+LIBHACL_HMAC_HEADERS= \
+               Modules/_hacl/Hacl_HMAC.h \
+               Modules/_hacl/Hacl_Streaming_HMAC.h \
+               Modules/_hacl/internal/Hacl_HMAC.h \
+               Modules/_hacl/internal/Hacl_Streaming_HMAC.h \
+               Modules/_hacl/libintvector-shim.h \
+               $(LIBHACL_MD5_HEADERS) \
+               $(LIBHACL_SHA1_HEADERS) \
+               $(LIBHACL_SHA2_HEADERS) \
+               $(LIBHACL_SHA3_HEADERS) \
+               $(LIBHACL_BLAKE2_HEADERS) \
+               $(LIBHACL_HEADERS)
+
 #########################################################################
 # Rules
 
@@ -1408,10 +1460,25 @@ $(LIBEXPAT_A): $(LIBEXPAT_OBJS)
        $(AR) $(ARFLAGS) $@ $(LIBEXPAT_OBJS)
 
 ##########################################################################
-# Build HACL* static libraries for hashlib: libHacl_Hash_SHA2.a, and
-# libHacl_Blake2.a -- the contents of the latter vary depending on whether we
+# Build HACL* static libraries for hashlib and HACL* HMAC.
+#
+# The contents of libHacl_Blake2.a vary depending on whether we
 # have the ability to compile vectorized versions
 
+Modules/_hacl/Hacl_Hash_MD5.o: $(srcdir)/Modules/_hacl/Hacl_Hash_MD5.c $(LIBHACL_MD5_HEADERS)
+       $(CC) -c $(LIBHACL_CFLAGS) -o $@ $(srcdir)/Modules/_hacl/Hacl_Hash_MD5.c
+
+$(LIBHACL_MD5_A): $(LIBHACL_MD5_OBJS)
+       -rm -f $@
+       $(AR) $(ARFLAGS) $@ $(LIBHACL_MD5_OBJS)
+
+Modules/_hacl/Hacl_Hash_SHA1.o: $(srcdir)/Modules/_hacl/Hacl_Hash_SHA1.c $(LIBHACL_SHA1_HEADERS)
+       $(CC) -c $(LIBHACL_CFLAGS) -o $@ $(srcdir)/Modules/_hacl/Hacl_Hash_SHA1.c
+
+$(LIBHACL_SHA1_A): $(LIBHACL_SHA1_OBJS)
+       -rm -f $@
+       $(AR) $(ARFLAGS) $@ $(LIBHACL_SHA1_OBJS)
+
 Modules/_hacl/Hacl_Hash_SHA2.o: $(srcdir)/Modules/_hacl/Hacl_Hash_SHA2.c $(LIBHACL_SHA2_HEADERS)
        $(CC) -c $(LIBHACL_CFLAGS) -o $@ $(srcdir)/Modules/_hacl/Hacl_Hash_SHA2.c
 
@@ -1419,6 +1486,13 @@ $(LIBHACL_SHA2_A): $(LIBHACL_SHA2_OBJS)
        -rm -f $@
        $(AR) $(ARFLAGS) $@ $(LIBHACL_SHA2_OBJS)
 
+Modules/_hacl/Hacl_Hash_SHA3.o: $(srcdir)/Modules/_hacl/Hacl_Hash_SHA3.c $(LIBHACL_SHA3_HEADERS)
+       $(CC) -c $(LIBHACL_CFLAGS) -o $@ $(srcdir)/Modules/_hacl/Hacl_Hash_SHA3.c
+
+$(LIBHACL_SHA3_A): $(LIBHACL_SHA3_OBJS)
+       -rm -f $@
+       $(AR) $(ARFLAGS) $@ $(LIBHACL_SHA3_OBJS)
+
 Modules/_hacl/Hacl_Hash_Blake2s.o: $(srcdir)/Modules/_hacl/Hacl_Hash_Blake2s.c $(LIBHACL_BLAKE2_HEADERS)
        $(CC) -c $(LIBHACL_CFLAGS) -o $@ $(srcdir)/Modules/_hacl/Hacl_Hash_Blake2s.c
 
@@ -1444,6 +1518,16 @@ $(LIBHACL_BLAKE2_A): $(LIBHACL_BLAKE2_OBJS)
        -rm -f $@
        $(AR) $(ARFLAGS) $@ $(LIBHACL_BLAKE2_OBJS)
 
+Modules/_hacl/Hacl_HMAC.o: $(srcdir)/Modules/_hacl/Hacl_HMAC.c $(LIBHACL_HMAC_HEADERS)
+       $(CC) -c $(LIBHACL_CFLAGS) -o $@ $(srcdir)/Modules/_hacl/Hacl_HMAC.c
+
+Modules/_hacl/Hacl_Streaming_HMAC.o: $(srcdir)/Modules/_hacl/Hacl_Streaming_HMAC.c $(LIBHACL_HMAC_HEADERS)
+       $(CC) -Wno-unused-variable -c $(LIBHACL_CFLAGS) -o $@ $(srcdir)/Modules/_hacl/Hacl_Streaming_HMAC.c
+
+$(LIBHACL_HMAC_A): $(LIBHACL_HMAC_OBJS)
+       -rm -f $@
+       $(AR) $(ARFLAGS) $@ $(LIBHACL_HMAC_OBJS)
+
 # create relative links from build/lib.platform/egg.so to Modules/egg.so
 # pybuilddir.txt is created too late. We cannot use it in Makefile
 # targets. ln --relative is not portable.
@@ -3216,11 +3300,12 @@ MODULE__DECIMAL_DEPS=$(srcdir)/Modules/_decimal/docstrings.h @LIBMPDEC_INTERNAL@
 MODULE__ELEMENTTREE_DEPS=$(srcdir)/Modules/pyexpat.c @LIBEXPAT_INTERNAL@
 MODULE__HASHLIB_DEPS=$(srcdir)/Modules/hashlib.h
 MODULE__IO_DEPS=$(srcdir)/Modules/_io/_iomodule.h
-MODULE__MD5_DEPS=$(srcdir)/Modules/hashlib.h $(LIBHACL_HEADERS) Modules/_hacl/Hacl_Hash_MD5.h Modules/_hacl/internal/Hacl_Hash_MD5.h Modules/_hacl/Hacl_Hash_MD5.c
-MODULE__SHA1_DEPS=$(srcdir)/Modules/hashlib.h $(LIBHACL_HEADERS) Modules/_hacl/Hacl_Hash_SHA1.h Modules/_hacl/internal/Hacl_Hash_SHA1.h Modules/_hacl/Hacl_Hash_SHA1.c
+MODULE__MD5_DEPS=$(srcdir)/Modules/hashlib.h $(LIBHACL_MD5_HEADERS) $(LIBHACL_MD5_A)
+MODULE__SHA1_DEPS=$(srcdir)/Modules/hashlib.h $(LIBHACL_SHA1_HEADERS) $(LIBHACL_SHA1_A)
 MODULE__SHA2_DEPS=$(srcdir)/Modules/hashlib.h $(LIBHACL_SHA2_HEADERS) $(LIBHACL_SHA2_A)
-MODULE__SHA3_DEPS=$(srcdir)/Modules/hashlib.h $(LIBHACL_HEADERS) Modules/_hacl/Hacl_Hash_SHA3.h Modules/_hacl/internal/Hacl_Hash_SHA3.h Modules/_hacl/Hacl_Hash_SHA3.c
+MODULE__SHA3_DEPS=$(srcdir)/Modules/hashlib.h $(LIBHACL_SHA3_HEADERS) $(LIBHACL_SHA3_A)
 MODULE__BLAKE2_DEPS=$(srcdir)/Modules/hashlib.h $(LIBHACL_BLAKE2_HEADERS) $(LIBHACL_BLAKE2_A)
+MODULE__HMAC_DEPS=$(srcdir)/Modules/hashlib.h $(LIBHACL_HMAC_HEADERS) $(LIBHACL_HMAC_A)
 MODULE__SOCKET_DEPS=$(srcdir)/Modules/socketmodule.h $(srcdir)/Modules/addrinfo.h $(srcdir)/Modules/getaddrinfo.c $(srcdir)/Modules/getnameinfo.c
 MODULE__SSL_DEPS=$(srcdir)/Modules/_ssl.h $(srcdir)/Modules/_ssl/cert.c $(srcdir)/Modules/_ssl/debughelpers.c $(srcdir)/Modules/_ssl/misc.c $(srcdir)/Modules/_ssl_data_111.h $(srcdir)/Modules/_ssl_data_300.h $(srcdir)/Modules/socketmodule.h
 MODULE__TESTCAPI_DEPS=$(srcdir)/Modules/_testcapi/parts.h $(srcdir)/Modules/_testcapi/util.h
diff --git a/Misc/NEWS.d/next/Core_and_Builtins/2025-02-15-14-36-32.gh-issue-99108.u6CfmK.rst b/Misc/NEWS.d/next/Core_and_Builtins/2025-02-15-14-36-32.gh-issue-99108.u6CfmK.rst
new file mode 100644 (file)
index 0000000..4cb6af1
--- /dev/null
@@ -0,0 +1,2 @@
+Add support for built-in implementation of HMAC (:rfc:`2104`) based on
+HACL*. Patch by Bénédikt Tran.
index 617c631c357db2c6659ea3ed3b168609409343b6..678a64df97743291c2994d0690e7e6e067b32658 100644 (file)
       ],
       "fileName": "Modules/expat/xmltok_ns.c"
     },
+    {
+      "SPDXID": "SPDXRef-FILE-Modules-hacl-Hacl-HMAC.c",
+      "checksums": [
+        {
+          "algorithm": "SHA1",
+          "checksumValue": "705dc7220dad725881592749f7febaf6135cc9fd"
+        },
+        {
+          "algorithm": "SHA256",
+          "checksumValue": "142adb769ff02b8a5327f0eb837e1f9a797bdf9a1684d21acd749dbb5b2e5be2"
+        }
+      ],
+      "fileName": "Modules/_hacl/Hacl_HMAC.c"
+    },
+    {
+      "SPDXID": "SPDXRef-FILE-Modules-hacl-Hacl-HMAC.h",
+      "checksums": [
+        {
+          "algorithm": "SHA1",
+          "checksumValue": "de7179fe6970e2b5d281dfed977ed91be635b8d2"
+        },
+        {
+          "algorithm": "SHA256",
+          "checksumValue": "c0ba888d87775c7d7f7d8a08dac7b3988fed81e11bb52396d90f762a8e90a7eb"
+        }
+      ],
+      "fileName": "Modules/_hacl/Hacl_HMAC.h"
+    },
     {
       "SPDXID": "SPDXRef-FILE-Modules-hacl-Hacl-Hash-Blake2b.c",
       "checksums": [
       ],
       "fileName": "Modules/_hacl/Hacl_Hash_SHA3.h"
     },
+    {
+      "SPDXID": "SPDXRef-FILE-Modules-hacl-Hacl-Streaming-HMAC.c",
+      "checksums": [
+        {
+          "algorithm": "SHA1",
+          "checksumValue": "8140310f505bb2619a749777a91487d666237bcf"
+        },
+        {
+          "algorithm": "SHA256",
+          "checksumValue": "9d95e6a651c22185d9b7c38f363d30159f810e6fcdc2208f29492837ed891e82"
+        }
+      ],
+      "fileName": "Modules/_hacl/Hacl_Streaming_HMAC.c"
+    },
+    {
+      "SPDXID": "SPDXRef-FILE-Modules-hacl-Hacl-Streaming-HMAC.h",
+      "checksums": [
+        {
+          "algorithm": "SHA1",
+          "checksumValue": "49523144583a15d96ba1646af02dc292e633bf8f"
+        },
+        {
+          "algorithm": "SHA256",
+          "checksumValue": "78345519bf6789264f6792b809ee97a9ecf7cb5829c674c61e2d99bfdfdc36fc"
+        }
+      ],
+      "fileName": "Modules/_hacl/Hacl_Streaming_HMAC.h"
+    },
     {
       "SPDXID": "SPDXRef-FILE-Modules-hacl-Hacl-Streaming-Types.h",
       "checksums": [
       ],
       "fileName": "Modules/_hacl/include/krml/lowstar_endianness.h"
     },
+    {
+      "SPDXID": "SPDXRef-FILE-Modules-hacl-internal-Hacl-HMAC.h",
+      "checksums": [
+        {
+          "algorithm": "SHA1",
+          "checksumValue": "aaa656e25a92ba83655e1398a97efa6981f60fc4"
+        },
+        {
+          "algorithm": "SHA256",
+          "checksumValue": "a59abc6e9b3019cb18976a15e634f5146bd965fc9babf4ccbf2b531164a34f85"
+        }
+      ],
+      "fileName": "Modules/_hacl/internal/Hacl_HMAC.h"
+    },
     {
       "SPDXID": "SPDXRef-FILE-Modules-hacl-internal-Hacl-Hash-Blake2b.h",
       "checksums": [
       ],
       "fileName": "Modules/_hacl/internal/Hacl_Impl_Blake2_Constants.h"
     },
+    {
+      "SPDXID": "SPDXRef-FILE-Modules-hacl-internal-Hacl-Streaming-HMAC.h",
+      "checksums": [
+        {
+          "algorithm": "SHA1",
+          "checksumValue": "2048f3cd61dbda2df862a2982ebaf24b6815ed51"
+        },
+        {
+          "algorithm": "SHA256",
+          "checksumValue": "b0f5a79c98525b0cb1659238e095641328b7da16a94cb57a0793e635d1da3653"
+        }
+      ],
+      "fileName": "Modules/_hacl/internal/Hacl_Streaming_HMAC.h"
+    },
     {
       "SPDXID": "SPDXRef-FILE-Modules-hacl-internal-Hacl-Streaming-Types.h",
       "checksums": [
       ],
       "fileName": "Modules/_hacl/lib_memzero0.h"
     },
+    {
+      "SPDXID": "SPDXRef-FILE-Modules-hacl-libintvector-shim.h",
+      "checksums": [
+        {
+          "algorithm": "SHA1",
+          "checksumValue": "a28d706b06985c14f01a5527e568beb28f28109e"
+        },
+        {
+          "algorithm": "SHA256",
+          "checksumValue": "f26e8339da7e0db3d6c8f70247300bd5876110a30e1fb883e59370da48e38f9e"
+        }
+      ],
+      "fileName": "Modules/_hacl/libintvector-shim.h"
+    },
     {
       "SPDXID": "SPDXRef-FILE-Modules-hacl-libintvector.h",
       "checksums": [
       "checksums": [
         {
           "algorithm": "SHA1",
-          "checksumValue": "37e3eb63c5c6f8ae671748bfde642c180b96d2de"
+          "checksumValue": "dbed915328619b1159012649a427c6928033dd90"
         },
         {
           "algorithm": "SHA256",
-          "checksumValue": "0b5c7892cc25a2b3467936c1f346a6186d9d0a257d1bd5671beda253b66e0f68"
+          "checksumValue": "0297ea0a5d1117e001d5dbb90f99d47ee9e0f9d3dd45da02ba5dc477e551cb5a"
         }
       ],
       "fileName": "Modules/_hacl/python_hacl_namespaces.h"
       "relationshipType": "CONTAINS",
       "spdxElementId": "SPDXRef-PACKAGE-expat"
     },
+    {
+      "relatedSpdxElement": "SPDXRef-FILE-Modules-hacl-Hacl-HMAC.c",
+      "relationshipType": "CONTAINS",
+      "spdxElementId": "SPDXRef-PACKAGE-hacl-star"
+    },
+    {
+      "relatedSpdxElement": "SPDXRef-FILE-Modules-hacl-Hacl-HMAC.h",
+      "relationshipType": "CONTAINS",
+      "spdxElementId": "SPDXRef-PACKAGE-hacl-star"
+    },
     {
       "relatedSpdxElement": "SPDXRef-FILE-Modules-hacl-Hacl-Hash-Blake2b.c",
       "relationshipType": "CONTAINS",
       "relationshipType": "CONTAINS",
       "spdxElementId": "SPDXRef-PACKAGE-hacl-star"
     },
+    {
+      "relatedSpdxElement": "SPDXRef-FILE-Modules-hacl-Hacl-Streaming-HMAC.c",
+      "relationshipType": "CONTAINS",
+      "spdxElementId": "SPDXRef-PACKAGE-hacl-star"
+    },
+    {
+      "relatedSpdxElement": "SPDXRef-FILE-Modules-hacl-Hacl-Streaming-HMAC.h",
+      "relationshipType": "CONTAINS",
+      "spdxElementId": "SPDXRef-PACKAGE-hacl-star"
+    },
     {
       "relatedSpdxElement": "SPDXRef-FILE-Modules-hacl-Hacl-Streaming-Types.h",
       "relationshipType": "CONTAINS",
       "relationshipType": "CONTAINS",
       "spdxElementId": "SPDXRef-PACKAGE-hacl-star"
     },
+    {
+      "relatedSpdxElement": "SPDXRef-FILE-Modules-hacl-internal-Hacl-HMAC.h",
+      "relationshipType": "CONTAINS",
+      "spdxElementId": "SPDXRef-PACKAGE-hacl-star"
+    },
     {
       "relatedSpdxElement": "SPDXRef-FILE-Modules-hacl-internal-Hacl-Hash-Blake2b.h",
       "relationshipType": "CONTAINS",
       "relationshipType": "CONTAINS",
       "spdxElementId": "SPDXRef-PACKAGE-hacl-star"
     },
+    {
+      "relatedSpdxElement": "SPDXRef-FILE-Modules-hacl-internal-Hacl-Streaming-HMAC.h",
+      "relationshipType": "CONTAINS",
+      "spdxElementId": "SPDXRef-PACKAGE-hacl-star"
+    },
     {
       "relatedSpdxElement": "SPDXRef-FILE-Modules-hacl-internal-Hacl-Streaming-Types.h",
       "relationshipType": "CONTAINS",
       "relationshipType": "CONTAINS",
       "spdxElementId": "SPDXRef-PACKAGE-hacl-star"
     },
+    {
+      "relatedSpdxElement": "SPDXRef-FILE-Modules-hacl-libintvector-shim.h",
+      "relationshipType": "CONTAINS",
+      "spdxElementId": "SPDXRef-PACKAGE-hacl-star"
+    },
     {
       "relatedSpdxElement": "SPDXRef-FILE-Modules-hacl-libintvector.h",
       "relationshipType": "CONTAINS",
index ddf39e0b9666100dc3e12645380bac54742aa79b..f075571ab94577fe33526df6af6e2eebd653a76b 100644 (file)
@@ -165,11 +165,12 @@ PYTHONPATH=$(COREPYTHONPATH)
 #pyexpat pyexpat.c
 
 # hashing builtins
-#_blake2 blake2module.c -I$(srcdir)/Modules/_hacl/include Modules/_hacl/libHacl_Hash_Blake2.a
-#_md5 md5module.c -I$(srcdir)/Modules/_hacl/include _hacl/Hacl_Hash_MD5.c -D_BSD_SOURCE -D_DEFAULT_SOURCE
-#_sha1 sha1module.c -I$(srcdir)/Modules/_hacl/include _hacl/Hacl_Hash_SHA1.c -D_BSD_SOURCE -D_DEFAULT_SOURCE
-#_sha2 sha2module.c -I$(srcdir)/Modules/_hacl/include Modules/_hacl/libHacl_Hash_SHA2.a
-#_sha3 sha3module.c -I$(srcdir)/Modules/_hacl/include _hacl/Hacl_Hash_SHA3.c -D_BSD_SOURCE -D_DEFAULT_SOURCE
+#_blake2 blake2module.c -I$(srcdir)/Modules/_hacl/include Modules/_hacl/libHacl_Hash_Blake2.a -D_BSD_SOURCE -D_DEFAULT_SOURCE
+#_md5 md5module.c -I$(srcdir)/Modules/_hacl/include Modules/_hacl/libHacl_Hash_MD5.a -D_BSD_SOURCE -D_DEFAULT_SOURCE
+#_sha1 sha1module.c -I$(srcdir)/Modules/_hacl/include Modules/_hacl/libHacl_Hash_SHA1.a -D_BSD_SOURCE -D_DEFAULT_SOURCE
+#_sha2 sha2module.c -I$(srcdir)/Modules/_hacl/include Modules/_hacl/libHacl_Hash_SHA2.a -D_BSD_SOURCE -D_DEFAULT_SOURCE
+#_sha3 sha3module.c -I$(srcdir)/Modules/_hacl/include Modules/_hacl/libHacl_Hash_SHA3.a -D_BSD_SOURCE -D_DEFAULT_SOURCE
+#_hmac hmacmodule.c -I$(srcdir)/Modules/_hacl/include Modules/_hacl/libHacl_HMAC.a -D_BSD_SOURCE -D_DEFAULT_SOURCE
 
 # text encodings and unicode
 #_codecs_cn cjkcodecs/_codecs_cn.c
index 6bb05a06a3465decf91d485293d46a1fce9c44b8..913c804c34ef764c41237e9f5a1afbe5a43e1a70 100644 (file)
 @MODULE_READLINE_TRUE@readline readline.c
 
 # hashing builtins, can be disabled with --without-builtin-hashlib-hashes
-@MODULE__MD5_TRUE@_md5 md5module.c -I$(srcdir)/Modules/_hacl/include _hacl/Hacl_Hash_MD5.c -D_BSD_SOURCE -D_DEFAULT_SOURCE
-@MODULE__SHA1_TRUE@_sha1 sha1module.c -I$(srcdir)/Modules/_hacl/include _hacl/Hacl_Hash_SHA1.c -D_BSD_SOURCE -D_DEFAULT_SOURCE
-@MODULE__SHA2_TRUE@_sha2 sha2module.c -I$(srcdir)/Modules/_hacl/include Modules/_hacl/libHacl_Hash_SHA2.a
-@MODULE__SHA3_TRUE@_sha3 sha3module.c -I$(srcdir)/Modules/_hacl/include _hacl/Hacl_Hash_SHA3.c -D_BSD_SOURCE -D_DEFAULT_SOURCE
-@MODULE__BLAKE2_TRUE@_blake2 blake2module.c -I$(srcdir)/Modules/_hacl/include Modules/_hacl/libHacl_Hash_Blake2.a
+@MODULE__MD5_TRUE@_md5 md5module.c -I$(srcdir)/Modules/_hacl/include Modules/_hacl/libHacl_Hash_MD5.a -D_BSD_SOURCE -D_DEFAULT_SOURCE
+@MODULE__SHA1_TRUE@_sha1 sha1module.c -I$(srcdir)/Modules/_hacl/include Modules/_hacl/libHacl_Hash_SHA1.a -D_BSD_SOURCE -D_DEFAULT_SOURCE
+@MODULE__SHA2_TRUE@_sha2 sha2module.c -I$(srcdir)/Modules/_hacl/include Modules/_hacl/libHacl_Hash_SHA2.a -D_BSD_SOURCE -D_DEFAULT_SOURCE
+@MODULE__SHA3_TRUE@_sha3 sha3module.c -I$(srcdir)/Modules/_hacl/include Modules/_hacl/libHacl_Hash_SHA3.a -D_BSD_SOURCE -D_DEFAULT_SOURCE
+@MODULE__BLAKE2_TRUE@_blake2 blake2module.c -I$(srcdir)/Modules/_hacl/include Modules/_hacl/libHacl_Hash_Blake2.a -D_BSD_SOURCE -D_DEFAULT_SOURCE
+
+@MODULE__HMAC_TRUE@_hmac hmacmodule.c
 
 ############################################################################
 # XML and text
diff --git a/Modules/_hacl/Hacl_HMAC.c b/Modules/_hacl/Hacl_HMAC.c
new file mode 100644 (file)
index 0000000..5299830
--- /dev/null
@@ -0,0 +1,1567 @@
+/* MIT License
+ *
+ * Copyright (c) 2016-2022 INRIA, CMU and Microsoft Corporation
+ * Copyright (c) 2022-2023 HACL* Contributors
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+
+#include "internal/Hacl_HMAC.h"
+
+#include "Hacl_Streaming_Types.h"
+
+#include "Hacl_Hash_SHA3.h"
+#include "Hacl_Hash_SHA2.h"
+#include "Hacl_Hash_Blake2s.h"
+#include "Hacl_Hash_Blake2b.h"
+
+#include "internal/Hacl_Hash_SHA3.h"
+#include "internal/Hacl_Hash_SHA2.h"
+#include "internal/Hacl_Hash_SHA1.h"
+#include "internal/Hacl_Hash_MD5.h"
+#include "internal/Hacl_Hash_Blake2s.h"
+#include "internal/Hacl_Hash_Blake2b.h"
+
+/**
+Write the HMAC-MD5 MAC of a message (`data`) by using a key (`key`) into `dst`.
+
+The key can be any length and will be hashed if it is longer and padded if it is shorter than 64 byte.
+`dst` must point to 16 bytes of memory.
+*/
+void
+Hacl_HMAC_compute_md5(
+  uint8_t *dst,
+  uint8_t *key,
+  uint32_t key_len,
+  uint8_t *data,
+  uint32_t data_len
+)
+{
+  uint8_t key_block[64U];
+  memset(key_block, 0U, 64U * sizeof (uint8_t));
+  uint8_t *nkey = key_block;
+  uint32_t ite;
+  if (key_len <= 64U)
+  {
+    ite = key_len;
+  }
+  else
+  {
+    ite = 16U;
+  }
+  uint8_t *zeroes = key_block + ite;
+  KRML_MAYBE_UNUSED_VAR(zeroes);
+  if (key_len <= 64U)
+  {
+    memcpy(nkey, key, key_len * sizeof (uint8_t));
+  }
+  else
+  {
+    Hacl_Hash_MD5_hash_oneshot(nkey, key, key_len);
+  }
+  uint8_t ipad[64U];
+  memset(ipad, 0x36U, 64U * sizeof (uint8_t));
+  for (uint32_t i = 0U; i < 64U; i++)
+  {
+    uint8_t xi = ipad[i];
+    uint8_t yi = key_block[i];
+    ipad[i] = (uint32_t)xi ^ (uint32_t)yi;
+  }
+  uint8_t opad[64U];
+  memset(opad, 0x5cU, 64U * sizeof (uint8_t));
+  for (uint32_t i = 0U; i < 64U; i++)
+  {
+    uint8_t xi = opad[i];
+    uint8_t yi = key_block[i];
+    opad[i] = (uint32_t)xi ^ (uint32_t)yi;
+  }
+  uint32_t s[4U] = { 0x67452301U, 0xefcdab89U, 0x98badcfeU, 0x10325476U };
+  uint8_t *dst1 = ipad;
+  if (data_len == 0U)
+  {
+    Hacl_Hash_MD5_update_last(s, 0ULL, ipad, 64U);
+  }
+  else
+  {
+    uint32_t block_len = 64U;
+    uint32_t n_blocks0 = data_len / block_len;
+    uint32_t rem0 = data_len % block_len;
+    K___uint32_t_uint32_t scrut;
+    if (n_blocks0 > 0U && rem0 == 0U)
+    {
+      uint32_t n_blocks_ = n_blocks0 - 1U;
+      scrut = ((K___uint32_t_uint32_t){ .fst = n_blocks_, .snd = data_len - n_blocks_ * block_len });
+    }
+    else
+    {
+      scrut = ((K___uint32_t_uint32_t){ .fst = n_blocks0, .snd = rem0 });
+    }
+    uint32_t n_blocks = scrut.fst;
+    uint32_t rem_len = scrut.snd;
+    uint32_t full_blocks_len = n_blocks * block_len;
+    uint8_t *full_blocks = data;
+    uint8_t *rem = data + full_blocks_len;
+    Hacl_Hash_MD5_update_multi(s, ipad, 1U);
+    Hacl_Hash_MD5_update_multi(s, full_blocks, n_blocks);
+    Hacl_Hash_MD5_update_last(s, (uint64_t)64U + (uint64_t)full_blocks_len, rem, rem_len);
+  }
+  Hacl_Hash_MD5_finish(s, dst1);
+  uint8_t *hash1 = ipad;
+  Hacl_Hash_MD5_init(s);
+  uint32_t block_len = 64U;
+  uint32_t n_blocks0 = 16U / block_len;
+  uint32_t rem0 = 16U % block_len;
+  K___uint32_t_uint32_t scrut;
+  if (n_blocks0 > 0U && rem0 == 0U)
+  {
+    uint32_t n_blocks_ = n_blocks0 - 1U;
+    scrut = ((K___uint32_t_uint32_t){ .fst = n_blocks_, .snd = 16U - n_blocks_ * block_len });
+  }
+  else
+  {
+    scrut = ((K___uint32_t_uint32_t){ .fst = n_blocks0, .snd = rem0 });
+  }
+  uint32_t n_blocks = scrut.fst;
+  uint32_t rem_len = scrut.snd;
+  uint32_t full_blocks_len = n_blocks * block_len;
+  uint8_t *full_blocks = hash1;
+  uint8_t *rem = hash1 + full_blocks_len;
+  Hacl_Hash_MD5_update_multi(s, opad, 1U);
+  Hacl_Hash_MD5_update_multi(s, full_blocks, n_blocks);
+  Hacl_Hash_MD5_update_last(s, (uint64_t)64U + (uint64_t)full_blocks_len, rem, rem_len);
+  Hacl_Hash_MD5_finish(s, dst);
+}
+
+/**
+Write the HMAC-SHA-1 MAC of a message (`data`) by using a key (`key`) into `dst`.
+
+The key can be any length and will be hashed if it is longer and padded if it is shorter than 64 byte.
+`dst` must point to 20 bytes of memory.
+*/
+void
+Hacl_HMAC_compute_sha1(
+  uint8_t *dst,
+  uint8_t *key,
+  uint32_t key_len,
+  uint8_t *data,
+  uint32_t data_len
+)
+{
+  uint8_t key_block[64U];
+  memset(key_block, 0U, 64U * sizeof (uint8_t));
+  uint8_t *nkey = key_block;
+  uint32_t ite;
+  if (key_len <= 64U)
+  {
+    ite = key_len;
+  }
+  else
+  {
+    ite = 20U;
+  }
+  uint8_t *zeroes = key_block + ite;
+  KRML_MAYBE_UNUSED_VAR(zeroes);
+  if (key_len <= 64U)
+  {
+    memcpy(nkey, key, key_len * sizeof (uint8_t));
+  }
+  else
+  {
+    Hacl_Hash_SHA1_hash_oneshot(nkey, key, key_len);
+  }
+  uint8_t ipad[64U];
+  memset(ipad, 0x36U, 64U * sizeof (uint8_t));
+  for (uint32_t i = 0U; i < 64U; i++)
+  {
+    uint8_t xi = ipad[i];
+    uint8_t yi = key_block[i];
+    ipad[i] = (uint32_t)xi ^ (uint32_t)yi;
+  }
+  uint8_t opad[64U];
+  memset(opad, 0x5cU, 64U * sizeof (uint8_t));
+  for (uint32_t i = 0U; i < 64U; i++)
+  {
+    uint8_t xi = opad[i];
+    uint8_t yi = key_block[i];
+    opad[i] = (uint32_t)xi ^ (uint32_t)yi;
+  }
+  uint32_t s[5U] = { 0x67452301U, 0xefcdab89U, 0x98badcfeU, 0x10325476U, 0xc3d2e1f0U };
+  uint8_t *dst1 = ipad;
+  if (data_len == 0U)
+  {
+    Hacl_Hash_SHA1_update_last(s, 0ULL, ipad, 64U);
+  }
+  else
+  {
+    uint32_t block_len = 64U;
+    uint32_t n_blocks0 = data_len / block_len;
+    uint32_t rem0 = data_len % block_len;
+    K___uint32_t_uint32_t scrut;
+    if (n_blocks0 > 0U && rem0 == 0U)
+    {
+      uint32_t n_blocks_ = n_blocks0 - 1U;
+      scrut = ((K___uint32_t_uint32_t){ .fst = n_blocks_, .snd = data_len - n_blocks_ * block_len });
+    }
+    else
+    {
+      scrut = ((K___uint32_t_uint32_t){ .fst = n_blocks0, .snd = rem0 });
+    }
+    uint32_t n_blocks = scrut.fst;
+    uint32_t rem_len = scrut.snd;
+    uint32_t full_blocks_len = n_blocks * block_len;
+    uint8_t *full_blocks = data;
+    uint8_t *rem = data + full_blocks_len;
+    Hacl_Hash_SHA1_update_multi(s, ipad, 1U);
+    Hacl_Hash_SHA1_update_multi(s, full_blocks, n_blocks);
+    Hacl_Hash_SHA1_update_last(s, (uint64_t)64U + (uint64_t)full_blocks_len, rem, rem_len);
+  }
+  Hacl_Hash_SHA1_finish(s, dst1);
+  uint8_t *hash1 = ipad;
+  Hacl_Hash_SHA1_init(s);
+  uint32_t block_len = 64U;
+  uint32_t n_blocks0 = 20U / block_len;
+  uint32_t rem0 = 20U % block_len;
+  K___uint32_t_uint32_t scrut;
+  if (n_blocks0 > 0U && rem0 == 0U)
+  {
+    uint32_t n_blocks_ = n_blocks0 - 1U;
+    scrut = ((K___uint32_t_uint32_t){ .fst = n_blocks_, .snd = 20U - n_blocks_ * block_len });
+  }
+  else
+  {
+    scrut = ((K___uint32_t_uint32_t){ .fst = n_blocks0, .snd = rem0 });
+  }
+  uint32_t n_blocks = scrut.fst;
+  uint32_t rem_len = scrut.snd;
+  uint32_t full_blocks_len = n_blocks * block_len;
+  uint8_t *full_blocks = hash1;
+  uint8_t *rem = hash1 + full_blocks_len;
+  Hacl_Hash_SHA1_update_multi(s, opad, 1U);
+  Hacl_Hash_SHA1_update_multi(s, full_blocks, n_blocks);
+  Hacl_Hash_SHA1_update_last(s, (uint64_t)64U + (uint64_t)full_blocks_len, rem, rem_len);
+  Hacl_Hash_SHA1_finish(s, dst);
+}
+
+/**
+Write the HMAC-SHA-2-224 MAC of a message (`data`) by using a key (`key`) into `dst`.
+
+The key can be any length and will be hashed if it is longer and padded if it is shorter than 64 bytes.
+`dst` must point to 28 bytes of memory.
+*/
+void
+Hacl_HMAC_compute_sha2_224(
+  uint8_t *dst,
+  uint8_t *key,
+  uint32_t key_len,
+  uint8_t *data,
+  uint32_t data_len
+)
+{
+  uint8_t key_block[64U];
+  memset(key_block, 0U, 64U * sizeof (uint8_t));
+  uint8_t *nkey = key_block;
+  uint32_t ite;
+  if (key_len <= 64U)
+  {
+    ite = key_len;
+  }
+  else
+  {
+    ite = 28U;
+  }
+  uint8_t *zeroes = key_block + ite;
+  KRML_MAYBE_UNUSED_VAR(zeroes);
+  if (key_len <= 64U)
+  {
+    memcpy(nkey, key, key_len * sizeof (uint8_t));
+  }
+  else
+  {
+    Hacl_Hash_SHA2_hash_224(nkey, key, key_len);
+  }
+  uint8_t ipad[64U];
+  memset(ipad, 0x36U, 64U * sizeof (uint8_t));
+  for (uint32_t i = 0U; i < 64U; i++)
+  {
+    uint8_t xi = ipad[i];
+    uint8_t yi = key_block[i];
+    ipad[i] = (uint32_t)xi ^ (uint32_t)yi;
+  }
+  uint8_t opad[64U];
+  memset(opad, 0x5cU, 64U * sizeof (uint8_t));
+  for (uint32_t i = 0U; i < 64U; i++)
+  {
+    uint8_t xi = opad[i];
+    uint8_t yi = key_block[i];
+    opad[i] = (uint32_t)xi ^ (uint32_t)yi;
+  }
+  uint32_t st[8U] = { 0U };
+  KRML_MAYBE_FOR8(i,
+    0U,
+    8U,
+    1U,
+    uint32_t *os = st;
+    uint32_t x = Hacl_Hash_SHA2_h224[i];
+    os[i] = x;);
+  uint32_t *s = st;
+  uint8_t *dst1 = ipad;
+  if (data_len == 0U)
+  {
+    Hacl_Hash_SHA2_sha224_update_last(0ULL + (uint64_t)64U, 64U, ipad, s);
+  }
+  else
+  {
+    uint32_t block_len = 64U;
+    uint32_t n_blocks0 = data_len / block_len;
+    uint32_t rem0 = data_len % block_len;
+    K___uint32_t_uint32_t scrut;
+    if (n_blocks0 > 0U && rem0 == 0U)
+    {
+      uint32_t n_blocks_ = n_blocks0 - 1U;
+      scrut = ((K___uint32_t_uint32_t){ .fst = n_blocks_, .snd = data_len - n_blocks_ * block_len });
+    }
+    else
+    {
+      scrut = ((K___uint32_t_uint32_t){ .fst = n_blocks0, .snd = rem0 });
+    }
+    uint32_t n_blocks = scrut.fst;
+    uint32_t rem_len = scrut.snd;
+    uint32_t full_blocks_len = n_blocks * block_len;
+    uint8_t *full_blocks = data;
+    uint8_t *rem = data + full_blocks_len;
+    Hacl_Hash_SHA2_sha224_update_nblocks(64U, ipad, s);
+    Hacl_Hash_SHA2_sha224_update_nblocks(n_blocks * 64U, full_blocks, s);
+    Hacl_Hash_SHA2_sha224_update_last((uint64_t)64U + (uint64_t)full_blocks_len + (uint64_t)rem_len,
+      rem_len,
+      rem,
+      s);
+  }
+  Hacl_Hash_SHA2_sha224_finish(s, dst1);
+  uint8_t *hash1 = ipad;
+  Hacl_Hash_SHA2_sha224_init(s);
+  uint32_t block_len = 64U;
+  uint32_t n_blocks0 = 28U / block_len;
+  uint32_t rem0 = 28U % block_len;
+  K___uint32_t_uint32_t scrut;
+  if (n_blocks0 > 0U && rem0 == 0U)
+  {
+    uint32_t n_blocks_ = n_blocks0 - 1U;
+    scrut = ((K___uint32_t_uint32_t){ .fst = n_blocks_, .snd = 28U - n_blocks_ * block_len });
+  }
+  else
+  {
+    scrut = ((K___uint32_t_uint32_t){ .fst = n_blocks0, .snd = rem0 });
+  }
+  uint32_t n_blocks = scrut.fst;
+  uint32_t rem_len = scrut.snd;
+  uint32_t full_blocks_len = n_blocks * block_len;
+  uint8_t *full_blocks = hash1;
+  uint8_t *rem = hash1 + full_blocks_len;
+  Hacl_Hash_SHA2_sha224_update_nblocks(64U, opad, s);
+  Hacl_Hash_SHA2_sha224_update_nblocks(n_blocks * 64U, full_blocks, s);
+  Hacl_Hash_SHA2_sha224_update_last((uint64_t)64U + (uint64_t)full_blocks_len + (uint64_t)rem_len,
+    rem_len,
+    rem,
+    s);
+  Hacl_Hash_SHA2_sha224_finish(s, dst);
+}
+
+/**
+Write the HMAC-SHA-2-256 MAC of a message (`data`) by using a key (`key`) into `dst`.
+
+The key can be any length and will be hashed if it is longer and padded if it is shorter than 64 bytes.
+`dst` must point to 32 bytes of memory.
+*/
+void
+Hacl_HMAC_compute_sha2_256(
+  uint8_t *dst,
+  uint8_t *key,
+  uint32_t key_len,
+  uint8_t *data,
+  uint32_t data_len
+)
+{
+  uint8_t key_block[64U];
+  memset(key_block, 0U, 64U * sizeof (uint8_t));
+  uint8_t *nkey = key_block;
+  uint32_t ite;
+  if (key_len <= 64U)
+  {
+    ite = key_len;
+  }
+  else
+  {
+    ite = 32U;
+  }
+  uint8_t *zeroes = key_block + ite;
+  KRML_MAYBE_UNUSED_VAR(zeroes);
+  if (key_len <= 64U)
+  {
+    memcpy(nkey, key, key_len * sizeof (uint8_t));
+  }
+  else
+  {
+    Hacl_Hash_SHA2_hash_256(nkey, key, key_len);
+  }
+  uint8_t ipad[64U];
+  memset(ipad, 0x36U, 64U * sizeof (uint8_t));
+  for (uint32_t i = 0U; i < 64U; i++)
+  {
+    uint8_t xi = ipad[i];
+    uint8_t yi = key_block[i];
+    ipad[i] = (uint32_t)xi ^ (uint32_t)yi;
+  }
+  uint8_t opad[64U];
+  memset(opad, 0x5cU, 64U * sizeof (uint8_t));
+  for (uint32_t i = 0U; i < 64U; i++)
+  {
+    uint8_t xi = opad[i];
+    uint8_t yi = key_block[i];
+    opad[i] = (uint32_t)xi ^ (uint32_t)yi;
+  }
+  uint32_t st[8U] = { 0U };
+  KRML_MAYBE_FOR8(i,
+    0U,
+    8U,
+    1U,
+    uint32_t *os = st;
+    uint32_t x = Hacl_Hash_SHA2_h256[i];
+    os[i] = x;);
+  uint32_t *s = st;
+  uint8_t *dst1 = ipad;
+  if (data_len == 0U)
+  {
+    Hacl_Hash_SHA2_sha256_update_last(0ULL + (uint64_t)64U, 64U, ipad, s);
+  }
+  else
+  {
+    uint32_t block_len = 64U;
+    uint32_t n_blocks0 = data_len / block_len;
+    uint32_t rem0 = data_len % block_len;
+    K___uint32_t_uint32_t scrut;
+    if (n_blocks0 > 0U && rem0 == 0U)
+    {
+      uint32_t n_blocks_ = n_blocks0 - 1U;
+      scrut = ((K___uint32_t_uint32_t){ .fst = n_blocks_, .snd = data_len - n_blocks_ * block_len });
+    }
+    else
+    {
+      scrut = ((K___uint32_t_uint32_t){ .fst = n_blocks0, .snd = rem0 });
+    }
+    uint32_t n_blocks = scrut.fst;
+    uint32_t rem_len = scrut.snd;
+    uint32_t full_blocks_len = n_blocks * block_len;
+    uint8_t *full_blocks = data;
+    uint8_t *rem = data + full_blocks_len;
+    Hacl_Hash_SHA2_sha256_update_nblocks(64U, ipad, s);
+    Hacl_Hash_SHA2_sha256_update_nblocks(n_blocks * 64U, full_blocks, s);
+    Hacl_Hash_SHA2_sha256_update_last((uint64_t)64U + (uint64_t)full_blocks_len + (uint64_t)rem_len,
+      rem_len,
+      rem,
+      s);
+  }
+  Hacl_Hash_SHA2_sha256_finish(s, dst1);
+  uint8_t *hash1 = ipad;
+  Hacl_Hash_SHA2_sha256_init(s);
+  uint32_t block_len = 64U;
+  uint32_t n_blocks0 = 32U / block_len;
+  uint32_t rem0 = 32U % block_len;
+  K___uint32_t_uint32_t scrut;
+  if (n_blocks0 > 0U && rem0 == 0U)
+  {
+    uint32_t n_blocks_ = n_blocks0 - 1U;
+    scrut = ((K___uint32_t_uint32_t){ .fst = n_blocks_, .snd = 32U - n_blocks_ * block_len });
+  }
+  else
+  {
+    scrut = ((K___uint32_t_uint32_t){ .fst = n_blocks0, .snd = rem0 });
+  }
+  uint32_t n_blocks = scrut.fst;
+  uint32_t rem_len = scrut.snd;
+  uint32_t full_blocks_len = n_blocks * block_len;
+  uint8_t *full_blocks = hash1;
+  uint8_t *rem = hash1 + full_blocks_len;
+  Hacl_Hash_SHA2_sha256_update_nblocks(64U, opad, s);
+  Hacl_Hash_SHA2_sha256_update_nblocks(n_blocks * 64U, full_blocks, s);
+  Hacl_Hash_SHA2_sha256_update_last((uint64_t)64U + (uint64_t)full_blocks_len + (uint64_t)rem_len,
+    rem_len,
+    rem,
+    s);
+  Hacl_Hash_SHA2_sha256_finish(s, dst);
+}
+
+/**
+Write the HMAC-SHA-2-384 MAC of a message (`data`) by using a key (`key`) into `dst`.
+
+The key can be any length and will be hashed if it is longer and padded if it is shorter than 128 bytes.
+`dst` must point to 48 bytes of memory.
+*/
+void
+Hacl_HMAC_compute_sha2_384(
+  uint8_t *dst,
+  uint8_t *key,
+  uint32_t key_len,
+  uint8_t *data,
+  uint32_t data_len
+)
+{
+  uint8_t key_block[128U];
+  memset(key_block, 0U, 128U * sizeof (uint8_t));
+  uint8_t *nkey = key_block;
+  uint32_t ite;
+  if (key_len <= 128U)
+  {
+    ite = key_len;
+  }
+  else
+  {
+    ite = 48U;
+  }
+  uint8_t *zeroes = key_block + ite;
+  KRML_MAYBE_UNUSED_VAR(zeroes);
+  if (key_len <= 128U)
+  {
+    memcpy(nkey, key, key_len * sizeof (uint8_t));
+  }
+  else
+  {
+    Hacl_Hash_SHA2_hash_384(nkey, key, key_len);
+  }
+  uint8_t ipad[128U];
+  memset(ipad, 0x36U, 128U * sizeof (uint8_t));
+  for (uint32_t i = 0U; i < 128U; i++)
+  {
+    uint8_t xi = ipad[i];
+    uint8_t yi = key_block[i];
+    ipad[i] = (uint32_t)xi ^ (uint32_t)yi;
+  }
+  uint8_t opad[128U];
+  memset(opad, 0x5cU, 128U * sizeof (uint8_t));
+  for (uint32_t i = 0U; i < 128U; i++)
+  {
+    uint8_t xi = opad[i];
+    uint8_t yi = key_block[i];
+    opad[i] = (uint32_t)xi ^ (uint32_t)yi;
+  }
+  uint64_t st[8U] = { 0U };
+  KRML_MAYBE_FOR8(i,
+    0U,
+    8U,
+    1U,
+    uint64_t *os = st;
+    uint64_t x = Hacl_Hash_SHA2_h384[i];
+    os[i] = x;);
+  uint64_t *s = st;
+  uint8_t *dst1 = ipad;
+  if (data_len == 0U)
+  {
+    Hacl_Hash_SHA2_sha384_update_last(FStar_UInt128_add(FStar_UInt128_uint64_to_uint128(0ULL),
+        FStar_UInt128_uint64_to_uint128((uint64_t)128U)),
+      128U,
+      ipad,
+      s);
+  }
+  else
+  {
+    uint32_t block_len = 128U;
+    uint32_t n_blocks0 = data_len / block_len;
+    uint32_t rem0 = data_len % block_len;
+    K___uint32_t_uint32_t scrut;
+    if (n_blocks0 > 0U && rem0 == 0U)
+    {
+      uint32_t n_blocks_ = n_blocks0 - 1U;
+      scrut = ((K___uint32_t_uint32_t){ .fst = n_blocks_, .snd = data_len - n_blocks_ * block_len });
+    }
+    else
+    {
+      scrut = ((K___uint32_t_uint32_t){ .fst = n_blocks0, .snd = rem0 });
+    }
+    uint32_t n_blocks = scrut.fst;
+    uint32_t rem_len = scrut.snd;
+    uint32_t full_blocks_len = n_blocks * block_len;
+    uint8_t *full_blocks = data;
+    uint8_t *rem = data + full_blocks_len;
+    Hacl_Hash_SHA2_sha384_update_nblocks(128U, ipad, s);
+    Hacl_Hash_SHA2_sha384_update_nblocks(n_blocks * 128U, full_blocks, s);
+    Hacl_Hash_SHA2_sha384_update_last(FStar_UInt128_add(FStar_UInt128_add(FStar_UInt128_uint64_to_uint128((uint64_t)128U),
+          FStar_UInt128_uint64_to_uint128((uint64_t)full_blocks_len)),
+        FStar_UInt128_uint64_to_uint128((uint64_t)rem_len)),
+      rem_len,
+      rem,
+      s);
+  }
+  Hacl_Hash_SHA2_sha384_finish(s, dst1);
+  uint8_t *hash1 = ipad;
+  Hacl_Hash_SHA2_sha384_init(s);
+  uint32_t block_len = 128U;
+  uint32_t n_blocks0 = 48U / block_len;
+  uint32_t rem0 = 48U % block_len;
+  K___uint32_t_uint32_t scrut;
+  if (n_blocks0 > 0U && rem0 == 0U)
+  {
+    uint32_t n_blocks_ = n_blocks0 - 1U;
+    scrut = ((K___uint32_t_uint32_t){ .fst = n_blocks_, .snd = 48U - n_blocks_ * block_len });
+  }
+  else
+  {
+    scrut = ((K___uint32_t_uint32_t){ .fst = n_blocks0, .snd = rem0 });
+  }
+  uint32_t n_blocks = scrut.fst;
+  uint32_t rem_len = scrut.snd;
+  uint32_t full_blocks_len = n_blocks * block_len;
+  uint8_t *full_blocks = hash1;
+  uint8_t *rem = hash1 + full_blocks_len;
+  Hacl_Hash_SHA2_sha384_update_nblocks(128U, opad, s);
+  Hacl_Hash_SHA2_sha384_update_nblocks(n_blocks * 128U, full_blocks, s);
+  Hacl_Hash_SHA2_sha384_update_last(FStar_UInt128_add(FStar_UInt128_add(FStar_UInt128_uint64_to_uint128((uint64_t)128U),
+        FStar_UInt128_uint64_to_uint128((uint64_t)full_blocks_len)),
+      FStar_UInt128_uint64_to_uint128((uint64_t)rem_len)),
+    rem_len,
+    rem,
+    s);
+  Hacl_Hash_SHA2_sha384_finish(s, dst);
+}
+
+/**
+Write the HMAC-SHA-2-512 MAC of a message (`data`) by using a key (`key`) into `dst`.
+
+The key can be any length and will be hashed if it is longer and padded if it is shorter than 128 bytes.
+`dst` must point to 64 bytes of memory.
+*/
+void
+Hacl_HMAC_compute_sha2_512(
+  uint8_t *dst,
+  uint8_t *key,
+  uint32_t key_len,
+  uint8_t *data,
+  uint32_t data_len
+)
+{
+  uint8_t key_block[128U];
+  memset(key_block, 0U, 128U * sizeof (uint8_t));
+  uint8_t *nkey = key_block;
+  uint32_t ite;
+  if (key_len <= 128U)
+  {
+    ite = key_len;
+  }
+  else
+  {
+    ite = 64U;
+  }
+  uint8_t *zeroes = key_block + ite;
+  KRML_MAYBE_UNUSED_VAR(zeroes);
+  if (key_len <= 128U)
+  {
+    memcpy(nkey, key, key_len * sizeof (uint8_t));
+  }
+  else
+  {
+    Hacl_Hash_SHA2_hash_512(nkey, key, key_len);
+  }
+  uint8_t ipad[128U];
+  memset(ipad, 0x36U, 128U * sizeof (uint8_t));
+  for (uint32_t i = 0U; i < 128U; i++)
+  {
+    uint8_t xi = ipad[i];
+    uint8_t yi = key_block[i];
+    ipad[i] = (uint32_t)xi ^ (uint32_t)yi;
+  }
+  uint8_t opad[128U];
+  memset(opad, 0x5cU, 128U * sizeof (uint8_t));
+  for (uint32_t i = 0U; i < 128U; i++)
+  {
+    uint8_t xi = opad[i];
+    uint8_t yi = key_block[i];
+    opad[i] = (uint32_t)xi ^ (uint32_t)yi;
+  }
+  uint64_t st[8U] = { 0U };
+  KRML_MAYBE_FOR8(i,
+    0U,
+    8U,
+    1U,
+    uint64_t *os = st;
+    uint64_t x = Hacl_Hash_SHA2_h512[i];
+    os[i] = x;);
+  uint64_t *s = st;
+  uint8_t *dst1 = ipad;
+  if (data_len == 0U)
+  {
+    Hacl_Hash_SHA2_sha512_update_last(FStar_UInt128_add(FStar_UInt128_uint64_to_uint128(0ULL),
+        FStar_UInt128_uint64_to_uint128((uint64_t)128U)),
+      128U,
+      ipad,
+      s);
+  }
+  else
+  {
+    uint32_t block_len = 128U;
+    uint32_t n_blocks0 = data_len / block_len;
+    uint32_t rem0 = data_len % block_len;
+    K___uint32_t_uint32_t scrut;
+    if (n_blocks0 > 0U && rem0 == 0U)
+    {
+      uint32_t n_blocks_ = n_blocks0 - 1U;
+      scrut = ((K___uint32_t_uint32_t){ .fst = n_blocks_, .snd = data_len - n_blocks_ * block_len });
+    }
+    else
+    {
+      scrut = ((K___uint32_t_uint32_t){ .fst = n_blocks0, .snd = rem0 });
+    }
+    uint32_t n_blocks = scrut.fst;
+    uint32_t rem_len = scrut.snd;
+    uint32_t full_blocks_len = n_blocks * block_len;
+    uint8_t *full_blocks = data;
+    uint8_t *rem = data + full_blocks_len;
+    Hacl_Hash_SHA2_sha512_update_nblocks(128U, ipad, s);
+    Hacl_Hash_SHA2_sha512_update_nblocks(n_blocks * 128U, full_blocks, s);
+    Hacl_Hash_SHA2_sha512_update_last(FStar_UInt128_add(FStar_UInt128_add(FStar_UInt128_uint64_to_uint128((uint64_t)128U),
+          FStar_UInt128_uint64_to_uint128((uint64_t)full_blocks_len)),
+        FStar_UInt128_uint64_to_uint128((uint64_t)rem_len)),
+      rem_len,
+      rem,
+      s);
+  }
+  Hacl_Hash_SHA2_sha512_finish(s, dst1);
+  uint8_t *hash1 = ipad;
+  Hacl_Hash_SHA2_sha512_init(s);
+  uint32_t block_len = 128U;
+  uint32_t n_blocks0 = 64U / block_len;
+  uint32_t rem0 = 64U % block_len;
+  K___uint32_t_uint32_t scrut;
+  if (n_blocks0 > 0U && rem0 == 0U)
+  {
+    uint32_t n_blocks_ = n_blocks0 - 1U;
+    scrut = ((K___uint32_t_uint32_t){ .fst = n_blocks_, .snd = 64U - n_blocks_ * block_len });
+  }
+  else
+  {
+    scrut = ((K___uint32_t_uint32_t){ .fst = n_blocks0, .snd = rem0 });
+  }
+  uint32_t n_blocks = scrut.fst;
+  uint32_t rem_len = scrut.snd;
+  uint32_t full_blocks_len = n_blocks * block_len;
+  uint8_t *full_blocks = hash1;
+  uint8_t *rem = hash1 + full_blocks_len;
+  Hacl_Hash_SHA2_sha512_update_nblocks(128U, opad, s);
+  Hacl_Hash_SHA2_sha512_update_nblocks(n_blocks * 128U, full_blocks, s);
+  Hacl_Hash_SHA2_sha512_update_last(FStar_UInt128_add(FStar_UInt128_add(FStar_UInt128_uint64_to_uint128((uint64_t)128U),
+        FStar_UInt128_uint64_to_uint128((uint64_t)full_blocks_len)),
+      FStar_UInt128_uint64_to_uint128((uint64_t)rem_len)),
+    rem_len,
+    rem,
+    s);
+  Hacl_Hash_SHA2_sha512_finish(s, dst);
+}
+
+/**
+Write the HMAC-SHA-3-224 MAC of a message (`data`) by using a key (`key`) into `dst`.
+
+The key can be any length and will be hashed if it is longer and padded if it is shorter than 144 bytes.
+`dst` must point to 28 bytes of memory.
+*/
+void
+Hacl_HMAC_compute_sha3_224(
+  uint8_t *dst,
+  uint8_t *key,
+  uint32_t key_len,
+  uint8_t *data,
+  uint32_t data_len
+)
+{
+  uint8_t key_block[144U];
+  memset(key_block, 0U, 144U * sizeof (uint8_t));
+  uint8_t *nkey = key_block;
+  uint32_t ite;
+  if (key_len <= 144U)
+  {
+    ite = key_len;
+  }
+  else
+  {
+    ite = 28U;
+  }
+  uint8_t *zeroes = key_block + ite;
+  KRML_MAYBE_UNUSED_VAR(zeroes);
+  if (key_len <= 144U)
+  {
+    memcpy(nkey, key, key_len * sizeof (uint8_t));
+  }
+  else
+  {
+    Hacl_Hash_SHA3_sha3_224(nkey, key, key_len);
+  }
+  uint8_t ipad[144U];
+  memset(ipad, 0x36U, 144U * sizeof (uint8_t));
+  for (uint32_t i = 0U; i < 144U; i++)
+  {
+    uint8_t xi = ipad[i];
+    uint8_t yi = key_block[i];
+    ipad[i] = (uint32_t)xi ^ (uint32_t)yi;
+  }
+  uint8_t opad[144U];
+  memset(opad, 0x5cU, 144U * sizeof (uint8_t));
+  for (uint32_t i = 0U; i < 144U; i++)
+  {
+    uint8_t xi = opad[i];
+    uint8_t yi = key_block[i];
+    opad[i] = (uint32_t)xi ^ (uint32_t)yi;
+  }
+  uint64_t s[25U] = { 0U };
+  uint8_t *dst1 = ipad;
+  if (data_len == 0U)
+  {
+    Hacl_Hash_SHA3_update_last_sha3(Spec_Hash_Definitions_SHA3_224, s, ipad, 144U);
+  }
+  else
+  {
+    uint32_t block_len = 144U;
+    uint32_t n_blocks0 = data_len / block_len;
+    uint32_t rem0 = data_len % block_len;
+    K___uint32_t_uint32_t scrut;
+    if (n_blocks0 > 0U && rem0 == 0U)
+    {
+      uint32_t n_blocks_ = n_blocks0 - 1U;
+      scrut = ((K___uint32_t_uint32_t){ .fst = n_blocks_, .snd = data_len - n_blocks_ * block_len });
+    }
+    else
+    {
+      scrut = ((K___uint32_t_uint32_t){ .fst = n_blocks0, .snd = rem0 });
+    }
+    uint32_t n_blocks = scrut.fst;
+    uint32_t rem_len = scrut.snd;
+    uint32_t full_blocks_len = n_blocks * block_len;
+    uint8_t *full_blocks = data;
+    uint8_t *rem = data + full_blocks_len;
+    Hacl_Hash_SHA3_update_multi_sha3(Spec_Hash_Definitions_SHA3_224, s, ipad, 1U);
+    Hacl_Hash_SHA3_update_multi_sha3(Spec_Hash_Definitions_SHA3_224, s, full_blocks, n_blocks);
+    Hacl_Hash_SHA3_update_last_sha3(Spec_Hash_Definitions_SHA3_224, s, rem, rem_len);
+  }
+  uint32_t remOut = 28U;
+  uint8_t hbuf0[256U] = { 0U };
+  uint64_t ws0[32U] = { 0U };
+  memcpy(ws0, s, 25U * sizeof (uint64_t));
+  for (uint32_t i = 0U; i < 32U; i++)
+  {
+    store64_le(hbuf0 + i * 8U, ws0[i]);
+  }
+  memcpy(dst1 + 28U - remOut, hbuf0, remOut * sizeof (uint8_t));
+  uint8_t *hash1 = ipad;
+  Hacl_Hash_SHA3_init_(Spec_Hash_Definitions_SHA3_224, s);
+  uint32_t block_len = 144U;
+  uint32_t n_blocks0 = 28U / block_len;
+  uint32_t rem0 = 28U % block_len;
+  K___uint32_t_uint32_t scrut;
+  if (n_blocks0 > 0U && rem0 == 0U)
+  {
+    uint32_t n_blocks_ = n_blocks0 - 1U;
+    scrut = ((K___uint32_t_uint32_t){ .fst = n_blocks_, .snd = 28U - n_blocks_ * block_len });
+  }
+  else
+  {
+    scrut = ((K___uint32_t_uint32_t){ .fst = n_blocks0, .snd = rem0 });
+  }
+  uint32_t n_blocks = scrut.fst;
+  uint32_t rem_len = scrut.snd;
+  uint32_t full_blocks_len = n_blocks * block_len;
+  uint8_t *full_blocks = hash1;
+  uint8_t *rem = hash1 + full_blocks_len;
+  Hacl_Hash_SHA3_update_multi_sha3(Spec_Hash_Definitions_SHA3_224, s, opad, 1U);
+  Hacl_Hash_SHA3_update_multi_sha3(Spec_Hash_Definitions_SHA3_224, s, full_blocks, n_blocks);
+  Hacl_Hash_SHA3_update_last_sha3(Spec_Hash_Definitions_SHA3_224, s, rem, rem_len);
+  uint32_t remOut0 = 28U;
+  uint8_t hbuf[256U] = { 0U };
+  uint64_t ws[32U] = { 0U };
+  memcpy(ws, s, 25U * sizeof (uint64_t));
+  for (uint32_t i = 0U; i < 32U; i++)
+  {
+    store64_le(hbuf + i * 8U, ws[i]);
+  }
+  memcpy(dst + 28U - remOut0, hbuf, remOut0 * sizeof (uint8_t));
+}
+
+/**
+Write the HMAC-SHA-3-256 MAC of a message (`data`) by using a key (`key`) into `dst`.
+
+The key can be any length and will be hashed if it is longer and padded if it is shorter than 136 bytes.
+`dst` must point to 32 bytes of memory.
+*/
+void
+Hacl_HMAC_compute_sha3_256(
+  uint8_t *dst,
+  uint8_t *key,
+  uint32_t key_len,
+  uint8_t *data,
+  uint32_t data_len
+)
+{
+  uint8_t key_block[136U];
+  memset(key_block, 0U, 136U * sizeof (uint8_t));
+  uint8_t *nkey = key_block;
+  uint32_t ite;
+  if (key_len <= 136U)
+  {
+    ite = key_len;
+  }
+  else
+  {
+    ite = 32U;
+  }
+  uint8_t *zeroes = key_block + ite;
+  KRML_MAYBE_UNUSED_VAR(zeroes);
+  if (key_len <= 136U)
+  {
+    memcpy(nkey, key, key_len * sizeof (uint8_t));
+  }
+  else
+  {
+    Hacl_Hash_SHA3_sha3_256(nkey, key, key_len);
+  }
+  uint8_t ipad[136U];
+  memset(ipad, 0x36U, 136U * sizeof (uint8_t));
+  for (uint32_t i = 0U; i < 136U; i++)
+  {
+    uint8_t xi = ipad[i];
+    uint8_t yi = key_block[i];
+    ipad[i] = (uint32_t)xi ^ (uint32_t)yi;
+  }
+  uint8_t opad[136U];
+  memset(opad, 0x5cU, 136U * sizeof (uint8_t));
+  for (uint32_t i = 0U; i < 136U; i++)
+  {
+    uint8_t xi = opad[i];
+    uint8_t yi = key_block[i];
+    opad[i] = (uint32_t)xi ^ (uint32_t)yi;
+  }
+  uint64_t s[25U] = { 0U };
+  uint8_t *dst1 = ipad;
+  if (data_len == 0U)
+  {
+    Hacl_Hash_SHA3_update_last_sha3(Spec_Hash_Definitions_SHA3_256, s, ipad, 136U);
+  }
+  else
+  {
+    uint32_t block_len = 136U;
+    uint32_t n_blocks0 = data_len / block_len;
+    uint32_t rem0 = data_len % block_len;
+    K___uint32_t_uint32_t scrut;
+    if (n_blocks0 > 0U && rem0 == 0U)
+    {
+      uint32_t n_blocks_ = n_blocks0 - 1U;
+      scrut = ((K___uint32_t_uint32_t){ .fst = n_blocks_, .snd = data_len - n_blocks_ * block_len });
+    }
+    else
+    {
+      scrut = ((K___uint32_t_uint32_t){ .fst = n_blocks0, .snd = rem0 });
+    }
+    uint32_t n_blocks = scrut.fst;
+    uint32_t rem_len = scrut.snd;
+    uint32_t full_blocks_len = n_blocks * block_len;
+    uint8_t *full_blocks = data;
+    uint8_t *rem = data + full_blocks_len;
+    Hacl_Hash_SHA3_update_multi_sha3(Spec_Hash_Definitions_SHA3_256, s, ipad, 1U);
+    Hacl_Hash_SHA3_update_multi_sha3(Spec_Hash_Definitions_SHA3_256, s, full_blocks, n_blocks);
+    Hacl_Hash_SHA3_update_last_sha3(Spec_Hash_Definitions_SHA3_256, s, rem, rem_len);
+  }
+  uint32_t remOut = 32U;
+  uint8_t hbuf0[256U] = { 0U };
+  uint64_t ws0[32U] = { 0U };
+  memcpy(ws0, s, 25U * sizeof (uint64_t));
+  for (uint32_t i = 0U; i < 32U; i++)
+  {
+    store64_le(hbuf0 + i * 8U, ws0[i]);
+  }
+  memcpy(dst1 + 32U - remOut, hbuf0, remOut * sizeof (uint8_t));
+  uint8_t *hash1 = ipad;
+  Hacl_Hash_SHA3_init_(Spec_Hash_Definitions_SHA3_256, s);
+  uint32_t block_len = 136U;
+  uint32_t n_blocks0 = 32U / block_len;
+  uint32_t rem0 = 32U % block_len;
+  K___uint32_t_uint32_t scrut;
+  if (n_blocks0 > 0U && rem0 == 0U)
+  {
+    uint32_t n_blocks_ = n_blocks0 - 1U;
+    scrut = ((K___uint32_t_uint32_t){ .fst = n_blocks_, .snd = 32U - n_blocks_ * block_len });
+  }
+  else
+  {
+    scrut = ((K___uint32_t_uint32_t){ .fst = n_blocks0, .snd = rem0 });
+  }
+  uint32_t n_blocks = scrut.fst;
+  uint32_t rem_len = scrut.snd;
+  uint32_t full_blocks_len = n_blocks * block_len;
+  uint8_t *full_blocks = hash1;
+  uint8_t *rem = hash1 + full_blocks_len;
+  Hacl_Hash_SHA3_update_multi_sha3(Spec_Hash_Definitions_SHA3_256, s, opad, 1U);
+  Hacl_Hash_SHA3_update_multi_sha3(Spec_Hash_Definitions_SHA3_256, s, full_blocks, n_blocks);
+  Hacl_Hash_SHA3_update_last_sha3(Spec_Hash_Definitions_SHA3_256, s, rem, rem_len);
+  uint32_t remOut0 = 32U;
+  uint8_t hbuf[256U] = { 0U };
+  uint64_t ws[32U] = { 0U };
+  memcpy(ws, s, 25U * sizeof (uint64_t));
+  for (uint32_t i = 0U; i < 32U; i++)
+  {
+    store64_le(hbuf + i * 8U, ws[i]);
+  }
+  memcpy(dst + 32U - remOut0, hbuf, remOut0 * sizeof (uint8_t));
+}
+
+/**
+Write the HMAC-SHA-3-384 MAC of a message (`data`) by using a key (`key`) into `dst`.
+
+The key can be any length and will be hashed if it is longer and padded if it is shorter than 104 bytes.
+`dst` must point to 48 bytes of memory.
+*/
+void
+Hacl_HMAC_compute_sha3_384(
+  uint8_t *dst,
+  uint8_t *key,
+  uint32_t key_len,
+  uint8_t *data,
+  uint32_t data_len
+)
+{
+  uint8_t key_block[104U];
+  memset(key_block, 0U, 104U * sizeof (uint8_t));
+  uint8_t *nkey = key_block;
+  uint32_t ite;
+  if (key_len <= 104U)
+  {
+    ite = key_len;
+  }
+  else
+  {
+    ite = 48U;
+  }
+  uint8_t *zeroes = key_block + ite;
+  KRML_MAYBE_UNUSED_VAR(zeroes);
+  if (key_len <= 104U)
+  {
+    memcpy(nkey, key, key_len * sizeof (uint8_t));
+  }
+  else
+  {
+    Hacl_Hash_SHA3_sha3_384(nkey, key, key_len);
+  }
+  uint8_t ipad[104U];
+  memset(ipad, 0x36U, 104U * sizeof (uint8_t));
+  for (uint32_t i = 0U; i < 104U; i++)
+  {
+    uint8_t xi = ipad[i];
+    uint8_t yi = key_block[i];
+    ipad[i] = (uint32_t)xi ^ (uint32_t)yi;
+  }
+  uint8_t opad[104U];
+  memset(opad, 0x5cU, 104U * sizeof (uint8_t));
+  for (uint32_t i = 0U; i < 104U; i++)
+  {
+    uint8_t xi = opad[i];
+    uint8_t yi = key_block[i];
+    opad[i] = (uint32_t)xi ^ (uint32_t)yi;
+  }
+  uint64_t s[25U] = { 0U };
+  uint8_t *dst1 = ipad;
+  if (data_len == 0U)
+  {
+    Hacl_Hash_SHA3_update_last_sha3(Spec_Hash_Definitions_SHA3_384, s, ipad, 104U);
+  }
+  else
+  {
+    uint32_t block_len = 104U;
+    uint32_t n_blocks0 = data_len / block_len;
+    uint32_t rem0 = data_len % block_len;
+    K___uint32_t_uint32_t scrut;
+    if (n_blocks0 > 0U && rem0 == 0U)
+    {
+      uint32_t n_blocks_ = n_blocks0 - 1U;
+      scrut = ((K___uint32_t_uint32_t){ .fst = n_blocks_, .snd = data_len - n_blocks_ * block_len });
+    }
+    else
+    {
+      scrut = ((K___uint32_t_uint32_t){ .fst = n_blocks0, .snd = rem0 });
+    }
+    uint32_t n_blocks = scrut.fst;
+    uint32_t rem_len = scrut.snd;
+    uint32_t full_blocks_len = n_blocks * block_len;
+    uint8_t *full_blocks = data;
+    uint8_t *rem = data + full_blocks_len;
+    Hacl_Hash_SHA3_update_multi_sha3(Spec_Hash_Definitions_SHA3_384, s, ipad, 1U);
+    Hacl_Hash_SHA3_update_multi_sha3(Spec_Hash_Definitions_SHA3_384, s, full_blocks, n_blocks);
+    Hacl_Hash_SHA3_update_last_sha3(Spec_Hash_Definitions_SHA3_384, s, rem, rem_len);
+  }
+  uint32_t remOut = 48U;
+  uint8_t hbuf0[256U] = { 0U };
+  uint64_t ws0[32U] = { 0U };
+  memcpy(ws0, s, 25U * sizeof (uint64_t));
+  for (uint32_t i = 0U; i < 32U; i++)
+  {
+    store64_le(hbuf0 + i * 8U, ws0[i]);
+  }
+  memcpy(dst1 + 48U - remOut, hbuf0, remOut * sizeof (uint8_t));
+  uint8_t *hash1 = ipad;
+  Hacl_Hash_SHA3_init_(Spec_Hash_Definitions_SHA3_384, s);
+  uint32_t block_len = 104U;
+  uint32_t n_blocks0 = 48U / block_len;
+  uint32_t rem0 = 48U % block_len;
+  K___uint32_t_uint32_t scrut;
+  if (n_blocks0 > 0U && rem0 == 0U)
+  {
+    uint32_t n_blocks_ = n_blocks0 - 1U;
+    scrut = ((K___uint32_t_uint32_t){ .fst = n_blocks_, .snd = 48U - n_blocks_ * block_len });
+  }
+  else
+  {
+    scrut = ((K___uint32_t_uint32_t){ .fst = n_blocks0, .snd = rem0 });
+  }
+  uint32_t n_blocks = scrut.fst;
+  uint32_t rem_len = scrut.snd;
+  uint32_t full_blocks_len = n_blocks * block_len;
+  uint8_t *full_blocks = hash1;
+  uint8_t *rem = hash1 + full_blocks_len;
+  Hacl_Hash_SHA3_update_multi_sha3(Spec_Hash_Definitions_SHA3_384, s, opad, 1U);
+  Hacl_Hash_SHA3_update_multi_sha3(Spec_Hash_Definitions_SHA3_384, s, full_blocks, n_blocks);
+  Hacl_Hash_SHA3_update_last_sha3(Spec_Hash_Definitions_SHA3_384, s, rem, rem_len);
+  uint32_t remOut0 = 48U;
+  uint8_t hbuf[256U] = { 0U };
+  uint64_t ws[32U] = { 0U };
+  memcpy(ws, s, 25U * sizeof (uint64_t));
+  for (uint32_t i = 0U; i < 32U; i++)
+  {
+    store64_le(hbuf + i * 8U, ws[i]);
+  }
+  memcpy(dst + 48U - remOut0, hbuf, remOut0 * sizeof (uint8_t));
+}
+
+/**
+Write the HMAC-SHA-3-512 MAC of a message (`data`) by using a key (`key`) into `dst`.
+
+The key can be any length and will be hashed if it is longer and padded if it is shorter than 72 bytes.
+`dst` must point to 64 bytes of memory.
+*/
+void
+Hacl_HMAC_compute_sha3_512(
+  uint8_t *dst,
+  uint8_t *key,
+  uint32_t key_len,
+  uint8_t *data,
+  uint32_t data_len
+)
+{
+  uint8_t key_block[72U];
+  memset(key_block, 0U, 72U * sizeof (uint8_t));
+  uint8_t *nkey = key_block;
+  uint32_t ite;
+  if (key_len <= 72U)
+  {
+    ite = key_len;
+  }
+  else
+  {
+    ite = 64U;
+  }
+  uint8_t *zeroes = key_block + ite;
+  KRML_MAYBE_UNUSED_VAR(zeroes);
+  if (key_len <= 72U)
+  {
+    memcpy(nkey, key, key_len * sizeof (uint8_t));
+  }
+  else
+  {
+    Hacl_Hash_SHA3_sha3_512(nkey, key, key_len);
+  }
+  uint8_t ipad[72U];
+  memset(ipad, 0x36U, 72U * sizeof (uint8_t));
+  for (uint32_t i = 0U; i < 72U; i++)
+  {
+    uint8_t xi = ipad[i];
+    uint8_t yi = key_block[i];
+    ipad[i] = (uint32_t)xi ^ (uint32_t)yi;
+  }
+  uint8_t opad[72U];
+  memset(opad, 0x5cU, 72U * sizeof (uint8_t));
+  for (uint32_t i = 0U; i < 72U; i++)
+  {
+    uint8_t xi = opad[i];
+    uint8_t yi = key_block[i];
+    opad[i] = (uint32_t)xi ^ (uint32_t)yi;
+  }
+  uint64_t s[25U] = { 0U };
+  uint8_t *dst1 = ipad;
+  if (data_len == 0U)
+  {
+    Hacl_Hash_SHA3_update_last_sha3(Spec_Hash_Definitions_SHA3_512, s, ipad, 72U);
+  }
+  else
+  {
+    uint32_t block_len = 72U;
+    uint32_t n_blocks0 = data_len / block_len;
+    uint32_t rem0 = data_len % block_len;
+    K___uint32_t_uint32_t scrut;
+    if (n_blocks0 > 0U && rem0 == 0U)
+    {
+      uint32_t n_blocks_ = n_blocks0 - 1U;
+      scrut = ((K___uint32_t_uint32_t){ .fst = n_blocks_, .snd = data_len - n_blocks_ * block_len });
+    }
+    else
+    {
+      scrut = ((K___uint32_t_uint32_t){ .fst = n_blocks0, .snd = rem0 });
+    }
+    uint32_t n_blocks = scrut.fst;
+    uint32_t rem_len = scrut.snd;
+    uint32_t full_blocks_len = n_blocks * block_len;
+    uint8_t *full_blocks = data;
+    uint8_t *rem = data + full_blocks_len;
+    Hacl_Hash_SHA3_update_multi_sha3(Spec_Hash_Definitions_SHA3_512, s, ipad, 1U);
+    Hacl_Hash_SHA3_update_multi_sha3(Spec_Hash_Definitions_SHA3_512, s, full_blocks, n_blocks);
+    Hacl_Hash_SHA3_update_last_sha3(Spec_Hash_Definitions_SHA3_512, s, rem, rem_len);
+  }
+  uint32_t remOut = 64U;
+  uint8_t hbuf0[256U] = { 0U };
+  uint64_t ws0[32U] = { 0U };
+  memcpy(ws0, s, 25U * sizeof (uint64_t));
+  for (uint32_t i = 0U; i < 32U; i++)
+  {
+    store64_le(hbuf0 + i * 8U, ws0[i]);
+  }
+  memcpy(dst1 + 64U - remOut, hbuf0, remOut * sizeof (uint8_t));
+  uint8_t *hash1 = ipad;
+  Hacl_Hash_SHA3_init_(Spec_Hash_Definitions_SHA3_512, s);
+  uint32_t block_len = 72U;
+  uint32_t n_blocks0 = 64U / block_len;
+  uint32_t rem0 = 64U % block_len;
+  K___uint32_t_uint32_t scrut;
+  if (n_blocks0 > 0U && rem0 == 0U)
+  {
+    uint32_t n_blocks_ = n_blocks0 - 1U;
+    scrut = ((K___uint32_t_uint32_t){ .fst = n_blocks_, .snd = 64U - n_blocks_ * block_len });
+  }
+  else
+  {
+    scrut = ((K___uint32_t_uint32_t){ .fst = n_blocks0, .snd = rem0 });
+  }
+  uint32_t n_blocks = scrut.fst;
+  uint32_t rem_len = scrut.snd;
+  uint32_t full_blocks_len = n_blocks * block_len;
+  uint8_t *full_blocks = hash1;
+  uint8_t *rem = hash1 + full_blocks_len;
+  Hacl_Hash_SHA3_update_multi_sha3(Spec_Hash_Definitions_SHA3_512, s, opad, 1U);
+  Hacl_Hash_SHA3_update_multi_sha3(Spec_Hash_Definitions_SHA3_512, s, full_blocks, n_blocks);
+  Hacl_Hash_SHA3_update_last_sha3(Spec_Hash_Definitions_SHA3_512, s, rem, rem_len);
+  uint32_t remOut0 = 64U;
+  uint8_t hbuf[256U] = { 0U };
+  uint64_t ws[32U] = { 0U };
+  memcpy(ws, s, 25U * sizeof (uint64_t));
+  for (uint32_t i = 0U; i < 32U; i++)
+  {
+    store64_le(hbuf + i * 8U, ws[i]);
+  }
+  memcpy(dst + 64U - remOut0, hbuf, remOut0 * sizeof (uint8_t));
+}
+
+/**
+Write the HMAC-BLAKE2s MAC of a message (`data`) by using a key (`key`) into `dst`.
+
+The key can be any length and will be hashed if it is longer and padded if it is shorter than 64 bytes.
+`dst` must point to 32 bytes of memory.
+*/
+void
+Hacl_HMAC_compute_blake2s_32(
+  uint8_t *dst,
+  uint8_t *key,
+  uint32_t key_len,
+  uint8_t *data,
+  uint32_t data_len
+)
+{
+  uint8_t key_block[64U];
+  memset(key_block, 0U, 64U * sizeof (uint8_t));
+  uint8_t *nkey = key_block;
+  uint32_t ite;
+  if (key_len <= 64U)
+  {
+    ite = key_len;
+  }
+  else
+  {
+    ite = 32U;
+  }
+  uint8_t *zeroes = key_block + ite;
+  KRML_MAYBE_UNUSED_VAR(zeroes);
+  if (key_len <= 64U)
+  {
+    memcpy(nkey, key, key_len * sizeof (uint8_t));
+  }
+  else
+  {
+    Hacl_Hash_Blake2s_hash_with_key(nkey, 32U, key, key_len, NULL, 0U);
+  }
+  uint8_t ipad[64U];
+  memset(ipad, 0x36U, 64U * sizeof (uint8_t));
+  for (uint32_t i = 0U; i < 64U; i++)
+  {
+    uint8_t xi = ipad[i];
+    uint8_t yi = key_block[i];
+    ipad[i] = (uint32_t)xi ^ (uint32_t)yi;
+  }
+  uint8_t opad[64U];
+  memset(opad, 0x5cU, 64U * sizeof (uint8_t));
+  for (uint32_t i = 0U; i < 64U; i++)
+  {
+    uint8_t xi = opad[i];
+    uint8_t yi = key_block[i];
+    opad[i] = (uint32_t)xi ^ (uint32_t)yi;
+  }
+  uint32_t s[16U] = { 0U };
+  Hacl_Hash_Blake2s_init(s, 0U, 32U);
+  uint32_t *s0 = s;
+  uint8_t *dst1 = ipad;
+  if (data_len == 0U)
+  {
+    uint32_t wv[16U] = { 0U };
+    Hacl_Hash_Blake2s_update_last(64U, wv, s0, false, 0ULL, 64U, ipad);
+  }
+  else
+  {
+    uint32_t block_len = 64U;
+    uint32_t n_blocks0 = data_len / block_len;
+    uint32_t rem0 = data_len % block_len;
+    K___uint32_t_uint32_t scrut;
+    if (n_blocks0 > 0U && rem0 == 0U)
+    {
+      uint32_t n_blocks_ = n_blocks0 - 1U;
+      scrut = ((K___uint32_t_uint32_t){ .fst = n_blocks_, .snd = data_len - n_blocks_ * block_len });
+    }
+    else
+    {
+      scrut = ((K___uint32_t_uint32_t){ .fst = n_blocks0, .snd = rem0 });
+    }
+    uint32_t n_blocks = scrut.fst;
+    uint32_t rem_len = scrut.snd;
+    uint32_t full_blocks_len = n_blocks * block_len;
+    uint8_t *full_blocks = data;
+    uint8_t *rem = data + full_blocks_len;
+    uint32_t wv[16U] = { 0U };
+    Hacl_Hash_Blake2s_update_multi(64U, wv, s0, 0ULL, ipad, 1U);
+    uint32_t wv0[16U] = { 0U };
+    Hacl_Hash_Blake2s_update_multi(n_blocks * 64U,
+      wv0,
+      s0,
+      (uint64_t)block_len,
+      full_blocks,
+      n_blocks);
+    uint32_t wv1[16U] = { 0U };
+    Hacl_Hash_Blake2s_update_last(rem_len,
+      wv1,
+      s0,
+      false,
+      (uint64_t)64U + (uint64_t)full_blocks_len,
+      rem_len,
+      rem);
+  }
+  Hacl_Hash_Blake2s_finish(32U, dst1, s0);
+  uint8_t *hash1 = ipad;
+  Hacl_Hash_Blake2s_init(s0, 0U, 32U);
+  uint32_t block_len = 64U;
+  uint32_t n_blocks0 = 32U / block_len;
+  uint32_t rem0 = 32U % block_len;
+  K___uint32_t_uint32_t scrut;
+  if (n_blocks0 > 0U && rem0 == 0U)
+  {
+    uint32_t n_blocks_ = n_blocks0 - 1U;
+    scrut = ((K___uint32_t_uint32_t){ .fst = n_blocks_, .snd = 32U - n_blocks_ * block_len });
+  }
+  else
+  {
+    scrut = ((K___uint32_t_uint32_t){ .fst = n_blocks0, .snd = rem0 });
+  }
+  uint32_t n_blocks = scrut.fst;
+  uint32_t rem_len = scrut.snd;
+  uint32_t full_blocks_len = n_blocks * block_len;
+  uint8_t *full_blocks = hash1;
+  uint8_t *rem = hash1 + full_blocks_len;
+  uint32_t wv[16U] = { 0U };
+  Hacl_Hash_Blake2s_update_multi(64U, wv, s0, 0ULL, opad, 1U);
+  uint32_t wv0[16U] = { 0U };
+  Hacl_Hash_Blake2s_update_multi(n_blocks * 64U,
+    wv0,
+    s0,
+    (uint64_t)block_len,
+    full_blocks,
+    n_blocks);
+  uint32_t wv1[16U] = { 0U };
+  Hacl_Hash_Blake2s_update_last(rem_len,
+    wv1,
+    s0,
+    false,
+    (uint64_t)64U + (uint64_t)full_blocks_len,
+    rem_len,
+    rem);
+  Hacl_Hash_Blake2s_finish(32U, dst, s0);
+}
+
+/**
+Write the HMAC-BLAKE2b MAC of a message (`data`) by using a key (`key`) into `dst`.
+
+The key can be any length and will be hashed if it is longer and padded if it is shorter than 128 bytes.
+`dst` must point to 64 bytes of memory.
+*/
+void
+Hacl_HMAC_compute_blake2b_32(
+  uint8_t *dst,
+  uint8_t *key,
+  uint32_t key_len,
+  uint8_t *data,
+  uint32_t data_len
+)
+{
+  uint8_t key_block[128U];
+  memset(key_block, 0U, 128U * sizeof (uint8_t));
+  uint8_t *nkey = key_block;
+  uint32_t ite;
+  if (key_len <= 128U)
+  {
+    ite = key_len;
+  }
+  else
+  {
+    ite = 64U;
+  }
+  uint8_t *zeroes = key_block + ite;
+  KRML_MAYBE_UNUSED_VAR(zeroes);
+  if (key_len <= 128U)
+  {
+    memcpy(nkey, key, key_len * sizeof (uint8_t));
+  }
+  else
+  {
+    Hacl_Hash_Blake2b_hash_with_key(nkey, 64U, key, key_len, NULL, 0U);
+  }
+  uint8_t ipad[128U];
+  memset(ipad, 0x36U, 128U * sizeof (uint8_t));
+  for (uint32_t i = 0U; i < 128U; i++)
+  {
+    uint8_t xi = ipad[i];
+    uint8_t yi = key_block[i];
+    ipad[i] = (uint32_t)xi ^ (uint32_t)yi;
+  }
+  uint8_t opad[128U];
+  memset(opad, 0x5cU, 128U * sizeof (uint8_t));
+  for (uint32_t i = 0U; i < 128U; i++)
+  {
+    uint8_t xi = opad[i];
+    uint8_t yi = key_block[i];
+    opad[i] = (uint32_t)xi ^ (uint32_t)yi;
+  }
+  uint64_t s[16U] = { 0U };
+  Hacl_Hash_Blake2b_init(s, 0U, 64U);
+  uint64_t *s0 = s;
+  uint8_t *dst1 = ipad;
+  if (data_len == 0U)
+  {
+    uint64_t wv[16U] = { 0U };
+    Hacl_Hash_Blake2b_update_last(128U,
+      wv,
+      s0,
+      false,
+      FStar_UInt128_uint64_to_uint128(0ULL),
+      128U,
+      ipad);
+  }
+  else
+  {
+    uint32_t block_len = 128U;
+    uint32_t n_blocks0 = data_len / block_len;
+    uint32_t rem0 = data_len % block_len;
+    K___uint32_t_uint32_t scrut;
+    if (n_blocks0 > 0U && rem0 == 0U)
+    {
+      uint32_t n_blocks_ = n_blocks0 - 1U;
+      scrut = ((K___uint32_t_uint32_t){ .fst = n_blocks_, .snd = data_len - n_blocks_ * block_len });
+    }
+    else
+    {
+      scrut = ((K___uint32_t_uint32_t){ .fst = n_blocks0, .snd = rem0 });
+    }
+    uint32_t n_blocks = scrut.fst;
+    uint32_t rem_len = scrut.snd;
+    uint32_t full_blocks_len = n_blocks * block_len;
+    uint8_t *full_blocks = data;
+    uint8_t *rem = data + full_blocks_len;
+    uint64_t wv[16U] = { 0U };
+    Hacl_Hash_Blake2b_update_multi(128U, wv, s0, FStar_UInt128_uint64_to_uint128(0ULL), ipad, 1U);
+    uint64_t wv0[16U] = { 0U };
+    Hacl_Hash_Blake2b_update_multi(n_blocks * 128U,
+      wv0,
+      s0,
+      FStar_UInt128_uint64_to_uint128((uint64_t)block_len),
+      full_blocks,
+      n_blocks);
+    uint64_t wv1[16U] = { 0U };
+    Hacl_Hash_Blake2b_update_last(rem_len,
+      wv1,
+      s0,
+      false,
+      FStar_UInt128_add(FStar_UInt128_uint64_to_uint128((uint64_t)128U),
+        FStar_UInt128_uint64_to_uint128((uint64_t)full_blocks_len)),
+      rem_len,
+      rem);
+  }
+  Hacl_Hash_Blake2b_finish(64U, dst1, s0);
+  uint8_t *hash1 = ipad;
+  Hacl_Hash_Blake2b_init(s0, 0U, 64U);
+  uint32_t block_len = 128U;
+  uint32_t n_blocks0 = 64U / block_len;
+  uint32_t rem0 = 64U % block_len;
+  K___uint32_t_uint32_t scrut;
+  if (n_blocks0 > 0U && rem0 == 0U)
+  {
+    uint32_t n_blocks_ = n_blocks0 - 1U;
+    scrut = ((K___uint32_t_uint32_t){ .fst = n_blocks_, .snd = 64U - n_blocks_ * block_len });
+  }
+  else
+  {
+    scrut = ((K___uint32_t_uint32_t){ .fst = n_blocks0, .snd = rem0 });
+  }
+  uint32_t n_blocks = scrut.fst;
+  uint32_t rem_len = scrut.snd;
+  uint32_t full_blocks_len = n_blocks * block_len;
+  uint8_t *full_blocks = hash1;
+  uint8_t *rem = hash1 + full_blocks_len;
+  uint64_t wv[16U] = { 0U };
+  Hacl_Hash_Blake2b_update_multi(128U, wv, s0, FStar_UInt128_uint64_to_uint128(0ULL), opad, 1U);
+  uint64_t wv0[16U] = { 0U };
+  Hacl_Hash_Blake2b_update_multi(n_blocks * 128U,
+    wv0,
+    s0,
+    FStar_UInt128_uint64_to_uint128((uint64_t)block_len),
+    full_blocks,
+    n_blocks);
+  uint64_t wv1[16U] = { 0U };
+  Hacl_Hash_Blake2b_update_last(rem_len,
+    wv1,
+    s0,
+    false,
+    FStar_UInt128_add(FStar_UInt128_uint64_to_uint128((uint64_t)128U),
+      FStar_UInt128_uint64_to_uint128((uint64_t)full_blocks_len)),
+    rem_len,
+    rem);
+  Hacl_Hash_Blake2b_finish(64U, dst, s0);
+}
+
diff --git a/Modules/_hacl/Hacl_HMAC.h b/Modules/_hacl/Hacl_HMAC.h
new file mode 100644 (file)
index 0000000..10ff151
--- /dev/null
@@ -0,0 +1,224 @@
+/* MIT License
+ *
+ * Copyright (c) 2016-2022 INRIA, CMU and Microsoft Corporation
+ * Copyright (c) 2022-2023 HACL* Contributors
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+
+#ifndef __Hacl_HMAC_H
+#define __Hacl_HMAC_H
+
+#if defined(__cplusplus)
+extern "C" {
+#endif
+
+#include <string.h>
+#include "python_hacl_namespaces.h"
+#include "krml/internal/types.h"
+#include "krml/lowstar_endianness.h"
+#include "krml/internal/target.h"
+
+/**
+Write the HMAC-MD5 MAC of a message (`data`) by using a key (`key`) into `dst`.
+
+The key can be any length and will be hashed if it is longer and padded if it is shorter than 64 byte.
+`dst` must point to 16 bytes of memory.
+*/
+void
+Hacl_HMAC_compute_md5(
+  uint8_t *dst,
+  uint8_t *key,
+  uint32_t key_len,
+  uint8_t *data,
+  uint32_t data_len
+);
+
+/**
+Write the HMAC-SHA-1 MAC of a message (`data`) by using a key (`key`) into `dst`.
+
+The key can be any length and will be hashed if it is longer and padded if it is shorter than 64 byte.
+`dst` must point to 20 bytes of memory.
+*/
+void
+Hacl_HMAC_compute_sha1(
+  uint8_t *dst,
+  uint8_t *key,
+  uint32_t key_len,
+  uint8_t *data,
+  uint32_t data_len
+);
+
+/**
+Write the HMAC-SHA-2-224 MAC of a message (`data`) by using a key (`key`) into `dst`.
+
+The key can be any length and will be hashed if it is longer and padded if it is shorter than 64 bytes.
+`dst` must point to 28 bytes of memory.
+*/
+void
+Hacl_HMAC_compute_sha2_224(
+  uint8_t *dst,
+  uint8_t *key,
+  uint32_t key_len,
+  uint8_t *data,
+  uint32_t data_len
+);
+
+/**
+Write the HMAC-SHA-2-256 MAC of a message (`data`) by using a key (`key`) into `dst`.
+
+The key can be any length and will be hashed if it is longer and padded if it is shorter than 64 bytes.
+`dst` must point to 32 bytes of memory.
+*/
+void
+Hacl_HMAC_compute_sha2_256(
+  uint8_t *dst,
+  uint8_t *key,
+  uint32_t key_len,
+  uint8_t *data,
+  uint32_t data_len
+);
+
+/**
+Write the HMAC-SHA-2-384 MAC of a message (`data`) by using a key (`key`) into `dst`.
+
+The key can be any length and will be hashed if it is longer and padded if it is shorter than 128 bytes.
+`dst` must point to 48 bytes of memory.
+*/
+void
+Hacl_HMAC_compute_sha2_384(
+  uint8_t *dst,
+  uint8_t *key,
+  uint32_t key_len,
+  uint8_t *data,
+  uint32_t data_len
+);
+
+/**
+Write the HMAC-SHA-2-512 MAC of a message (`data`) by using a key (`key`) into `dst`.
+
+The key can be any length and will be hashed if it is longer and padded if it is shorter than 128 bytes.
+`dst` must point to 64 bytes of memory.
+*/
+void
+Hacl_HMAC_compute_sha2_512(
+  uint8_t *dst,
+  uint8_t *key,
+  uint32_t key_len,
+  uint8_t *data,
+  uint32_t data_len
+);
+
+/**
+Write the HMAC-SHA-3-224 MAC of a message (`data`) by using a key (`key`) into `dst`.
+
+The key can be any length and will be hashed if it is longer and padded if it is shorter than 144 bytes.
+`dst` must point to 28 bytes of memory.
+*/
+void
+Hacl_HMAC_compute_sha3_224(
+  uint8_t *dst,
+  uint8_t *key,
+  uint32_t key_len,
+  uint8_t *data,
+  uint32_t data_len
+);
+
+/**
+Write the HMAC-SHA-3-256 MAC of a message (`data`) by using a key (`key`) into `dst`.
+
+The key can be any length and will be hashed if it is longer and padded if it is shorter than 136 bytes.
+`dst` must point to 32 bytes of memory.
+*/
+void
+Hacl_HMAC_compute_sha3_256(
+  uint8_t *dst,
+  uint8_t *key,
+  uint32_t key_len,
+  uint8_t *data,
+  uint32_t data_len
+);
+
+/**
+Write the HMAC-SHA-3-384 MAC of a message (`data`) by using a key (`key`) into `dst`.
+
+The key can be any length and will be hashed if it is longer and padded if it is shorter than 104 bytes.
+`dst` must point to 48 bytes of memory.
+*/
+void
+Hacl_HMAC_compute_sha3_384(
+  uint8_t *dst,
+  uint8_t *key,
+  uint32_t key_len,
+  uint8_t *data,
+  uint32_t data_len
+);
+
+/**
+Write the HMAC-SHA-3-512 MAC of a message (`data`) by using a key (`key`) into `dst`.
+
+The key can be any length and will be hashed if it is longer and padded if it is shorter than 72 bytes.
+`dst` must point to 64 bytes of memory.
+*/
+void
+Hacl_HMAC_compute_sha3_512(
+  uint8_t *dst,
+  uint8_t *key,
+  uint32_t key_len,
+  uint8_t *data,
+  uint32_t data_len
+);
+
+/**
+Write the HMAC-BLAKE2s MAC of a message (`data`) by using a key (`key`) into `dst`.
+
+The key can be any length and will be hashed if it is longer and padded if it is shorter than 64 bytes.
+`dst` must point to 32 bytes of memory.
+*/
+void
+Hacl_HMAC_compute_blake2s_32(
+  uint8_t *dst,
+  uint8_t *key,
+  uint32_t key_len,
+  uint8_t *data,
+  uint32_t data_len
+);
+
+/**
+Write the HMAC-BLAKE2b MAC of a message (`data`) by using a key (`key`) into `dst`.
+
+The key can be any length and will be hashed if it is longer and padded if it is shorter than 128 bytes.
+`dst` must point to 64 bytes of memory.
+*/
+void
+Hacl_HMAC_compute_blake2b_32(
+  uint8_t *dst,
+  uint8_t *key,
+  uint32_t key_len,
+  uint8_t *data,
+  uint32_t data_len
+);
+
+#if defined(__cplusplus)
+}
+#endif
+
+#define __Hacl_HMAC_H_DEFINED
+#endif
diff --git a/Modules/_hacl/Hacl_Streaming_HMAC.c b/Modules/_hacl/Hacl_Streaming_HMAC.c
new file mode 100644 (file)
index 0000000..d28b397
--- /dev/null
@@ -0,0 +1,2551 @@
+/* MIT License
+ *
+ * Copyright (c) 2016-2022 INRIA, CMU and Microsoft Corporation
+ * Copyright (c) 2022-2023 HACL* Contributors
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+
+#include "internal/Hacl_Streaming_HMAC.h"
+
+#include "Hacl_Streaming_Types.h"
+
+#include "Hacl_Hash_SHA3.h"
+#include "Hacl_Hash_SHA2.h"
+#include "Hacl_Hash_Blake2s_Simd128.h"
+#include "Hacl_Hash_Blake2s.h"
+#include "Hacl_Hash_Blake2b_Simd256.h"
+#include "Hacl_Hash_Blake2b.h"
+#include "internal/Hacl_Streaming_Types.h"
+
+#include "internal/Hacl_Hash_SHA3.h"
+#include "internal/Hacl_Hash_SHA2.h"
+#include "internal/Hacl_Hash_SHA1.h"
+#include "internal/Hacl_Hash_MD5.h"
+#include "internal/Hacl_Hash_Blake2s_Simd128.h"
+#include "internal/Hacl_Hash_Blake2s.h"
+#include "internal/Hacl_Hash_Blake2b_Simd256.h"
+#include "internal/Hacl_Hash_Blake2b.h"
+
+static Spec_Hash_Definitions_hash_alg alg_of_impl(Hacl_Agile_Hash_impl i)
+{
+  switch (i)
+  {
+    case Hacl_Agile_Hash_MD5:
+      {
+        return Spec_Hash_Definitions_MD5;
+      }
+    case Hacl_Agile_Hash_SHA1:
+      {
+        return Spec_Hash_Definitions_SHA1;
+      }
+    case Hacl_Agile_Hash_SHA2_224:
+      {
+        return Spec_Hash_Definitions_SHA2_224;
+      }
+    case Hacl_Agile_Hash_SHA2_256:
+      {
+        return Spec_Hash_Definitions_SHA2_256;
+      }
+    case Hacl_Agile_Hash_SHA2_384:
+      {
+        return Spec_Hash_Definitions_SHA2_384;
+      }
+    case Hacl_Agile_Hash_SHA2_512:
+      {
+        return Spec_Hash_Definitions_SHA2_512;
+      }
+    case Hacl_Agile_Hash_SHA3_224:
+      {
+        return Spec_Hash_Definitions_SHA3_224;
+      }
+    case Hacl_Agile_Hash_SHA3_256:
+      {
+        return Spec_Hash_Definitions_SHA3_256;
+      }
+    case Hacl_Agile_Hash_SHA3_384:
+      {
+        return Spec_Hash_Definitions_SHA3_384;
+      }
+    case Hacl_Agile_Hash_SHA3_512:
+      {
+        return Spec_Hash_Definitions_SHA3_512;
+      }
+    case Hacl_Agile_Hash_Blake2S_32:
+      {
+        return Spec_Hash_Definitions_Blake2S;
+      }
+    case Hacl_Agile_Hash_Blake2S_128:
+      {
+        return Spec_Hash_Definitions_Blake2S;
+      }
+    case Hacl_Agile_Hash_Blake2B_32:
+      {
+        return Spec_Hash_Definitions_Blake2B;
+      }
+    case Hacl_Agile_Hash_Blake2B_256:
+      {
+        return Spec_Hash_Definitions_Blake2B;
+      }
+    default:
+      {
+        KRML_HOST_EPRINTF("KaRaMeL incomplete match at %s:%d\n", __FILE__, __LINE__);
+        KRML_HOST_EXIT(253U);
+      }
+  }
+}
+
+static Hacl_Agile_Hash_impl impl_of_state_s(Hacl_Agile_Hash_state_s s)
+{
+  if (s.tag == Hacl_Agile_Hash_MD5_a)
+  {
+    return Hacl_Agile_Hash_MD5;
+  }
+  if (s.tag == Hacl_Agile_Hash_SHA1_a)
+  {
+    return Hacl_Agile_Hash_SHA1;
+  }
+  if (s.tag == Hacl_Agile_Hash_SHA2_224_a)
+  {
+    return Hacl_Agile_Hash_SHA2_224;
+  }
+  if (s.tag == Hacl_Agile_Hash_SHA2_256_a)
+  {
+    return Hacl_Agile_Hash_SHA2_256;
+  }
+  if (s.tag == Hacl_Agile_Hash_SHA2_384_a)
+  {
+    return Hacl_Agile_Hash_SHA2_384;
+  }
+  if (s.tag == Hacl_Agile_Hash_SHA2_512_a)
+  {
+    return Hacl_Agile_Hash_SHA2_512;
+  }
+  if (s.tag == Hacl_Agile_Hash_SHA3_224_a)
+  {
+    return Hacl_Agile_Hash_SHA3_224;
+  }
+  if (s.tag == Hacl_Agile_Hash_SHA3_256_a)
+  {
+    return Hacl_Agile_Hash_SHA3_256;
+  }
+  if (s.tag == Hacl_Agile_Hash_SHA3_384_a)
+  {
+    return Hacl_Agile_Hash_SHA3_384;
+  }
+  if (s.tag == Hacl_Agile_Hash_SHA3_512_a)
+  {
+    return Hacl_Agile_Hash_SHA3_512;
+  }
+  if (s.tag == Hacl_Agile_Hash_Blake2S_a)
+  {
+    return Hacl_Agile_Hash_Blake2S_32;
+  }
+  if (s.tag == Hacl_Agile_Hash_Blake2S_128_a)
+  {
+    return Hacl_Agile_Hash_Blake2S_128;
+  }
+  if (s.tag == Hacl_Agile_Hash_Blake2B_a)
+  {
+    return Hacl_Agile_Hash_Blake2B_32;
+  }
+  if (s.tag == Hacl_Agile_Hash_Blake2B_256_a)
+  {
+    return Hacl_Agile_Hash_Blake2B_256;
+  }
+  KRML_HOST_EPRINTF("KaRaMeL abort at %s:%d\n%s\n",
+    __FILE__,
+    __LINE__,
+    "unreachable (pattern matches are exhaustive in F*)");
+  KRML_HOST_EXIT(255U);
+}
+
+static Hacl_Agile_Hash_impl impl_of_state(Hacl_Agile_Hash_state_s *s)
+{
+  return impl_of_state_s(*s);
+}
+
+static Hacl_Agile_Hash_state_s *malloc_(Hacl_Agile_Hash_impl a)
+{
+  switch (a)
+  {
+    case Hacl_Agile_Hash_MD5:
+      {
+        uint32_t *s = (uint32_t *)KRML_HOST_CALLOC(4U, sizeof (uint32_t));
+        if (s == NULL)
+        {
+          return NULL;
+        }
+        uint32_t *s1 = s;
+        Hacl_Agile_Hash_state_s
+        *st = (Hacl_Agile_Hash_state_s *)KRML_HOST_MALLOC(sizeof (Hacl_Agile_Hash_state_s));
+        if (st != NULL)
+        {
+          st[0U]
+          = ((Hacl_Agile_Hash_state_s){ .tag = Hacl_Agile_Hash_MD5_a, { .case_MD5_a = s1 } });
+        }
+        if (st == NULL)
+        {
+          KRML_HOST_FREE(s1);
+          return NULL;
+        }
+        return st;
+      }
+    case Hacl_Agile_Hash_SHA1:
+      {
+        uint32_t *s = (uint32_t *)KRML_HOST_CALLOC(5U, sizeof (uint32_t));
+        if (s == NULL)
+        {
+          return NULL;
+        }
+        uint32_t *s1 = s;
+        Hacl_Agile_Hash_state_s
+        *st = (Hacl_Agile_Hash_state_s *)KRML_HOST_MALLOC(sizeof (Hacl_Agile_Hash_state_s));
+        if (st != NULL)
+        {
+          st[0U]
+          = ((Hacl_Agile_Hash_state_s){ .tag = Hacl_Agile_Hash_SHA1_a, { .case_SHA1_a = s1 } });
+        }
+        if (st == NULL)
+        {
+          KRML_HOST_FREE(s1);
+          return NULL;
+        }
+        return st;
+      }
+    case Hacl_Agile_Hash_SHA2_224:
+      {
+        uint32_t *s = (uint32_t *)KRML_HOST_CALLOC(8U, sizeof (uint32_t));
+        if (s == NULL)
+        {
+          return NULL;
+        }
+        uint32_t *s1 = s;
+        Hacl_Agile_Hash_state_s
+        *st = (Hacl_Agile_Hash_state_s *)KRML_HOST_MALLOC(sizeof (Hacl_Agile_Hash_state_s));
+        if (st != NULL)
+        {
+          st[0U]
+          =
+            (
+              (Hacl_Agile_Hash_state_s){
+                .tag = Hacl_Agile_Hash_SHA2_224_a,
+                { .case_SHA2_224_a = s1 }
+              }
+            );
+        }
+        if (st == NULL)
+        {
+          KRML_HOST_FREE(s1);
+          return NULL;
+        }
+        return st;
+      }
+    case Hacl_Agile_Hash_SHA2_256:
+      {
+        uint32_t *s = (uint32_t *)KRML_HOST_CALLOC(8U, sizeof (uint32_t));
+        if (s == NULL)
+        {
+          return NULL;
+        }
+        uint32_t *s1 = s;
+        Hacl_Agile_Hash_state_s
+        *st = (Hacl_Agile_Hash_state_s *)KRML_HOST_MALLOC(sizeof (Hacl_Agile_Hash_state_s));
+        if (st != NULL)
+        {
+          st[0U]
+          =
+            (
+              (Hacl_Agile_Hash_state_s){
+                .tag = Hacl_Agile_Hash_SHA2_256_a,
+                { .case_SHA2_256_a = s1 }
+              }
+            );
+        }
+        if (st == NULL)
+        {
+          KRML_HOST_FREE(s1);
+          return NULL;
+        }
+        return st;
+      }
+    case Hacl_Agile_Hash_SHA2_384:
+      {
+        uint64_t *s = (uint64_t *)KRML_HOST_CALLOC(8U, sizeof (uint64_t));
+        if (s == NULL)
+        {
+          return NULL;
+        }
+        uint64_t *s1 = s;
+        Hacl_Agile_Hash_state_s
+        *st = (Hacl_Agile_Hash_state_s *)KRML_HOST_MALLOC(sizeof (Hacl_Agile_Hash_state_s));
+        if (st != NULL)
+        {
+          st[0U]
+          =
+            (
+              (Hacl_Agile_Hash_state_s){
+                .tag = Hacl_Agile_Hash_SHA2_384_a,
+                { .case_SHA2_384_a = s1 }
+              }
+            );
+        }
+        if (st == NULL)
+        {
+          KRML_HOST_FREE(s1);
+          return NULL;
+        }
+        return st;
+      }
+    case Hacl_Agile_Hash_SHA2_512:
+      {
+        uint64_t *s = (uint64_t *)KRML_HOST_CALLOC(8U, sizeof (uint64_t));
+        if (s == NULL)
+        {
+          return NULL;
+        }
+        uint64_t *s1 = s;
+        Hacl_Agile_Hash_state_s
+        *st = (Hacl_Agile_Hash_state_s *)KRML_HOST_MALLOC(sizeof (Hacl_Agile_Hash_state_s));
+        if (st != NULL)
+        {
+          st[0U]
+          =
+            (
+              (Hacl_Agile_Hash_state_s){
+                .tag = Hacl_Agile_Hash_SHA2_512_a,
+                { .case_SHA2_512_a = s1 }
+              }
+            );
+        }
+        if (st == NULL)
+        {
+          KRML_HOST_FREE(s1);
+          return NULL;
+        }
+        return st;
+      }
+    case Hacl_Agile_Hash_SHA3_224:
+      {
+        uint64_t *s = (uint64_t *)KRML_HOST_CALLOC(25U, sizeof (uint64_t));
+        if (s == NULL)
+        {
+          return NULL;
+        }
+        uint64_t *s1 = s;
+        Hacl_Agile_Hash_state_s
+        *st = (Hacl_Agile_Hash_state_s *)KRML_HOST_MALLOC(sizeof (Hacl_Agile_Hash_state_s));
+        if (st != NULL)
+        {
+          st[0U]
+          =
+            (
+              (Hacl_Agile_Hash_state_s){
+                .tag = Hacl_Agile_Hash_SHA3_224_a,
+                { .case_SHA3_224_a = s1 }
+              }
+            );
+        }
+        if (st == NULL)
+        {
+          KRML_HOST_FREE(s1);
+          return NULL;
+        }
+        return st;
+      }
+    case Hacl_Agile_Hash_SHA3_256:
+      {
+        uint64_t *s = (uint64_t *)KRML_HOST_CALLOC(25U, sizeof (uint64_t));
+        if (s == NULL)
+        {
+          return NULL;
+        }
+        uint64_t *s1 = s;
+        Hacl_Agile_Hash_state_s
+        *st = (Hacl_Agile_Hash_state_s *)KRML_HOST_MALLOC(sizeof (Hacl_Agile_Hash_state_s));
+        if (st != NULL)
+        {
+          st[0U]
+          =
+            (
+              (Hacl_Agile_Hash_state_s){
+                .tag = Hacl_Agile_Hash_SHA3_256_a,
+                { .case_SHA3_256_a = s1 }
+              }
+            );
+        }
+        if (st == NULL)
+        {
+          KRML_HOST_FREE(s1);
+          return NULL;
+        }
+        return st;
+      }
+    case Hacl_Agile_Hash_SHA3_384:
+      {
+        uint64_t *s = (uint64_t *)KRML_HOST_CALLOC(25U, sizeof (uint64_t));
+        if (s == NULL)
+        {
+          return NULL;
+        }
+        uint64_t *s1 = s;
+        Hacl_Agile_Hash_state_s
+        *st = (Hacl_Agile_Hash_state_s *)KRML_HOST_MALLOC(sizeof (Hacl_Agile_Hash_state_s));
+        if (st != NULL)
+        {
+          st[0U]
+          =
+            (
+              (Hacl_Agile_Hash_state_s){
+                .tag = Hacl_Agile_Hash_SHA3_384_a,
+                { .case_SHA3_384_a = s1 }
+              }
+            );
+        }
+        if (st == NULL)
+        {
+          KRML_HOST_FREE(s1);
+          return NULL;
+        }
+        return st;
+      }
+    case Hacl_Agile_Hash_SHA3_512:
+      {
+        uint64_t *s = (uint64_t *)KRML_HOST_CALLOC(25U, sizeof (uint64_t));
+        if (s == NULL)
+        {
+          return NULL;
+        }
+        uint64_t *s1 = s;
+        Hacl_Agile_Hash_state_s
+        *st = (Hacl_Agile_Hash_state_s *)KRML_HOST_MALLOC(sizeof (Hacl_Agile_Hash_state_s));
+        if (st != NULL)
+        {
+          st[0U]
+          =
+            (
+              (Hacl_Agile_Hash_state_s){
+                .tag = Hacl_Agile_Hash_SHA3_512_a,
+                { .case_SHA3_512_a = s1 }
+              }
+            );
+        }
+        if (st == NULL)
+        {
+          KRML_HOST_FREE(s1);
+          return NULL;
+        }
+        return st;
+      }
+    case Hacl_Agile_Hash_Blake2S_32:
+      {
+        uint32_t *s = (uint32_t *)KRML_HOST_CALLOC(16U, sizeof (uint32_t));
+        if (s == NULL)
+        {
+          return NULL;
+        }
+        uint32_t *s1 = s;
+        Hacl_Agile_Hash_state_s
+        *st = (Hacl_Agile_Hash_state_s *)KRML_HOST_MALLOC(sizeof (Hacl_Agile_Hash_state_s));
+        if (st != NULL)
+        {
+          st[0U]
+          =
+            (
+              (Hacl_Agile_Hash_state_s){
+                .tag = Hacl_Agile_Hash_Blake2S_a,
+                { .case_Blake2S_a = s1 }
+              }
+            );
+        }
+        if (st == NULL)
+        {
+          KRML_HOST_FREE(s1);
+          return NULL;
+        }
+        return st;
+      }
+    case Hacl_Agile_Hash_Blake2S_128:
+      {
+        #if HACL_CAN_COMPILE_VEC128
+        Lib_IntVector_Intrinsics_vec128
+        *s = Hacl_Hash_Blake2s_Simd128_malloc_internal_state_with_key();
+        if (s == NULL)
+        {
+          return NULL;
+        }
+        Hacl_Agile_Hash_state_s
+        *st = (Hacl_Agile_Hash_state_s *)KRML_HOST_MALLOC(sizeof (Hacl_Agile_Hash_state_s));
+        if (st != NULL)
+        {
+          st[0U]
+          =
+            (
+              (Hacl_Agile_Hash_state_s){
+                .tag = Hacl_Agile_Hash_Blake2S_128_a,
+                { .case_Blake2S_128_a = s }
+              }
+            );
+        }
+        if (st == NULL)
+        {
+          KRML_ALIGNED_FREE(s);
+          return NULL;
+        }
+        return st;
+        #else
+        KRML_HOST_EPRINTF("KaRaMeL abort at %s:%d\n%s\n",
+          __FILE__,
+          __LINE__,
+          "provably unreachable code: did an unverified caller violate a precondition\?");
+        KRML_HOST_EXIT(255U);
+        #endif
+        break;
+      }
+    case Hacl_Agile_Hash_Blake2B_32:
+      {
+        uint64_t *s = (uint64_t *)KRML_HOST_CALLOC(16U, sizeof (uint64_t));
+        if (s == NULL)
+        {
+          return NULL;
+        }
+        uint64_t *s1 = s;
+        Hacl_Agile_Hash_state_s
+        *st = (Hacl_Agile_Hash_state_s *)KRML_HOST_MALLOC(sizeof (Hacl_Agile_Hash_state_s));
+        if (st != NULL)
+        {
+          st[0U]
+          =
+            (
+              (Hacl_Agile_Hash_state_s){
+                .tag = Hacl_Agile_Hash_Blake2B_a,
+                { .case_Blake2B_a = s1 }
+              }
+            );
+        }
+        if (st == NULL)
+        {
+          KRML_HOST_FREE(s1);
+          return NULL;
+        }
+        return st;
+      }
+    case Hacl_Agile_Hash_Blake2B_256:
+      {
+        #if HACL_CAN_COMPILE_VEC256
+        Lib_IntVector_Intrinsics_vec256
+        *s = Hacl_Hash_Blake2b_Simd256_malloc_internal_state_with_key();
+        if (s == NULL)
+        {
+          return NULL;
+        }
+        Hacl_Agile_Hash_state_s
+        *st = (Hacl_Agile_Hash_state_s *)KRML_HOST_MALLOC(sizeof (Hacl_Agile_Hash_state_s));
+        if (st != NULL)
+        {
+          st[0U]
+          =
+            (
+              (Hacl_Agile_Hash_state_s){
+                .tag = Hacl_Agile_Hash_Blake2B_256_a,
+                { .case_Blake2B_256_a = s }
+              }
+            );
+        }
+        if (st == NULL)
+        {
+          KRML_ALIGNED_FREE(s);
+          return NULL;
+        }
+        return st;
+        #else
+        KRML_HOST_EPRINTF("KaRaMeL abort at %s:%d\n%s\n",
+          __FILE__,
+          __LINE__,
+          "provably unreachable code: did an unverified caller violate a precondition\?");
+        KRML_HOST_EXIT(255U);
+        #endif
+        break;
+      }
+    default:
+      {
+        KRML_HOST_EPRINTF("KaRaMeL incomplete match at %s:%d\n", __FILE__, __LINE__);
+        KRML_HOST_EXIT(253U);
+      }
+  }
+}
+
+static void init(Hacl_Agile_Hash_state_s *s)
+{
+  Hacl_Agile_Hash_state_s scrut = *s;
+  if (scrut.tag == Hacl_Agile_Hash_MD5_a)
+  {
+    uint32_t *p1 = scrut.case_MD5_a;
+    Hacl_Hash_MD5_init(p1);
+    return;
+  }
+  if (scrut.tag == Hacl_Agile_Hash_SHA1_a)
+  {
+    uint32_t *p1 = scrut.case_SHA1_a;
+    Hacl_Hash_SHA1_init(p1);
+    return;
+  }
+  if (scrut.tag == Hacl_Agile_Hash_SHA2_224_a)
+  {
+    uint32_t *p1 = scrut.case_SHA2_224_a;
+    Hacl_Hash_SHA2_sha224_init(p1);
+    return;
+  }
+  if (scrut.tag == Hacl_Agile_Hash_SHA2_256_a)
+  {
+    uint32_t *p1 = scrut.case_SHA2_256_a;
+    Hacl_Hash_SHA2_sha256_init(p1);
+    return;
+  }
+  if (scrut.tag == Hacl_Agile_Hash_SHA2_384_a)
+  {
+    uint64_t *p1 = scrut.case_SHA2_384_a;
+    Hacl_Hash_SHA2_sha384_init(p1);
+    return;
+  }
+  if (scrut.tag == Hacl_Agile_Hash_SHA2_512_a)
+  {
+    uint64_t *p1 = scrut.case_SHA2_512_a;
+    Hacl_Hash_SHA2_sha512_init(p1);
+    return;
+  }
+  if (scrut.tag == Hacl_Agile_Hash_SHA3_224_a)
+  {
+    uint64_t *p1 = scrut.case_SHA3_224_a;
+    Hacl_Hash_SHA3_init_(Spec_Hash_Definitions_SHA3_224, p1);
+    return;
+  }
+  if (scrut.tag == Hacl_Agile_Hash_SHA3_256_a)
+  {
+    uint64_t *p1 = scrut.case_SHA3_256_a;
+    Hacl_Hash_SHA3_init_(Spec_Hash_Definitions_SHA3_256, p1);
+    return;
+  }
+  if (scrut.tag == Hacl_Agile_Hash_SHA3_384_a)
+  {
+    uint64_t *p1 = scrut.case_SHA3_384_a;
+    Hacl_Hash_SHA3_init_(Spec_Hash_Definitions_SHA3_384, p1);
+    return;
+  }
+  if (scrut.tag == Hacl_Agile_Hash_SHA3_512_a)
+  {
+    uint64_t *p1 = scrut.case_SHA3_512_a;
+    Hacl_Hash_SHA3_init_(Spec_Hash_Definitions_SHA3_512, p1);
+    return;
+  }
+  if (scrut.tag == Hacl_Agile_Hash_Blake2S_a)
+  {
+    uint32_t *p1 = scrut.case_Blake2S_a;
+    Hacl_Hash_Blake2s_init(p1, 0U, 32U);
+    return;
+  }
+  if (scrut.tag == Hacl_Agile_Hash_Blake2S_128_a)
+  {
+    Lib_IntVector_Intrinsics_vec128 *p1 = scrut.case_Blake2S_128_a;
+    #if HACL_CAN_COMPILE_VEC128
+    Hacl_Hash_Blake2s_Simd128_init(p1, 0U, 32U);
+    return;
+    #else
+    KRML_MAYBE_UNUSED_VAR(p1);
+    return;
+    #endif
+  }
+  if (scrut.tag == Hacl_Agile_Hash_Blake2B_a)
+  {
+    uint64_t *p1 = scrut.case_Blake2B_a;
+    Hacl_Hash_Blake2b_init(p1, 0U, 64U);
+    return;
+  }
+  if (scrut.tag == Hacl_Agile_Hash_Blake2B_256_a)
+  {
+    Lib_IntVector_Intrinsics_vec256 *p1 = scrut.case_Blake2B_256_a;
+    #if HACL_CAN_COMPILE_VEC256
+    Hacl_Hash_Blake2b_Simd256_init(p1, 0U, 64U);
+    return;
+    #else
+    KRML_MAYBE_UNUSED_VAR(p1);
+    return;
+    #endif
+  }
+  KRML_HOST_EPRINTF("KaRaMeL abort at %s:%d\n%s\n",
+    __FILE__,
+    __LINE__,
+    "unreachable (pattern matches are exhaustive in F*)");
+  KRML_HOST_EXIT(255U);
+}
+
+static void
+update_multi(Hacl_Agile_Hash_state_s *s, uint64_t prevlen, uint8_t *blocks, uint32_t len)
+{
+  Hacl_Agile_Hash_state_s scrut = *s;
+  if (scrut.tag == Hacl_Agile_Hash_MD5_a)
+  {
+    uint32_t *p1 = scrut.case_MD5_a;
+    uint32_t n = len / 64U;
+    Hacl_Hash_MD5_update_multi(p1, blocks, n);
+    return;
+  }
+  if (scrut.tag == Hacl_Agile_Hash_SHA1_a)
+  {
+    uint32_t *p1 = scrut.case_SHA1_a;
+    uint32_t n = len / 64U;
+    Hacl_Hash_SHA1_update_multi(p1, blocks, n);
+    return;
+  }
+  if (scrut.tag == Hacl_Agile_Hash_SHA2_224_a)
+  {
+    uint32_t *p1 = scrut.case_SHA2_224_a;
+    uint32_t n = len / 64U;
+    Hacl_Hash_SHA2_sha224_update_nblocks(n * 64U, blocks, p1);
+    return;
+  }
+  if (scrut.tag == Hacl_Agile_Hash_SHA2_256_a)
+  {
+    uint32_t *p1 = scrut.case_SHA2_256_a;
+    uint32_t n = len / 64U;
+    Hacl_Hash_SHA2_sha256_update_nblocks(n * 64U, blocks, p1);
+    return;
+  }
+  if (scrut.tag == Hacl_Agile_Hash_SHA2_384_a)
+  {
+    uint64_t *p1 = scrut.case_SHA2_384_a;
+    uint32_t n = len / 128U;
+    Hacl_Hash_SHA2_sha384_update_nblocks(n * 128U, blocks, p1);
+    return;
+  }
+  if (scrut.tag == Hacl_Agile_Hash_SHA2_512_a)
+  {
+    uint64_t *p1 = scrut.case_SHA2_512_a;
+    uint32_t n = len / 128U;
+    Hacl_Hash_SHA2_sha512_update_nblocks(n * 128U, blocks, p1);
+    return;
+  }
+  if (scrut.tag == Hacl_Agile_Hash_SHA3_224_a)
+  {
+    uint64_t *p1 = scrut.case_SHA3_224_a;
+    uint32_t n = len / 144U;
+    Hacl_Hash_SHA3_update_multi_sha3(Spec_Hash_Definitions_SHA3_224, p1, blocks, n);
+    return;
+  }
+  if (scrut.tag == Hacl_Agile_Hash_SHA3_256_a)
+  {
+    uint64_t *p1 = scrut.case_SHA3_256_a;
+    uint32_t n = len / 136U;
+    Hacl_Hash_SHA3_update_multi_sha3(Spec_Hash_Definitions_SHA3_256, p1, blocks, n);
+    return;
+  }
+  if (scrut.tag == Hacl_Agile_Hash_SHA3_384_a)
+  {
+    uint64_t *p1 = scrut.case_SHA3_384_a;
+    uint32_t n = len / 104U;
+    Hacl_Hash_SHA3_update_multi_sha3(Spec_Hash_Definitions_SHA3_384, p1, blocks, n);
+    return;
+  }
+  if (scrut.tag == Hacl_Agile_Hash_SHA3_512_a)
+  {
+    uint64_t *p1 = scrut.case_SHA3_512_a;
+    uint32_t n = len / 72U;
+    Hacl_Hash_SHA3_update_multi_sha3(Spec_Hash_Definitions_SHA3_512, p1, blocks, n);
+    return;
+  }
+  if (scrut.tag == Hacl_Agile_Hash_Blake2S_a)
+  {
+    uint32_t *p1 = scrut.case_Blake2S_a;
+    uint32_t n = len / 64U;
+    uint32_t wv[16U] = { 0U };
+    Hacl_Hash_Blake2s_update_multi(n * 64U, wv, p1, prevlen, blocks, n);
+    return;
+  }
+  if (scrut.tag == Hacl_Agile_Hash_Blake2S_128_a)
+  {
+    Lib_IntVector_Intrinsics_vec128 *p1 = scrut.case_Blake2S_128_a;
+    #if HACL_CAN_COMPILE_VEC128
+    uint32_t n = len / 64U;
+    Hacl_Hash_Blake2s_Simd128_update_multi_no_inline(p1, prevlen, blocks, n);
+    return;
+    #else
+    KRML_MAYBE_UNUSED_VAR(p1);
+    return;
+    #endif
+  }
+  if (scrut.tag == Hacl_Agile_Hash_Blake2B_a)
+  {
+    uint64_t *p1 = scrut.case_Blake2B_a;
+    uint32_t n = len / 128U;
+    uint64_t wv[16U] = { 0U };
+    Hacl_Hash_Blake2b_update_multi(n * 128U,
+      wv,
+      p1,
+      FStar_UInt128_uint64_to_uint128(prevlen),
+      blocks,
+      n);
+    return;
+  }
+  if (scrut.tag == Hacl_Agile_Hash_Blake2B_256_a)
+  {
+    Lib_IntVector_Intrinsics_vec256 *p1 = scrut.case_Blake2B_256_a;
+    #if HACL_CAN_COMPILE_VEC256
+    uint32_t n = len / 128U;
+    Hacl_Hash_Blake2b_Simd256_update_multi_no_inline(p1,
+      FStar_UInt128_uint64_to_uint128(prevlen),
+      blocks,
+      n);
+    return;
+    #else
+    KRML_MAYBE_UNUSED_VAR(p1);
+    return;
+    #endif
+  }
+  KRML_HOST_EPRINTF("KaRaMeL abort at %s:%d\n%s\n",
+    __FILE__,
+    __LINE__,
+    "unreachable (pattern matches are exhaustive in F*)");
+  KRML_HOST_EXIT(255U);
+}
+
+static void
+update_last(Hacl_Agile_Hash_state_s *s, uint64_t prev_len, uint8_t *last, uint32_t last_len)
+{
+  Hacl_Agile_Hash_state_s scrut = *s;
+  if (scrut.tag == Hacl_Agile_Hash_MD5_a)
+  {
+    uint32_t *p1 = scrut.case_MD5_a;
+    Hacl_Hash_MD5_update_last(p1, prev_len, last, last_len);
+    return;
+  }
+  if (scrut.tag == Hacl_Agile_Hash_SHA1_a)
+  {
+    uint32_t *p1 = scrut.case_SHA1_a;
+    Hacl_Hash_SHA1_update_last(p1, prev_len, last, last_len);
+    return;
+  }
+  if (scrut.tag == Hacl_Agile_Hash_SHA2_224_a)
+  {
+    uint32_t *p1 = scrut.case_SHA2_224_a;
+    Hacl_Hash_SHA2_sha224_update_last(prev_len + (uint64_t)last_len, last_len, last, p1);
+    return;
+  }
+  if (scrut.tag == Hacl_Agile_Hash_SHA2_256_a)
+  {
+    uint32_t *p1 = scrut.case_SHA2_256_a;
+    Hacl_Hash_SHA2_sha256_update_last(prev_len + (uint64_t)last_len, last_len, last, p1);
+    return;
+  }
+  if (scrut.tag == Hacl_Agile_Hash_SHA2_384_a)
+  {
+    uint64_t *p1 = scrut.case_SHA2_384_a;
+    Hacl_Hash_SHA2_sha384_update_last(FStar_UInt128_add(FStar_UInt128_uint64_to_uint128(prev_len),
+        FStar_UInt128_uint64_to_uint128((uint64_t)last_len)),
+      last_len,
+      last,
+      p1);
+    return;
+  }
+  if (scrut.tag == Hacl_Agile_Hash_SHA2_512_a)
+  {
+    uint64_t *p1 = scrut.case_SHA2_512_a;
+    Hacl_Hash_SHA2_sha512_update_last(FStar_UInt128_add(FStar_UInt128_uint64_to_uint128(prev_len),
+        FStar_UInt128_uint64_to_uint128((uint64_t)last_len)),
+      last_len,
+      last,
+      p1);
+    return;
+  }
+  if (scrut.tag == Hacl_Agile_Hash_SHA3_224_a)
+  {
+    uint64_t *p1 = scrut.case_SHA3_224_a;
+    Hacl_Hash_SHA3_update_last_sha3(Spec_Hash_Definitions_SHA3_224, p1, last, last_len);
+    return;
+  }
+  if (scrut.tag == Hacl_Agile_Hash_SHA3_256_a)
+  {
+    uint64_t *p1 = scrut.case_SHA3_256_a;
+    Hacl_Hash_SHA3_update_last_sha3(Spec_Hash_Definitions_SHA3_256, p1, last, last_len);
+    return;
+  }
+  if (scrut.tag == Hacl_Agile_Hash_SHA3_384_a)
+  {
+    uint64_t *p1 = scrut.case_SHA3_384_a;
+    Hacl_Hash_SHA3_update_last_sha3(Spec_Hash_Definitions_SHA3_384, p1, last, last_len);
+    return;
+  }
+  if (scrut.tag == Hacl_Agile_Hash_SHA3_512_a)
+  {
+    uint64_t *p1 = scrut.case_SHA3_512_a;
+    Hacl_Hash_SHA3_update_last_sha3(Spec_Hash_Definitions_SHA3_512, p1, last, last_len);
+    return;
+  }
+  if (scrut.tag == Hacl_Agile_Hash_Blake2S_a)
+  {
+    uint32_t *p1 = scrut.case_Blake2S_a;
+    uint32_t wv[16U] = { 0U };
+    Hacl_Hash_Blake2s_update_last(last_len, wv, p1, false, prev_len, last_len, last);
+    return;
+  }
+  if (scrut.tag == Hacl_Agile_Hash_Blake2S_128_a)
+  {
+    Lib_IntVector_Intrinsics_vec128 *p1 = scrut.case_Blake2S_128_a;
+    #if HACL_CAN_COMPILE_VEC128
+    Hacl_Hash_Blake2s_Simd128_update_last_no_inline(p1, prev_len, last, last_len);
+    return;
+    #else
+    KRML_MAYBE_UNUSED_VAR(p1);
+    return;
+    #endif
+  }
+  if (scrut.tag == Hacl_Agile_Hash_Blake2B_a)
+  {
+    uint64_t *p1 = scrut.case_Blake2B_a;
+    uint64_t wv[16U] = { 0U };
+    Hacl_Hash_Blake2b_update_last(last_len,
+      wv,
+      p1,
+      false,
+      FStar_UInt128_uint64_to_uint128(prev_len),
+      last_len,
+      last);
+    return;
+  }
+  if (scrut.tag == Hacl_Agile_Hash_Blake2B_256_a)
+  {
+    Lib_IntVector_Intrinsics_vec256 *p1 = scrut.case_Blake2B_256_a;
+    #if HACL_CAN_COMPILE_VEC256
+    Hacl_Hash_Blake2b_Simd256_update_last_no_inline(p1,
+      FStar_UInt128_uint64_to_uint128(prev_len),
+      last,
+      last_len);
+    return;
+    #else
+    KRML_MAYBE_UNUSED_VAR(p1);
+    return;
+    #endif
+  }
+  KRML_HOST_EPRINTF("KaRaMeL abort at %s:%d\n%s\n",
+    __FILE__,
+    __LINE__,
+    "unreachable (pattern matches are exhaustive in F*)");
+  KRML_HOST_EXIT(255U);
+}
+
+static void finish(Hacl_Agile_Hash_state_s *s, uint8_t *dst)
+{
+  Hacl_Agile_Hash_state_s scrut = *s;
+  if (scrut.tag == Hacl_Agile_Hash_MD5_a)
+  {
+    uint32_t *p1 = scrut.case_MD5_a;
+    Hacl_Hash_MD5_finish(p1, dst);
+    return;
+  }
+  if (scrut.tag == Hacl_Agile_Hash_SHA1_a)
+  {
+    uint32_t *p1 = scrut.case_SHA1_a;
+    Hacl_Hash_SHA1_finish(p1, dst);
+    return;
+  }
+  if (scrut.tag == Hacl_Agile_Hash_SHA2_224_a)
+  {
+    uint32_t *p1 = scrut.case_SHA2_224_a;
+    Hacl_Hash_SHA2_sha224_finish(p1, dst);
+    return;
+  }
+  if (scrut.tag == Hacl_Agile_Hash_SHA2_256_a)
+  {
+    uint32_t *p1 = scrut.case_SHA2_256_a;
+    Hacl_Hash_SHA2_sha256_finish(p1, dst);
+    return;
+  }
+  if (scrut.tag == Hacl_Agile_Hash_SHA2_384_a)
+  {
+    uint64_t *p1 = scrut.case_SHA2_384_a;
+    Hacl_Hash_SHA2_sha384_finish(p1, dst);
+    return;
+  }
+  if (scrut.tag == Hacl_Agile_Hash_SHA2_512_a)
+  {
+    uint64_t *p1 = scrut.case_SHA2_512_a;
+    Hacl_Hash_SHA2_sha512_finish(p1, dst);
+    return;
+  }
+  if (scrut.tag == Hacl_Agile_Hash_SHA3_224_a)
+  {
+    uint64_t *p1 = scrut.case_SHA3_224_a;
+    uint32_t remOut = 28U;
+    uint8_t hbuf[256U] = { 0U };
+    uint64_t ws[32U] = { 0U };
+    memcpy(ws, p1, 25U * sizeof (uint64_t));
+    for (uint32_t i = 0U; i < 32U; i++)
+    {
+      store64_le(hbuf + i * 8U, ws[i]);
+    }
+    memcpy(dst + 28U - remOut, hbuf, remOut * sizeof (uint8_t));
+    return;
+  }
+  if (scrut.tag == Hacl_Agile_Hash_SHA3_256_a)
+  {
+    uint64_t *p1 = scrut.case_SHA3_256_a;
+    uint32_t remOut = 32U;
+    uint8_t hbuf[256U] = { 0U };
+    uint64_t ws[32U] = { 0U };
+    memcpy(ws, p1, 25U * sizeof (uint64_t));
+    for (uint32_t i = 0U; i < 32U; i++)
+    {
+      store64_le(hbuf + i * 8U, ws[i]);
+    }
+    memcpy(dst + 32U - remOut, hbuf, remOut * sizeof (uint8_t));
+    return;
+  }
+  if (scrut.tag == Hacl_Agile_Hash_SHA3_384_a)
+  {
+    uint64_t *p1 = scrut.case_SHA3_384_a;
+    uint32_t remOut = 48U;
+    uint8_t hbuf[256U] = { 0U };
+    uint64_t ws[32U] = { 0U };
+    memcpy(ws, p1, 25U * sizeof (uint64_t));
+    for (uint32_t i = 0U; i < 32U; i++)
+    {
+      store64_le(hbuf + i * 8U, ws[i]);
+    }
+    memcpy(dst + 48U - remOut, hbuf, remOut * sizeof (uint8_t));
+    return;
+  }
+  if (scrut.tag == Hacl_Agile_Hash_SHA3_512_a)
+  {
+    uint64_t *p1 = scrut.case_SHA3_512_a;
+    uint32_t remOut = 64U;
+    uint8_t hbuf[256U] = { 0U };
+    uint64_t ws[32U] = { 0U };
+    memcpy(ws, p1, 25U * sizeof (uint64_t));
+    for (uint32_t i = 0U; i < 32U; i++)
+    {
+      store64_le(hbuf + i * 8U, ws[i]);
+    }
+    memcpy(dst + 64U - remOut, hbuf, remOut * sizeof (uint8_t));
+    return;
+  }
+  if (scrut.tag == Hacl_Agile_Hash_Blake2S_a)
+  {
+    uint32_t *p1 = scrut.case_Blake2S_a;
+    Hacl_Hash_Blake2s_finish(32U, dst, p1);
+    return;
+  }
+  if (scrut.tag == Hacl_Agile_Hash_Blake2S_128_a)
+  {
+    Lib_IntVector_Intrinsics_vec128 *p1 = scrut.case_Blake2S_128_a;
+    #if HACL_CAN_COMPILE_VEC128
+    Hacl_Hash_Blake2s_Simd128_finish(32U, dst, p1);
+    return;
+    #else
+    KRML_MAYBE_UNUSED_VAR(p1);
+    return;
+    #endif
+  }
+  if (scrut.tag == Hacl_Agile_Hash_Blake2B_a)
+  {
+    uint64_t *p1 = scrut.case_Blake2B_a;
+    Hacl_Hash_Blake2b_finish(64U, dst, p1);
+    return;
+  }
+  if (scrut.tag == Hacl_Agile_Hash_Blake2B_256_a)
+  {
+    Lib_IntVector_Intrinsics_vec256 *p1 = scrut.case_Blake2B_256_a;
+    #if HACL_CAN_COMPILE_VEC256
+    Hacl_Hash_Blake2b_Simd256_finish(64U, dst, p1);
+    return;
+    #else
+    KRML_MAYBE_UNUSED_VAR(p1);
+    return;
+    #endif
+  }
+  KRML_HOST_EPRINTF("KaRaMeL abort at %s:%d\n%s\n",
+    __FILE__,
+    __LINE__,
+    "unreachable (pattern matches are exhaustive in F*)");
+  KRML_HOST_EXIT(255U);
+}
+
+static void free_(Hacl_Agile_Hash_state_s *s)
+{
+  Hacl_Agile_Hash_state_s scrut = *s;
+  if (scrut.tag == Hacl_Agile_Hash_MD5_a)
+  {
+    uint32_t *p1 = scrut.case_MD5_a;
+    KRML_HOST_FREE(p1);
+  }
+  else if (scrut.tag == Hacl_Agile_Hash_SHA1_a)
+  {
+    uint32_t *p1 = scrut.case_SHA1_a;
+    KRML_HOST_FREE(p1);
+  }
+  else if (scrut.tag == Hacl_Agile_Hash_SHA2_224_a)
+  {
+    uint32_t *p1 = scrut.case_SHA2_224_a;
+    KRML_HOST_FREE(p1);
+  }
+  else if (scrut.tag == Hacl_Agile_Hash_SHA2_256_a)
+  {
+    uint32_t *p1 = scrut.case_SHA2_256_a;
+    KRML_HOST_FREE(p1);
+  }
+  else if (scrut.tag == Hacl_Agile_Hash_SHA2_384_a)
+  {
+    uint64_t *p1 = scrut.case_SHA2_384_a;
+    KRML_HOST_FREE(p1);
+  }
+  else if (scrut.tag == Hacl_Agile_Hash_SHA2_512_a)
+  {
+    uint64_t *p1 = scrut.case_SHA2_512_a;
+    KRML_HOST_FREE(p1);
+  }
+  else if (scrut.tag == Hacl_Agile_Hash_SHA3_224_a)
+  {
+    uint64_t *p1 = scrut.case_SHA3_224_a;
+    KRML_HOST_FREE(p1);
+  }
+  else if (scrut.tag == Hacl_Agile_Hash_SHA3_256_a)
+  {
+    uint64_t *p1 = scrut.case_SHA3_256_a;
+    KRML_HOST_FREE(p1);
+  }
+  else if (scrut.tag == Hacl_Agile_Hash_SHA3_384_a)
+  {
+    uint64_t *p1 = scrut.case_SHA3_384_a;
+    KRML_HOST_FREE(p1);
+  }
+  else if (scrut.tag == Hacl_Agile_Hash_SHA3_512_a)
+  {
+    uint64_t *p1 = scrut.case_SHA3_512_a;
+    KRML_HOST_FREE(p1);
+  }
+  else if (scrut.tag == Hacl_Agile_Hash_Blake2S_a)
+  {
+    uint32_t *p1 = scrut.case_Blake2S_a;
+    KRML_HOST_FREE(p1);
+  }
+  else if (scrut.tag == Hacl_Agile_Hash_Blake2S_128_a)
+  {
+    Lib_IntVector_Intrinsics_vec128 *p1 = scrut.case_Blake2S_128_a;
+    KRML_ALIGNED_FREE(p1);
+  }
+  else if (scrut.tag == Hacl_Agile_Hash_Blake2B_a)
+  {
+    uint64_t *p1 = scrut.case_Blake2B_a;
+    KRML_HOST_FREE(p1);
+  }
+  else if (scrut.tag == Hacl_Agile_Hash_Blake2B_256_a)
+  {
+    Lib_IntVector_Intrinsics_vec256 *p1 = scrut.case_Blake2B_256_a;
+    KRML_ALIGNED_FREE(p1);
+  }
+  else
+  {
+    KRML_HOST_EPRINTF("KaRaMeL abort at %s:%d\n%s\n",
+      __FILE__,
+      __LINE__,
+      "unreachable (pattern matches are exhaustive in F*)");
+    KRML_HOST_EXIT(255U);
+  }
+  KRML_HOST_FREE(s);
+}
+
+static void copy(Hacl_Agile_Hash_state_s *s_src, Hacl_Agile_Hash_state_s *s_dst)
+{
+  Hacl_Agile_Hash_state_s scrut = *s_src;
+  if (scrut.tag == Hacl_Agile_Hash_MD5_a)
+  {
+    uint32_t *p_src = scrut.case_MD5_a;
+    Hacl_Agile_Hash_state_s x1 = *s_dst;
+    uint32_t *p_dst;
+    if (x1.tag == Hacl_Agile_Hash_MD5_a)
+    {
+      p_dst = x1.case_MD5_a;
+    }
+    else
+    {
+      p_dst = KRML_EABORT(uint32_t *, "unreachable (pattern matches are exhaustive in F*)");
+    }
+    memcpy(p_dst, p_src, 4U * sizeof (uint32_t));
+    return;
+  }
+  if (scrut.tag == Hacl_Agile_Hash_SHA1_a)
+  {
+    uint32_t *p_src = scrut.case_SHA1_a;
+    Hacl_Agile_Hash_state_s x1 = *s_dst;
+    uint32_t *p_dst;
+    if (x1.tag == Hacl_Agile_Hash_SHA1_a)
+    {
+      p_dst = x1.case_SHA1_a;
+    }
+    else
+    {
+      p_dst = KRML_EABORT(uint32_t *, "unreachable (pattern matches are exhaustive in F*)");
+    }
+    memcpy(p_dst, p_src, 5U * sizeof (uint32_t));
+    return;
+  }
+  if (scrut.tag == Hacl_Agile_Hash_SHA2_224_a)
+  {
+    uint32_t *p_src = scrut.case_SHA2_224_a;
+    Hacl_Agile_Hash_state_s x1 = *s_dst;
+    uint32_t *p_dst;
+    if (x1.tag == Hacl_Agile_Hash_SHA2_224_a)
+    {
+      p_dst = x1.case_SHA2_224_a;
+    }
+    else
+    {
+      p_dst = KRML_EABORT(uint32_t *, "unreachable (pattern matches are exhaustive in F*)");
+    }
+    memcpy(p_dst, p_src, 8U * sizeof (uint32_t));
+    return;
+  }
+  if (scrut.tag == Hacl_Agile_Hash_SHA2_256_a)
+  {
+    uint32_t *p_src = scrut.case_SHA2_256_a;
+    Hacl_Agile_Hash_state_s x1 = *s_dst;
+    uint32_t *p_dst;
+    if (x1.tag == Hacl_Agile_Hash_SHA2_256_a)
+    {
+      p_dst = x1.case_SHA2_256_a;
+    }
+    else
+    {
+      p_dst = KRML_EABORT(uint32_t *, "unreachable (pattern matches are exhaustive in F*)");
+    }
+    memcpy(p_dst, p_src, 8U * sizeof (uint32_t));
+    return;
+  }
+  if (scrut.tag == Hacl_Agile_Hash_SHA2_384_a)
+  {
+    uint64_t *p_src = scrut.case_SHA2_384_a;
+    Hacl_Agile_Hash_state_s x1 = *s_dst;
+    uint64_t *p_dst;
+    if (x1.tag == Hacl_Agile_Hash_SHA2_384_a)
+    {
+      p_dst = x1.case_SHA2_384_a;
+    }
+    else
+    {
+      p_dst = KRML_EABORT(uint64_t *, "unreachable (pattern matches are exhaustive in F*)");
+    }
+    memcpy(p_dst, p_src, 8U * sizeof (uint64_t));
+    return;
+  }
+  if (scrut.tag == Hacl_Agile_Hash_SHA2_512_a)
+  {
+    uint64_t *p_src = scrut.case_SHA2_512_a;
+    Hacl_Agile_Hash_state_s x1 = *s_dst;
+    uint64_t *p_dst;
+    if (x1.tag == Hacl_Agile_Hash_SHA2_512_a)
+    {
+      p_dst = x1.case_SHA2_512_a;
+    }
+    else
+    {
+      p_dst = KRML_EABORT(uint64_t *, "unreachable (pattern matches are exhaustive in F*)");
+    }
+    memcpy(p_dst, p_src, 8U * sizeof (uint64_t));
+    return;
+  }
+  if (scrut.tag == Hacl_Agile_Hash_SHA3_224_a)
+  {
+    uint64_t *p_src = scrut.case_SHA3_224_a;
+    Hacl_Agile_Hash_state_s x1 = *s_dst;
+    uint64_t *p_dst;
+    if (x1.tag == Hacl_Agile_Hash_SHA3_224_a)
+    {
+      p_dst = x1.case_SHA3_224_a;
+    }
+    else
+    {
+      p_dst = KRML_EABORT(uint64_t *, "unreachable (pattern matches are exhaustive in F*)");
+    }
+    memcpy(p_dst, p_src, 25U * sizeof (uint64_t));
+    return;
+  }
+  if (scrut.tag == Hacl_Agile_Hash_SHA3_256_a)
+  {
+    uint64_t *p_src = scrut.case_SHA3_256_a;
+    Hacl_Agile_Hash_state_s x1 = *s_dst;
+    uint64_t *p_dst;
+    if (x1.tag == Hacl_Agile_Hash_SHA3_256_a)
+    {
+      p_dst = x1.case_SHA3_256_a;
+    }
+    else
+    {
+      p_dst = KRML_EABORT(uint64_t *, "unreachable (pattern matches are exhaustive in F*)");
+    }
+    memcpy(p_dst, p_src, 25U * sizeof (uint64_t));
+    return;
+  }
+  if (scrut.tag == Hacl_Agile_Hash_SHA3_384_a)
+  {
+    uint64_t *p_src = scrut.case_SHA3_384_a;
+    Hacl_Agile_Hash_state_s x1 = *s_dst;
+    uint64_t *p_dst;
+    if (x1.tag == Hacl_Agile_Hash_SHA3_384_a)
+    {
+      p_dst = x1.case_SHA3_384_a;
+    }
+    else
+    {
+      p_dst = KRML_EABORT(uint64_t *, "unreachable (pattern matches are exhaustive in F*)");
+    }
+    memcpy(p_dst, p_src, 25U * sizeof (uint64_t));
+    return;
+  }
+  if (scrut.tag == Hacl_Agile_Hash_SHA3_512_a)
+  {
+    uint64_t *p_src = scrut.case_SHA3_512_a;
+    Hacl_Agile_Hash_state_s x1 = *s_dst;
+    uint64_t *p_dst;
+    if (x1.tag == Hacl_Agile_Hash_SHA3_512_a)
+    {
+      p_dst = x1.case_SHA3_512_a;
+    }
+    else
+    {
+      p_dst = KRML_EABORT(uint64_t *, "unreachable (pattern matches are exhaustive in F*)");
+    }
+    memcpy(p_dst, p_src, 25U * sizeof (uint64_t));
+    return;
+  }
+  if (scrut.tag == Hacl_Agile_Hash_Blake2S_a)
+  {
+    uint32_t *p_src = scrut.case_Blake2S_a;
+    Hacl_Agile_Hash_state_s x1 = *s_dst;
+    uint32_t *p_dst;
+    if (x1.tag == Hacl_Agile_Hash_Blake2S_a)
+    {
+      p_dst = x1.case_Blake2S_a;
+    }
+    else
+    {
+      p_dst = KRML_EABORT(uint32_t *, "unreachable (pattern matches are exhaustive in F*)");
+    }
+    memcpy(p_dst, p_src, 16U * sizeof (uint32_t));
+    return;
+  }
+  if (scrut.tag == Hacl_Agile_Hash_Blake2S_128_a)
+  {
+    Lib_IntVector_Intrinsics_vec128 *p_src = scrut.case_Blake2S_128_a;
+    KRML_MAYBE_UNUSED_VAR(p_src);
+    #if HACL_CAN_COMPILE_VEC128
+    Hacl_Agile_Hash_state_s x1 = *s_dst;
+    Lib_IntVector_Intrinsics_vec128 *p_dst;
+    if (x1.tag == Hacl_Agile_Hash_Blake2S_128_a)
+    {
+      p_dst = x1.case_Blake2S_128_a;
+    }
+    else
+    {
+      p_dst =
+        KRML_EABORT(Lib_IntVector_Intrinsics_vec128 *,
+          "unreachable (pattern matches are exhaustive in F*)");
+    }
+    Hacl_Hash_Blake2s_Simd128_copy_internal_state(p_src, p_dst);
+    return;
+    #else
+    return;
+    #endif
+  }
+  if (scrut.tag == Hacl_Agile_Hash_Blake2B_a)
+  {
+    uint64_t *p_src = scrut.case_Blake2B_a;
+    Hacl_Agile_Hash_state_s x1 = *s_dst;
+    uint64_t *p_dst;
+    if (x1.tag == Hacl_Agile_Hash_Blake2B_a)
+    {
+      p_dst = x1.case_Blake2B_a;
+    }
+    else
+    {
+      p_dst = KRML_EABORT(uint64_t *, "unreachable (pattern matches are exhaustive in F*)");
+    }
+    memcpy(p_dst, p_src, 16U * sizeof (uint64_t));
+    return;
+  }
+  if (scrut.tag == Hacl_Agile_Hash_Blake2B_256_a)
+  {
+    Lib_IntVector_Intrinsics_vec256 *p_src = scrut.case_Blake2B_256_a;
+    KRML_MAYBE_UNUSED_VAR(p_src);
+    #if HACL_CAN_COMPILE_VEC256
+    Hacl_Agile_Hash_state_s x1 = *s_dst;
+    Lib_IntVector_Intrinsics_vec256 *p_dst;
+    if (x1.tag == Hacl_Agile_Hash_Blake2B_256_a)
+    {
+      p_dst = x1.case_Blake2B_256_a;
+    }
+    else
+    {
+      p_dst =
+        KRML_EABORT(Lib_IntVector_Intrinsics_vec256 *,
+          "unreachable (pattern matches are exhaustive in F*)");
+    }
+    Hacl_Hash_Blake2b_Simd256_copy_internal_state(p_src, p_dst);
+    return;
+    #else
+    return;
+    #endif
+  }
+  KRML_HOST_EPRINTF("KaRaMeL abort at %s:%d\n%s\n",
+    __FILE__,
+    __LINE__,
+    "unreachable (pattern matches are exhaustive in F*)");
+  KRML_HOST_EXIT(255U);
+}
+
+static void hash(Hacl_Agile_Hash_impl i, uint8_t *dst, uint8_t *input, uint32_t input_len)
+{
+  switch (i)
+  {
+    case Hacl_Agile_Hash_MD5:
+      {
+        Hacl_Hash_MD5_hash_oneshot(dst, input, input_len);
+        break;
+      }
+    case Hacl_Agile_Hash_SHA1:
+      {
+        Hacl_Hash_SHA1_hash_oneshot(dst, input, input_len);
+        break;
+      }
+    case Hacl_Agile_Hash_SHA2_224:
+      {
+        Hacl_Hash_SHA2_hash_224(dst, input, input_len);
+        break;
+      }
+    case Hacl_Agile_Hash_SHA2_256:
+      {
+        Hacl_Hash_SHA2_hash_256(dst, input, input_len);
+        break;
+      }
+    case Hacl_Agile_Hash_SHA2_384:
+      {
+        Hacl_Hash_SHA2_hash_384(dst, input, input_len);
+        break;
+      }
+    case Hacl_Agile_Hash_SHA2_512:
+      {
+        Hacl_Hash_SHA2_hash_512(dst, input, input_len);
+        break;
+      }
+    case Hacl_Agile_Hash_SHA3_224:
+      {
+        Hacl_Hash_SHA3_sha3_224(dst, input, input_len);
+        break;
+      }
+    case Hacl_Agile_Hash_SHA3_256:
+      {
+        Hacl_Hash_SHA3_sha3_256(dst, input, input_len);
+        break;
+      }
+    case Hacl_Agile_Hash_SHA3_384:
+      {
+        Hacl_Hash_SHA3_sha3_384(dst, input, input_len);
+        break;
+      }
+    case Hacl_Agile_Hash_SHA3_512:
+      {
+        Hacl_Hash_SHA3_sha3_512(dst, input, input_len);
+        break;
+      }
+    case Hacl_Agile_Hash_Blake2S_32:
+      {
+        Hacl_Hash_Blake2s_hash_with_key(dst, 32U, input, input_len, NULL, 0U);
+        break;
+      }
+    case Hacl_Agile_Hash_Blake2S_128:
+      {
+        #if HACL_CAN_COMPILE_VEC128
+        Hacl_Hash_Blake2s_Simd128_hash_with_key(dst, 32U, input, input_len, NULL, 0U);
+        #endif
+        break;
+      }
+    case Hacl_Agile_Hash_Blake2B_32:
+      {
+        Hacl_Hash_Blake2b_hash_with_key(dst, 64U, input, input_len, NULL, 0U);
+        break;
+      }
+    case Hacl_Agile_Hash_Blake2B_256:
+      {
+        #if HACL_CAN_COMPILE_VEC256
+        Hacl_Hash_Blake2b_Simd256_hash_with_key(dst, 64U, input, input_len, NULL, 0U);
+        #endif
+        break;
+      }
+    default:
+      {
+        KRML_HOST_EPRINTF("KaRaMeL incomplete match at %s:%d\n", __FILE__, __LINE__);
+        KRML_HOST_EXIT(253U);
+      }
+  }
+}
+
+static uint32_t hash_len(Spec_Hash_Definitions_hash_alg a)
+{
+  switch (a)
+  {
+    case Spec_Hash_Definitions_MD5:
+      {
+        return 16U;
+      }
+    case Spec_Hash_Definitions_SHA1:
+      {
+        return 20U;
+      }
+    case Spec_Hash_Definitions_SHA2_224:
+      {
+        return 28U;
+      }
+    case Spec_Hash_Definitions_SHA2_256:
+      {
+        return 32U;
+      }
+    case Spec_Hash_Definitions_SHA2_384:
+      {
+        return 48U;
+      }
+    case Spec_Hash_Definitions_SHA2_512:
+      {
+        return 64U;
+      }
+    case Spec_Hash_Definitions_Blake2S:
+      {
+        return 32U;
+      }
+    case Spec_Hash_Definitions_Blake2B:
+      {
+        return 64U;
+      }
+    case Spec_Hash_Definitions_SHA3_224:
+      {
+        return 28U;
+      }
+    case Spec_Hash_Definitions_SHA3_256:
+      {
+        return 32U;
+      }
+    case Spec_Hash_Definitions_SHA3_384:
+      {
+        return 48U;
+      }
+    case Spec_Hash_Definitions_SHA3_512:
+      {
+        return 64U;
+      }
+    default:
+      {
+        KRML_HOST_EPRINTF("KaRaMeL incomplete match at %s:%d\n", __FILE__, __LINE__);
+        KRML_HOST_EXIT(253U);
+      }
+  }
+}
+
+static uint32_t block_len(Spec_Hash_Definitions_hash_alg a)
+{
+  switch (a)
+  {
+    case Spec_Hash_Definitions_MD5:
+      {
+        return 64U;
+      }
+    case Spec_Hash_Definitions_SHA1:
+      {
+        return 64U;
+      }
+    case Spec_Hash_Definitions_SHA2_224:
+      {
+        return 64U;
+      }
+    case Spec_Hash_Definitions_SHA2_256:
+      {
+        return 64U;
+      }
+    case Spec_Hash_Definitions_SHA2_384:
+      {
+        return 128U;
+      }
+    case Spec_Hash_Definitions_SHA2_512:
+      {
+        return 128U;
+      }
+    case Spec_Hash_Definitions_SHA3_224:
+      {
+        return 144U;
+      }
+    case Spec_Hash_Definitions_SHA3_256:
+      {
+        return 136U;
+      }
+    case Spec_Hash_Definitions_SHA3_384:
+      {
+        return 104U;
+      }
+    case Spec_Hash_Definitions_SHA3_512:
+      {
+        return 72U;
+      }
+    case Spec_Hash_Definitions_Shake128:
+      {
+        return 168U;
+      }
+    case Spec_Hash_Definitions_Shake256:
+      {
+        return 136U;
+      }
+    case Spec_Hash_Definitions_Blake2S:
+      {
+        return 64U;
+      }
+    case Spec_Hash_Definitions_Blake2B:
+      {
+        return 128U;
+      }
+    default:
+      {
+        KRML_HOST_EPRINTF("KaRaMeL incomplete match at %s:%d\n", __FILE__, __LINE__);
+        KRML_HOST_EXIT(253U);
+      }
+  }
+}
+
+static uint64_t max_input_len64(Spec_Hash_Definitions_hash_alg a)
+{
+  switch (a)
+  {
+    case Spec_Hash_Definitions_MD5:
+      {
+        return 2305843009213693951ULL;
+      }
+    case Spec_Hash_Definitions_SHA1:
+      {
+        return 2305843009213693951ULL;
+      }
+    case Spec_Hash_Definitions_SHA2_224:
+      {
+        return 2305843009213693951ULL;
+      }
+    case Spec_Hash_Definitions_SHA2_256:
+      {
+        return 2305843009213693951ULL;
+      }
+    case Spec_Hash_Definitions_SHA2_384:
+      {
+        return 18446744073709551615ULL;
+      }
+    case Spec_Hash_Definitions_SHA2_512:
+      {
+        return 18446744073709551615ULL;
+      }
+    case Spec_Hash_Definitions_Blake2S:
+      {
+        return 18446744073709551615ULL;
+      }
+    case Spec_Hash_Definitions_Blake2B:
+      {
+        return 18446744073709551615ULL;
+      }
+    case Spec_Hash_Definitions_SHA3_224:
+      {
+        return 18446744073709551615ULL;
+      }
+    case Spec_Hash_Definitions_SHA3_256:
+      {
+        return 18446744073709551615ULL;
+      }
+    case Spec_Hash_Definitions_SHA3_384:
+      {
+        return 18446744073709551615ULL;
+      }
+    case Spec_Hash_Definitions_SHA3_512:
+      {
+        return 18446744073709551615ULL;
+      }
+    case Spec_Hash_Definitions_Shake128:
+      {
+        return 18446744073709551615ULL;
+      }
+    case Spec_Hash_Definitions_Shake256:
+      {
+        return 18446744073709551615ULL;
+      }
+    default:
+      {
+        KRML_HOST_EPRINTF("KaRaMeL incomplete match at %s:%d\n", __FILE__, __LINE__);
+        KRML_HOST_EXIT(253U);
+      }
+  }
+}
+
+static void wrap_key(Hacl_Agile_Hash_impl impl, uint8_t *output, uint8_t *key, uint32_t len)
+{
+  uint8_t *nkey = output;
+  uint32_t ite;
+  if (len <= block_len(alg_of_impl(impl)))
+  {
+    ite = len;
+  }
+  else
+  {
+    ite = hash_len(alg_of_impl(impl));
+  }
+  uint8_t *zeroes = output + ite;
+  KRML_MAYBE_UNUSED_VAR(zeroes);
+  if (len <= block_len(alg_of_impl(impl)))
+  {
+    if (len > 0U)
+    {
+      memcpy(nkey, key, len * sizeof (uint8_t));
+      return;
+    }
+    return;
+  }
+  hash(impl, nkey, key, len);
+}
+
+static void init0(uint8_t *k, uint8_t *buf, Hacl_Streaming_HMAC_Definitions_two_state s)
+{
+  uint32_t k_len = s.fst;
+  Hacl_Agile_Hash_state_s *s1 = s.snd;
+  Hacl_Agile_Hash_state_s *s2 = s.thd;
+  init(s1);
+  init(s2);
+  Hacl_Agile_Hash_impl i1 = impl_of_state(s1);
+  Spec_Hash_Definitions_hash_alg a = alg_of_impl(i1);
+  uint8_t b0[168U] = { 0U };
+  uint8_t *block = b0;
+  wrap_key(i1, block, k, k_len);
+  uint8_t b1[168U];
+  memset(b1, 0x36U, 168U * sizeof (uint8_t));
+  uint8_t *ipad = b1;
+  uint8_t b[168U];
+  memset(b, 0x5cU, 168U * sizeof (uint8_t));
+  uint8_t *opad = b;
+  for (uint32_t i = 0U; i < block_len(a); i++)
+  {
+    uint8_t xi = ipad[i];
+    uint8_t yi = block[i];
+    buf[i] = (uint32_t)xi ^ (uint32_t)yi;
+  }
+  for (uint32_t i = 0U; i < block_len(a); i++)
+  {
+    uint8_t xi = opad[i];
+    uint8_t yi = block[i];
+    opad[i] = (uint32_t)xi ^ (uint32_t)yi;
+  }
+  update_multi(s2, 0ULL, opad, block_len(a));
+}
+
+static void finish0(Hacl_Streaming_HMAC_Definitions_two_state s, uint8_t *dst)
+{
+  Hacl_Agile_Hash_state_s *s2 = s.thd;
+  Hacl_Agile_Hash_state_s *s1 = s.snd;
+  Hacl_Agile_Hash_impl i1 = impl_of_state(s1);
+  Spec_Hash_Definitions_hash_alg a = alg_of_impl(i1);
+  finish(s1, dst);
+  update_last(s2, (uint64_t)block_len(a), dst, hash_len(a));
+  finish(s2, dst);
+}
+
+Hacl_Agile_Hash_state_s
+*Hacl_Streaming_HMAC_s1(
+  Hacl_Streaming_HMAC_Definitions_index i,
+  Hacl_Streaming_HMAC_Definitions_two_state s
+)
+{
+  KRML_MAYBE_UNUSED_VAR(i);
+  return s.snd;
+}
+
+Hacl_Agile_Hash_state_s
+*Hacl_Streaming_HMAC_s2(
+  Hacl_Streaming_HMAC_Definitions_index i,
+  Hacl_Streaming_HMAC_Definitions_two_state s
+)
+{
+  KRML_MAYBE_UNUSED_VAR(i);
+  return s.thd;
+}
+
+Hacl_Streaming_HMAC_Definitions_index
+Hacl_Streaming_HMAC_index_of_state(Hacl_Streaming_HMAC_Definitions_two_state s)
+{
+  Hacl_Agile_Hash_state_s *s11 = s.snd;
+  uint32_t kl = s.fst;
+  Hacl_Agile_Hash_impl i1 = impl_of_state(s11);
+  return ((Hacl_Streaming_HMAC_Definitions_index){ .fst = i1, .snd = kl });
+}
+
+static Hacl_Agile_Hash_impl
+__proj__Mkdtuple2__item___1__Hacl_Agile_Hash_impl_uint32_t(
+  Hacl_Streaming_HMAC_Definitions_index pair
+)
+{
+  return pair.fst;
+}
+
+static Hacl_Agile_Hash_impl
+dfst__Hacl_Agile_Hash_impl_uint32_t(Hacl_Streaming_HMAC_Definitions_index t)
+{
+  return __proj__Mkdtuple2__item___1__Hacl_Agile_Hash_impl_uint32_t(t);
+}
+
+static uint32_t
+__proj__Mkdtuple2__item___2__Hacl_Agile_Hash_impl_uint32_t(
+  Hacl_Streaming_HMAC_Definitions_index pair
+)
+{
+  return pair.snd;
+}
+
+static uint32_t dsnd__Hacl_Agile_Hash_impl_uint32_t(Hacl_Streaming_HMAC_Definitions_index t)
+{
+  return __proj__Mkdtuple2__item___2__Hacl_Agile_Hash_impl_uint32_t(t);
+}
+
+typedef struct option___uint32_t____Hacl_Agile_Hash_state_s_____Hacl_Agile_Hash_state_s___s
+{
+  Hacl_Streaming_Types_optional tag;
+  Hacl_Streaming_HMAC_Definitions_two_state v;
+}
+option___uint32_t____Hacl_Agile_Hash_state_s_____Hacl_Agile_Hash_state_s__;
+
+KRML_MAYBE_UNUSED static Hacl_Streaming_HMAC_agile_state
+*malloc_internal(Hacl_Streaming_HMAC_Definitions_index i, uint8_t *key)
+{
+  KRML_CHECK_SIZE(sizeof (uint8_t),
+    block_len(alg_of_impl(dfst__Hacl_Agile_Hash_impl_uint32_t(i))));
+  uint8_t
+  *buf =
+    (uint8_t *)KRML_HOST_CALLOC(block_len(alg_of_impl(dfst__Hacl_Agile_Hash_impl_uint32_t(i))),
+      sizeof (uint8_t));
+  if (buf == NULL)
+  {
+    return NULL;
+  }
+  uint8_t *buf1 = buf;
+  Hacl_Agile_Hash_state_s *s110 = malloc_(dfst__Hacl_Agile_Hash_impl_uint32_t(i));
+  option___uint32_t____Hacl_Agile_Hash_state_s_____Hacl_Agile_Hash_state_s__ block_state;
+  if (s110 == NULL)
+  {
+    block_state =
+      (
+        (option___uint32_t____Hacl_Agile_Hash_state_s_____Hacl_Agile_Hash_state_s__){
+          .tag = Hacl_Streaming_Types_None
+        }
+      );
+  }
+  else
+  {
+    Hacl_Agile_Hash_state_s *s21 = malloc_(dfst__Hacl_Agile_Hash_impl_uint32_t(i));
+    if (s21 == NULL)
+    {
+      KRML_HOST_FREE(s110);
+      block_state =
+        (
+          (option___uint32_t____Hacl_Agile_Hash_state_s_____Hacl_Agile_Hash_state_s__){
+            .tag = Hacl_Streaming_Types_None
+          }
+        );
+    }
+    else
+    {
+      block_state =
+        (
+          (option___uint32_t____Hacl_Agile_Hash_state_s_____Hacl_Agile_Hash_state_s__){
+            .tag = Hacl_Streaming_Types_Some,
+            .v = { .fst = dsnd__Hacl_Agile_Hash_impl_uint32_t(i), .snd = s110, .thd = s21 }
+          }
+        );
+    }
+  }
+  if (block_state.tag == Hacl_Streaming_Types_None)
+  {
+    KRML_HOST_FREE(buf1);
+    return NULL;
+  }
+  if (block_state.tag == Hacl_Streaming_Types_Some)
+  {
+    Hacl_Streaming_HMAC_Definitions_two_state block_state1 = block_state.v;
+    Hacl_Streaming_Types_optional k_ = Hacl_Streaming_Types_Some;
+    switch (k_)
+    {
+      case Hacl_Streaming_Types_None:
+        {
+          return NULL;
+        }
+      case Hacl_Streaming_Types_Some:
+        {
+          Hacl_Streaming_HMAC_agile_state
+          s =
+            {
+              .block_state = block_state1,
+              .buf = buf1,
+              .total_len = (uint64_t)block_len(alg_of_impl(dfst__Hacl_Agile_Hash_impl_uint32_t(i)))
+            };
+          Hacl_Streaming_HMAC_agile_state
+          *p =
+            (Hacl_Streaming_HMAC_agile_state *)KRML_HOST_MALLOC(sizeof (
+                Hacl_Streaming_HMAC_agile_state
+              ));
+          if (p != NULL)
+          {
+            p[0U] = s;
+          }
+          if (p == NULL)
+          {
+            Hacl_Agile_Hash_state_s *s21 = block_state1.thd;
+            Hacl_Agile_Hash_state_s *s11 = block_state1.snd;
+            free_(s11);
+            free_(s21);
+            KRML_HOST_FREE(buf1);
+            return NULL;
+          }
+          init0(key, buf1, block_state1);
+          return p;
+        }
+      default:
+        {
+          KRML_HOST_EPRINTF("KaRaMeL incomplete match at %s:%d\n", __FILE__, __LINE__);
+          KRML_HOST_EXIT(253U);
+        }
+    }
+  }
+  KRML_HOST_EPRINTF("KaRaMeL abort at %s:%d\n%s\n",
+    __FILE__,
+    __LINE__,
+    "unreachable (pattern matches are exhaustive in F*)");
+  KRML_HOST_EXIT(255U);
+}
+
+KRML_MAYBE_UNUSED static bool is_blake2b_256(Hacl_Agile_Hash_impl uu___)
+{
+  switch (uu___)
+  {
+    case Hacl_Agile_Hash_Blake2B_256:
+      {
+        return true;
+      }
+    default:
+      {
+        return false;
+      }
+  }
+}
+
+KRML_MAYBE_UNUSED static bool is_blake2s_128(Hacl_Agile_Hash_impl uu___)
+{
+  switch (uu___)
+  {
+    case Hacl_Agile_Hash_Blake2S_128:
+      {
+        return true;
+      }
+    default:
+      {
+        return false;
+      }
+  }
+}
+
+Hacl_Streaming_Types_error_code
+Hacl_Streaming_HMAC_malloc_(
+  Hacl_Agile_Hash_impl impl,
+  uint8_t *key,
+  uint32_t key_length,
+  Hacl_Streaming_HMAC_agile_state **dst
+)
+{
+  KRML_MAYBE_UNUSED_VAR(key);
+  KRML_MAYBE_UNUSED_VAR(key_length);
+  KRML_MAYBE_UNUSED_VAR(dst);
+  #if !HACL_CAN_COMPILE_VEC256
+  if (is_blake2b_256(impl))
+  {
+    return Hacl_Streaming_Types_InvalidAlgorithm;
+  }
+  #endif
+  #if !HACL_CAN_COMPILE_VEC128
+  if (is_blake2s_128(impl))
+  {
+    return Hacl_Streaming_Types_InvalidAlgorithm;
+  }
+  #endif
+  Hacl_Streaming_HMAC_agile_state
+  *st =
+    malloc_internal(((Hacl_Streaming_HMAC_Definitions_index){ .fst = impl, .snd = key_length }),
+      key);
+  if (st == NULL)
+  {
+    return Hacl_Streaming_Types_OutOfMemory;
+  }
+  *dst = st;
+  return Hacl_Streaming_Types_Success;
+}
+
+Hacl_Streaming_HMAC_Definitions_index
+Hacl_Streaming_HMAC_get_impl(Hacl_Streaming_HMAC_agile_state *s)
+{
+  Hacl_Streaming_HMAC_Definitions_two_state block_state = (*s).block_state;
+  return Hacl_Streaming_HMAC_index_of_state(block_state);
+}
+
+static void reset_internal(Hacl_Streaming_HMAC_agile_state *state, uint8_t *key)
+{
+  Hacl_Streaming_HMAC_agile_state scrut = *state;
+  uint8_t *buf = scrut.buf;
+  Hacl_Streaming_HMAC_Definitions_two_state block_state = scrut.block_state;
+  Hacl_Streaming_HMAC_Definitions_index i1 = Hacl_Streaming_HMAC_index_of_state(block_state);
+  KRML_MAYBE_UNUSED_VAR(i1);
+  init0(key, buf, block_state);
+  Hacl_Streaming_HMAC_agile_state
+  tmp =
+    {
+      .block_state = block_state,
+      .buf = buf,
+      .total_len = (uint64_t)block_len(alg_of_impl(dfst__Hacl_Agile_Hash_impl_uint32_t(i1)))
+    };
+  state[0U] = tmp;
+}
+
+Hacl_Streaming_Types_error_code
+Hacl_Streaming_HMAC_reset(
+  Hacl_Streaming_HMAC_agile_state *state,
+  uint8_t *key,
+  uint32_t key_length
+)
+{
+  uint32_t k_len = Hacl_Streaming_HMAC_get_impl(state).snd;
+  if (key_length != k_len)
+  {
+    return Hacl_Streaming_Types_InvalidLength;
+  }
+  reset_internal(state, key);
+  return Hacl_Streaming_Types_Success;
+}
+
+Hacl_Streaming_Types_error_code
+Hacl_Streaming_HMAC_update(
+  Hacl_Streaming_HMAC_agile_state *state,
+  uint8_t *chunk,
+  uint32_t chunk_len
+)
+{
+  Hacl_Streaming_HMAC_agile_state s = *state;
+  Hacl_Streaming_HMAC_Definitions_two_state block_state = s.block_state;
+  uint64_t total_len = s.total_len;
+  Hacl_Streaming_HMAC_Definitions_index i1 = Hacl_Streaming_HMAC_index_of_state(block_state);
+  if
+  (
+    (uint64_t)chunk_len
+    > max_input_len64(alg_of_impl(dfst__Hacl_Agile_Hash_impl_uint32_t(i1))) - total_len
+  )
+  {
+    return Hacl_Streaming_Types_MaximumLengthExceeded;
+  }
+  uint32_t sz;
+  if
+  (
+    total_len
+    % (uint64_t)block_len(alg_of_impl(dfst__Hacl_Agile_Hash_impl_uint32_t(i1)))
+    == 0ULL
+    && total_len > 0ULL
+  )
+  {
+    sz = block_len(alg_of_impl(dfst__Hacl_Agile_Hash_impl_uint32_t(i1)));
+  }
+  else
+  {
+    sz =
+      (uint32_t)(total_len
+      % (uint64_t)block_len(alg_of_impl(dfst__Hacl_Agile_Hash_impl_uint32_t(i1))));
+  }
+  if (chunk_len <= block_len(alg_of_impl(dfst__Hacl_Agile_Hash_impl_uint32_t(i1))) - sz)
+  {
+    Hacl_Streaming_HMAC_agile_state s3 = *state;
+    Hacl_Streaming_HMAC_Definitions_two_state block_state1 = s3.block_state;
+    uint8_t *buf = s3.buf;
+    uint64_t total_len1 = s3.total_len;
+    uint32_t sz1;
+    if
+    (
+      total_len1
+      % (uint64_t)block_len(alg_of_impl(dfst__Hacl_Agile_Hash_impl_uint32_t(i1)))
+      == 0ULL
+      && total_len1 > 0ULL
+    )
+    {
+      sz1 = block_len(alg_of_impl(dfst__Hacl_Agile_Hash_impl_uint32_t(i1)));
+    }
+    else
+    {
+      sz1 =
+        (uint32_t)(total_len1
+        % (uint64_t)block_len(alg_of_impl(dfst__Hacl_Agile_Hash_impl_uint32_t(i1))));
+    }
+    uint8_t *buf2 = buf + sz1;
+    memcpy(buf2, chunk, chunk_len * sizeof (uint8_t));
+    uint64_t total_len2 = total_len1 + (uint64_t)chunk_len;
+    *state
+    =
+      (
+        (Hacl_Streaming_HMAC_agile_state){
+          .block_state = block_state1,
+          .buf = buf,
+          .total_len = total_len2
+        }
+      );
+  }
+  else if (sz == 0U)
+  {
+    Hacl_Streaming_HMAC_agile_state s3 = *state;
+    Hacl_Streaming_HMAC_Definitions_two_state block_state1 = s3.block_state;
+    uint8_t *buf = s3.buf;
+    uint64_t total_len1 = s3.total_len;
+    uint32_t sz1;
+    if
+    (
+      total_len1
+      % (uint64_t)block_len(alg_of_impl(dfst__Hacl_Agile_Hash_impl_uint32_t(i1)))
+      == 0ULL
+      && total_len1 > 0ULL
+    )
+    {
+      sz1 = block_len(alg_of_impl(dfst__Hacl_Agile_Hash_impl_uint32_t(i1)));
+    }
+    else
+    {
+      sz1 =
+        (uint32_t)(total_len1
+        % (uint64_t)block_len(alg_of_impl(dfst__Hacl_Agile_Hash_impl_uint32_t(i1))));
+    }
+    if (!(sz1 == 0U))
+    {
+      uint64_t prevlen = total_len1 - (uint64_t)sz1;
+      Hacl_Agile_Hash_state_s *s11 = block_state1.snd;
+      update_multi(s11,
+        prevlen,
+        buf,
+        block_len(alg_of_impl(dfst__Hacl_Agile_Hash_impl_uint32_t(i1))));
+    }
+    uint32_t ite;
+    if
+    (
+      (uint64_t)chunk_len
+      % (uint64_t)block_len(alg_of_impl(dfst__Hacl_Agile_Hash_impl_uint32_t(i1)))
+      == 0ULL
+      && (uint64_t)chunk_len > 0ULL
+    )
+    {
+      ite = block_len(alg_of_impl(dfst__Hacl_Agile_Hash_impl_uint32_t(i1)));
+    }
+    else
+    {
+      ite =
+        (uint32_t)((uint64_t)chunk_len
+        % (uint64_t)block_len(alg_of_impl(dfst__Hacl_Agile_Hash_impl_uint32_t(i1))));
+    }
+    uint32_t
+    n_blocks = (chunk_len - ite) / block_len(alg_of_impl(dfst__Hacl_Agile_Hash_impl_uint32_t(i1)));
+    uint32_t
+    data1_len = n_blocks * block_len(alg_of_impl(dfst__Hacl_Agile_Hash_impl_uint32_t(i1)));
+    uint32_t data2_len = chunk_len - data1_len;
+    uint8_t *data1 = chunk;
+    uint8_t *data2 = chunk + data1_len;
+    Hacl_Agile_Hash_state_s *s11 = block_state1.snd;
+    update_multi(s11, total_len1, data1, data1_len);
+    uint8_t *dst = buf;
+    memcpy(dst, data2, data2_len * sizeof (uint8_t));
+    *state
+    =
+      (
+        (Hacl_Streaming_HMAC_agile_state){
+          .block_state = block_state1,
+          .buf = buf,
+          .total_len = total_len1 + (uint64_t)chunk_len
+        }
+      );
+  }
+  else
+  {
+    uint32_t diff = block_len(alg_of_impl(dfst__Hacl_Agile_Hash_impl_uint32_t(i1))) - sz;
+    uint8_t *chunk1 = chunk;
+    uint8_t *chunk2 = chunk + diff;
+    Hacl_Streaming_HMAC_agile_state s3 = *state;
+    Hacl_Streaming_HMAC_Definitions_two_state block_state10 = s3.block_state;
+    uint8_t *buf0 = s3.buf;
+    uint64_t total_len10 = s3.total_len;
+    uint32_t sz10;
+    if
+    (
+      total_len10
+      % (uint64_t)block_len(alg_of_impl(dfst__Hacl_Agile_Hash_impl_uint32_t(i1)))
+      == 0ULL
+      && total_len10 > 0ULL
+    )
+    {
+      sz10 = block_len(alg_of_impl(dfst__Hacl_Agile_Hash_impl_uint32_t(i1)));
+    }
+    else
+    {
+      sz10 =
+        (uint32_t)(total_len10
+        % (uint64_t)block_len(alg_of_impl(dfst__Hacl_Agile_Hash_impl_uint32_t(i1))));
+    }
+    uint8_t *buf2 = buf0 + sz10;
+    memcpy(buf2, chunk1, diff * sizeof (uint8_t));
+    uint64_t total_len2 = total_len10 + (uint64_t)diff;
+    *state
+    =
+      (
+        (Hacl_Streaming_HMAC_agile_state){
+          .block_state = block_state10,
+          .buf = buf0,
+          .total_len = total_len2
+        }
+      );
+    Hacl_Streaming_HMAC_agile_state s30 = *state;
+    Hacl_Streaming_HMAC_Definitions_two_state block_state1 = s30.block_state;
+    uint8_t *buf = s30.buf;
+    uint64_t total_len1 = s30.total_len;
+    uint32_t sz1;
+    if
+    (
+      total_len1
+      % (uint64_t)block_len(alg_of_impl(dfst__Hacl_Agile_Hash_impl_uint32_t(i1)))
+      == 0ULL
+      && total_len1 > 0ULL
+    )
+    {
+      sz1 = block_len(alg_of_impl(dfst__Hacl_Agile_Hash_impl_uint32_t(i1)));
+    }
+    else
+    {
+      sz1 =
+        (uint32_t)(total_len1
+        % (uint64_t)block_len(alg_of_impl(dfst__Hacl_Agile_Hash_impl_uint32_t(i1))));
+    }
+    if (!(sz1 == 0U))
+    {
+      uint64_t prevlen = total_len1 - (uint64_t)sz1;
+      Hacl_Agile_Hash_state_s *s11 = block_state1.snd;
+      update_multi(s11,
+        prevlen,
+        buf,
+        block_len(alg_of_impl(dfst__Hacl_Agile_Hash_impl_uint32_t(i1))));
+    }
+    uint32_t ite;
+    if
+    (
+      (uint64_t)(chunk_len - diff)
+      % (uint64_t)block_len(alg_of_impl(dfst__Hacl_Agile_Hash_impl_uint32_t(i1)))
+      == 0ULL
+      && (uint64_t)(chunk_len - diff) > 0ULL
+    )
+    {
+      ite = block_len(alg_of_impl(dfst__Hacl_Agile_Hash_impl_uint32_t(i1)));
+    }
+    else
+    {
+      ite =
+        (uint32_t)((uint64_t)(chunk_len - diff)
+        % (uint64_t)block_len(alg_of_impl(dfst__Hacl_Agile_Hash_impl_uint32_t(i1))));
+    }
+    uint32_t
+    n_blocks =
+      (chunk_len - diff - ite)
+      / block_len(alg_of_impl(dfst__Hacl_Agile_Hash_impl_uint32_t(i1)));
+    uint32_t
+    data1_len = n_blocks * block_len(alg_of_impl(dfst__Hacl_Agile_Hash_impl_uint32_t(i1)));
+    uint32_t data2_len = chunk_len - diff - data1_len;
+    uint8_t *data1 = chunk2;
+    uint8_t *data2 = chunk2 + data1_len;
+    Hacl_Agile_Hash_state_s *s11 = block_state1.snd;
+    update_multi(s11, total_len1, data1, data1_len);
+    uint8_t *dst = buf;
+    memcpy(dst, data2, data2_len * sizeof (uint8_t));
+    *state
+    =
+      (
+        (Hacl_Streaming_HMAC_agile_state){
+          .block_state = block_state1,
+          .buf = buf,
+          .total_len = total_len1 + (uint64_t)(chunk_len - diff)
+        }
+      );
+  }
+  return Hacl_Streaming_Types_Success;
+}
+
+typedef struct
+___uint32_t____Hacl_Agile_Hash_state_s_____Hacl_Agile_Hash_state_s____uint32_t____Hacl_Agile_Hash_state_s_____Hacl_Agile_Hash_state_s___s
+{
+  Hacl_Streaming_HMAC_Definitions_two_state fst;
+  Hacl_Streaming_HMAC_Definitions_two_state snd;
+}
+___uint32_t____Hacl_Agile_Hash_state_s_____Hacl_Agile_Hash_state_s____uint32_t____Hacl_Agile_Hash_state_s_____Hacl_Agile_Hash_state_s__;
+
+Hacl_Streaming_Types_error_code
+Hacl_Streaming_HMAC_digest(
+  Hacl_Streaming_HMAC_agile_state *state,
+  uint8_t *output,
+  uint32_t digest_length
+)
+{
+  KRML_MAYBE_UNUSED_VAR(digest_length);
+  Hacl_Streaming_HMAC_Definitions_two_state block_state0 = (*state).block_state;
+  Hacl_Streaming_HMAC_Definitions_index i1 = Hacl_Streaming_HMAC_index_of_state(block_state0);
+  Hacl_Streaming_HMAC_agile_state scrut0 = *state;
+  Hacl_Streaming_HMAC_Definitions_two_state block_state = scrut0.block_state;
+  uint8_t *buf_ = scrut0.buf;
+  uint64_t total_len = scrut0.total_len;
+  uint32_t r;
+  if
+  (
+    total_len
+    % (uint64_t)block_len(alg_of_impl(dfst__Hacl_Agile_Hash_impl_uint32_t(i1)))
+    == 0ULL
+    && total_len > 0ULL
+  )
+  {
+    r = block_len(alg_of_impl(dfst__Hacl_Agile_Hash_impl_uint32_t(i1)));
+  }
+  else
+  {
+    r =
+      (uint32_t)(total_len
+      % (uint64_t)block_len(alg_of_impl(dfst__Hacl_Agile_Hash_impl_uint32_t(i1))));
+  }
+  uint8_t *buf_1 = buf_;
+  Hacl_Agile_Hash_state_s *s110 = malloc_(dfst__Hacl_Agile_Hash_impl_uint32_t(i1));
+  option___uint32_t____Hacl_Agile_Hash_state_s_____Hacl_Agile_Hash_state_s__ tmp_block_state;
+  if (s110 == NULL)
+  {
+    tmp_block_state =
+      (
+        (option___uint32_t____Hacl_Agile_Hash_state_s_____Hacl_Agile_Hash_state_s__){
+          .tag = Hacl_Streaming_Types_None
+        }
+      );
+  }
+  else
+  {
+    Hacl_Agile_Hash_state_s *s21 = malloc_(dfst__Hacl_Agile_Hash_impl_uint32_t(i1));
+    if (s21 == NULL)
+    {
+      KRML_HOST_FREE(s110);
+      tmp_block_state =
+        (
+          (option___uint32_t____Hacl_Agile_Hash_state_s_____Hacl_Agile_Hash_state_s__){
+            .tag = Hacl_Streaming_Types_None
+          }
+        );
+    }
+    else
+    {
+      tmp_block_state =
+        (
+          (option___uint32_t____Hacl_Agile_Hash_state_s_____Hacl_Agile_Hash_state_s__){
+            .tag = Hacl_Streaming_Types_Some,
+            .v = { .fst = dsnd__Hacl_Agile_Hash_impl_uint32_t(i1), .snd = s110, .thd = s21 }
+          }
+        );
+    }
+  }
+  if (tmp_block_state.tag == Hacl_Streaming_Types_None)
+  {
+    return Hacl_Streaming_Types_OutOfMemory;
+  }
+  if (tmp_block_state.tag == Hacl_Streaming_Types_Some)
+  {
+    Hacl_Streaming_HMAC_Definitions_two_state tmp_block_state1 = tmp_block_state.v;
+    ___uint32_t____Hacl_Agile_Hash_state_s_____Hacl_Agile_Hash_state_s____uint32_t____Hacl_Agile_Hash_state_s_____Hacl_Agile_Hash_state_s__
+    scrut = { .fst = block_state, .snd = tmp_block_state1 };
+    Hacl_Agile_Hash_state_s *s2_ = scrut.snd.thd;
+    Hacl_Agile_Hash_state_s *s1_ = scrut.snd.snd;
+    Hacl_Agile_Hash_state_s *s21 = scrut.fst.thd;
+    Hacl_Agile_Hash_state_s *s111 = scrut.fst.snd;
+    copy(s111, s1_);
+    copy(s21, s2_);
+    uint64_t prev_len = total_len - (uint64_t)r;
+    uint32_t ite;
+    if (r % block_len(alg_of_impl(dfst__Hacl_Agile_Hash_impl_uint32_t(i1))) == 0U && r > 0U)
+    {
+      ite = block_len(alg_of_impl(dfst__Hacl_Agile_Hash_impl_uint32_t(i1)));
+    }
+    else
+    {
+      ite = r % block_len(alg_of_impl(dfst__Hacl_Agile_Hash_impl_uint32_t(i1)));
+    }
+    uint8_t *buf_last = buf_1 + r - ite;
+    uint8_t *buf_multi = buf_1;
+    Hacl_Agile_Hash_state_s *s112 = tmp_block_state1.snd;
+    update_multi(s112, prev_len, buf_multi, 0U);
+    uint64_t prev_len_last = total_len - (uint64_t)r;
+    Hacl_Agile_Hash_state_s *s11 = tmp_block_state1.snd;
+    update_last(s11, prev_len_last, buf_last, r);
+    finish0(tmp_block_state1, output);
+    return Hacl_Streaming_Types_Success;
+  }
+  KRML_HOST_EPRINTF("KaRaMeL abort at %s:%d\n%s\n",
+    __FILE__,
+    __LINE__,
+    "unreachable (pattern matches are exhaustive in F*)");
+  KRML_HOST_EXIT(255U);
+}
+
+void Hacl_Streaming_HMAC_free(Hacl_Streaming_HMAC_agile_state *state)
+{
+  Hacl_Streaming_HMAC_Definitions_two_state block_state0 = (*state).block_state;
+  Hacl_Streaming_HMAC_Definitions_index i1 = Hacl_Streaming_HMAC_index_of_state(block_state0);
+  KRML_MAYBE_UNUSED_VAR(i1);
+  Hacl_Streaming_HMAC_agile_state scrut = *state;
+  uint8_t *buf = scrut.buf;
+  Hacl_Streaming_HMAC_Definitions_two_state block_state = scrut.block_state;
+  Hacl_Agile_Hash_state_s *s21 = block_state.thd;
+  Hacl_Agile_Hash_state_s *s11 = block_state.snd;
+  free_(s11);
+  free_(s21);
+  KRML_HOST_FREE(buf);
+  KRML_HOST_FREE(state);
+}
+
+Hacl_Streaming_HMAC_agile_state
+*Hacl_Streaming_HMAC_copy(Hacl_Streaming_HMAC_agile_state *state)
+{
+  Hacl_Streaming_HMAC_agile_state scrut0 = *state;
+  Hacl_Streaming_HMAC_Definitions_two_state block_state0 = scrut0.block_state;
+  uint8_t *buf0 = scrut0.buf;
+  uint64_t total_len0 = scrut0.total_len;
+  Hacl_Streaming_HMAC_Definitions_index i1 = Hacl_Streaming_HMAC_index_of_state(block_state0);
+  KRML_CHECK_SIZE(sizeof (uint8_t),
+    block_len(alg_of_impl(dfst__Hacl_Agile_Hash_impl_uint32_t(i1))));
+  uint8_t
+  *buf =
+    (uint8_t *)KRML_HOST_CALLOC(block_len(alg_of_impl(dfst__Hacl_Agile_Hash_impl_uint32_t(i1))),
+      sizeof (uint8_t));
+  if (buf == NULL)
+  {
+    return NULL;
+  }
+  memcpy(buf,
+    buf0,
+    block_len(alg_of_impl(dfst__Hacl_Agile_Hash_impl_uint32_t(i1))) * sizeof (uint8_t));
+  Hacl_Agile_Hash_state_s *s110 = malloc_(dfst__Hacl_Agile_Hash_impl_uint32_t(i1));
+  option___uint32_t____Hacl_Agile_Hash_state_s_____Hacl_Agile_Hash_state_s__ block_state;
+  if (s110 == NULL)
+  {
+    block_state =
+      (
+        (option___uint32_t____Hacl_Agile_Hash_state_s_____Hacl_Agile_Hash_state_s__){
+          .tag = Hacl_Streaming_Types_None
+        }
+      );
+  }
+  else
+  {
+    Hacl_Agile_Hash_state_s *s21 = malloc_(dfst__Hacl_Agile_Hash_impl_uint32_t(i1));
+    if (s21 == NULL)
+    {
+      KRML_HOST_FREE(s110);
+      block_state =
+        (
+          (option___uint32_t____Hacl_Agile_Hash_state_s_____Hacl_Agile_Hash_state_s__){
+            .tag = Hacl_Streaming_Types_None
+          }
+        );
+    }
+    else
+    {
+      block_state =
+        (
+          (option___uint32_t____Hacl_Agile_Hash_state_s_____Hacl_Agile_Hash_state_s__){
+            .tag = Hacl_Streaming_Types_Some,
+            .v = { .fst = dsnd__Hacl_Agile_Hash_impl_uint32_t(i1), .snd = s110, .thd = s21 }
+          }
+        );
+    }
+  }
+  if (block_state.tag == Hacl_Streaming_Types_None)
+  {
+    KRML_HOST_FREE(buf);
+    return NULL;
+  }
+  if (block_state.tag == Hacl_Streaming_Types_Some)
+  {
+    Hacl_Streaming_HMAC_Definitions_two_state block_state1 = block_state.v;
+    ___uint32_t____Hacl_Agile_Hash_state_s_____Hacl_Agile_Hash_state_s____uint32_t____Hacl_Agile_Hash_state_s_____Hacl_Agile_Hash_state_s__
+    scrut = { .fst = block_state0, .snd = block_state1 };
+    Hacl_Agile_Hash_state_s *s2_ = scrut.snd.thd;
+    Hacl_Agile_Hash_state_s *s1_ = scrut.snd.snd;
+    Hacl_Agile_Hash_state_s *s21 = scrut.fst.thd;
+    Hacl_Agile_Hash_state_s *s111 = scrut.fst.snd;
+    copy(s111, s1_);
+    copy(s21, s2_);
+    Hacl_Streaming_Types_optional k_ = Hacl_Streaming_Types_Some;
+    switch (k_)
+    {
+      case Hacl_Streaming_Types_None:
+        {
+          return NULL;
+        }
+      case Hacl_Streaming_Types_Some:
+        {
+          Hacl_Streaming_HMAC_agile_state
+          s = { .block_state = block_state1, .buf = buf, .total_len = total_len0 };
+          Hacl_Streaming_HMAC_agile_state
+          *p =
+            (Hacl_Streaming_HMAC_agile_state *)KRML_HOST_MALLOC(sizeof (
+                Hacl_Streaming_HMAC_agile_state
+              ));
+          if (p != NULL)
+          {
+            p[0U] = s;
+          }
+          if (p == NULL)
+          {
+            Hacl_Agile_Hash_state_s *s210 = block_state1.thd;
+            Hacl_Agile_Hash_state_s *s11 = block_state1.snd;
+            free_(s11);
+            free_(s210);
+            KRML_HOST_FREE(buf);
+            return NULL;
+          }
+          return p;
+        }
+      default:
+        {
+          KRML_HOST_EPRINTF("KaRaMeL incomplete match at %s:%d\n", __FILE__, __LINE__);
+          KRML_HOST_EXIT(253U);
+        }
+    }
+  }
+  KRML_HOST_EPRINTF("KaRaMeL abort at %s:%d\n%s\n",
+    __FILE__,
+    __LINE__,
+    "unreachable (pattern matches are exhaustive in F*)");
+  KRML_HOST_EXIT(255U);
+}
+
diff --git a/Modules/_hacl/Hacl_Streaming_HMAC.h b/Modules/_hacl/Hacl_Streaming_HMAC.h
new file mode 100644 (file)
index 0000000..a0806c0
--- /dev/null
@@ -0,0 +1,134 @@
+/* MIT License
+ *
+ * Copyright (c) 2016-2022 INRIA, CMU and Microsoft Corporation
+ * Copyright (c) 2022-2023 HACL* Contributors
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+
+#ifndef __Hacl_Streaming_HMAC_H
+#define __Hacl_Streaming_HMAC_H
+
+#if defined(__cplusplus)
+extern "C" {
+#endif
+
+#include <string.h>
+#include "python_hacl_namespaces.h"
+#include "krml/internal/types.h"
+#include "krml/lowstar_endianness.h"
+#include "krml/internal/target.h"
+
+#include "Hacl_Streaming_Types.h"
+
+#define Hacl_Agile_Hash_MD5 0
+#define Hacl_Agile_Hash_SHA1 1
+#define Hacl_Agile_Hash_SHA2_224 2
+#define Hacl_Agile_Hash_SHA2_256 3
+#define Hacl_Agile_Hash_SHA2_384 4
+#define Hacl_Agile_Hash_SHA2_512 5
+#define Hacl_Agile_Hash_SHA3_224 6
+#define Hacl_Agile_Hash_SHA3_256 7
+#define Hacl_Agile_Hash_SHA3_384 8
+#define Hacl_Agile_Hash_SHA3_512 9
+#define Hacl_Agile_Hash_Blake2S_32 10
+#define Hacl_Agile_Hash_Blake2S_128 11
+#define Hacl_Agile_Hash_Blake2B_32 12
+#define Hacl_Agile_Hash_Blake2B_256 13
+
+typedef uint8_t Hacl_Agile_Hash_impl;
+
+typedef struct Hacl_Agile_Hash_state_s_s Hacl_Agile_Hash_state_s;
+
+typedef struct Hacl_Streaming_HMAC_Definitions_index_s
+{
+  Hacl_Agile_Hash_impl fst;
+  uint32_t snd;
+}
+Hacl_Streaming_HMAC_Definitions_index;
+
+typedef struct Hacl_Streaming_HMAC_Definitions_two_state_s
+{
+  uint32_t fst;
+  Hacl_Agile_Hash_state_s *snd;
+  Hacl_Agile_Hash_state_s *thd;
+}
+Hacl_Streaming_HMAC_Definitions_two_state;
+
+Hacl_Agile_Hash_state_s
+*Hacl_Streaming_HMAC_s1(
+  Hacl_Streaming_HMAC_Definitions_index i,
+  Hacl_Streaming_HMAC_Definitions_two_state s
+);
+
+Hacl_Agile_Hash_state_s
+*Hacl_Streaming_HMAC_s2(
+  Hacl_Streaming_HMAC_Definitions_index i,
+  Hacl_Streaming_HMAC_Definitions_two_state s
+);
+
+Hacl_Streaming_HMAC_Definitions_index
+Hacl_Streaming_HMAC_index_of_state(Hacl_Streaming_HMAC_Definitions_two_state s);
+
+typedef struct Hacl_Streaming_HMAC_agile_state_s Hacl_Streaming_HMAC_agile_state;
+
+Hacl_Streaming_Types_error_code
+Hacl_Streaming_HMAC_malloc_(
+  Hacl_Agile_Hash_impl impl,
+  uint8_t *key,
+  uint32_t key_length,
+  Hacl_Streaming_HMAC_agile_state **dst
+);
+
+Hacl_Streaming_HMAC_Definitions_index
+Hacl_Streaming_HMAC_get_impl(Hacl_Streaming_HMAC_agile_state *s);
+
+Hacl_Streaming_Types_error_code
+Hacl_Streaming_HMAC_reset(
+  Hacl_Streaming_HMAC_agile_state *state,
+  uint8_t *key,
+  uint32_t key_length
+);
+
+Hacl_Streaming_Types_error_code
+Hacl_Streaming_HMAC_update(
+  Hacl_Streaming_HMAC_agile_state *state,
+  uint8_t *chunk,
+  uint32_t chunk_len
+);
+
+Hacl_Streaming_Types_error_code
+Hacl_Streaming_HMAC_digest(
+  Hacl_Streaming_HMAC_agile_state *state,
+  uint8_t *output,
+  uint32_t digest_length
+);
+
+void Hacl_Streaming_HMAC_free(Hacl_Streaming_HMAC_agile_state *state);
+
+Hacl_Streaming_HMAC_agile_state
+*Hacl_Streaming_HMAC_copy(Hacl_Streaming_HMAC_agile_state *state);
+
+#if defined(__cplusplus)
+}
+#endif
+
+#define __Hacl_Streaming_HMAC_H_DEFINED
+#endif
index e6a156a54b3cee5b72a5e834bd7dd3070712eb70..0d6454cdd6efb3637b94ced0df9e994d48986cf2 100644 (file)
@@ -8,10 +8,10 @@ safety, functional correctness, and secret independence.
 
 ## Updating HACL*
 
-Use the `refresh.sh` script in this directory to pull in a new upstream code
-version.  The upstream git hash used for the most recent code pull is recorded
-in the script.  Modify the script as needed to bring in more if changes are
-needed based on upstream code refactoring.
+Use the [refresh.sh](refresh.sh) script in this directory to pull in a new
+upstream code version.  The upstream git hash used for the most recent code
+pull is recorded in the script.  Modify the script as needed to bring in more
+if changes are needed based on upstream code refactoring.
 
 Never manually edit HACL\* files. Always add transformation shell code to the
 `refresh.sh` script to perform any necessary edits. If there are serious code
@@ -19,9 +19,9 @@ changes needed, work with the upstream repository.
 
 ## Local files
 
-1. `./include/python_hacl_namespaces.h`
-1. `./README.md`
-1. `./refresh.sh`
+* [python_hacl_namespaces.h](python_hacl_namespaces.h)
+* [README.md](README.md)
+* [refresh.sh](refresh.sh)
 
 ## ACKS
 
diff --git a/Modules/_hacl/internal/Hacl_HMAC.h b/Modules/_hacl/internal/Hacl_HMAC.h
new file mode 100644 (file)
index 0000000..ad29d50
--- /dev/null
@@ -0,0 +1,52 @@
+/* MIT License
+ *
+ * Copyright (c) 2016-2022 INRIA, CMU and Microsoft Corporation
+ * Copyright (c) 2022-2023 HACL* Contributors
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+
+#ifndef __internal_Hacl_HMAC_H
+#define __internal_Hacl_HMAC_H
+
+#if defined(__cplusplus)
+extern "C" {
+#endif
+
+#include <string.h>
+#include "krml/internal/types.h"
+#include "krml/lowstar_endianness.h"
+#include "krml/internal/target.h"
+
+#include "../Hacl_HMAC.h"
+
+typedef struct K___uint32_t_uint32_t_s
+{
+  uint32_t fst;
+  uint32_t snd;
+}
+K___uint32_t_uint32_t;
+
+#if defined(__cplusplus)
+}
+#endif
+
+#define __internal_Hacl_HMAC_H_DEFINED
+#endif
diff --git a/Modules/_hacl/internal/Hacl_Streaming_HMAC.h b/Modules/_hacl/internal/Hacl_Streaming_HMAC.h
new file mode 100644 (file)
index 0000000..acc4f39
--- /dev/null
@@ -0,0 +1,94 @@
+/* MIT License
+ *
+ * Copyright (c) 2016-2022 INRIA, CMU and Microsoft Corporation
+ * Copyright (c) 2022-2023 HACL* Contributors
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+
+#ifndef __internal_Hacl_Streaming_HMAC_H
+#define __internal_Hacl_Streaming_HMAC_H
+
+#if defined(__cplusplus)
+extern "C" {
+#endif
+
+#include <string.h>
+#include "krml/internal/types.h"
+#include "krml/lowstar_endianness.h"
+#include "krml/internal/target.h"
+
+#include "../Hacl_Streaming_HMAC.h"
+#include "libintvector-shim.h"
+
+#define Hacl_Agile_Hash_MD5_a 0
+#define Hacl_Agile_Hash_SHA1_a 1
+#define Hacl_Agile_Hash_SHA2_224_a 2
+#define Hacl_Agile_Hash_SHA2_256_a 3
+#define Hacl_Agile_Hash_SHA2_384_a 4
+#define Hacl_Agile_Hash_SHA2_512_a 5
+#define Hacl_Agile_Hash_SHA3_224_a 6
+#define Hacl_Agile_Hash_SHA3_256_a 7
+#define Hacl_Agile_Hash_SHA3_384_a 8
+#define Hacl_Agile_Hash_SHA3_512_a 9
+#define Hacl_Agile_Hash_Blake2S_a 10
+#define Hacl_Agile_Hash_Blake2S_128_a 11
+#define Hacl_Agile_Hash_Blake2B_a 12
+#define Hacl_Agile_Hash_Blake2B_256_a 13
+
+typedef uint8_t Hacl_Agile_Hash_state_s_tags;
+
+typedef struct Hacl_Agile_Hash_state_s_s
+{
+  Hacl_Agile_Hash_state_s_tags tag;
+  union {
+    uint32_t *case_MD5_a;
+    uint32_t *case_SHA1_a;
+    uint32_t *case_SHA2_224_a;
+    uint32_t *case_SHA2_256_a;
+    uint64_t *case_SHA2_384_a;
+    uint64_t *case_SHA2_512_a;
+    uint64_t *case_SHA3_224_a;
+    uint64_t *case_SHA3_256_a;
+    uint64_t *case_SHA3_384_a;
+    uint64_t *case_SHA3_512_a;
+    uint32_t *case_Blake2S_a;
+    Lib_IntVector_Intrinsics_vec128 *case_Blake2S_128_a;
+    uint64_t *case_Blake2B_a;
+    Lib_IntVector_Intrinsics_vec256 *case_Blake2B_256_a;
+  }
+  ;
+}
+Hacl_Agile_Hash_state_s;
+
+typedef struct Hacl_Streaming_HMAC_agile_state_s
+{
+  Hacl_Streaming_HMAC_Definitions_two_state block_state;
+  uint8_t *buf;
+  uint64_t total_len;
+}
+Hacl_Streaming_HMAC_agile_state;
+
+#if defined(__cplusplus)
+}
+#endif
+
+#define __internal_Hacl_Streaming_HMAC_H_DEFINED
+#endif
diff --git a/Modules/_hacl/libintvector-shim.h b/Modules/_hacl/libintvector-shim.h
new file mode 100644 (file)
index 0000000..34e0161
--- /dev/null
@@ -0,0 +1,35 @@
+/* Some older compilers do not let you include, e.g., <immintrin.h> unless you also use e.g. -mavx.
+ * This poses a problem for files like Hacl_Streaming_HMAC.c, which *do* need a vec128 type defined
+ * in scope (so that their state type can be defined), but which *must not* be compiled with -mavx
+ * (otherwise it would result in illegal instruction errors on machines without -mavx).
+ *
+ * Rather than add another layer of hacks with `[@ CAbstractStruct ]` and another internal
+ * abstraction barrier between Hacl_Streaming_HMAC and optimized files, we simply define the two
+ * relevant types to be an incomplete struct (we could also define them to be void). Two
+ * consequences:
+ * - these types cannot be constructed, which enforces the abstraction barrier -- you can define the
+ *   Hacl_Streaming_HMAC state type but only if it uses vec128 behind a pointer, which is exactly
+ *   the intent, and
+ * - the absence of actual operations over these types once again enforces that a client module
+ *   which relies on this header only does type definitions, nothing more, and leaves the actual
+ *   operations to the relevant module (e.g. Hacl_Hash_Blake2b_256) -- that one will include
+ *   libintvector.h
+ *
+ * See https://github.com/python/cpython/issues/130213 for a detailed description of the issue
+ * including actual problematic compilers.
+ *
+ * Currently, only Hacl_Streaming_HMAC is crafted carefully enough to do this.
+ */
+
+typedef struct __vec128 Lib_IntVector_Intrinsics_vec128;
+typedef struct __vec256 Lib_IntVector_Intrinsics_vec256;
+
+/* If a module includes this header, it almost certainly has #ifdef HACL_CAN_COMPILE_XXX all over
+ * the place, so bring that into scope too via config.h */
+#if defined(__has_include)
+#if __has_include("config.h")
+#include "config.h"
+#endif
+#endif
+
+#define HACL_INTRINSICS_SHIMMED
index 8a1f4aef384d6268b23d377393b8b4d6d4271388..e234a123e1606daccb80bf25e802978218c10091 100644 (file)
 #define Hacl_Hash_SHA3_state_free python_hashlib_Hacl_Hash_SHA3_state_free
 #define Hacl_Hash_SHA3_state_malloc python_hashlib_Hacl_Hash_SHA3_state_malloc
 
+// Streaming HMAC
+#define Hacl_Streaming_HMAC_malloc_ python_hashlib_Hacl_Streaming_HMAC_malloc_
+#define Hacl_Streaming_HMAC_get_impl python_hashlib_Hacl_Streaming_HMAC_get_impl
+#define Hacl_Streaming_HMAC_reset python_hashlib_Hacl_Streaming_HMAC_reset
+#define Hacl_Streaming_HMAC_update python_hashlib_Hacl_Streaming_HMAC_update
+#define Hacl_Streaming_HMAC_digest python_hashlib_Hacl_Streaming_HMAC_digest
+#define Hacl_Streaming_HMAC_copy python_hashlib_Hacl_Streaming_HMAC_copy
+#define Hacl_Streaming_HMAC_free python_hashlib_Hacl_Streaming_HMAC_free
+
+// HMAC-MD5
+#define Hacl_HMAC_compute_md5 python_hashlib_Hacl_HMAC_compute_md5
+// HMAC-SHA-1
+#define Hacl_HMAC_compute_sha1 python_hashlib_Hacl_HMAC_compute_sha1
+// HMAC-SHA-2
+#define Hacl_HMAC_compute_sha2_224 python_hashlib_Hacl_HMAC_compute_sha2_224
+#define Hacl_HMAC_compute_sha2_256 python_hashlib_Hacl_HMAC_compute_sha2_256
+#define Hacl_HMAC_compute_sha2_384 python_hashlib_Hacl_HMAC_compute_sha2_384
+#define Hacl_HMAC_compute_sha2_512 python_hashlib_Hacl_HMAC_compute_sha2_512
+// HMAC-SHA-3
+#define Hacl_HMAC_compute_sha3_224 python_hashlib_Hacl_HMAC_compute_sha3_224
+#define Hacl_HMAC_compute_sha3_256 python_hashlib_Hacl_HMAC_compute_sha3_256
+#define Hacl_HMAC_compute_sha3_384 python_hashlib_Hacl_HMAC_compute_sha3_384
+#define Hacl_HMAC_compute_sha3_512 python_hashlib_Hacl_HMAC_compute_sha3_512
+// HMAC-BLAKE
+#define Hacl_HMAC_compute_blake2s_32 python_hashlib_Hacl_HMAC_compute_blake2s_32
+#define Hacl_HMAC_compute_blake2b_32 python_hashlib_Hacl_HMAC_compute_blake2b_32
+
 #endif  // _PYTHON_HACL_NAMESPACES_H
index 86e5b4b016107243fe040f110a74c2e8746a22ee..903d7fb2afd362cdc7d740a6e8ecde0af5e8883f 100755 (executable)
@@ -41,6 +41,8 @@ fi
 declare -a dist_files
 dist_files=(
   Hacl_Streaming_Types.h
+  internal/Hacl_Streaming_Types.h
+# Cryptographic Hash Functions (headers)
   Hacl_Hash_MD5.h
   Hacl_Hash_SHA1.h
   Hacl_Hash_SHA2.h
@@ -49,6 +51,10 @@ dist_files=(
   Hacl_Hash_Blake2s.h
   Hacl_Hash_Blake2b_Simd256.h
   Hacl_Hash_Blake2s_Simd128.h
+# Cryptographic Primitives (headers)
+  Hacl_HMAC.h
+  Hacl_Streaming_HMAC.h
+# Cryptographic Hash Functions (internal headers)
   internal/Hacl_Hash_MD5.h
   internal/Hacl_Hash_SHA1.h
   internal/Hacl_Hash_SHA2.h
@@ -58,7 +64,10 @@ dist_files=(
   internal/Hacl_Hash_Blake2b_Simd256.h
   internal/Hacl_Hash_Blake2s_Simd128.h
   internal/Hacl_Impl_Blake2_Constants.h
-  internal/Hacl_Streaming_Types.h
+# Cryptographic Primitives (internal headers)
+  internal/Hacl_HMAC.h
+  internal/Hacl_Streaming_HMAC.h
+# Cryptographic Hash Functions (sources)
   Hacl_Hash_MD5.c
   Hacl_Hash_SHA1.c
   Hacl_Hash_SHA2.c
@@ -67,7 +76,12 @@ dist_files=(
   Hacl_Hash_Blake2s.c
   Hacl_Hash_Blake2b_Simd256.c
   Hacl_Hash_Blake2s_Simd128.c
+# Cryptographic Primitives (sources)
+  Hacl_HMAC.c
+  Hacl_Streaming_HMAC.c
+# Miscellaneous
   libintvector.h
+  libintvector-shim.h
   lib_memzero0.h
   Lib_Memzero0.c
 )
@@ -126,7 +140,10 @@ $sed -i -z 's!#define KRML_TYPES_H!#define KRML_TYPES_H\n#define KRML_VERIFIED_U
 $sed -i 's!#include.*Hacl_Krmllib.h"!!g' "${all_files[@]}"
 
 # Use globally unique names for the Hacl_ C APIs to avoid linkage conflicts.
-$sed -i -z 's!#include <string.h>!#include <string.h>\n#include "python_hacl_namespaces.h"!' Hacl_Hash_*.h
+$sed -i -z 's!#include <string.h>!#include <string.h>\n#include "python_hacl_namespaces.h"!' \
+  Hacl_Hash_*.h \
+  Hacl_HMAC.h \
+  Hacl_Streaming_HMAC.h
 
 # Step 3: trim whitespace (for the linter)
 
diff --git a/Modules/clinic/hmacmodule.c.h b/Modules/clinic/hmacmodule.c.h
new file mode 100644 (file)
index 0000000..1ceb2d8
--- /dev/null
@@ -0,0 +1,673 @@
+/*[clinic input]
+preserve
+[clinic start generated code]*/
+
+#if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE)
+#  include "pycore_gc.h"          // PyGC_Head
+#  include "pycore_runtime.h"     // _Py_ID()
+#endif
+#include "pycore_modsupport.h"    // _PyArg_UnpackKeywords()
+
+PyDoc_STRVAR(_hmac_new__doc__,
+"new($module, /, key, msg=None, digestmod=None)\n"
+"--\n"
+"\n"
+"Return a new HMAC object.");
+
+#define _HMAC_NEW_METHODDEF    \
+    {"new", _PyCFunction_CAST(_hmac_new), METH_FASTCALL|METH_KEYWORDS, _hmac_new__doc__},
+
+static PyObject *
+_hmac_new_impl(PyObject *module, PyObject *keyobj, PyObject *msgobj,
+               PyObject *hash_info_ref);
+
+static PyObject *
+_hmac_new(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames)
+{
+    PyObject *return_value = NULL;
+    #if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE)
+
+    #define NUM_KEYWORDS 3
+    static struct {
+        PyGC_Head _this_is_not_used;
+        PyObject_VAR_HEAD
+        Py_hash_t ob_hash;
+        PyObject *ob_item[NUM_KEYWORDS];
+    } _kwtuple = {
+        .ob_base = PyVarObject_HEAD_INIT(&PyTuple_Type, NUM_KEYWORDS)
+        .ob_hash = -1,
+        .ob_item = { &_Py_ID(key), &_Py_ID(msg), &_Py_ID(digestmod), },
+    };
+    #undef NUM_KEYWORDS
+    #define KWTUPLE (&_kwtuple.ob_base.ob_base)
+
+    #else  // !Py_BUILD_CORE
+    #  define KWTUPLE NULL
+    #endif  // !Py_BUILD_CORE
+
+    static const char * const _keywords[] = {"key", "msg", "digestmod", NULL};
+    static _PyArg_Parser _parser = {
+        .keywords = _keywords,
+        .fname = "new",
+        .kwtuple = KWTUPLE,
+    };
+    #undef KWTUPLE
+    PyObject *argsbuf[3];
+    Py_ssize_t noptargs = nargs + (kwnames ? PyTuple_GET_SIZE(kwnames) : 0) - 1;
+    PyObject *keyobj;
+    PyObject *msgobj = NULL;
+    PyObject *hash_info_ref = NULL;
+
+    args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser,
+            /*minpos*/ 1, /*maxpos*/ 3, /*minkw*/ 0, /*varpos*/ 0, argsbuf);
+    if (!args) {
+        goto exit;
+    }
+    keyobj = args[0];
+    if (!noptargs) {
+        goto skip_optional_pos;
+    }
+    if (args[1]) {
+        msgobj = args[1];
+        if (!--noptargs) {
+            goto skip_optional_pos;
+        }
+    }
+    hash_info_ref = args[2];
+skip_optional_pos:
+    return_value = _hmac_new_impl(module, keyobj, msgobj, hash_info_ref);
+
+exit:
+    return return_value;
+}
+
+PyDoc_STRVAR(_hmac_HMAC_copy__doc__,
+"copy($self, /)\n"
+"--\n"
+"\n"
+"Return a copy (\"clone\") of the HMAC object.");
+
+#define _HMAC_HMAC_COPY_METHODDEF    \
+    {"copy", _PyCFunction_CAST(_hmac_HMAC_copy), METH_METHOD|METH_FASTCALL|METH_KEYWORDS, _hmac_HMAC_copy__doc__},
+
+static PyObject *
+_hmac_HMAC_copy_impl(HMACObject *self, PyTypeObject *cls);
+
+static PyObject *
+_hmac_HMAC_copy(PyObject *self, PyTypeObject *cls, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames)
+{
+    if (nargs || (kwnames && PyTuple_GET_SIZE(kwnames))) {
+        PyErr_SetString(PyExc_TypeError, "copy() takes no arguments");
+        return NULL;
+    }
+    return _hmac_HMAC_copy_impl((HMACObject *)self, cls);
+}
+
+PyDoc_STRVAR(_hmac_HMAC_update__doc__,
+"update($self, /, msg)\n"
+"--\n"
+"\n"
+"Update the HMAC object with the given message.");
+
+#define _HMAC_HMAC_UPDATE_METHODDEF    \
+    {"update", _PyCFunction_CAST(_hmac_HMAC_update), METH_FASTCALL|METH_KEYWORDS, _hmac_HMAC_update__doc__},
+
+static PyObject *
+_hmac_HMAC_update_impl(HMACObject *self, PyObject *msgobj);
+
+static PyObject *
+_hmac_HMAC_update(PyObject *self, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames)
+{
+    PyObject *return_value = NULL;
+    #if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE)
+
+    #define NUM_KEYWORDS 1
+    static struct {
+        PyGC_Head _this_is_not_used;
+        PyObject_VAR_HEAD
+        Py_hash_t ob_hash;
+        PyObject *ob_item[NUM_KEYWORDS];
+    } _kwtuple = {
+        .ob_base = PyVarObject_HEAD_INIT(&PyTuple_Type, NUM_KEYWORDS)
+        .ob_hash = -1,
+        .ob_item = { &_Py_ID(msg), },
+    };
+    #undef NUM_KEYWORDS
+    #define KWTUPLE (&_kwtuple.ob_base.ob_base)
+
+    #else  // !Py_BUILD_CORE
+    #  define KWTUPLE NULL
+    #endif  // !Py_BUILD_CORE
+
+    static const char * const _keywords[] = {"msg", NULL};
+    static _PyArg_Parser _parser = {
+        .keywords = _keywords,
+        .fname = "update",
+        .kwtuple = KWTUPLE,
+    };
+    #undef KWTUPLE
+    PyObject *argsbuf[1];
+    PyObject *msgobj;
+
+    args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser,
+            /*minpos*/ 1, /*maxpos*/ 1, /*minkw*/ 0, /*varpos*/ 0, argsbuf);
+    if (!args) {
+        goto exit;
+    }
+    msgobj = args[0];
+    return_value = _hmac_HMAC_update_impl((HMACObject *)self, msgobj);
+
+exit:
+    return return_value;
+}
+
+PyDoc_STRVAR(_hmac_HMAC_digest__doc__,
+"digest($self, /)\n"
+"--\n"
+"\n"
+"Return the digest of the bytes passed to the update() method so far.\n"
+"\n"
+"This method may raise a MemoryError.");
+
+#define _HMAC_HMAC_DIGEST_METHODDEF    \
+    {"digest", (PyCFunction)_hmac_HMAC_digest, METH_NOARGS, _hmac_HMAC_digest__doc__},
+
+static PyObject *
+_hmac_HMAC_digest_impl(HMACObject *self);
+
+static PyObject *
+_hmac_HMAC_digest(PyObject *self, PyObject *Py_UNUSED(ignored))
+{
+    return _hmac_HMAC_digest_impl((HMACObject *)self);
+}
+
+PyDoc_STRVAR(_hmac_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.\n"
+"\n"
+"This method may raise a MemoryError.");
+
+#define _HMAC_HMAC_HEXDIGEST_METHODDEF    \
+    {"hexdigest", (PyCFunction)_hmac_HMAC_hexdigest, METH_NOARGS, _hmac_HMAC_hexdigest__doc__},
+
+static PyObject *
+_hmac_HMAC_hexdigest_impl(HMACObject *self);
+
+static PyObject *
+_hmac_HMAC_hexdigest(PyObject *self, PyObject *Py_UNUSED(ignored))
+{
+    return _hmac_HMAC_hexdigest_impl((HMACObject *)self);
+}
+
+#if !defined(_hmac_HMAC_name_DOCSTR)
+#  define _hmac_HMAC_name_DOCSTR NULL
+#endif
+#if defined(_HMAC_HMAC_NAME_GETSETDEF)
+#  undef _HMAC_HMAC_NAME_GETSETDEF
+#  define _HMAC_HMAC_NAME_GETSETDEF {"name", (getter)_hmac_HMAC_name_get, (setter)_hmac_HMAC_name_set, _hmac_HMAC_name_DOCSTR},
+#else
+#  define _HMAC_HMAC_NAME_GETSETDEF {"name", (getter)_hmac_HMAC_name_get, NULL, _hmac_HMAC_name_DOCSTR},
+#endif
+
+static PyObject *
+_hmac_HMAC_name_get_impl(HMACObject *self);
+
+static PyObject *
+_hmac_HMAC_name_get(PyObject *self, void *Py_UNUSED(context))
+{
+    return _hmac_HMAC_name_get_impl((HMACObject *)self);
+}
+
+#if !defined(_hmac_HMAC_block_size_DOCSTR)
+#  define _hmac_HMAC_block_size_DOCSTR NULL
+#endif
+#if defined(_HMAC_HMAC_BLOCK_SIZE_GETSETDEF)
+#  undef _HMAC_HMAC_BLOCK_SIZE_GETSETDEF
+#  define _HMAC_HMAC_BLOCK_SIZE_GETSETDEF {"block_size", (getter)_hmac_HMAC_block_size_get, (setter)_hmac_HMAC_block_size_set, _hmac_HMAC_block_size_DOCSTR},
+#else
+#  define _HMAC_HMAC_BLOCK_SIZE_GETSETDEF {"block_size", (getter)_hmac_HMAC_block_size_get, NULL, _hmac_HMAC_block_size_DOCSTR},
+#endif
+
+static PyObject *
+_hmac_HMAC_block_size_get_impl(HMACObject *self);
+
+static PyObject *
+_hmac_HMAC_block_size_get(PyObject *self, void *Py_UNUSED(context))
+{
+    return _hmac_HMAC_block_size_get_impl((HMACObject *)self);
+}
+
+#if !defined(_hmac_HMAC_digest_size_DOCSTR)
+#  define _hmac_HMAC_digest_size_DOCSTR NULL
+#endif
+#if defined(_HMAC_HMAC_DIGEST_SIZE_GETSETDEF)
+#  undef _HMAC_HMAC_DIGEST_SIZE_GETSETDEF
+#  define _HMAC_HMAC_DIGEST_SIZE_GETSETDEF {"digest_size", (getter)_hmac_HMAC_digest_size_get, (setter)_hmac_HMAC_digest_size_set, _hmac_HMAC_digest_size_DOCSTR},
+#else
+#  define _HMAC_HMAC_DIGEST_SIZE_GETSETDEF {"digest_size", (getter)_hmac_HMAC_digest_size_get, NULL, _hmac_HMAC_digest_size_DOCSTR},
+#endif
+
+static PyObject *
+_hmac_HMAC_digest_size_get_impl(HMACObject *self);
+
+static PyObject *
+_hmac_HMAC_digest_size_get(PyObject *self, void *Py_UNUSED(context))
+{
+    return _hmac_HMAC_digest_size_get_impl((HMACObject *)self);
+}
+
+PyDoc_STRVAR(_hmac_compute_digest__doc__,
+"compute_digest($module, /, key, msg, digest)\n"
+"--\n"
+"\n");
+
+#define _HMAC_COMPUTE_DIGEST_METHODDEF    \
+    {"compute_digest", _PyCFunction_CAST(_hmac_compute_digest), METH_FASTCALL|METH_KEYWORDS, _hmac_compute_digest__doc__},
+
+static PyObject *
+_hmac_compute_digest_impl(PyObject *module, PyObject *key, PyObject *msg,
+                          PyObject *digest);
+
+static PyObject *
+_hmac_compute_digest(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames)
+{
+    PyObject *return_value = NULL;
+    #if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE)
+
+    #define NUM_KEYWORDS 3
+    static struct {
+        PyGC_Head _this_is_not_used;
+        PyObject_VAR_HEAD
+        Py_hash_t ob_hash;
+        PyObject *ob_item[NUM_KEYWORDS];
+    } _kwtuple = {
+        .ob_base = PyVarObject_HEAD_INIT(&PyTuple_Type, NUM_KEYWORDS)
+        .ob_hash = -1,
+        .ob_item = { &_Py_ID(key), &_Py_ID(msg), &_Py_ID(digest), },
+    };
+    #undef NUM_KEYWORDS
+    #define KWTUPLE (&_kwtuple.ob_base.ob_base)
+
+    #else  // !Py_BUILD_CORE
+    #  define KWTUPLE NULL
+    #endif  // !Py_BUILD_CORE
+
+    static const char * const _keywords[] = {"key", "msg", "digest", NULL};
+    static _PyArg_Parser _parser = {
+        .keywords = _keywords,
+        .fname = "compute_digest",
+        .kwtuple = KWTUPLE,
+    };
+    #undef KWTUPLE
+    PyObject *argsbuf[3];
+    PyObject *key;
+    PyObject *msg;
+    PyObject *digest;
+
+    args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser,
+            /*minpos*/ 3, /*maxpos*/ 3, /*minkw*/ 0, /*varpos*/ 0, argsbuf);
+    if (!args) {
+        goto exit;
+    }
+    key = args[0];
+    msg = args[1];
+    digest = args[2];
+    return_value = _hmac_compute_digest_impl(module, key, msg, digest);
+
+exit:
+    return return_value;
+}
+
+PyDoc_STRVAR(_hmac_compute_md5__doc__,
+"compute_md5($module, key, msg, /)\n"
+"--\n"
+"\n");
+
+#define _HMAC_COMPUTE_MD5_METHODDEF    \
+    {"compute_md5", _PyCFunction_CAST(_hmac_compute_md5), METH_FASTCALL, _hmac_compute_md5__doc__},
+
+static PyObject *
+_hmac_compute_md5_impl(PyObject *module, PyObject *key, PyObject *msg);
+
+static PyObject *
+_hmac_compute_md5(PyObject *module, PyObject *const *args, Py_ssize_t nargs)
+{
+    PyObject *return_value = NULL;
+    PyObject *key;
+    PyObject *msg;
+
+    if (!_PyArg_CheckPositional("compute_md5", nargs, 2, 2)) {
+        goto exit;
+    }
+    key = args[0];
+    msg = args[1];
+    return_value = _hmac_compute_md5_impl(module, key, msg);
+
+exit:
+    return return_value;
+}
+
+PyDoc_STRVAR(_hmac_compute_sha1__doc__,
+"compute_sha1($module, key, msg, /)\n"
+"--\n"
+"\n");
+
+#define _HMAC_COMPUTE_SHA1_METHODDEF    \
+    {"compute_sha1", _PyCFunction_CAST(_hmac_compute_sha1), METH_FASTCALL, _hmac_compute_sha1__doc__},
+
+static PyObject *
+_hmac_compute_sha1_impl(PyObject *module, PyObject *key, PyObject *msg);
+
+static PyObject *
+_hmac_compute_sha1(PyObject *module, PyObject *const *args, Py_ssize_t nargs)
+{
+    PyObject *return_value = NULL;
+    PyObject *key;
+    PyObject *msg;
+
+    if (!_PyArg_CheckPositional("compute_sha1", nargs, 2, 2)) {
+        goto exit;
+    }
+    key = args[0];
+    msg = args[1];
+    return_value = _hmac_compute_sha1_impl(module, key, msg);
+
+exit:
+    return return_value;
+}
+
+PyDoc_STRVAR(_hmac_compute_sha2_224__doc__,
+"compute_sha224($module, key, msg, /)\n"
+"--\n"
+"\n");
+
+#define _HMAC_COMPUTE_SHA2_224_METHODDEF    \
+    {"compute_sha224", _PyCFunction_CAST(_hmac_compute_sha2_224), METH_FASTCALL, _hmac_compute_sha2_224__doc__},
+
+static PyObject *
+_hmac_compute_sha2_224_impl(PyObject *module, PyObject *key, PyObject *msg);
+
+static PyObject *
+_hmac_compute_sha2_224(PyObject *module, PyObject *const *args, Py_ssize_t nargs)
+{
+    PyObject *return_value = NULL;
+    PyObject *key;
+    PyObject *msg;
+
+    if (!_PyArg_CheckPositional("compute_sha224", nargs, 2, 2)) {
+        goto exit;
+    }
+    key = args[0];
+    msg = args[1];
+    return_value = _hmac_compute_sha2_224_impl(module, key, msg);
+
+exit:
+    return return_value;
+}
+
+PyDoc_STRVAR(_hmac_compute_sha2_256__doc__,
+"compute_sha256($module, key, msg, /)\n"
+"--\n"
+"\n");
+
+#define _HMAC_COMPUTE_SHA2_256_METHODDEF    \
+    {"compute_sha256", _PyCFunction_CAST(_hmac_compute_sha2_256), METH_FASTCALL, _hmac_compute_sha2_256__doc__},
+
+static PyObject *
+_hmac_compute_sha2_256_impl(PyObject *module, PyObject *key, PyObject *msg);
+
+static PyObject *
+_hmac_compute_sha2_256(PyObject *module, PyObject *const *args, Py_ssize_t nargs)
+{
+    PyObject *return_value = NULL;
+    PyObject *key;
+    PyObject *msg;
+
+    if (!_PyArg_CheckPositional("compute_sha256", nargs, 2, 2)) {
+        goto exit;
+    }
+    key = args[0];
+    msg = args[1];
+    return_value = _hmac_compute_sha2_256_impl(module, key, msg);
+
+exit:
+    return return_value;
+}
+
+PyDoc_STRVAR(_hmac_compute_sha2_384__doc__,
+"compute_sha384($module, key, msg, /)\n"
+"--\n"
+"\n");
+
+#define _HMAC_COMPUTE_SHA2_384_METHODDEF    \
+    {"compute_sha384", _PyCFunction_CAST(_hmac_compute_sha2_384), METH_FASTCALL, _hmac_compute_sha2_384__doc__},
+
+static PyObject *
+_hmac_compute_sha2_384_impl(PyObject *module, PyObject *key, PyObject *msg);
+
+static PyObject *
+_hmac_compute_sha2_384(PyObject *module, PyObject *const *args, Py_ssize_t nargs)
+{
+    PyObject *return_value = NULL;
+    PyObject *key;
+    PyObject *msg;
+
+    if (!_PyArg_CheckPositional("compute_sha384", nargs, 2, 2)) {
+        goto exit;
+    }
+    key = args[0];
+    msg = args[1];
+    return_value = _hmac_compute_sha2_384_impl(module, key, msg);
+
+exit:
+    return return_value;
+}
+
+PyDoc_STRVAR(_hmac_compute_sha2_512__doc__,
+"compute_sha512($module, key, msg, /)\n"
+"--\n"
+"\n");
+
+#define _HMAC_COMPUTE_SHA2_512_METHODDEF    \
+    {"compute_sha512", _PyCFunction_CAST(_hmac_compute_sha2_512), METH_FASTCALL, _hmac_compute_sha2_512__doc__},
+
+static PyObject *
+_hmac_compute_sha2_512_impl(PyObject *module, PyObject *key, PyObject *msg);
+
+static PyObject *
+_hmac_compute_sha2_512(PyObject *module, PyObject *const *args, Py_ssize_t nargs)
+{
+    PyObject *return_value = NULL;
+    PyObject *key;
+    PyObject *msg;
+
+    if (!_PyArg_CheckPositional("compute_sha512", nargs, 2, 2)) {
+        goto exit;
+    }
+    key = args[0];
+    msg = args[1];
+    return_value = _hmac_compute_sha2_512_impl(module, key, msg);
+
+exit:
+    return return_value;
+}
+
+PyDoc_STRVAR(_hmac_compute_sha3_224__doc__,
+"compute_sha3_224($module, key, msg, /)\n"
+"--\n"
+"\n");
+
+#define _HMAC_COMPUTE_SHA3_224_METHODDEF    \
+    {"compute_sha3_224", _PyCFunction_CAST(_hmac_compute_sha3_224), METH_FASTCALL, _hmac_compute_sha3_224__doc__},
+
+static PyObject *
+_hmac_compute_sha3_224_impl(PyObject *module, PyObject *key, PyObject *msg);
+
+static PyObject *
+_hmac_compute_sha3_224(PyObject *module, PyObject *const *args, Py_ssize_t nargs)
+{
+    PyObject *return_value = NULL;
+    PyObject *key;
+    PyObject *msg;
+
+    if (!_PyArg_CheckPositional("compute_sha3_224", nargs, 2, 2)) {
+        goto exit;
+    }
+    key = args[0];
+    msg = args[1];
+    return_value = _hmac_compute_sha3_224_impl(module, key, msg);
+
+exit:
+    return return_value;
+}
+
+PyDoc_STRVAR(_hmac_compute_sha3_256__doc__,
+"compute_sha3_256($module, key, msg, /)\n"
+"--\n"
+"\n");
+
+#define _HMAC_COMPUTE_SHA3_256_METHODDEF    \
+    {"compute_sha3_256", _PyCFunction_CAST(_hmac_compute_sha3_256), METH_FASTCALL, _hmac_compute_sha3_256__doc__},
+
+static PyObject *
+_hmac_compute_sha3_256_impl(PyObject *module, PyObject *key, PyObject *msg);
+
+static PyObject *
+_hmac_compute_sha3_256(PyObject *module, PyObject *const *args, Py_ssize_t nargs)
+{
+    PyObject *return_value = NULL;
+    PyObject *key;
+    PyObject *msg;
+
+    if (!_PyArg_CheckPositional("compute_sha3_256", nargs, 2, 2)) {
+        goto exit;
+    }
+    key = args[0];
+    msg = args[1];
+    return_value = _hmac_compute_sha3_256_impl(module, key, msg);
+
+exit:
+    return return_value;
+}
+
+PyDoc_STRVAR(_hmac_compute_sha3_384__doc__,
+"compute_sha3_384($module, key, msg, /)\n"
+"--\n"
+"\n");
+
+#define _HMAC_COMPUTE_SHA3_384_METHODDEF    \
+    {"compute_sha3_384", _PyCFunction_CAST(_hmac_compute_sha3_384), METH_FASTCALL, _hmac_compute_sha3_384__doc__},
+
+static PyObject *
+_hmac_compute_sha3_384_impl(PyObject *module, PyObject *key, PyObject *msg);
+
+static PyObject *
+_hmac_compute_sha3_384(PyObject *module, PyObject *const *args, Py_ssize_t nargs)
+{
+    PyObject *return_value = NULL;
+    PyObject *key;
+    PyObject *msg;
+
+    if (!_PyArg_CheckPositional("compute_sha3_384", nargs, 2, 2)) {
+        goto exit;
+    }
+    key = args[0];
+    msg = args[1];
+    return_value = _hmac_compute_sha3_384_impl(module, key, msg);
+
+exit:
+    return return_value;
+}
+
+PyDoc_STRVAR(_hmac_compute_sha3_512__doc__,
+"compute_sha3_512($module, key, msg, /)\n"
+"--\n"
+"\n");
+
+#define _HMAC_COMPUTE_SHA3_512_METHODDEF    \
+    {"compute_sha3_512", _PyCFunction_CAST(_hmac_compute_sha3_512), METH_FASTCALL, _hmac_compute_sha3_512__doc__},
+
+static PyObject *
+_hmac_compute_sha3_512_impl(PyObject *module, PyObject *key, PyObject *msg);
+
+static PyObject *
+_hmac_compute_sha3_512(PyObject *module, PyObject *const *args, Py_ssize_t nargs)
+{
+    PyObject *return_value = NULL;
+    PyObject *key;
+    PyObject *msg;
+
+    if (!_PyArg_CheckPositional("compute_sha3_512", nargs, 2, 2)) {
+        goto exit;
+    }
+    key = args[0];
+    msg = args[1];
+    return_value = _hmac_compute_sha3_512_impl(module, key, msg);
+
+exit:
+    return return_value;
+}
+
+PyDoc_STRVAR(_hmac_compute_blake2s_32__doc__,
+"compute_blake2s_32($module, key, msg, /)\n"
+"--\n"
+"\n");
+
+#define _HMAC_COMPUTE_BLAKE2S_32_METHODDEF    \
+    {"compute_blake2s_32", _PyCFunction_CAST(_hmac_compute_blake2s_32), METH_FASTCALL, _hmac_compute_blake2s_32__doc__},
+
+static PyObject *
+_hmac_compute_blake2s_32_impl(PyObject *module, PyObject *key, PyObject *msg);
+
+static PyObject *
+_hmac_compute_blake2s_32(PyObject *module, PyObject *const *args, Py_ssize_t nargs)
+{
+    PyObject *return_value = NULL;
+    PyObject *key;
+    PyObject *msg;
+
+    if (!_PyArg_CheckPositional("compute_blake2s_32", nargs, 2, 2)) {
+        goto exit;
+    }
+    key = args[0];
+    msg = args[1];
+    return_value = _hmac_compute_blake2s_32_impl(module, key, msg);
+
+exit:
+    return return_value;
+}
+
+PyDoc_STRVAR(_hmac_compute_blake2b_32__doc__,
+"compute_blake2b_32($module, key, msg, /)\n"
+"--\n"
+"\n");
+
+#define _HMAC_COMPUTE_BLAKE2B_32_METHODDEF    \
+    {"compute_blake2b_32", _PyCFunction_CAST(_hmac_compute_blake2b_32), METH_FASTCALL, _hmac_compute_blake2b_32__doc__},
+
+static PyObject *
+_hmac_compute_blake2b_32_impl(PyObject *module, PyObject *key, PyObject *msg);
+
+static PyObject *
+_hmac_compute_blake2b_32(PyObject *module, PyObject *const *args, Py_ssize_t nargs)
+{
+    PyObject *return_value = NULL;
+    PyObject *key;
+    PyObject *msg;
+
+    if (!_PyArg_CheckPositional("compute_blake2b_32", nargs, 2, 2)) {
+        goto exit;
+    }
+    key = args[0];
+    msg = args[1];
+    return_value = _hmac_compute_blake2b_32_impl(module, key, msg);
+
+exit:
+    return return_value;
+}
+/*[clinic end generated code: output=30c0614482d963f5 input=a9049054013a1b77]*/
diff --git a/Modules/hmacmodule.c b/Modules/hmacmodule.c
new file mode 100644 (file)
index 0000000..faf4e0a
--- /dev/null
@@ -0,0 +1,1758 @@
+/*
+ * @author Bénédikt Tran
+ *
+ * Implement the HMAC algorithm as described by RFC 2104 using HACL*.
+ *
+ * Using HACL* implementation implicitly assumes that the caller wants
+ * a formally verified implementation. In particular, only algorithms
+ * given by their names will be recognized.
+ *
+ * Some algorithms exposed by `_hashlib` such as truncated SHA-2-512-224/256
+ * are not yet implemented by the HACL* project. Nonetheless, the supported
+ * HMAC algorithms form a subset of those supported by '_hashlib'.
+ */
+
+#ifndef Py_BUILD_CORE_BUILTIN
+#  define Py_BUILD_CORE_MODULE 1
+#endif
+
+#include "Python.h"
+#include "pycore_hashtable.h"
+#include "pycore_strhex.h"              // _Py_strhex()
+
+// Small mismatch between the variable names Python defines as part of configure
+// at the ones HACL* expects to be set in order to enable those headers.
+#define HACL_CAN_COMPILE_VEC128 HACL_CAN_COMPILE_SIMD128
+#define HACL_CAN_COMPILE_VEC256 HACL_CAN_COMPILE_SIMD256
+
+#include "_hacl/Hacl_HMAC.h"
+#include "_hacl/Hacl_Streaming_HMAC.h"  // Hacl_Agile_Hash_* identifiers
+#include "_hacl/Hacl_Streaming_Types.h" // Hacl_Streaming_Types_error_code
+
+#include <stdbool.h>
+
+#include "hashlib.h"
+
+// --- Reusable error messages ------------------------------------------------
+
+#define INVALID_KEY_LENGTH  "key length exceeds UINT32_MAX"
+#define INVALID_MSG_LENGTH  "message length exceeds UINT32_MAX"
+
+// --- HMAC underlying hash function static information -----------------------
+
+#define UINT32_MAX_AS_SSIZE_T                   ((Py_ssize_t)UINT32_MAX)
+
+#define Py_hmac_hash_max_block_size             144
+#define Py_hmac_hash_max_digest_size            64
+
+/* MD-5 */
+// HACL_HID = md5
+#define Py_hmac_md5_block_size                  64
+#define Py_hmac_md5_digest_size                 16
+
+#define Py_hmac_md5_compute_func                Hacl_HMAC_compute_md5
+
+/* SHA-1 family */
+// HACL_HID = sha1
+#define Py_hmac_sha1_block_size                 64
+#define Py_hmac_sha1_digest_size                20
+
+#define Py_hmac_sha1_compute_func               Hacl_HMAC_compute_sha1
+
+/* SHA-2 family */
+// HACL_HID = sha2_224
+#define Py_hmac_sha2_224_block_size             64
+#define Py_hmac_sha2_224_digest_size            28
+
+#define Py_hmac_sha2_224_compute_func           Hacl_HMAC_compute_sha2_224
+
+// HACL_HID = sha2_256
+#define Py_hmac_sha2_256_block_size             64
+#define Py_hmac_sha2_256_digest_size            32
+
+#define Py_hmac_sha2_256_compute_func           Hacl_HMAC_compute_sha2_256
+
+// HACL_HID = sha2_384
+#define Py_hmac_sha2_384_block_size             128
+#define Py_hmac_sha2_384_digest_size            48
+
+#define Py_hmac_sha2_384_compute_func           Hacl_HMAC_compute_sha2_384
+
+// HACL_HID = sha2_512
+#define Py_hmac_sha2_512_block_size             128
+#define Py_hmac_sha2_512_digest_size            64
+
+#define Py_hmac_sha2_512_compute_func           Hacl_HMAC_compute_sha2_512
+
+/* SHA-3 family */
+// HACL_HID = sha3_224
+#define Py_hmac_sha3_224_block_size             144
+#define Py_hmac_sha3_224_digest_size            28
+
+#define Py_hmac_sha3_224_compute_func           Hacl_HMAC_compute_sha3_224
+
+// HACL_HID = sha3_256
+#define Py_hmac_sha3_256_block_size             136
+#define Py_hmac_sha3_256_digest_size            32
+
+#define Py_hmac_sha3_256_compute_func           Hacl_HMAC_compute_sha3_256
+
+// HACL_HID = sha3_384
+#define Py_hmac_sha3_384_block_size             104
+#define Py_hmac_sha3_384_digest_size            48
+
+#define Py_hmac_sha3_384_compute_func           Hacl_HMAC_compute_sha3_384
+
+// HACL_HID = sha3_512
+#define Py_hmac_sha3_512_block_size             72
+#define Py_hmac_sha3_512_digest_size            64
+
+#define Py_hmac_sha3_512_compute_func           Hacl_HMAC_compute_sha3_512
+
+/* Blake2 family */
+// HACL_HID = blake2s_32
+#define Py_hmac_blake2s_32_block_size           64
+#define Py_hmac_blake2s_32_digest_size          32
+
+#define Py_hmac_blake2s_32_compute_func         Hacl_HMAC_compute_blake2s_32
+
+// HACL_HID = blake2b_32
+#define Py_hmac_blake2b_32_block_size           128
+#define Py_hmac_blake2b_32_digest_size          64
+
+#define Py_hmac_blake2b_32_compute_func         Hacl_HMAC_compute_blake2b_32
+
+/* Enumeration indicating the underlying hash function used by HMAC. */
+typedef enum HMAC_Hash_Kind {
+    Py_hmac_kind_hash_unknown = -1,
+#define DECL_HACL_HMAC_HASH_KIND(NAME, HACL_NAME)  \
+    Py_hmac_kind_hmac_ ## NAME = Hacl_Agile_Hash_ ## HACL_NAME,
+    /* MD5 */
+    DECL_HACL_HMAC_HASH_KIND(md5, MD5)
+    /* SHA-1 */
+    DECL_HACL_HMAC_HASH_KIND(sha1, SHA1)
+    /* SHA-2 family */
+    DECL_HACL_HMAC_HASH_KIND(sha2_224, SHA2_224)
+    DECL_HACL_HMAC_HASH_KIND(sha2_256, SHA2_256)
+    DECL_HACL_HMAC_HASH_KIND(sha2_384, SHA2_384)
+    DECL_HACL_HMAC_HASH_KIND(sha2_512, SHA2_512)
+    /* SHA-3 family */
+    DECL_HACL_HMAC_HASH_KIND(sha3_224, SHA3_224)
+    DECL_HACL_HMAC_HASH_KIND(sha3_256, SHA3_256)
+    DECL_HACL_HMAC_HASH_KIND(sha3_384, SHA3_384)
+    DECL_HACL_HMAC_HASH_KIND(sha3_512, SHA3_512)
+    /* Blake family */
+    DECL_HACL_HMAC_HASH_KIND(blake2s_32, Blake2S_32)
+    DECL_HACL_HMAC_HASH_KIND(blake2b_32, Blake2B_32)
+    /* Blake runtime family (should not be used statically) */
+    DECL_HACL_HMAC_HASH_KIND(vectorized_blake2s_32, Blake2S_128)
+    DECL_HACL_HMAC_HASH_KIND(vectorized_blake2b_32, Blake2B_256)
+#undef DECL_HACL_HMAC_HASH_KIND
+} HMAC_Hash_Kind;
+
+typedef Hacl_Streaming_Types_error_code hacl_errno_t;
+
+/* Function pointer type for 1-shot HACL* HMAC functions. */
+typedef void
+(*HACL_HMAC_compute_func)(uint8_t *out,
+                          uint8_t *key, uint32_t keylen,
+                          uint8_t *msg, uint32_t msglen);
+/* Function pointer type for 1-shot HACL* HMAC CPython AC functions. */
+typedef PyObject *
+(*PyAC_HMAC_compute_func)(PyObject *module, PyObject *key, PyObject *msg);
+
+/*
+ * HACL* HMAC minimal interface.
+ */
+typedef struct py_hmac_hacl_api {
+    HACL_HMAC_compute_func compute;
+    PyAC_HMAC_compute_func compute_py;
+} py_hmac_hacl_api;
+
+#if PY_SSIZE_T_MAX > UINT32_MAX
+#define Py_HMAC_SSIZE_LARGER_THAN_UINT32
+#endif
+
+/*
+ * Assert that 'LEN' can be safely casted to uint32_t.
+ *
+ * The 'LEN' parameter should be convertible to Py_ssize_t.
+ */
+#ifdef Py_HMAC_SSIZE_LARGER_THAN_UINT32
+#define Py_CHECK_HACL_UINT32_T_LENGTH(LEN)                  \
+    do {                                                    \
+        assert((Py_ssize_t)(LEN) <= UINT32_MAX_AS_SSIZE_T); \
+    } while (0)
+#else
+#define Py_CHECK_HACL_UINT32_T_LENGTH(LEN)
+#endif
+
+/*
+ * Call the HACL* HMAC-HASH update function on the given data.
+ *
+ * The magnitude of 'LEN' is not checked and thus 'LEN' must be
+ * safely convertible to a uint32_t value.
+ */
+#define Py_HMAC_HACL_UPDATE_CALL(HACL_STATE, BUF, LEN)          \
+    Hacl_Streaming_HMAC_update(HACL_STATE, BUF, (uint32_t)(LEN))
+
+/*
+ * Call the HACL* HMAC-HASH update function on the given data.
+ *
+ * On DEBUG builds, the 'ERRACTION' statements are executed if
+ * the update() call returned a non-successful HACL* exit code.
+ *
+ * The buffer 'BUF' and its length 'LEN' are left untouched.
+ *
+ * The formal signature of this macro is:
+ *
+ *     (HACL_HMAC_state *, uint8_t *, uint32_t, PyObject *, (C statements))
+ */
+#ifndef NDEBUG
+#define Py_HMAC_HACL_UPDATE_ONCE(                                           \
+    HACL_STATE, BUF, LEN,                                                   \
+    ALGORITHM, ERRACTION                                                    \
+)                                                                           \
+    do {                                                                    \
+        Py_CHECK_HACL_UINT32_T_LENGTH(LEN);                                 \
+        hacl_errno_t code = Py_HMAC_HACL_UPDATE_CALL(HACL_STATE, BUF, LEN); \
+        if (_hacl_convert_errno(code, (ALGORITHM)) < 0) {                   \
+            ERRACTION;                                                      \
+        }                                                                   \
+    } while (0)
+#else
+#define Py_HMAC_HACL_UPDATE_ONCE(                                   \
+    HACL_STATE, BUF, LEN,                                           \
+    _ALGORITHM, _ERRACTION                                          \
+)                                                                   \
+    do {                                                            \
+        (void)Py_HMAC_HACL_UPDATE_CALL(HACL_STATE, BUF, (LEN));     \
+    } while (0)
+#endif
+
+/*
+ * Repetivively call the HACL* HMAC-HASH update function on the given
+ * data until the buffer length 'LEN' is strictly less than UINT32_MAX.
+ *
+ * On builds with PY_SSIZE_T_MAX <= UINT32_MAX, this is a no-op.
+ *
+ * The buffer 'BUF' (resp. 'LEN') is advanced (resp. decremented)
+ * by UINT32_MAX after each update. On DEBUG builds, each update()
+ * call is verified and the 'ERRACTION' statements are executed if
+ * a non-successful HACL* exit code is being returned.
+ *
+ * In particular, 'BUF' and 'LEN' must be variable names and not
+ * expressions on their own.
+ *
+ * The formal signature of this macro is:
+ *
+ *     (HACL_HMAC_state *, uint8_t *, C integer, PyObject *, (C statements))
+ */
+#ifdef Py_HMAC_SSIZE_LARGER_THAN_UINT32
+#define Py_HMAC_HACL_UPDATE_LOOP(                                   \
+    HACL_STATE, BUF, LEN,                                           \
+    ALGORITHM, ERRACTION                                            \
+)                                                                   \
+    do {                                                            \
+        while ((Py_ssize_t)LEN > UINT32_MAX_AS_SSIZE_T) {           \
+            Py_HMAC_HACL_UPDATE_ONCE(HACL_STATE, BUF, UINT32_MAX,   \
+                                     ALGORITHM, ERRACTION);         \
+            BUF += UINT32_MAX;                                      \
+            LEN -= UINT32_MAX;                                      \
+        }                                                           \
+    } while (0)
+#else
+#define Py_HMAC_HACL_UPDATE_LOOP(   \
+    HACL_STATE, BUF, LEN,           \
+    _ALGORITHM, _ERRACTION          \
+)
+#endif
+
+/*
+ * Perform the HMAC-HASH update() operation in a streaming fashion.
+ *
+ * The formal signature of this macro is:
+ *
+ *     (HACL_HMAC_state *, uint8_t *, C integer, PyObject *, (C statements))
+ */
+#define Py_HMAC_HACL_UPDATE(                            \
+    HACL_STATE, BUF, LEN,                               \
+    ALGORITHM, ERRACTION                                \
+)                                                       \
+    do {                                                \
+        Py_HMAC_HACL_UPDATE_LOOP(HACL_STATE, BUF, LEN,  \
+                                 ALGORITHM, ERRACTION); \
+        Py_HMAC_HACL_UPDATE_ONCE(HACL_STATE, BUF, LEN,  \
+                                 ALGORITHM, ERRACTION); \
+    } while (0)
+
+/*
+ * HMAC underlying hash function static information.
+ */
+typedef struct py_hmac_hinfo {
+    /*
+     * Name of the hash function used by the HACL* HMAC module.
+     *
+     * This name may differ from the hashlib names. For instance,
+     * SHA-2/224 is named "sha2_224" instead of "sha224" as it is
+     * done by 'hashlib'.
+     */
+    const char *name;
+
+    /* hash function information */
+    HMAC_Hash_Kind kind;
+    uint32_t block_size;
+    uint32_t digest_size;
+
+    /* HACL* HMAC API */
+    py_hmac_hacl_api api;
+
+    /*
+     * Cached field storing the 'hashlib_name' field as a Python string.
+     *
+     * This field is NULL by default in the items of "py_hmac_static_hinfo"
+     * but will be populated when creating the module's state "hinfo_table".
+     */
+    PyObject *display_name;
+    const char *hashlib_name;   /* hashlib preferred name (default: name) */
+
+    Py_ssize_t refcnt;
+} py_hmac_hinfo;
+
+// --- HMAC module state ------------------------------------------------------
+
+typedef struct hmacmodule_state {
+    _Py_hashtable_t *hinfo_table;
+    PyObject *unknown_hash_error;
+    /* HMAC object type */
+    PyTypeObject *hmac_type;
+    /* interned strings */
+    PyObject *str_lower;
+
+    bool can_run_simd128;
+    bool can_run_simd256;
+} hmacmodule_state;
+
+static inline hmacmodule_state *
+get_hmacmodule_state(PyObject *module)
+{
+    void *state = PyModule_GetState(module);
+    assert(state != NULL);
+    return (hmacmodule_state *)state;
+}
+
+static inline hmacmodule_state *
+get_hmacmodule_state_by_cls(PyTypeObject *cls)
+{
+    void *state = PyType_GetModuleState(cls);
+    assert(state != NULL);
+    return (hmacmodule_state *)state;
+}
+
+// --- HMAC Object ------------------------------------------------------------
+
+typedef Hacl_Streaming_HMAC_agile_state HACL_HMAC_state;
+
+typedef struct HMACObject {
+    PyObject_HEAD
+
+    bool use_mutex;
+    PyMutex mutex;
+
+    // Hash function information
+    PyObject *name;         // rendered name (exact unicode object)
+    HMAC_Hash_Kind kind;    // can be used for runtime dispatch (must be known)
+    uint32_t block_size;
+    uint32_t digest_size;
+    py_hmac_hacl_api api;
+
+    // HMAC HACL* internal state.
+    HACL_HMAC_state *state;
+} HMACObject;
+
+#define HMACObject_CAST(op) ((HMACObject *)(op))
+
+// --- HMAC module clinic configuration ---------------------------------------
+
+/*[clinic input]
+module _hmac
+class _hmac.HMAC "HMACObject *" "clinic_state()->hmac_type"
+[clinic start generated code]*/
+/*[clinic end generated code: output=da39a3ee5e6b4b0d input=c8bab73fde49ba8a]*/
+
+#define clinic_state()  (get_hmacmodule_state_by_cls(Py_TYPE(self)))
+#include "clinic/hmacmodule.c.h"
+#undef clinic_state
+
+// --- Helpers ----------------------------------------------------------------
+//
+// The helpers have the following naming conventions:
+//
+// - Helpers with the "_hacl" prefix are thin wrappers around HACL* functions.
+//   Buffer lengths given as inputs should fit on 32-bit integers.
+//
+// - Helpers with the "hmac_" prefix act on HMAC objects and accept buffers
+//   whose length fits on 32-bit or 64-bit integers (depending on the host
+//   machine).
+
+/*
+ * Assert that a HMAC hash kind is a static kind.
+ *
+ * A "static" kind is specified in the 'py_hmac_static_hinfo'
+ * table and is always independent of the host CPUID features.
+ */
+#ifndef NDEBUG
+static void
+assert_is_static_hmac_hash_kind(HMAC_Hash_Kind kind)
+{
+    switch (kind) {
+        case Py_hmac_kind_hash_unknown: {
+            Py_FatalError("HMAC hash kind must be a known kind");
+            return;
+        }
+        case Py_hmac_kind_hmac_vectorized_blake2s_32:
+        case Py_hmac_kind_hmac_vectorized_blake2b_32: {
+            Py_FatalError("HMAC hash kind must not be a vectorized kind");
+            return;
+        }
+        default:
+            return;
+    }
+}
+#else
+static inline void
+assert_is_static_hmac_hash_kind(HMAC_Hash_Kind Py_UNUSED(kind)) {}
+#endif
+
+/*
+ * Convert a HMAC hash static kind into a runtime kind.
+ *
+ * A "runtime" kind is derived from a static kind and depends
+ * on the host CPUID features. In particular, this is the kind
+ * that a HMAC object internally stores.
+ */
+static HMAC_Hash_Kind
+narrow_hmac_hash_kind(hmacmodule_state *state, HMAC_Hash_Kind kind)
+{
+    switch (kind) {
+        case Py_hmac_kind_hmac_blake2s_32: {
+#if HACL_CAN_COMPILE_SIMD128
+            if (state->can_run_simd128) {
+                return Py_hmac_kind_hmac_vectorized_blake2s_32;
+            }
+#endif
+            return kind;
+        }
+        case Py_hmac_kind_hmac_blake2b_32: {
+#if HACL_CAN_COMPILE_SIMD256
+            if (state->can_run_simd256) {
+                return Py_hmac_kind_hmac_vectorized_blake2b_32;
+            }
+#endif
+            return kind;
+        }
+        default:
+            return kind;
+    }
+}
+
+/*
+ * Handle the HACL* exit code.
+ *
+ * If 'code' represents a successful operation, this returns 0.
+ * Otherwise, this sets an appropriate exception and returns -1.
+ */
+static int
+_hacl_convert_errno(hacl_errno_t code, PyObject *algorithm)
+{
+    switch (code) {
+        case Hacl_Streaming_Types_Success: {
+            return 0;
+        }
+        case Hacl_Streaming_Types_InvalidAlgorithm: {
+            // only makes sense if an algorithm is known at call time
+            assert(algorithm != NULL);
+            assert(PyUnicode_CheckExact(algorithm));
+            PyErr_Format(PyExc_ValueError, "invalid algorithm: %U", algorithm);
+            return -1;
+        }
+        case Hacl_Streaming_Types_InvalidLength: {
+            PyErr_SetString(PyExc_ValueError, "invalid length");
+            return -1;
+        }
+        case Hacl_Streaming_Types_MaximumLengthExceeded: {
+            PyErr_SetString(PyExc_OverflowError, "maximum length exceeded");
+            return -1;
+        }
+        case Hacl_Streaming_Types_OutOfMemory: {
+            PyErr_NoMemory();
+            return -1;
+        }
+        default: {
+            PyErr_Format(PyExc_RuntimeError,
+                         "HACL* internal routine failed with error code: %d",
+                         code);
+            return -1;
+        }
+    }
+}
+
+/*
+ * Return a new HACL* internal state or return NULL on failure.
+ *
+ * An appropriate exception is set if the state cannot be created.
+ */
+static HACL_HMAC_state *
+_hacl_hmac_state_new(HMAC_Hash_Kind kind, uint8_t *key, uint32_t len)
+{
+    assert(kind != Py_hmac_kind_hash_unknown);
+    HACL_HMAC_state *state = NULL;
+    hacl_errno_t retcode = Hacl_Streaming_HMAC_malloc_(kind, key, len, &state);
+    if (_hacl_convert_errno(retcode, NULL) < 0) {
+        assert(state == NULL);
+        return NULL;
+    }
+    return state;
+}
+
+/*
+ * Free the HACL* internal state.
+ */
+static inline void
+_hacl_hmac_state_free(HACL_HMAC_state *state)
+{
+    if (state != NULL) {
+        Hacl_Streaming_HMAC_free(state);
+    }
+}
+
+/* Static information used to construct the hash table. */
+static const py_hmac_hinfo py_hmac_static_hinfo[] = {
+#define Py_HMAC_HINFO_HACL_API(HACL_HID)                                \
+    {                                                                   \
+        /* one-shot helpers */                                          \
+        .compute = &Py_hmac_## HACL_HID ##_compute_func,                \
+        .compute_py = &_hmac_compute_## HACL_HID ##_impl,               \
+    }
+
+#define Py_HMAC_HINFO_ENTRY(HACL_HID, HLIB_NAME)            \
+    {                                                       \
+        .name = Py_STRINGIFY(HACL_HID),                     \
+        .kind = Py_hmac_kind_hmac_ ## HACL_HID,             \
+        .block_size = Py_hmac_## HACL_HID ##_block_size,    \
+        .digest_size = Py_hmac_## HACL_HID ##_digest_size,  \
+        .api = Py_HMAC_HINFO_HACL_API(HACL_HID),            \
+        .display_name = NULL,                               \
+        .hashlib_name = HLIB_NAME,                          \
+        .refcnt = 0,                                        \
+    }
+    /* MD5 */
+    Py_HMAC_HINFO_ENTRY(md5, NULL),
+    /* SHA-1 */
+    Py_HMAC_HINFO_ENTRY(sha1, NULL),
+    /* SHA-2 family */
+    Py_HMAC_HINFO_ENTRY(sha2_224, "sha224"),
+    Py_HMAC_HINFO_ENTRY(sha2_256, "sha256"),
+    Py_HMAC_HINFO_ENTRY(sha2_384, "sha384"),
+    Py_HMAC_HINFO_ENTRY(sha2_512, "sha512"),
+    /* SHA-3 family */
+    Py_HMAC_HINFO_ENTRY(sha3_224, NULL),
+    Py_HMAC_HINFO_ENTRY(sha3_256, NULL),
+    Py_HMAC_HINFO_ENTRY(sha3_384, NULL),
+    Py_HMAC_HINFO_ENTRY(sha3_512, NULL),
+    /* Blake family */
+    Py_HMAC_HINFO_ENTRY(blake2s_32, "blake2s"),
+    Py_HMAC_HINFO_ENTRY(blake2b_32, "blake2b"),
+#undef Py_HMAC_HINFO_ENTRY
+#undef Py_HMAC_HINFO_HACL_API
+    /* sentinel */
+    {
+        NULL, Py_hmac_kind_hash_unknown, 0, 0,
+        {NULL, NULL},
+        NULL, NULL,
+        0,
+    },
+};
+
+/*
+ * Check whether 'name' is a known HMAC hash function name,
+ * storing the corresponding static information in 'info'.
+ *
+ * This function always succeeds and never set an exception.
+ */
+static inline bool
+find_hash_info_by_utf8name(hmacmodule_state *state,
+                           const char *name,
+                           const py_hmac_hinfo **info)
+{
+    assert(name != NULL);
+    *info = _Py_hashtable_get(state->hinfo_table, name);
+    return *info != NULL;
+}
+
+/*
+ * Find the corresponding HMAC hash function static information by its name.
+ *
+ * On error, propagate the exception, set 'info' to NULL and return -1.
+ *
+ * If no correspondence exists, set 'info' to NULL and return 0.
+ * Otherwise, set 'info' to the deduced information and return 1.
+ *
+ * Parameters
+ *
+ *      state           The HMAC module state.
+ *      name            The hash function name.
+ *      info            The deduced information, if any.
+ */
+static int
+find_hash_info_by_name(hmacmodule_state *state,
+                       PyObject *name,
+                       const py_hmac_hinfo **info)
+{
+    const char *utf8name = PyUnicode_AsUTF8(name);
+    if (utf8name == NULL) {
+        goto error;
+    }
+    if (find_hash_info_by_utf8name(state, utf8name, info)) {
+        return 1;
+    }
+
+    // try to find an alternative using the lowercase name
+    PyObject *lower = PyObject_CallMethodNoArgs(name, state->str_lower);
+    if (lower == NULL) {
+        goto error;
+    }
+    const char *utf8lower = PyUnicode_AsUTF8(lower);
+    if (utf8lower == NULL) {
+        Py_DECREF(lower);
+        goto error;
+    }
+    int found = find_hash_info_by_utf8name(state, utf8lower, info);
+    Py_DECREF(lower);
+    return found;
+
+error:
+    *info = NULL;
+    return -1;
+}
+
+/*
+ * Find the corresponding HMAC hash function static information.
+ *
+ * On error, propagate the exception, set 'info' to NULL and return -1.
+ *
+ * If no correspondence exists, set 'info' to NULL and return 0.
+ * Otherwise, set 'info' to the deduced information and return 1.
+ *
+ * Parameters
+ *
+ *      state           The HMAC module state.
+ *      hash_info_ref   An input to hashlib.new().
+ *      info            The deduced information, if any.
+ */
+static int
+find_hash_info_impl(hmacmodule_state *state,
+                    PyObject *hash_info_ref,
+                    const py_hmac_hinfo **info)
+{
+    if (PyUnicode_Check(hash_info_ref)) {
+        return find_hash_info_by_name(state, hash_info_ref, info);
+    }
+    // NOTE(picnixz): For now, we only support named algorithms.
+    // In the future, we need to decide whether 'hashlib.openssl_md5'
+    // would make sense as an alias to 'md5' and how to remove OpenSSL.
+    *info = NULL;
+    return 0;
+}
+
+/*
+ * Find the corresponding HMAC hash function static information.
+ *
+ * If nothing can be found or if an error occurred, return NULL
+ * with an exception set. Otherwise return a non-NULL object.
+ */
+static const py_hmac_hinfo *
+find_hash_info(hmacmodule_state *state, PyObject *hash_info_ref)
+{
+    const py_hmac_hinfo *info = NULL;
+    int rc = find_hash_info_impl(state, hash_info_ref, &info);
+    // The code below could be simplfied with only 'rc == 0' case,
+    // but we are deliberately verbose to ease future improvements.
+    if (rc < 0) {
+        return NULL;
+    }
+    if (rc == 0) {
+        PyErr_Format(state->unknown_hash_error,
+                     "unsupported hash type: %R", hash_info_ref);
+        return NULL;
+    }
+    assert(info != NULL);
+    return info;
+}
+
+/* Check that the buffer length fits on a uint32_t. */
+static inline int
+has_uint32_t_buffer_length(const Py_buffer *buffer)
+{
+#ifdef Py_HMAC_SSIZE_LARGER_THAN_UINT32
+    return buffer->len <= UINT32_MAX_AS_SSIZE_T;
+#else
+    return 1;
+#endif
+}
+
+// --- HMAC object ------------------------------------------------------------
+
+/*
+ * Use the HMAC information 'info' to populate the corresponding fields.
+ *
+ * The real 'kind' for BLAKE-2 is obtained once and depends on both static
+ * capabilities (supported compiler flags) and runtime CPUID features.
+ */
+static void
+hmac_set_hinfo(hmacmodule_state *state,
+               HMACObject *self, const py_hmac_hinfo *info)
+{
+    assert(info->display_name != NULL);
+    self->name = Py_NewRef(info->display_name);
+    assert_is_static_hmac_hash_kind(info->kind);
+    self->kind = narrow_hmac_hash_kind(state, info->kind);
+    assert(info->block_size <= Py_hmac_hash_max_block_size);
+    self->block_size = info->block_size;
+    assert(info->digest_size <= Py_hmac_hash_max_digest_size);
+    self->digest_size = info->digest_size;
+    assert(info->api.compute != NULL);
+    assert(info->api.compute_py != NULL);
+    self->api = info->api;
+}
+
+/*
+ * Create initial HACL* internal state with the given key.
+ *
+ * This function MUST only be called by the HMAC object constructor
+ * and after hmac_set_hinfo() has been called, lest the behaviour is
+ * undefined.
+ *
+ * Return 0 on success; otherwise, set an exception and return -1 on failure.
+ */
+static int
+hmac_new_initial_state(HMACObject *self, uint8_t *key, Py_ssize_t len)
+{
+    assert(key != NULL);
+#ifdef Py_HMAC_SSIZE_LARGER_THAN_UINT32
+    // Technically speaking, we could hash the key to make it small
+    // but it would require to call the hash functions ourselves and
+    // not rely on HACL* implementation anymore. As such, we explicitly
+    // reject keys that do not fit on 32 bits until HACL* handles them.
+    if (len > UINT32_MAX_AS_SSIZE_T) {
+        PyErr_SetString(PyExc_OverflowError, INVALID_KEY_LENGTH);
+        return -1;
+    }
+#endif
+    assert(self->kind != Py_hmac_kind_hash_unknown);
+    // cast to uint32_t is now safe even on 32-bit platforms
+    self->state = _hacl_hmac_state_new(self->kind, key, (uint32_t)len);
+    // _hacl_hmac_state_new() may set an exception on error
+    return self->state == NULL ? -1 : 0;
+}
+
+/*
+ * Feed initial data.
+ *
+ * This function MUST only be called by the HMAC object constructor
+ * and after hmac_set_hinfo() and hmac_new_initial_state() have been
+ * called, lest the behaviour is undefined.
+ *
+ * Return 0 on success; otherwise, set an exception and return -1 on failure.
+ */
+static int
+hmac_feed_initial_data(HMACObject *self, uint8_t *msg, Py_ssize_t len)
+{
+    assert(self->name != NULL);
+    assert(self->state != NULL);
+    if (len == 0) {
+        // do nothing if the buffer is empty
+        return 0;
+    }
+
+    if (len < HASHLIB_GIL_MINSIZE) {
+        Py_HMAC_HACL_UPDATE(self->state, msg, len, self->name, return -1);
+        return 0;
+    }
+
+    int res = 0;
+    Py_BEGIN_ALLOW_THREADS
+        Py_HMAC_HACL_UPDATE(self->state, msg, len, self->name, goto error);
+        goto done;
+#ifndef NDEBUG
+error:
+        res = -1;
+#else
+        Py_UNREACHABLE();
+#endif
+done:
+    Py_END_ALLOW_THREADS
+    return res;
+}
+
+/*[clinic input]
+_hmac.new
+
+    key as keyobj: object
+    msg as msgobj: object(c_default="NULL") = None
+    digestmod as hash_info_ref: object(c_default="NULL") = None
+
+Return a new HMAC object.
+[clinic start generated code]*/
+
+static PyObject *
+_hmac_new_impl(PyObject *module, PyObject *keyobj, PyObject *msgobj,
+               PyObject *hash_info_ref)
+/*[clinic end generated code: output=7c7573a427d58758 input=92fc7c0a00707d42]*/
+{
+    hmacmodule_state *state = get_hmacmodule_state(module);
+    if (hash_info_ref == NULL) {
+        PyErr_SetString(PyExc_TypeError,
+                        "new() missing 1 required argument 'digestmod'");
+        return NULL;
+    }
+
+    const py_hmac_hinfo *info = find_hash_info(state, hash_info_ref);
+    if (info == NULL) {
+        return NULL;
+    }
+
+    HMACObject *self = PyObject_GC_New(HMACObject, state->hmac_type);
+    if (self == NULL) {
+        return NULL;
+    }
+    HASHLIB_INIT_MUTEX(self);
+    hmac_set_hinfo(state, self, info);
+    int rc;
+    // Create the HACL* internal state with the given key.
+    Py_buffer key;
+    GET_BUFFER_VIEW_OR_ERROR(keyobj, &key, goto error_on_key);
+    rc = hmac_new_initial_state(self, key.buf, key.len);
+    PyBuffer_Release(&key);
+    if (rc < 0) {
+        goto error;
+    }
+    // Feed the internal state the initial message if any.
+    if (msgobj != NULL && msgobj != Py_None) {
+        Py_buffer msg;
+        GET_BUFFER_VIEW_OR_ERROR(msgobj, &msg, goto error);
+        rc = hmac_feed_initial_data(self, msg.buf, msg.len);
+        PyBuffer_Release(&msg);
+#ifndef NDEBUG
+        if (rc < 0) {
+            goto error;
+        }
+#else
+        (void)rc;
+#endif
+    }
+    assert(rc == 0);
+    PyObject_GC_Track(self);
+    return (PyObject *)self;
+
+error_on_key:
+    self->state = NULL;
+error:
+    Py_DECREF(self);
+    return NULL;
+}
+
+/*
+ * Copy HMAC hash information from 'src' to 'out'.
+ */
+static void
+hmac_copy_hinfo(HMACObject *out, const HMACObject *src)
+{
+    assert(src->name != NULL);
+    out->name = Py_NewRef(src->name);
+    assert(src->kind != Py_hmac_kind_hash_unknown);
+    out->kind = src->kind;
+    assert(src->block_size <= Py_hmac_hash_max_block_size);
+    out->block_size = src->block_size;
+    assert(src->digest_size <= Py_hmac_hash_max_digest_size);
+    out->digest_size = src->digest_size;
+    assert(src->api.compute != NULL);
+    assert(src->api.compute_py != NULL);
+    out->api = src->api;
+}
+
+/*
+ * Copy the HMAC internal state from 'src' to 'out'.
+ *
+ * The internal state of 'out' must not already exist.
+ *
+ * Return 0 on success; otherwise, set an exception and return -1 on failure.
+ */
+static int
+hmac_copy_state(HMACObject *out, const HMACObject *src)
+{
+    assert(src->state != NULL);
+    out->state = Hacl_Streaming_HMAC_copy(src->state);
+    if (out->state == NULL) {
+        PyErr_NoMemory();
+        return -1;
+    }
+    return 0;
+}
+
+/*[clinic input]
+_hmac.HMAC.copy
+
+    cls: defining_class
+
+Return a copy ("clone") of the HMAC object.
+[clinic start generated code]*/
+
+static PyObject *
+_hmac_HMAC_copy_impl(HMACObject *self, PyTypeObject *cls)
+/*[clinic end generated code: output=a955bfa55b65b215 input=17b2c0ad0b147e36]*/
+{
+    hmacmodule_state *state = get_hmacmodule_state_by_cls(cls);
+    HMACObject *copy = PyObject_GC_New(HMACObject, state->hmac_type);
+    if (copy == NULL) {
+        return NULL;
+    }
+
+    ENTER_HASHLIB(self);
+    /* copy hash information */
+    hmac_copy_hinfo(copy, self);
+    /* copy internal state */
+    int rc = hmac_copy_state(copy, self);
+    LEAVE_HASHLIB(self);
+
+    if (rc < 0) {
+        Py_DECREF(copy);
+        return NULL;
+    }
+
+    HASHLIB_INIT_MUTEX(copy);
+    PyObject_GC_Track(copy);
+    return (PyObject *)copy;
+}
+
+/*
+ * Update the HMAC object with the given buffer.
+ *
+ * This unconditionally acquires the lock on the HMAC object.
+ *
+ * On DEBUG builds, each update() call is verified.
+ *
+ * Return 0 on success; otherwise, set an exception and return -1 on failure.
+ */
+static int
+hmac_update_state_with_lock(HMACObject *self, uint8_t *buf, Py_ssize_t len)
+{
+    int res = 0;
+    Py_BEGIN_ALLOW_THREADS
+        PyMutex_Lock(&self->mutex);  // unconditionally acquire a lock
+        Py_HMAC_HACL_UPDATE(self->state, buf, len, self->name, goto error);
+        goto done;
+#ifndef NDEBUG
+error:
+        res = -1;
+#else
+        Py_UNREACHABLE();
+#endif
+done:
+        PyMutex_Unlock(&self->mutex);
+    Py_END_ALLOW_THREADS
+    return res;
+}
+
+/*
+ * Update the HMAC object with the given buffer.
+ *
+ * This conditionally acquires the lock on the HMAC object.
+ *
+ * On DEBUG builds, each update() call is verified.
+ *
+ * Return 0 on success; otherwise, set an exception and return -1 on failure.
+ */
+static int
+hmac_update_state_cond_lock(HMACObject *self, uint8_t *buf, Py_ssize_t len)
+{
+    ENTER_HASHLIB(self);  // conditionally acquire a lock
+    Py_HMAC_HACL_UPDATE(self->state, buf, len, self->name, goto error);
+    LEAVE_HASHLIB(self);
+    return 0;
+
+#ifndef NDEBUG
+error:
+    LEAVE_HASHLIB(self);
+    return -1;
+#else
+    Py_UNREACHABLE();
+#endif
+}
+
+/*
+ * Update the internal HMAC state with the given buffer.
+ *
+ * Return 0 on success; otherwise, set an exception and return -1 on failure.
+ */
+static inline int
+hmac_update_state(HMACObject *self, uint8_t *buf, Py_ssize_t len)
+{
+    assert(buf != 0);
+    assert(len >= 0);
+    return len == 0
+               ? 0 /* nothing to do */
+               : len < HASHLIB_GIL_MINSIZE
+                     ? hmac_update_state_cond_lock(self, buf, len)
+                     : hmac_update_state_with_lock(self, buf, len);
+}
+
+/*[clinic input]
+_hmac.HMAC.update
+
+    msg as msgobj: object
+
+Update the HMAC object with the given message.
+[clinic start generated code]*/
+
+static PyObject *
+_hmac_HMAC_update_impl(HMACObject *self, PyObject *msgobj)
+/*[clinic end generated code: output=962134ada5e55985 input=7c0ea830efb03367]*/
+{
+    Py_buffer msg;
+    GET_BUFFER_VIEW_OR_ERROUT(msgobj, &msg);
+    int rc = hmac_update_state(self, msg.buf, msg.len);
+    PyBuffer_Release(&msg);
+    return rc < 0 ? NULL : Py_None;
+}
+
+/*
+ * Compute the HMAC-HASH digest from the internal HACL* state.
+ *
+ * At least 'self->digest_size' bytes should be available
+ * in the 'digest' pointed memory area.
+ *
+ * Return 0 on success; otherwise, set an exception and return -1 on failure.
+ *
+ * Note: this function may raise a MemoryError.
+ */
+static int
+hmac_digest_compute_cond_lock(HMACObject *self, uint8_t *digest)
+{
+    assert(digest != NULL);
+    hacl_errno_t rc;
+    ENTER_HASHLIB(self);  // conditionally acquire a lock
+    rc = Hacl_Streaming_HMAC_digest(self->state, digest, self->digest_size);
+    LEAVE_HASHLIB(self);
+    assert(
+        rc == Hacl_Streaming_Types_Success ||
+        rc == Hacl_Streaming_Types_OutOfMemory
+    );
+    return _hacl_convert_errno(rc, NULL);
+}
+
+/*[clinic input]
+_hmac.HMAC.digest
+
+Return the digest of the bytes passed to the update() method so far.
+
+This method may raise a MemoryError.
+[clinic start generated code]*/
+
+static PyObject *
+_hmac_HMAC_digest_impl(HMACObject *self)
+/*[clinic end generated code: output=5bf3cc5862d26ada input=a70feb0b8e2bbe7d]*/
+{
+    assert(self->digest_size <= Py_hmac_hash_max_digest_size);
+    uint8_t digest[Py_hmac_hash_max_digest_size];
+    if (hmac_digest_compute_cond_lock(self, digest) < 0) {
+        return NULL;
+    }
+    return PyBytes_FromStringAndSize((const char *)digest, self->digest_size);
+}
+
+/*[clinic input]
+_hmac.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.
+
+This method may raise a MemoryError.
+[clinic start generated code]*/
+
+static PyObject *
+_hmac_HMAC_hexdigest_impl(HMACObject *self)
+/*[clinic end generated code: output=6659807a09ae14ec input=493b2db8013982b9]*/
+{
+    assert(self->digest_size <= Py_hmac_hash_max_digest_size);
+    uint8_t digest[Py_hmac_hash_max_digest_size];
+    if (hmac_digest_compute_cond_lock(self, digest) < 0) {
+        return NULL;
+    }
+    return _Py_strhex((const char *)digest, self->digest_size);
+}
+
+/*[clinic input]
+@getter
+_hmac.HMAC.name
+[clinic start generated code]*/
+
+static PyObject *
+_hmac_HMAC_name_get_impl(HMACObject *self)
+/*[clinic end generated code: output=ae693f09778d96d9 input=41c2c5dd1cf47fbc]*/
+{
+    assert(self->name != NULL);
+    return PyUnicode_FromFormat("hmac-%U", self->name);
+}
+
+/*[clinic input]
+@getter
+_hmac.HMAC.block_size
+[clinic start generated code]*/
+
+static PyObject *
+_hmac_HMAC_block_size_get_impl(HMACObject *self)
+/*[clinic end generated code: output=52cb11dee4e80cae input=9dda6b8d43e995b4]*/
+{
+    return PyLong_FromUInt32(self->block_size);
+}
+
+/*[clinic input]
+@getter
+_hmac.HMAC.digest_size
+[clinic start generated code]*/
+
+static PyObject *
+_hmac_HMAC_digest_size_get_impl(HMACObject *self)
+/*[clinic end generated code: output=22eeca1010ac6255 input=5622bb2840025b5a]*/
+{
+    return PyLong_FromUInt32(self->digest_size);
+}
+
+static PyObject *
+HMACObject_repr(PyObject *op)
+{
+    HMACObject *self = HMACObject_CAST(op);
+    assert(self->name != NULL);
+    return PyUnicode_FromFormat("<%U HMAC object @ %p>", self->name, self);
+}
+
+static int
+HMACObject_clear(PyObject *op)
+{
+    HMACObject *self = HMACObject_CAST(op);
+    Py_CLEAR(self->name);
+    _hacl_hmac_state_free(self->state);
+    self->state = NULL;
+    return 0;
+}
+
+static void
+HMACObject_dealloc(PyObject *op)
+{
+    PyTypeObject *type = Py_TYPE(op);
+    PyObject_GC_UnTrack(op);
+    (void)HMACObject_clear(op);
+    type->tp_free(op);
+    Py_DECREF(type);
+}
+
+static int
+HMACObject_traverse(PyObject *op, visitproc visit, void *arg)
+{
+    Py_VISIT(Py_TYPE(op));
+    return 0;
+}
+
+static PyMethodDef HMACObject_methods[] = {
+    _HMAC_HMAC_COPY_METHODDEF
+    _HMAC_HMAC_UPDATE_METHODDEF
+    _HMAC_HMAC_DIGEST_METHODDEF
+    _HMAC_HMAC_HEXDIGEST_METHODDEF
+    {NULL, NULL, 0, NULL} /* sentinel */
+};
+
+static PyGetSetDef HMACObject_getsets[] = {
+    _HMAC_HMAC_NAME_GETSETDEF
+    _HMAC_HMAC_BLOCK_SIZE_GETSETDEF
+    _HMAC_HMAC_DIGEST_SIZE_GETSETDEF
+    {NULL, NULL, NULL, NULL, NULL} /* sentinel */
+};
+
+static PyType_Slot HMACObject_Type_slots[] = {
+    {Py_tp_repr, HMACObject_repr},
+    {Py_tp_methods, HMACObject_methods},
+    {Py_tp_getset, HMACObject_getsets},
+    {Py_tp_clear, HMACObject_clear},
+    {Py_tp_dealloc, HMACObject_dealloc},
+    {Py_tp_traverse, HMACObject_traverse},
+    {0, NULL} /* sentinel */
+};
+
+static PyType_Spec HMAC_Type_spec = {
+    .name = "_hmac.HMAC",
+    .basicsize = sizeof(HMACObject),
+    .flags = Py_TPFLAGS_DEFAULT
+             | Py_TPFLAGS_DISALLOW_INSTANTIATION
+             | Py_TPFLAGS_HEAPTYPE
+             | Py_TPFLAGS_IMMUTABLETYPE
+             | Py_TPFLAGS_HAVE_GC,
+    .slots = HMACObject_Type_slots,
+};
+
+// --- One-shot HMAC-HASH interface -------------------------------------------
+
+/*[clinic input]
+_hmac.compute_digest
+
+    key: object
+    msg: object
+    digest: object
+
+[clinic start generated code]*/
+
+static PyObject *
+_hmac_compute_digest_impl(PyObject *module, PyObject *key, PyObject *msg,
+                          PyObject *digest)
+/*[clinic end generated code: output=c519b7c4c9f57333 input=1c2bfc2cd8598574]*/
+{
+    hmacmodule_state *state = get_hmacmodule_state(module);
+    const py_hmac_hinfo *info = find_hash_info(state, digest);
+    if (info == NULL) {
+        return NULL;
+    }
+    assert(info->api.compute_py != NULL);
+    return info->api.compute_py(module, key, msg);
+}
+
+/*
+ * One-shot HMAC-HASH using the given HACL_HID.
+ *
+ * The length of the key and message buffers must not exceed UINT32_MAX,
+ * lest an OverflowError is raised. The Python implementation takes care
+ * of dispatching to the OpenSSL implementation in this case.
+ */
+#define Py_HMAC_HACL_ONESHOT(HACL_HID, KEY, MSG)                        \
+    do {                                                                \
+        Py_buffer keyview, msgview;                                     \
+        GET_BUFFER_VIEW_OR_ERROUT((KEY), &keyview);                     \
+        if (!has_uint32_t_buffer_length(&keyview)) {                    \
+            PyBuffer_Release(&keyview);                                 \
+            PyErr_SetString(PyExc_OverflowError, INVALID_KEY_LENGTH);   \
+            return NULL;                                                \
+        }                                                               \
+        GET_BUFFER_VIEW_OR_ERROR((MSG), &msgview,                       \
+                                 PyBuffer_Release(&keyview);            \
+                                 return NULL);                          \
+        if (!has_uint32_t_buffer_length(&msgview)) {                    \
+            PyBuffer_Release(&msgview);                                 \
+            PyBuffer_Release(&keyview);                                 \
+            PyErr_SetString(PyExc_OverflowError, INVALID_MSG_LENGTH);   \
+            return NULL;                                                \
+        }                                                               \
+        uint8_t out[Py_hmac_## HACL_HID ##_digest_size];                \
+        Py_hmac_## HACL_HID ##_compute_func(                            \
+            out,                                                        \
+            (uint8_t *)keyview.buf, (uint32_t)keyview.len,              \
+            (uint8_t *)msgview.buf, (uint32_t)msgview.len               \
+        );                                                              \
+        PyBuffer_Release(&msgview);                                     \
+        PyBuffer_Release(&keyview);                                     \
+        return PyBytes_FromStringAndSize(                               \
+            (const char *)out,                                          \
+            Py_hmac_## HACL_HID ##_digest_size                          \
+        );                                                              \
+    } while (0)
+
+/*[clinic input]
+_hmac.compute_md5
+
+    key: object
+    msg: object
+    /
+
+[clinic start generated code]*/
+
+static PyObject *
+_hmac_compute_md5_impl(PyObject *module, PyObject *key, PyObject *msg)
+/*[clinic end generated code: output=7837a4ceccbbf636 input=77a4b774c7d61218]*/
+{
+    Py_HMAC_HACL_ONESHOT(md5, key, msg);
+}
+
+/*[clinic input]
+_hmac.compute_sha1
+
+    key: object
+    msg: object
+    /
+
+[clinic start generated code]*/
+
+static PyObject *
+_hmac_compute_sha1_impl(PyObject *module, PyObject *key, PyObject *msg)
+/*[clinic end generated code: output=79fd7689c83691d8 input=3b64dccc6bdbe4ba]*/
+{
+    Py_HMAC_HACL_ONESHOT(sha1, key, msg);
+}
+
+/*[clinic input]
+_hmac.compute_sha224 as _hmac_compute_sha2_224
+
+    key: object
+    msg: object
+    /
+
+[clinic start generated code]*/
+
+static PyObject *
+_hmac_compute_sha2_224_impl(PyObject *module, PyObject *key, PyObject *msg)
+/*[clinic end generated code: output=7f21f1613e53979e input=a1a75f25f23449af]*/
+{
+    Py_HMAC_HACL_ONESHOT(sha2_224, key, msg);
+}
+
+/*[clinic input]
+_hmac.compute_sha256 as _hmac_compute_sha2_256
+
+    key: object
+    msg: object
+    /
+
+[clinic start generated code]*/
+
+static PyObject *
+_hmac_compute_sha2_256_impl(PyObject *module, PyObject *key, PyObject *msg)
+/*[clinic end generated code: output=d4a291f7d9a82459 input=5c9ccf2df048ace3]*/
+{
+    Py_HMAC_HACL_ONESHOT(sha2_256, key, msg);
+}
+
+/*[clinic input]
+_hmac.compute_sha384 as _hmac_compute_sha2_384
+
+    key: object
+    msg: object
+    /
+
+[clinic start generated code]*/
+
+static PyObject *
+_hmac_compute_sha2_384_impl(PyObject *module, PyObject *key, PyObject *msg)
+/*[clinic end generated code: output=f211fa26e3700c27 input=2fee2c14766af231]*/
+{
+    Py_HMAC_HACL_ONESHOT(sha2_384, key, msg);
+}
+
+/*[clinic input]
+_hmac.compute_sha512 as _hmac_compute_sha2_512
+
+    key: object
+    msg: object
+    /
+
+[clinic start generated code]*/
+
+static PyObject *
+_hmac_compute_sha2_512_impl(PyObject *module, PyObject *key, PyObject *msg)
+/*[clinic end generated code: output=d5c20373762cecca input=3371eaac315c7864]*/
+{
+    Py_HMAC_HACL_ONESHOT(sha2_512, key, msg);
+}
+
+/*[clinic input]
+_hmac.compute_sha3_224
+
+    key: object
+    msg: object
+    /
+
+[clinic start generated code]*/
+
+static PyObject *
+_hmac_compute_sha3_224_impl(PyObject *module, PyObject *key, PyObject *msg)
+/*[clinic end generated code: output=a242ccac9ad9c22b input=d0ab0c7d189c3d87]*/
+{
+    Py_HMAC_HACL_ONESHOT(sha3_224, key, msg);
+}
+
+/*[clinic input]
+_hmac.compute_sha3_256
+
+    key: object
+    msg: object
+    /
+
+[clinic start generated code]*/
+
+static PyObject *
+_hmac_compute_sha3_256_impl(PyObject *module, PyObject *key, PyObject *msg)
+/*[clinic end generated code: output=b539dbb61af2fe0b input=f05d7b6364b35d02]*/
+{
+    Py_HMAC_HACL_ONESHOT(sha3_256, key, msg);
+}
+
+/*[clinic input]
+_hmac.compute_sha3_384
+
+    key: object
+    msg: object
+    /
+
+[clinic start generated code]*/
+
+static PyObject *
+_hmac_compute_sha3_384_impl(PyObject *module, PyObject *key, PyObject *msg)
+/*[clinic end generated code: output=5eb372fb5c4ffd3a input=d842d393e7aa05ae]*/
+{
+    Py_HMAC_HACL_ONESHOT(sha3_384, key, msg);
+}
+
+/*[clinic input]
+_hmac.compute_sha3_512
+
+    key: object
+    msg: object
+    /
+
+[clinic start generated code]*/
+
+static PyObject *
+_hmac_compute_sha3_512_impl(PyObject *module, PyObject *key, PyObject *msg)
+/*[clinic end generated code: output=154bcbf8c2eacac1 input=166fe5baaeaabfde]*/
+{
+    Py_HMAC_HACL_ONESHOT(sha3_512, key, msg);
+}
+
+/*[clinic input]
+_hmac.compute_blake2s_32
+
+    key: object
+    msg: object
+    /
+
+[clinic start generated code]*/
+
+static PyObject *
+_hmac_compute_blake2s_32_impl(PyObject *module, PyObject *key, PyObject *msg)
+/*[clinic end generated code: output=cfc730791bc62361 input=d22c36e7fe31a985]*/
+{
+    Py_HMAC_HACL_ONESHOT(blake2s_32, key, msg);
+}
+
+/*[clinic input]
+_hmac.compute_blake2b_32
+
+    key: object
+    msg: object
+    /
+
+[clinic start generated code]*/
+
+static PyObject *
+_hmac_compute_blake2b_32_impl(PyObject *module, PyObject *key, PyObject *msg)
+/*[clinic end generated code: output=765c5c4fb9124636 input=4a35ee058d172f4b]*/
+{
+    Py_HMAC_HACL_ONESHOT(blake2b_32, key, msg);
+}
+
+// --- HMAC module methods ----------------------------------------------------
+
+static PyMethodDef hmacmodule_methods[] = {
+    _HMAC_NEW_METHODDEF
+    /* one-shot dispatcher */
+    _HMAC_COMPUTE_DIGEST_METHODDEF
+    /* one-shot methods */
+    _HMAC_COMPUTE_MD5_METHODDEF
+    _HMAC_COMPUTE_SHA1_METHODDEF
+    _HMAC_COMPUTE_SHA2_224_METHODDEF
+    _HMAC_COMPUTE_SHA2_256_METHODDEF
+    _HMAC_COMPUTE_SHA2_384_METHODDEF
+    _HMAC_COMPUTE_SHA2_512_METHODDEF
+    _HMAC_COMPUTE_SHA3_224_METHODDEF
+    _HMAC_COMPUTE_SHA3_256_METHODDEF
+    _HMAC_COMPUTE_SHA3_384_METHODDEF
+    _HMAC_COMPUTE_SHA3_512_METHODDEF
+    _HMAC_COMPUTE_BLAKE2S_32_METHODDEF
+    _HMAC_COMPUTE_BLAKE2B_32_METHODDEF
+    {NULL, NULL, 0, NULL} /* sentinel */
+};
+
+// --- HMAC static information table ------------------------------------------
+
+static inline Py_uhash_t
+py_hmac_hinfo_ht_hash(const void *name)
+{
+    return Py_HashBuffer(name, strlen((const char *)name));
+}
+
+static inline int
+py_hmac_hinfo_ht_comp(const void *a, const void *b)
+{
+    return strcmp((const char *)a, (const char *)b) == 0;
+}
+
+static void
+py_hmac_hinfo_ht_free(void *hinfo)
+{
+    py_hmac_hinfo *entry = (py_hmac_hinfo *)hinfo;
+    assert(entry->display_name != NULL);
+    if (--(entry->refcnt) == 0) {
+        Py_CLEAR(entry->display_name);
+        PyMem_Free(hinfo);
+    }
+}
+
+/*
+ * Equivalent to table.setdefault(key, info).
+ *
+ * Return 1 if a new item has been created, 0 if 'key' is NULL or
+ * an entry 'table[key]' existed, and -1 if a memory error occurs.
+ *
+ * To reduce memory footprint, 'info' may be a borrowed reference,
+ * namely, multiple keys can be associated with the same 'info'.
+ *
+ * In particular, resources owned by 'info' must only be released
+ * when a single key associated with 'info' remains.
+ */
+static int
+py_hmac_hinfo_ht_add(_Py_hashtable_t *table, const void *key, void *info)
+{
+    if (key == NULL || _Py_hashtable_get_entry(table, key) != NULL) {
+        return 0;
+    }
+    if (_Py_hashtable_set(table, key, info) < 0) {
+        assert(!PyErr_Occurred());
+        PyErr_NoMemory();
+        return -1;
+    }
+    return 1;
+}
+
+/*
+ * Create a new hashtable from the static 'py_hmac_static_hinfo' object,
+ * or set an exception and return NULL if an error occurs.
+ */
+static _Py_hashtable_t *
+py_hmac_hinfo_ht_new(void)
+{
+    _Py_hashtable_t *table = _Py_hashtable_new_full(
+        py_hmac_hinfo_ht_hash,
+        py_hmac_hinfo_ht_comp,
+        NULL,
+        py_hmac_hinfo_ht_free,
+        NULL
+    );
+
+    if (table == NULL) {
+        assert(!PyErr_Occurred());
+        PyErr_NoMemory();
+        return NULL;
+    }
+
+    for (const py_hmac_hinfo *e = py_hmac_static_hinfo; e->name != NULL; e++) {
+        /*
+         * The real kind of a HMAC object is obtained only once and is
+         * derived from the kind of the 'py_hmac_hinfo' that could be
+         * found by its name.
+         *
+         * Since 'vectorized_blake2{s,b}_32' depend on the runtime CPUID
+         * features, we should not create 'py_hmac_hinfo' entries for them.
+         */
+        assert_is_static_hmac_hash_kind(e->kind);
+
+        py_hmac_hinfo *value = PyMem_Malloc(sizeof(py_hmac_hinfo));
+        if (value == NULL) {
+            PyErr_NoMemory();
+            goto error;
+        }
+
+        memcpy(value, e, sizeof(py_hmac_hinfo));
+        assert(value->display_name == NULL);
+        value->refcnt = 0;
+
+#define Py_HMAC_HINFO_LINK(KEY)                                 \
+        do {                                                    \
+            int rc = py_hmac_hinfo_ht_add(table, KEY, value);   \
+            if (rc < 0) {                                       \
+                PyMem_Free(value);                              \
+                goto error;                                     \
+            }                                                   \
+            else if (rc == 1) {                                 \
+                value->refcnt++;                                \
+            }                                                   \
+        } while (0)
+        Py_HMAC_HINFO_LINK(e->name);
+        Py_HMAC_HINFO_LINK(e->hashlib_name);
+#undef Py_HMAC_HINFO_LINK
+        assert(value->refcnt > 0);
+        assert(value->display_name == NULL);
+        value->display_name = PyUnicode_FromString(
+            /* display name is synchronized with hashlib's name */
+            e->hashlib_name == NULL ? e->name : e->hashlib_name
+        );
+        if (value->display_name == NULL) {
+            PyMem_Free(value);
+            goto error;
+        }
+    }
+
+    return table;
+
+error:
+    _Py_hashtable_destroy(table);
+    return NULL;
+}
+
+// --- HMAC module initialization and finalization functions ------------------
+
+static int
+hmacmodule_init_hash_info_table(hmacmodule_state *state)
+{
+    // py_hmac_hinfo_ht_new() sets an exception on error
+    state->hinfo_table = py_hmac_hinfo_ht_new();
+    return state->hinfo_table == NULL ? -1 : 0;
+}
+
+static int
+hmacmodule_init_exceptions(PyObject *module, hmacmodule_state *state)
+{
+#define ADD_EXC(ATTR, NAME, BASE)                                       \
+    do {                                                                \
+        state->ATTR = PyErr_NewException("_hmac." NAME, BASE, NULL);    \
+        if (state->ATTR == NULL) {                                      \
+            return -1;                                                  \
+        }                                                               \
+        if (PyModule_AddObjectRef(module, NAME, state->ATTR) < 0) {     \
+            return -1;                                                  \
+        }                                                               \
+    } while (0)
+    ADD_EXC(unknown_hash_error, "UnknownHashError", PyExc_ValueError);
+#undef ADD_EXC
+    return 0;
+}
+
+static int
+hmacmodule_init_hmac_type(PyObject *module, hmacmodule_state *state)
+{
+    state->hmac_type = (PyTypeObject *)PyType_FromModuleAndSpec(module,
+                                                                &HMAC_Type_spec,
+                                                                NULL);
+    if (state->hmac_type == NULL) {
+        return -1;
+    }
+    if (PyModule_AddType(module, state->hmac_type) < 0) {
+        return -1;
+    }
+    return 0;
+}
+
+static int
+hmacmodule_init_strings(hmacmodule_state *state)
+{
+#define ADD_STR(ATTR, STRING)                       \
+    do {                                            \
+        state->ATTR = PyUnicode_FromString(STRING); \
+        if (state->ATTR == NULL) {                  \
+            return -1;                              \
+        }                                           \
+    } while (0)
+    ADD_STR(str_lower, "lower");
+#undef ADD_STR
+    return 0;
+}
+
+static void
+hmacmodule_init_cpu_features(hmacmodule_state *state)
+{
+#if HACL_CAN_COMPILE_SIMD128
+    // TODO: use py_cpuid_features (gh-125022) to deduce what we want
+    state->can_run_simd128 = false;
+#else
+    state->can_run_simd128 = false;
+#endif
+
+#if HACL_CAN_COMPILE_SIMD256
+    // TODO: use py_cpuid_features (gh-125022) to deduce what we want
+    state->can_run_simd256 = false;
+#else
+    state->can_run_simd256 = false;
+#endif
+}
+
+static int
+hmacmodule_exec(PyObject *module)
+{
+    hmacmodule_state *state = get_hmacmodule_state(module);
+    if (hmacmodule_init_hash_info_table(state) < 0) {
+        return -1;
+    }
+    if (hmacmodule_init_exceptions(module, state) < 0) {
+        return -1;
+    }
+    if (hmacmodule_init_hmac_type(module, state) < 0) {
+        return -1;
+    }
+    if (hmacmodule_init_strings(state) < 0) {
+        return -1;
+    }
+    hmacmodule_init_cpu_features(state);
+    return 0;
+}
+
+static int
+hmacmodule_traverse(PyObject *mod, visitproc visit, void *arg)
+{
+    Py_VISIT(Py_TYPE(mod));
+    hmacmodule_state *state = get_hmacmodule_state(mod);
+    Py_VISIT(state->unknown_hash_error);
+    Py_VISIT(state->hmac_type);
+    Py_VISIT(state->str_lower);
+    return 0;
+}
+
+static int
+hmacmodule_clear(PyObject *mod)
+{
+    hmacmodule_state *state = get_hmacmodule_state(mod);
+    if (state->hinfo_table != NULL) {
+        _Py_hashtable_destroy(state->hinfo_table);
+        state->hinfo_table = NULL;
+    }
+    Py_CLEAR(state->unknown_hash_error);
+    Py_CLEAR(state->hmac_type);
+    Py_CLEAR(state->str_lower);
+    return 0;
+}
+
+static inline void
+hmacmodule_free(void *mod)
+{
+    (void)hmacmodule_clear((PyObject *)mod);
+}
+
+static struct PyModuleDef_Slot hmacmodule_slots[] = {
+    {Py_mod_exec, hmacmodule_exec},
+    {Py_mod_multiple_interpreters, Py_MOD_PER_INTERPRETER_GIL_SUPPORTED},
+    {Py_mod_gil, Py_MOD_GIL_NOT_USED},
+    {0, NULL} /* sentinel */
+};
+
+static struct PyModuleDef _hmacmodule = {
+    PyModuleDef_HEAD_INIT,
+    .m_name = "_hmac",
+    .m_size = sizeof(hmacmodule_state),
+    .m_methods = hmacmodule_methods,
+    .m_slots = hmacmodule_slots,
+    .m_traverse = hmacmodule_traverse,
+    .m_clear = hmacmodule_clear,
+    .m_free = hmacmodule_free,
+};
+
+PyMODINIT_FUNC
+PyInit__hmac(void)
+{
+    return PyModuleDef_Init(&_hmacmodule);
+}
index 873f93063057dccdf1e98d6e5713e8205f3a0112..5c6f37ccf218964b7bab99d919b6eb7a017d031e 100644 (file)
@@ -14,19 +14,24 @@ extern PyObject* PyInit_faulthandler(void);
 extern PyObject* PyInit__tracemalloc(void);
 extern PyObject* PyInit_gc(void);
 extern PyObject* PyInit_math(void);
-extern PyObject* PyInit__md5(void);
 extern PyObject* PyInit_nt(void);
 extern PyObject* PyInit__operator(void);
 extern PyObject* PyInit__signal(void);
-extern PyObject* PyInit__sha1(void);
-extern PyObject* PyInit__sha2(void);
-extern PyObject* PyInit__sha3(void);
 extern PyObject* PyInit__statistics(void);
 extern PyObject* PyInit__sysconfig(void);
 extern PyObject* PyInit__typing(void);
-extern PyObject* PyInit__blake2(void);
 extern PyObject* PyInit_time(void);
 extern PyObject* PyInit__thread(void);
+
+/* cryptographic hash functions */
+extern PyObject* PyInit__blake2(void);
+extern PyObject* PyInit__md5(void);
+extern PyObject* PyInit__sha1(void);
+extern PyObject* PyInit__sha2(void);
+extern PyObject* PyInit__sha3(void);
+/* other cryptographic primitives */
+extern PyObject* PyInit__hmac(void);
+
 #ifdef WIN32
 extern PyObject* PyInit_msvcrt(void);
 extern PyObject* PyInit__locale(void);
@@ -98,17 +103,22 @@ struct _inittab _PyImport_Inittab[] = {
     {"nt", PyInit_nt}, /* Use the NT os functions, not posix */
     {"_operator", PyInit__operator},
     {"_signal", PyInit__signal},
-    {"_md5", PyInit__md5},
-    {"_sha1", PyInit__sha1},
-    {"_sha2", PyInit__sha2},
-    {"_sha3", PyInit__sha3},
-    {"_blake2", PyInit__blake2},
     {"_sysconfig", PyInit__sysconfig},
     {"time", PyInit_time},
     {"_thread", PyInit__thread},
     {"_tokenize", PyInit__tokenize},
     {"_typing", PyInit__typing},
     {"_statistics", PyInit__statistics},
+
+    /* cryptographic hash functions */
+    {"_blake2", PyInit__blake2},
+    {"_md5", PyInit__md5},
+    {"_sha1", PyInit__sha1},
+    {"_sha2", PyInit__sha2},
+    {"_sha3", PyInit__sha3},
+    /* other cryptographic primitives */
+    {"_hmac", PyInit__hmac},
+
 #ifdef WIN32
     {"msvcrt", PyInit_msvcrt},
     {"_locale", PyInit__locale},
index 009e4f2302e31143a2dffc22be2eee627b116f9e..27c50fa53dab87f743cfbc578199f7ee9881291c 100644 (file)
     <ClCompile Include="..\Modules\_hacl\Hacl_Hash_SHA1.c" />
     <ClCompile Include="..\Modules\_hacl\Hacl_Hash_SHA2.c" />
     <ClCompile Include="..\Modules\_hacl\Hacl_Hash_SHA3.c" />
+    <ClCompile Include="..\Modules\_hacl\Hacl_HMAC.c" />
+    <ClCompile Include="..\Modules\_hacl\Hacl_Streaming_HMAC.c" />
     <ClCompile Include="..\Modules\_hacl\Lib_Memzero0.c" />
     <ClCompile Include="..\Modules\_hacl\Hacl_Hash_Blake2b.c" />
     <ClCompile Include="..\Modules\_hacl\Hacl_Hash_Blake2s.c" />
     <ClCompile Include="..\Modules\faulthandler.c" />
     <ClCompile Include="..\Modules\gcmodule.c" />
     <ClCompile Include="..\Modules\getbuildinfo.c" />
+    <ClCompile Include="..\Modules\hmacmodule.c" />
     <ClCompile Include="..\Modules\itertoolsmodule.c" />
     <ClCompile Include="..\Modules\main.c" />
     <ClCompile Include="..\Modules\mathmodule.c" />
index 134212662ab3795aad6dcdb2d39eb1f1efcc51cd..617165b576e3620ef685a36da1f97ca149c34ede 100644 (file)
     <ClCompile Include="..\Modules\_hacl\Hacl_Hash_SHA3.c">
       <Filter>Modules</Filter>
     </ClCompile>
+    <ClCompile Include="..\Modules\_hacl\Hacl_HMAC.c">
+      <Filter>Modules</Filter>
+    </ClCompile>
+    <ClCompile Include="..\Modules\_hacl\Hacl_Streaming_HMAC.c">
+      <Filter>Modules</Filter>
+    </ClCompile>
     <ClCompile Include="..\Modules\_heapqmodule.c">
       <Filter>Modules</Filter>
     </ClCompile>
     <ClCompile Include="..\Modules\binascii.c">
       <Filter>Modules</Filter>
     </ClCompile>
+    <ClCompile Include="..\Modules\blake2module.c">
+      <Filter>Modules</Filter>
+    </ClCompile>
     <ClCompile Include="..\Modules\cmathmodule.c">
       <Filter>Modules</Filter>
     </ClCompile>
     <ClCompile Include="..\Modules\gcmodule.c">
       <Filter>Modules</Filter>
     </ClCompile>
+    <ClCompile Include="..\Modules\hmacmodule.c">
+      <Filter>Modules</Filter>
+    </ClCompile>
     <ClCompile Include="..\Modules\itertoolsmodule.c">
       <Filter>Modules</Filter>
     </ClCompile>
index ec8976277aad4ccf546a8d829989855e21cff89d..29dd5c1df0f23a1c39827c8675f597871996610f 100644 (file)
@@ -40,6 +40,7 @@ static const char* _Py_stdlib_module_names[] = {
 "_gdbm",
 "_hashlib",
 "_heapq",
+"_hmac",
 "_imp",
 "_interpchannels",
 "_interpqueues",
index a08b32fa45db3e57e33e4cb20ff8c023c4217081..037fe11ea223c793e68749bc0d87085d6fbf2618 100644 (file)
@@ -126,6 +126,7 @@ Modules/sha1module.c        Modules/_hacl/include
 Modules/sha2module.c   Modules/_hacl/include
 Modules/sha3module.c   Modules/_hacl/include
 Modules/blake2module.c Modules/_hacl/include
+Modules/hmacmodule.c   Modules/_hacl/include
 Objects/stringlib/*.h  Objects
 
 # possible system-installed headers, just in case
index 9b624d809879ff4c50d6afc3d72154b79a6cf83b..18e543ab33bb16eb4ed2617292f93967ae9568d4 100644 (file)
@@ -308,6 +308,7 @@ Modules/cmathmodule.c       -       tanh_special_values     -
 Modules/config.c       -       _PyImport_Inittab       -
 Modules/faulthandler.c -       faulthandler_handlers   -
 Modules/getnameinfo.c  -       gni_afdl        -
+Modules/hmacmodule.c   -       py_hmac_static_hinfo    -
 Modules/posixmodule.c  os_getxattr_impl        buffer_sizes    -
 Modules/posixmodule.c  os_listxattr_impl       buffer_sizes    -
 Modules/posixmodule.c  -       posix_constants_confstr -
index d7153914fe7b5eb9c63f869620b1dd6c8b392923..49de2f5db55e71de0f1c5788d44af58681dc64d0 100755 (executable)
--- a/configure
+++ b/configure
@@ -706,6 +706,8 @@ MODULE__CURSES_FALSE
 MODULE__CURSES_TRUE
 MODULE__CTYPES_FALSE
 MODULE__CTYPES_TRUE
+MODULE__HMAC_FALSE
+MODULE__HMAC_TRUE
 LIBHACL_SIMD256_OBJS
 LIBHACL_SIMD256_FLAGS
 LIBHACL_SIMD128_OBJS
 
 
 
+  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for stdlib extension module _hmac" >&5
+printf %s "checking for stdlib extension module _hmac... " >&6; }
+        if test "$py_cv_module__hmac" != "n/a"
+then :
+
+    if true
+then :
+  if true
+then :
+  py_cv_module__hmac=yes
+else case e in #(
+  e) py_cv_module__hmac=missing ;;
+esac
+fi
+else case e in #(
+  e) py_cv_module__hmac=disabled ;;
+esac
+fi
+
+fi
+  as_fn_append MODULE_BLOCK "MODULE__HMAC_STATE=$py_cv_module__hmac$as_nl"
+  if test "x$py_cv_module__hmac" = xyes
+then :
+
+    as_fn_append MODULE_BLOCK "MODULE__HMAC_CFLAGS=$LIBHACL_CFLAGS$as_nl"
+    as_fn_append MODULE_BLOCK "MODULE__HMAC_LDFLAGS=$LIBHACL_CFLAGS Modules/_hacl/libHacl_HMAC.a$as_nl"
+
+fi
+   if test "$py_cv_module__hmac" = yes; then
+  MODULE__HMAC_TRUE=
+  MODULE__HMAC_FALSE='#'
+else
+  MODULE__HMAC_TRUE='#'
+  MODULE__HMAC_FALSE=
+fi
+
+  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $py_cv_module__hmac" >&5
+printf "%s\n" "$py_cv_module__hmac" >&6; }
+
+
+
   { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for stdlib extension module _ctypes" >&5
 printf %s "checking for stdlib extension module _ctypes... " >&6; }
         if test "$py_cv_module__ctypes" != "n/a"
@@ -33820,6 +33863,10 @@ if test -z "${MODULE__BLAKE2_TRUE}" && test -z "${MODULE__BLAKE2_FALSE}"; then
   as_fn_error $? "conditional \"MODULE__BLAKE2\" was never defined.
 Usually this means the macro was only invoked conditionally." "$LINENO" 5
 fi
+if test -z "${MODULE__HMAC_TRUE}" && test -z "${MODULE__HMAC_FALSE}"; then
+  as_fn_error $? "conditional \"MODULE__HMAC\" was never defined.
+Usually this means the macro was only invoked conditionally." "$LINENO" 5
+fi
 if test -z "${MODULE__CTYPES_TRUE}" && test -z "${MODULE__CTYPES_FALSE}"; then
   as_fn_error $? "conditional \"MODULE__CTYPES\" was never defined.
 Usually this means the macro was only invoked conditionally." "$LINENO" 5
index 4e24930662c1f8ec35e376198320bcaee650d9f2..ac86a1f847e675e5f4735c28d63c05e06c5c7f30 100644 (file)
@@ -7920,6 +7920,13 @@ fi
 AC_SUBST([LIBHACL_SIMD256_FLAGS])
 AC_SUBST([LIBHACL_SIMD256_OBJS])
 
+dnl HMAC builtin library does not need OpenSSL for now. In the future
+dnl we might want to rely on OpenSSL EVP/NID interface or implement
+dnl our own for algorithm resolution.
+PY_STDLIB_MOD([_hmac], [], [],
+  [$LIBHACL_CFLAGS],
+  [$LIBHACL_CFLAGS Modules/_hacl/libHacl_HMAC.a])
+
 PY_STDLIB_MOD([_ctypes],
   [], [test "$have_libffi" = yes],
   [$NO_STRICT_OVERFLOW_CFLAGS $LIBFFI_CFLAGS], [$LIBFFI_LIBS])