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