162306a36Sopenharmony_ci/* 262306a36Sopenharmony_ci * Cryptographic API. 362306a36Sopenharmony_ci * 462306a36Sopenharmony_ci * T10 Data Integrity Field CRC16 Crypto Transform 562306a36Sopenharmony_ci * 662306a36Sopenharmony_ci * Copyright (c) 2007 Oracle Corporation. All rights reserved. 762306a36Sopenharmony_ci * Written by Martin K. Petersen <martin.petersen@oracle.com> 862306a36Sopenharmony_ci * Copyright (C) 2013 Intel Corporation 962306a36Sopenharmony_ci * Author: Tim Chen <tim.c.chen@linux.intel.com> 1062306a36Sopenharmony_ci * 1162306a36Sopenharmony_ci * This program is free software; you can redistribute it and/or modify it 1262306a36Sopenharmony_ci * under the terms of the GNU General Public License as published by the Free 1362306a36Sopenharmony_ci * Software Foundation; either version 2 of the License, or (at your option) 1462306a36Sopenharmony_ci * any later version. 1562306a36Sopenharmony_ci * 1662306a36Sopenharmony_ci * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 1762306a36Sopenharmony_ci * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 1862306a36Sopenharmony_ci * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 1962306a36Sopenharmony_ci * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS 2062306a36Sopenharmony_ci * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN 2162306a36Sopenharmony_ci * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 2262306a36Sopenharmony_ci * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 2362306a36Sopenharmony_ci * SOFTWARE. 2462306a36Sopenharmony_ci * 2562306a36Sopenharmony_ci */ 2662306a36Sopenharmony_ci 2762306a36Sopenharmony_ci#include <linux/module.h> 2862306a36Sopenharmony_ci#include <linux/crc-t10dif.h> 2962306a36Sopenharmony_ci#include <crypto/internal/hash.h> 3062306a36Sopenharmony_ci#include <linux/init.h> 3162306a36Sopenharmony_ci#include <linux/kernel.h> 3262306a36Sopenharmony_ci 3362306a36Sopenharmony_cistruct chksum_desc_ctx { 3462306a36Sopenharmony_ci __u16 crc; 3562306a36Sopenharmony_ci}; 3662306a36Sopenharmony_ci 3762306a36Sopenharmony_ci/* 3862306a36Sopenharmony_ci * Steps through buffer one byte at a time, calculates reflected 3962306a36Sopenharmony_ci * crc using table. 4062306a36Sopenharmony_ci */ 4162306a36Sopenharmony_ci 4262306a36Sopenharmony_cistatic int chksum_init(struct shash_desc *desc) 4362306a36Sopenharmony_ci{ 4462306a36Sopenharmony_ci struct chksum_desc_ctx *ctx = shash_desc_ctx(desc); 4562306a36Sopenharmony_ci 4662306a36Sopenharmony_ci ctx->crc = 0; 4762306a36Sopenharmony_ci 4862306a36Sopenharmony_ci return 0; 4962306a36Sopenharmony_ci} 5062306a36Sopenharmony_ci 5162306a36Sopenharmony_cistatic int chksum_update(struct shash_desc *desc, const u8 *data, 5262306a36Sopenharmony_ci unsigned int length) 5362306a36Sopenharmony_ci{ 5462306a36Sopenharmony_ci struct chksum_desc_ctx *ctx = shash_desc_ctx(desc); 5562306a36Sopenharmony_ci 5662306a36Sopenharmony_ci ctx->crc = crc_t10dif_generic(ctx->crc, data, length); 5762306a36Sopenharmony_ci return 0; 5862306a36Sopenharmony_ci} 5962306a36Sopenharmony_ci 6062306a36Sopenharmony_cistatic int chksum_final(struct shash_desc *desc, u8 *out) 6162306a36Sopenharmony_ci{ 6262306a36Sopenharmony_ci struct chksum_desc_ctx *ctx = shash_desc_ctx(desc); 6362306a36Sopenharmony_ci 6462306a36Sopenharmony_ci *(__u16 *)out = ctx->crc; 6562306a36Sopenharmony_ci return 0; 6662306a36Sopenharmony_ci} 6762306a36Sopenharmony_ci 6862306a36Sopenharmony_cistatic int __chksum_finup(__u16 crc, const u8 *data, unsigned int len, u8 *out) 6962306a36Sopenharmony_ci{ 7062306a36Sopenharmony_ci *(__u16 *)out = crc_t10dif_generic(crc, data, len); 7162306a36Sopenharmony_ci return 0; 7262306a36Sopenharmony_ci} 7362306a36Sopenharmony_ci 7462306a36Sopenharmony_cistatic int chksum_finup(struct shash_desc *desc, const u8 *data, 7562306a36Sopenharmony_ci unsigned int len, u8 *out) 7662306a36Sopenharmony_ci{ 7762306a36Sopenharmony_ci struct chksum_desc_ctx *ctx = shash_desc_ctx(desc); 7862306a36Sopenharmony_ci 7962306a36Sopenharmony_ci return __chksum_finup(ctx->crc, data, len, out); 8062306a36Sopenharmony_ci} 8162306a36Sopenharmony_ci 8262306a36Sopenharmony_cistatic int chksum_digest(struct shash_desc *desc, const u8 *data, 8362306a36Sopenharmony_ci unsigned int length, u8 *out) 8462306a36Sopenharmony_ci{ 8562306a36Sopenharmony_ci return __chksum_finup(0, data, length, out); 8662306a36Sopenharmony_ci} 8762306a36Sopenharmony_ci 8862306a36Sopenharmony_cistatic struct shash_alg alg = { 8962306a36Sopenharmony_ci .digestsize = CRC_T10DIF_DIGEST_SIZE, 9062306a36Sopenharmony_ci .init = chksum_init, 9162306a36Sopenharmony_ci .update = chksum_update, 9262306a36Sopenharmony_ci .final = chksum_final, 9362306a36Sopenharmony_ci .finup = chksum_finup, 9462306a36Sopenharmony_ci .digest = chksum_digest, 9562306a36Sopenharmony_ci .descsize = sizeof(struct chksum_desc_ctx), 9662306a36Sopenharmony_ci .base = { 9762306a36Sopenharmony_ci .cra_name = "crct10dif", 9862306a36Sopenharmony_ci .cra_driver_name = "crct10dif-generic", 9962306a36Sopenharmony_ci .cra_priority = 100, 10062306a36Sopenharmony_ci .cra_blocksize = CRC_T10DIF_BLOCK_SIZE, 10162306a36Sopenharmony_ci .cra_module = THIS_MODULE, 10262306a36Sopenharmony_ci } 10362306a36Sopenharmony_ci}; 10462306a36Sopenharmony_ci 10562306a36Sopenharmony_cistatic int __init crct10dif_mod_init(void) 10662306a36Sopenharmony_ci{ 10762306a36Sopenharmony_ci return crypto_register_shash(&alg); 10862306a36Sopenharmony_ci} 10962306a36Sopenharmony_ci 11062306a36Sopenharmony_cistatic void __exit crct10dif_mod_fini(void) 11162306a36Sopenharmony_ci{ 11262306a36Sopenharmony_ci crypto_unregister_shash(&alg); 11362306a36Sopenharmony_ci} 11462306a36Sopenharmony_ci 11562306a36Sopenharmony_cisubsys_initcall(crct10dif_mod_init); 11662306a36Sopenharmony_cimodule_exit(crct10dif_mod_fini); 11762306a36Sopenharmony_ci 11862306a36Sopenharmony_ciMODULE_AUTHOR("Tim Chen <tim.c.chen@linux.intel.com>"); 11962306a36Sopenharmony_ciMODULE_DESCRIPTION("T10 DIF CRC calculation."); 12062306a36Sopenharmony_ciMODULE_LICENSE("GPL"); 12162306a36Sopenharmony_ciMODULE_ALIAS_CRYPTO("crct10dif"); 12262306a36Sopenharmony_ciMODULE_ALIAS_CRYPTO("crct10dif-generic"); 123