aboutsummaryrefslogtreecommitdiffstats
path: root/crypto/crc32c.c
diff options
context:
space:
mode:
authorRusty Russell <rusty@rustcorp.com.au>2008-12-29 16:32:35 -0500
committerRusty Russell <rusty@rustcorp.com.au>2008-12-29 16:32:35 -0500
commit33edcf133ba93ecba2e4b6472e97b689895d805c (patch)
tree327d7a20acef64005e7c5ccbfa1265be28aeb6ac /crypto/crc32c.c
parentbe4d638c1597580ed2294d899d9f1a2cd10e462c (diff)
parent3c92ec8ae91ecf59d88c798301833d7cf83f2179 (diff)
Merge branch 'master' of git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux-2.6
Diffstat (limited to 'crypto/crc32c.c')
-rw-r--r--crypto/crc32c.c290
1 files changed, 160 insertions, 130 deletions
diff --git a/crypto/crc32c.c b/crypto/crc32c.c
index a882d9e4e63e..973bc2cfab2e 100644
--- a/crypto/crc32c.c
+++ b/crypto/crc32c.c
@@ -3,8 +3,29 @@
3 * 3 *
4 * CRC32C chksum 4 * CRC32C chksum
5 * 5 *
6 * This module file is a wrapper to invoke the lib/crc32c routines. 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.
7 * 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.
8 * Copyright (c) 2008 Herbert Xu <herbert@gondor.apana.org.au> 29 * Copyright (c) 2008 Herbert Xu <herbert@gondor.apana.org.au>
9 * 30 *
10 * This program is free software; you can redistribute it and/or modify it 31 * This program is free software; you can redistribute it and/or modify it
@@ -18,208 +39,217 @@
18#include <linux/init.h> 39#include <linux/init.h>
19#include <linux/module.h> 40#include <linux/module.h>
20#include <linux/string.h> 41#include <linux/string.h>
21#include <linux/crc32c.h>
22#include <linux/kernel.h> 42#include <linux/kernel.h>
23 43
24#define CHKSUM_BLOCK_SIZE 1 44#define CHKSUM_BLOCK_SIZE 1
25#define CHKSUM_DIGEST_SIZE 4 45#define CHKSUM_DIGEST_SIZE 4
26 46
27struct chksum_ctx { 47struct chksum_ctx {
28 u32 crc;
29 u32 key; 48 u32 key;
30}; 49};
31 50
51struct chksum_desc_ctx {
52 u32 crc;
53};
54
32/* 55/*
33 * Steps through buffer one byte at at time, calculates reflected 56 * This is the CRC-32C table
34 * crc using table. 57 * Generated with:
58 * width = 32 bits
59 * poly = 0x1EDC6F41
60 * reflect input bytes = true
61 * reflect output bytes = true
35 */ 62 */
36 63
37static void chksum_init(struct crypto_tfm *tfm) 64static const u32 crc32c_table[256] = {
38{ 65 0x00000000L, 0xF26B8303L, 0xE13B70F7L, 0x1350F3F4L,
39 struct chksum_ctx *mctx = crypto_tfm_ctx(tfm); 66 0xC79A971FL, 0x35F1141CL, 0x26A1E7E8L, 0xD4CA64EBL,
40 67 0x8AD958CFL, 0x78B2DBCCL, 0x6BE22838L, 0x9989AB3BL,
41 mctx->crc = mctx->key; 68 0x4D43CFD0L, 0xBF284CD3L, 0xAC78BF27L, 0x5E133C24L,
42} 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};
43 130
44/* 131/*
45 * Setting the seed allows arbitrary accumulators and flexible XOR policy 132 * Steps through buffer one byte at at time, calculates reflected
46 * If your algorithm starts with ~0, then XOR with ~0 before you set 133 * crc using table.
47 * the seed.
48 */ 134 */
49static int chksum_setkey(struct crypto_tfm *tfm, const u8 *key,
50 unsigned int keylen)
51{
52 struct chksum_ctx *mctx = crypto_tfm_ctx(tfm);
53 135
54 if (keylen != sizeof(mctx->crc)) { 136static u32 crc32c(u32 crc, const u8 *data, unsigned int length)
55 tfm->crt_flags |= CRYPTO_TFM_RES_BAD_KEY_LEN;
56 return -EINVAL;
57 }
58 mctx->key = le32_to_cpu(*(__le32 *)key);
59 return 0;
60}
61
62static void chksum_update(struct crypto_tfm *tfm, const u8 *data,
63 unsigned int length)
64{ 137{
65 struct chksum_ctx *mctx = crypto_tfm_ctx(tfm); 138 while (length--)
139 crc = crc32c_table[(crc ^ *data++) & 0xFFL] ^ (crc >> 8);
66 140
67 mctx->crc = crc32c(mctx->crc, data, length); 141 return crc;
68} 142}
69 143
70static void chksum_final(struct crypto_tfm *tfm, u8 *out) 144/*
71{ 145 * Steps through buffer one byte at at time, calculates reflected
72 struct chksum_ctx *mctx = crypto_tfm_ctx(tfm); 146 * crc using table.
73 147 */
74 *(__le32 *)out = ~cpu_to_le32(mctx->crc);
75}
76 148
77static int crc32c_cra_init_old(struct crypto_tfm *tfm) 149static int chksum_init(struct shash_desc *desc)
78{ 150{
79 struct chksum_ctx *mctx = crypto_tfm_ctx(tfm); 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;
80 155
81 mctx->key = ~0;
82 return 0; 156 return 0;
83} 157}
84 158
85static struct crypto_alg old_alg = {
86 .cra_name = "crc32c",
87 .cra_flags = CRYPTO_ALG_TYPE_DIGEST,
88 .cra_blocksize = CHKSUM_BLOCK_SIZE,
89 .cra_ctxsize = sizeof(struct chksum_ctx),
90 .cra_module = THIS_MODULE,
91 .cra_list = LIST_HEAD_INIT(old_alg.cra_list),
92 .cra_init = crc32c_cra_init_old,
93 .cra_u = {
94 .digest = {
95 .dia_digestsize= CHKSUM_DIGEST_SIZE,
96 .dia_setkey = chksum_setkey,
97 .dia_init = chksum_init,
98 .dia_update = chksum_update,
99 .dia_final = chksum_final
100 }
101 }
102};
103
104/* 159/*
105 * Setting the seed allows arbitrary accumulators and flexible XOR policy 160 * Setting the seed allows arbitrary accumulators and flexible XOR policy
106 * If your algorithm starts with ~0, then XOR with ~0 before you set 161 * If your algorithm starts with ~0, then XOR with ~0 before you set
107 * the seed. 162 * the seed.
108 */ 163 */
109static int crc32c_setkey(struct crypto_ahash *hash, const u8 *key, 164static int chksum_setkey(struct crypto_shash *tfm, const u8 *key,
110 unsigned int keylen) 165 unsigned int keylen)
111{ 166{
112 u32 *mctx = crypto_ahash_ctx(hash); 167 struct chksum_ctx *mctx = crypto_shash_ctx(tfm);
113 168
114 if (keylen != sizeof(u32)) { 169 if (keylen != sizeof(mctx->key)) {
115 crypto_ahash_set_flags(hash, CRYPTO_TFM_RES_BAD_KEY_LEN); 170 crypto_shash_set_flags(tfm, CRYPTO_TFM_RES_BAD_KEY_LEN);
116 return -EINVAL; 171 return -EINVAL;
117 } 172 }
118 *mctx = le32_to_cpup((__le32 *)key); 173 mctx->key = le32_to_cpu(*(__le32 *)key);
119 return 0; 174 return 0;
120} 175}
121 176
122static int crc32c_init(struct ahash_request *req) 177static int chksum_update(struct shash_desc *desc, const u8 *data,
178 unsigned int length)
123{ 179{
124 u32 *mctx = crypto_ahash_ctx(crypto_ahash_reqtfm(req)); 180 struct chksum_desc_ctx *ctx = shash_desc_ctx(desc);
125 u32 *crcp = ahash_request_ctx(req);
126 181
127 *crcp = *mctx; 182 ctx->crc = crc32c(ctx->crc, data, length);
128 return 0; 183 return 0;
129} 184}
130 185
131static int crc32c_update(struct ahash_request *req) 186static int chksum_final(struct shash_desc *desc, u8 *out)
132{ 187{
133 struct crypto_hash_walk walk; 188 struct chksum_desc_ctx *ctx = shash_desc_ctx(desc);
134 u32 *crcp = ahash_request_ctx(req);
135 u32 crc = *crcp;
136 int nbytes;
137
138 for (nbytes = crypto_hash_walk_first(req, &walk); nbytes;
139 nbytes = crypto_hash_walk_done(&walk, 0))
140 crc = crc32c(crc, walk.data, nbytes);
141 189
142 *crcp = crc; 190 *(__le32 *)out = ~cpu_to_le32p(&ctx->crc);
143 return 0; 191 return 0;
144} 192}
145 193
146static int crc32c_final(struct ahash_request *req) 194static int __chksum_finup(u32 *crcp, const u8 *data, unsigned int len, u8 *out)
147{ 195{
148 u32 *crcp = ahash_request_ctx(req); 196 *(__le32 *)out = ~cpu_to_le32(crc32c(*crcp, data, len));
149
150 *(__le32 *)req->result = ~cpu_to_le32p(crcp);
151 return 0; 197 return 0;
152} 198}
153 199
154static int crc32c_digest(struct ahash_request *req) 200static int chksum_finup(struct shash_desc *desc, const u8 *data,
201 unsigned int len, u8 *out)
155{ 202{
156 struct crypto_hash_walk walk; 203 struct chksum_desc_ctx *ctx = shash_desc_ctx(desc);
157 u32 *mctx = crypto_ahash_ctx(crypto_ahash_reqtfm(req));
158 u32 crc = *mctx;
159 int nbytes;
160 204
161 for (nbytes = crypto_hash_walk_first(req, &walk); nbytes; 205 return __chksum_finup(&ctx->crc, data, len, out);
162 nbytes = crypto_hash_walk_done(&walk, 0))
163 crc = crc32c(crc, walk.data, nbytes);
164
165 *(__le32 *)req->result = ~cpu_to_le32(crc);
166 return 0;
167} 206}
168 207
169static int crc32c_cra_init(struct crypto_tfm *tfm) 208static int chksum_digest(struct shash_desc *desc, const u8 *data,
209 unsigned int length, u8 *out)
170{ 210{
171 u32 *key = crypto_tfm_ctx(tfm); 211 struct chksum_ctx *mctx = crypto_shash_ctx(desc->tfm);
172 212
173 *key = ~0; 213 return __chksum_finup(&mctx->key, data, length, out);
214}
174 215
175 tfm->crt_ahash.reqsize = sizeof(u32); 216static int crc32c_cra_init(struct crypto_tfm *tfm)
217{
218 struct chksum_ctx *mctx = crypto_tfm_ctx(tfm);
176 219
220 mctx->key = ~0;
177 return 0; 221 return 0;
178} 222}
179 223
180static struct crypto_alg alg = { 224static struct shash_alg alg = {
181 .cra_name = "crc32c", 225 .digestsize = CHKSUM_DIGEST_SIZE,
182 .cra_driver_name = "crc32c-generic", 226 .setkey = chksum_setkey,
183 .cra_priority = 100, 227 .init = chksum_init,
184 .cra_flags = CRYPTO_ALG_TYPE_AHASH, 228 .update = chksum_update,
185 .cra_blocksize = CHKSUM_BLOCK_SIZE, 229 .final = chksum_final,
186 .cra_alignmask = 3, 230 .finup = chksum_finup,
187 .cra_ctxsize = sizeof(u32), 231 .digest = chksum_digest,
188 .cra_module = THIS_MODULE, 232 .descsize = sizeof(struct chksum_desc_ctx),
189 .cra_list = LIST_HEAD_INIT(alg.cra_list), 233 .base = {
190 .cra_init = crc32c_cra_init, 234 .cra_name = "crc32c",
191 .cra_type = &crypto_ahash_type, 235 .cra_driver_name = "crc32c-generic",
192 .cra_u = { 236 .cra_priority = 100,
193 .ahash = { 237 .cra_blocksize = CHKSUM_BLOCK_SIZE,
194 .digestsize = CHKSUM_DIGEST_SIZE, 238 .cra_alignmask = 3,
195 .setkey = crc32c_setkey, 239 .cra_ctxsize = sizeof(struct chksum_ctx),
196 .init = crc32c_init, 240 .cra_module = THIS_MODULE,
197 .update = crc32c_update, 241 .cra_init = crc32c_cra_init,
198 .final = crc32c_final,
199 .digest = crc32c_digest,
200 }
201 } 242 }
202}; 243};
203 244
204static int __init crc32c_mod_init(void) 245static int __init crc32c_mod_init(void)
205{ 246{
206 int err; 247 return crypto_register_shash(&alg);
207
208 err = crypto_register_alg(&old_alg);
209 if (err)
210 return err;
211
212 err = crypto_register_alg(&alg);
213 if (err)
214 crypto_unregister_alg(&old_alg);
215
216 return err;
217} 248}
218 249
219static void __exit crc32c_mod_fini(void) 250static void __exit crc32c_mod_fini(void)
220{ 251{
221 crypto_unregister_alg(&alg); 252 crypto_unregister_shash(&alg);
222 crypto_unregister_alg(&old_alg);
223} 253}
224 254
225module_init(crc32c_mod_init); 255module_init(crc32c_mod_init);