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
  44#define CHKSUM_BLOCK_SIZE       1
  45#define CHKSUM_DIGEST_SIZE      4
  46
  47struct chksum_ctx {
  48        u32 key;
  49};
  50
  51struct chksum_desc_ctx {
  52        u32 crc;
  53};
  54
  55/*
  56 * This is the CRC-32C table
  57 * Generated with:
  58 * width = 32 bits
  59 * poly = 0x1EDC6F41
  60 * reflect input bytes = true
  61 * reflect output bytes = true
  62 */
  63
  64static const u32 crc32c_table[256] = {
  65        0x00000000L, 0xF26B8303L, 0xE13B70F7L, 0x1350F3F4L,
  66        0xC79A971FL, 0x35F1141CL, 0x26A1E7E8L, 0xD4CA64EBL,
  67        0x8AD958CFL, 0x78B2DBCCL, 0x6BE22838L, 0x9989AB3BL,
  68        0x4D43CFD0L, 0xBF284CD3L, 0xAC78BF27L, 0x5E133C24L,
  69        0x105EC76FL, 0xE235446CL, 0xF165B798L, 0x030E349BL,
  70        0xD7C45070L, 0x25AFD373L, 0x36FF2087L, 0xC494A384L,
  71        0x9A879FA0L, 0x68EC1CA3L, 0x7BBCEF57L, 0x89D76C54L,
  72        0x5D1D08BFL, 0xAF768BBCL, 0xBC267848L, 0x4E4DFB4BL,
  73        0x20BD8EDEL, 0xD2D60DDDL, 0xC186FE29L, 0x33ED7D2AL,
  74        0xE72719C1L, 0x154C9AC2L, 0x061C6936L, 0xF477EA35L,
  75        0xAA64D611L, 0x580F5512L, 0x4B5FA6E6L, 0xB93425E5L,
  76        0x6DFE410EL, 0x9F95C20DL, 0x8CC531F9L, 0x7EAEB2FAL,
  77        0x30E349B1L, 0xC288CAB2L, 0xD1D83946L, 0x23B3BA45L,
  78        0xF779DEAEL, 0x05125DADL, 0x1642AE59L, 0xE4292D5AL,
  79        0xBA3A117EL, 0x4851927DL, 0x5B016189L, 0xA96AE28AL,
  80        0x7DA08661L, 0x8FCB0562L, 0x9C9BF696L, 0x6EF07595L,
  81        0x417B1DBCL, 0xB3109EBFL, 0xA0406D4BL, 0x522BEE48L,
  82        0x86E18AA3L, 0x748A09A0L, 0x67DAFA54L, 0x95B17957L,
  83        0xCBA24573L, 0x39C9C670L, 0x2A993584L, 0xD8F2B687L,
  84        0x0C38D26CL, 0xFE53516FL, 0xED03A29BL, 0x1F682198L,
  85        0x5125DAD3L, 0xA34E59D0L, 0xB01EAA24L, 0x42752927L,
  86        0x96BF4DCCL, 0x64D4CECFL, 0x77843D3BL, 0x85EFBE38L,
  87        0xDBFC821CL, 0x2997011FL, 0x3AC7F2EBL, 0xC8AC71E8L,
  88        0x1C661503L, 0xEE0D9600L, 0xFD5D65F4L, 0x0F36E6F7L,
  89        0x61C69362L, 0x93AD1061L, 0x80FDE395L, 0x72966096L,
  90        0xA65C047DL, 0x5437877EL, 0x4767748AL, 0xB50CF789L,
  91        0xEB1FCBADL, 0x197448AEL, 0x0A24BB5AL, 0xF84F3859L,
  92        0x2C855CB2L, 0xDEEEDFB1L, 0xCDBE2C45L, 0x3FD5AF46L,
  93        0x7198540DL, 0x83F3D70EL, 0x90A324FAL, 0x62C8A7F9L,
  94        0xB602C312L, 0x44694011L, 0x5739B3E5L, 0xA55230E6L,
  95        0xFB410CC2L, 0x092A8FC1L, 0x1A7A7C35L, 0xE811FF36L,
  96        0x3CDB9BDDL, 0xCEB018DEL, 0xDDE0EB2AL, 0x2F8B6829L,
  97        0x82F63B78L, 0x709DB87BL, 0x63CD4B8FL, 0x91A6C88CL,
  98        0x456CAC67L, 0xB7072F64L, 0xA457DC90L, 0x563C5F93L,
  99        0x082F63B7L, 0xFA44E0B4L, 0xE9141340L, 0x1B7F9043L,
 100        0xCFB5F4A8L, 0x3DDE77ABL, 0x2E8E845FL, 0xDCE5075CL,
 101        0x92A8FC17L, 0x60C37F14L, 0x73938CE0L, 0x81F80FE3L,
 102        0x55326B08L, 0xA759E80BL, 0xB4091BFFL, 0x466298FCL,
 103        0x1871A4D8L, 0xEA1A27DBL, 0xF94AD42FL, 0x0B21572CL,
 104        0xDFEB33C7L, 0x2D80B0C4L, 0x3ED04330L, 0xCCBBC033L,
 105        0xA24BB5A6L, 0x502036A5L, 0x4370C551L, 0xB11B4652L,
 106        0x65D122B9L, 0x97BAA1BAL, 0x84EA524EL, 0x7681D14DL,
 107        0x2892ED69L, 0xDAF96E6AL, 0xC9A99D9EL, 0x3BC21E9DL,
 108        0xEF087A76L, 0x1D63F975L, 0x0E330A81L, 0xFC588982L,
 109        0xB21572C9L, 0x407EF1CAL, 0x532E023EL, 0xA145813DL,
 110        0x758FE5D6L, 0x87E466D5L, 0x94B49521L, 0x66DF1622L,
 111        0x38CC2A06L, 0xCAA7A905L, 0xD9F75AF1L, 0x2B9CD9F2L,
 112        0xFF56BD19L, 0x0D3D3E1AL, 0x1E6DCDEEL, 0xEC064EEDL,
 113        0xC38D26C4L, 0x31E6A5C7L, 0x22B65633L, 0xD0DDD530L,
 114        0x0417B1DBL, 0xF67C32D8L, 0xE52CC12CL, 0x1747422FL,
 115        0x49547E0BL, 0xBB3FFD08L, 0xA86F0EFCL, 0x5A048DFFL,
 116        0x8ECEE914L, 0x7CA56A17L, 0x6FF599E3L, 0x9D9E1AE0L,
 117        0xD3D3E1ABL, 0x21B862A8L, 0x32E8915CL, 0xC083125FL,
 118        0x144976B4L, 0xE622F5B7L, 0xF5720643L, 0x07198540L,
 119        0x590AB964L, 0xAB613A67L, 0xB831C993L, 0x4A5A4A90L,
 120        0x9E902E7BL, 0x6CFBAD78L, 0x7FAB5E8CL, 0x8DC0DD8FL,
 121        0xE330A81AL, 0x115B2B19L, 0x020BD8EDL, 0xF0605BEEL,
 122        0x24AA3F05L, 0xD6C1BC06L, 0xC5914FF2L, 0x37FACCF1L,
 123        0x69E9F0D5L, 0x9B8273D6L, 0x88D28022L, 0x7AB90321L,
 124        0xAE7367CAL, 0x5C18E4C9L, 0x4F48173DL, 0xBD23943EL,
 125        0xF36E6F75L, 0x0105EC76L, 0x12551F82L, 0xE03E9C81L,
 126        0x34F4F86AL, 0xC69F7B69L, 0xD5CF889DL, 0x27A40B9EL,
 127        0x79B737BAL, 0x8BDCB4B9L, 0x988C474DL, 0x6AE7C44EL,
 128        0xBE2DA0A5L, 0x4C4623A6L, 0x5F16D052L, 0xAD7D5351L
 129};
 130
 131/*
 132 * Steps through buffer one byte at at time, calculates reflected
 133 * crc using table.
 134 */
 135
 136static u32 crc32c(u32 crc, const u8 *data, unsigned int length)
 137{
 138        while (length--)
 139                crc = crc32c_table[(crc ^ *data++) & 0xFFL] ^ (crc >> 8);
 140
 141        return crc;
 142}
 143
 144/*
 145 * Steps through buffer one byte at at time, calculates reflected
 146 * crc using table.
 147 */
 148
 149static int chksum_init(struct shash_desc *desc)
 150{
 151        struct chksum_ctx *mctx = crypto_shash_ctx(desc->tfm);
 152        struct chksum_desc_ctx *ctx = shash_desc_ctx(desc);
 153
 154        ctx->crc = mctx->key;
 155
 156        return 0;
 157}
 158
 159/*
 160 * Setting the seed allows arbitrary accumulators and flexible XOR policy
 161 * If your algorithm starts with ~0, then XOR with ~0 before you set
 162 * the seed.
 163 */
 164static int chksum_setkey(struct crypto_shash *tfm, const u8 *key,
 165                         unsigned int keylen)
 166{
 167        struct chksum_ctx *mctx = crypto_shash_ctx(tfm);
 168
 169        if (keylen != sizeof(mctx->key)) {
 170                crypto_shash_set_flags(tfm, CRYPTO_TFM_RES_BAD_KEY_LEN);
 171                return -EINVAL;
 172        }
 173        mctx->key = le32_to_cpu(*(__le32 *)key);
 174        return 0;
 175}
 176
 177static int chksum_update(struct shash_desc *desc, const u8 *data,
 178                         unsigned int length)
 179{
 180        struct chksum_desc_ctx *ctx = shash_desc_ctx(desc);
 181
 182        ctx->crc = crc32c(ctx->crc, data, length);
 183        return 0;
 184}
 185
 186static int chksum_final(struct shash_desc *desc, u8 *out)
 187{
 188        struct chksum_desc_ctx *ctx = shash_desc_ctx(desc);
 189
 190        *(__le32 *)out = ~cpu_to_le32p(&ctx->crc);
 191        return 0;
 192}
 193
 194static int __chksum_finup(u32 *crcp, const u8 *data, unsigned int len, u8 *out)
 195{
 196        *(__le32 *)out = ~cpu_to_le32(crc32c(*crcp, data, len));
 197        return 0;
 198}
 199
 200static int chksum_finup(struct shash_desc *desc, const u8 *data,
 201                        unsigned int len, u8 *out)
 202{
 203        struct chksum_desc_ctx *ctx = shash_desc_ctx(desc);
 204
 205        return __chksum_finup(&ctx->crc, data, len, out);
 206}
 207
 208static int chksum_digest(struct shash_desc *desc, const u8 *data,
 209                         unsigned int length, u8 *out)
 210{
 211        struct chksum_ctx *mctx = crypto_shash_ctx(desc->tfm);
 212
 213        return __chksum_finup(&mctx->key, data, length, out);
 214}
 215
 216static int crc32c_cra_init(struct crypto_tfm *tfm)
 217{
 218        struct chksum_ctx *mctx = crypto_tfm_ctx(tfm);
 219
 220        mctx->key = ~0;
 221        return 0;
 222}
 223
 224static struct shash_alg alg = {
 225        .digestsize             =       CHKSUM_DIGEST_SIZE,
 226        .setkey                 =       chksum_setkey,
 227        .init                   =       chksum_init,
 228        .update                 =       chksum_update,
 229        .final                  =       chksum_final,
 230        .finup                  =       chksum_finup,
 231        .digest                 =       chksum_digest,
 232        .descsize               =       sizeof(struct chksum_desc_ctx),
 233        .base                   =       {
 234                .cra_name               =       "crc32c",
 235                .cra_driver_name        =       "crc32c-generic",
 236                .cra_priority           =       100,
 237                .cra_blocksize          =       CHKSUM_BLOCK_SIZE,
 238                .cra_alignmask          =       3,
 239                .cra_ctxsize            =       sizeof(struct chksum_ctx),
 240                .cra_module             =       THIS_MODULE,
 241                .cra_init               =       crc32c_cra_init,
 242        }
 243};
 244
 245static int __init crc32c_mod_init(void)
 246{
 247        return crypto_register_shash(&alg);
 248}
 249
 250static void __exit crc32c_mod_fini(void)
 251{
 252        crypto_unregister_shash(&alg);
 253}
 254
 255module_init(crc32c_mod_init);
 256module_exit(crc32c_mod_fini);
 257
 258MODULE_AUTHOR("Clay Haapala <chaapala@cisco.com>");
 259MODULE_DESCRIPTION("CRC32c (Castagnoli) calculations wrapper for lib/crc32c");
 260MODULE_LICENSE("GPL");
 261