xref: /linux/crypto/crct10dif_generic.c (revision 71952d78)
126052f9bSHerbert Xu /*
226052f9bSHerbert Xu  * Cryptographic API.
326052f9bSHerbert Xu  *
426052f9bSHerbert Xu  * T10 Data Integrity Field CRC16 Crypto Transform
526052f9bSHerbert Xu  *
626052f9bSHerbert Xu  * Copyright (c) 2007 Oracle Corporation.  All rights reserved.
726052f9bSHerbert Xu  * Written by Martin K. Petersen <martin.petersen@oracle.com>
826052f9bSHerbert Xu  * Copyright (C) 2013 Intel Corporation
926052f9bSHerbert Xu  * Author: Tim Chen <tim.c.chen@linux.intel.com>
1026052f9bSHerbert Xu  *
1126052f9bSHerbert Xu  * This program is free software; you can redistribute it and/or modify it
1226052f9bSHerbert Xu  * under the terms of the GNU General Public License as published by the Free
1326052f9bSHerbert Xu  * Software Foundation; either version 2 of the License, or (at your option)
1426052f9bSHerbert Xu  * any later version.
1526052f9bSHerbert Xu  *
1626052f9bSHerbert Xu  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
1726052f9bSHerbert Xu  * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
1826052f9bSHerbert Xu  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
1926052f9bSHerbert Xu  * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
2026052f9bSHerbert Xu  * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
2126052f9bSHerbert Xu  * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
2226052f9bSHerbert Xu  * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
2326052f9bSHerbert Xu  * SOFTWARE.
2426052f9bSHerbert Xu  *
2526052f9bSHerbert Xu  */
2626052f9bSHerbert Xu 
2726052f9bSHerbert Xu #include <linux/module.h>
2826052f9bSHerbert Xu #include <linux/crc-t10dif.h>
2926052f9bSHerbert Xu #include <crypto/internal/hash.h>
3026052f9bSHerbert Xu #include <linux/init.h>
3126052f9bSHerbert Xu #include <linux/kernel.h>
3226052f9bSHerbert Xu 
3326052f9bSHerbert Xu struct chksum_desc_ctx {
3426052f9bSHerbert Xu 	__u16 crc;
3526052f9bSHerbert Xu };
3626052f9bSHerbert Xu 
3726052f9bSHerbert Xu /*
38*71952d78SRandy Dunlap  * Steps through buffer one byte at a time, calculates reflected
3926052f9bSHerbert Xu  * crc using table.
4026052f9bSHerbert Xu  */
4126052f9bSHerbert Xu 
chksum_init(struct shash_desc * desc)4226052f9bSHerbert Xu static int chksum_init(struct shash_desc *desc)
4326052f9bSHerbert Xu {
4426052f9bSHerbert Xu 	struct chksum_desc_ctx *ctx = shash_desc_ctx(desc);
4526052f9bSHerbert Xu 
4626052f9bSHerbert Xu 	ctx->crc = 0;
4726052f9bSHerbert Xu 
4826052f9bSHerbert Xu 	return 0;
4926052f9bSHerbert Xu }
5026052f9bSHerbert Xu 
chksum_update(struct shash_desc * desc,const u8 * data,unsigned int length)5126052f9bSHerbert Xu static int chksum_update(struct shash_desc *desc, const u8 *data,
5226052f9bSHerbert Xu 			 unsigned int length)
5326052f9bSHerbert Xu {
5426052f9bSHerbert Xu 	struct chksum_desc_ctx *ctx = shash_desc_ctx(desc);
5526052f9bSHerbert Xu 
5626052f9bSHerbert Xu 	ctx->crc = crc_t10dif_generic(ctx->crc, data, length);
5726052f9bSHerbert Xu 	return 0;
5826052f9bSHerbert Xu }
5926052f9bSHerbert Xu 
chksum_final(struct shash_desc * desc,u8 * out)6026052f9bSHerbert Xu static int chksum_final(struct shash_desc *desc, u8 *out)
6126052f9bSHerbert Xu {
6226052f9bSHerbert Xu 	struct chksum_desc_ctx *ctx = shash_desc_ctx(desc);
6326052f9bSHerbert Xu 
6426052f9bSHerbert Xu 	*(__u16 *)out = ctx->crc;
6526052f9bSHerbert Xu 	return 0;
6626052f9bSHerbert Xu }
6726052f9bSHerbert Xu 
__chksum_finup(__u16 crc,const u8 * data,unsigned int len,u8 * out)68307508d1SEric Biggers static int __chksum_finup(__u16 crc, const u8 *data, unsigned int len, u8 *out)
6926052f9bSHerbert Xu {
70307508d1SEric Biggers 	*(__u16 *)out = crc_t10dif_generic(crc, data, len);
7126052f9bSHerbert Xu 	return 0;
7226052f9bSHerbert Xu }
7326052f9bSHerbert Xu 
chksum_finup(struct shash_desc * desc,const u8 * data,unsigned int len,u8 * out)7426052f9bSHerbert Xu static int chksum_finup(struct shash_desc *desc, const u8 *data,
7526052f9bSHerbert Xu 			unsigned int len, u8 *out)
7626052f9bSHerbert Xu {
7726052f9bSHerbert Xu 	struct chksum_desc_ctx *ctx = shash_desc_ctx(desc);
7826052f9bSHerbert Xu 
79307508d1SEric Biggers 	return __chksum_finup(ctx->crc, data, len, out);
8026052f9bSHerbert Xu }
8126052f9bSHerbert Xu 
chksum_digest(struct shash_desc * desc,const u8 * data,unsigned int length,u8 * out)8226052f9bSHerbert Xu static int chksum_digest(struct shash_desc *desc, const u8 *data,
8326052f9bSHerbert Xu 			 unsigned int length, u8 *out)
8426052f9bSHerbert Xu {
85307508d1SEric Biggers 	return __chksum_finup(0, data, length, out);
8626052f9bSHerbert Xu }
8726052f9bSHerbert Xu 
8826052f9bSHerbert Xu static struct shash_alg alg = {
8926052f9bSHerbert Xu 	.digestsize		=	CRC_T10DIF_DIGEST_SIZE,
9026052f9bSHerbert Xu 	.init		=	chksum_init,
9126052f9bSHerbert Xu 	.update		=	chksum_update,
9226052f9bSHerbert Xu 	.final		=	chksum_final,
9326052f9bSHerbert Xu 	.finup		=	chksum_finup,
9426052f9bSHerbert Xu 	.digest		=	chksum_digest,
9526052f9bSHerbert Xu 	.descsize		=	sizeof(struct chksum_desc_ctx),
9626052f9bSHerbert Xu 	.base			=	{
9726052f9bSHerbert Xu 		.cra_name		=	"crct10dif",
9826052f9bSHerbert Xu 		.cra_driver_name	=	"crct10dif-generic",
9926052f9bSHerbert Xu 		.cra_priority		=	100,
10026052f9bSHerbert Xu 		.cra_blocksize		=	CRC_T10DIF_BLOCK_SIZE,
10126052f9bSHerbert Xu 		.cra_module		=	THIS_MODULE,
10226052f9bSHerbert Xu 	}
10326052f9bSHerbert Xu };
10426052f9bSHerbert Xu 
crct10dif_mod_init(void)10526052f9bSHerbert Xu static int __init crct10dif_mod_init(void)
10626052f9bSHerbert Xu {
10736e09e1fSMasahiro Yamada 	return crypto_register_shash(&alg);
10826052f9bSHerbert Xu }
10926052f9bSHerbert Xu 
crct10dif_mod_fini(void)11026052f9bSHerbert Xu static void __exit crct10dif_mod_fini(void)
11126052f9bSHerbert Xu {
11226052f9bSHerbert Xu 	crypto_unregister_shash(&alg);
11326052f9bSHerbert Xu }
11426052f9bSHerbert Xu 
115c4741b23SEric Biggers subsys_initcall(crct10dif_mod_init);
11626052f9bSHerbert Xu module_exit(crct10dif_mod_fini);
11726052f9bSHerbert Xu 
11826052f9bSHerbert Xu MODULE_AUTHOR("Tim Chen <tim.c.chen@linux.intel.com>");
11926052f9bSHerbert Xu MODULE_DESCRIPTION("T10 DIF CRC calculation.");
12026052f9bSHerbert Xu MODULE_LICENSE("GPL");
1215d26a105SKees Cook MODULE_ALIAS_CRYPTO("crct10dif");
1223e14dcf7SMathias Krause MODULE_ALIAS_CRYPTO("crct10dif-generic");
123