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])