Blame view

crypto/crc32c.c 7.99 KB
db83aabfe   Richard Hartmann   crypto: crc32 - F...
1
  /*
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2
3
4
5
   * Cryptographic API.
   *
   * CRC32C chksum
   *
69c35efcf   Herbert Xu   libcrc32c: Move i...
6
7
8
9
10
11
12
13
14
15
16
17
18
19
   *@Article{castagnoli-crc,
   * author =       { Guy Castagnoli and Stefan Braeuer and Martin Herrman},
   * title =        {{Optimization of Cyclic Redundancy-Check Codes with 24
   *                 and 32 Parity Bits}},
   * journal =      IEEE Transactions on Communication,
   * year =         {1993},
   * volume =       {41},
   * number =       {6},
   * pages =        {},
   * month =        {June},
   *}
   * Used by the iSCSI driver, possibly others, and derived from the
   * the iscsi-crc.c module of the linux-iscsi driver at
   * http://linux-iscsi.sourceforge.net.
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
20
   *
69c35efcf   Herbert Xu   libcrc32c: Move i...
21
22
23
24
25
26
27
28
   * Following the example of lib/crc32, this function is intended to be
   * flexible and useful for all users.  Modules that currently have their
   * own crc32c, but hopefully may be able to use this one are:
   *  net/sctp (please add all your doco to here if you change to
   *            use this one!)
   *  <endoflist>
   *
   * Copyright (c) 2004 Cisco Systems, Inc.
5773a3e6e   Herbert Xu   crypto: crc32c - ...
29
30
   * Copyright (c) 2008 Herbert Xu <herbert@gondor.apana.org.au>
   *
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
31
32
   * This program is free software; you can redistribute it and/or modify it
   * under the terms of the GNU General Public License as published by the Free
db83aabfe   Richard Hartmann   crypto: crc32 - F...
33
   * Software Foundation; either version 2 of the License, or (at your option)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
34
35
36
   * any later version.
   *
   */
5773a3e6e   Herbert Xu   crypto: crc32c - ...
37
38
  
  #include <crypto/internal/hash.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
39
40
41
  #include <linux/init.h>
  #include <linux/module.h>
  #include <linux/string.h>
25cdbcd9e   Herbert Xu   [CRYPTO] crc32c: ...
42
  #include <linux/kernel.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
43

5773a3e6e   Herbert Xu   crypto: crc32c - ...
44
  #define CHKSUM_BLOCK_SIZE	1
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
45
46
47
  #define CHKSUM_DIGEST_SIZE	4
  
  struct chksum_ctx {
25cdbcd9e   Herbert Xu   [CRYPTO] crc32c: ...
48
  	u32 key;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
49
  };
