diff --git a/Doc/whatsnew/3.14.rst b/Doc/whatsnew/3.14.rst
index a561d3b3383fc5..c475d33472a318 100644
--- a/Doc/whatsnew/3.14.rst
+++ b/Doc/whatsnew/3.14.rst
@@ -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* `__ 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* `__ project.
+ (Contributed by Bénédikt Tran in :gh:`99108`.)
+
+
http
----
diff --git a/Lib/hmac.py b/Lib/hmac.py
index 30b6b478734dfc..2af11c26947064 100644
--- a/Lib/hmac.py
+++ b/Lib/hmac.py
@@ -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 @@
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 @@
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 @@ def __init__(self, key, msg=None, digestmod=''):
"""
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 @@ def _init_old(self, key, msg, digestmod):
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 @@ def hexdigest(self):
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)
diff --git a/Lib/test/support/hashlib_helper.py b/Lib/test/support/hashlib_helper.py
index bed3d696cb384d..06fac410a5e20f 100644
--- a/Lib/test/support/hashlib_helper.py
+++ b/Lib/test/support/hashlib_helper.py
@@ -8,11 +8,20 @@
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)
diff --git a/Lib/test/test_hmac.py b/Lib/test/test_hmac.py
index 03b9defdce87d7..42b8a91ae580d2 100644
--- a/Lib/test/test_hmac.py
+++ b/Lib/test/test_hmac.py
@@ -4,6 +4,7 @@
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 @@ def setUpClass(cls):
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 @@ def hmac_digest(self, key, msg=None, digestmod=None):
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 @@ def assert_hmac(
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 @@ def assert_hmac_new(
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 @@ def assert_hmac_new_by_name(
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 @@ def assert_hmac_hexdigest(
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 @@ def assert_hmac_hexdigest_by_name(
):
"""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 @@ def hmac_digest_by_name(self, key, msg=None, *, hashname):
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 @@ def raiser():
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 @@ def test_hmac_digest_digestmod_parameter(self):
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 @@ def test_repr(self):
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 @@ def HMAC(self, key, msg=None):
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 @@ def test_realcopy(self):
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:
diff --git a/Makefile.pre.in b/Makefile.pre.in
index 3ef0c6320c85db..e10c78d6403472 100644
--- a/Makefile.pre.in
+++ b/Makefile.pre.in
@@ -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
index 00000000000000..4cb6af14ee6c65
--- /dev/null
+++ b/Misc/NEWS.d/next/Core_and_Builtins/2025-02-15-14-36-32.gh-issue-99108.u6CfmK.rst
@@ -0,0 +1,2 @@
+Add support for built-in implementation of HMAC (:rfc:`2104`) based on
+HACL*. Patch by Bénédikt Tran.
diff --git a/Misc/sbom.spdx.json b/Misc/sbom.spdx.json
index 617c631c357db2..678a64df977432 100644
--- a/Misc/sbom.spdx.json
+++ b/Misc/sbom.spdx.json
@@ -281,6 +281,34 @@
],
"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": [
@@ -533,6 +561,34 @@
],
"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": [
@@ -659,6 +715,20 @@
],
"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": [
@@ -785,6 +855,20 @@
],
"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": [
@@ -813,6 +897,20 @@
],
"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": [
@@ -832,11 +930,11 @@
"checksums": [
{
"algorithm": "SHA1",
- "checksumValue": "37e3eb63c5c6f8ae671748bfde642c180b96d2de"
+ "checksumValue": "dbed915328619b1159012649a427c6928033dd90"
},
{
"algorithm": "SHA256",
- "checksumValue": "0b5c7892cc25a2b3467936c1f346a6186d9d0a257d1bd5671beda253b66e0f68"
+ "checksumValue": "0297ea0a5d1117e001d5dbb90f99d47ee9e0f9d3dd45da02ba5dc477e551cb5a"
}
],
"fileName": "Modules/_hacl/python_hacl_namespaces.h"
@@ -1817,6 +1915,16 @@
"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",
@@ -1907,6 +2015,16 @@
"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",
@@ -1952,6 +2070,11 @@
"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",
@@ -1997,6 +2120,11 @@
"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",
@@ -2007,6 +2135,11 @@
"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",
diff --git a/Modules/Setup b/Modules/Setup
index ddf39e0b966610..f075571ab94577 100644
--- a/Modules/Setup
+++ b/Modules/Setup
@@ -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
diff --git a/Modules/Setup.stdlib.in b/Modules/Setup.stdlib.in
index 6bb05a06a3465d..913c804c34ef76 100644
--- a/Modules/Setup.stdlib.in
+++ b/Modules/Setup.stdlib.in
@@ -78,11 +78,13 @@
@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
index 00000000000000..5299830865448a
--- /dev/null
+++ b/Modules/_hacl/Hacl_HMAC.c
@@ -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
index 00000000000000..10ff15183f2834
--- /dev/null
+++ b/Modules/_hacl/Hacl_HMAC.h
@@ -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
+#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
index 00000000000000..d28b39792af576
--- /dev/null
+++ b/Modules/_hacl/Hacl_Streaming_HMAC.c
@@ -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
index 00000000000000..a0806c02d0bb9f
--- /dev/null
+++ b/Modules/_hacl/Hacl_Streaming_HMAC.h
@@ -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
+#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
diff --git a/Modules/_hacl/README.md b/Modules/_hacl/README.md
index e6a156a54b3cee..0d6454cdd6efb3 100644
--- a/Modules/_hacl/README.md
+++ b/Modules/_hacl/README.md
@@ -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
index 00000000000000..ad29d50760c3aa
--- /dev/null
+++ b/Modules/_hacl/internal/Hacl_HMAC.h
@@ -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
+#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
index 00000000000000..acc4f3996026ee
--- /dev/null
+++ b/Modules/_hacl/internal/Hacl_Streaming_HMAC.h
@@ -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
+#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
index 00000000000000..34e0161b33b951
--- /dev/null
+++ b/Modules/_hacl/libintvector-shim.h
@@ -0,0 +1,35 @@
+/* Some older compilers do not let you include, e.g., 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
diff --git a/Modules/_hacl/python_hacl_namespaces.h b/Modules/_hacl/python_hacl_namespaces.h
index 8a1f4aef384d62..e234a123e1606d 100644
--- a/Modules/_hacl/python_hacl_namespaces.h
+++ b/Modules/_hacl/python_hacl_namespaces.h
@@ -209,4 +209,31 @@
#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
diff --git a/Modules/_hacl/refresh.sh b/Modules/_hacl/refresh.sh
index 86e5b4b0161072..903d7fb2afd362 100755
--- a/Modules/_hacl/refresh.sh
+++ b/Modules/_hacl/refresh.sh
@@ -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 !#include \n#include "python_hacl_namespaces.h"!' Hacl_Hash_*.h
+$sed -i -z 's!#include !#include \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
index 00000000000000..1ceb2d809e830a
--- /dev/null
+++ b/Modules/clinic/hmacmodule.c.h
@@ -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
index 00000000000000..faf4e0a023147e
--- /dev/null
+++ b/Modules/hmacmodule.c
@@ -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
+
+#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);
+}
diff --git a/PC/config.c b/PC/config.c
index 873f93063057dc..5c6f37ccf21896 100644
--- a/PC/config.c
+++ b/PC/config.c
@@ -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},
diff --git a/PCbuild/pythoncore.vcxproj b/PCbuild/pythoncore.vcxproj
index 009e4f2302e311..27c50fa53dab87 100644
--- a/PCbuild/pythoncore.vcxproj
+++ b/PCbuild/pythoncore.vcxproj
@@ -428,6 +428,8 @@
+
+
@@ -464,6 +466,7 @@
+
diff --git a/PCbuild/pythoncore.vcxproj.filters b/PCbuild/pythoncore.vcxproj.filters
index 134212662ab379..617165b576e362 100644
--- a/PCbuild/pythoncore.vcxproj.filters
+++ b/PCbuild/pythoncore.vcxproj.filters
@@ -959,6 +959,12 @@
Modules
+
+ Modules
+
+
+ Modules
+
Modules
@@ -1013,6 +1019,9 @@
Modules
+
+ Modules
+
Modules
@@ -1028,6 +1037,9 @@
Modules
+
+ Modules
+
Modules
diff --git a/Python/stdlib_module_names.h b/Python/stdlib_module_names.h
index ec8976277aad4c..29dd5c1df0f23a 100644
--- a/Python/stdlib_module_names.h
+++ b/Python/stdlib_module_names.h
@@ -40,6 +40,7 @@ static const char* _Py_stdlib_module_names[] = {
"_gdbm",
"_hashlib",
"_heapq",
+"_hmac",
"_imp",
"_interpchannels",
"_interpqueues",
diff --git a/Tools/c-analyzer/cpython/_parser.py b/Tools/c-analyzer/cpython/_parser.py
index a08b32fa45db3e..037fe11ea223c7 100644
--- a/Tools/c-analyzer/cpython/_parser.py
+++ b/Tools/c-analyzer/cpython/_parser.py
@@ -126,6 +126,7 @@ def clean_lines(text):
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
diff --git a/Tools/c-analyzer/cpython/ignored.tsv b/Tools/c-analyzer/cpython/ignored.tsv
index 9b624d809879ff..18e543ab33bb16 100644
--- a/Tools/c-analyzer/cpython/ignored.tsv
+++ b/Tools/c-analyzer/cpython/ignored.tsv
@@ -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 -
diff --git a/configure b/configure
index d7153914fe7b5e..49de2f5db55e71 100755
--- 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
@@ -32267,6 +32269,47 @@ fi
+ { 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
diff --git a/configure.ac b/configure.ac
index 4e24930662c1f8..ac86a1f847e675 100644
--- a/configure.ac
+++ b/configure.ac
@@ -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])