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
  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 a 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                return -EINVAL;
  79        mctx->key = get_unaligned_le32(key);
  80        return 0;
  81}
  82
  83static int chksum_update(struct shash_desc *desc, const u8 *data,
  84                         unsigned int length)
  85{
  86        struct chksum_desc_ctx *ctx = shash_desc_ctx(desc);
  87
  88        ctx->crc = __crc32c_le(ctx->crc, data, length);
  89        return 0;
  90}
  91
  92static int chksum_final(struct shash_desc *desc, u8 *out)
  93{
  94        struct chksum_desc_ctx *ctx = shash_desc_ctx(desc);
  95
  96        put_unaligned_le32(~ctx->crc, out);
  97        return 0;
  98}
  99
 100static int __chksum_finup(u32 *crcp, const u8 *data, unsigned int len, u8 *out)
 101{
 102        put_unaligned_le32(~__crc32c_le(*crcp, data, len), out);
 103        return 0;
 104}
 105
 106static int chksum_finup(struct shash_desc *desc, const u8 *data,
 107                        unsigned int len, u8 *out)
 108{
 109        struct chksum_desc_ctx *ctx = shash_desc_ctx(desc);
 110
 111        return __chksum_finup(&ctx->crc, data, len, out);
 112}
 113
 114static int chksum_digest(struct shash_desc *desc, const u8 *data,
 115                         unsigned int length, u8 *out)
 116{
 117        struct chksum_ctx *mctx = crypto_shash_ctx(desc->tfm);
 118
 119        return __chksum_finup(&mctx->key, data, length, out);
 120}
 121
 122static int crc32c_cra_init(struct crypto_tfm *tfm)
 123{
 124        struct chksum_ctx *mctx = crypto_tfm_ctx(tfm);
 125
 126        mctx->key = ~0;
 127        return 0;
 128}
 129
 130static struct shash_alg alg = {
 131        .digestsize             =       CHKSUM_DIGEST_SIZE,
 132        .setkey                 =       chksum_setkey,
 133        .init           =       chksum_init,
 134        .update         =       chksum_update,
 135        .final          =       chksum_final,
 136        .finup          =       chksum_finup,
 137        .digest         =       chksum_digest,
 138        .descsize               =       sizeof(struct chksum_desc_ctx),
 139        .base                   =       {
 140                .cra_name               =       "crc32c",
 141                .cra_driver_name        =       "crc32c-generic",
 142                .cra_priority           =       100,
 143                .cra_flags              =       CRYPTO_ALG_OPTIONAL_KEY,
 144                .cra_blocksize          =       CHKSUM_BLOCK_SIZE,
 145                .cra_ctxsize            =       sizeof(struct chksum_ctx),
 146                .cra_module             =       THIS_MODULE,
 147                .cra_init               =       crc32c_cra_init,
 148        }
 149};
 150
 151static int __init crc32c_mod_init(void)
 152{
 153        return crypto_register_shash(&alg);
 154}
 155
 156static void __exit crc32c_mod_fini(void)
 157{
 158        crypto_unregister_shash(&alg);
 159}
 160
 161subsys_initcall(crc32c_mod_init);
 162module_exit(crc32c_mod_fini);
 163
 164MODULE_AUTHOR("Clay Haapala <chaapala@cisco.com>");
 165MODULE_DESCRIPTION("CRC32c (Castagnoli) calculations wrapper for lib/crc32c");
 166MODULE_LICENSE("GPL");
 167MODULE_ALIAS_CRYPTO("crc32c");
 168MODULE_ALIAS_CRYPTO("crc32c-generic");
 169