1/* 2 * Cryptographic API. 3 * 4 * CRC32C chksum 5 * 6 *@Article{castagnoli-crc, 7 * author = { Guy Castagnoli and Stefan Braeuer and Martin Herrman}, 8 * title = {{Optimization of Cyclic Redundancy-Check Codes with 24 9 * and 32 Parity Bits}}, 10 * journal = IEEE Transactions on Communication, 11 * year = {1993}, 12 * volume = {41}, 13 * number = {6}, 14 * pages = {}, 15 * month = {June}, 16 *} 17 * Used by the iSCSI driver, possibly others, and derived from the 18 * the iscsi-crc.c module of the linux-iscsi driver at 19 * http://linux-iscsi.sourceforge.net. 20 * 21 * Following the example of lib/crc32, this function is intended to be 22 * flexible and useful for all users. Modules that currently have their 23 * own crc32c, but hopefully may be able to use this one are: 24 * net/sctp (please add all your doco to here if you change to 25 * use this one!) 26 * <endoflist> 27 * 28 * Copyright (c) 2004 Cisco Systems, Inc. 29 * Copyright (c) 2008 Herbert Xu <herbert@gondor.apana.org.au> 30 * 31 * This program is free software; you can redistribute it and/or modify it 32 * under the terms of the GNU General Public License as published by the Free 33 * Software Foundation; either version 2 of the License, or (at your option) 34 * any later version. 35 * 36 */ 37 38#include <crypto/internal/hash.h> 39#include <linux/init.h> 40#include <linux/module.h> 41#include <linux/string.h> 42#include <linux/kernel.h> 43#include <linux/crc32.h> 44 45#define CHKSUM_BLOCK_SIZE 1 46#define CHKSUM_DIGEST_SIZE 4 47 48struct chksum_ctx { 49 u32 key; 50}; 51 52struct chksum_desc_ctx { 53 u32 crc; 54}; 55 56/* 57 * Steps through buffer one byte at at time, calculates reflected 58 * crc using table. 59 */ 60 61static int chksum_init(struct shash_desc *desc) 62{ 63 struct chksum_ctx *mctx = crypto_shash_ctx(desc->tfm); 64 struct chksum_desc_ctx *ctx = shash_desc_ctx(desc); 65 66 ctx->crc = mctx->key; 67 68 return 0; 69} 70 71/* 72 * Setting the seed allows arbitrary accumulators and flexible XOR policy 73 * If your algorithm starts with ~0, then XOR with ~0 before you set 74 * the seed. 75 */ 76static int chksum_setkey(struct crypto_shash *tfm, const u8 *key, 77 unsigned int keylen) 78{ 79 struct chksum_ctx *mctx = crypto_shash_ctx(tfm); 80 81 if (keylen != sizeof(mctx->key)) { 82 crypto_shash_set_flags(tfm, CRYPTO_TFM_RES_BAD_KEY_LEN); 83 return -EINVAL; 84 } 85 mctx->key = le32_to_cpu(*(__le32 *)key); 86 return 0; 87} 88 89static int chksum_update(struct shash_desc *desc, const u8 *data, 90 unsigned int length) 91{ 92 struct chksum_desc_ctx *ctx = shash_desc_ctx(desc); 93 94 ctx->crc = __crc32c_le(ctx->crc, data, length); 95 return 0; 96} 97 98static int chksum_final(struct shash_desc *desc, u8 *out) 99{ 100 struct chksum_desc_ctx *ctx = shash_desc_ctx(desc); 101 102 *(__le32 *)out = ~cpu_to_le32p(&ctx->crc); 103 return 0; 104} 105 106static int __chksum_finup(u32 *crcp, const u8 *data, unsigned int len, u8 *out) 107{ 108 *(__le32 *)out = ~cpu_to_le32(__crc32c_le(*crcp, data, len)); 109 return 0; 110} 111 112static int chksum_finup(struct shash_desc *desc, const u8 *data, 113 unsigned int len, u8 *out) 114{ 115 struct chksum_desc_ctx *ctx = shash_desc_ctx(desc); 116 117 return __chksum_finup(&ctx->crc, data, len, out); 118} 119 120static int chksum_digest(struct shash_desc *desc, const u8 *data, 121 unsigned int length, u8 *out) 122{ 123 struct chksum_ctx *mctx = crypto_shash_ctx(desc->tfm); 124 125 return __chksum_finup(&mctx->key, data, length, out); 126} 127 128static int crc32c_cra_init(struct crypto_tfm *tfm) 129{ 130 struct chksum_ctx *mctx = crypto_tfm_ctx(tfm); 131 132 mctx->key = ~0; 133 return 0; 134} 135 136static struct shash_alg alg = { 137 .digestsize = CHKSUM_DIGEST_SIZE, 138 .setkey = chksum_setkey, 139 .init = chksum_init, 140 .update = chksum_update, 141 .final = chksum_final, 142 .finup = chksum_finup, 143 .digest = chksum_digest, 144 .descsize = sizeof(struct chksum_desc_ctx), 145 .base = { 146 .cra_name = "crc32c", 147 .cra_driver_name = "crc32c-generic", 148 .cra_priority = 100, 149 .cra_blocksize = CHKSUM_BLOCK_SIZE, 150 .cra_alignmask = 3, 151 .cra_ctxsize = sizeof(struct chksum_ctx), 152 .cra_module = THIS_MODULE, 153 .cra_init = crc32c_cra_init, 154 } 155}; 156 157static int __init crc32c_mod_init(void) 158{ 159 return crypto_register_shash(&alg); 160} 161 162static void __exit crc32c_mod_fini(void) 163{ 164 crypto_unregister_shash(&alg); 165} 166 167module_init(crc32c_mod_init); 168module_exit(crc32c_mod_fini); 169 170MODULE_AUTHOR("Clay Haapala <chaapala@cisco.com>"); 171MODULE_DESCRIPTION("CRC32c (Castagnoli) calculations wrapper for lib/crc32c"); 172MODULE_LICENSE("GPL"); 173MODULE_ALIAS_CRYPTO("crc32c"); 174MODULE_ALIAS_CRYPTO("crc32c-generic"); 175