aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--crypto/crc32c.c185
1 files changed, 53 insertions, 132 deletions
diff --git a/crypto/crc32c.c b/crypto/crc32c.c
index a882d9e4e63e..b21b93f2bb90 100644
--- a/crypto/crc32c.c
+++ b/crypto/crc32c.c
@@ -25,20 +25,26 @@
25#define CHKSUM_DIGEST_SIZE 4 25#define CHKSUM_DIGEST_SIZE 4
26 26
27struct chksum_ctx { 27struct chksum_ctx {
28 u32 crc;
29 u32 key; 28 u32 key;
30}; 29};
31 30
31struct chksum_desc_ctx {
32 u32 crc;
33};
34
32/* 35/*
33 * Steps through buffer one byte at at time, calculates reflected 36 * Steps through buffer one byte at at time, calculates reflected
34 * crc using table. 37 * crc using table.
35 */ 38 */
36 39
37static void chksum_init(struct crypto_tfm *tfm) 40static int chksum_init(struct shash_desc *desc)
38{ 41{
39 struct chksum_ctx *mctx = crypto_tfm_ctx(tfm); 42 struct chksum_ctx *mctx = crypto_shash_ctx(desc->tfm);
43 struct chksum_desc_ctx *ctx = shash_desc_ctx(desc);
44
45 ctx->crc = mctx->key;
40 46
41 mctx->crc = mctx->key; 47 return 0;
42} 48}
43 49
44/* 50/*
@@ -46,180 +52,95 @@ static void chksum_init(struct crypto_tfm *tfm)
46 * If your algorithm starts with ~0, then XOR with ~0 before you set 52 * If your algorithm starts with ~0, then XOR with ~0 before you set
47 * the seed. 53 * the seed.
48 */ 54 */
49static int chksum_setkey(struct crypto_tfm *tfm, const u8 *key, 55static int chksum_setkey(struct crypto_shash *tfm, const u8 *key,
50 unsigned int keylen) 56 unsigned int keylen)
51{ 57{
52 struct chksum_ctx *mctx = crypto_tfm_ctx(tfm); 58 struct chksum_ctx *mctx = crypto_shash_ctx(tfm);
53 59
54 if (keylen != sizeof(mctx->crc)) { 60 if (keylen != sizeof(mctx->key)) {
55 tfm->crt_flags |= CRYPTO_TFM_RES_BAD_KEY_LEN; 61 crypto_shash_set_flags(tfm, CRYPTO_TFM_RES_BAD_KEY_LEN);
56 return -EINVAL; 62 return -EINVAL;
57 } 63 }
58 mctx->key = le32_to_cpu(*(__le32 *)key); 64 mctx->key = le32_to_cpu(*(__le32 *)key);
59 return 0; 65 return 0;
60} 66}
61 67
62static void chksum_update(struct crypto_tfm *tfm, const u8 *data, 68static int chksum_update(struct shash_desc *desc, const u8 *data,
63 unsigned int length) 69 unsigned int length)
64{ 70{
65 struct chksum_ctx *mctx = crypto_tfm_ctx(tfm); 71 struct chksum_desc_ctx *ctx = shash_desc_ctx(desc);
66 72
67 mctx->crc = crc32c(mctx->crc, data, length); 73 ctx->crc = crc32c(ctx->crc, data, length);
68}
69
70static void chksum_final(struct crypto_tfm *tfm, u8 *out)
71{
72 struct chksum_ctx *mctx = crypto_tfm_ctx(tfm);
73
74 *(__le32 *)out = ~cpu_to_le32(mctx->crc);
75}
76
77static int crc32c_cra_init_old(struct crypto_tfm *tfm)
78{
79 struct chksum_ctx *mctx = crypto_tfm_ctx(tfm);
80
81 mctx->key = ~0;
82 return 0; 74 return 0;
83} 75}
84 76
85static struct crypto_alg old_alg = { 77static int chksum_final(struct shash_desc *desc, u8 *out)
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/*
105 * Setting the seed allows arbitrary accumulators and flexible XOR policy
106 * If your algorithm starts with ~0, then XOR with ~0 before you set
107 * the seed.
108 */
109static int crc32c_setkey(struct crypto_ahash *hash, const u8 *key,
110 unsigned int keylen)
111{ 78{
112 u32 *mctx = crypto_ahash_ctx(hash); 79 struct chksum_desc_ctx *ctx = shash_desc_ctx(desc);
113 80
114 if (keylen != sizeof(u32)) { 81 *(__le32 *)out = ~cpu_to_le32p(&ctx->crc);
115 crypto_ahash_set_flags(hash, CRYPTO_TFM_RES_BAD_KEY_LEN);
116 return -EINVAL;
117 }
118 *mctx = le32_to_cpup((__le32 *)key);
119 return 0; 82 return 0;
120} 83}
121 84
122static int crc32c_init(struct ahash_request *req) 85static int __chksum_finup(u32 *crcp, const u8 *data, unsigned int len, u8 *out)
123{ 86{
124 u32 *mctx = crypto_ahash_ctx(crypto_ahash_reqtfm(req)); 87 *(__le32 *)out = ~cpu_to_le32(crc32c(*crcp, data, len));
125 u32 *crcp = ahash_request_ctx(req);
126
127 *crcp = *mctx;
128 return 0; 88 return 0;
129} 89}
130 90
131static int crc32c_update(struct ahash_request *req) 91static int chksum_finup(struct shash_desc *desc, const u8 *data,
92 unsigned int len, u8 *out)
132{ 93{
133 struct crypto_hash_walk walk; 94 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 95
142 *crcp = crc; 96 return __chksum_finup(&ctx->crc, data, len, out);
143 return 0;
144} 97}
145 98
146static int crc32c_final(struct ahash_request *req) 99static int chksum_digest(struct shash_desc *desc, const u8 *data,
100 unsigned int length, u8 *out)
147{ 101{
148 u32 *crcp = ahash_request_ctx(req); 102 struct chksum_ctx *mctx = crypto_shash_ctx(desc->tfm);
149
150 *(__le32 *)req->result = ~cpu_to_le32p(crcp);
151 return 0;
152}
153 103
154static int crc32c_digest(struct ahash_request *req) 104 return __chksum_finup(&mctx->key, data, length, out);
155{
156 struct crypto_hash_walk walk;
157 u32 *mctx = crypto_ahash_ctx(crypto_ahash_reqtfm(req));
158 u32 crc = *mctx;
159 int nbytes;
160
161 for (nbytes = crypto_hash_walk_first(req, &walk); nbytes;
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} 105}
168 106
169static int crc32c_cra_init(struct crypto_tfm *tfm) 107static int crc32c_cra_init(struct crypto_tfm *tfm)
170{ 108{
171 u32 *key = crypto_tfm_ctx(tfm); 109 struct chksum_ctx *mctx = crypto_tfm_ctx(tfm);
172
173 *key = ~0;
174
175 tfm->crt_ahash.reqsize = sizeof(u32);
176 110
111 mctx->key = ~0;
177 return 0; 112 return 0;
178} 113}
179 114
180static struct crypto_alg alg = { 115static struct shash_alg alg = {
181 .cra_name = "crc32c", 116 .digestsize = CHKSUM_DIGEST_SIZE,
182 .cra_driver_name = "crc32c-generic", 117 .setkey = chksum_setkey,
183 .cra_priority = 100, 118 .init = chksum_init,
184 .cra_flags = CRYPTO_ALG_TYPE_AHASH, 119 .update = chksum_update,
185 .cra_blocksize = CHKSUM_BLOCK_SIZE, 120 .final = chksum_final,
186 .cra_alignmask = 3, 121 .finup = chksum_finup,
187 .cra_ctxsize = sizeof(u32), 122 .digest = chksum_digest,
188 .cra_module = THIS_MODULE, 123 .descsize = sizeof(struct chksum_desc_ctx),
189 .cra_list = LIST_HEAD_INIT(alg.cra_list), 124 .base = {
190 .cra_init = crc32c_cra_init, 125 .cra_name = "crc32c",
191 .cra_type = &crypto_ahash_type, 126 .cra_driver_name = "crc32c-generic",
192 .cra_u = { 127 .cra_priority = 100,
193 .ahash = { 128 .cra_blocksize = CHKSUM_BLOCK_SIZE,
194 .digestsize = CHKSUM_DIGEST_SIZE, 129 .cra_alignmask = 3,
195 .setkey = crc32c_setkey, 130 .cra_ctxsize = sizeof(struct chksum_ctx),
196 .init = crc32c_init, 131 .cra_module = THIS_MODULE,
197 .update = crc32c_update, 132 .cra_init = crc32c_cra_init,
198 .final = crc32c_final,
199 .digest = crc32c_digest,
200 }
201 } 133 }
202}; 134};
203 135
204static int __init crc32c_mod_init(void) 136static int __init crc32c_mod_init(void)
205{ 137{
206 int err; 138 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} 139}
218 140
219static void __exit crc32c_mod_fini(void) 141static void __exit crc32c_mod_fini(void)
220{ 142{
221 crypto_unregister_alg(&alg); 143 crypto_unregister_shash(&alg);
222 crypto_unregister_alg(&old_alg);
223} 144}
224 145
225module_init(crc32c_mod_init); 146module_init(crc32c_mod_init);