initial implementation of Ascon-Hash256
Signed-off-by: Rusydi H. Makarim <rusydi.makarim@kriptograf.id>
---
include/crypto/ascon_hash.h | 2 +-
lib/crypto/Kconfig | 8 +++
lib/crypto/Makefile | 5 ++
lib/crypto/ascon_hash.c | 154 ++++++++++++++++++++++++++++++++++++++++++++
lib/crypto/hash_info.c | 2 +
5 files changed, 170 insertions(+), 1 deletion(-)
diff --git a/include/crypto/ascon_hash.h b/include/crypto/ascon_hash.h
index bb3561a745a9..c03a1414eec9 100644
--- a/include/crypto/ascon_hash.h
+++ b/include/crypto/ascon_hash.h
@@ -18,7 +18,7 @@
/*
* The standard of Ascon permutation in NIST SP 800-232 specifies 16 round
- * constants to accomodate potential functionality extensions in the future
+ * constants to accommodate potential functionality extensions in the future
* (see page 2).
*/
static const u64 ascon_p_rndc[] = {
diff --git a/lib/crypto/Kconfig b/lib/crypto/Kconfig
index 6871a41e5069..5f39ed6746de 100644
--- a/lib/crypto/Kconfig
+++ b/lib/crypto/Kconfig
@@ -223,6 +223,14 @@ config CRYPTO_LIB_SHA3_ARCH
default y if ARM64 && KERNEL_MODE_NEON
default y if S390
+config CRYPTO_LIB_ASCON_HASH
+ tristate
+ select CRYPTO_LIB_UTILS
+ help
+ The Ascon-Hash library functions. Select this if your module uses any of
+ the functions from <crypto/ascon_hash.h>
+
+
config CRYPTO_LIB_SM3
tristate
diff --git a/lib/crypto/Makefile b/lib/crypto/Makefile
index 330ab65b29c4..6657ea3d8771 100644
--- a/lib/crypto/Makefile
+++ b/lib/crypto/Makefile
@@ -297,6 +297,11 @@ endif # CONFIG_CRYPTO_LIB_SHA3_ARCH
################################################################################
+obj-$(CONFIG_CRYPTO_LIB_ASCON_HASH) += libascon_hash.o
+libascon_hash-y := ascon_hash.o
+
+################################################################################
+
obj-$(CONFIG_MPILIB) += mpi/
obj-$(CONFIG_CRYPTO_SELFTESTS_FULL) += simd.o
diff --git a/lib/crypto/ascon_hash.c b/lib/crypto/ascon_hash.c
new file mode 100644
index 000000000000..e435a0e72195
--- /dev/null
+++ b/lib/crypto/ascon_hash.c
@@ -0,0 +1,154 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * Ascon-Hash library functions
+ *
+ * Copyright (c) 2025 Rusydi H. Makarim <rusydi.makarim@kriptograf.id>
+ */
+
+#include <linux/module.h>
+#include <crypto/ascon_hash.h>
+#include <crypto/utils.h>
+
+
+static inline void ascon_round(u64 s[ASCON_STATE_WORDS], u64 C)
+{
+ u64 t[ASCON_STATE_WORDS];
+
+ // pC
+ s[2] ^= C;
+
+ // pS
+ s[0] ^= s[4];
+ s[4] ^= s[3];
+ s[2] ^= s[1];
+ t[0] = s[0] ^ (~s[1] & s[2]);
+ t[1] = s[1] ^ (~s[2] & s[3]);
+ t[2] = s[2] ^ (~s[3] & s[4]);
+ t[3] = s[3] ^ (~s[4] & s[0]);
+ t[4] = s[4] ^ (~s[0] & s[1]);
+ t[1] ^= t[0];
+ t[0] ^= t[4];
+ t[3] ^= t[2];
+ t[2] = ~t[2];
+
+ // pL
+ s[0] = t[0] ^ ror64(t[0], 19) ^ ror64(t[0], 28);
+ s[1] = t[1] ^ ror64(t[1], 61) ^ ror64(t[1], 39);
+ s[2] = t[2] ^ ror64(t[2], 1) ^ ror64(t[2], 6);
+ s[3] = t[3] ^ ror64(t[3], 10) ^ ror64(t[3], 17);
+ s[4] = t[4] ^ ror64(t[4], 7) ^ ror64(t[4], 41);
+}
+
+static inline void ascon_p12_generic(struct ascon_state *state)
+{
+ int i;
+
+ for (i = 0; i < ARRAY_SIZE(state->words); ++i)
+ state->native_words[i] = le64_to_cpu(state->words[i]);
+
+ for (i = 0; i < 12; ++i)
+ ascon_round(state->native_words, ascon_p_rndc[16 - 12 + i]);
+
+ for (i = 0; i < ARRAY_SIZE(state->words); ++i)
+ state->words[i] = cpu_to_le64(state->native_words[i]);
+}
+
+static void __maybe_unused ascon_hash256_absorb_blocks_generic(
+ struct ascon_state *state, const u8 *in, size_t nblocks)
+{
+ do {
+ for (size_t i = 0; i < ASCON_HASH256_BLOCK_SIZE; i += 8)
+ state->words[i / 8] ^= get_unaligned((__le64 *)&in[i]);
+ ascon_p12_generic(state);
+ in += ASCON_HASH256_BLOCK_SIZE;
+ } while (--nblocks);
+}
+
+#define ascon_p12 ascon_p12_generic
+#define ascon_hash256_absorb_blocks ascon_hash256_absorb_blocks_generic
+
+void ascon_hash256_init(struct ascon_hash256_ctx *asc_hash256_ctx)
+{
+ struct __ascon_hash_ctx *ctx = &asc_hash256_ctx->ctx;
+
+ ctx->state.words[0] = ASCON_HASH256_IV;
+ ctx->state.words[1] = 0;
+ ctx->state.words[2] = 0;
+ ctx->state.words[3] = 0;
+ ctx->state.words[4] = 0;
+ ctx->absorb_offset = 0;
+ ascon_p12(&ctx->state);
+}
+EXPORT_SYMBOL_GPL(ascon_hash256_init);
+
+void ascon_hash256_update(struct ascon_hash256_ctx *asc_hash256_ctx, const u8 *in,
+ size_t in_len)
+{
+ struct __ascon_hash_ctx *ctx = &asc_hash256_ctx->ctx;
+ u8 absorb_offset = ctx->absorb_offset;
+
+ WARN_ON_ONCE(absorb_offset >= ASCON_HASH256_BLOCK_SIZE);
+
+ if (absorb_offset && absorb_offset + in_len >= ASCON_HASH256_BLOCK_SIZE) {
+ crypto_xor(&ctx->state.bytes[absorb_offset], in,
+ ASCON_HASH256_BLOCK_SIZE - absorb_offset);
+ in += ASCON_HASH256_BLOCK_SIZE - absorb_offset;
+ in_len -= ASCON_HASH256_BLOCK_SIZE - absorb_offset;
+ ascon_p12(&ctx->state);
+ absorb_offset = 0;
+ }
+
+ if (in_len >= ASCON_HASH256_BLOCK_SIZE) {
+ size_t nblocks = in_len / ASCON_HASH256_BLOCK_SIZE;
+
+ ascon_hash256_absorb_blocks(&ctx->state, in, nblocks);
+ in += nblocks * ASCON_HASH256_BLOCK_SIZE;
+ in_len -= nblocks * ASCON_HASH256_BLOCK_SIZE;
+ }
+
+ if (in_len) {
+ crypto_xor(&ctx->state.bytes[absorb_offset], in, in_len);
+ absorb_offset += in_len;
+
+ }
+ ctx->absorb_offset = absorb_offset;
+}
+EXPORT_SYMBOL_GPL(ascon_hash256_update);
+
+void ascon_hash256_final(struct ascon_hash256_ctx *asc_hash256_ctx,
+ u8 out[ASCON_HASH256_DIGEST_SIZE])
+{
+ struct __ascon_hash_ctx *ctx = &asc_hash256_ctx->ctx;
+
+ // padding
+ ctx->state.bytes[ctx->absorb_offset] ^= 0x01;
+ ascon_p12(&ctx->state);
+
+ // squeezing
+ size_t len = ASCON_HASH256_DIGEST_SIZE;
+
+ while (len > ASCON_HASH256_RATE) {
+ memcpy(out, ctx->state.bytes, ASCON_HASH256_RATE);
+ ascon_p12(&ctx->state);
+ out += ASCON_HASH256_RATE;
+ len -= ASCON_HASH256_RATE;
+ }
+ memcpy(out, ctx->state.bytes, ASCON_HASH256_RATE);
+ memzero_explicit(asc_hash256_ctx, sizeof(*asc_hash256_ctx));
+}
+EXPORT_SYMBOL_GPL(ascon_hash256_final);
+
+
+void ascon_hash256(const u8 *in, size_t in_len,
+ u8 out[ASCON_HASH256_DIGEST_SIZE])
+{
+ struct ascon_hash256_ctx ctx;
+
+ ascon_hash256_init(&ctx);
+ ascon_hash256_update(&ctx, in, in_len);
+ ascon_hash256_final(&ctx, out);
+}
+EXPORT_SYMBOL_GPL(ascon_hash256);
+
+MODULE_DESCRIPTION("Ascon-Hash256 library functions");
+MODULE_LICENSE("GPL");
diff --git a/lib/crypto/hash_info.c b/lib/crypto/hash_info.c
index 9a467638c971..49ce182c6d08 100644
--- a/lib/crypto/hash_info.c
+++ b/lib/crypto/hash_info.c
@@ -32,6 +32,7 @@ const char *const hash_algo_name[HASH_ALGO__LAST] = {
[HASH_ALGO_SHA3_256] = "sha3-256",
[HASH_ALGO_SHA3_384] = "sha3-384",
[HASH_ALGO_SHA3_512] = "sha3-512",
+ [HASH_ALGO_ASCON_HASH256] = "ascon-hash256",
};
EXPORT_SYMBOL_GPL(hash_algo_name);
@@ -59,5 +60,6 @@ const int hash_digest_size[HASH_ALGO__LAST] = {
[HASH_ALGO_SHA3_256] = SHA3_256_DIGEST_SIZE,
[HASH_ALGO_SHA3_384] = SHA3_384_DIGEST_SIZE,
[HASH_ALGO_SHA3_512] = SHA3_512_DIGEST_SIZE,
+ [HASH_ALGO_ASCON_HASH256] = ASCON_HASH256_DIGEST_SIZE,
};
EXPORT_SYMBOL_GPL(hash_digest_size);
--
2.52.0
Hi Rusydi,
kernel test robot noticed the following build errors:
[auto build test ERROR on ebiggers/libcrypto-next]
[also build test ERROR on ebiggers/libcrypto-fixes linus/master v6.19-rc1 next-20251215]
[cannot apply to herbert-cryptodev-2.6/master herbert-crypto-2.6/master]
[If your patch is applied to the wrong git tree, kindly drop us a note.
And when submitting patch, we suggest to use '--base' as documented in
https://git-scm.com/docs/git-format-patch#_base_tree_information]
url: https://github.com/intel-lab-lkp/linux/commits/Rusydi-H-Makarim/lib-crypto-Initial-implementation-of-Ascon-Hash256/20251215-165442
base: https://git.kernel.org/pub/scm/linux/kernel/git/ebiggers/linux.git libcrypto-next
patch link: https://lore.kernel.org/r/20251215-ascon_hash256-v1-2-24ae735e571e%40kriptograf.id
patch subject: [PATCH 2/3] lib/crypto: Initial implementation of Ascon-Hash256
config: x86_64-kexec (https://download.01.org/0day-ci/archive/20251216/202512160656.DWMVkABi-lkp@intel.com/config)
compiler: clang version 20.1.8 (https://github.com/llvm/llvm-project 87f0227cb60147a26a1eeb4fb06e3b505e9c7261)
reproduce (this is a W=1 build): (https://download.01.org/0day-ci/archive/20251216/202512160656.DWMVkABi-lkp@intel.com/reproduce)
If you fix the issue in a separate patch/commit (i.e. not just a new version of
the same patch/commit), kindly add following tags
| Reported-by: kernel test robot <lkp@intel.com>
| Closes: https://lore.kernel.org/oe-kbuild-all/202512160656.DWMVkABi-lkp@intel.com/
All errors (new ones prefixed by >>):
>> lib/crypto/hash_info.c:35:3: error: use of undeclared identifier 'HASH_ALGO_ASCON_HASH256'
35 | [HASH_ALGO_ASCON_HASH256] = "ascon-hash256",
| ^
>> lib/crypto/hash_info.c:63:30: error: use of undeclared identifier 'ASCON_HASH256_DIGEST_SIZE'
63 | [HASH_ALGO_ASCON_HASH256] = ASCON_HASH256_DIGEST_SIZE,
| ^
lib/crypto/hash_info.c:63:3: error: use of undeclared identifier 'HASH_ALGO_ASCON_HASH256'
63 | [HASH_ALGO_ASCON_HASH256] = ASCON_HASH256_DIGEST_SIZE,
| ^
3 errors generated.
vim +/HASH_ALGO_ASCON_HASH256 +35 lib/crypto/hash_info.c
10
11 const char *const hash_algo_name[HASH_ALGO__LAST] = {
12 [HASH_ALGO_MD4] = "md4",
13 [HASH_ALGO_MD5] = "md5",
14 [HASH_ALGO_SHA1] = "sha1",
15 [HASH_ALGO_RIPE_MD_160] = "rmd160",
16 [HASH_ALGO_SHA256] = "sha256",
17 [HASH_ALGO_SHA384] = "sha384",
18 [HASH_ALGO_SHA512] = "sha512",
19 [HASH_ALGO_SHA224] = "sha224",
20 [HASH_ALGO_RIPE_MD_128] = "rmd128",
21 [HASH_ALGO_RIPE_MD_256] = "rmd256",
22 [HASH_ALGO_RIPE_MD_320] = "rmd320",
23 [HASH_ALGO_WP_256] = "wp256",
24 [HASH_ALGO_WP_384] = "wp384",
25 [HASH_ALGO_WP_512] = "wp512",
26 [HASH_ALGO_TGR_128] = "tgr128",
27 [HASH_ALGO_TGR_160] = "tgr160",
28 [HASH_ALGO_TGR_192] = "tgr192",
29 [HASH_ALGO_SM3_256] = "sm3",
30 [HASH_ALGO_STREEBOG_256] = "streebog256",
31 [HASH_ALGO_STREEBOG_512] = "streebog512",
32 [HASH_ALGO_SHA3_256] = "sha3-256",
33 [HASH_ALGO_SHA3_384] = "sha3-384",
34 [HASH_ALGO_SHA3_512] = "sha3-512",
> 35 [HASH_ALGO_ASCON_HASH256] = "ascon-hash256",
36 };
37 EXPORT_SYMBOL_GPL(hash_algo_name);
38
39 const int hash_digest_size[HASH_ALGO__LAST] = {
40 [HASH_ALGO_MD4] = MD5_DIGEST_SIZE,
41 [HASH_ALGO_MD5] = MD5_DIGEST_SIZE,
42 [HASH_ALGO_SHA1] = SHA1_DIGEST_SIZE,
43 [HASH_ALGO_RIPE_MD_160] = RMD160_DIGEST_SIZE,
44 [HASH_ALGO_SHA256] = SHA256_DIGEST_SIZE,
45 [HASH_ALGO_SHA384] = SHA384_DIGEST_SIZE,
46 [HASH_ALGO_SHA512] = SHA512_DIGEST_SIZE,
47 [HASH_ALGO_SHA224] = SHA224_DIGEST_SIZE,
48 [HASH_ALGO_RIPE_MD_128] = RMD128_DIGEST_SIZE,
49 [HASH_ALGO_RIPE_MD_256] = RMD256_DIGEST_SIZE,
50 [HASH_ALGO_RIPE_MD_320] = RMD320_DIGEST_SIZE,
51 [HASH_ALGO_WP_256] = WP256_DIGEST_SIZE,
52 [HASH_ALGO_WP_384] = WP384_DIGEST_SIZE,
53 [HASH_ALGO_WP_512] = WP512_DIGEST_SIZE,
54 [HASH_ALGO_TGR_128] = TGR128_DIGEST_SIZE,
55 [HASH_ALGO_TGR_160] = TGR160_DIGEST_SIZE,
56 [HASH_ALGO_TGR_192] = TGR192_DIGEST_SIZE,
57 [HASH_ALGO_SM3_256] = SM3256_DIGEST_SIZE,
58 [HASH_ALGO_STREEBOG_256] = STREEBOG256_DIGEST_SIZE,
59 [HASH_ALGO_STREEBOG_512] = STREEBOG512_DIGEST_SIZE,
60 [HASH_ALGO_SHA3_256] = SHA3_256_DIGEST_SIZE,
61 [HASH_ALGO_SHA3_384] = SHA3_384_DIGEST_SIZE,
62 [HASH_ALGO_SHA3_512] = SHA3_512_DIGEST_SIZE,
> 63 [HASH_ALGO_ASCON_HASH256] = ASCON_HASH256_DIGEST_SIZE,
--
0-DAY CI Kernel Test Service
https://github.com/intel/lkp-tests/wiki
© 2016 - 2025 Red Hat, Inc.