faccc4bba   Herbert Xu   crypto: crc32c - ...
50
51
52
  struct chksum_desc_ctx {
  	u32 crc;
  };
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
53
  /*
69c35efcf   Herbert Xu   libcrc32c: Move i...
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
   * This is the CRC-32C table
   * Generated with:
   * width = 32 bits
   * poly = 0x1EDC6F41
   * reflect input bytes = true
   * reflect output bytes = true
   */
  
  static const u32 crc32c_table[256] = {
  	0x00000000L, 0xF26B8303L, 0xE13B70F7L, 0x1350F3F4L,
  	0xC79A971FL, 0x35F1141CL, 0x26A1E7E8L, 0xD4CA64EBL,
  	0x8AD958CFL, 0x78B2DBCCL, 0x6BE22838L, 0x9989AB3BL,
  	0x4D43CFD0L, 0xBF284CD3L, 0xAC78BF27L, 0x5E133C24L,
  	0x105EC76FL, 0xE235446CL, 0xF165B798L, 0x030E349BL,
  	0xD7C45070L, 0x25AFD373L, 0x36FF2087L, 0xC494A384L,
  	0x9A879FA0L, 0x68EC1CA3L, 0x7BBCEF57L, 0x89D76C54L,
  	0x5D1D08BFL, 0xAF768BBCL, 0xBC267848L, 0x4E4DFB4BL,
  	0x20BD8EDEL, 0xD2D60DDDL, 0xC186FE29L, 0x33ED7D2AL,
  	0xE72719C1L, 0x154C9AC2L, 0x061C6936L, 0xF477EA35L,
  	0xAA64D611L, 0x580F5512L, 0x4B5FA6E6L, 0xB93425E5L,
  	0x6DFE410EL, 0x9F95C20DL, 0x8CC531F9L, 0x7EAEB2FAL,
  	0x30E349B1L, 0xC288CAB2L, 0xD1D83946L, 0x23B3BA45L,
  	0xF779DEAEL, 0x05125DADL, 0x1642AE59L, 0xE4292D5AL,
  	0xBA3A117EL, 0x4851927DL, 0x5B016189L, 0xA96AE28AL,
  	0x7DA08661L, 0x8FCB0562L, 0x9C9BF696L, 0x6EF07595L,
  	0x417B1DBCL, 0xB3109EBFL, 0xA0406D4BL, 0x522BEE48L,
  	0x86E18AA3L, 0x748A09A0L, 0x67DAFA54L, 0x95B17957L,
  	0xCBA24573L, 0x39C9C670L, 0x2A993584L, 0xD8F2B687L,
  	0x0C38D26CL, 0xFE53516FL, 0xED03A29BL, 0x1F682198L,
  	0x5125DAD3L, 0xA34E59D0L, 0xB01EAA24L, 0x42752927L,
  	0x96BF4DCCL, 0x64D4CECFL, 0x77843D3BL, 0x85EFBE38L,
  	0xDBFC821CL, 0x2997011FL, 0x3AC7F2EBL, 0xC8AC71E8L,
  	0x1C661503L, 0xEE0D9600L, 0xFD5D65F4L, 0x0F36E6F7L,
  	0x61C69362L, 0x93AD1061L, 0x80FDE395L, 0x72966096L,
  	0xA65C047DL, 0x5437877EL, 0x4767748AL, 0xB50CF789L,
  	0xEB1FCBADL, 0x197448AEL, 0x0A24BB5AL, 0xF84F3859L,
  	0x2C855CB2L, 0xDEEEDFB1L, 0xCDBE2C45L, 0x3FD5AF46L,
  	0x7198540DL, 0x83F3D70EL, 0x90A324FAL, 0x62C8A7F9L,
  	0xB602C312L, 0x44694011L, 0x5739B3E5L, 0xA55230E6L,
  	0xFB410CC2L, 0x092A8FC1L, 0x1A7A7C35L, 0xE811FF36L,
  	0x3CDB9BDDL, 0xCEB018DEL, 0xDDE0EB2AL, 0x2F8B6829L,
  	0x82F63B78L, 0x709DB87BL, 0x63CD4B8FL, 0x91A6C88CL,
  	0x456CAC67L, 0xB7072F64L, 0xA457DC90L, 0x563C5F93L,
  	0x082F63B7L, 0xFA44E0B4L, 0xE9141340L, 0x1B7F9043L,
  	0xCFB5F4A8L, 0x3DDE77ABL, 0x2E8E845FL, 0xDCE5075CL,
  	0x92A8FC17L, 0x60C37F14L, 0x73938CE0L, 0x81F80FE3L,
  	0x55326B08L, 0xA759E80BL, 0xB4091BFFL, 0x466298FCL,
  	0x1871A4D8L, 0xEA1A27DBL, 0xF94AD42FL, 0x0B21572CL,
  	0xDFEB33C7L, 0x2D80B0C4L, 0x3ED04330L, 0xCCBBC033L,
  	0xA24BB5A6L, 0x502036A5L, 0x4370C551L, 0xB11B4652L,
  	0x65D122B9L, 0x97BAA1BAL, 0x84EA524EL, 0x7681D14DL,
  	0x2892ED69L, 0xDAF96E6AL, 0xC9A99D9EL, 0x3BC21E9DL,
  	0xEF087A76L, 0x1D63F975L, 0x0E330A81L, 0xFC588982L,
  	0xB21572C9L, 0x407EF1CAL, 0x532E023EL, 0xA145813DL,
  	0x758FE5D6L, 0x87E466D5L, 0x94B49521L, 0x66DF1622L,
  	0x38CC2A06L, 0xCAA7A905L, 0xD9F75AF1L, 0x2B9CD9F2L,
  	0xFF56BD19L, 0x0D3D3E1AL, 0x1E6DCDEEL, 0xEC064EEDL,
  	0xC38D26C4L, 0x31E6A5C7L, 0x22B65633L, 0xD0DDD530L,
  	0x0417B1DBL, 0xF67C32D8L, 0xE52CC12CL, 0x1747422FL,
  	0x49547E0BL, 0xBB3FFD08L, 0xA86F0EFCL, 0x5A048DFFL,
  	0x8ECEE914L, 0x7CA56A17L, 0x6FF599E3L, 0x9D9E1AE0L,
  	0xD3D3E1ABL, 0x21B862A8L, 0x32E8915CL, 0xC083125FL,
  	0x144976B4L, 0xE622F5B7L, 0xF5720643L, 0x07198540L,
  	0x590AB964L, 0xAB613A67L, 0xB831C993L, 0x4A5A4A90L,
  	0x9E902E7BL, 0x6CFBAD78L, 0x7FAB5E8CL, 0x8DC0DD8FL,
  	0xE330A81AL, 0x115B2B19L, 0x020BD8EDL, 0xF0605BEEL,
  	0x24AA3F05L, 0xD6C1BC06L, 0xC5914FF2L, 0x37FACCF1L,
  	0x69E9F0D5L, 0x9B8273D6L, 0x88D28022L, 0x7AB90321L,
  	0xAE7367CAL, 0x5C18E4C9L, 0x4F48173DL, 0xBD23943EL,
  	0xF36E6F75L, 0x0105EC76L, 0x12551F82L, 0xE03E9C81L,
  	0x34F4F86AL, 0xC69F7B69L, 0xD5CF889DL, 0x27A40B9EL,
  	0x79B737BAL, 0x8BDCB4B9L, 0x988C474DL, 0x6AE7C44EL,
  	0xBE2DA0A5L, 0x4C4623A6L, 0x5F16D052L, 0xAD7D5351L
  };
  
  /*
   * Steps through buffer one byte at at time, calculates reflected
   * crc using table.
   */
  
  static u32 crc32c(u32 crc, const u8 *data, unsigned int length)
  {
  	while (length--)
  		crc = crc32c_table[(crc ^ *data++) & 0xFFL] ^ (crc >> 8);
  
  	return crc;
  }
  
  /*
db83aabfe   Richard Hartmann   crypto: crc32 - F...
143
   * Steps through buffer one byte at at time, calculates reflected
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
144
145
   * crc using table.
   */
