1 // SPDX-License-Identifier: GPL-2.0-or-later 2 /* 3 * crypto_shash support for CRC-32C 4 * 5 *@Article{castagnoli-crc, 6 * author = { Guy Castagnoli and Stefan Braeuer and Martin Herrman}, 7 * title = {{Optimization of Cyclic Redundancy-Check Codes with 24 8 * and 32 Parity Bits}}, 9 * journal = IEEE Transactions on Communication, 10 * year = {1993}, 11 * volume = {41}, 12 * number = {6}, 13 * pages = {}, 14 * month = {June}, 15 *} 16 * 17 * Copyright (c) 2004 Cisco Systems, Inc. 18 * Copyright (c) 2008 Herbert Xu <herbert@gondor.apana.org.au> 19 */ 20 21 #include <linux/unaligned.h> 22 #include <crypto/internal/hash.h> 23 #include <linux/init.h> 24 #include <linux/module.h> 25 #include <linux/string.h> 26 #include <linux/kernel.h> 27 #include <linux/crc32.h> 28 29 #define CHKSUM_BLOCK_SIZE 1 30 #define CHKSUM_DIGEST_SIZE 4 31 32 struct chksum_ctx { 33 u32 key; 34 }; 35 36 struct chksum_desc_ctx { 37 u32 crc; 38 }; 39 40 static int chksum_init(struct shash_desc *desc) 41 { 42 struct chksum_ctx *mctx = crypto_shash_ctx(desc->tfm); 43 struct chksum_desc_ctx *ctx = shash_desc_ctx(desc); 44 45 ctx->crc = mctx->key; 46 47 return 0; 48 } 49 50 /* 51 * Setting the seed allows arbitrary accumulators and flexible XOR policy 52 * If your algorithm starts with ~0, then XOR with ~0 before you set 53 * the seed. 54 */ 55 static int chksum_setkey(struct crypto_shash *tfm, const u8 *key, 56 unsigned int keylen) 57 { 58 struct chksum_ctx *mctx = crypto_shash_ctx(tfm); 59 60 if (keylen != sizeof(mctx->key)) 61 return -EINVAL; 62 mctx->key = get_unaligned_le32(key); 63 return 0; 64 } 65 66 static int chksum_update(struct shash_desc *desc, const u8 *data, 67 unsigned int length) 68 { 69 struct chksum_desc_ctx *ctx = shash_desc_ctx(desc); 70 71 ctx->crc = crc32c(ctx->crc, data, length); 72 return 0; 73 } 74 75 static int chksum_final(struct shash_desc *desc, u8 *out) 76 { 77 struct chksum_desc_ctx *ctx = shash_desc_ctx(desc); 78 79 put_unaligned_le32(~ctx->crc, out); 80 return 0; 81 } 82 83 static int __chksum_finup(u32 *crcp, const u8 *data, unsigned int len, u8 *out) 84 { 85 put_unaligned_le32(~crc32c(*crcp, data, len), out); 86 return 0; 87 } 88 89 static int chksum_finup(struct shash_desc *desc, const u8 *data, 90 unsigned int len, u8 *out) 91 { 92 struct chksum_desc_ctx *ctx = shash_desc_ctx(desc); 93 94 return __chksum_finup(&ctx->crc, data, len, out); 95 } 96 97 static int chksum_digest(struct shash_desc *desc, const u8 *data, 98 unsigned int length, u8 *out) 99 { 100 struct chksum_ctx *mctx = crypto_shash_ctx(desc->tfm); 101 102 return __chksum_finup(&mctx->key, data, length, out); 103 } 104 105 static int crc32c_cra_init(struct crypto_tfm *tfm) 106 { 107 struct chksum_ctx *mctx = crypto_tfm_ctx(tfm); 108 109 mctx->key = ~0; 110 return 0; 111 } 112 113 static struct shash_alg alg = { 114 .digestsize = CHKSUM_DIGEST_SIZE, 115 .setkey = chksum_setkey, 116 .init = chksum_init, 117 .update = chksum_update, 118 .final = chksum_final, 119 .finup = chksum_finup, 120 .digest = chksum_digest, 121 .descsize = sizeof(struct chksum_desc_ctx), 122 123 .base.cra_name = "crc32c", 124 .base.cra_driver_name = "crc32c-lib", 125 .base.cra_priority = 100, 126 .base.cra_flags = CRYPTO_ALG_OPTIONAL_KEY, 127 .base.cra_blocksize = CHKSUM_BLOCK_SIZE, 128 .base.cra_ctxsize = sizeof(struct chksum_ctx), 129 .base.cra_module = THIS_MODULE, 130 .base.cra_init = crc32c_cra_init, 131 }; 132 133 static int __init crc32c_mod_init(void) 134 { 135 return crypto_register_shash(&alg); 136 } 137 138 static void __exit crc32c_mod_fini(void) 139 { 140 crypto_unregister_shash(&alg); 141 } 142 143 module_init(crc32c_mod_init); 144 module_exit(crc32c_mod_fini); 145 146 MODULE_AUTHOR("Clay Haapala <chaapala@cisco.com>"); 147 MODULE_DESCRIPTION("CRC32c (Castagnoli) calculations wrapper for lib/crc32c"); 148 MODULE_LICENSE("GPL"); 149 MODULE_ALIAS_CRYPTO("crc32c"); 150