xref: /linux/crypto/xxhash_generic.c (revision 674f368a)
167882e76SNikolay Borisov // SPDX-License-Identifier: GPL-2.0
267882e76SNikolay Borisov 
367882e76SNikolay Borisov #include <crypto/internal/hash.h>
467882e76SNikolay Borisov #include <linux/init.h>
567882e76SNikolay Borisov #include <linux/module.h>
667882e76SNikolay Borisov #include <linux/xxhash.h>
767882e76SNikolay Borisov #include <asm/unaligned.h>
867882e76SNikolay Borisov 
967882e76SNikolay Borisov #define XXHASH64_BLOCK_SIZE	32
1067882e76SNikolay Borisov #define XXHASH64_DIGEST_SIZE	8
1167882e76SNikolay Borisov 
1267882e76SNikolay Borisov struct xxhash64_tfm_ctx {
1367882e76SNikolay Borisov 	u64 seed;
1467882e76SNikolay Borisov };
1567882e76SNikolay Borisov 
1667882e76SNikolay Borisov struct xxhash64_desc_ctx {
1767882e76SNikolay Borisov 	struct xxh64_state xxhstate;
1867882e76SNikolay Borisov };
1967882e76SNikolay Borisov 
xxhash64_setkey(struct crypto_shash * tfm,const u8 * key,unsigned int keylen)2067882e76SNikolay Borisov static int xxhash64_setkey(struct crypto_shash *tfm, const u8 *key,
2167882e76SNikolay Borisov 			 unsigned int keylen)
2267882e76SNikolay Borisov {
2367882e76SNikolay Borisov 	struct xxhash64_tfm_ctx *tctx = crypto_shash_ctx(tfm);
2467882e76SNikolay Borisov 
25*674f368aSEric Biggers 	if (keylen != sizeof(tctx->seed))
2667882e76SNikolay Borisov 		return -EINVAL;
2767882e76SNikolay Borisov 	tctx->seed = get_unaligned_le64(key);
2867882e76SNikolay Borisov 	return 0;
2967882e76SNikolay Borisov }
3067882e76SNikolay Borisov 
xxhash64_init(struct shash_desc * desc)3167882e76SNikolay Borisov static int xxhash64_init(struct shash_desc *desc)
3267882e76SNikolay Borisov {
3367882e76SNikolay Borisov 	struct xxhash64_tfm_ctx *tctx = crypto_shash_ctx(desc->tfm);
3467882e76SNikolay Borisov 	struct xxhash64_desc_ctx *dctx = shash_desc_ctx(desc);
3567882e76SNikolay Borisov 
3667882e76SNikolay Borisov 	xxh64_reset(&dctx->xxhstate, tctx->seed);
3767882e76SNikolay Borisov 
3867882e76SNikolay Borisov 	return 0;
3967882e76SNikolay Borisov }
4067882e76SNikolay Borisov 
xxhash64_update(struct shash_desc * desc,const u8 * data,unsigned int length)4167882e76SNikolay Borisov static int xxhash64_update(struct shash_desc *desc, const u8 *data,
4267882e76SNikolay Borisov 			 unsigned int length)
4367882e76SNikolay Borisov {
4467882e76SNikolay Borisov 	struct xxhash64_desc_ctx *dctx = shash_desc_ctx(desc);
4567882e76SNikolay Borisov 
4667882e76SNikolay Borisov 	xxh64_update(&dctx->xxhstate, data, length);
4767882e76SNikolay Borisov 
4867882e76SNikolay Borisov 	return 0;
4967882e76SNikolay Borisov }
5067882e76SNikolay Borisov 
xxhash64_final(struct shash_desc * desc,u8 * out)5167882e76SNikolay Borisov static int xxhash64_final(struct shash_desc *desc, u8 *out)
5267882e76SNikolay Borisov {
5367882e76SNikolay Borisov 	struct xxhash64_desc_ctx *dctx = shash_desc_ctx(desc);
5467882e76SNikolay Borisov 
5567882e76SNikolay Borisov 	put_unaligned_le64(xxh64_digest(&dctx->xxhstate), out);
5667882e76SNikolay Borisov 
5767882e76SNikolay Borisov 	return 0;
5867882e76SNikolay Borisov }
5967882e76SNikolay Borisov 
xxhash64_digest(struct shash_desc * desc,const u8 * data,unsigned int length,u8 * out)6067882e76SNikolay Borisov static int xxhash64_digest(struct shash_desc *desc, const u8 *data,
6167882e76SNikolay Borisov 			 unsigned int length, u8 *out)
6267882e76SNikolay Borisov {
6367882e76SNikolay Borisov 	struct xxhash64_tfm_ctx *tctx = crypto_shash_ctx(desc->tfm);
6467882e76SNikolay Borisov 
6567882e76SNikolay Borisov 	put_unaligned_le64(xxh64(data, length, tctx->seed), out);
6667882e76SNikolay Borisov 
6767882e76SNikolay Borisov 	return 0;
6867882e76SNikolay Borisov }
6967882e76SNikolay Borisov 
7067882e76SNikolay Borisov static struct shash_alg alg = {
7167882e76SNikolay Borisov 	.digestsize	= XXHASH64_DIGEST_SIZE,
7267882e76SNikolay Borisov 	.setkey		= xxhash64_setkey,
7367882e76SNikolay Borisov 	.init		= xxhash64_init,
7467882e76SNikolay Borisov 	.update		= xxhash64_update,
7567882e76SNikolay Borisov 	.final		= xxhash64_final,
7667882e76SNikolay Borisov 	.digest		= xxhash64_digest,
7767882e76SNikolay Borisov 	.descsize	= sizeof(struct xxhash64_desc_ctx),
7867882e76SNikolay Borisov 	.base		= {
7967882e76SNikolay Borisov 		.cra_name	 = "xxhash64",
8067882e76SNikolay Borisov 		.cra_driver_name = "xxhash64-generic",
8167882e76SNikolay Borisov 		.cra_priority	 = 100,
8267882e76SNikolay Borisov 		.cra_flags	 = CRYPTO_ALG_OPTIONAL_KEY,
8367882e76SNikolay Borisov 		.cra_blocksize	 = XXHASH64_BLOCK_SIZE,
8467882e76SNikolay Borisov 		.cra_ctxsize	 = sizeof(struct xxhash64_tfm_ctx),
8567882e76SNikolay Borisov 		.cra_module	 = THIS_MODULE,
8667882e76SNikolay Borisov 	}
8767882e76SNikolay Borisov };
8867882e76SNikolay Borisov 
xxhash_mod_init(void)8967882e76SNikolay Borisov static int __init xxhash_mod_init(void)
9067882e76SNikolay Borisov {
9167882e76SNikolay Borisov 	return crypto_register_shash(&alg);
9267882e76SNikolay Borisov }
9367882e76SNikolay Borisov 
xxhash_mod_fini(void)9467882e76SNikolay Borisov static void __exit xxhash_mod_fini(void)
9567882e76SNikolay Borisov {
9667882e76SNikolay Borisov 	crypto_unregister_shash(&alg);
9767882e76SNikolay Borisov }
9867882e76SNikolay Borisov 
9967882e76SNikolay Borisov subsys_initcall(xxhash_mod_init);
10067882e76SNikolay Borisov module_exit(xxhash_mod_fini);
10167882e76SNikolay Borisov 
10267882e76SNikolay Borisov MODULE_AUTHOR("Nikolay Borisov <nborisov@suse.com>");
10367882e76SNikolay Borisov MODULE_DESCRIPTION("xxhash calculations wrapper for lib/xxhash.c");
10467882e76SNikolay Borisov MODULE_LICENSE("GPL");
10567882e76SNikolay Borisov MODULE_ALIAS_CRYPTO("xxhash64");
10667882e76SNikolay Borisov MODULE_ALIAS_CRYPTO("xxhash64-generic");
107