faccc4bba   Herbert Xu   crypto: crc32c - ...
146
  static int chksum_init(struct shash_desc *desc)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
147
  {
faccc4bba   Herbert Xu   crypto: crc32c - ...
148
149
150
151
  	struct chksum_ctx *mctx = crypto_shash_ctx(desc->tfm);
  	struct chksum_desc_ctx *ctx = shash_desc_ctx(desc);
  
  	ctx->crc = mctx->key;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
152

faccc4bba   Herbert Xu   crypto: crc32c - ...
153
  	return 0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
154
155
156
157
158
159
160
  }
  
  /*
   * Setting the seed allows arbitrary accumulators and flexible XOR policy
   * If your algorithm starts with ~0, then XOR with ~0 before you set
   * the seed.
   */
faccc4bba   Herbert Xu   crypto: crc32c - ...
161
  static int chksum_setkey(struct crypto_shash *tfm, const u8 *key,
560c06ae1   Herbert Xu   [CRYPTO] api: Get...
162
  			 unsigned int keylen)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
163
  {
faccc4bba   Herbert Xu   crypto: crc32c - ...
164
  	struct chksum_ctx *mctx = crypto_shash_ctx(tfm);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
165

faccc4bba   Herbert Xu   crypto: crc32c - ...
166
167
  	if (keylen != sizeof(mctx->key)) {
  		crypto_shash_set_flags(tfm, CRYPTO_TFM_RES_BAD_KEY_LEN);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
168
169
  		return -EINVAL;
  	}
25cdbcd9e   Herbert Xu   [CRYPTO] crc32c: ...
170
  	mctx->key = le32_to_cpu(*(__le32 *)key);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
171
172
  	return 0;
  }
faccc4bba   Herbert Xu   crypto: crc32c - ...
173
174
  static int chksum_update(struct shash_desc *desc, const u8 *data,
  			 unsigned int length)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
175
  {
faccc4bba   Herbert Xu   crypto: crc32c - ...
176
  	struct chksum_desc_ctx *ctx = shash_desc_ctx(desc);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
177

faccc4bba   Herbert Xu   crypto: crc32c - ...
178
  	ctx->crc = crc32c(ctx->crc, data, length);
25cdbcd9e   Herbert Xu   [CRYPTO] crc32c: ...
179
  	return 0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
180
  }
faccc4bba   Herbert Xu   crypto: crc32c - ...
181
  static int chksum_final(struct shash_desc *desc, u8 *out)
5773a3e6e   Herbert Xu   crypto: crc32c - ...
182
  {
faccc4bba   Herbert Xu   crypto: crc32c - ...
183
  	struct chksum_desc_ctx *ctx = shash_desc_ctx(desc);
5773a3e6e   Herbert Xu   crypto: crc32c - ...
184

faccc4bba   Herbert Xu   crypto: crc32c - ...
185
  	*(__le32 *)out = ~cpu_to_le32p(&ctx->crc);
5773a3e6e   Herbert Xu   crypto: crc32c - ...
186
187
  	return 0;
  }
faccc4bba   Herbert Xu   crypto: crc32c - ...
188
  static int __chksum_finup(u32 *crcp, const u8 *data, unsigned int len, u8 *out)
