1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
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
57
58
59
60
61
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
133
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
146
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
161
162
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