From d2e72aa825520419f1f666def610bbfc4f4f5e7b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?B=C3=A9n=C3=A9dikt=20Tran?= <10796600+picnixz@users.noreply.github.com> Date: Thu, 12 Dec 2024 16:08:47 +0100 Subject: [PATCH 01/45] update vendored HACL* project This pull the required files from the HACL* project. Once streaming HACL* HMAC becomes available upstream, we will update this commit with the required files. --- Misc/sbom.spdx.json | 137 +- Modules/_hacl/Hacl_HMAC.c | 1567 +++++++++++ Modules/_hacl/Hacl_HMAC.h | 224 ++ Modules/_hacl/Hacl_Streaming_HMAC.c | 2551 ++++++++++++++++++ Modules/_hacl/Hacl_Streaming_HMAC.h | 134 + Modules/_hacl/README.md | 14 +- Modules/_hacl/internal/Hacl_HMAC.h | 52 + Modules/_hacl/internal/Hacl_Streaming_HMAC.h | 94 + Modules/_hacl/libintvector-shim.h | 35 + Modules/_hacl/python_hacl_namespaces.h | 36 + Modules/_hacl/refresh.sh | 21 +- 11 files changed, 4854 insertions(+), 11 deletions(-) create mode 100644 Modules/_hacl/Hacl_HMAC.c create mode 100644 Modules/_hacl/Hacl_HMAC.h create mode 100644 Modules/_hacl/Hacl_Streaming_HMAC.c create mode 100644 Modules/_hacl/Hacl_Streaming_HMAC.h create mode 100644 Modules/_hacl/internal/Hacl_HMAC.h create mode 100644 Modules/_hacl/internal/Hacl_Streaming_HMAC.h create mode 100644 Modules/_hacl/libintvector-shim.h diff --git a/Misc/sbom.spdx.json b/Misc/sbom.spdx.json index 2bfe2a33fd1b1b..67a07d574e1437 100644 --- a/Misc/sbom.spdx.json +++ b/Misc/sbom.spdx.json @@ -295,6 +295,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": [ @@ -547,6 +575,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": [ @@ -673,6 +729,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": [ @@ -799,6 +869,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": [ @@ -827,6 +911,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": [ @@ -846,11 +944,11 @@ "checksums": [ { "algorithm": "SHA1", - "checksumValue": "37e3eb63c5c6f8ae671748bfde642c180b96d2de" + "checksumValue": "bd1b8f44a5391b2c6e7703b32d44ce1f2723ff99" }, { "algorithm": "SHA256", - "checksumValue": "0b5c7892cc25a2b3467936c1f346a6186d9d0a257d1bd5671beda253b66e0f68" + "checksumValue": "56c7482895b5969475aae40fd1f83e65d421a2667f68764d54b8e2f6f173b7ad" } ], "fileName": "Modules/_hacl/python_hacl_namespaces.h" @@ -1836,6 +1934,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", @@ -1926,6 +2034,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", @@ -1971,6 +2089,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", @@ -2016,6 +2139,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", @@ -2026,6 +2154,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/_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..184ec34942705d 100644 --- a/Modules/_hacl/python_hacl_namespaces.h +++ b/Modules/_hacl/python_hacl_namespaces.h @@ -209,4 +209,40 @@ #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 + +// 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. +#ifndef HACL_CAN_COMPILE_VEC128 +#define HACL_CAN_COMPILE_VEC128 HACL_CAN_COMPILE_SIMD128 +#endif +#ifndef HACL_CAN_COMPILE_VEC256 +#define HACL_CAN_COMPILE_VEC256 HACL_CAN_COMPILE_SIMD256 +#endif + #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) From 9fa2b0b9c177b83407fc97ef1d91a9561773ebba Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?B=C3=A9n=C3=A9dikt=20Tran?= <10796600+picnixz@users.noreply.github.com> Date: Thu, 12 Dec 2024 16:12:05 +0100 Subject: [PATCH 02/45] prepare build configurations This commit contains auto-generated files and files needed for the minimal build. --- Makefile.pre.in | 123 ++++++++++++++++++++++++----- Modules/Setup | 10 +-- Modules/Setup.stdlib.in | 10 +-- PCbuild/pythoncore.vcxproj | 2 + PCbuild/pythoncore.vcxproj.filters | 9 +++ 5 files changed, 125 insertions(+), 29 deletions(-) diff --git a/Makefile.pre.in b/Makefile.pre.in index a65854ac125c60..e2ce9573b09177 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@ @@ -655,30 +659,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= \ @@ -694,6 +733,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 @@ -1403,10 +1455,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 @@ -1414,6 +1481,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 @@ -1439,6 +1513,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. @@ -3211,11 +3295,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/Modules/Setup b/Modules/Setup index ddf39e0b966610..3537523bbc0a50 100644 --- a/Modules/Setup +++ b/Modules/Setup @@ -165,11 +165,11 @@ 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 # text encodings and unicode #_codecs_cn cjkcodecs/_codecs_cn.c diff --git a/Modules/Setup.stdlib.in b/Modules/Setup.stdlib.in index 6bb05a06a3465d..66352fadb79542 100644 --- a/Modules/Setup.stdlib.in +++ b/Modules/Setup.stdlib.in @@ -78,11 +78,11 @@ @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 ############################################################################ # XML and text diff --git a/PCbuild/pythoncore.vcxproj b/PCbuild/pythoncore.vcxproj index 4eda251ee0ce53..ec414378c07fe7 100644 --- a/PCbuild/pythoncore.vcxproj +++ b/PCbuild/pythoncore.vcxproj @@ -431,6 +431,8 @@ + + diff --git a/PCbuild/pythoncore.vcxproj.filters b/PCbuild/pythoncore.vcxproj.filters index 6c76a6ab592a84..1afd4a70b18793 100644 --- a/PCbuild/pythoncore.vcxproj.filters +++ b/PCbuild/pythoncore.vcxproj.filters @@ -932,6 +932,12 @@ Modules + + Modules + + + Modules + Modules @@ -986,6 +992,9 @@ Modules + + Modules + Modules From 1f33995f8aa8631d881d97dfbe331ca52f9c6b99 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?B=C3=A9n=C3=A9dikt=20Tran?= <10796600+picnixz@users.noreply.github.com> Date: Fri, 13 Dec 2024 10:14:22 +0100 Subject: [PATCH 03/45] add HMAC module --- Modules/Setup | 1 + Modules/Setup.stdlib.in | 2 ++ Modules/hmacmodule.c | 54 +++++++++++++++++++++++++++++ PC/config.c | 2 ++ PCbuild/pythoncore.vcxproj | 1 + PCbuild/pythoncore.vcxproj.filters | 3 ++ Python/stdlib_module_names.h | 1 + Tools/c-analyzer/cpython/_parser.py | 1 + configure | 47 +++++++++++++++++++++++++ configure.ac | 7 ++++ 10 files changed, 119 insertions(+) create mode 100644 Modules/hmacmodule.c diff --git a/Modules/Setup b/Modules/Setup index 3537523bbc0a50..f075571ab94577 100644 --- a/Modules/Setup +++ b/Modules/Setup @@ -170,6 +170,7 @@ PYTHONPATH=$(COREPYTHONPATH) #_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 66352fadb79542..913c804c34ef76 100644 --- a/Modules/Setup.stdlib.in +++ b/Modules/Setup.stdlib.in @@ -84,6 +84,8 @@ @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/hmacmodule.c b/Modules/hmacmodule.c new file mode 100644 index 00000000000000..a69b67baf5be7a --- /dev/null +++ b/Modules/hmacmodule.c @@ -0,0 +1,54 @@ +/* + * @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" + +// --- HMAC module clinic configuration --------------------------------------- + +/*[clinic input] +module _hmac +[clinic start generated code]*/ +/*[clinic end generated code: output=da39a3ee5e6b4b0d input=799f0f10157d561f]*/ + +// --- HMAC module methods ---------------------------------------------------- + +static PyMethodDef hmacmodule_methods[] = { + {NULL, NULL, 0, NULL} /* sentinel */ +}; + +// --- HMAC module initialization and finalization functions ------------------ + +static struct PyModuleDef_Slot hmacmodule_slots[] = { + {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 = 0, + .m_methods = hmacmodule_methods, + .m_slots = hmacmodule_slots, +}; + +PyMODINIT_FUNC +PyInit__hmac(void) +{ + return PyModuleDef_Init(&_hmacmodule); +} diff --git a/PC/config.c b/PC/config.c index b744f711b0d636..1af3d1ecbd2851 100644 --- a/PC/config.c +++ b/PC/config.c @@ -25,6 +25,7 @@ extern PyObject* PyInit__statistics(void); extern PyObject* PyInit__sysconfig(void); extern PyObject* PyInit__typing(void); extern PyObject* PyInit__blake2(void); +extern PyObject* PyInit__hmac(void); extern PyObject* PyInit_time(void); extern PyObject* PyInit__thread(void); #ifdef WIN32 @@ -102,6 +103,7 @@ struct _inittab _PyImport_Inittab[] = { {"_sha2", PyInit__sha2}, {"_sha3", PyInit__sha3}, {"_blake2", PyInit__blake2}, + {"_hmac", PyInit__hmac}, {"_sysconfig", PyInit__sysconfig}, {"time", PyInit_time}, {"_thread", PyInit__thread}, diff --git a/PCbuild/pythoncore.vcxproj b/PCbuild/pythoncore.vcxproj index ec414378c07fe7..0d2168b952c9cb 100644 --- a/PCbuild/pythoncore.vcxproj +++ b/PCbuild/pythoncore.vcxproj @@ -469,6 +469,7 @@ + diff --git a/PCbuild/pythoncore.vcxproj.filters b/PCbuild/pythoncore.vcxproj.filters index 1afd4a70b18793..49a42f52a1f0e8 100644 --- a/PCbuild/pythoncore.vcxproj.filters +++ b/PCbuild/pythoncore.vcxproj.filters @@ -1010,6 +1010,9 @@ Modules + + Modules + Modules diff --git a/Python/stdlib_module_names.h b/Python/stdlib_module_names.h index 584b050fc4bb6e..544856c53655d7 100644 --- a/Python/stdlib_module_names.h +++ b/Python/stdlib_module_names.h @@ -39,6 +39,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/configure b/configure index d0ae103014a301..a2c8e29b0a30e4 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 @@ -32224,6 +32226,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" @@ -33777,6 +33820,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 8bb0f1c6ef4a49..1a91a5ec6c8938 100644 --- a/configure.ac +++ b/configure.ac @@ -7898,6 +7898,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]) From 816261635ba8558a681bf82ff633a3244f8aa926 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?B=C3=A9n=C3=A9dikt=20Tran?= <10796600+picnixz@users.noreply.github.com> Date: Fri, 13 Dec 2024 10:14:22 +0100 Subject: [PATCH 04/45] add HMAC module state This adds the `hmacmodule_state` structure. This structure will grow later, containing interned strings, specific exception types, object types as well as internal data. --- Modules/hmacmodule.c | 47 +++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 46 insertions(+), 1 deletion(-) diff --git a/Modules/hmacmodule.c b/Modules/hmacmodule.c index a69b67baf5be7a..60e34064fecc30 100644 --- a/Modules/hmacmodule.c +++ b/Modules/hmacmodule.c @@ -18,6 +18,19 @@ #include "Python.h" +// --- HMAC module state ------------------------------------------------------ + +typedef struct hmacmodule_state { +} hmacmodule_state; + +static inline hmacmodule_state * +get_hmacmodule_state(PyObject *module) +{ + void *state = PyModule_GetState(module); + assert(state != NULL); + return (hmacmodule_state *)state; +} + // --- HMAC module clinic configuration --------------------------------------- /*[clinic input] @@ -33,7 +46,36 @@ static PyMethodDef hmacmodule_methods[] = { // --- HMAC module initialization and finalization functions ------------------ +static int +hmacmodule_exec(PyObject *module) +{ + hmacmodule_state *state = get_hmacmodule_state(module); + return 0; +} + +static int +hmacmodule_traverse(PyObject *mod, visitproc visit, void *arg) +{ + Py_VISIT(Py_TYPE(mod)); + hmacmodule_state *state = get_hmacmodule_state(mod); + return 0; +} + +static int +hmacmodule_clear(PyObject *mod) +{ + hmacmodule_state *state = get_hmacmodule_state(mod); + 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 */ @@ -42,9 +84,12 @@ static struct PyModuleDef_Slot hmacmodule_slots[] = { static struct PyModuleDef _hmacmodule = { PyModuleDef_HEAD_INIT, .m_name = "_hmac", - .m_size = 0, + .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 From 02988f01a3022fc932b00fbeac4eb8104aa164d8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?B=C3=A9n=C3=A9dikt=20Tran?= <10796600+picnixz@users.noreply.github.com> Date: Fri, 13 Dec 2024 10:56:48 +0100 Subject: [PATCH 05/45] add HMAC-HASH static information Static information for each hash function supported by HACL* HMAC is added (discriminated type, names, block size, digest size). By convention, `_hmac` defines its own standard names but allows hashlib-based aliases (e.g., "sha2_224" is the standard HMAC name that can also be obtained when using "sha224"). --- Modules/hmacmodule.c | 157 +++++++++++++++++++++++++++ Tools/c-analyzer/cpython/ignored.tsv | 1 + 2 files changed, 158 insertions(+) diff --git a/Modules/hmacmodule.c b/Modules/hmacmodule.c index 60e34064fecc30..630dba2cd1a810 100644 --- a/Modules/hmacmodule.c +++ b/Modules/hmacmodule.c @@ -17,10 +17,127 @@ #endif #include "Python.h" +#include "pycore_hashtable.h" + +#include "_hacl/Hacl_Streaming_HMAC.h" // Hacl_Agile_Hash_* identifiers + +// --- HMAC underlying hash function static information ----------------------- + +#define Py_hmac_hash_max_block_size 128 +#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 + +/* SHA-1 family */ +// HACL_HID = sha1 +#define Py_hmac_sha1_block_size 64 +#define Py_hmac_sha1_digest_size 20 + +/* SHA-2 family */ +// HACL_HID = sha2_224 +#define Py_hmac_sha2_224_block_size 64 +#define Py_hmac_sha2_224_digest_size 28 + +// HACL_HID = sha2_256 +#define Py_hmac_sha2_256_block_size 64 +#define Py_hmac_sha2_256_digest_size 32 + +// HACL_HID = sha2_384 +#define Py_hmac_sha2_384_block_size 128 +#define Py_hmac_sha2_384_digest_size 48 + +// HACL_HID = sha2_512 +#define Py_hmac_sha2_512_block_size 128 +#define Py_hmac_sha2_512_digest_size 64 + +/* SHA-3 family */ +// HACL_HID = sha3_224 +#define Py_hmac_sha3_224_block_size 144 +#define Py_hmac_sha3_224_digest_size 28 + +// HACL_HID = sha3_256 +#define Py_hmac_sha3_256_block_size 136 +#define Py_hmac_sha3_256_digest_size 32 + +// HACL_HID = sha3_384 +#define Py_hmac_sha3_384_block_size 104 +#define Py_hmac_sha3_384_digest_size 48 + +// HACL_HID = sha3_512 +#define Py_hmac_sha3_512_block_size 72 +#define Py_hmac_sha3_512_digest_size 64 + +/* Blake2 family */ +// HACL_HID = blake2s_32 +#define Py_hmac_blake2s_32_block_size 64 +#define Py_hmac_blake2s_32_digest_size 32 + +// HACL_HID = blake2b_32 +#define Py_hmac_blake2b_32_block_size 128 +#define Py_hmac_blake2b_32_digest_size 64 + +/* 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) +#undef DECL_HACL_HMAC_HASH_KIND +} HMAC_Hash_Kind; + +/* + * 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; + + /* + * 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; } hmacmodule_state; static inline hmacmodule_state * @@ -38,6 +155,46 @@ module _hmac [clinic start generated code]*/ /*[clinic end generated code: output=da39a3ee5e6b4b0d input=799f0f10157d561f]*/ +// --- Helpers ---------------------------------------------------------------- + +/* Static information used to construct the hash table. */ +static const py_hmac_hinfo py_hmac_static_hinfo[] = { +#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, \ + .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 + /* sentinel */ + { + NULL, Py_hmac_kind_hash_unknown, 0, 0, + NULL, NULL, + 0, + }, +}; + // --- HMAC module methods ---------------------------------------------------- static PyMethodDef hmacmodule_methods[] = { diff --git a/Tools/c-analyzer/cpython/ignored.tsv b/Tools/c-analyzer/cpython/ignored.tsv index 9b624d809879ff..ef663ed45622eb 100644 --- a/Tools/c-analyzer/cpython/ignored.tsv +++ b/Tools/c-analyzer/cpython/ignored.tsv @@ -307,6 +307,7 @@ Modules/cmathmodule.c - sqrt_special_values - Modules/cmathmodule.c - tanh_special_values - Modules/config.c - _PyImport_Inittab - Modules/faulthandler.c - faulthandler_handlers - +Modules/faulthandler.c - py_hmac_static_hinfo - Modules/getnameinfo.c - gni_afdl - Modules/posixmodule.c os_getxattr_impl buffer_sizes - Modules/posixmodule.c os_listxattr_impl buffer_sizes - From 8df0fbfa898b994bfae2d9fbe1a9f811c3298446 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?B=C3=A9n=C3=A9dikt=20Tran?= <10796600+picnixz@users.noreply.github.com> Date: Fri, 13 Dec 2024 10:24:03 +0100 Subject: [PATCH 06/45] implement HMAC-HASH known hashes table This commit implements the bits needed for allocating, freeing, modifying and introspecting a hash table that maps canonical HMAC hash algorithm names to static data. --- Modules/hmacmodule.c | 132 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 132 insertions(+) diff --git a/Modules/hmacmodule.c b/Modules/hmacmodule.c index 630dba2cd1a810..8a3c62b0243679 100644 --- a/Modules/hmacmodule.c +++ b/Modules/hmacmodule.c @@ -201,12 +201,140 @@ static PyMethodDef hmacmodule_methods[] = { {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++) { + assert(e->kind != Py_hmac_kind_hash_unknown); + 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_exec(PyObject *module) { hmacmodule_state *state = get_hmacmodule_state(module); + if (hmacmodule_init_hash_info_table(state) < 0) { + return -1; + } return 0; } @@ -222,6 +350,10 @@ 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; + } return 0; } From f541600774a7392e4c6dae5cc9161dbb66249ff8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?B=C3=A9n=C3=A9dikt=20Tran?= <10796600+picnixz@users.noreply.github.com> Date: Fri, 13 Dec 2024 10:26:52 +0100 Subject: [PATCH 07/45] add HMAC unknown hash exception type This commit adds the exception type used when a requested hash name is not recognized by `_hmac`. --- Modules/hmacmodule.c | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/Modules/hmacmodule.c b/Modules/hmacmodule.c index 8a3c62b0243679..e788bccce5b720 100644 --- a/Modules/hmacmodule.c +++ b/Modules/hmacmodule.c @@ -138,6 +138,7 @@ typedef struct py_hmac_hinfo { typedef struct hmacmodule_state { _Py_hashtable_t *hinfo_table; + PyObject *unknown_hash_error; } hmacmodule_state; static inline hmacmodule_state * @@ -328,6 +329,24 @@ hmacmodule_init_hash_info_table(hmacmodule_state *state) 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_exec(PyObject *module) { @@ -335,6 +354,9 @@ hmacmodule_exec(PyObject *module) if (hmacmodule_init_hash_info_table(state) < 0) { return -1; } + if (hmacmodule_init_exceptions(module, state) < 0) { + return -1; + } return 0; } @@ -343,6 +365,7 @@ 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); return 0; } @@ -354,6 +377,7 @@ hmacmodule_clear(PyObject *mod) _Py_hashtable_destroy(state->hinfo_table); state->hinfo_table = NULL; } + Py_CLEAR(state->unknown_hash_error); return 0; } From 88d2b967ef8c59743ce310c3fba624b82b1c6b63 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?B=C3=A9n=C3=A9dikt=20Tran?= <10796600+picnixz@users.noreply.github.com> Date: Fri, 13 Dec 2024 11:00:35 +0100 Subject: [PATCH 08/45] intern `"lower"` for `str.lower` calls --- Modules/hmacmodule.c | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/Modules/hmacmodule.c b/Modules/hmacmodule.c index e788bccce5b720..6dc1c0a05045c8 100644 --- a/Modules/hmacmodule.c +++ b/Modules/hmacmodule.c @@ -139,6 +139,8 @@ typedef struct py_hmac_hinfo { typedef struct hmacmodule_state { _Py_hashtable_t *hinfo_table; PyObject *unknown_hash_error; + /* interned strings */ + PyObject *str_lower; } hmacmodule_state; static inline hmacmodule_state * @@ -347,6 +349,21 @@ hmacmodule_init_exceptions(PyObject *module, hmacmodule_state *state) 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 int hmacmodule_exec(PyObject *module) { @@ -357,6 +374,9 @@ hmacmodule_exec(PyObject *module) if (hmacmodule_init_exceptions(module, state) < 0) { return -1; } + if (hmacmodule_init_strings(state) < 0) { + return -1; + } return 0; } @@ -366,6 +386,7 @@ 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->str_lower); return 0; } @@ -378,6 +399,7 @@ hmacmodule_clear(PyObject *mod) state->hinfo_table = NULL; } Py_CLEAR(state->unknown_hash_error); + Py_CLEAR(state->str_lower); return 0; } From 77e51d4b437fccb7ab830f9f865cddec17b4fab3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?B=C3=A9n=C3=A9dikt=20Tran?= <10796600+picnixz@users.noreply.github.com> Date: Fri, 13 Dec 2024 11:04:32 +0100 Subject: [PATCH 09/45] implement hash information lookup This commit implements the bits needed for finding static hash information data from an algorithm name. Search is case-insensitive and only algorithm names given as strings are supported. --- Modules/hmacmodule.c | 90 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 90 insertions(+) diff --git a/Modules/hmacmodule.c b/Modules/hmacmodule.c index 6dc1c0a05045c8..ce389c81d81da1 100644 --- a/Modules/hmacmodule.c +++ b/Modules/hmacmodule.c @@ -21,6 +21,8 @@ #include "_hacl/Hacl_Streaming_HMAC.h" // Hacl_Agile_Hash_* identifiers +#include + // --- HMAC underlying hash function static information ----------------------- #define Py_hmac_hash_max_block_size 128 @@ -198,6 +200,94 @@ static const py_hmac_hinfo py_hmac_static_hinfo[] = { }, }; +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; +} + +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. + * + * If an error occurs or if nothing can be found, this + * returns -1 or 0 respectively, and sets 'info' to NULL. + * Otherwise, this returns 1 and stores the result in 'info'. + * + * 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; +} + +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; + } + return info; +} + // --- HMAC module methods ---------------------------------------------------- static PyMethodDef hmacmodule_methods[] = { From 264e43cd59b10f42b4a977c2b509b1b5955c1f19 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?B=C3=A9n=C3=A9dikt=20Tran?= <10796600+picnixz@users.noreply.github.com> Date: Fri, 13 Dec 2024 10:31:15 +0100 Subject: [PATCH 10/45] add one-shot HMAC HACL* minimal API This commit adds the interface needed to interact with one-shot HACL*-HMAC. One-shot HACL*-HMAC only supports keys or messages of 32-bit length. --- Modules/hmacmodule.c | 64 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 64 insertions(+) diff --git a/Modules/hmacmodule.c b/Modules/hmacmodule.c index ce389c81d81da1..34b039fce82ee8 100644 --- a/Modules/hmacmodule.c +++ b/Modules/hmacmodule.c @@ -19,12 +19,16 @@ #include "Python.h" #include "pycore_hashtable.h" +#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 // --- HMAC underlying hash function static information ----------------------- +#define UINT32_MAX_AS_SSIZE_T ((Py_ssize_t)UINT32_MAX) + #define Py_hmac_hash_max_block_size 128 #define Py_hmac_hash_max_digest_size 64 @@ -33,54 +37,78 @@ #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, @@ -106,6 +134,29 @@ typedef enum HMAC_Hash_Kind { #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 + /* * HMAC underlying hash function static information. */ @@ -124,6 +175,9 @@ typedef struct py_hmac_hinfo { 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. * @@ -164,12 +218,20 @@ module _hmac /* 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 = NULL, \ + } + #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, \ @@ -192,9 +254,11 @@ static const py_hmac_hinfo py_hmac_static_hinfo[] = { 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, }, From c791febd774234e6a68f38f68b32477eafe39cd8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?B=C3=A9n=C3=A9dikt=20Tran?= <10796600+picnixz@users.noreply.github.com> Date: Fri, 13 Dec 2024 10:32:46 +0100 Subject: [PATCH 11/45] implement one-shot HMAC This commit implements the fast (but limited) one-shot HMAC functions as `_hmac.compute_HASH(key, msg)`. --- Modules/clinic/hmacmodule.c.h | 418 ++++++++++++++++++++++++++++++++++ Modules/hmacmodule.c | 293 +++++++++++++++++++++++- 2 files changed, 710 insertions(+), 1 deletion(-) create mode 100644 Modules/clinic/hmacmodule.c.h diff --git a/Modules/clinic/hmacmodule.c.h b/Modules/clinic/hmacmodule.c.h new file mode 100644 index 00000000000000..394b455d784658 --- /dev/null +++ b/Modules/clinic/hmacmodule.c.h @@ -0,0 +1,418 @@ +/*[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_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 + PyObject *ob_item[NUM_KEYWORDS]; + } _kwtuple = { + .ob_base = PyVarObject_HEAD_INIT(&PyTuple_Type, NUM_KEYWORDS) + .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_sha2_224($module, key, msg, /)\n" +"--\n" +"\n"); + +#define _HMAC_COMPUTE_SHA2_224_METHODDEF \ + {"compute_sha2_224", _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_sha2_224", 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_sha2_256($module, key, msg, /)\n" +"--\n" +"\n"); + +#define _HMAC_COMPUTE_SHA2_256_METHODDEF \ + {"compute_sha2_256", _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_sha2_256", 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_sha2_384($module, key, msg, /)\n" +"--\n" +"\n"); + +#define _HMAC_COMPUTE_SHA2_384_METHODDEF \ + {"compute_sha2_384", _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_sha2_384", 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_sha2_512($module, key, msg, /)\n" +"--\n" +"\n"); + +#define _HMAC_COMPUTE_SHA2_512_METHODDEF \ + {"compute_sha2_512", _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_sha2_512", 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=39363b9f0016460a input=a9049054013a1b77]*/ diff --git a/Modules/hmacmodule.c b/Modules/hmacmodule.c index 34b039fce82ee8..e5dba5a20c3a11 100644 --- a/Modules/hmacmodule.c +++ b/Modules/hmacmodule.c @@ -25,6 +25,13 @@ #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) @@ -214,6 +221,8 @@ module _hmac [clinic start generated code]*/ /*[clinic end generated code: output=da39a3ee5e6b4b0d input=799f0f10157d561f]*/ +#include "clinic/hmacmodule.c.h" + // --- Helpers ---------------------------------------------------------------- /* Static information used to construct the hash table. */ @@ -222,7 +231,7 @@ static const py_hmac_hinfo py_hmac_static_hinfo[] = { { \ /* one-shot helpers */ \ .compute = &Py_hmac_## HACL_HID ##_compute_func, \ - .compute_py = NULL, \ + .compute_py = &_hmac_compute_## HACL_HID ##_impl, \ } #define Py_HMAC_HINFO_ENTRY(HACL_HID, HLIB_NAME) \ @@ -352,9 +361,291 @@ find_hash_info(hmacmodule_state *state, PyObject *hash_info_ref) 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 +} + +// --- 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_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=bcaac7a3637484ce]*/ +{ + Py_HMAC_HACL_ONESHOT(sha2_224, key, msg); +} + +/*[clinic input] +_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=6e2d1f6fe9c56d21]*/ +{ + Py_HMAC_HACL_ONESHOT(sha2_256, key, msg); +} + +/*[clinic input] +_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=9ce8de89dda79e62]*/ +{ + Py_HMAC_HACL_ONESHOT(sha2_384, key, msg); +} + +/*[clinic input] +_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=b964bb8487d7debd]*/ +{ + 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[] = { + /* 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 */ }; From 6b778446a6f93adb82c1e0979383c6da5d7d9896 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?B=C3=A9n=C3=A9dikt=20Tran?= <10796600+picnixz@users.noreply.github.com> Date: Fri, 13 Dec 2024 11:16:38 +0100 Subject: [PATCH 12/45] implement minimal HMAC object interface This commit adds the initial bits for a stateful HMAC object to provide streaming HMAC. --- Modules/hmacmodule.c | 131 ++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 130 insertions(+), 1 deletion(-) diff --git a/Modules/hmacmodule.c b/Modules/hmacmodule.c index e5dba5a20c3a11..089e5e6fc4e72f 100644 --- a/Modules/hmacmodule.c +++ b/Modules/hmacmodule.c @@ -19,6 +19,11 @@ #include "Python.h" #include "pycore_hashtable.h" +// 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 @@ -202,6 +207,8 @@ typedef struct py_hmac_hinfo { typedef struct hmacmodule_state { _Py_hashtable_t *hinfo_table; PyObject *unknown_hash_error; + /* HMAC object type */ + PyTypeObject *hmac_type; /* interned strings */ PyObject *str_lower; } hmacmodule_state; @@ -214,17 +221,62 @@ get_hmacmodule_state(PyObject *module) 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=799f0f10157d561f]*/ +/*[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 ---------------------------------------------------------------- +/* + * 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) \ @@ -372,6 +424,63 @@ has_uint32_t_buffer_length(const Py_buffer *buffer) #endif } +// --- HMAC object ------------------------------------------------------------ + +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[] = { + {NULL, NULL, 0, NULL} /* sentinel */ +}; + +static PyGetSetDef HMACObject_getsets[] = { + {NULL, NULL, NULL, NULL, NULL} /* sentinel */ +}; + +static PyType_Slot HMACObject_Type_slots[] = { + {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] @@ -794,6 +903,21 @@ hmacmodule_init_exceptions(PyObject *module, hmacmodule_state *state) 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) { @@ -819,6 +943,9 @@ hmacmodule_exec(PyObject *module) 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; } @@ -831,6 +958,7 @@ 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; } @@ -844,6 +972,7 @@ hmacmodule_clear(PyObject *mod) state->hinfo_table = NULL; } Py_CLEAR(state->unknown_hash_error); + Py_CLEAR(state->hmac_type); Py_CLEAR(state->str_lower); return 0; } From 077020279960fc6ca5a48965afe68edf36d81eec Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?B=C3=A9n=C3=A9dikt=20Tran?= <10796600+picnixz@users.noreply.github.com> Date: Fri, 13 Dec 2024 11:10:43 +0100 Subject: [PATCH 13/45] implement HMAC simple getters - `HMAC.name` - `HMAC.block_size` - `HMAC.digest_size` --- Modules/clinic/hmacmodule.c.h | 59 ++++++++++++++++++++++++++++++++++- Modules/hmacmodule.c | 40 ++++++++++++++++++++++++ 2 files changed, 98 insertions(+), 1 deletion(-) diff --git a/Modules/clinic/hmacmodule.c.h b/Modules/clinic/hmacmodule.c.h index 394b455d784658..a3b3b27654b046 100644 --- a/Modules/clinic/hmacmodule.c.h +++ b/Modules/clinic/hmacmodule.c.h @@ -8,6 +8,63 @@ preserve #endif #include "pycore_modsupport.h" // _PyArg_UnpackKeywords() +#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" @@ -415,4 +472,4 @@ _hmac_compute_blake2b_32(PyObject *module, PyObject *const *args, Py_ssize_t nar exit: return return_value; } -/*[clinic end generated code: output=39363b9f0016460a input=a9049054013a1b77]*/ +/*[clinic end generated code: output=b3ccaa9e79eace79 input=a9049054013a1b77]*/ diff --git a/Modules/hmacmodule.c b/Modules/hmacmodule.c index 089e5e6fc4e72f..dee1c8a422643c 100644 --- a/Modules/hmacmodule.c +++ b/Modules/hmacmodule.c @@ -426,6 +426,43 @@ has_uint32_t_buffer_length(const Py_buffer *buffer) // --- HMAC object ------------------------------------------------------------ +/*[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 int HMACObject_clear(PyObject *op) { @@ -458,6 +495,9 @@ static PyMethodDef HMACObject_methods[] = { }; static PyGetSetDef HMACObject_getsets[] = { + _HMAC_HMAC_NAME_GETSETDEF + _HMAC_HMAC_BLOCK_SIZE_GETSETDEF + _HMAC_HMAC_DIGEST_SIZE_GETSETDEF {NULL, NULL, NULL, NULL, NULL} /* sentinel */ }; From af443c2cc0d5812228a04b0186c731de153f0e3b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?B=C3=A9n=C3=A9dikt=20Tran?= <10796600+picnixz@users.noreply.github.com> Date: Thu, 12 Dec 2024 16:44:02 +0100 Subject: [PATCH 14/45] implement `HMAC.__repr__()` method --- Modules/hmacmodule.c | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/Modules/hmacmodule.c b/Modules/hmacmodule.c index dee1c8a422643c..5fce801262167e 100644 --- a/Modules/hmacmodule.c +++ b/Modules/hmacmodule.c @@ -463,6 +463,14 @@ _hmac_HMAC_digest_size_get_impl(HMACObject *self) 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) { @@ -502,6 +510,7 @@ static PyGetSetDef HMACObject_getsets[] = { }; 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}, From 4a0e9cd70c1db47e46d474c124e5788fac28da5c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?B=C3=A9n=C3=A9dikt=20Tran?= <10796600+picnixz@users.noreply.github.com> Date: Thu, 12 Dec 2024 16:47:54 +0100 Subject: [PATCH 15/45] implement streaming `HMAC.update()` macros This introduces generic macros for streaming HMAC update() that solely rely on an update() function taking as inputs blocks of at most 32-bit length. --- Modules/hmacmodule.c | 159 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 159 insertions(+) diff --git a/Modules/hmacmodule.c b/Modules/hmacmodule.c index 5fce801262167e..61c93043ce8614 100644 --- a/Modules/hmacmodule.c +++ b/Modules/hmacmodule.c @@ -169,6 +169,119 @@ typedef struct py_hmac_hacl_api { #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. */ @@ -265,6 +378,52 @@ class _hmac.HMAC "HMACObject *" "clinic_state()->hmac_type" #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. + +/* + * 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; + } + } +} /* * Free the HACL* internal state. From 2d025777409889631a714aa4df940252d6b90fd8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?B=C3=A9n=C3=A9dikt=20Tran?= <10796600+picnixz@users.noreply.github.com> Date: Thu, 12 Dec 2024 16:51:57 +0100 Subject: [PATCH 16/45] implement streaming `HMAC.update()` interface Depending on whether Python is compiled in free-threaded mode or not, and depending on the length of the message fed to HMAC, a lock is temporarily acquired on the object to avoid concurrent state modifications. --- Modules/clinic/hmacmodule.c.h | 58 ++++++++++++++++++++- Modules/hmacmodule.c | 98 +++++++++++++++++++++++++++++++++++ 2 files changed, 155 insertions(+), 1 deletion(-) diff --git a/Modules/clinic/hmacmodule.c.h b/Modules/clinic/hmacmodule.c.h index a3b3b27654b046..f0d1266b27087e 100644 --- a/Modules/clinic/hmacmodule.c.h +++ b/Modules/clinic/hmacmodule.c.h @@ -8,6 +8,62 @@ preserve #endif #include "pycore_modsupport.h" // _PyArg_UnpackKeywords() +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 + PyObject *ob_item[NUM_KEYWORDS]; + } _kwtuple = { + .ob_base = PyVarObject_HEAD_INIT(&PyTuple_Type, NUM_KEYWORDS) + .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; +} + #if !defined(_hmac_HMAC_name_DOCSTR) # define _hmac_HMAC_name_DOCSTR NULL #endif @@ -472,4 +528,4 @@ _hmac_compute_blake2b_32(PyObject *module, PyObject *const *args, Py_ssize_t nar exit: return return_value; } -/*[clinic end generated code: output=b3ccaa9e79eace79 input=a9049054013a1b77]*/ +/*[clinic end generated code: output=ee95583e077dcfdf input=a9049054013a1b77]*/ diff --git a/Modules/hmacmodule.c b/Modules/hmacmodule.c index 61c93043ce8614..8fb8db2f33758b 100644 --- a/Modules/hmacmodule.c +++ b/Modules/hmacmodule.c @@ -383,6 +383,10 @@ class _hmac.HMAC "HMACObject *" "clinic_state()->hmac_type" // // - 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). /* * Handle the HACL* exit code. @@ -585,6 +589,99 @@ has_uint32_t_buffer_length(const Py_buffer *buffer) // --- HMAC object ------------------------------------------------------------ +/* + * 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. + * On other builds, only the last update() call is verified. + * + * Return 0 on success and -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. + * On other builds, only the last update() call is verified. + * + * Return 0 on success and -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 and -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; +} + /*[clinic input] @getter _hmac.HMAC.name @@ -658,6 +755,7 @@ HMACObject_traverse(PyObject *op, visitproc visit, void *arg) } static PyMethodDef HMACObject_methods[] = { + _HMAC_HMAC_UPDATE_METHODDEF {NULL, NULL, 0, NULL} /* sentinel */ }; From 2b010ef3e23a64bca15a92444adb984967211719 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?B=C3=A9n=C3=A9dikt=20Tran?= <10796600+picnixz@users.noreply.github.com> Date: Thu, 12 Dec 2024 16:54:05 +0100 Subject: [PATCH 17/45] implement `HMAC.{digest,hexdigest}()` methods The HMAC-HASH digest can be extracted using the internal HACL* state. Stated otherwise, this adds a thin (thread-safe) wrapper around `Hacl_Streaming_HMAC_digest`. --- Modules/clinic/hmacmodule.c.h | 41 ++++++++++++++++++++++++++- Modules/hmacmodule.c | 53 +++++++++++++++++++++++++++++++++++ 2 files changed, 93 insertions(+), 1 deletion(-) diff --git a/Modules/clinic/hmacmodule.c.h b/Modules/clinic/hmacmodule.c.h index f0d1266b27087e..1398682ff32a3f 100644 --- a/Modules/clinic/hmacmodule.c.h +++ b/Modules/clinic/hmacmodule.c.h @@ -64,6 +64,45 @@ _hmac_HMAC_update(PyObject *self, PyObject *const *args, Py_ssize_t nargs, PyObj 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."); + +#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."); + +#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 @@ -528,4 +567,4 @@ _hmac_compute_blake2b_32(PyObject *module, PyObject *const *args, Py_ssize_t nar exit: return return_value; } -/*[clinic end generated code: output=ee95583e077dcfdf input=a9049054013a1b77]*/ +/*[clinic end generated code: output=51a224ad3322770f input=a9049054013a1b77]*/ diff --git a/Modules/hmacmodule.c b/Modules/hmacmodule.c index 8fb8db2f33758b..62c8ae6544e9b7 100644 --- a/Modules/hmacmodule.c +++ b/Modules/hmacmodule.c @@ -18,6 +18,7 @@ #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. @@ -682,6 +683,56 @@ _hmac_HMAC_update_impl(HMACObject *self, PyObject *msgobj) 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. + */ +static inline void +hmac_digest_compute_cond_lock(HMACObject *self, uint8_t *digest) +{ + assert(digest != NULL); + ENTER_HASHLIB(self); // conditionally acquire a lock + Hacl_Streaming_HMAC_digest(self->state, digest, self->digest_size); + LEAVE_HASHLIB(self); +} + +/*[clinic input] +_hmac.HMAC.digest + +Return the digest of the bytes passed to the update() method so far. +[clinic start generated code]*/ + +static PyObject * +_hmac_HMAC_digest_impl(HMACObject *self) +/*[clinic end generated code: output=5bf3cc5862d26ada input=46ada2d337ddcc85]*/ +{ + assert(self->digest_size <= Py_hmac_hash_max_digest_size); + uint8_t digest[Py_hmac_hash_max_digest_size]; + hmac_digest_compute_cond_lock(self, digest); + 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. +[clinic start generated code]*/ + +static PyObject * +_hmac_HMAC_hexdigest_impl(HMACObject *self) +/*[clinic end generated code: output=6659807a09ae14ec input=a7460247846b4c15]*/ +{ + assert(self->digest_size <= Py_hmac_hash_max_digest_size); + uint8_t digest[Py_hmac_hash_max_digest_size]; + hmac_digest_compute_cond_lock(self, digest); + return _Py_strhex((const char *)digest, self->digest_size); +} + /*[clinic input] @getter _hmac.HMAC.name @@ -756,6 +807,8 @@ HMACObject_traverse(PyObject *op, visitproc visit, void *arg) static PyMethodDef HMACObject_methods[] = { _HMAC_HMAC_UPDATE_METHODDEF + _HMAC_HMAC_DIGEST_METHODDEF + _HMAC_HMAC_HEXDIGEST_METHODDEF {NULL, NULL, 0, NULL} /* sentinel */ }; From 6227892259f1d0c887833898e5bf19d6a19b4a93 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?B=C3=A9n=C3=A9dikt=20Tran?= <10796600+picnixz@users.noreply.github.com> Date: Thu, 12 Dec 2024 16:57:02 +0100 Subject: [PATCH 18/45] implement `HMAC.copy()` interface The internal HACL* state can be agilely copied. Stated otherwise, this only adds a thin wrapper around `Hacl_Streaming_HMAC_copy` --- Modules/clinic/hmacmodule.c.h | 24 +++++++++++- Modules/hmacmodule.c | 74 +++++++++++++++++++++++++++++++++++ 2 files changed, 97 insertions(+), 1 deletion(-) diff --git a/Modules/clinic/hmacmodule.c.h b/Modules/clinic/hmacmodule.c.h index 1398682ff32a3f..8377d33581fccf 100644 --- a/Modules/clinic/hmacmodule.c.h +++ b/Modules/clinic/hmacmodule.c.h @@ -8,6 +8,28 @@ preserve #endif #include "pycore_modsupport.h" // _PyArg_UnpackKeywords() +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" @@ -567,4 +589,4 @@ _hmac_compute_blake2b_32(PyObject *module, PyObject *const *args, Py_ssize_t nar exit: return return_value; } -/*[clinic end generated code: output=51a224ad3322770f input=a9049054013a1b77]*/ +/*[clinic end generated code: output=f1b21b57fed96fa4 input=a9049054013a1b77]*/ diff --git a/Modules/hmacmodule.c b/Modules/hmacmodule.c index 62c8ae6544e9b7..47c8cd47620883 100644 --- a/Modules/hmacmodule.c +++ b/Modules/hmacmodule.c @@ -590,6 +590,79 @@ has_uint32_t_buffer_length(const Py_buffer *buffer) // --- HMAC object ------------------------------------------------------------ +/* + * 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 and -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. * @@ -806,6 +879,7 @@ HMACObject_traverse(PyObject *op, visitproc visit, void *arg) } static PyMethodDef HMACObject_methods[] = { + _HMAC_HMAC_COPY_METHODDEF _HMAC_HMAC_UPDATE_METHODDEF _HMAC_HMAC_DIGEST_METHODDEF _HMAC_HMAC_HEXDIGEST_METHODDEF From 5c13316c69d389709e77187e554b741aa358f54d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?B=C3=A9n=C3=A9dikt=20Tran?= <10796600+picnixz@users.noreply.github.com> Date: Thu, 12 Dec 2024 17:04:09 +0100 Subject: [PATCH 19/45] add vectorized blake2s/2b kinds Since HACL* supports vectorized blake2s/2b, we need to introduce additional discriminated types in order to use the corresponding typed states. Note that we perform both a static and a runtime tests to avoid "illegal instruction" errors due to the host CPU. --- Modules/hmacmodule.c | 97 +++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 96 insertions(+), 1 deletion(-) diff --git a/Modules/hmacmodule.c b/Modules/hmacmodule.c index 47c8cd47620883..cf4b627f60090a 100644 --- a/Modules/hmacmodule.c +++ b/Modules/hmacmodule.c @@ -144,6 +144,9 @@ typedef enum HMAC_Hash_Kind { /* 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; @@ -325,6 +328,9 @@ typedef struct hmacmodule_state { PyTypeObject *hmac_type; /* interned strings */ PyObject *str_lower; + + bool can_run_simd128; + bool can_run_simd256; } hmacmodule_state; static inline hmacmodule_state * @@ -389,6 +395,67 @@ class _hmac.HMAC "HMACObject *" "clinic_state()->hmac_type" // 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. * @@ -1264,7 +1331,16 @@ py_hmac_hinfo_ht_new(void) } for (const py_hmac_hinfo *e = py_hmac_static_hinfo; e->name != NULL; e++) { - assert(e->kind != Py_hmac_kind_hash_unknown); + /* + * 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(); @@ -1366,6 +1442,24 @@ hmacmodule_init_strings(hmacmodule_state *state) 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) { @@ -1382,6 +1476,7 @@ hmacmodule_exec(PyObject *module) if (hmacmodule_init_strings(state) < 0) { return -1; } + hmacmodule_init_cpu_features(state); return 0; } From 617b793c7650e0f5e64e5e58d8211e56a4244c8b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?B=C3=A9n=C3=A9dikt=20Tran?= <10796600+picnixz@users.noreply.github.com> Date: Thu, 12 Dec 2024 17:08:04 +0100 Subject: [PATCH 20/45] implement `HMAC.new()` interface We eventually implement the constructor for a HMAC object, making it materializable from Python. --- Modules/clinic/hmacmodule.c.h | 73 +++++++++++++- Modules/hmacmodule.c | 177 ++++++++++++++++++++++++++++++++++ 2 files changed, 249 insertions(+), 1 deletion(-) diff --git a/Modules/clinic/hmacmodule.c.h b/Modules/clinic/hmacmodule.c.h index 8377d33581fccf..08141deaa66575 100644 --- a/Modules/clinic/hmacmodule.c.h +++ b/Modules/clinic/hmacmodule.c.h @@ -8,6 +8,77 @@ preserve #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 + PyObject *ob_item[NUM_KEYWORDS]; + } _kwtuple = { + .ob_base = PyVarObject_HEAD_INIT(&PyTuple_Type, NUM_KEYWORDS) + .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" @@ -589,4 +660,4 @@ _hmac_compute_blake2b_32(PyObject *module, PyObject *const *args, Py_ssize_t nar exit: return return_value; } -/*[clinic end generated code: output=f1b21b57fed96fa4 input=a9049054013a1b77]*/ +/*[clinic end generated code: output=f8ee3b852e0e09e3 input=a9049054013a1b77]*/ diff --git a/Modules/hmacmodule.c b/Modules/hmacmodule.c index cf4b627f60090a..549ab124a37f4c 100644 --- a/Modules/hmacmodule.c +++ b/Modules/hmacmodule.c @@ -497,6 +497,24 @@ _hacl_convert_errno(hacl_errno_t code, PyObject *algorithm) } } +/* + * 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. */ @@ -657,6 +675,164 @@ has_uint32_t_buffer_length(const Py_buffer *buffer) // --- 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 and -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); + // _hacl_hmac_state_new() may set an exception on error + self->state = _hacl_hmac_state_new(self->kind, key, len); + 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 and -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'. */ @@ -1240,6 +1416,7 @@ _hmac_compute_blake2b_32_impl(PyObject *module, PyObject *key, PyObject *msg) // --- HMAC module methods ---------------------------------------------------- static PyMethodDef hmacmodule_methods[] = { + _HMAC_NEW_METHODDEF /* one-shot dispatcher */ _HMAC_COMPUTE_DIGEST_METHODDEF /* one-shot methods */ From cc28e3e9be7508e76fdc798c281950a03155cf6a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?B=C3=A9n=C3=A9dikt=20Tran?= <10796600+picnixz@users.noreply.github.com> Date: Thu, 12 Dec 2024 16:41:08 +0100 Subject: [PATCH 21/45] update HMAC python interface - Update the HMAC high-level API to use the HACL* implementation. - Always set `_inner` and `_outer` attributes to None when using a C implementation. --- Lib/hmac.py | 91 +++++++++++++++++++++++++++++++++++------------------ 1 file changed, 61 insertions(+), 30 deletions(-) diff --git a/Lib/hmac.py b/Lib/hmac.py index 30b6b478734dfc..20e0c93df89c3e 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)) @@ -23,12 +25,26 @@ # hashing module used. Use digest_size from the instance of HMAC instead. 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 +66,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 +116,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') @@ -184,7 +213,6 @@ def new(key, msg=None, digestmod=''): """ return HMAC(key, msg, digestmod) - def digest(key, msg, digest): """Fast inline implementation of HMAC. @@ -200,19 +228,22 @@ def 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 is not None 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) From 166e7e81b9c9a2a6edeec0cf88f4c16f7fabe025 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?B=C3=A9n=C3=A9dikt=20Tran?= <10796600+picnixz@users.noreply.github.com> Date: Sat, 15 Feb 2025 14:41:25 +0100 Subject: [PATCH 22/45] add blurb & CHANGELOG entries --- Doc/whatsnew/3.14.rst | 7 +++++++ .../2025-02-15-14-36-32.gh-issue-99108.u6CfmK.rst | 2 ++ 2 files changed, 9 insertions(+) create mode 100644 Misc/NEWS.d/next/Core_and_Builtins/2025-02-15-14-36-32.gh-issue-99108.u6CfmK.rst diff --git a/Doc/whatsnew/3.14.rst b/Doc/whatsnew/3.14.rst index b1337190636529..6c758a3cfb9048 100644 --- a/Doc/whatsnew/3.14.rst +++ b/Doc/whatsnew/3.14.rst @@ -370,6 +370,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`.) + + New modules =========== 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. From f2817ae1a63e78df9656135fc42d19caa83aa082 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?B=C3=A9n=C3=A9dikt=20Tran?= <10796600+picnixz@users.noreply.github.com> Date: Tue, 11 Mar 2025 13:14:57 +0100 Subject: [PATCH 23/45] add `hashlib_helper.requires_builtin_hmac` --- Lib/test/support/hashlib_helper.py | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/Lib/test/support/hashlib_helper.py b/Lib/test/support/hashlib_helper.py index bed3d696cb384d..e44f79933798a3 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: + _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) From 2b544e5bdb8a83a14a9d612a094cc5bee55f4b33 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?B=C3=A9n=C3=A9dikt=20Tran?= <10796600+picnixz@users.noreply.github.com> Date: Tue, 11 Mar 2025 13:46:27 +0100 Subject: [PATCH 24/45] add various tests for the HACL* HMAC implementation - create `ThroughBuiltinAPIMixin` similar to `ThroughOpenSSLAPIMixin` - add tests for RFC test vectors - add tests for `digestmod` parameter - add sanity check tests - add hmac.update() tests - add hmac.copy() tests --- Lib/test/test_hmac.py | 95 +++++++++++++++++++++++++++++++++++++++---- 1 file changed, 86 insertions(+), 9 deletions(-) diff --git a/Lib/test/test_hmac.py b/Lib/test/test_hmac.py index ed96af2b2d874b..121d9a36848534 100644 --- a/Lib/test/test_hmac.py +++ b/Lib/test/test_hmac.py @@ -47,7 +47,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 +128,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).""" @@ -335,6 +345,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().""" @@ -603,6 +617,15 @@ class OpenSSLRFCTestCase(OpenSSLAssertersMixin, """ +class BuiltinRFCTestCase(BuiltinAssertersMixin, + WithNamedHashFunctions, RFCTestCaseMixin, + unittest.TestCase): + """Built-in HACL* implementation of HMAC. + + The underlying hash functions are also HACL*-based. + """ + + # 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 @@ -610,7 +633,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.""" @@ -753,11 +776,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 @@ -804,6 +831,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. @@ -859,6 +904,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).""" @@ -890,7 +949,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') @@ -900,7 +959,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: @@ -991,7 +1059,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: From b4bfe5e4e8812988d86db046e5e955a33aa1d69b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?B=C3=A9n=C3=A9dikt=20Tran?= <10796600+picnixz@users.noreply.github.com> Date: Mon, 17 Mar 2025 13:07:16 +0100 Subject: [PATCH 25/45] update comments concerning `int` return values --- Modules/hmacmodule.c | 48 ++++++++++++++++++++++++++++++++++---------- 1 file changed, 37 insertions(+), 11 deletions(-) diff --git a/Modules/hmacmodule.c b/Modules/hmacmodule.c index 549ab124a37f4c..3e26465e48cb00 100644 --- a/Modules/hmacmodule.c +++ b/Modules/hmacmodule.c @@ -574,6 +574,12 @@ static const py_hmac_hinfo py_hmac_static_hinfo[] = { }, }; +/* + * 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, @@ -584,6 +590,20 @@ find_hash_info_by_utf8name(hmacmodule_state *state, 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, @@ -619,9 +639,10 @@ find_hash_info_by_name(hmacmodule_state *state, /* * Find the corresponding HMAC hash function static information. * - * If an error occurs or if nothing can be found, this - * returns -1 or 0 respectively, and sets 'info' to NULL. - * Otherwise, this returns 1 and stores the result in 'info'. + * 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 * @@ -644,6 +665,12 @@ find_hash_info_impl(hmacmodule_state *state, 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) { @@ -659,6 +686,7 @@ find_hash_info(hmacmodule_state *state, PyObject *hash_info_ref) "unsupported hash type: %R", hash_info_ref); return NULL; } + assert(info != NULL); return info; } @@ -705,7 +733,7 @@ hmac_set_hinfo(hmacmodule_state *state, * and after hmac_set_hinfo() has been called, lest the behaviour is * undefined. * - * Return 0 on success and -1 on failure. + * 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) @@ -734,7 +762,7 @@ hmac_new_initial_state(HMACObject *self, uint8_t *key, Py_ssize_t len) * and after hmac_set_hinfo() and hmac_new_initial_state() have been * called, lest the behaviour is undefined. * - * Return 0 on success and -1 on failure. + * 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) @@ -857,7 +885,7 @@ hmac_copy_hinfo(HMACObject *out, const HMACObject *src) * * The internal state of 'out' must not already exist. * - * Return 0 on success and -1 on failure. + * Return 0 on success; otherwise, set an exception and return -1 on failure. */ static int hmac_copy_state(HMACObject *out, const HMACObject *src) @@ -912,9 +940,8 @@ _hmac_HMAC_copy_impl(HMACObject *self, PyTypeObject *cls) * This unconditionally acquires the lock on the HMAC object. * * On DEBUG builds, each update() call is verified. - * On other builds, only the last update() call is verified. * - * Return 0 on success and -1 on failure. + * 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) @@ -942,9 +969,8 @@ hmac_update_state_with_lock(HMACObject *self, uint8_t *buf, Py_ssize_t len) * This conditionally acquires the lock on the HMAC object. * * On DEBUG builds, each update() call is verified. - * On other builds, only the last update() call is verified. * - * Return 0 on success and -1 on failure. + * 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) @@ -966,7 +992,7 @@ hmac_update_state_cond_lock(HMACObject *self, uint8_t *buf, Py_ssize_t len) /* * Update the internal HMAC state with the given buffer. * - * Return 0 on success and -1 on failure. + * 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) From 3aae0a89aba4de9c17028f22af85bfda06706847 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?B=C3=A9n=C3=A9dikt=20Tran?= <10796600+picnixz@users.noreply.github.com> Date: Mon, 17 Mar 2025 13:07:31 +0100 Subject: [PATCH 26/45] handle error code returned by `Hacl_Streaming_HMAC_digest` --- Modules/hmacmodule.c | 26 ++++++++++++++++++++++---- 1 file changed, 22 insertions(+), 4 deletions(-) diff --git a/Modules/hmacmodule.c b/Modules/hmacmodule.c index 3e26465e48cb00..d4b114a668cab7 100644 --- a/Modules/hmacmodule.c +++ b/Modules/hmacmodule.c @@ -1030,20 +1030,32 @@ _hmac_HMAC_update_impl(HMACObject *self, PyObject *msgobj) * * 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 inline void +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 - Hacl_Streaming_HMAC_digest(self->state, digest, self->digest_size); + 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 * @@ -1052,7 +1064,9 @@ _hmac_HMAC_digest_impl(HMACObject *self) { assert(self->digest_size <= Py_hmac_hash_max_digest_size); uint8_t digest[Py_hmac_hash_max_digest_size]; - hmac_digest_compute_cond_lock(self, digest); + if (hmac_digest_compute_cond_lock(self, digest) < 0) { + return NULL; + } return PyBytes_FromStringAndSize((const char *)digest, self->digest_size); } @@ -1063,6 +1077,8 @@ 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 * @@ -1071,7 +1087,9 @@ _hmac_HMAC_hexdigest_impl(HMACObject *self) { assert(self->digest_size <= Py_hmac_hash_max_digest_size); uint8_t digest[Py_hmac_hash_max_digest_size]; - hmac_digest_compute_cond_lock(self, digest); + if (hmac_digest_compute_cond_lock(self, digest) < 0) { + return NULL; + } return _Py_strhex((const char *)digest, self->digest_size); } From c86d51e467a2b3fbe44ba19d2affc168aa06990b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?B=C3=A9n=C3=A9dikt=20Tran?= <10796600+picnixz@users.noreply.github.com> Date: Tue, 18 Mar 2025 10:30:18 +0100 Subject: [PATCH 27/45] summarize HMAC changes in "Improved Modules" as well --- Doc/whatsnew/3.14.rst | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/Doc/whatsnew/3.14.rst b/Doc/whatsnew/3.14.rst index e78ca6c2c9c273..2d1bd7986fe763 100644 --- a/Doc/whatsnew/3.14.rst +++ b/Doc/whatsnew/3.14.rst @@ -623,6 +623,14 @@ http (Contributed by Yorik Hansen in :gh:`123430`.) +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`.) + + imaplib ------- From 5fd72f00fb23d07dce6108e448284d19f096e52e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?B=C3=A9n=C3=A9dikt=20Tran?= <10796600+picnixz@users.noreply.github.com> Date: Tue, 18 Mar 2025 10:34:16 +0100 Subject: [PATCH 28/45] force safe downcast to `uint32_t` in `hmac_new_initial_state` --- Modules/hmacmodule.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Modules/hmacmodule.c b/Modules/hmacmodule.c index d4b114a668cab7..cf0fdcf4580d5e 100644 --- a/Modules/hmacmodule.c +++ b/Modules/hmacmodule.c @@ -750,8 +750,9 @@ hmac_new_initial_state(HMACObject *self, uint8_t *key, Py_ssize_t len) } #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 - self->state = _hacl_hmac_state_new(self->kind, key, len); return self->state == NULL ? -1 : 0; } From da71ef8962086a939c6ec86568d2dcf14191a071 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?B=C3=A9n=C3=A9dikt=20Tran?= <10796600+picnixz@users.noreply.github.com> Date: Tue, 18 Mar 2025 11:07:20 +0100 Subject: [PATCH 29/45] `make clinic` --- Modules/clinic/hmacmodule.c.h | 10 +++++++--- Modules/hmacmodule.c | 4 ++-- 2 files changed, 9 insertions(+), 5 deletions(-) diff --git a/Modules/clinic/hmacmodule.c.h b/Modules/clinic/hmacmodule.c.h index 08141deaa66575..30bf0c01980b39 100644 --- a/Modules/clinic/hmacmodule.c.h +++ b/Modules/clinic/hmacmodule.c.h @@ -161,7 +161,9 @@ PyDoc_STRVAR(_hmac_HMAC_digest__doc__, "digest($self, /)\n" "--\n" "\n" -"Return the digest of the bytes passed to the update() method so far."); +"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__}, @@ -182,7 +184,9 @@ PyDoc_STRVAR(_hmac_HMAC_hexdigest__doc__, "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."); +"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__}, @@ -660,4 +664,4 @@ _hmac_compute_blake2b_32(PyObject *module, PyObject *const *args, Py_ssize_t nar exit: return return_value; } -/*[clinic end generated code: output=f8ee3b852e0e09e3 input=a9049054013a1b77]*/ +/*[clinic end generated code: output=7e0a5a87ff3fa5fa input=a9049054013a1b77]*/ diff --git a/Modules/hmacmodule.c b/Modules/hmacmodule.c index cf0fdcf4580d5e..59a2ec46701074 100644 --- a/Modules/hmacmodule.c +++ b/Modules/hmacmodule.c @@ -1061,7 +1061,7 @@ This method may raise a MemoryError. static PyObject * _hmac_HMAC_digest_impl(HMACObject *self) -/*[clinic end generated code: output=5bf3cc5862d26ada input=46ada2d337ddcc85]*/ +/*[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]; @@ -1084,7 +1084,7 @@ This method may raise a MemoryError. static PyObject * _hmac_HMAC_hexdigest_impl(HMACObject *self) -/*[clinic end generated code: output=6659807a09ae14ec input=a7460247846b4c15]*/ +/*[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]; From 5baa87445a9115a621e8f996ddf032f27348238c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?B=C3=A9n=C3=A9dikt=20Tran?= <10796600+picnixz@users.noreply.github.com> Date: Tue, 18 Mar 2025 11:38:26 +0100 Subject: [PATCH 30/45] fix HMAC max block size HMAC-SHA3/224 has block_size=144 --- Modules/hmacmodule.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Modules/hmacmodule.c b/Modules/hmacmodule.c index 59a2ec46701074..267ed0f62ded1e 100644 --- a/Modules/hmacmodule.c +++ b/Modules/hmacmodule.c @@ -42,7 +42,7 @@ #define UINT32_MAX_AS_SSIZE_T ((Py_ssize_t)UINT32_MAX) -#define Py_hmac_hash_max_block_size 128 +#define Py_hmac_hash_max_block_size 144 #define Py_hmac_hash_max_digest_size 64 /* MD-5 */ From aab2b0b3c38c00232a41c10910d3cc5a4ef4b4c6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?B=C3=A9n=C3=A9dikt=20Tran?= <10796600+picnixz@users.noreply.github.com> Date: Tue, 18 Mar 2025 14:18:09 +0100 Subject: [PATCH 31/45] align naming of one-shot HMAC with OpenSSL --- Modules/clinic/hmacmodule.c.h | 26 +++++++++++++------------- Modules/hmacmodule.c | 16 ++++++++-------- 2 files changed, 21 insertions(+), 21 deletions(-) diff --git a/Modules/clinic/hmacmodule.c.h b/Modules/clinic/hmacmodule.c.h index 30bf0c01980b39..e20cc6c062fdc0 100644 --- a/Modules/clinic/hmacmodule.c.h +++ b/Modules/clinic/hmacmodule.c.h @@ -376,12 +376,12 @@ _hmac_compute_sha1(PyObject *module, PyObject *const *args, Py_ssize_t nargs) } PyDoc_STRVAR(_hmac_compute_sha2_224__doc__, -"compute_sha2_224($module, key, msg, /)\n" +"compute_sha224($module, key, msg, /)\n" "--\n" "\n"); #define _HMAC_COMPUTE_SHA2_224_METHODDEF \ - {"compute_sha2_224", _PyCFunction_CAST(_hmac_compute_sha2_224), METH_FASTCALL, _hmac_compute_sha2_224__doc__}, + {"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); @@ -393,7 +393,7 @@ _hmac_compute_sha2_224(PyObject *module, PyObject *const *args, Py_ssize_t nargs PyObject *key; PyObject *msg; - if (!_PyArg_CheckPositional("compute_sha2_224", nargs, 2, 2)) { + if (!_PyArg_CheckPositional("compute_sha224", nargs, 2, 2)) { goto exit; } key = args[0]; @@ -405,12 +405,12 @@ _hmac_compute_sha2_224(PyObject *module, PyObject *const *args, Py_ssize_t nargs } PyDoc_STRVAR(_hmac_compute_sha2_256__doc__, -"compute_sha2_256($module, key, msg, /)\n" +"compute_sha256($module, key, msg, /)\n" "--\n" "\n"); #define _HMAC_COMPUTE_SHA2_256_METHODDEF \ - {"compute_sha2_256", _PyCFunction_CAST(_hmac_compute_sha2_256), METH_FASTCALL, _hmac_compute_sha2_256__doc__}, + {"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); @@ -422,7 +422,7 @@ _hmac_compute_sha2_256(PyObject *module, PyObject *const *args, Py_ssize_t nargs PyObject *key; PyObject *msg; - if (!_PyArg_CheckPositional("compute_sha2_256", nargs, 2, 2)) { + if (!_PyArg_CheckPositional("compute_sha256", nargs, 2, 2)) { goto exit; } key = args[0]; @@ -434,12 +434,12 @@ _hmac_compute_sha2_256(PyObject *module, PyObject *const *args, Py_ssize_t nargs } PyDoc_STRVAR(_hmac_compute_sha2_384__doc__, -"compute_sha2_384($module, key, msg, /)\n" +"compute_sha384($module, key, msg, /)\n" "--\n" "\n"); #define _HMAC_COMPUTE_SHA2_384_METHODDEF \ - {"compute_sha2_384", _PyCFunction_CAST(_hmac_compute_sha2_384), METH_FASTCALL, _hmac_compute_sha2_384__doc__}, + {"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); @@ -451,7 +451,7 @@ _hmac_compute_sha2_384(PyObject *module, PyObject *const *args, Py_ssize_t nargs PyObject *key; PyObject *msg; - if (!_PyArg_CheckPositional("compute_sha2_384", nargs, 2, 2)) { + if (!_PyArg_CheckPositional("compute_sha384", nargs, 2, 2)) { goto exit; } key = args[0]; @@ -463,12 +463,12 @@ _hmac_compute_sha2_384(PyObject *module, PyObject *const *args, Py_ssize_t nargs } PyDoc_STRVAR(_hmac_compute_sha2_512__doc__, -"compute_sha2_512($module, key, msg, /)\n" +"compute_sha512($module, key, msg, /)\n" "--\n" "\n"); #define _HMAC_COMPUTE_SHA2_512_METHODDEF \ - {"compute_sha2_512", _PyCFunction_CAST(_hmac_compute_sha2_512), METH_FASTCALL, _hmac_compute_sha2_512__doc__}, + {"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); @@ -480,7 +480,7 @@ _hmac_compute_sha2_512(PyObject *module, PyObject *const *args, Py_ssize_t nargs PyObject *key; PyObject *msg; - if (!_PyArg_CheckPositional("compute_sha2_512", nargs, 2, 2)) { + if (!_PyArg_CheckPositional("compute_sha512", nargs, 2, 2)) { goto exit; } key = args[0]; @@ -664,4 +664,4 @@ _hmac_compute_blake2b_32(PyObject *module, PyObject *const *args, Py_ssize_t nar exit: return return_value; } -/*[clinic end generated code: output=7e0a5a87ff3fa5fa input=a9049054013a1b77]*/ +/*[clinic end generated code: output=bdfd9d967c6a052c input=a9049054013a1b77]*/ diff --git a/Modules/hmacmodule.c b/Modules/hmacmodule.c index 267ed0f62ded1e..faf4e0a023147e 100644 --- a/Modules/hmacmodule.c +++ b/Modules/hmacmodule.c @@ -1299,7 +1299,7 @@ _hmac_compute_sha1_impl(PyObject *module, PyObject *key, PyObject *msg) } /*[clinic input] -_hmac.compute_sha2_224 +_hmac.compute_sha224 as _hmac_compute_sha2_224 key: object msg: object @@ -1309,13 +1309,13 @@ _hmac.compute_sha2_224 static PyObject * _hmac_compute_sha2_224_impl(PyObject *module, PyObject *key, PyObject *msg) -/*[clinic end generated code: output=7f21f1613e53979e input=bcaac7a3637484ce]*/ +/*[clinic end generated code: output=7f21f1613e53979e input=a1a75f25f23449af]*/ { Py_HMAC_HACL_ONESHOT(sha2_224, key, msg); } /*[clinic input] -_hmac.compute_sha2_256 +_hmac.compute_sha256 as _hmac_compute_sha2_256 key: object msg: object @@ -1325,13 +1325,13 @@ _hmac.compute_sha2_256 static PyObject * _hmac_compute_sha2_256_impl(PyObject *module, PyObject *key, PyObject *msg) -/*[clinic end generated code: output=d4a291f7d9a82459 input=6e2d1f6fe9c56d21]*/ +/*[clinic end generated code: output=d4a291f7d9a82459 input=5c9ccf2df048ace3]*/ { Py_HMAC_HACL_ONESHOT(sha2_256, key, msg); } /*[clinic input] -_hmac.compute_sha2_384 +_hmac.compute_sha384 as _hmac_compute_sha2_384 key: object msg: object @@ -1341,13 +1341,13 @@ _hmac.compute_sha2_384 static PyObject * _hmac_compute_sha2_384_impl(PyObject *module, PyObject *key, PyObject *msg) -/*[clinic end generated code: output=f211fa26e3700c27 input=9ce8de89dda79e62]*/ +/*[clinic end generated code: output=f211fa26e3700c27 input=2fee2c14766af231]*/ { Py_HMAC_HACL_ONESHOT(sha2_384, key, msg); } /*[clinic input] -_hmac.compute_sha2_512 +_hmac.compute_sha512 as _hmac_compute_sha2_512 key: object msg: object @@ -1357,7 +1357,7 @@ _hmac.compute_sha2_512 static PyObject * _hmac_compute_sha2_512_impl(PyObject *module, PyObject *key, PyObject *msg) -/*[clinic end generated code: output=d5c20373762cecca input=b964bb8487d7debd]*/ +/*[clinic end generated code: output=d5c20373762cecca input=3371eaac315c7864]*/ { Py_HMAC_HACL_ONESHOT(sha2_512, key, msg); } From da3a3e3be934a25604aea05db1f1f7428b094cd0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?B=C3=A9n=C3=A9dikt=20Tran?= <10796600+picnixz@users.noreply.github.com> Date: Tue, 18 Mar 2025 14:31:08 +0100 Subject: [PATCH 32/45] test one-shot HMAC functions --- Lib/test/test_hmac.py | 52 +++++++++++++++++++++++++++++++------------ 1 file changed, 38 insertions(+), 14 deletions(-) diff --git a/Lib/test/test_hmac.py b/Lib/test/test_hmac.py index 242aed1f884208..e9d5101ea992f4 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 @@ -215,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 @@ -234,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}, @@ -247,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. @@ -282,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}, @@ -293,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.""" + """Extra 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) @@ -741,6 +756,15 @@ class BuiltinRFCTestCase(BuiltinAssertersMixin, 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 = eval(f'self.hmac.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 From b2540ef4b41f46006d6f7bfe39b6ad38cd8454ba Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?B=C3=A9n=C3=A9dikt=20Tran?= <10796600+picnixz@users.noreply.github.com> Date: Wed, 19 Mar 2025 02:06:29 +0100 Subject: [PATCH 33/45] remove dubious `eval` --- Lib/test/test_hmac.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Lib/test/test_hmac.py b/Lib/test/test_hmac.py index e9d5101ea992f4..eeb6d88dda891d 100644 --- a/Lib/test/test_hmac.py +++ b/Lib/test/test_hmac.py @@ -761,7 +761,7 @@ def assert_hmac_extra_cases( ): # assert one-shot HMAC at the same time with self.subTest(key=key, msg=msg, hashname=hashname): - func = eval(f'self.hmac.compute_{hashname}') + func = getattr(self.hmac, f'compute_{hashname}') self.assertTrue(callable(func)) self.check_hmac_hexdigest(key, msg, hexdigest, digest_size, func) From 0b18234f70f38a8673dbe69ececca4b82414945d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?B=C3=A9n=C3=A9dikt=20Tran?= <10796600+picnixz@users.noreply.github.com> Date: Fri, 28 Mar 2025 14:20:19 +0100 Subject: [PATCH 34/45] fixup test docstring --- Lib/test/test_hmac.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Lib/test/test_hmac.py b/Lib/test/test_hmac.py index eeb6d88dda891d..42b8a91ae580d2 100644 --- a/Lib/test/test_hmac.py +++ b/Lib/test/test_hmac.py @@ -324,7 +324,7 @@ def check_hmac_hexdigest( def assert_hmac_common_cases( self, key, msg, hexdigest, digestmod, hashname, digest_size, block_size ): - """Extra common tests executed by all 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") From 218015a0b123e07cb06797b7146ab7064e75279b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?B=C3=A9n=C3=A9dikt=20Tran?= <10796600+picnixz@users.noreply.github.com> Date: Fri, 28 Mar 2025 14:20:41 +0100 Subject: [PATCH 35/45] remove un-necessary guards --- Modules/_hacl/python_hacl_namespaces.h | 9 --------- 1 file changed, 9 deletions(-) diff --git a/Modules/_hacl/python_hacl_namespaces.h b/Modules/_hacl/python_hacl_namespaces.h index 184ec34942705d..e234a123e1606d 100644 --- a/Modules/_hacl/python_hacl_namespaces.h +++ b/Modules/_hacl/python_hacl_namespaces.h @@ -236,13 +236,4 @@ #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 -// 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. -#ifndef HACL_CAN_COMPILE_VEC128 -#define HACL_CAN_COMPILE_VEC128 HACL_CAN_COMPILE_SIMD128 -#endif -#ifndef HACL_CAN_COMPILE_VEC256 -#define HACL_CAN_COMPILE_VEC256 HACL_CAN_COMPILE_SIMD256 -#endif - #endif // _PYTHON_HACL_NAMESPACES_H From 0ae4a9d4eff7dec076f0cd89ccf6e455b3e3be24 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?B=C3=A9n=C3=A9dikt=20Tran?= <10796600+picnixz@users.noreply.github.com> Date: Fri, 28 Mar 2025 14:57:51 +0100 Subject: [PATCH 36/45] make clinic --- Modules/clinic/hmacmodule.c.h | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/Modules/clinic/hmacmodule.c.h b/Modules/clinic/hmacmodule.c.h index e20cc6c062fdc0..1ceb2d809e830a 100644 --- a/Modules/clinic/hmacmodule.c.h +++ b/Modules/clinic/hmacmodule.c.h @@ -31,9 +31,11 @@ _hmac_new(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *k 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 @@ -123,9 +125,11 @@ _hmac_HMAC_update(PyObject *self, PyObject *const *args, Py_ssize_t nargs, PyObj 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 @@ -279,9 +283,11 @@ _hmac_compute_digest(PyObject *module, PyObject *const *args, Py_ssize_t nargs, 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 @@ -664,4 +670,4 @@ _hmac_compute_blake2b_32(PyObject *module, PyObject *const *args, Py_ssize_t nar exit: return return_value; } -/*[clinic end generated code: output=bdfd9d967c6a052c input=a9049054013a1b77]*/ +/*[clinic end generated code: output=30c0614482d963f5 input=a9049054013a1b77]*/ From 47a15d6d1383904dfb1fa677e000eed2e01c0bae Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?B=C3=A9n=C3=A9dikt=20Tran?= <10796600+picnixz@users.noreply.github.com> Date: Fri, 28 Mar 2025 15:23:38 +0100 Subject: [PATCH 37/45] make regen-sbom --- Misc/sbom.spdx.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Misc/sbom.spdx.json b/Misc/sbom.spdx.json index 4df69210038a3a..678a64df977432 100644 --- a/Misc/sbom.spdx.json +++ b/Misc/sbom.spdx.json @@ -930,11 +930,11 @@ "checksums": [ { "algorithm": "SHA1", - "checksumValue": "bd1b8f44a5391b2c6e7703b32d44ce1f2723ff99" + "checksumValue": "dbed915328619b1159012649a427c6928033dd90" }, { "algorithm": "SHA256", - "checksumValue": "56c7482895b5969475aae40fd1f83e65d421a2667f68764d54b8e2f6f173b7ad" + "checksumValue": "0297ea0a5d1117e001d5dbb90f99d47ee9e0f9d3dd45da02ba5dc477e551cb5a" } ], "fileName": "Modules/_hacl/python_hacl_namespaces.h" From f203c6d5e85c26b83331727b21962040a556b9ab Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?B=C3=A9n=C3=A9dikt=20Tran?= <10796600+picnixz@users.noreply.github.com> Date: Fri, 28 Mar 2025 21:00:08 +0100 Subject: [PATCH 38/45] fix obvious typo --- Tools/c-analyzer/cpython/ignored.tsv | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Tools/c-analyzer/cpython/ignored.tsv b/Tools/c-analyzer/cpython/ignored.tsv index ef663ed45622eb..18e543ab33bb16 100644 --- a/Tools/c-analyzer/cpython/ignored.tsv +++ b/Tools/c-analyzer/cpython/ignored.tsv @@ -307,8 +307,8 @@ Modules/cmathmodule.c - sqrt_special_values - Modules/cmathmodule.c - tanh_special_values - Modules/config.c - _PyImport_Inittab - Modules/faulthandler.c - faulthandler_handlers - -Modules/faulthandler.c - py_hmac_static_hinfo - 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 - From a5fc810405a44c196e9ceee349c58904d542d561 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?B=C3=A9n=C3=A9dikt=20Tran?= <10796600+picnixz@users.noreply.github.com> Date: Sat, 29 Mar 2025 17:18:10 +0100 Subject: [PATCH 39/45] narrow `except` guard Co-authored-by: Hugo van Kemenade <1324225+hugovk@users.noreply.github.com> --- Lib/test/support/hashlib_helper.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Lib/test/support/hashlib_helper.py b/Lib/test/support/hashlib_helper.py index e44f79933798a3..06fac410a5e20f 100644 --- a/Lib/test/support/hashlib_helper.py +++ b/Lib/test/support/hashlib_helper.py @@ -10,7 +10,7 @@ try: import _hmac -except: +except ImportError: _hmac = None From b58073dc06ccd2c80ac35a10b3170313ce58cf24 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?B=C3=A9n=C3=A9dikt=20Tran?= <10796600+picnixz@users.noreply.github.com> Date: Sat, 29 Mar 2025 17:19:13 +0100 Subject: [PATCH 40/45] put `hmac` section before `http` section --- Doc/whatsnew/3.14.rst | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/Doc/whatsnew/3.14.rst b/Doc/whatsnew/3.14.rst index 9ab8199f738fe7..a8fc21c9645ecf 100644 --- a/Doc/whatsnew/3.14.rst +++ b/Doc/whatsnew/3.14.rst @@ -629,14 +629,6 @@ graphlib (Contributed by Daniel Pope in :gh:`130914`) -http ----- - -* Directory lists and error pages generated by the :mod:`http.server` - module allow the browser to apply its default dark mode. - (Contributed by Yorik Hansen in :gh:`123430`.) - - hmac ---- @@ -645,6 +637,14 @@ hmac (Contributed by Bénédikt Tran in :gh:`99108`.) +http +---- + +* Directory lists and error pages generated by the :mod:`http.server` + module allow the browser to apply its default dark mode. + (Contributed by Yorik Hansen in :gh:`123430`.) + + imaplib ------- From 6f84a82768d3aac29870e3d53f04e9ca9e84be4b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?B=C3=A9n=C3=A9dikt=20Tran?= <10796600+picnixz@users.noreply.github.com> Date: Tue, 1 Apr 2025 11:44:41 +0200 Subject: [PATCH 41/45] cosmetic changes in hmac.py - add two blank lines for separating functions - use consistent truthy checks --- Lib/hmac.py | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/Lib/hmac.py b/Lib/hmac.py index 20e0c93df89c3e..2af11c26947064 100644 --- a/Lib/hmac.py +++ b/Lib/hmac.py @@ -25,6 +25,7 @@ # hashing module used. Use digest_size from the instance of HMAC instead. digest_size = None + def _get_digest_constructor(digest_like): if callable(digest_like): return digest_like @@ -37,6 +38,7 @@ def digest_wrapper(d=b''): return digest_like.new(d) return digest_wrapper + class HMAC: """RFC 2104 HMAC class. Also complies with RFC 4231. @@ -194,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. @@ -213,6 +216,7 @@ def new(key, msg=None, digestmod=''): """ return HMAC(key, msg, digestmod) + def digest(key, msg, digest): """Fast inline implementation of HMAC. @@ -222,13 +226,13 @@ 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 _hmac is not None and isinstance(digest, str): + if _hmac and isinstance(digest, str): try: return _hmac.compute_digest(key, msg, digest) except (OverflowError, _hmac.UnknownHashError): @@ -236,6 +240,7 @@ def digest(key, msg, digest): return _compute_digest_fallback(key, msg, digest) + def _compute_digest_fallback(key, msg, digest): digest_cons = _get_digest_constructor(digest) inner = digest_cons() From de7ad74b86d963b0510e43868e09265b7dd72c7a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?B=C3=A9n=C3=A9dikt=20Tran?= <10796600+picnixz@users.noreply.github.com> Date: Tue, 1 Apr 2025 11:45:05 +0200 Subject: [PATCH 42/45] group cryptographic primitives modules --- PC/config.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/PC/config.c b/PC/config.c index d7ee9c1fe4248f..a8274ef29bf2b1 100644 --- a/PC/config.c +++ b/PC/config.c @@ -99,12 +99,15 @@ struct _inittab _PyImport_Inittab[] = { {"nt", PyInit_nt}, /* Use the NT os functions, not posix */ {"_operator", PyInit__operator}, {"_signal", PyInit__signal}, + /* cryptographic hash functions */ + {"_blake2", PyInit__blake2}, {"_md5", PyInit__md5}, {"_sha1", PyInit__sha1}, {"_sha2", PyInit__sha2}, {"_sha3", PyInit__sha3}, - {"_blake2", PyInit__blake2}, + /* other cryptographic primitives */ {"_hmac", PyInit__hmac}, + {"_sysconfig", PyInit__sysconfig}, {"time", PyInit_time}, {"_thread", PyInit__thread}, From 674af0793cb2020800aedca2df6039f1e54b2135 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?B=C3=A9n=C3=A9dikt=20Tran?= <10796600+picnixz@users.noreply.github.com> Date: Tue, 1 Apr 2025 11:58:26 +0200 Subject: [PATCH 43/45] better group cryptographic primitives --- PC/config.c | 27 +++++++++++++++------------ 1 file changed, 15 insertions(+), 12 deletions(-) diff --git a/PC/config.c b/PC/config.c index a8274ef29bf2b1..29a7a0578ad62f 100644 --- a/PC/config.c +++ b/PC/config.c @@ -14,20 +14,22 @@ 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__hmac(void); extern PyObject* PyInit_time(void); extern PyObject* PyInit__thread(void); +/* cryptographic primitives */ +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); +extern PyObject* PyInit__hmac(void); +/* ------------------------ */ #ifdef WIN32 extern PyObject* PyInit_msvcrt(void); extern PyObject* PyInit__locale(void); @@ -99,6 +101,13 @@ struct _inittab _PyImport_Inittab[] = { {"nt", PyInit_nt}, /* Use the NT os functions, not posix */ {"_operator", PyInit__operator}, {"_signal", PyInit__signal}, + {"_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}, @@ -108,12 +117,6 @@ struct _inittab _PyImport_Inittab[] = { /* other cryptographic primitives */ {"_hmac", PyInit__hmac}, - {"_sysconfig", PyInit__sysconfig}, - {"time", PyInit_time}, - {"_thread", PyInit__thread}, - {"_tokenize", PyInit__tokenize}, - {"_typing", PyInit__typing}, - {"_statistics", PyInit__statistics}, #ifdef WIN32 {"msvcrt", PyInit_msvcrt}, {"_locale", PyInit__locale}, From 26cfeb074ec8fa49e66eb5d1ac5e8aa976ccd47d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?B=C3=A9n=C3=A9dikt=20Tran?= <10796600+picnixz@users.noreply.github.com> Date: Tue, 1 Apr 2025 11:59:31 +0200 Subject: [PATCH 44/45] update naming --- PC/config.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/PC/config.c b/PC/config.c index 29a7a0578ad62f..7affa5ae1bf01c 100644 --- a/PC/config.c +++ b/PC/config.c @@ -22,12 +22,13 @@ extern PyObject* PyInit__sysconfig(void); extern PyObject* PyInit__typing(void); extern PyObject* PyInit_time(void); extern PyObject* PyInit__thread(void); -/* cryptographic primitives */ +/* 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 From 258aa20b2e275c797166483567d9a7f530318561 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?B=C3=A9n=C3=A9dikt=20Tran?= <10796600+picnixz@users.noreply.github.com> Date: Tue, 1 Apr 2025 11:59:44 +0200 Subject: [PATCH 45/45] update naming --- PC/config.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/PC/config.c b/PC/config.c index 7affa5ae1bf01c..5c6f37ccf21896 100644 --- a/PC/config.c +++ b/PC/config.c @@ -22,6 +22,7 @@ extern PyObject* PyInit__sysconfig(void); extern PyObject* PyInit__typing(void); extern PyObject* PyInit_time(void); extern PyObject* PyInit__thread(void); + /* cryptographic hash functions */ extern PyObject* PyInit__blake2(void); extern PyObject* PyInit__md5(void); @@ -30,7 +31,7 @@ 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);