[PATCH 2/3] lib/crypto: Initial implementation of Ascon-Hash256

Rusydi H. Makarim posted 3 patches 1 day, 20 hours ago
[PATCH 2/3] lib/crypto: Initial implementation of Ascon-Hash256
Posted by Rusydi H. Makarim 1 day, 20 hours ago
	    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
Re: [PATCH 2/3] lib/crypto: Initial implementation of Ascon-Hash256
Posted by kernel test robot 1 day, 5 hours ago
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