crypto: hash - move "ahash wrapping shash" functions to ahash.c
[linux-2.6-block.git] / crypto / ahash.c
CommitLineData
2874c5fd 1// SPDX-License-Identifier: GPL-2.0-or-later
004a403c
LH
2/*
3 * Asynchronous Cryptographic Hash operations.
4 *
4d707a47
EB
5 * This is the implementation of the ahash (asynchronous hash) API. It differs
6 * from shash (synchronous hash) in that ahash supports asynchronous operations,
7 * and it hashes data from scatterlists instead of virtually addressed buffers.
8 *
9 * The ahash API provides access to both ahash and shash algorithms. The shash
10 * API only provides access to shash algorithms.
004a403c
LH
11 *
12 * Copyright (c) 2008 Loc Ho <lho@amcc.com>
004a403c
LH
13 */
14
20036252 15#include <crypto/scatterwalk.h>
42808e5d 16#include <linux/cryptouser.h>
004a403c
LH
17#include <linux/err.h>
18#include <linux/kernel.h>
19#include <linux/module.h>
20#include <linux/sched.h>
21#include <linux/slab.h>
22#include <linux/seq_file.h>
42808e5d 23#include <linux/string.h>
6238cbae 24#include <net/netlink.h>
004a403c 25
42808e5d 26#include "hash.h"
004a403c 27
b64d143b
HX
28#define CRYPTO_ALG_TYPE_AHASH_MASK 0x0000000e
29
6d1b41fc
EB
30static const struct crypto_type crypto_ahash_type;
31
ecf889b7
EB
32static int shash_async_setkey(struct crypto_ahash *tfm, const u8 *key,
33 unsigned int keylen)
34{
35 struct crypto_shash **ctx = crypto_ahash_ctx(tfm);
36
37 return crypto_shash_setkey(*ctx, key, keylen);
38}
39
40static int shash_async_init(struct ahash_request *req)
41{
42 struct crypto_shash **ctx = crypto_ahash_ctx(crypto_ahash_reqtfm(req));
43 struct shash_desc *desc = ahash_request_ctx(req);
44
45 desc->tfm = *ctx;
46
47 return crypto_shash_init(desc);
48}
49
50int shash_ahash_update(struct ahash_request *req, struct shash_desc *desc)
51{
52 struct crypto_hash_walk walk;
53 int nbytes;
54
55 for (nbytes = crypto_hash_walk_first(req, &walk); nbytes > 0;
56 nbytes = crypto_hash_walk_done(&walk, nbytes))
57 nbytes = crypto_shash_update(desc, walk.data, nbytes);
58
59 return nbytes;
60}
61EXPORT_SYMBOL_GPL(shash_ahash_update);
62
63static int shash_async_update(struct ahash_request *req)
64{
65 return shash_ahash_update(req, ahash_request_ctx(req));
66}
67
68static int shash_async_final(struct ahash_request *req)
69{
70 return crypto_shash_final(ahash_request_ctx(req), req->result);
71}
72
73int shash_ahash_finup(struct ahash_request *req, struct shash_desc *desc)
74{
75 struct crypto_hash_walk walk;
76 int nbytes;
77
78 nbytes = crypto_hash_walk_first(req, &walk);
79 if (!nbytes)
80 return crypto_shash_final(desc, req->result);
81
82 do {
83 nbytes = crypto_hash_walk_last(&walk) ?
84 crypto_shash_finup(desc, walk.data, nbytes,
85 req->result) :
86 crypto_shash_update(desc, walk.data, nbytes);
87 nbytes = crypto_hash_walk_done(&walk, nbytes);
88 } while (nbytes > 0);
89
90 return nbytes;
91}
92EXPORT_SYMBOL_GPL(shash_ahash_finup);
93
94static int shash_async_finup(struct ahash_request *req)
95{
96 struct crypto_shash **ctx = crypto_ahash_ctx(crypto_ahash_reqtfm(req));
97 struct shash_desc *desc = ahash_request_ctx(req);
98
99 desc->tfm = *ctx;
100
101 return shash_ahash_finup(req, desc);
102}
103
104int shash_ahash_digest(struct ahash_request *req, struct shash_desc *desc)
105{
106 unsigned int nbytes = req->nbytes;
107 struct scatterlist *sg;
108 unsigned int offset;
109 int err;
110
111 if (nbytes &&
112 (sg = req->src, offset = sg->offset,
113 nbytes <= min(sg->length, ((unsigned int)(PAGE_SIZE)) - offset))) {
114 void *data;
115
116 data = kmap_local_page(sg_page(sg));
117 err = crypto_shash_digest(desc, data + offset, nbytes,
118 req->result);
119 kunmap_local(data);
120 } else
121 err = crypto_shash_init(desc) ?:
122 shash_ahash_finup(req, desc);
123
124 return err;
125}
126EXPORT_SYMBOL_GPL(shash_ahash_digest);
127
128static int shash_async_digest(struct ahash_request *req)
129{
130 struct crypto_shash **ctx = crypto_ahash_ctx(crypto_ahash_reqtfm(req));
131 struct shash_desc *desc = ahash_request_ctx(req);
132
133 desc->tfm = *ctx;
134
135 return shash_ahash_digest(req, desc);
136}
137
138static int shash_async_export(struct ahash_request *req, void *out)
139{
140 return crypto_shash_export(ahash_request_ctx(req), out);
141}
142
143static int shash_async_import(struct ahash_request *req, const void *in)
144{
145 struct crypto_shash **ctx = crypto_ahash_ctx(crypto_ahash_reqtfm(req));
146 struct shash_desc *desc = ahash_request_ctx(req);
147
148 desc->tfm = *ctx;
149
150 return crypto_shash_import(desc, in);
151}
152
153static void crypto_exit_shash_ops_async(struct crypto_tfm *tfm)
154{
155 struct crypto_shash **ctx = crypto_tfm_ctx(tfm);
156
157 crypto_free_shash(*ctx);
158}
159
160static int crypto_init_shash_ops_async(struct crypto_tfm *tfm)
161{
162 struct crypto_alg *calg = tfm->__crt_alg;
163 struct shash_alg *alg = __crypto_shash_alg(calg);
164 struct crypto_ahash *crt = __crypto_ahash_cast(tfm);
165 struct crypto_shash **ctx = crypto_tfm_ctx(tfm);
166 struct crypto_shash *shash;
167
168 if (!crypto_mod_get(calg))
169 return -EAGAIN;
170
171 shash = crypto_create_tfm(calg, &crypto_shash_type);
172 if (IS_ERR(shash)) {
173 crypto_mod_put(calg);
174 return PTR_ERR(shash);
175 }
176
177 *ctx = shash;
178 tfm->exit = crypto_exit_shash_ops_async;
179
180 crt->init = shash_async_init;
181 crt->update = shash_async_update;
182 crt->final = shash_async_final;
183 crt->finup = shash_async_finup;
184 crt->digest = shash_async_digest;
185 if (crypto_shash_alg_has_setkey(alg))
186 crt->setkey = shash_async_setkey;
187
188 crypto_ahash_set_flags(crt, crypto_shash_get_flags(shash) &
189 CRYPTO_TFM_NEED_KEY);
190
191 crt->export = shash_async_export;
192 crt->import = shash_async_import;
193
194 crt->reqsize = sizeof(struct shash_desc) + crypto_shash_descsize(shash);
195
196 return 0;
197}
198
199static struct crypto_ahash *
200crypto_clone_shash_ops_async(struct crypto_ahash *nhash,
201 struct crypto_ahash *hash)
202{
203 struct crypto_shash **nctx = crypto_ahash_ctx(nhash);
204 struct crypto_shash **ctx = crypto_ahash_ctx(hash);
205 struct crypto_shash *shash;
206
207 shash = crypto_clone_shash(*ctx);
208 if (IS_ERR(shash)) {
209 crypto_free_ahash(nhash);
210 return ERR_CAST(shash);
211 }
212
213 *nctx = shash;
214
215 return nhash;
216}
217
20036252
HX
218static int hash_walk_next(struct crypto_hash_walk *walk)
219{
20036252
HX
220 unsigned int offset = walk->offset;
221 unsigned int nbytes = min(walk->entrylen,
222 ((unsigned int)(PAGE_SIZE)) - offset);
223
aa969515 224 walk->data = kmap_local_page(walk->pg);
20036252 225 walk->data += offset;
20036252
HX
226 walk->entrylen -= nbytes;
227 return nbytes;
228}
229
230static int hash_walk_new_entry(struct crypto_hash_walk *walk)
231{
232 struct scatterlist *sg;
233
234 sg = walk->sg;
20036252 235 walk->offset = sg->offset;
13f4bb78
HX
236 walk->pg = sg_page(walk->sg) + (walk->offset >> PAGE_SHIFT);
237 walk->offset = offset_in_page(walk->offset);
20036252
HX
238 walk->entrylen = sg->length;
239
240 if (walk->entrylen > walk->total)
241 walk->entrylen = walk->total;
242 walk->total -= walk->entrylen;
243
244 return hash_walk_next(walk);
245}
246
247int crypto_hash_walk_done(struct crypto_hash_walk *walk, int err)
248{
20036252
HX
249 walk->data -= walk->offset;
250
aa969515 251 kunmap_local(walk->data);
8afa25aa 252 crypto_yield(walk->flags);
20036252
HX
253
254 if (err)
255 return err;
256
77568e53 257 if (walk->entrylen) {
d315a0e0
HX
258 walk->offset = 0;
259 walk->pg++;
20036252 260 return hash_walk_next(walk);
d315a0e0 261 }
20036252
HX
262
263 if (!walk->total)
264 return 0;
265
5be4d4c9 266 walk->sg = sg_next(walk->sg);
20036252
HX
267
268 return hash_walk_new_entry(walk);
269}
270EXPORT_SYMBOL_GPL(crypto_hash_walk_done);
271
272int crypto_hash_walk_first(struct ahash_request *req,
273 struct crypto_hash_walk *walk)
274{
275 walk->total = req->nbytes;
276
6d9529c5
TC
277 if (!walk->total) {
278 walk->entrylen = 0;
20036252 279 return 0;
6d9529c5 280 }
20036252 281
20036252 282 walk->sg = req->src;
8afa25aa 283 walk->flags = req->base.flags;
20036252
HX
284
285 return hash_walk_new_entry(walk);
286}
287EXPORT_SYMBOL_GPL(crypto_hash_walk_first);
288
ba7d7433
EB
289static int ahash_nosetkey(struct crypto_ahash *tfm, const u8 *key,
290 unsigned int keylen)
291{
292 return -ENOSYS;
293}
294
295static void ahash_set_needkey(struct crypto_ahash *tfm)
296{
297 const struct hash_alg_common *alg = crypto_hash_alg_common(tfm);
298
299 if (tfm->setkey != ahash_nosetkey &&
300 !(alg->base.cra_flags & CRYPTO_ALG_OPTIONAL_KEY))
301 crypto_ahash_set_flags(tfm, CRYPTO_TFM_NEED_KEY);
302}
303
66f6ce5e 304int crypto_ahash_setkey(struct crypto_ahash *tfm, const u8 *key,
004a403c
LH
305 unsigned int keylen)
306{
c626910f 307 int err = tfm->setkey(tfm, key, keylen);
9fa68f62 308
ba7d7433
EB
309 if (unlikely(err)) {
310 ahash_set_needkey(tfm);
9fa68f62 311 return err;
ba7d7433 312 }
004a403c 313
9fa68f62
EB
314 crypto_ahash_clear_flags(tfm, CRYPTO_TFM_NEED_KEY);
315 return 0;
004a403c 316}
66f6ce5e 317EXPORT_SYMBOL_GPL(crypto_ahash_setkey);
004a403c 318
d9588045
HX
319static int ahash_save_req(struct ahash_request *req, crypto_completion_t cplt,
320 bool has_state)
66f6ce5e
HX
321{
322 struct crypto_ahash *tfm = crypto_ahash_reqtfm(req);
66f6ce5e 323 unsigned int ds = crypto_ahash_digestsize(tfm);
d9588045
HX
324 struct ahash_request *subreq;
325 unsigned int subreq_size;
326 unsigned int reqsize;
327 u8 *result;
328 gfp_t gfp;
329 u32 flags;
66f6ce5e 330
d9588045
HX
331 subreq_size = sizeof(*subreq);
332 reqsize = crypto_ahash_reqsize(tfm);
333 reqsize = ALIGN(reqsize, crypto_tfm_ctx_alignment());
334 subreq_size += reqsize;
335 subreq_size += ds;
d9588045
HX
336
337 flags = ahash_request_flags(req);
338 gfp = (flags & CRYPTO_TFM_REQ_MAY_SLEEP) ? GFP_KERNEL : GFP_ATOMIC;
339 subreq = kmalloc(subreq_size, gfp);
340 if (!subreq)
66f6ce5e
HX
341 return -ENOMEM;
342
d9588045
HX
343 ahash_request_set_tfm(subreq, tfm);
344 ahash_request_set_callback(subreq, flags, cplt, req);
345
346 result = (u8 *)(subreq + 1) + reqsize;
d9588045
HX
347
348 ahash_request_set_crypt(subreq, req->src, result, req->nbytes);
349
350 if (has_state) {
351 void *state;
352
353 state = kmalloc(crypto_ahash_statesize(tfm), gfp);
354 if (!state) {
355 kfree(subreq);
356 return -ENOMEM;
357 }
358
359 crypto_ahash_export(req, state);
360 crypto_ahash_import(subreq, state);
361 kfree_sensitive(state);
362 }
363
364 req->priv = subreq;
66f6ce5e 365
1ffc9fbd
MV
366 return 0;
367}
368
ef0579b6 369static void ahash_restore_req(struct ahash_request *req, int err)
1ffc9fbd 370{
d9588045 371 struct ahash_request *subreq = req->priv;
1ffc9fbd 372
ef0579b6 373 if (!err)
d9588045 374 memcpy(req->result, subreq->result,
ef0579b6
HX
375 crypto_ahash_digestsize(crypto_ahash_reqtfm(req)));
376
1ffc9fbd
MV
377 req->priv = NULL;
378
d9588045 379 kfree_sensitive(subreq);
1ffc9fbd
MV
380}
381
66f6ce5e
HX
382int crypto_ahash_final(struct ahash_request *req)
383{
f7d76e05 384 struct crypto_ahash *tfm = crypto_ahash_reqtfm(req);
42808e5d 385 struct hash_alg_common *alg = crypto_hash_alg_common(tfm);
cac5818c 386
42808e5d
HX
387 if (IS_ENABLED(CONFIG_CRYPTO_STATS))
388 atomic64_inc(&hash_get_stat(alg)->hash_cnt);
389
c626910f 390 return crypto_hash_errstat(alg, tfm->final(req));
66f6ce5e
HX
391}
392EXPORT_SYMBOL_GPL(crypto_ahash_final);
393
394int crypto_ahash_finup(struct ahash_request *req)
395{
f7d76e05 396 struct crypto_ahash *tfm = crypto_ahash_reqtfm(req);
42808e5d 397 struct hash_alg_common *alg = crypto_hash_alg_common(tfm);
cac5818c 398
42808e5d
HX
399 if (IS_ENABLED(CONFIG_CRYPTO_STATS)) {
400 struct crypto_istat_hash *istat = hash_get_stat(alg);
401
402 atomic64_inc(&istat->hash_cnt);
403 atomic64_add(req->nbytes, &istat->hash_tlen);
404 }
405
c626910f 406 return crypto_hash_errstat(alg, tfm->finup(req));
66f6ce5e
HX
407}
408EXPORT_SYMBOL_GPL(crypto_ahash_finup);
409
410int crypto_ahash_digest(struct ahash_request *req)
411{
9fa68f62 412 struct crypto_ahash *tfm = crypto_ahash_reqtfm(req);
42808e5d 413 struct hash_alg_common *alg = crypto_hash_alg_common(tfm);
c626910f 414 int err;
42808e5d
HX
415
416 if (IS_ENABLED(CONFIG_CRYPTO_STATS)) {
417 struct crypto_istat_hash *istat = hash_get_stat(alg);
418
419 atomic64_inc(&istat->hash_cnt);
420 atomic64_add(req->nbytes, &istat->hash_tlen);
421 }
9fa68f62
EB
422
423 if (crypto_ahash_get_flags(tfm) & CRYPTO_TFM_NEED_KEY)
c626910f
EB
424 err = -ENOKEY;
425 else
426 err = tfm->digest(req);
42808e5d 427
c626910f 428 return crypto_hash_errstat(alg, err);
66f6ce5e
HX
429}
430EXPORT_SYMBOL_GPL(crypto_ahash_digest);
431
255e48eb 432static void ahash_def_finup_done2(void *data, int err)
66f6ce5e 433{
255e48eb 434 struct ahash_request *areq = data;
66f6ce5e
HX
435
436 if (err == -EINPROGRESS)
437 return;
438
ef0579b6 439 ahash_restore_req(areq, err);
66f6ce5e 440
d9588045 441 ahash_request_complete(areq, err);
66f6ce5e
HX
442}
443
444static int ahash_def_finup_finish1(struct ahash_request *req, int err)
445{
d9588045
HX
446 struct ahash_request *subreq = req->priv;
447
66f6ce5e
HX
448 if (err)
449 goto out;
450
d9588045 451 subreq->base.complete = ahash_def_finup_done2;
ef0579b6 452
d9588045 453 err = crypto_ahash_reqtfm(req)->final(subreq);
4e5b0ad5 454 if (err == -EINPROGRESS || err == -EBUSY)
ef0579b6 455 return err;
66f6ce5e
HX
456
457out:
ef0579b6 458 ahash_restore_req(req, err);
66f6ce5e
HX
459 return err;
460}
461
255e48eb 462static void ahash_def_finup_done1(void *data, int err)
66f6ce5e 463{
255e48eb 464 struct ahash_request *areq = data;
d9588045 465 struct ahash_request *subreq;
66f6ce5e 466
d9588045
HX
467 if (err == -EINPROGRESS)
468 goto out;
ef0579b6 469
d9588045
HX
470 subreq = areq->priv;
471 subreq->base.flags &= CRYPTO_TFM_REQ_MAY_BACKLOG;
ef0579b6 472
66f6ce5e 473 err = ahash_def_finup_finish1(areq, err);
d9588045 474 if (err == -EINPROGRESS || err == -EBUSY)
ef0579b6 475 return;
66f6ce5e 476
d9588045
HX
477out:
478 ahash_request_complete(areq, err);
66f6ce5e
HX
479}
480
481static int ahash_def_finup(struct ahash_request *req)
482{
483 struct crypto_ahash *tfm = crypto_ahash_reqtfm(req);
d4a7a0fb 484 int err;
66f6ce5e 485
d9588045 486 err = ahash_save_req(req, ahash_def_finup_done1, true);
d4a7a0fb
MV
487 if (err)
488 return err;
66f6ce5e 489
d9588045 490 err = tfm->update(req->priv);
4e5b0ad5 491 if (err == -EINPROGRESS || err == -EBUSY)
ef0579b6
HX
492 return err;
493
d4a7a0fb 494 return ahash_def_finup_finish1(req, err);
66f6ce5e
HX
495}
496
e73d340d
HX
497static void crypto_ahash_exit_tfm(struct crypto_tfm *tfm)
498{
499 struct crypto_ahash *hash = __crypto_ahash_cast(tfm);
500 struct ahash_alg *alg = crypto_ahash_alg(hash);
501
502 alg->exit_tfm(hash);
503}
504
88056ec3
HX
505static int crypto_ahash_init_tfm(struct crypto_tfm *tfm)
506{
507 struct crypto_ahash *hash = __crypto_ahash_cast(tfm);
508 struct ahash_alg *alg = crypto_ahash_alg(hash);
88056ec3 509
66f6ce5e 510 hash->setkey = ahash_nosetkey;
66f6ce5e 511
c7535fb2
HX
512 crypto_ahash_set_statesize(hash, alg->halg.statesize);
513
88056ec3
HX
514 if (tfm->__crt_alg->cra_type != &crypto_ahash_type)
515 return crypto_init_shash_ops_async(tfm);
516
88056ec3
HX
517 hash->init = alg->init;
518 hash->update = alg->update;
66f6ce5e
HX
519 hash->final = alg->final;
520 hash->finup = alg->finup ?: ahash_def_finup;
88056ec3 521 hash->digest = alg->digest;
6f221f7e
KK
522 hash->export = alg->export;
523 hash->import = alg->import;
66f6ce5e 524
a5596d63 525 if (alg->setkey) {
66f6ce5e 526 hash->setkey = alg->setkey;
ba7d7433 527 ahash_set_needkey(hash);
a5596d63 528 }
88056ec3 529
e73d340d
HX
530 if (alg->exit_tfm)
531 tfm->exit = crypto_ahash_exit_tfm;
532
533 return alg->init_tfm ? alg->init_tfm(hash) : 0;
88056ec3
HX
534}
535
536static unsigned int crypto_ahash_extsize(struct crypto_alg *alg)
537{
2495cf25
HX
538 if (alg->cra_type != &crypto_ahash_type)
539 return sizeof(struct crypto_shash *);
88056ec3 540
2495cf25 541 return crypto_alg_extsize(alg);
88056ec3
HX
542}
543
48fb3e57
EB
544static void crypto_ahash_free_instance(struct crypto_instance *inst)
545{
546 struct ahash_instance *ahash = ahash_instance(inst);
547
48fb3e57
EB
548 ahash->free(ahash);
549}
550
c0f9e01d
HX
551static int __maybe_unused crypto_ahash_report(
552 struct sk_buff *skb, struct crypto_alg *alg)
6238cbae
SK
553{
554 struct crypto_report_hash rhash;
555
37db69e0
EB
556 memset(&rhash, 0, sizeof(rhash));
557
558 strscpy(rhash.type, "ahash", sizeof(rhash.type));
6238cbae
SK
559
560 rhash.blocksize = alg->cra_blocksize;
561 rhash.digestsize = __crypto_hash_alg_common(alg)->digestsize;
562
37db69e0 563 return nla_put(skb, CRYPTOCFGA_REPORT_HASH, sizeof(rhash), &rhash);
6238cbae
SK
564}
565
004a403c 566static void crypto_ahash_show(struct seq_file *m, struct crypto_alg *alg)
d8c34b94 567 __maybe_unused;
004a403c
LH
568static void crypto_ahash_show(struct seq_file *m, struct crypto_alg *alg)
569{
570 seq_printf(m, "type : ahash\n");
571 seq_printf(m, "async : %s\n", alg->cra_flags & CRYPTO_ALG_ASYNC ?
572 "yes" : "no");
573 seq_printf(m, "blocksize : %u\n", alg->cra_blocksize);
88056ec3
HX
574 seq_printf(m, "digestsize : %u\n",
575 __crypto_hash_alg_common(alg)->digestsize);
004a403c
LH
576}
577
42808e5d
HX
578static int __maybe_unused crypto_ahash_report_stat(
579 struct sk_buff *skb, struct crypto_alg *alg)
580{
581 return crypto_hash_report_stat(skb, alg, "ahash");
582}
583
6d1b41fc 584static const struct crypto_type crypto_ahash_type = {
88056ec3
HX
585 .extsize = crypto_ahash_extsize,
586 .init_tfm = crypto_ahash_init_tfm,
48fb3e57 587 .free = crypto_ahash_free_instance,
004a403c
LH
588#ifdef CONFIG_PROC_FS
589 .show = crypto_ahash_show,
590#endif
b8969a1b 591#if IS_ENABLED(CONFIG_CRYPTO_USER)
6238cbae 592 .report = crypto_ahash_report,
c0f9e01d 593#endif
42808e5d
HX
594#ifdef CONFIG_CRYPTO_STATS
595 .report_stat = crypto_ahash_report_stat,
596#endif
88056ec3
HX
597 .maskclear = ~CRYPTO_ALG_TYPE_MASK,
598 .maskset = CRYPTO_ALG_TYPE_AHASH_MASK,
599 .type = CRYPTO_ALG_TYPE_AHASH,
600 .tfmsize = offsetof(struct crypto_ahash, base),
004a403c 601};
004a403c 602
84a9c938
EB
603int crypto_grab_ahash(struct crypto_ahash_spawn *spawn,
604 struct crypto_instance *inst,
605 const char *name, u32 type, u32 mask)
606{
607 spawn->base.frontend = &crypto_ahash_type;
608 return crypto_grab_spawn(&spawn->base, inst, name, type, mask);
609}
610EXPORT_SYMBOL_GPL(crypto_grab_ahash);
611
88056ec3
HX
612struct crypto_ahash *crypto_alloc_ahash(const char *alg_name, u32 type,
613 u32 mask)
614{
615 return crypto_alloc_tfm(alg_name, &crypto_ahash_type, type, mask);
616}
617EXPORT_SYMBOL_GPL(crypto_alloc_ahash);
618
8d18e34c
HX
619int crypto_has_ahash(const char *alg_name, u32 type, u32 mask)
620{
621 return crypto_type_has_alg(alg_name, &crypto_ahash_type, type, mask);
622}
623EXPORT_SYMBOL_GPL(crypto_has_ahash);
624
ed3630b8
HX
625struct crypto_ahash *crypto_clone_ahash(struct crypto_ahash *hash)
626{
627 struct hash_alg_common *halg = crypto_hash_alg_common(hash);
628 struct crypto_tfm *tfm = crypto_ahash_tfm(hash);
629 struct crypto_ahash *nhash;
630 struct ahash_alg *alg;
631 int err;
632
633 if (!crypto_hash_alg_has_setkey(halg)) {
634 tfm = crypto_tfm_get(tfm);
635 if (IS_ERR(tfm))
636 return ERR_CAST(tfm);
637
638 return hash;
639 }
640
641 nhash = crypto_clone_tfm(&crypto_ahash_type, tfm);
642
643 if (IS_ERR(nhash))
644 return nhash;
645
646 nhash->init = hash->init;
647 nhash->update = hash->update;
648 nhash->final = hash->final;
649 nhash->finup = hash->finup;
650 nhash->digest = hash->digest;
651 nhash->export = hash->export;
652 nhash->import = hash->import;
653 nhash->setkey = hash->setkey;
654 nhash->reqsize = hash->reqsize;
c7535fb2 655 nhash->statesize = hash->statesize;
ed3630b8
HX
656
657 if (tfm->__crt_alg->cra_type != &crypto_ahash_type)
658 return crypto_clone_shash_ops_async(nhash, hash);
659
660 err = -ENOSYS;
661 alg = crypto_ahash_alg(hash);
662 if (!alg->clone_tfm)
663 goto out_free_nhash;
664
665 err = alg->clone_tfm(nhash, hash);
666 if (err)
667 goto out_free_nhash;
668
669 return nhash;
670
671out_free_nhash:
672 crypto_free_ahash(nhash);
673 return ERR_PTR(err);
674}
675EXPORT_SYMBOL_GPL(crypto_clone_ahash);
676
01c2dece
HX
677static int ahash_prepare_alg(struct ahash_alg *alg)
678{
679 struct crypto_alg *base = &alg->halg.base;
42808e5d 680 int err;
01c2dece 681
42808e5d 682 if (alg->halg.statesize == 0)
01c2dece
HX
683 return -EINVAL;
684
42808e5d
HX
685 err = hash_prepare_alg(&alg->halg);
686 if (err)
687 return err;
688
01c2dece 689 base->cra_type = &crypto_ahash_type;
01c2dece
HX
690 base->cra_flags |= CRYPTO_ALG_TYPE_AHASH;
691
692 return 0;
693}
694
695int crypto_register_ahash(struct ahash_alg *alg)
696{
697 struct crypto_alg *base = &alg->halg.base;
698 int err;
699
700 err = ahash_prepare_alg(alg);
701 if (err)
702 return err;
703
704 return crypto_register_alg(base);
705}
706EXPORT_SYMBOL_GPL(crypto_register_ahash);
707
c6d633a9 708void crypto_unregister_ahash(struct ahash_alg *alg)
01c2dece 709{
c6d633a9 710 crypto_unregister_alg(&alg->halg.base);
01c2dece
HX
711}
712EXPORT_SYMBOL_GPL(crypto_unregister_ahash);
713
6f7473c5
RV
714int crypto_register_ahashes(struct ahash_alg *algs, int count)
715{
716 int i, ret;
717
718 for (i = 0; i < count; i++) {
719 ret = crypto_register_ahash(&algs[i]);
720 if (ret)
721 goto err;
722 }
723
724 return 0;
725
726err:
727 for (--i; i >= 0; --i)
728 crypto_unregister_ahash(&algs[i]);
729
730 return ret;
731}
732EXPORT_SYMBOL_GPL(crypto_register_ahashes);
733
734void crypto_unregister_ahashes(struct ahash_alg *algs, int count)
735{
736 int i;
737
738 for (i = count - 1; i >= 0; --i)
739 crypto_unregister_ahash(&algs[i]);
740}
741EXPORT_SYMBOL_GPL(crypto_unregister_ahashes);
742
01c2dece
HX
743int ahash_register_instance(struct crypto_template *tmpl,
744 struct ahash_instance *inst)
745{
746 int err;
747
d4fdc2df
EB
748 if (WARN_ON(!inst->free))
749 return -EINVAL;
750
01c2dece
HX
751 err = ahash_prepare_alg(&inst->alg);
752 if (err)
753 return err;
754
755 return crypto_register_instance(tmpl, ahash_crypto_instance(inst));
756}
757EXPORT_SYMBOL_GPL(ahash_register_instance);
758
cd6ed77a
EB
759bool crypto_hash_alg_has_setkey(struct hash_alg_common *halg)
760{
761 struct crypto_alg *alg = &halg->base;
762
763 if (alg->cra_type != &crypto_ahash_type)
764 return crypto_shash_alg_has_setkey(__crypto_shash_alg(alg));
765
766 return __crypto_ahash_alg(alg)->setkey != NULL;
767}
768EXPORT_SYMBOL_GPL(crypto_hash_alg_has_setkey);
769
004a403c
LH
770MODULE_LICENSE("GPL");
771MODULE_DESCRIPTION("Asynchronous cryptographic hash type");