linux/crypto/crc32c_generic.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 <asm/unaligned.h>
  39#include <crypto/internal/hash.h>
  40#include <linux/init.h>
  41#include <linux/module.h>
  42#include <linux/string.h>
  43#include <linux/kernel.h>
  44#include <linux/crc32.h>
  45
  46#define CHKSUM_BLOCK_SIZE       1
  47#define CHKSUM_DIGEST_SIZE      4
  48
  49struct chksum_ctx {
  50        u32 key;
  51};
  52
  53struct chksum_desc_ctx {
  54        u32 crc;
  55};
  56
  57/*
  58 * Steps through buffer one byte at at time, calculates reflected
  59 * crc using table.
  60 */
  61
  62static int chksum_init(struct shash_desc *desc)
  63{
  64        struct chksum_ctx *mctx = crypto_shash_ctx(desc->tfm);
  65        struct chksum_desc_ctx *ctx = shash_desc_ctx(desc);
  66
  67        ctx->crc = mctx->key;
  68
  69        return 0;
  70}
  71
  72/*
  73 * Setting the seed allows arbitrary accumulators and flexible XOR policy
  74 * If your algorithm starts with ~0, then XOR with ~0 before you set
  75 * the seed.
  76 */
  77static int chksum_setkey(struct crypto_shash *tfm, const u8 *key,
  78                         unsigned int keylen)
  79{
  80        struct chksum_ctx *mctx = crypto_shash_ctx(tfm);
  81
  82        if (keylen != sizeof(mctx->key)) {
  83                crypto_shash_set_flags(tfm, CRYPTO_TFM_RES_BAD_KEY_LEN);
  84                return -EINVAL;
  85        }
  86        mctx->key = get_unaligned_le32(key);
  87        return 0;
  88}
  89
  90static int chksum_update(struct shash_desc *desc, const u8 *data,
  91                         unsigned int length)
  92{
  93        struct chksum_desc_ctx *ctx = shash_desc_ctx(desc);
  94
  95        ctx->crc = __crc32c_le(ctx->crc, data, length);
  96        return 0;
  97}
  98
  99static int chksum_final(struct shash_desc *desc, u8 *out)
 100{
 101        struct chksum_desc_ctx *ctx = shash_desc_ctx(desc);
 102
 103        put_unaligned_le32(~ctx->crc, out);
 104        return 0;
 105}
 106
 107static int __chksum_finup(u32 *crcp, const u8 *data, unsigned int len, u8 *out)
 108{
 109        put_unaligned_le32(~__crc32c_le(*crcp, data, len), out);
 110        return 0;
 111}
 112
 113static int chksum_finup(struct shash_desc *desc, const u8 *data,
 114                        unsigned int len, u8 *out)
 115{
 116        struct chksum_desc_ctx *ctx = shash_desc_ctx(desc);
 117
 118        return __chksum_finup(&ctx->crc, data, len, out);
 119}
 120
 121static int chksum_digest(struct shash_desc *desc, const u8 *data,
 122                         unsigned int length, u8 *out)
 123{
 124        struct chksum_ctx *mctx = crypto_shash_ctx(desc->tfm);
 125
 126        return __chksum_finup(&mctx->key, data, length, out);
 127}
 128
 129static int crc32c_cra_init(struct crypto_tfm *tfm)
 130{
 131        struct chksum_ctx *mctx = crypto_tfm_ctx(tfm);
 132
 133        mctx->key = ~0;
 134        return 0;
 135}
 136
 137static struct shash_alg alg = {
 138        .digestsize             =       CHKSUM_DIGEST_SIZE,
 139        .setkey                 =       chksum_setkey,
 140        .init           =       chksum_init,
 141        .update         =       chksum_update,
 142        .final          =       chksum_final,
 143        .finup          =       chksum_finup,
 144        .digest         =       chksum_digest,
 145        .descsize               =       sizeof(struct chksum_desc_ctx),
 146        .base                   =       {
 147                .cra_name               =       "crc32c",
 148                .cra_driver_name        =       "crc32c-generic",
 149                .cra_priority           =       100,
 150                .cra_flags              =       CRYPTO_ALG_OPTIONAL_KEY,
 151                .cra_blocksize          =       CHKSUM_BLOCK_SIZE,
 152                .cra_ctxsize            =       sizeof(struct chksum_ctx),
 153                .cra_module             =       THIS_MODULE,
 154                .cra_init               =       crc32c_cra_init,
 155        }
 156};
 157
 158static int __init crc32c_mod_init(void)
 159{
 160        return crypto_register_shash(&alg);
 161}
 162
 163static void __exit crc32c_mod_fini(void)
 164{
 165        crypto_unregister_shash(&alg);
 166}
 167
 168module_init(crc32c_mod_init);
 169module_exit(crc32c_mod_fini);
 170
 171MODULE_AUTHOR("Clay Haapala <chaapala@cisco.com>");
 172MODULE_DESCRIPTION("CRC32c (Castagnoli) calculations wrapper for lib/crc32c");
 173MODULE_LICENSE("GPL");
 174MODULE_ALIAS_CRYPTO("crc32c");
 175MODULE_ALIAS_CRYPTO("crc32c-generic");
 176