Back to home page

LXR

 
 

    


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