0001
0002
0003 #include <crypto/internal/hash.h>
0004 #include <linux/init.h>
0005 #include <linux/module.h>
0006 #include <linux/xxhash.h>
0007 #include <asm/unaligned.h>
0008
0009 #define XXHASH64_BLOCK_SIZE 32
0010 #define XXHASH64_DIGEST_SIZE 8
0011
0012 struct xxhash64_tfm_ctx {
0013 u64 seed;
0014 };
0015
0016 struct xxhash64_desc_ctx {
0017 struct xxh64_state xxhstate;
0018 };
0019
0020 static int xxhash64_setkey(struct crypto_shash *tfm, const u8 *key,
0021 unsigned int keylen)
0022 {
0023 struct xxhash64_tfm_ctx *tctx = crypto_shash_ctx(tfm);
0024
0025 if (keylen != sizeof(tctx->seed))
0026 return -EINVAL;
0027 tctx->seed = get_unaligned_le64(key);
0028 return 0;
0029 }
0030
0031 static int xxhash64_init(struct shash_desc *desc)
0032 {
0033 struct xxhash64_tfm_ctx *tctx = crypto_shash_ctx(desc->tfm);
0034 struct xxhash64_desc_ctx *dctx = shash_desc_ctx(desc);
0035
0036 xxh64_reset(&dctx->xxhstate, tctx->seed);
0037
0038 return 0;
0039 }
0040
0041 static int xxhash64_update(struct shash_desc *desc, const u8 *data,
0042 unsigned int length)
0043 {
0044 struct xxhash64_desc_ctx *dctx = shash_desc_ctx(desc);
0045
0046 xxh64_update(&dctx->xxhstate, data, length);
0047
0048 return 0;
0049 }
0050
0051 static int xxhash64_final(struct shash_desc *desc, u8 *out)
0052 {
0053 struct xxhash64_desc_ctx *dctx = shash_desc_ctx(desc);
0054
0055 put_unaligned_le64(xxh64_digest(&dctx->xxhstate), out);
0056
0057 return 0;
0058 }
0059
0060 static int xxhash64_digest(struct shash_desc *desc, const u8 *data,
0061 unsigned int length, u8 *out)
0062 {
0063 struct xxhash64_tfm_ctx *tctx = crypto_shash_ctx(desc->tfm);
0064
0065 put_unaligned_le64(xxh64(data, length, tctx->seed), out);
0066
0067 return 0;
0068 }
0069
0070 static struct shash_alg alg = {
0071 .digestsize = XXHASH64_DIGEST_SIZE,
0072 .setkey = xxhash64_setkey,
0073 .init = xxhash64_init,
0074 .update = xxhash64_update,
0075 .final = xxhash64_final,
0076 .digest = xxhash64_digest,
0077 .descsize = sizeof(struct xxhash64_desc_ctx),
0078 .base = {
0079 .cra_name = "xxhash64",
0080 .cra_driver_name = "xxhash64-generic",
0081 .cra_priority = 100,
0082 .cra_flags = CRYPTO_ALG_OPTIONAL_KEY,
0083 .cra_blocksize = XXHASH64_BLOCK_SIZE,
0084 .cra_ctxsize = sizeof(struct xxhash64_tfm_ctx),
0085 .cra_module = THIS_MODULE,
0086 }
0087 };
0088
0089 static int __init xxhash_mod_init(void)
0090 {
0091 return crypto_register_shash(&alg);
0092 }
0093
0094 static void __exit xxhash_mod_fini(void)
0095 {
0096 crypto_unregister_shash(&alg);
0097 }
0098
0099 subsys_initcall(xxhash_mod_init);
0100 module_exit(xxhash_mod_fini);
0101
0102 MODULE_AUTHOR("Nikolay Borisov <nborisov@suse.com>");
0103 MODULE_DESCRIPTION("xxhash calculations wrapper for lib/xxhash.c");
0104 MODULE_LICENSE("GPL");
0105 MODULE_ALIAS_CRYPTO("xxhash64");
0106 MODULE_ALIAS_CRYPTO("xxhash64-generic");