• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
47 struct chksum_ctx {
48 	u32 key;
49 };
50 
51 struct 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 
64 static 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 
crc32c(u32 crc,const u8 * data,unsigned int length)136 static 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 
chksum_init(struct shash_desc * desc)149 static 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  */
chksum_setkey(struct crypto_shash * tfm,const u8 * key,unsigned int keylen)164 static 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 
chksum_update(struct shash_desc * desc,const u8 * data,unsigned int length)177 static 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 
chksum_final(struct shash_desc * desc,u8 * out)186 static 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 
__chksum_finup(u32 * crcp,const u8 * data,unsigned int len,u8 * out)194 static 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 
chksum_finup(struct shash_desc * desc,const u8 * data,unsigned int len,u8 * out)200 static 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 
chksum_digest(struct shash_desc * desc,const u8 * data,unsigned int length,u8 * out)208 static 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 
crc32c_cra_init(struct crypto_tfm * tfm)216 static 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 
224 static 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 
crc32c_mod_init(void)245 static int __init crc32c_mod_init(void)
246 {
247 	return crypto_register_shash(&alg);
248 }
249 
crc32c_mod_fini(void)250 static void __exit crc32c_mod_fini(void)
251 {
252 	crypto_unregister_shash(&alg);
253 }
254 
255 module_init(crc32c_mod_init);
256 module_exit(crc32c_mod_fini);
257 
258 MODULE_AUTHOR("Clay Haapala <chaapala@cisco.com>");
259 MODULE_DESCRIPTION("CRC32c (Castagnoli) calculations wrapper for lib/crc32c");
260 MODULE_LICENSE("GPL");
261