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 48 struct chksum_ctx { 49 u32 key; 50 }; 51 52 struct 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 61 static 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 */ 76 static 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 89 static 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 98 static 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 106 static 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 112 static 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 120 static 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 128 static 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 136 static 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_flags = CRYPTO_ALG_OPTIONAL_KEY, 150 .cra_blocksize = CHKSUM_BLOCK_SIZE, 151 .cra_alignmask = 3, 152 .cra_ctxsize = sizeof(struct chksum_ctx), 153 .cra_module = THIS_MODULE, 154 .cra_init = crc32c_cra_init, 155 } 156 }; 157 158 static int __init crc32c_mod_init(void) 159 { 160 return crypto_register_shash(&alg); 161 } 162 163 static void __exit crc32c_mod_fini(void) 164 { 165 crypto_unregister_shash(&alg); 166 } 167 168 module_init(crc32c_mod_init); 169 module_exit(crc32c_mod_fini); 170 171 MODULE_AUTHOR("Clay Haapala <chaapala@cisco.com>"); 172 MODULE_DESCRIPTION("CRC32c (Castagnoli) calculations wrapper for lib/crc32c"); 173 MODULE_LICENSE("GPL"); 174 MODULE_ALIAS_CRYPTO("crc32c"); 175 MODULE_ALIAS_CRYPTO("crc32c-generic"); 176