Whamcloud - gitweb
0c8fc25a07431885c6ae0e3faf04d8ed00a38274
[fs/lustre-release.git] / libcfs / libcfs / linux / linux-crypto-crc32.c
1 /* GPL HEADER START
2  *
3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4  *
5  * This program is free software; you can redistribute it and/or modify
6  * it under the terms of the GNU General Public License version 2 only,
7  * as published by the Free Software Foundation.
8  *
9  * This program is distributed in the hope that it will be useful, but
10  * WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12  * General Public License version 2 for more details (a copy is included
13  * in the LICENSE file that accompanied this code).
14  *
15  * You should have received a copy of the GNU General Public License
16  * version 2 along with this program; If not, see http://www.gnu.org/licenses
17  *
18  * Please  visit http://www.xyratex.com/contact if you need additional
19  * information or have any questions.
20  *
21  * GPL HEADER END
22  */
23
24 /*
25  * Copyright 2012 Xyratex Technology Limited
26  */
27
28 /*
29  * This is crypto api shash wrappers to crc32_le.
30  */
31
32 #include <linux/crc32.h>
33 #ifdef HAVE_STRUCT_SHASH_ALG
34 #include <crypto/internal/hash.h>
35 #else
36 #include <linux/crypto.h>
37 #endif
38
39 #define CHKSUM_BLOCK_SIZE       1
40 #define CHKSUM_DIGEST_SIZE      4
41
42 static u32 __crc32_le(u32 crc, unsigned char const *p, size_t len)
43 {
44         return crc32_le(crc, p, len);
45 }
46
47 /** No default init with ~0 */
48 static int crc32_cra_init(struct crypto_tfm *tfm)
49 {
50         u32 *key = crypto_tfm_ctx(tfm);
51
52         *key = 0;
53
54         return 0;
55 }
56
57
58 #ifdef HAVE_STRUCT_SHASH_ALG
59 /*
60  * Setting the seed allows arbitrary accumulators and flexible XOR policy
61  * If your algorithm starts with ~0, then XOR with ~0 before you set
62  * the seed.
63  */
64 static int crc32_setkey(struct crypto_shash *hash, const u8 *key,
65                         unsigned int keylen)
66 {
67         u32 *mctx = crypto_shash_ctx(hash);
68
69         if (keylen != sizeof(u32)) {
70                 crypto_shash_set_flags(hash, CRYPTO_TFM_RES_BAD_KEY_LEN);
71                 return -EINVAL;
72         }
73         *mctx = le32_to_cpup((__le32 *)key);
74         return 0;
75 }
76
77 static int crc32_init(struct shash_desc *desc)
78 {
79         u32 *mctx = crypto_shash_ctx(desc->tfm);
80         u32 *crcp = shash_desc_ctx(desc);
81
82         *crcp = *mctx;
83
84         return 0;
85 }
86
87 static int crc32_update(struct shash_desc *desc, const u8 *data,
88                         unsigned int len)
89 {
90         u32 *crcp = shash_desc_ctx(desc);
91
92         *crcp = __crc32_le(*crcp, data, len);
93         return 0;
94 }
95 /* No final XOR 0xFFFFFFFF, like crc32_le */
96 static int __crc32_finup(u32 *crcp, const u8 *data, unsigned int len,
97                          u8 *out)
98 {
99         *(__le32 *)out = cpu_to_le32(__crc32_le(*crcp, data, len));
100         return 0;
101 }
102
103 static int crc32_finup(struct shash_desc *desc, const u8 *data,
104                        unsigned int len, u8 *out)
105 {
106         return __crc32_finup(shash_desc_ctx(desc), data, len, out);
107 }
108
109 static int crc32_final(struct shash_desc *desc, u8 *out)
110 {
111         u32 *crcp = shash_desc_ctx(desc);
112
113         *(__le32 *)out = cpu_to_le32p(crcp);
114         return 0;
115 }
116
117 static int crc32_digest(struct shash_desc *desc, const u8 *data,
118                         unsigned int len, u8 *out)
119 {
120         return __crc32_finup(crypto_shash_ctx(desc->tfm), data, len,
121                              out);
122 }
123 static struct shash_alg alg = {
124         .setkey         = crc32_setkey,
125         .init           = crc32_init,
126         .update         = crc32_update,
127         .final          = crc32_final,
128         .finup          = crc32_finup,
129         .digest         = crc32_digest,
130         .descsize       = sizeof(u32),
131         .digestsize     = CHKSUM_DIGEST_SIZE,
132         .base           = {
133                 .cra_name               = "crc32",
134                 .cra_driver_name        = "crc32-table",
135                 .cra_priority           = 100,
136                 .cra_blocksize          = CHKSUM_BLOCK_SIZE,
137                 .cra_ctxsize            = sizeof(u32),
138                 .cra_module             = THIS_MODULE,
139                 .cra_init               = crc32_cra_init,
140         }
141 };
142 #else   /* HAVE_STRUCT_SHASH_ALG */
143 #ifdef HAVE_DIGEST_SETKEY_FLAGS
144 static int crc32_digest_setkey(struct crypto_tfm *tfm, const u8 *key,
145                                unsigned int keylen, unsigned int *flags)
146 #else
147 static int crc32_digest_setkey(struct crypto_tfm *tfm, const u8 *key,
148                                unsigned int keylen)
149 #endif
150 {
151         u32 *mctx = crypto_tfm_ctx(tfm);
152
153         if (keylen != sizeof(u32)) {
154                 tfm->crt_flags |= CRYPTO_TFM_RES_BAD_KEY_LEN;
155                 return -EINVAL;
156         }
157         *mctx = le32_to_cpup((__le32 *)key);
158         return 0;
159 }
160
161 static void crc32_digest_init(struct crypto_tfm *tfm)
162 {
163         u32 *mctx = crypto_tfm_ctx(tfm);
164
165         *mctx = 0;
166
167 }
168 static void crc32_digest_update(struct crypto_tfm *tfm, const u8 *data,
169                                 unsigned int len)
170 {
171         u32 *crcp = crypto_tfm_ctx(tfm);
172
173         *crcp = __crc32_le(*crcp, data, len);
174 }
175
176 static void crc32_digest_final(struct crypto_tfm *tfm, u8 *out)
177 {
178         u32 *crcp = crypto_tfm_ctx(tfm);
179
180         *(__le32 *)out = cpu_to_le32p(crcp);
181 }
182
183 static struct crypto_alg alg = {
184         .cra_name               = "crc32",
185         .cra_flags              = CRYPTO_ALG_TYPE_DIGEST,
186         .cra_driver_name        = "crc32-table",
187         .cra_priority           = 100,
188         .cra_blocksize          = CHKSUM_BLOCK_SIZE,
189         .cra_ctxsize            = sizeof(u32),
190         .cra_module             = THIS_MODULE,
191         .cra_init               = crc32_cra_init,
192         .cra_list               = LIST_HEAD_INIT(alg.cra_list),
193         .cra_u                  = {
194                 .digest         = {
195                         .dia_digestsize = CHKSUM_DIGEST_SIZE,
196                         .dia_setkey     = crc32_digest_setkey,
197                         .dia_init       = crc32_digest_init,
198                         .dia_update     = crc32_digest_update,
199                         .dia_final      = crc32_digest_final
200                 }
201         }
202 };
203 #endif  /* HAVE_STRUCT_SHASH_ALG */
204
205 int cfs_crypto_crc32_register(void)
206 {
207 #ifdef HAVE_STRUCT_SHASH_ALG
208         return crypto_register_shash(&alg);
209 #else
210         return crypto_register_alg(&alg);
211 #endif
212 }
213 EXPORT_SYMBOL(cfs_crypto_crc32_register);
214
215 void cfs_crypto_crc32_unregister(void)
216 {
217 #ifdef HAVE_STRUCT_SHASH_ALG
218         crypto_unregister_shash(&alg);
219 #else
220         crypto_unregister_alg(&alg);
221 #endif
222 }
223 EXPORT_SYMBOL(cfs_crypto_crc32_unregister);