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