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