Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-or-later
0002 /*
0003  * Cryptographic API.
0004  *
0005  * CRC32C chksum
0006  *
0007  *@Article{castagnoli-crc,
0008  * author =       { Guy Castagnoli and Stefan Braeuer and Martin Herrman},
0009  * title =        {{Optimization of Cyclic Redundancy-Check Codes with 24
0010  *                 and 32 Parity Bits}},
0011  * journal =      IEEE Transactions on Communication,
0012  * year =         {1993},
0013  * volume =       {41},
0014  * number =       {6},
0015  * pages =        {},
0016  * month =        {June},
0017  *}
0018  * Used by the iSCSI driver, possibly others, and derived from
0019  * the iscsi-crc.c module of the linux-iscsi driver at
0020  * http://linux-iscsi.sourceforge.net.
0021  *
0022  * Following the example of lib/crc32, this function is intended to be
0023  * flexible and useful for all users.  Modules that currently have their
0024  * own crc32c, but hopefully may be able to use this one are:
0025  *  net/sctp (please add all your doco to here if you change to
0026  *            use this one!)
0027  *  <endoflist>
0028  *
0029  * Copyright (c) 2004 Cisco Systems, Inc.
0030  * Copyright (c) 2008 Herbert Xu <herbert@gondor.apana.org.au>
0031  */
0032 
0033 #include <asm/unaligned.h>
0034 #include <crypto/internal/hash.h>
0035 #include <linux/init.h>
0036 #include <linux/module.h>
0037 #include <linux/string.h>
0038 #include <linux/kernel.h>
0039 #include <linux/crc32.h>
0040 
0041 #define CHKSUM_BLOCK_SIZE   1
0042 #define CHKSUM_DIGEST_SIZE  4
0043 
0044 struct chksum_ctx {
0045     u32 key;
0046 };
0047 
0048 struct chksum_desc_ctx {
0049     u32 crc;
0050 };
0051 
0052 /*
0053  * Steps through buffer one byte at a time, calculates reflected
0054  * crc using table.
0055  */
0056 
0057 static int chksum_init(struct shash_desc *desc)
0058 {
0059     struct chksum_ctx *mctx = crypto_shash_ctx(desc->tfm);
0060     struct chksum_desc_ctx *ctx = shash_desc_ctx(desc);
0061 
0062     ctx->crc = mctx->key;
0063 
0064     return 0;
0065 }
0066 
0067 /*
0068  * Setting the seed allows arbitrary accumulators and flexible XOR policy
0069  * If your algorithm starts with ~0, then XOR with ~0 before you set
0070  * the seed.
0071  */
0072 static int chksum_setkey(struct crypto_shash *tfm, const u8 *key,
0073              unsigned int keylen)
0074 {
0075     struct chksum_ctx *mctx = crypto_shash_ctx(tfm);
0076 
0077     if (keylen != sizeof(mctx->key))
0078         return -EINVAL;
0079     mctx->key = get_unaligned_le32(key);
0080     return 0;
0081 }
0082 
0083 static int chksum_update(struct shash_desc *desc, const u8 *data,
0084              unsigned int length)
0085 {
0086     struct chksum_desc_ctx *ctx = shash_desc_ctx(desc);
0087 
0088     ctx->crc = __crc32c_le(ctx->crc, data, length);
0089     return 0;
0090 }
0091 
0092 static int chksum_final(struct shash_desc *desc, u8 *out)
0093 {
0094     struct chksum_desc_ctx *ctx = shash_desc_ctx(desc);
0095 
0096     put_unaligned_le32(~ctx->crc, out);
0097     return 0;
0098 }
0099 
0100 static int __chksum_finup(u32 *crcp, const u8 *data, unsigned int len, u8 *out)
0101 {
0102     put_unaligned_le32(~__crc32c_le(*crcp, data, len), out);
0103     return 0;
0104 }
0105 
0106 static int chksum_finup(struct shash_desc *desc, const u8 *data,
0107             unsigned int len, u8 *out)
0108 {
0109     struct chksum_desc_ctx *ctx = shash_desc_ctx(desc);
0110 
0111     return __chksum_finup(&ctx->crc, data, len, out);
0112 }
0113 
0114 static int chksum_digest(struct shash_desc *desc, const u8 *data,
0115              unsigned int length, u8 *out)
0116 {
0117     struct chksum_ctx *mctx = crypto_shash_ctx(desc->tfm);
0118 
0119     return __chksum_finup(&mctx->key, data, length, out);
0120 }
0121 
0122 static int crc32c_cra_init(struct crypto_tfm *tfm)
0123 {
0124     struct chksum_ctx *mctx = crypto_tfm_ctx(tfm);
0125 
0126     mctx->key = ~0;
0127     return 0;
0128 }
0129 
0130 static struct shash_alg alg = {
0131     .digestsize     =   CHKSUM_DIGEST_SIZE,
0132     .setkey         =   chksum_setkey,
0133     .init       =   chksum_init,
0134     .update     =   chksum_update,
0135     .final      =   chksum_final,
0136     .finup      =   chksum_finup,
0137     .digest     =   chksum_digest,
0138     .descsize       =   sizeof(struct chksum_desc_ctx),
0139     .base           =   {
0140         .cra_name       =   "crc32c",
0141         .cra_driver_name    =   "crc32c-generic",
0142         .cra_priority       =   100,
0143         .cra_flags      =   CRYPTO_ALG_OPTIONAL_KEY,
0144         .cra_blocksize      =   CHKSUM_BLOCK_SIZE,
0145         .cra_ctxsize        =   sizeof(struct chksum_ctx),
0146         .cra_module     =   THIS_MODULE,
0147         .cra_init       =   crc32c_cra_init,
0148     }
0149 };
0150 
0151 static int __init crc32c_mod_init(void)
0152 {
0153     return crypto_register_shash(&alg);
0154 }
0155 
0156 static void __exit crc32c_mod_fini(void)
0157 {
0158     crypto_unregister_shash(&alg);
0159 }
0160 
0161 subsys_initcall(crc32c_mod_init);
0162 module_exit(crc32c_mod_fini);
0163 
0164 MODULE_AUTHOR("Clay Haapala <chaapala@cisco.com>");
0165 MODULE_DESCRIPTION("CRC32c (Castagnoli) calculations wrapper for lib/crc32c");
0166 MODULE_LICENSE("GPL");
0167 MODULE_ALIAS_CRYPTO("crc32c");
0168 MODULE_ALIAS_CRYPTO("crc32c-generic");