xref: /linux/crypto/crc32_generic.c (revision 0f049f7d)
1*0f049f7dSChristophe JAILLET // SPDX-License-Identifier: GPL-2.0-only
2a7c58ac0SHerbert Xu /*
3a7c58ac0SHerbert Xu  * Copyright 2012 Xyratex Technology Limited
4a7c58ac0SHerbert Xu  */
5a7c58ac0SHerbert Xu 
6a7c58ac0SHerbert Xu /*
7a7c58ac0SHerbert Xu  * This is crypto api shash wrappers to crc32_le.
8a7c58ac0SHerbert Xu  */
9a7c58ac0SHerbert Xu 
10fffe7d92SEric Biggers #include <asm/unaligned.h>
11a7c58ac0SHerbert Xu #include <linux/crc32.h>
12a7c58ac0SHerbert Xu #include <crypto/internal/hash.h>
13a7c58ac0SHerbert Xu #include <linux/init.h>
14a7c58ac0SHerbert Xu #include <linux/module.h>
15a7c58ac0SHerbert Xu #include <linux/string.h>
16a7c58ac0SHerbert Xu #include <linux/kernel.h>
17a7c58ac0SHerbert Xu 
18a7c58ac0SHerbert Xu #define CHKSUM_BLOCK_SIZE	1
19a7c58ac0SHerbert Xu #define CHKSUM_DIGEST_SIZE	4
20a7c58ac0SHerbert Xu 
21a7c58ac0SHerbert Xu /** No default init with ~0 */
crc32_cra_init(struct crypto_tfm * tfm)22a7c58ac0SHerbert Xu static int crc32_cra_init(struct crypto_tfm *tfm)
23a7c58ac0SHerbert Xu {
24a7c58ac0SHerbert Xu 	u32 *key = crypto_tfm_ctx(tfm);
25a7c58ac0SHerbert Xu 
26a7c58ac0SHerbert Xu 	*key = 0;
27a7c58ac0SHerbert Xu 
28a7c58ac0SHerbert Xu 	return 0;
29a7c58ac0SHerbert Xu }
30a7c58ac0SHerbert Xu 
31a7c58ac0SHerbert Xu /*
32a7c58ac0SHerbert Xu  * Setting the seed allows arbitrary accumulators and flexible XOR policy
33a7c58ac0SHerbert Xu  * If your algorithm starts with ~0, then XOR with ~0 before you set
34a7c58ac0SHerbert Xu  * the seed.
35a7c58ac0SHerbert Xu  */
crc32_setkey(struct crypto_shash * hash,const u8 * key,unsigned int keylen)36a7c58ac0SHerbert Xu static int crc32_setkey(struct crypto_shash *hash, const u8 *key,
37a7c58ac0SHerbert Xu 			unsigned int keylen)
38a7c58ac0SHerbert Xu {
39a7c58ac0SHerbert Xu 	u32 *mctx = crypto_shash_ctx(hash);
40a7c58ac0SHerbert Xu 
41674f368aSEric Biggers 	if (keylen != sizeof(u32))
42a7c58ac0SHerbert Xu 		return -EINVAL;
43fffe7d92SEric Biggers 	*mctx = get_unaligned_le32(key);
44a7c58ac0SHerbert Xu 	return 0;
45a7c58ac0SHerbert Xu }
46a7c58ac0SHerbert Xu 
crc32_init(struct shash_desc * desc)47a7c58ac0SHerbert Xu static int crc32_init(struct shash_desc *desc)
48a7c58ac0SHerbert Xu {
49a7c58ac0SHerbert Xu 	u32 *mctx = crypto_shash_ctx(desc->tfm);
50a7c58ac0SHerbert Xu 	u32 *crcp = shash_desc_ctx(desc);
51a7c58ac0SHerbert Xu 
52a7c58ac0SHerbert Xu 	*crcp = *mctx;
53a7c58ac0SHerbert Xu 
54a7c58ac0SHerbert Xu 	return 0;
55a7c58ac0SHerbert Xu }
56a7c58ac0SHerbert Xu 
crc32_update(struct shash_desc * desc,const u8 * data,unsigned int len)57a7c58ac0SHerbert Xu static int crc32_update(struct shash_desc *desc, const u8 *data,
58a7c58ac0SHerbert Xu 			unsigned int len)
59a7c58ac0SHerbert Xu {
60a7c58ac0SHerbert Xu 	u32 *crcp = shash_desc_ctx(desc);
61a7c58ac0SHerbert Xu 
626943546cSEric Biggers 	*crcp = crc32_le(*crcp, data, len);
63a7c58ac0SHerbert Xu 	return 0;
64a7c58ac0SHerbert Xu }
65a7c58ac0SHerbert Xu 
66a7c58ac0SHerbert Xu /* No final XOR 0xFFFFFFFF, like crc32_le */
__crc32_finup(u32 * crcp,const u8 * data,unsigned int len,u8 * out)67a7c58ac0SHerbert Xu static int __crc32_finup(u32 *crcp, const u8 *data, unsigned int len,
68a7c58ac0SHerbert Xu 			 u8 *out)
69a7c58ac0SHerbert Xu {
706943546cSEric Biggers 	put_unaligned_le32(crc32_le(*crcp, data, len), out);
71a7c58ac0SHerbert Xu 	return 0;
72a7c58ac0SHerbert Xu }
73a7c58ac0SHerbert Xu 
crc32_finup(struct shash_desc * desc,const u8 * data,unsigned int len,u8 * out)74a7c58ac0SHerbert Xu static int crc32_finup(struct shash_desc *desc, const u8 *data,
75a7c58ac0SHerbert Xu 		       unsigned int len, u8 *out)
76a7c58ac0SHerbert Xu {
77a7c58ac0SHerbert Xu 	return __crc32_finup(shash_desc_ctx(desc), data, len, out);
78a7c58ac0SHerbert Xu }
79a7c58ac0SHerbert Xu 
crc32_final(struct shash_desc * desc,u8 * out)80a7c58ac0SHerbert Xu static int crc32_final(struct shash_desc *desc, u8 *out)
81a7c58ac0SHerbert Xu {
82a7c58ac0SHerbert Xu 	u32 *crcp = shash_desc_ctx(desc);
83a7c58ac0SHerbert Xu 
84fffe7d92SEric Biggers 	put_unaligned_le32(*crcp, out);
85a7c58ac0SHerbert Xu 	return 0;
86a7c58ac0SHerbert Xu }
87a7c58ac0SHerbert Xu 
crc32_digest(struct shash_desc * desc,const u8 * data,unsigned int len,u8 * out)88a7c58ac0SHerbert Xu static int crc32_digest(struct shash_desc *desc, const u8 *data,
89a7c58ac0SHerbert Xu 			unsigned int len, u8 *out)
90a7c58ac0SHerbert Xu {
91a7c58ac0SHerbert Xu 	return __crc32_finup(crypto_shash_ctx(desc->tfm), data, len,
92a7c58ac0SHerbert Xu 			     out);
93a7c58ac0SHerbert Xu }
94a7c58ac0SHerbert Xu static struct shash_alg alg = {
95a7c58ac0SHerbert Xu 	.setkey		= crc32_setkey,
96a7c58ac0SHerbert Xu 	.init		= crc32_init,
97a7c58ac0SHerbert Xu 	.update		= crc32_update,
98a7c58ac0SHerbert Xu 	.final		= crc32_final,
99a7c58ac0SHerbert Xu 	.finup		= crc32_finup,
100a7c58ac0SHerbert Xu 	.digest		= crc32_digest,
101a7c58ac0SHerbert Xu 	.descsize	= sizeof(u32),
102a7c58ac0SHerbert Xu 	.digestsize	= CHKSUM_DIGEST_SIZE,
103a7c58ac0SHerbert Xu 	.base		= {
104a7c58ac0SHerbert Xu 		.cra_name		= "crc32",
105a7c58ac0SHerbert Xu 		.cra_driver_name	= "crc32-generic",
106a7c58ac0SHerbert Xu 		.cra_priority		= 100,
107a208fa8fSEric Biggers 		.cra_flags		= CRYPTO_ALG_OPTIONAL_KEY,
108a7c58ac0SHerbert Xu 		.cra_blocksize		= CHKSUM_BLOCK_SIZE,
109a7c58ac0SHerbert Xu 		.cra_ctxsize		= sizeof(u32),
110a7c58ac0SHerbert Xu 		.cra_module		= THIS_MODULE,
111a7c58ac0SHerbert Xu 		.cra_init		= crc32_cra_init,
112a7c58ac0SHerbert Xu 	}
113a7c58ac0SHerbert Xu };
114a7c58ac0SHerbert Xu 
crc32_mod_init(void)115a7c58ac0SHerbert Xu static int __init crc32_mod_init(void)
116a7c58ac0SHerbert Xu {
117a7c58ac0SHerbert Xu 	return crypto_register_shash(&alg);
118a7c58ac0SHerbert Xu }
119a7c58ac0SHerbert Xu 
crc32_mod_fini(void)120a7c58ac0SHerbert Xu static void __exit crc32_mod_fini(void)
121a7c58ac0SHerbert Xu {
122a7c58ac0SHerbert Xu 	crypto_unregister_shash(&alg);
123a7c58ac0SHerbert Xu }
124a7c58ac0SHerbert Xu 
125c4741b23SEric Biggers subsys_initcall(crc32_mod_init);
126a7c58ac0SHerbert Xu module_exit(crc32_mod_fini);
127a7c58ac0SHerbert Xu 
128a7c58ac0SHerbert Xu MODULE_AUTHOR("Alexander Boyko <alexander_boyko@xyratex.com>");
129a7c58ac0SHerbert Xu MODULE_DESCRIPTION("CRC32 calculations wrapper for lib/crc32");
130a7c58ac0SHerbert Xu MODULE_LICENSE("GPL");
131a7c58ac0SHerbert Xu MODULE_ALIAS_CRYPTO("crc32");
132a7c58ac0SHerbert Xu MODULE_ALIAS_CRYPTO("crc32-generic");
133