5773a3e6e   Herbert Xu   crypto: crc32c - ...
189
  {
faccc4bba   Herbert Xu   crypto: crc32c - ...
190
  	*(__le32 *)out = ~cpu_to_le32(crc32c(*crcp, data, len));
5773a3e6e   Herbert Xu   crypto: crc32c - ...
191
192
  	return 0;
  }
faccc4bba   Herbert Xu   crypto: crc32c - ...
193
194
  static int chksum_finup(struct shash_desc *desc, const u8 *data,
  			unsigned int len, u8 *out)
5773a3e6e   Herbert Xu   crypto: crc32c - ...
195
  {
faccc4bba   Herbert Xu   crypto: crc32c - ...
196
  	struct chksum_desc_ctx *ctx = shash_desc_ctx(desc);
5773a3e6e   Herbert Xu   crypto: crc32c - ...
197

faccc4bba   Herbert Xu   crypto: crc32c - ...
198
  	return __chksum_finup(&ctx->crc, data, len, out);
5773a3e6e   Herbert Xu   crypto: crc32c - ...
199
  }
faccc4bba   Herbert Xu   crypto: crc32c - ...
200
201
  static int chksum_digest(struct shash_desc *desc, const u8 *data,
  			 unsigned int length, u8 *out)
5773a3e6e   Herbert Xu   crypto: crc32c - ...
202
  {
faccc4bba   Herbert Xu   crypto: crc32c - ...
203
  	struct chksum_ctx *mctx = crypto_shash_ctx(desc->tfm);
5773a3e6e   Herbert Xu   crypto: crc32c - ...
204

faccc4bba   Herbert Xu   crypto: crc32c - ...
205
  	return __chksum_finup(&mctx->key, data, length, out);
5773a3e6e   Herbert Xu   crypto: crc32c - ...
206
207
208
209
  }
  
  static int crc32c_cra_init(struct crypto_tfm *tfm)
  {
faccc4bba   Herbert Xu   crypto: crc32c - ...
210
  	struct chksum_ctx *mctx = crypto_tfm_ctx(tfm);
5773a3e6e   Herbert Xu   crypto: crc32c - ...
211

faccc4bba   Herbert Xu   crypto: crc32c - ...
212
  	mctx->key = ~0;
5773a3e6e   Herbert Xu   crypto: crc32c - ...
213
214
  	return 0;
  }
faccc4bba   Herbert Xu   crypto: crc32c - ...
215
216
217
  static struct shash_alg alg = {
  	.digestsize		=	CHKSUM_DIGEST_SIZE,
  	.setkey			=	chksum_setkey,
fae366401   Mati Vait   crypto: crc32c - ...
218
219
220
221
222
  	.init		=	chksum_init,
  	.update		=	chksum_update,
  	.final		=	chksum_final,
  	.finup		=	chksum_finup,
  	.digest		=	chksum_digest,
faccc4bba   Herbert Xu   crypto: crc32c - ...
223
224
225
226
227
228
229
230
231
232
  	.descsize		=	sizeof(struct chksum_desc_ctx),
  	.base			=	{
  		.cra_name		=	"crc32c",
  		.cra_driver_name	=	"crc32c-generic",
  		.cra_priority		=	100,
  		.cra_blocksize		=	CHKSUM_BLOCK_SIZE,
  		.cra_alignmask		=	3,
  		.cra_ctxsize		=	sizeof(struct chksum_ctx),
  		.cra_module		=	THIS_MODULE,
  		.cra_init		=	crc32c_cra_init,
5773a3e6e   Herbert Xu   crypto: crc32c - ...
233
234
  	}
  };
3af5b90bd   Kamalesh Babulal   [CRYPTO] all: Cle...
235
  static int __init crc32c_mod_init(void)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
236
  {
faccc4bba   Herbert Xu   crypto: crc32c - ...
237
  	return crypto_register_shash(&alg);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
238
  }
3af5b90bd   Kamalesh Babulal   [CRYPTO] all: Cle...
239
  static void __exit crc32c_mod_fini(void)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
240
  {
faccc4bba   Herbert Xu   crypto: crc32c - ...
241
  	crypto_unregister_shash(&alg);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
242
  }
3af5b90bd   Kamalesh Babulal   [CRYPTO] all: Cle...
243
244
  module_init(crc32c_mod_init);
  module_exit(crc32c_mod_fini);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
245
246
247
248
  
  MODULE_AUTHOR("Clay Haapala <chaapala@cisco.com>");
  MODULE_DESCRIPTION("CRC32c (Castagnoli) calculations wrapper for lib/crc32c");
  MODULE_LICENSE("GPL");